1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 extern int mcs51_ptrRegReq;
97 extern int mcs51_nRegs;
98 extern FILE *codeOutFile;
99 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 sprintf (lb, "%s\t", inst);
140 sprintf (lb, "%s", inst);
141 vsprintf (lb + (strlen (lb)), fmt, ap);
144 vsprintf (lb, fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
386 val += (int) operandLitValue (IC_RIGHT (ic));
387 else if (ic->op == '-')
388 val -= (int) operandLitValue (IC_RIGHT (ic));
389 else if (IS_CAST_ICODE(ic)) {
390 sym_link *from_type = operandType(IC_RIGHT(ic));
391 aop->aopu.aop_immd.from_cast_remat = 1;
392 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
393 ptr_type = DCL_TYPE(from_type);
394 if (ptr_type == IPOINTER) {
401 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
405 sprintf (buffer, "(%s %c 0x%04x)",
406 OP_SYMBOL (IC_LEFT (ic))->rname,
407 val >= 0 ? '+' : '-',
410 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
413 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
414 /* set immd2 field if required */
415 if (aop->aopu.aop_immd.from_cast_remat) {
416 sprintf(buffer,"#0x%02x",ptr_type);
417 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
418 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
424 /*-----------------------------------------------------------------*/
425 /* regsInCommon - two operands have some registers in common */
426 /*-----------------------------------------------------------------*/
428 regsInCommon (operand * op1, operand * op2)
433 /* if they have registers in common */
434 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
437 sym1 = OP_SYMBOL (op1);
438 sym2 = OP_SYMBOL (op2);
440 if (sym1->nRegs == 0 || sym2->nRegs == 0)
443 for (i = 0; i < sym1->nRegs; i++)
449 for (j = 0; j < sym2->nRegs; j++)
454 if (sym2->regs[j] == sym1->regs[i])
462 /*-----------------------------------------------------------------*/
463 /* operandsEqu - equivalent */
464 /*-----------------------------------------------------------------*/
466 operandsEqu (operand * op1, operand * op2)
470 /* if they not symbols */
471 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
474 sym1 = OP_SYMBOL (op1);
475 sym2 = OP_SYMBOL (op2);
477 /* if both are itemps & one is spilt
478 and the other is not then false */
479 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
480 sym1->isspilt != sym2->isspilt)
483 /* if they are the same */
487 if (strcmp (sym1->rname, sym2->rname) == 0)
491 /* if left is a tmp & right is not */
492 if (IS_ITEMP (op1) &&
495 (sym1->usl.spillLoc == sym2))
498 if (IS_ITEMP (op2) &&
502 (sym2->usl.spillLoc == sym1))
508 /*-----------------------------------------------------------------*/
509 /* sameRegs - two asmops have the same registers */
510 /*-----------------------------------------------------------------*/
512 sameRegs (asmop * aop1, asmop * aop2)
519 if (aop1->type != AOP_REG ||
520 aop2->type != AOP_REG)
523 if (aop1->size != aop2->size)
526 for (i = 0; i < aop1->size; i++)
527 if (aop1->aopu.aop_reg[i] !=
528 aop2->aopu.aop_reg[i])
534 /*-----------------------------------------------------------------*/
535 /* aopOp - allocates an asmop for an operand : */
536 /*-----------------------------------------------------------------*/
538 aopOp (operand * op, iCode * ic, bool result)
547 /* if this a literal */
548 if (IS_OP_LITERAL (op))
550 op->aop = aop = newAsmop (AOP_LIT);
551 aop->aopu.aop_lit = op->operand.valOperand;
552 aop->size = getSize (operandType (op));
556 /* if already has a asmop then continue */
560 /* if the underlying symbol has a aop */
561 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
563 op->aop = OP_SYMBOL (op)->aop;
567 /* if this is a true symbol */
568 if (IS_TRUE_SYMOP (op))
570 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
574 /* this is a temporary : this has
580 e) can be a return use only */
582 sym = OP_SYMBOL (op);
584 /* if the type is a conditional */
585 if (sym->regType == REG_CND)
587 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
592 /* if it is spilt then two situations
594 b) has a spill location */
595 if (sym->isspilt || sym->nRegs == 0)
598 /* rematerialize it NOW */
601 sym->aop = op->aop = aop =
603 aop->size = getSize (sym->type);
610 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
611 aop->size = getSize (sym->type);
612 for (i = 0; i < 2; i++)
613 aop->aopu.aop_str[i] = accUse[i];
621 aop = op->aop = sym->aop = newAsmop (AOP_STR);
622 aop->size = getSize (sym->type);
623 for (i = 0; i < fReturnSizeMCS51; i++)
624 aop->aopu.aop_str[i] = fReturn[i];
628 /* else spill location */
629 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
630 /* force a new aop if sizes differ */
631 sym->usl.spillLoc->aop = NULL;
633 sym->aop = op->aop = aop =
634 aopForSym (ic, sym->usl.spillLoc, result);
635 aop->size = getSize (sym->type);
639 /* must be in a register */
640 sym->aop = op->aop = aop = newAsmop (AOP_REG);
641 aop->size = sym->nRegs;
642 for (i = 0; i < sym->nRegs; i++)
643 aop->aopu.aop_reg[i] = sym->regs[i];
646 /*-----------------------------------------------------------------*/
647 /* freeAsmop - free up the asmop given to an operand */
648 /*----------------------------------------------------------------*/
650 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
667 /* depending on the asmop type only three cases need work AOP_RO
668 , AOP_R1 && AOP_STK */
676 emitcode ("pop", "ar0");
680 bitVectUnSetBit (ic->rUsed, R0_IDX);
688 emitcode ("pop", "ar1");
692 bitVectUnSetBit (ic->rUsed, R1_IDX);
698 int stk = aop->aopu.aop_stk + aop->size;
699 bitVectUnSetBit (ic->rUsed, R0_IDX);
700 bitVectUnSetBit (ic->rUsed, R1_IDX);
702 getFreePtr (ic, &aop, FALSE);
706 emitcode ("mov", "a,_bp");
707 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
708 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
712 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
717 emitcode ("pop", "acc");
718 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
721 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
724 freeAsmop (op, NULL, ic, TRUE);
727 emitcode ("pop", "ar0");
733 emitcode ("pop", "ar1");
740 /* all other cases just dealloc */
746 OP_SYMBOL (op)->aop = NULL;
747 /* if the symbol has a spill */
749 SPIL_LOC (op)->aop = NULL;
754 /*-----------------------------------------------------------------*/
755 /* aopGet - for fetching value of the aop */
756 /*-----------------------------------------------------------------*/
758 aopGet (asmop * aop, int offset, bool bit16, bool dname)
763 /* offset is greater than
765 if (offset > (aop->size - 1) &&
766 aop->type != AOP_LIT)
769 /* depending on type */
775 /* if we need to increment it */
776 while (offset > aop->coff)
778 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
782 while (offset < aop->coff)
784 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
791 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
792 return (dname ? "acc" : "a");
794 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
795 rs = Safe_calloc (1, strlen (s) + 1);
800 while (offset > aop->coff)
802 emitcode ("inc", "dptr");
806 while (offset < aop->coff)
808 emitcode ("lcall", "__decdptr");
815 emitcode ("clr", "a");
816 emitcode ("movc", "a,@a+dptr");
820 emitcode ("movx", "a,@dptr");
822 return (dname ? "acc" : "a");
826 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
827 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
829 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
831 sprintf (s, "#(%s >> %d)",
832 aop->aopu.aop_immd.aop_immd1,
836 aop->aopu.aop_immd.aop_immd1);
837 rs = Safe_calloc (1, strlen (s) + 1);
843 sprintf (s, "(%s + %d)",
847 sprintf (s, "%s", aop->aopu.aop_dir);
848 rs = Safe_calloc (1, strlen (s) + 1);
854 return aop->aopu.aop_reg[offset]->dname;
856 return aop->aopu.aop_reg[offset]->name;
859 emitcode ("clr", "a");
860 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
861 emitcode ("rlc", "a");
862 return (dname ? "acc" : "a");
865 if (!offset && dname)
867 return aop->aopu.aop_str[offset];
870 return aopLiteral (aop->aopu.aop_lit, offset);
874 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
878 return aop->aopu.aop_str[offset];
882 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
883 "aopget got unsupported aop->type");
886 /*-----------------------------------------------------------------*/
887 /* aopPut - puts a string for a aop */
888 /*-----------------------------------------------------------------*/
890 aopPut (asmop * aop, char *s, int offset)
894 if (aop->size && offset > (aop->size - 1))
896 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
897 "aopPut got offset > aop->size");
901 /* will assign value to value */
902 /* depending on where it is ofcourse */
907 sprintf (d, "(%s + %d)",
908 aop->aopu.aop_dir, offset);
910 sprintf (d, "%s", aop->aopu.aop_dir);
913 emitcode ("mov", "%s,%s", d, s);
918 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
919 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
922 strcmp (s, "r0") == 0 ||
923 strcmp (s, "r1") == 0 ||
924 strcmp (s, "r2") == 0 ||
925 strcmp (s, "r3") == 0 ||
926 strcmp (s, "r4") == 0 ||
927 strcmp (s, "r5") == 0 ||
928 strcmp (s, "r6") == 0 ||
929 strcmp (s, "r7") == 0)
930 emitcode ("mov", "%s,%s",
931 aop->aopu.aop_reg[offset]->dname, s);
933 emitcode ("mov", "%s,%s",
934 aop->aopu.aop_reg[offset]->name, s);
941 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
942 "aopPut writting to code space");
946 while (offset > aop->coff)
949 emitcode ("inc", "dptr");
952 while (offset < aop->coff)
955 emitcode ("lcall", "__decdptr");
960 /* if not in accumulater */
963 emitcode ("movx", "@dptr,a");
968 while (offset > aop->coff)
971 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
973 while (offset < aop->coff)
976 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
983 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
989 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
991 else if (strcmp (s, "r0") == 0 ||
992 strcmp (s, "r1") == 0 ||
993 strcmp (s, "r2") == 0 ||
994 strcmp (s, "r3") == 0 ||
995 strcmp (s, "r4") == 0 ||
996 strcmp (s, "r5") == 0 ||
997 strcmp (s, "r6") == 0 ||
998 strcmp (s, "r7") == 0)
1001 sprintf (buffer, "a%s", s);
1002 emitcode ("mov", "@%s,%s",
1003 aop->aopu.aop_ptr->name, buffer);
1006 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1011 if (strcmp (s, "a") == 0)
1012 emitcode ("push", "acc");
1016 emitcode ("push", "acc");
1018 emitcode ("push", s);
1024 /* if bit variable */
1025 if (!aop->aopu.aop_dir)
1027 emitcode ("clr", "a");
1028 emitcode ("rlc", "a");
1033 emitcode ("clr", "%s", aop->aopu.aop_dir);
1035 emitcode ("setb", "%s", aop->aopu.aop_dir);
1036 else if (!strcmp (s, "c"))
1037 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1040 if (strcmp (s, "a"))
1045 symbol *lbl = newiTempLabel (NULL);
1046 emitcode ("clr", "c");
1047 emitcode ("jz", "%05d$", lbl->key + 100);
1048 emitcode ("cpl", "c");
1049 emitcode ("", "%05d$:", lbl->key + 100);
1050 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1058 if (strcmp (aop->aopu.aop_str[offset], s))
1059 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1064 if (!offset && (strcmp (s, "acc") == 0))
1067 if (strcmp (aop->aopu.aop_str[offset], s))
1068 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1072 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1073 "aopPut got unsupported aop->type");
1081 /*-----------------------------------------------------------------*/
1082 /* pointToEnd :- points to the last byte of the operand */
1083 /*-----------------------------------------------------------------*/
1085 pointToEnd (asmop * aop)
1091 aop->coff = count = (aop->size - 1);
1097 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1101 emitcode ("inc", "dptr");
1108 /*-----------------------------------------------------------------*/
1109 /* reAdjustPreg - points a register back to where it should */
1110 /*-----------------------------------------------------------------*/
1112 reAdjustPreg (asmop * aop)
1114 if ((aop->coff==0) || aop->size <= 1)
1122 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1127 emitcode ("lcall", "__decdptr");
1134 #define AOP(op) op->aop
1135 #define AOP_TYPE(op) AOP(op)->type
1136 #define AOP_SIZE(op) AOP(op)->size
1137 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1138 AOP_TYPE(x) == AOP_R0))
1140 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1141 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1143 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1144 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1145 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1147 /*-----------------------------------------------------------------*/
1148 /* genNotFloat - generates not for float operations */
1149 /*-----------------------------------------------------------------*/
1151 genNotFloat (operand * op, operand * res)
1157 D(emitcode (";", "genNotFloat"));
1159 /* we will put 127 in the first byte of
1161 aopPut (AOP (res), "#127", 0);
1162 size = AOP_SIZE (op) - 1;
1165 l = aopGet (op->aop, offset++, FALSE, FALSE);
1170 emitcode ("orl", "a,%s",
1172 offset++, FALSE, FALSE));
1175 tlbl = newiTempLabel (NULL);
1176 aopPut (res->aop, one, 1);
1177 emitcode ("jz", "%05d$", (tlbl->key + 100));
1178 aopPut (res->aop, zero, 1);
1179 emitcode ("", "%05d$:", (tlbl->key + 100));
1181 size = res->aop->size - 2;
1183 /* put zeros in the rest */
1185 aopPut (res->aop, zero, offset++);
1188 /*-----------------------------------------------------------------*/
1189 /* opIsGptr: returns non-zero if the passed operand is */
1190 /* a generic pointer type. */
1191 /*-----------------------------------------------------------------*/
1193 opIsGptr (operand * op)
1195 sym_link *type = operandType (op);
1197 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1204 /*-----------------------------------------------------------------*/
1205 /* getDataSize - get the operand data size */
1206 /*-----------------------------------------------------------------*/
1208 getDataSize (operand * op)
1211 size = AOP_SIZE (op);
1212 if (size == GPTRSIZE)
1214 sym_link *type = operandType (op);
1215 if (IS_GENPTR (type))
1217 /* generic pointer; arithmetic operations
1218 * should ignore the high byte (pointer type).
1226 /*-----------------------------------------------------------------*/
1227 /* outAcc - output Acc */
1228 /*-----------------------------------------------------------------*/
1230 outAcc (operand * result)
1233 size = getDataSize (result);
1236 aopPut (AOP (result), "a", 0);
1239 /* unsigned or positive */
1242 aopPut (AOP (result), zero, offset++);
1247 /*-----------------------------------------------------------------*/
1248 /* outBitC - output a bit C */
1249 /*-----------------------------------------------------------------*/
1251 outBitC (operand * result)
1253 /* if the result is bit */
1254 if (AOP_TYPE (result) == AOP_CRY)
1255 aopPut (AOP (result), "c", 0);
1258 emitcode ("clr", "a");
1259 emitcode ("rlc", "a");
1264 /*-----------------------------------------------------------------*/
1265 /* toBoolean - emit code for orl a,operator(sizeop) */
1266 /*-----------------------------------------------------------------*/
1268 toBoolean (operand * oper)
1270 int size = AOP_SIZE (oper) - 1;
1272 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1274 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1278 /*-----------------------------------------------------------------*/
1279 /* genNot - generate code for ! operation */
1280 /*-----------------------------------------------------------------*/
1285 sym_link *optype = operandType (IC_LEFT (ic));
1287 D(emitcode (";", "genNot"));
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if in bit space then a special case */
1294 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1296 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1297 emitcode ("cpl", "c");
1298 outBitC (IC_RESULT (ic));
1302 /* if type float then do float */
1303 if (IS_FLOAT (optype))
1305 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1309 toBoolean (IC_LEFT (ic));
1311 tlbl = newiTempLabel (NULL);
1312 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1313 emitcode ("", "%05d$:", tlbl->key + 100);
1314 outBitC (IC_RESULT (ic));
1317 /* release the aops */
1318 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1319 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1323 /*-----------------------------------------------------------------*/
1324 /* genCpl - generate code for complement */
1325 /*-----------------------------------------------------------------*/
1333 D(emitcode (";", "genCpl"));
1335 /* assign asmOps to operand & result */
1336 aopOp (IC_LEFT (ic), ic, FALSE);
1337 aopOp (IC_RESULT (ic), ic, TRUE);
1339 /* if both are in bit space then
1341 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1342 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1345 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1346 emitcode ("cpl", "c");
1347 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1351 size = AOP_SIZE (IC_RESULT (ic));
1354 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1356 emitcode ("cpl", "a");
1357 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1362 /* release the aops */
1363 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1364 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1367 /*-----------------------------------------------------------------*/
1368 /* genUminusFloat - unary minus for floating points */
1369 /*-----------------------------------------------------------------*/
1371 genUminusFloat (operand * op, operand * result)
1373 int size, offset = 0;
1376 D(emitcode (";", "genUminusFloat"));
1378 /* for this we just need to flip the
1379 first it then copy the rest in place */
1380 size = AOP_SIZE (op) - 1;
1381 l = aopGet (AOP (op), 3, FALSE, FALSE);
1385 emitcode ("cpl", "acc.7");
1386 aopPut (AOP (result), "a", 3);
1390 aopPut (AOP (result),
1391 aopGet (AOP (op), offset, FALSE, FALSE),
1397 /*-----------------------------------------------------------------*/
1398 /* genUminus - unary minus code generation */
1399 /*-----------------------------------------------------------------*/
1401 genUminus (iCode * ic)
1404 sym_link *optype, *rtype;
1407 D(emitcode (";", "genUminus"));
1410 aopOp (IC_LEFT (ic), ic, FALSE);
1411 aopOp (IC_RESULT (ic), ic, TRUE);
1413 /* if both in bit space then special
1415 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1416 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1419 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1420 emitcode ("cpl", "c");
1421 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1425 optype = operandType (IC_LEFT (ic));
1426 rtype = operandType (IC_RESULT (ic));
1428 /* if float then do float stuff */
1429 if (IS_FLOAT (optype))
1431 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1435 /* otherwise subtract from zero */
1436 size = AOP_SIZE (IC_LEFT (ic));
1441 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1442 if (!strcmp (l, "a"))
1446 emitcode ("cpl", "a");
1447 emitcode ("addc", "a,#0");
1453 emitcode ("clr", "a");
1454 emitcode ("subb", "a,%s", l);
1456 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1459 /* if any remaining bytes in the result */
1460 /* we just need to propagate the sign */
1461 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1463 emitcode ("rlc", "a");
1464 emitcode ("subb", "a,acc");
1466 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1470 /* release the aops */
1471 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1472 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1475 /*-----------------------------------------------------------------*/
1476 /* saveRegisters - will look for a call and save the registers */
1477 /*-----------------------------------------------------------------*/
1479 saveRegisters (iCode * lic)
1486 for (ic = lic; ic; ic = ic->next)
1487 if (ic->op == CALL || ic->op == PCALL)
1492 fprintf (stderr, "found parameter push with no function call\n");
1496 /* if the registers have been saved already or don't need to be then
1498 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1499 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1502 /* safe the registers in use at this time but skip the
1503 ones for the result */
1504 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1505 mcs51_rUmaskForOp (IC_RESULT(ic)));
1508 if (options.useXstack)
1510 if (bitVectBitValue (rsave, R0_IDX))
1511 emitcode ("mov", "b,r0");
1512 emitcode ("mov", "r0,%s", spname);
1513 for (i = 0; i < mcs51_nRegs; i++)
1515 if (bitVectBitValue (rsave, i))
1518 emitcode ("mov", "a,b");
1520 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1521 emitcode ("movx", "@r0,a");
1522 emitcode ("inc", "r0");
1525 emitcode ("mov", "%s,r0", spname);
1526 if (bitVectBitValue (rsave, R0_IDX))
1527 emitcode ("mov", "r0,b");
1530 for (i = 0; i < mcs51_nRegs; i++)
1532 if (bitVectBitValue (rsave, i))
1533 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1537 /*-----------------------------------------------------------------*/
1538 /* unsaveRegisters - pop the pushed registers */
1539 /*-----------------------------------------------------------------*/
1541 unsaveRegisters (iCode * ic)
1546 /* restore the registers in use at this time but skip the
1547 ones for the result */
1548 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1549 mcs51_rUmaskForOp (IC_RESULT(ic)));
1551 if (options.useXstack)
1553 emitcode ("mov", "r0,%s", spname);
1554 for (i = mcs51_nRegs; i >= 0; i--)
1556 if (bitVectBitValue (rsave, i))
1558 emitcode ("dec", "r0");
1559 emitcode ("movx", "a,@r0");
1561 emitcode ("mov", "b,a");
1563 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1567 emitcode ("mov", "%s,r0", spname);
1568 if (bitVectBitValue (rsave, R0_IDX))
1569 emitcode ("mov", "r0,b");
1572 for (i = mcs51_nRegs; i >= 0; i--)
1574 if (bitVectBitValue (rsave, i))
1575 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1581 /*-----------------------------------------------------------------*/
1583 /*-----------------------------------------------------------------*/
1585 pushSide (operand * oper, int size)
1590 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1591 if (AOP_TYPE (oper) != AOP_REG &&
1592 AOP_TYPE (oper) != AOP_DIR &&
1595 emitcode ("mov", "a,%s", l);
1596 emitcode ("push", "acc");
1599 emitcode ("push", "%s", l);
1603 /*-----------------------------------------------------------------*/
1604 /* assignResultValue - */
1605 /*-----------------------------------------------------------------*/
1607 assignResultValue (operand * oper)
1610 int size = AOP_SIZE (oper);
1613 aopPut (AOP (oper), fReturn[offset], offset);
1619 /*-----------------------------------------------------------------*/
1620 /* genXpush - pushes onto the external stack */
1621 /*-----------------------------------------------------------------*/
1623 genXpush (iCode * ic)
1625 asmop *aop = newAsmop (0);
1627 int size, offset = 0;
1629 D(emitcode (";", "genXpush"));
1631 aopOp (IC_LEFT (ic), ic, FALSE);
1632 r = getFreePtr (ic, &aop, FALSE);
1635 emitcode ("mov", "%s,_spx", r->name);
1637 size = AOP_SIZE (IC_LEFT (ic));
1641 char *l = aopGet (AOP (IC_LEFT (ic)),
1642 offset++, FALSE, FALSE);
1644 emitcode ("movx", "@%s,a", r->name);
1645 emitcode ("inc", "%s", r->name);
1650 emitcode ("mov", "_spx,%s", r->name);
1652 freeAsmop (NULL, aop, ic, TRUE);
1653 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1656 /*-----------------------------------------------------------------*/
1657 /* genIpush - genrate code for pushing this gets a little complex */
1658 /*-----------------------------------------------------------------*/
1660 genIpush (iCode * ic)
1662 int size, offset = 0;
1665 D(emitcode (";", "genIpush"));
1667 /* if this is not a parm push : ie. it is spill push
1668 and spill push is always done on the local stack */
1672 /* and the item is spilt then do nothing */
1673 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1676 aopOp (IC_LEFT (ic), ic, FALSE);
1677 size = AOP_SIZE (IC_LEFT (ic));
1678 /* push it on the stack */
1681 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1687 emitcode ("push", "%s", l);
1692 /* this is a paramter push: in this case we call
1693 the routine to find the call and save those
1694 registers that need to be saved */
1697 /* if use external stack then call the external
1698 stack pushing routine */
1699 if (options.useXstack)
1705 /* then do the push */
1706 aopOp (IC_LEFT (ic), ic, FALSE);
1709 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1710 size = AOP_SIZE (IC_LEFT (ic));
1714 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1715 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1716 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1719 emitcode ("mov", "a,%s", l);
1720 emitcode ("push", "acc");
1723 emitcode ("push", "%s", l);
1726 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1729 /*-----------------------------------------------------------------*/
1730 /* genIpop - recover the registers: can happen only for spilling */
1731 /*-----------------------------------------------------------------*/
1733 genIpop (iCode * ic)
1737 D(emitcode (";", "genIpop"));
1739 /* if the temp was not pushed then */
1740 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1743 aopOp (IC_LEFT (ic), ic, FALSE);
1744 size = AOP_SIZE (IC_LEFT (ic));
1745 offset = (size - 1);
1747 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1750 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1753 /*-----------------------------------------------------------------*/
1754 /* unsaveRBank - restores the resgister bank from stack */
1755 /*-----------------------------------------------------------------*/
1757 unsaveRBank (int bank, iCode * ic, bool popPsw)
1763 if (options.useXstack)
1767 /* Assume r0 is available for use. */
1768 r = mcs51_regWithIdx (R0_IDX);;
1773 r = getFreePtr (ic, &aop, FALSE);
1775 emitcode ("mov", "%s,_spx", r->name);
1780 if (options.useXstack)
1782 emitcode ("movx", "a,@%s", r->name);
1783 emitcode ("mov", "psw,a");
1784 emitcode ("dec", "%s", r->name);
1788 emitcode ("pop", "psw");
1792 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1794 if (options.useXstack)
1796 emitcode ("movx", "a,@%s", r->name);
1797 emitcode ("mov", "(%s+%d),a",
1798 regs8051[i].base, 8 * bank + regs8051[i].offset);
1799 emitcode ("dec", "%s", r->name);
1803 emitcode ("pop", "(%s+%d)",
1804 regs8051[i].base, 8 * bank + regs8051[i].offset);
1807 if (options.useXstack)
1809 emitcode ("mov", "_spx,%s", r->name);
1814 freeAsmop (NULL, aop, ic, TRUE);
1818 /*-----------------------------------------------------------------*/
1819 /* saveRBank - saves an entire register bank on the stack */
1820 /*-----------------------------------------------------------------*/
1822 saveRBank (int bank, iCode * ic, bool pushPsw)
1828 if (options.useXstack)
1832 /* Assume r0 is available for use. */
1833 r = mcs51_regWithIdx (R0_IDX);;
1838 r = getFreePtr (ic, &aop, FALSE);
1840 emitcode ("mov", "%s,_spx", r->name);
1843 for (i = 0; i < mcs51_nRegs; i++)
1845 if (options.useXstack)
1847 emitcode ("inc", "%s", r->name);
1848 emitcode ("mov", "a,(%s+%d)",
1849 regs8051[i].base, 8 * bank + regs8051[i].offset);
1850 emitcode ("movx", "@%s,a", r->name);
1853 emitcode ("push", "(%s+%d)",
1854 regs8051[i].base, 8 * bank + regs8051[i].offset);
1859 if (options.useXstack)
1861 emitcode ("mov", "a,psw");
1862 emitcode ("movx", "@%s,a", r->name);
1863 emitcode ("inc", "%s", r->name);
1864 emitcode ("mov", "_spx,%s", r->name);
1869 emitcode ("push", "psw");
1872 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1877 freeAsmop (NULL, aop, ic, TRUE);
1886 /*-----------------------------------------------------------------*/
1887 /* genCall - generates a call statement */
1888 /*-----------------------------------------------------------------*/
1890 genCall (iCode * ic)
1893 // bool restoreBank = FALSE;
1894 bool swapBanks = FALSE;
1896 D(emitcode(";", "genCall"));
1898 /* if send set is not empty the assign */
1903 for (sic = setFirstItem (_G.sendSet); sic;
1904 sic = setNextItem (_G.sendSet))
1906 int size, offset = 0;
1907 aopOp (IC_LEFT (sic), sic, FALSE);
1908 size = AOP_SIZE (IC_LEFT (sic));
1911 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1913 if (strcmp (l, fReturn[offset]))
1914 emitcode ("mov", "%s,%s",
1919 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1924 /* if we are calling a not _naked function that is not using
1925 the same register bank then we need to save the
1926 destination registers on the stack */
1927 dtype = operandType (IC_LEFT (ic));
1928 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1929 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1930 !IFFUNC_ISISR (dtype))
1932 // if (!ic->bankSaved)
1934 // /* This is unexpected; the bank should have been saved in
1937 // saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1938 // restoreBank = TRUE;
1940 // need caution message to user here
1944 /* if caller saves & we have not saved then */
1950 emitcode ("mov", "psw,#0x%02x",
1951 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1955 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1956 OP_SYMBOL (IC_LEFT (ic))->rname :
1957 OP_SYMBOL (IC_LEFT (ic))->name));
1961 emitcode ("mov", "psw,#0x%02x",
1962 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1965 /* if we need assign a result value */
1966 if ((IS_ITEMP (IC_RESULT (ic)) &&
1967 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1968 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1969 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1970 IS_TRUE_SYMOP (IC_RESULT (ic)))
1974 aopOp (IC_RESULT (ic), ic, FALSE);
1977 assignResultValue (IC_RESULT (ic));
1979 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1982 /* adjust the stack for parameters if
1987 if (ic->parmBytes > 3)
1989 emitcode ("mov", "a,%s", spname);
1990 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1991 emitcode ("mov", "%s,a", spname);
1994 for (i = 0; i < ic->parmBytes; i++)
1995 emitcode ("dec", "%s", spname);
1998 /* if we hade saved some registers then unsave them */
1999 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2000 unsaveRegisters (ic);
2002 // /* if register bank was saved then pop them */
2004 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2007 /*-----------------------------------------------------------------*/
2008 /* -10l - generates a call by pointer statement */
2009 /*-----------------------------------------------------------------*/
2011 genPcall (iCode * ic)
2014 symbol *rlbl = newiTempLabel (NULL);
2015 // bool restoreBank=FALSE;
2016 bool swapBanks = FALSE;
2018 D(emitcode(";", "genPCall"));
2020 /* if caller saves & we have not saved then */
2024 /* if we are calling a not _naked function that is not using
2025 the same register bank then we need to save the
2026 destination registers on the stack */
2027 dtype = operandType (IC_LEFT (ic))->next;
2028 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2029 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2030 !IFFUNC_ISISR (dtype))
2032 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2033 // restoreBank=TRUE;
2035 // need caution message to user here
2038 /* push the return address on to the stack */
2039 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2040 emitcode ("push", "acc");
2041 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2042 emitcode ("push", "acc");
2044 /* now push the calling address */
2045 aopOp (IC_LEFT (ic), ic, FALSE);
2047 pushSide (IC_LEFT (ic), FPTRSIZE);
2049 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2051 /* if send set is not empty the assign */
2056 for (sic = setFirstItem (_G.sendSet); sic;
2057 sic = setNextItem (_G.sendSet))
2059 int size, offset = 0;
2060 aopOp (IC_LEFT (sic), sic, FALSE);
2061 size = AOP_SIZE (IC_LEFT (sic));
2064 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2066 if (strcmp (l, fReturn[offset]))
2067 emitcode ("mov", "%s,%s",
2072 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2079 emitcode ("mov", "psw,#0x%02x",
2080 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2084 emitcode ("ret", "");
2085 emitcode ("", "%05d$:", (rlbl->key + 100));
2090 emitcode ("mov", "psw,#0x%02x",
2091 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2094 /* if we need assign a result value */
2095 if ((IS_ITEMP (IC_RESULT (ic)) &&
2096 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2097 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2098 IS_TRUE_SYMOP (IC_RESULT (ic)))
2102 aopOp (IC_RESULT (ic), ic, FALSE);
2105 assignResultValue (IC_RESULT (ic));
2107 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2110 /* adjust the stack for parameters if
2115 if (ic->parmBytes > 3)
2117 emitcode ("mov", "a,%s", spname);
2118 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2119 emitcode ("mov", "%s,a", spname);
2122 for (i = 0; i < ic->parmBytes; i++)
2123 emitcode ("dec", "%s", spname);
2127 // /* if register bank was saved then unsave them */
2129 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2131 /* if we hade saved some registers then
2133 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2134 unsaveRegisters (ic);
2137 /*-----------------------------------------------------------------*/
2138 /* resultRemat - result is rematerializable */
2139 /*-----------------------------------------------------------------*/
2141 resultRemat (iCode * ic)
2143 if (SKIP_IC (ic) || ic->op == IFX)
2146 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2148 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2149 if (sym->remat && !POINTER_SET (ic))
2156 #if defined(__BORLANDC__) || defined(_MSC_VER)
2157 #define STRCASECMP stricmp
2159 #define STRCASECMP strcasecmp
2162 /*-----------------------------------------------------------------*/
2163 /* inExcludeList - return 1 if the string is in exclude Reg list */
2164 /*-----------------------------------------------------------------*/
2166 inExcludeList (char *s)
2170 if (options.excludeRegs[i] &&
2171 STRCASECMP (options.excludeRegs[i], "none") == 0)
2174 for (i = 0; options.excludeRegs[i]; i++)
2176 if (options.excludeRegs[i] &&
2177 STRCASECMP (s, options.excludeRegs[i]) == 0)
2183 /*-----------------------------------------------------------------*/
2184 /* genFunction - generated code for function entry */
2185 /*-----------------------------------------------------------------*/
2187 genFunction (iCode * ic)
2191 bool switchedPSW = FALSE;
2192 int calleesaves_saved_register = -1;
2195 /* create the function header */
2196 emitcode (";", "-----------------------------------------");
2197 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2198 emitcode (";", "-----------------------------------------");
2200 emitcode ("", "%s:", sym->rname);
2201 ftype = operandType (IC_LEFT (ic));
2203 if (IFFUNC_ISNAKED(ftype))
2205 emitcode(";", "naked function: no prologue.");
2209 /* if critical function then turn interrupts off */
2210 if (IFFUNC_ISCRITICAL (ftype))
2211 emitcode ("clr", "ea");
2213 /* here we need to generate the equates for the
2214 register bank if required */
2215 if (FUNC_REGBANK (ftype) != rbank)
2219 rbank = FUNC_REGBANK (ftype);
2220 for (i = 0; i < mcs51_nRegs; i++)
2222 if (strcmp (regs8051[i].base, "0") == 0)
2223 emitcode ("", "%s = 0x%02x",
2225 8 * rbank + regs8051[i].offset);
2227 emitcode ("", "%s = %s + 0x%02x",
2230 8 * rbank + regs8051[i].offset);
2234 /* if this is an interrupt service routine then
2235 save acc, b, dpl, dph */
2236 if (IFFUNC_ISISR (sym->type))
2239 if (!inExcludeList ("acc"))
2240 emitcode ("push", "acc");
2241 if (!inExcludeList ("b"))
2242 emitcode ("push", "b");
2243 if (!inExcludeList ("dpl"))
2244 emitcode ("push", "dpl");
2245 if (!inExcludeList ("dph"))
2246 emitcode ("push", "dph");
2247 /* if this isr has no bank i.e. is going to
2248 run with bank 0 , then we need to save more
2250 if (!FUNC_REGBANK (sym->type))
2253 /* if this function does not call any other
2254 function then we can be economical and
2255 save only those registers that are used */
2256 if (!IFFUNC_HASFCALL(sym->type))
2260 /* if any registers used */
2263 /* save the registers used */
2264 for (i = 0; i < sym->regsUsed->size; i++)
2266 if (bitVectBitValue (sym->regsUsed, i) ||
2267 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2268 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2275 /* this function has a function call cannot
2276 determines register usage so we will have to push the
2278 saveRBank (0, ic, FALSE);
2283 /* This ISR uses a non-zero bank.
2285 * We assume that the bank is available for our
2288 * However, if this ISR calls a function which uses some
2289 * other bank, we must save that bank entirely.
2291 unsigned long banksToSave = 0;
2293 if (IFFUNC_HASFCALL(sym->type))
2296 #define MAX_REGISTER_BANKS 4
2301 for (i = ic; i; i = i->next)
2303 if (i->op == ENDFUNCTION)
2305 /* we got to the end OK. */
2313 dtype = operandType (IC_LEFT(i));
2315 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2317 /* Mark this bank for saving. */
2318 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2320 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2324 banksToSave |= (1 << FUNC_REGBANK(dtype));
2327 /* And note that we don't need to do it in
2335 /* This is a mess; we have no idea what
2336 * register bank the called function might
2339 * The only thing I can think of to do is
2340 * throw a warning and hope.
2342 werror(W_FUNCPTR_IN_USING_ISR);
2346 if (banksToSave && options.useXstack)
2348 /* Since we aren't passing it an ic,
2349 * saveRBank will assume r0 is available to abuse.
2351 * So switch to our (trashable) bank now, so
2352 * the caller's R0 isn't trashed.
2354 emitcode ("push", "psw");
2355 emitcode ("mov", "psw,#0x%02x",
2356 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2360 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2362 if (banksToSave & (1 << ix))
2364 saveRBank(ix, NULL, FALSE);
2368 // jwk: this needs a closer look
2369 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2374 /* if callee-save to be used for this function
2375 then save the registers being used in this function */
2376 if (IFFUNC_CALLEESAVES(sym->type))
2380 /* if any registers used */
2383 /* save the registers used */
2384 for (i = 0; i < sym->regsUsed->size; i++)
2386 if (bitVectBitValue (sym->regsUsed, i) ||
2387 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2389 /* remember one saved register for later usage */
2390 if (calleesaves_saved_register < 0)
2391 calleesaves_saved_register = i;
2392 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2400 /* set the register bank to the desired value */
2401 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2404 emitcode ("push", "psw");
2405 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2408 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2411 if (options.useXstack)
2413 emitcode ("mov", "r0,%s", spname);
2414 emitcode ("mov", "a,_bp");
2415 emitcode ("movx", "@r0,a");
2416 emitcode ("inc", "%s", spname);
2420 /* set up the stack */
2421 emitcode ("push", "_bp"); /* save the callers stack */
2423 emitcode ("mov", "_bp,%s", spname);
2426 /* adjust the stack for the function */
2432 werror (W_STACK_OVERFLOW, sym->name);
2434 if (i > 3 && sym->recvSize < 4)
2437 emitcode ("mov", "a,sp");
2438 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2439 emitcode ("mov", "sp,a");
2444 if (IFFUNC_CALLEESAVES(sym->type))
2446 /* if it's a callee-saves function we need a saved register */
2447 if (calleesaves_saved_register >= 0)
2449 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2450 emitcode ("mov", "a,sp");
2451 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2452 emitcode ("mov", "sp,a");
2453 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2456 /* do it the hard way */
2458 emitcode ("inc", "sp");
2462 /* not callee-saves, we can clobber ar0 */
2463 emitcode ("mov", "ar0,a");
2464 emitcode ("mov", "a,sp");
2465 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2466 emitcode ("mov", "sp,a");
2467 emitcode ("mov", "a,ar0");
2472 emitcode ("inc", "sp");
2478 emitcode ("mov", "a,_spx");
2479 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2480 emitcode ("mov", "_spx,a");
2485 /*-----------------------------------------------------------------*/
2486 /* genEndFunction - generates epilogue for functions */
2487 /*-----------------------------------------------------------------*/
2489 genEndFunction (iCode * ic)
2491 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2493 if (IFFUNC_ISNAKED(sym->type))
2495 emitcode(";", "naked function: no epilogue.");
2499 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2501 emitcode ("mov", "%s,_bp", spname);
2504 /* if use external stack but some variables were
2505 added to the local stack then decrement the
2507 if (options.useXstack && sym->stack)
2509 emitcode ("mov", "a,sp");
2510 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2511 emitcode ("mov", "sp,a");
2515 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2517 if (options.useXstack)
2519 emitcode ("mov", "r0,%s", spname);
2520 emitcode ("movx", "a,@r0");
2521 emitcode ("mov", "_bp,a");
2522 emitcode ("dec", "%s", spname);
2526 emitcode ("pop", "_bp");
2530 /* restore the register bank */
2531 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2533 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2534 || !options.useXstack)
2536 /* Special case of ISR using non-zero bank with useXstack
2539 emitcode ("pop", "psw");
2543 if (IFFUNC_ISISR (sym->type))
2546 /* now we need to restore the registers */
2547 /* if this isr has no bank i.e. is going to
2548 run with bank 0 , then we need to save more
2550 if (!FUNC_REGBANK (sym->type))
2552 /* if this function does not call any other
2553 function then we can be economical and
2554 save only those registers that are used */
2555 if (!IFFUNC_HASFCALL(sym->type))
2559 /* if any registers used */
2562 /* save the registers used */
2563 for (i = sym->regsUsed->size; i >= 0; i--)
2565 if (bitVectBitValue (sym->regsUsed, i) ||
2566 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2567 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2574 /* this function has a function call cannot
2575 determines register usage so we will have to pop the
2577 unsaveRBank (0, ic, FALSE);
2582 /* This ISR uses a non-zero bank.
2584 * Restore any register banks saved by genFunction
2587 // jwk: this needs a closer look
2588 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2591 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2593 if (savedBanks & (1 << ix))
2595 unsaveRBank(ix, NULL, FALSE);
2599 if (options.useXstack)
2601 /* Restore bank AFTER calling unsaveRBank,
2602 * since it can trash r0.
2604 emitcode ("pop", "psw");
2608 if (!inExcludeList ("dph"))
2609 emitcode ("pop", "dph");
2610 if (!inExcludeList ("dpl"))
2611 emitcode ("pop", "dpl");
2612 if (!inExcludeList ("b"))
2613 emitcode ("pop", "b");
2614 if (!inExcludeList ("acc"))
2615 emitcode ("pop", "acc");
2617 if (IFFUNC_ISCRITICAL (sym->type))
2618 emitcode ("setb", "ea");
2620 /* if debug then send end of function */
2621 if (options.debug && currFunc)
2624 emitcode ("", "C$%s$%d$%d$%d ==.",
2625 FileBaseName (ic->filename), currFunc->lastLine,
2626 ic->level, ic->block);
2627 if (IS_STATIC (currFunc->etype))
2628 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2630 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2634 emitcode ("reti", "");
2638 if (IFFUNC_ISCRITICAL (sym->type))
2639 emitcode ("setb", "ea");
2641 if (IFFUNC_CALLEESAVES(sym->type))
2645 /* if any registers used */
2648 /* save the registers used */
2649 for (i = sym->regsUsed->size; i >= 0; i--)
2651 if (bitVectBitValue (sym->regsUsed, i) ||
2652 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2653 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2659 /* if debug then send end of function */
2660 if (options.debug && currFunc)
2663 emitcode ("", "C$%s$%d$%d$%d ==.",
2664 FileBaseName (ic->filename), currFunc->lastLine,
2665 ic->level, ic->block);
2666 if (IS_STATIC (currFunc->etype))
2667 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2669 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2673 emitcode ("ret", "");
2678 /*-----------------------------------------------------------------*/
2679 /* genRet - generate code for return statement */
2680 /*-----------------------------------------------------------------*/
2684 int size, offset = 0, pushed = 0;
2686 D(emitcode (";", "genRet"));
2688 /* if we have no return value then
2689 just generate the "ret" */
2693 /* we have something to return then
2694 move the return value into place */
2695 aopOp (IC_LEFT (ic), ic, FALSE);
2696 size = AOP_SIZE (IC_LEFT (ic));
2701 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2704 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2706 emitcode ("push", "%s", l);
2711 l = aopGet (AOP (IC_LEFT (ic)), offset,
2713 if (strcmp (fReturn[offset], l))
2714 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2723 if (strcmp (fReturn[pushed], "a"))
2724 emitcode ("pop", fReturn[pushed]);
2726 emitcode ("pop", "acc");
2729 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2732 /* generate a jump to the return label
2733 if the next is not the return statement */
2734 if (!(ic->next && ic->next->op == LABEL &&
2735 IC_LABEL (ic->next) == returnLabel))
2737 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2741 /*-----------------------------------------------------------------*/
2742 /* genLabel - generates a label */
2743 /*-----------------------------------------------------------------*/
2745 genLabel (iCode * ic)
2747 /* special case never generate */
2748 if (IC_LABEL (ic) == entryLabel)
2751 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2754 /*-----------------------------------------------------------------*/
2755 /* genGoto - generates a ljmp */
2756 /*-----------------------------------------------------------------*/
2758 genGoto (iCode * ic)
2760 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2763 /*-----------------------------------------------------------------*/
2764 /* findLabelBackwards: walks back through the iCode chain looking */
2765 /* for the given label. Returns number of iCode instructions */
2766 /* between that label and given ic. */
2767 /* Returns zero if label not found. */
2768 /*-----------------------------------------------------------------*/
2770 findLabelBackwards (iCode * ic, int key)
2779 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2781 /* printf("findLabelBackwards = %d\n", count); */
2789 /*-----------------------------------------------------------------*/
2790 /* genPlusIncr :- does addition with increment if possible */
2791 /*-----------------------------------------------------------------*/
2793 genPlusIncr (iCode * ic)
2795 unsigned int icount;
2796 unsigned int size = getDataSize (IC_RESULT (ic));
2798 /* will try to generate an increment */
2799 /* if the right side is not a literal
2801 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2804 /* if the literal value of the right hand side
2805 is greater than 4 then it is not worth it */
2806 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2809 D(emitcode (";", "genPlusIncr"));
2811 /* if increment 16 bits in register */
2812 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2820 /* If the next instruction is a goto and the goto target
2821 * is < 10 instructions previous to this, we can generate
2822 * jumps straight to that target.
2824 if (ic->next && ic->next->op == GOTO
2825 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2826 && labelRange <= 10)
2828 emitcode (";", "tail increment optimized");
2829 tlbl = IC_LABEL (ic->next);
2834 tlbl = newiTempLabel (NULL);
2837 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2838 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2839 IS_AOP_PREG (IC_RESULT (ic)))
2840 emitcode ("cjne", "%s,#0x00,%05d$"
2841 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2845 emitcode ("clr", "a");
2846 emitcode ("cjne", "a,%s,%05d$"
2847 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2851 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2854 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2855 IS_AOP_PREG (IC_RESULT (ic)))
2856 emitcode ("cjne", "%s,#0x00,%05d$"
2857 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2860 emitcode ("cjne", "a,%s,%05d$"
2861 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2864 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2868 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2869 IS_AOP_PREG (IC_RESULT (ic)))
2870 emitcode ("cjne", "%s,#0x00,%05d$"
2871 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2875 emitcode ("cjne", "a,%s,%05d$"
2876 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2879 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2884 emitcode ("", "%05d$:", tlbl->key + 100);
2889 /* if the sizes are greater than 1 then we cannot */
2890 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2891 AOP_SIZE (IC_LEFT (ic)) > 1)
2894 /* we can if the aops of the left & result match or
2895 if they are in registers and the registers are the
2897 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2902 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2903 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2904 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2910 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2919 /*-----------------------------------------------------------------*/
2920 /* outBitAcc - output a bit in acc */
2921 /*-----------------------------------------------------------------*/
2923 outBitAcc (operand * result)
2925 symbol *tlbl = newiTempLabel (NULL);
2926 /* if the result is a bit */
2927 if (AOP_TYPE (result) == AOP_CRY)
2929 aopPut (AOP (result), "a", 0);
2933 emitcode ("jz", "%05d$", tlbl->key + 100);
2934 emitcode ("mov", "a,%s", one);
2935 emitcode ("", "%05d$:", tlbl->key + 100);
2940 /*-----------------------------------------------------------------*/
2941 /* genPlusBits - generates code for addition of two bits */
2942 /*-----------------------------------------------------------------*/
2944 genPlusBits (iCode * ic)
2946 D(emitcode (";", "genPlusBits"));
2948 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2950 symbol *lbl = newiTempLabel (NULL);
2951 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2952 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2953 emitcode ("cpl", "c");
2954 emitcode ("", "%05d$:", (lbl->key + 100));
2955 outBitC (IC_RESULT (ic));
2959 emitcode ("clr", "a");
2960 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2961 emitcode ("rlc", "a");
2962 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2963 emitcode ("addc", "a,#0x00");
2964 outAcc (IC_RESULT (ic));
2969 /* This is the original version of this code.
2971 * This is being kept around for reference,
2972 * because I am not entirely sure I got it right...
2975 adjustArithmeticResult (iCode * ic)
2977 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2978 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2979 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2980 aopPut (AOP (IC_RESULT (ic)),
2981 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2984 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2985 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2987 aopPut (AOP (IC_RESULT (ic)),
2988 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2991 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2992 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2993 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2994 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2995 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2998 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2999 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3003 /* This is the pure and virtuous version of this code.
3004 * I'm pretty certain it's right, but not enough to toss the old
3008 adjustArithmeticResult (iCode * ic)
3010 if (opIsGptr (IC_RESULT (ic)) &&
3011 opIsGptr (IC_LEFT (ic)) &&
3012 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3014 aopPut (AOP (IC_RESULT (ic)),
3015 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3019 if (opIsGptr (IC_RESULT (ic)) &&
3020 opIsGptr (IC_RIGHT (ic)) &&
3021 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3023 aopPut (AOP (IC_RESULT (ic)),
3024 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3028 if (opIsGptr (IC_RESULT (ic)) &&
3029 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3030 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3031 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3032 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3035 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3036 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3041 /*-----------------------------------------------------------------*/
3042 /* genPlus - generates code for addition */
3043 /*-----------------------------------------------------------------*/
3045 genPlus (iCode * ic)
3047 int size, offset = 0;
3049 /* special cases :- */
3051 D(emitcode (";", "genPlus"));
3053 aopOp (IC_LEFT (ic), ic, FALSE);
3054 aopOp (IC_RIGHT (ic), ic, FALSE);
3055 aopOp (IC_RESULT (ic), ic, TRUE);
3057 /* if literal, literal on the right or
3058 if left requires ACC or right is already
3060 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3061 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3062 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3064 operand *t = IC_RIGHT (ic);
3065 IC_RIGHT (ic) = IC_LEFT (ic);
3069 /* if both left & right are in bit
3071 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3072 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3078 /* if left in bit space & right literal */
3079 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3080 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3082 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3083 /* if result in bit space */
3084 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3086 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3087 emitcode ("cpl", "c");
3088 outBitC (IC_RESULT (ic));
3092 size = getDataSize (IC_RESULT (ic));
3095 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3096 emitcode ("addc", "a,#00");
3097 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3103 /* if I can do an increment instead
3104 of add then GOOD for ME */
3105 if (genPlusIncr (ic) == TRUE)
3108 size = getDataSize (IC_RESULT (ic));
3112 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3114 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3116 emitcode ("add", "a,%s",
3117 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3119 emitcode ("addc", "a,%s",
3120 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3124 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3126 emitcode ("add", "a,%s",
3127 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3129 emitcode ("addc", "a,%s",
3130 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3132 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3135 adjustArithmeticResult (ic);
3138 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3139 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3140 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3143 /*-----------------------------------------------------------------*/
3144 /* genMinusDec :- does subtraction with deccrement if possible */
3145 /*-----------------------------------------------------------------*/
3147 genMinusDec (iCode * ic)
3149 unsigned int icount;
3150 unsigned int size = getDataSize (IC_RESULT (ic));
3152 /* will try to generate an increment */
3153 /* if the right side is not a literal
3155 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3158 /* if the literal value of the right hand side
3159 is greater than 4 then it is not worth it */
3160 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3163 D(emitcode (";", "genMinusDec"));
3165 /* if decrement 16 bits in register */
3166 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3174 /* If the next instruction is a goto and the goto target
3175 * is <= 10 instructions previous to this, we can generate
3176 * jumps straight to that target.
3178 if (ic->next && ic->next->op == GOTO
3179 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3180 && labelRange <= 10)
3182 emitcode (";", "tail decrement optimized");
3183 tlbl = IC_LABEL (ic->next);
3188 tlbl = newiTempLabel (NULL);
3192 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3193 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3194 IS_AOP_PREG (IC_RESULT (ic)))
3195 emitcode ("cjne", "%s,#0xff,%05d$"
3196 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3200 emitcode ("mov", "a,#0xff");
3201 emitcode ("cjne", "a,%s,%05d$"
3202 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3205 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3208 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3209 IS_AOP_PREG (IC_RESULT (ic)))
3210 emitcode ("cjne", "%s,#0xff,%05d$"
3211 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3215 emitcode ("cjne", "a,%s,%05d$"
3216 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3219 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3223 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3224 IS_AOP_PREG (IC_RESULT (ic)))
3225 emitcode ("cjne", "%s,#0xff,%05d$"
3226 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3230 emitcode ("cjne", "a,%s,%05d$"
3231 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3234 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3238 emitcode ("", "%05d$:", tlbl->key + 100);
3243 /* if the sizes are greater than 1 then we cannot */
3244 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3245 AOP_SIZE (IC_LEFT (ic)) > 1)
3248 /* we can if the aops of the left & result match or
3249 if they are in registers and the registers are the
3251 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3255 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3263 /*-----------------------------------------------------------------*/
3264 /* addSign - complete with sign */
3265 /*-----------------------------------------------------------------*/
3267 addSign (operand * result, int offset, int sign)
3269 int size = (getDataSize (result) - offset);
3274 emitcode ("rlc", "a");
3275 emitcode ("subb", "a,acc");
3277 aopPut (AOP (result), "a", offset++);
3281 aopPut (AOP (result), zero, offset++);
3285 /*-----------------------------------------------------------------*/
3286 /* genMinusBits - generates code for subtraction of two bits */
3287 /*-----------------------------------------------------------------*/
3289 genMinusBits (iCode * ic)
3291 symbol *lbl = newiTempLabel (NULL);
3293 D(emitcode (";", "genMinusBits"));
3295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3297 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3298 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3299 emitcode ("cpl", "c");
3300 emitcode ("", "%05d$:", (lbl->key + 100));
3301 outBitC (IC_RESULT (ic));
3305 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3306 emitcode ("subb", "a,acc");
3307 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3308 emitcode ("inc", "a");
3309 emitcode ("", "%05d$:", (lbl->key + 100));
3310 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3311 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3315 /*-----------------------------------------------------------------*/
3316 /* genMinus - generates code for subtraction */
3317 /*-----------------------------------------------------------------*/
3319 genMinus (iCode * ic)
3321 int size, offset = 0;
3322 unsigned long lit = 0L;
3324 D(emitcode (";", "genMinus"));
3326 aopOp (IC_LEFT (ic), ic, FALSE);
3327 aopOp (IC_RIGHT (ic), ic, FALSE);
3328 aopOp (IC_RESULT (ic), ic, TRUE);
3330 /* special cases :- */
3331 /* if both left & right are in bit space */
3332 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3333 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3339 /* if I can do an decrement instead
3340 of subtract then GOOD for ME */
3341 if (genMinusDec (ic) == TRUE)
3344 size = getDataSize (IC_RESULT (ic));
3346 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3352 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3356 /* if literal, add a,#-lit, else normal subb */
3359 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3360 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3361 emitcode ("subb", "a,%s",
3362 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3365 /* first add without previous c */
3367 if (!size && lit==-1) {
3368 emitcode ("dec", "a");
3370 emitcode ("add", "a,#0x%02x",
3371 (unsigned int) (lit & 0x0FFL));
3374 emitcode ("addc", "a,#0x%02x",
3375 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3378 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3381 adjustArithmeticResult (ic);
3384 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3385 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3386 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3390 /*-----------------------------------------------------------------*/
3391 /* genMultbits :- multiplication of bits */
3392 /*-----------------------------------------------------------------*/
3394 genMultbits (operand * left,
3398 D(emitcode (";", "genMultbits"));
3400 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3401 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3406 /*-----------------------------------------------------------------*/
3407 /* genMultOneByte : 8*8=8/16 bit multiplication */
3408 /*-----------------------------------------------------------------*/
3410 genMultOneByte (operand * left,
3414 sym_link *opetype = operandType (result);
3416 int size=AOP_SIZE(result);
3418 D(emitcode (";", "genMultOneByte"));
3420 if (size<1 || size>2) {
3421 // this should never happen
3422 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3423 AOP_SIZE(result), __FILE__, lineno);
3427 /* (if two literals: the value is computed before) */
3428 /* if one literal, literal on the right */
3429 if (AOP_TYPE (left) == AOP_LIT)
3434 //emitcode (";", "swapped left and right");
3437 if (SPEC_USIGN(opetype)
3438 // ignore the sign of left and right, what else can we do?
3439 || (SPEC_USIGN(operandType(left)) &&
3440 SPEC_USIGN(operandType(right)))) {
3441 // just an unsigned 8*8=8/16 multiply
3442 //emitcode (";","unsigned");
3443 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3444 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3445 emitcode ("mul", "ab");
3446 aopPut (AOP (result), "a", 0);
3448 aopPut (AOP (result), "b", 1);
3453 // we have to do a signed multiply
3455 //emitcode (";", "signed");
3456 emitcode ("clr", "F0"); // reset sign flag
3457 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3459 lbl=newiTempLabel(NULL);
3460 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3461 // left side is negative, 8-bit two's complement, this fails for -128
3462 emitcode ("setb", "F0"); // set sign flag
3463 emitcode ("cpl", "a");
3464 emitcode ("inc", "a");
3466 emitcode ("", "%05d$:", lbl->key+100);
3469 if (AOP_TYPE(right)==AOP_LIT) {
3470 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3471 /* AND literal negative */
3473 emitcode ("cpl", "F0"); // complement sign flag
3474 emitcode ("mov", "b,#0x%02x", -val);
3476 emitcode ("mov", "b,#0x%02x", val);
3479 lbl=newiTempLabel(NULL);
3480 emitcode ("mov", "b,a");
3481 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3482 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3483 // right side is negative, 8-bit two's complement
3484 emitcode ("cpl", "F0"); // complement sign flag
3485 emitcode ("cpl", "a");
3486 emitcode ("inc", "a");
3487 emitcode ("", "%05d$:", lbl->key+100);
3489 emitcode ("mul", "ab");
3491 lbl=newiTempLabel(NULL);
3492 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3493 // only ONE op was negative, we have to do a 8/16-bit two's complement
3494 emitcode ("cpl", "a"); // lsb
3496 emitcode ("inc", "a");
3498 emitcode ("add", "a,#1");
3499 emitcode ("xch", "a,b");
3500 emitcode ("cpl", "a"); // msb
3501 emitcode ("addc", "a,#0");
3502 emitcode ("xch", "a,b");
3505 emitcode ("", "%05d$:", lbl->key+100);
3506 aopPut (AOP (result), "a", 0);
3508 aopPut (AOP (result), "b", 1);
3512 /*-----------------------------------------------------------------*/
3513 /* genMult - generates code for multiplication */
3514 /*-----------------------------------------------------------------*/
3516 genMult (iCode * ic)
3518 operand *left = IC_LEFT (ic);
3519 operand *right = IC_RIGHT (ic);
3520 operand *result = IC_RESULT (ic);
3522 D(emitcode (";", "genMult"));
3524 /* assign the amsops */
3525 aopOp (left, ic, FALSE);
3526 aopOp (right, ic, FALSE);
3527 aopOp (result, ic, TRUE);
3529 /* special cases first */
3531 if (AOP_TYPE (left) == AOP_CRY &&
3532 AOP_TYPE (right) == AOP_CRY)
3534 genMultbits (left, right, result);
3538 /* if both are of size == 1 */
3539 #if 0 // one of them can be a sloc shared with the result
3540 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3542 if (getSize(operandType(left)) == 1 &&
3543 getSize(operandType(right)) == 1)
3546 genMultOneByte (left, right, result);
3550 /* should have been converted to function call */
3551 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3552 getSize(OP_SYMBOL(right)->type));
3556 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3557 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3558 freeAsmop (result, NULL, ic, TRUE);
3561 /*-----------------------------------------------------------------*/
3562 /* genDivbits :- division of bits */
3563 /*-----------------------------------------------------------------*/
3565 genDivbits (operand * left,
3572 D(emitcode (";", "genDivbits"));
3574 /* the result must be bit */
3575 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3576 l = aopGet (AOP (left), 0, FALSE, FALSE);
3580 emitcode ("div", "ab");
3581 emitcode ("rrc", "a");
3582 aopPut (AOP (result), "c", 0);
3585 /*-----------------------------------------------------------------*/
3586 /* genDivOneByte : 8 bit division */
3587 /*-----------------------------------------------------------------*/
3589 genDivOneByte (operand * left,
3593 sym_link *opetype = operandType (result);
3598 D(emitcode (";", "genDivOneByte"));
3600 size = AOP_SIZE (result) - 1;
3602 /* signed or unsigned */
3603 if (SPEC_USIGN (opetype))
3605 /* unsigned is easy */
3606 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3607 l = aopGet (AOP (left), 0, FALSE, FALSE);
3609 emitcode ("div", "ab");
3610 aopPut (AOP (result), "a", 0);
3612 aopPut (AOP (result), zero, offset++);
3616 /* signed is a little bit more difficult */
3618 /* save the signs of the operands */
3619 l = aopGet (AOP (left), 0, FALSE, FALSE);
3621 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3622 emitcode ("push", "acc"); /* save it on the stack */
3624 /* now sign adjust for both left & right */
3625 l = aopGet (AOP (right), 0, FALSE, FALSE);
3627 lbl = newiTempLabel (NULL);
3628 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3629 emitcode ("cpl", "a");
3630 emitcode ("inc", "a");
3631 emitcode ("", "%05d$:", (lbl->key + 100));
3632 emitcode ("mov", "b,a");
3634 /* sign adjust left side */
3635 l = aopGet (AOP (left), 0, FALSE, FALSE);
3638 lbl = newiTempLabel (NULL);
3639 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3640 emitcode ("cpl", "a");
3641 emitcode ("inc", "a");
3642 emitcode ("", "%05d$:", (lbl->key + 100));
3644 /* now the division */
3645 emitcode ("div", "ab");
3646 /* we are interested in the lower order
3648 emitcode ("mov", "b,a");
3649 lbl = newiTempLabel (NULL);
3650 emitcode ("pop", "acc");
3651 /* if there was an over flow we don't
3652 adjust the sign of the result */
3653 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3654 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3656 emitcode ("clr", "a");
3657 emitcode ("subb", "a,b");
3658 emitcode ("mov", "b,a");
3659 emitcode ("", "%05d$:", (lbl->key + 100));
3661 /* now we are done */
3662 aopPut (AOP (result), "b", 0);
3665 emitcode ("mov", "c,b.7");
3666 emitcode ("subb", "a,acc");
3669 aopPut (AOP (result), "a", offset++);
3673 /*-----------------------------------------------------------------*/
3674 /* genDiv - generates code for division */
3675 /*-----------------------------------------------------------------*/
3679 operand *left = IC_LEFT (ic);
3680 operand *right = IC_RIGHT (ic);
3681 operand *result = IC_RESULT (ic);
3683 D(emitcode (";", "genDiv"));
3685 /* assign the amsops */
3686 aopOp (left, ic, FALSE);
3687 aopOp (right, ic, FALSE);
3688 aopOp (result, ic, TRUE);
3690 /* special cases first */
3692 if (AOP_TYPE (left) == AOP_CRY &&
3693 AOP_TYPE (right) == AOP_CRY)
3695 genDivbits (left, right, result);
3699 /* if both are of size == 1 */
3700 if (AOP_SIZE (left) == 1 &&
3701 AOP_SIZE (right) == 1)
3703 genDivOneByte (left, right, result);
3707 /* should have been converted to function call */
3710 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3711 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3712 freeAsmop (result, NULL, ic, TRUE);
3715 /*-----------------------------------------------------------------*/
3716 /* genModbits :- modulus of bits */
3717 /*-----------------------------------------------------------------*/
3719 genModbits (operand * left,
3726 D(emitcode (";", "genModbits"));
3728 /* the result must be bit */
3729 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3730 l = aopGet (AOP (left), 0, FALSE, FALSE);
3734 emitcode ("div", "ab");
3735 emitcode ("mov", "a,b");
3736 emitcode ("rrc", "a");
3737 aopPut (AOP (result), "c", 0);
3740 /*-----------------------------------------------------------------*/
3741 /* genModOneByte : 8 bit modulus */
3742 /*-----------------------------------------------------------------*/
3744 genModOneByte (operand * left,
3748 sym_link *opetype = operandType (result);
3752 D(emitcode (";", "genModOneByte"));
3754 /* signed or unsigned */
3755 if (SPEC_USIGN (opetype))
3757 /* unsigned is easy */
3758 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3759 l = aopGet (AOP (left), 0, FALSE, FALSE);
3761 emitcode ("div", "ab");
3762 aopPut (AOP (result), "b", 0);
3766 /* signed is a little bit more difficult */
3768 /* save the signs of the operands */
3769 l = aopGet (AOP (left), 0, FALSE, FALSE);
3772 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3773 emitcode ("push", "acc"); /* save it on the stack */
3775 /* now sign adjust for both left & right */
3776 l = aopGet (AOP (right), 0, FALSE, FALSE);
3779 lbl = newiTempLabel (NULL);
3780 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3781 emitcode ("cpl", "a");
3782 emitcode ("inc", "a");
3783 emitcode ("", "%05d$:", (lbl->key + 100));
3784 emitcode ("mov", "b,a");
3786 /* sign adjust left side */
3787 l = aopGet (AOP (left), 0, FALSE, FALSE);
3790 lbl = newiTempLabel (NULL);
3791 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3792 emitcode ("cpl", "a");
3793 emitcode ("inc", "a");
3794 emitcode ("", "%05d$:", (lbl->key + 100));
3796 /* now the multiplication */
3797 emitcode ("div", "ab");
3798 /* we are interested in the lower order
3800 lbl = newiTempLabel (NULL);
3801 emitcode ("pop", "acc");
3802 /* if there was an over flow we don't
3803 adjust the sign of the result */
3804 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3805 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3807 emitcode ("clr", "a");
3808 emitcode ("subb", "a,b");
3809 emitcode ("mov", "b,a");
3810 emitcode ("", "%05d$:", (lbl->key + 100));
3812 /* now we are done */
3813 aopPut (AOP (result), "b", 0);
3817 /*-----------------------------------------------------------------*/
3818 /* genMod - generates code for division */
3819 /*-----------------------------------------------------------------*/
3823 operand *left = IC_LEFT (ic);
3824 operand *right = IC_RIGHT (ic);
3825 operand *result = IC_RESULT (ic);
3827 D(emitcode (";", "genMod"));
3829 /* assign the amsops */
3830 aopOp (left, ic, FALSE);
3831 aopOp (right, ic, FALSE);
3832 aopOp (result, ic, TRUE);
3834 /* special cases first */
3836 if (AOP_TYPE (left) == AOP_CRY &&
3837 AOP_TYPE (right) == AOP_CRY)
3839 genModbits (left, right, result);
3843 /* if both are of size == 1 */
3844 if (AOP_SIZE (left) == 1 &&
3845 AOP_SIZE (right) == 1)
3847 genModOneByte (left, right, result);
3851 /* should have been converted to function call */
3855 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3856 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3857 freeAsmop (result, NULL, ic, TRUE);
3860 /*-----------------------------------------------------------------*/
3861 /* genIfxJump :- will create a jump depending on the ifx */
3862 /*-----------------------------------------------------------------*/
3864 genIfxJump (iCode * ic, char *jval)
3867 symbol *tlbl = newiTempLabel (NULL);
3870 D(emitcode (";", "genIfxJump"));
3872 /* if true label then we jump if condition
3876 jlbl = IC_TRUE (ic);
3877 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3878 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3882 /* false label is present */
3883 jlbl = IC_FALSE (ic);
3884 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3885 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3887 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3888 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3890 emitcode (inst, "%05d$", tlbl->key + 100);
3891 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3892 emitcode ("", "%05d$:", tlbl->key + 100);
3894 /* mark the icode as generated */
3898 /*-----------------------------------------------------------------*/
3899 /* genCmp :- greater or less than comparison */
3900 /*-----------------------------------------------------------------*/
3902 genCmp (operand * left, operand * right,
3903 operand * result, iCode * ifx, int sign, iCode *ic)
3905 int size, offset = 0;
3906 unsigned long lit = 0L;
3908 D(emitcode (";", "genCmp"));
3910 /* if left & right are bit variables */
3911 if (AOP_TYPE (left) == AOP_CRY &&
3912 AOP_TYPE (right) == AOP_CRY)
3914 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3915 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3919 /* subtract right from left if at the
3920 end the carry flag is set then we know that
3921 left is greater than right */
3922 size = max (AOP_SIZE (left), AOP_SIZE (right));
3924 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3925 if ((size == 1) && !sign &&
3926 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3928 symbol *lbl = newiTempLabel (NULL);
3929 emitcode ("cjne", "%s,%s,%05d$",
3930 aopGet (AOP (left), offset, FALSE, FALSE),
3931 aopGet (AOP (right), offset, FALSE, FALSE),
3933 emitcode ("", "%05d$:", lbl->key + 100);
3937 if (AOP_TYPE (right) == AOP_LIT)
3939 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3940 /* optimize if(x < 0) or if(x >= 0) */
3949 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3950 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3952 genIfxJump (ifx, "acc.7");
3956 emitcode ("rlc", "a");
3964 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3965 if (sign && size == 0)
3967 emitcode ("xrl", "a,#0x80");
3968 if (AOP_TYPE (right) == AOP_LIT)
3970 unsigned long lit = (unsigned long)
3971 floatFromVal (AOP (right)->aopu.aop_lit);
3972 emitcode ("subb", "a,#0x%02x",
3973 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3977 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3978 emitcode ("xrl", "b,#0x80");
3979 emitcode ("subb", "a,b");
3983 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3989 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3990 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3991 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3997 /* if the result is used in the next
3998 ifx conditional branch then generate
3999 code a little differently */
4001 genIfxJump (ifx, "c");
4004 /* leave the result in acc */
4008 /*-----------------------------------------------------------------*/
4009 /* genCmpGt :- greater than comparison */
4010 /*-----------------------------------------------------------------*/
4012 genCmpGt (iCode * ic, iCode * ifx)
4014 operand *left, *right, *result;
4015 sym_link *letype, *retype;
4018 D(emitcode (";", "genCmpGt"));
4020 left = IC_LEFT (ic);
4021 right = IC_RIGHT (ic);
4022 result = IC_RESULT (ic);
4024 letype = getSpec (operandType (left));
4025 retype = getSpec (operandType (right));
4026 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4027 /* assign the amsops */
4028 aopOp (left, ic, FALSE);
4029 aopOp (right, ic, FALSE);
4030 aopOp (result, ic, TRUE);
4032 genCmp (right, left, result, ifx, sign,ic);
4034 freeAsmop (result, NULL, ic, TRUE);
4037 /*-----------------------------------------------------------------*/
4038 /* genCmpLt - less than comparisons */
4039 /*-----------------------------------------------------------------*/
4041 genCmpLt (iCode * ic, iCode * ifx)
4043 operand *left, *right, *result;
4044 sym_link *letype, *retype;
4047 D(emitcode (";", "genCmpLt"));
4049 left = IC_LEFT (ic);
4050 right = IC_RIGHT (ic);
4051 result = IC_RESULT (ic);
4053 letype = getSpec (operandType (left));
4054 retype = getSpec (operandType (right));
4055 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4057 /* assign the amsops */
4058 aopOp (left, ic, FALSE);
4059 aopOp (right, ic, FALSE);
4060 aopOp (result, ic, TRUE);
4062 genCmp (left, right, result, ifx, sign,ic);
4064 freeAsmop (result, NULL, ic, TRUE);
4067 /*-----------------------------------------------------------------*/
4068 /* gencjneshort - compare and jump if not equal */
4069 /*-----------------------------------------------------------------*/
4071 gencjneshort (operand * left, operand * right, symbol * lbl)
4073 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4075 unsigned long lit = 0L;
4077 /* if the left side is a literal or
4078 if the right is in a pointer register and left
4080 if ((AOP_TYPE (left) == AOP_LIT) ||
4081 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4087 if (AOP_TYPE (right) == AOP_LIT)
4088 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4090 /* if the right side is a literal then anything goes */
4091 if (AOP_TYPE (right) == AOP_LIT &&
4092 AOP_TYPE (left) != AOP_DIR)
4096 emitcode ("cjne", "%s,%s,%05d$",
4097 aopGet (AOP (left), offset, FALSE, FALSE),
4098 aopGet (AOP (right), offset, FALSE, FALSE),
4104 /* if the right side is in a register or in direct space or
4105 if the left is a pointer register & right is not */
4106 else if (AOP_TYPE (right) == AOP_REG ||
4107 AOP_TYPE (right) == AOP_DIR ||
4108 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4109 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4113 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4114 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4115 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4116 emitcode ("jnz", "%05d$", lbl->key + 100);
4118 emitcode ("cjne", "a,%s,%05d$",
4119 aopGet (AOP (right), offset, FALSE, TRUE),
4126 /* right is a pointer reg need both a & b */
4129 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4130 if (strcmp (l, "b"))
4131 emitcode ("mov", "b,%s", l);
4132 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4133 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4139 /*-----------------------------------------------------------------*/
4140 /* gencjne - compare and jump if not equal */
4141 /*-----------------------------------------------------------------*/
4143 gencjne (operand * left, operand * right, symbol * lbl)
4145 symbol *tlbl = newiTempLabel (NULL);
4147 gencjneshort (left, right, lbl);
4149 emitcode ("mov", "a,%s", one);
4150 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4151 emitcode ("", "%05d$:", lbl->key + 100);
4152 emitcode ("clr", "a");
4153 emitcode ("", "%05d$:", tlbl->key + 100);
4156 /*-----------------------------------------------------------------*/
4157 /* genCmpEq - generates code for equal to */
4158 /*-----------------------------------------------------------------*/
4160 genCmpEq (iCode * ic, iCode * ifx)
4162 operand *left, *right, *result;
4164 D(emitcode (";", "genCmpEq"));
4166 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4167 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4168 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4170 /* if literal, literal on the right or
4171 if the right is in a pointer register and left
4173 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4174 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4176 operand *t = IC_RIGHT (ic);
4177 IC_RIGHT (ic) = IC_LEFT (ic);
4181 if (ifx && !AOP_SIZE (result))
4184 /* if they are both bit variables */
4185 if (AOP_TYPE (left) == AOP_CRY &&
4186 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4188 if (AOP_TYPE (right) == AOP_LIT)
4190 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4193 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4194 emitcode ("cpl", "c");
4198 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4202 emitcode ("clr", "c");
4204 /* AOP_TYPE(right) == AOP_CRY */
4208 symbol *lbl = newiTempLabel (NULL);
4209 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4210 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4211 emitcode ("cpl", "c");
4212 emitcode ("", "%05d$:", (lbl->key + 100));
4214 /* if true label then we jump if condition
4216 tlbl = newiTempLabel (NULL);
4219 emitcode ("jnc", "%05d$", tlbl->key + 100);
4220 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4224 emitcode ("jc", "%05d$", tlbl->key + 100);
4225 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4227 emitcode ("", "%05d$:", tlbl->key + 100);
4231 tlbl = newiTempLabel (NULL);
4232 gencjneshort (left, right, tlbl);
4235 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4236 emitcode ("", "%05d$:", tlbl->key + 100);
4240 symbol *lbl = newiTempLabel (NULL);
4241 emitcode ("sjmp", "%05d$", lbl->key + 100);
4242 emitcode ("", "%05d$:", tlbl->key + 100);
4243 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4244 emitcode ("", "%05d$:", lbl->key + 100);
4247 /* mark the icode as generated */
4252 /* if they are both bit variables */
4253 if (AOP_TYPE (left) == AOP_CRY &&
4254 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4256 if (AOP_TYPE (right) == AOP_LIT)
4258 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4262 emitcode ("cpl", "c");
4266 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4270 emitcode ("clr", "c");
4272 /* AOP_TYPE(right) == AOP_CRY */
4276 symbol *lbl = newiTempLabel (NULL);
4277 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4278 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4279 emitcode ("cpl", "c");
4280 emitcode ("", "%05d$:", (lbl->key + 100));
4283 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4290 genIfxJump (ifx, "c");
4293 /* if the result is used in an arithmetic operation
4294 then put the result in place */
4299 gencjne (left, right, newiTempLabel (NULL));
4300 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4302 aopPut (AOP (result), "a", 0);
4307 genIfxJump (ifx, "a");
4310 /* if the result is used in an arithmetic operation
4311 then put the result in place */
4312 if (AOP_TYPE (result) != AOP_CRY)
4314 /* leave the result in acc */
4318 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4319 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4320 freeAsmop (result, NULL, ic, TRUE);
4323 /*-----------------------------------------------------------------*/
4324 /* ifxForOp - returns the icode containing the ifx for operand */
4325 /*-----------------------------------------------------------------*/
4327 ifxForOp (operand * op, iCode * ic)
4329 /* if true symbol then needs to be assigned */
4330 if (IS_TRUE_SYMOP (op))
4333 /* if this has register type condition and
4334 the next instruction is ifx with the same operand
4335 and live to of the operand is upto the ifx only then */
4337 ic->next->op == IFX &&
4338 IC_COND (ic->next)->key == op->key &&
4339 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4345 /*-----------------------------------------------------------------*/
4346 /* hasInc - operand is incremented before any other use */
4347 /*-----------------------------------------------------------------*/
4349 hasInc (operand *op, iCode *ic,int osize)
4351 sym_link *type = operandType(op);
4352 sym_link *retype = getSpec (type);
4353 iCode *lic = ic->next;
4356 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4357 if (!IS_SYMOP(op)) return NULL;
4359 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4360 if (IS_AGGREGATE(type->next)) return NULL;
4361 if (osize != (isize = getSize(type->next))) return NULL;
4364 /* if operand of the form op = op + <sizeof *op> */
4365 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4366 isOperandEqual(IC_RESULT(lic),op) &&
4367 isOperandLiteral(IC_RIGHT(lic)) &&
4368 operandLitValue(IC_RIGHT(lic)) == isize) {
4371 /* if the operand used or deffed */
4372 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4375 /* if GOTO or IFX */
4376 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4382 /*-----------------------------------------------------------------*/
4383 /* genAndOp - for && operation */
4384 /*-----------------------------------------------------------------*/
4386 genAndOp (iCode * ic)
4388 operand *left, *right, *result;
4391 D(emitcode (";", "genAndOp"));
4393 /* note here that && operations that are in an
4394 if statement are taken away by backPatchLabels
4395 only those used in arthmetic operations remain */
4396 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4397 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4398 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4400 /* if both are bit variables */
4401 if (AOP_TYPE (left) == AOP_CRY &&
4402 AOP_TYPE (right) == AOP_CRY)
4404 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4405 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4410 tlbl = newiTempLabel (NULL);
4412 emitcode ("jz", "%05d$", tlbl->key + 100);
4414 emitcode ("", "%05d$:", tlbl->key + 100);
4418 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4419 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4420 freeAsmop (result, NULL, ic, TRUE);
4424 /*-----------------------------------------------------------------*/
4425 /* genOrOp - for || operation */
4426 /*-----------------------------------------------------------------*/
4428 genOrOp (iCode * ic)
4430 operand *left, *right, *result;
4433 D(emitcode (";", "genOrOp"));
4435 /* note here that || operations that are in an
4436 if statement are taken away by backPatchLabels
4437 only those used in arthmetic operations remain */
4438 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4439 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4440 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4442 /* if both are bit variables */
4443 if (AOP_TYPE (left) == AOP_CRY &&
4444 AOP_TYPE (right) == AOP_CRY)
4446 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4447 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4452 tlbl = newiTempLabel (NULL);
4454 emitcode ("jnz", "%05d$", tlbl->key + 100);
4456 emitcode ("", "%05d$:", tlbl->key + 100);
4460 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4461 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4462 freeAsmop (result, NULL, ic, TRUE);
4465 /*-----------------------------------------------------------------*/
4466 /* isLiteralBit - test if lit == 2^n */
4467 /*-----------------------------------------------------------------*/
4469 isLiteralBit (unsigned long lit)
4471 unsigned long pw[32] =
4472 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4473 0x100L, 0x200L, 0x400L, 0x800L,
4474 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4475 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4476 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4477 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4478 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4481 for (idx = 0; idx < 32; idx++)
4487 /*-----------------------------------------------------------------*/
4488 /* continueIfTrue - */
4489 /*-----------------------------------------------------------------*/
4491 continueIfTrue (iCode * ic)
4494 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4498 /*-----------------------------------------------------------------*/
4500 /*-----------------------------------------------------------------*/
4502 jumpIfTrue (iCode * ic)
4505 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4509 /*-----------------------------------------------------------------*/
4510 /* jmpTrueOrFalse - */
4511 /*-----------------------------------------------------------------*/
4513 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4515 // ugly but optimized by peephole
4518 symbol *nlbl = newiTempLabel (NULL);
4519 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4520 emitcode ("", "%05d$:", tlbl->key + 100);
4521 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4522 emitcode ("", "%05d$:", nlbl->key + 100);
4526 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4527 emitcode ("", "%05d$:", tlbl->key + 100);
4532 /*-----------------------------------------------------------------*/
4533 /* genAnd - code for and */
4534 /*-----------------------------------------------------------------*/
4536 genAnd (iCode * ic, iCode * ifx)
4538 operand *left, *right, *result;
4539 int size, offset = 0;
4540 unsigned long lit = 0L;
4544 D(emitcode (";", "genAnd"));
4546 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4547 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4548 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4551 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4553 AOP_TYPE (left), AOP_TYPE (right));
4554 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4556 AOP_SIZE (left), AOP_SIZE (right));
4559 /* if left is a literal & right is not then exchange them */
4560 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4561 AOP_NEEDSACC (left))
4563 operand *tmp = right;
4568 /* if result = right then exchange them */
4569 if (sameRegs (AOP (result), AOP (right)))
4571 operand *tmp = right;
4576 /* if right is bit then exchange them */
4577 if (AOP_TYPE (right) == AOP_CRY &&
4578 AOP_TYPE (left) != AOP_CRY)
4580 operand *tmp = right;
4584 if (AOP_TYPE (right) == AOP_LIT)
4585 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4587 size = AOP_SIZE (result);
4590 // result = bit & yy;
4591 if (AOP_TYPE (left) == AOP_CRY)
4593 // c = bit & literal;
4594 if (AOP_TYPE (right) == AOP_LIT)
4598 if (size && sameRegs (AOP (result), AOP (left)))
4601 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4606 if (size && (AOP_TYPE (result) == AOP_CRY))
4608 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4611 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4616 emitcode ("clr", "c");
4621 if (AOP_TYPE (right) == AOP_CRY)
4624 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4625 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4630 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4632 emitcode ("rrc", "a");
4633 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4641 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4642 genIfxJump (ifx, "c");
4646 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4647 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4648 if ((AOP_TYPE (right) == AOP_LIT) &&
4649 (AOP_TYPE (result) == AOP_CRY) &&
4650 (AOP_TYPE (left) != AOP_CRY))
4652 int posbit = isLiteralBit (lit);
4657 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4660 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4666 sprintf (buffer, "acc.%d", posbit & 0x07);
4667 genIfxJump (ifx, buffer);
4674 symbol *tlbl = newiTempLabel (NULL);
4675 int sizel = AOP_SIZE (left);
4677 emitcode ("setb", "c");
4680 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4682 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4684 if ((posbit = isLiteralBit (bytelit)) != 0)
4685 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4688 if (bytelit != 0x0FFL)
4689 emitcode ("anl", "a,%s",
4690 aopGet (AOP (right), offset, FALSE, TRUE));
4691 emitcode ("jnz", "%05d$", tlbl->key + 100);
4696 // bit = left & literal
4699 emitcode ("clr", "c");
4700 emitcode ("", "%05d$:", tlbl->key + 100);
4702 // if(left & literal)
4706 jmpTrueOrFalse (ifx, tlbl);
4714 /* if left is same as result */
4715 if (sameRegs (AOP (result), AOP (left)))
4717 for (; size--; offset++)
4719 if (AOP_TYPE (right) == AOP_LIT)
4721 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4723 else if (bytelit == 0)
4724 aopPut (AOP (result), zero, offset);
4725 else if (IS_AOP_PREG (result))
4727 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4728 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4729 aopPut (AOP (result), "a", offset);
4732 emitcode ("anl", "%s,%s",
4733 aopGet (AOP (left), offset, FALSE, TRUE),
4734 aopGet (AOP (right), offset, FALSE, FALSE));
4738 if (AOP_TYPE (left) == AOP_ACC)
4739 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4742 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4743 if (IS_AOP_PREG (result))
4745 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4746 aopPut (AOP (result), "a", offset);
4750 emitcode ("anl", "%s,a",
4751 aopGet (AOP (left), offset, FALSE, TRUE));
4758 // left & result in different registers
4759 if (AOP_TYPE (result) == AOP_CRY)
4762 // if(size), result in bit
4763 // if(!size && ifx), conditional oper: if(left & right)
4764 symbol *tlbl = newiTempLabel (NULL);
4765 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4767 emitcode ("setb", "c");
4770 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4771 emitcode ("anl", "a,%s",
4772 aopGet (AOP (right), offset, FALSE, FALSE));
4774 if (AOP_TYPE(left)==AOP_ACC) {
4775 emitcode("mov", "b,a");
4776 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4777 emitcode("anl", "a,b");
4779 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4780 emitcode ("anl", "a,%s",
4781 aopGet (AOP (left), offset, FALSE, FALSE));
4784 emitcode ("jnz", "%05d$", tlbl->key + 100);
4790 emitcode ("", "%05d$:", tlbl->key + 100);
4794 jmpTrueOrFalse (ifx, tlbl);
4798 for (; (size--); offset++)
4801 // result = left & right
4802 if (AOP_TYPE (right) == AOP_LIT)
4804 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4806 aopPut (AOP (result),
4807 aopGet (AOP (left), offset, FALSE, FALSE),
4811 else if (bytelit == 0)
4813 aopPut (AOP (result), zero, offset);
4817 // faster than result <- left, anl result,right
4818 // and better if result is SFR
4819 if (AOP_TYPE (left) == AOP_ACC)
4820 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4823 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4824 emitcode ("anl", "a,%s",
4825 aopGet (AOP (left), offset, FALSE, FALSE));
4827 aopPut (AOP (result), "a", offset);
4833 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4834 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4835 freeAsmop (result, NULL, ic, TRUE);
4838 /*-----------------------------------------------------------------*/
4839 /* genOr - code for or */
4840 /*-----------------------------------------------------------------*/
4842 genOr (iCode * ic, iCode * ifx)
4844 operand *left, *right, *result;
4845 int size, offset = 0;
4846 unsigned long lit = 0L;
4848 D(emitcode (";", "genOr"));
4850 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4851 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4852 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4855 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4857 AOP_TYPE (left), AOP_TYPE (right));
4858 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4860 AOP_SIZE (left), AOP_SIZE (right));
4863 /* if left is a literal & right is not then exchange them */
4864 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4865 AOP_NEEDSACC (left))
4867 operand *tmp = right;
4872 /* if result = right then exchange them */
4873 if (sameRegs (AOP (result), AOP (right)))
4875 operand *tmp = right;
4880 /* if right is bit then exchange them */
4881 if (AOP_TYPE (right) == AOP_CRY &&
4882 AOP_TYPE (left) != AOP_CRY)
4884 operand *tmp = right;
4888 if (AOP_TYPE (right) == AOP_LIT)
4889 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4891 size = AOP_SIZE (result);
4895 if (AOP_TYPE (left) == AOP_CRY)
4897 if (AOP_TYPE (right) == AOP_LIT)
4899 // c = bit & literal;
4902 // lit != 0 => result = 1
4903 if (AOP_TYPE (result) == AOP_CRY)
4906 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4908 continueIfTrue (ifx);
4911 emitcode ("setb", "c");
4915 // lit == 0 => result = left
4916 if (size && sameRegs (AOP (result), AOP (left)))
4918 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4923 if (AOP_TYPE (right) == AOP_CRY)
4926 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4927 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4932 symbol *tlbl = newiTempLabel (NULL);
4933 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4934 emitcode ("setb", "c");
4935 emitcode ("jb", "%s,%05d$",
4936 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4938 emitcode ("jnz", "%05d$", tlbl->key + 100);
4939 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4941 jmpTrueOrFalse (ifx, tlbl);
4947 emitcode ("", "%05d$:", tlbl->key + 100);
4956 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4957 genIfxJump (ifx, "c");
4961 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4962 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4963 if ((AOP_TYPE (right) == AOP_LIT) &&
4964 (AOP_TYPE (result) == AOP_CRY) &&
4965 (AOP_TYPE (left) != AOP_CRY))
4971 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4973 continueIfTrue (ifx);
4978 // lit = 0, result = boolean(left)
4980 emitcode ("setb", "c");
4984 symbol *tlbl = newiTempLabel (NULL);
4985 emitcode ("jnz", "%05d$", tlbl->key + 100);
4987 emitcode ("", "%05d$:", tlbl->key + 100);
4991 genIfxJump (ifx, "a");
4999 /* if left is same as result */
5000 if (sameRegs (AOP (result), AOP (left)))
5002 for (; size--; offset++)
5004 if (AOP_TYPE (right) == AOP_LIT)
5006 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5008 else if (IS_AOP_PREG (left))
5010 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5011 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5012 aopPut (AOP (result), "a", offset);
5015 emitcode ("orl", "%s,%s",
5016 aopGet (AOP (left), offset, FALSE, TRUE),
5017 aopGet (AOP (right), offset, FALSE, FALSE));
5021 if (AOP_TYPE (left) == AOP_ACC)
5022 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5025 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5026 if (IS_AOP_PREG (left))
5028 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5029 aopPut (AOP (result), "a", offset);
5032 emitcode ("orl", "%s,a",
5033 aopGet (AOP (left), offset, FALSE, TRUE));
5040 // left & result in different registers
5041 if (AOP_TYPE (result) == AOP_CRY)
5044 // if(size), result in bit
5045 // if(!size && ifx), conditional oper: if(left | right)
5046 symbol *tlbl = newiTempLabel (NULL);
5047 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5049 emitcode ("setb", "c");
5052 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5053 emitcode ("orl", "a,%s",
5054 aopGet (AOP (right), offset, FALSE, FALSE));
5056 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5057 emitcode ("orl", "a,%s",
5058 aopGet (AOP (left), offset, FALSE, FALSE));
5060 emitcode ("jnz", "%05d$", tlbl->key + 100);
5066 emitcode ("", "%05d$:", tlbl->key + 100);
5070 jmpTrueOrFalse (ifx, tlbl);
5073 for (; (size--); offset++)
5076 // result = left & right
5077 if (AOP_TYPE (right) == AOP_LIT)
5079 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5081 aopPut (AOP (result),
5082 aopGet (AOP (left), offset, FALSE, FALSE),
5087 // faster than result <- left, anl result,right
5088 // and better if result is SFR
5089 if (AOP_TYPE (left) == AOP_ACC)
5090 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5093 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5094 emitcode ("orl", "a,%s",
5095 aopGet (AOP (left), offset, FALSE, FALSE));
5097 aopPut (AOP (result), "a", offset);
5102 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5103 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5104 freeAsmop (result, NULL, ic, TRUE);
5107 /*-----------------------------------------------------------------*/
5108 /* genXor - code for xclusive or */
5109 /*-----------------------------------------------------------------*/
5111 genXor (iCode * ic, iCode * ifx)
5113 operand *left, *right, *result;
5114 int size, offset = 0;
5115 unsigned long lit = 0L;
5117 D(emitcode (";", "genXor"));
5119 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5120 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5121 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5124 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5126 AOP_TYPE (left), AOP_TYPE (right));
5127 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5129 AOP_SIZE (left), AOP_SIZE (right));
5132 /* if left is a literal & right is not ||
5133 if left needs acc & right does not */
5134 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5135 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5137 operand *tmp = right;
5142 /* if result = right then exchange them */
5143 if (sameRegs (AOP (result), AOP (right)))
5145 operand *tmp = right;
5150 /* if right is bit then exchange them */
5151 if (AOP_TYPE (right) == AOP_CRY &&
5152 AOP_TYPE (left) != AOP_CRY)
5154 operand *tmp = right;
5158 if (AOP_TYPE (right) == AOP_LIT)
5159 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5161 size = AOP_SIZE (result);
5165 if (AOP_TYPE (left) == AOP_CRY)
5167 if (AOP_TYPE (right) == AOP_LIT)
5169 // c = bit & literal;
5172 // lit>>1 != 0 => result = 1
5173 if (AOP_TYPE (result) == AOP_CRY)
5176 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5178 continueIfTrue (ifx);
5181 emitcode ("setb", "c");
5188 // lit == 0, result = left
5189 if (size && sameRegs (AOP (result), AOP (left)))
5191 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5195 // lit == 1, result = not(left)
5196 if (size && sameRegs (AOP (result), AOP (left)))
5198 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5203 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5204 emitcode ("cpl", "c");
5213 symbol *tlbl = newiTempLabel (NULL);
5214 if (AOP_TYPE (right) == AOP_CRY)
5217 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5221 int sizer = AOP_SIZE (right);
5223 // if val>>1 != 0, result = 1
5224 emitcode ("setb", "c");
5227 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5229 // test the msb of the lsb
5230 emitcode ("anl", "a,#0xfe");
5231 emitcode ("jnz", "%05d$", tlbl->key + 100);
5235 emitcode ("rrc", "a");
5237 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5238 emitcode ("cpl", "c");
5239 emitcode ("", "%05d$:", (tlbl->key + 100));
5246 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5247 genIfxJump (ifx, "c");
5251 if (sameRegs (AOP (result), AOP (left)))
5253 /* if left is same as result */
5254 for (; size--; offset++)
5256 if (AOP_TYPE (right) == AOP_LIT)
5258 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5260 else if (IS_AOP_PREG (left))
5262 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5263 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5264 aopPut (AOP (result), "a", offset);
5267 emitcode ("xrl", "%s,%s",
5268 aopGet (AOP (left), offset, FALSE, TRUE),
5269 aopGet (AOP (right), offset, FALSE, FALSE));
5273 if (AOP_TYPE (left) == AOP_ACC)
5274 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5277 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5278 if (IS_AOP_PREG (left))
5280 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5281 aopPut (AOP (result), "a", offset);
5284 emitcode ("xrl", "%s,a",
5285 aopGet (AOP (left), offset, FALSE, TRUE));
5292 // left & result in different registers
5293 if (AOP_TYPE (result) == AOP_CRY)
5296 // if(size), result in bit
5297 // if(!size && ifx), conditional oper: if(left ^ right)
5298 symbol *tlbl = newiTempLabel (NULL);
5299 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5301 emitcode ("setb", "c");
5304 if ((AOP_TYPE (right) == AOP_LIT) &&
5305 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5307 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5311 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5312 emitcode ("xrl", "a,%s",
5313 aopGet (AOP (right), offset, FALSE, FALSE));
5315 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5316 emitcode ("xrl", "a,%s",
5317 aopGet (AOP (left), offset, FALSE, FALSE));
5320 emitcode ("jnz", "%05d$", tlbl->key + 100);
5326 emitcode ("", "%05d$:", tlbl->key + 100);
5330 jmpTrueOrFalse (ifx, tlbl);
5333 for (; (size--); offset++)
5336 // result = left & right
5337 if (AOP_TYPE (right) == AOP_LIT)
5339 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5341 aopPut (AOP (result),
5342 aopGet (AOP (left), offset, FALSE, FALSE),
5347 // faster than result <- left, anl result,right
5348 // and better if result is SFR
5349 if (AOP_TYPE (left) == AOP_ACC)
5350 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5353 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5354 emitcode ("xrl", "a,%s",
5355 aopGet (AOP (left), offset, FALSE, TRUE));
5357 aopPut (AOP (result), "a", offset);
5362 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5363 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5364 freeAsmop (result, NULL, ic, TRUE);
5367 /*-----------------------------------------------------------------*/
5368 /* genInline - write the inline code out */
5369 /*-----------------------------------------------------------------*/
5371 genInline (iCode * ic)
5373 char *buffer, *bp, *bp1;
5375 D(emitcode (";", "genInline"));
5377 _G.inLine += (!options.asmpeep);
5379 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5380 strcpy (buffer, IC_INLINE (ic));
5382 /* emit each line as a code */
5407 /* emitcode("",buffer); */
5408 _G.inLine -= (!options.asmpeep);
5411 /*-----------------------------------------------------------------*/
5412 /* genRRC - rotate right with carry */
5413 /*-----------------------------------------------------------------*/
5417 operand *left, *result;
5418 int size, offset = 0;
5421 D(emitcode (";", "genRRC"));
5423 /* rotate right with carry */
5424 left = IC_LEFT (ic);
5425 result = IC_RESULT (ic);
5426 aopOp (left, ic, FALSE);
5427 aopOp (result, ic, FALSE);
5429 /* move it to the result */
5430 size = AOP_SIZE (result);
5432 if (size == 1) { /* special case for 1 byte */
5433 l = aopGet (AOP (left), offset, FALSE, FALSE);
5435 emitcode ("rr", "a");
5441 l = aopGet (AOP (left), offset, FALSE, FALSE);
5443 emitcode ("rrc", "a");
5444 if (AOP_SIZE (result) > 1)
5445 aopPut (AOP (result), "a", offset--);
5447 /* now we need to put the carry into the
5448 highest order byte of the result */
5449 if (AOP_SIZE (result) > 1)
5451 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5454 emitcode ("mov", "acc.7,c");
5456 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5457 freeAsmop (left, NULL, ic, TRUE);
5458 freeAsmop (result, NULL, ic, TRUE);
5461 /*-----------------------------------------------------------------*/
5462 /* genRLC - generate code for rotate left with carry */
5463 /*-----------------------------------------------------------------*/
5467 operand *left, *result;
5468 int size, offset = 0;
5471 D(emitcode (";", "genRLC"));
5473 /* rotate right with carry */
5474 left = IC_LEFT (ic);
5475 result = IC_RESULT (ic);
5476 aopOp (left, ic, FALSE);
5477 aopOp (result, ic, FALSE);
5479 /* move it to the result */
5480 size = AOP_SIZE (result);
5484 l = aopGet (AOP (left), offset, FALSE, FALSE);
5486 if (size == 0) { /* special case for 1 byte */
5490 emitcode ("add", "a,acc");
5491 if (AOP_SIZE (result) > 1)
5492 aopPut (AOP (result), "a", offset++);
5495 l = aopGet (AOP (left), offset, FALSE, FALSE);
5497 emitcode ("rlc", "a");
5498 if (AOP_SIZE (result) > 1)
5499 aopPut (AOP (result), "a", offset++);
5502 /* now we need to put the carry into the
5503 highest order byte of the result */
5504 if (AOP_SIZE (result) > 1)
5506 l = aopGet (AOP (result), 0, FALSE, FALSE);
5509 emitcode ("mov", "acc.0,c");
5511 aopPut (AOP (result), "a", 0);
5512 freeAsmop (left, NULL, ic, TRUE);
5513 freeAsmop (result, NULL, ic, TRUE);
5516 /*-----------------------------------------------------------------*/
5517 /* genGetHbit - generates code get highest order bit */
5518 /*-----------------------------------------------------------------*/
5520 genGetHbit (iCode * ic)
5522 operand *left, *result;
5524 D(emitcode (";", "genGetHbit"));
5526 left = IC_LEFT (ic);
5527 result = IC_RESULT (ic);
5528 aopOp (left, ic, FALSE);
5529 aopOp (result, ic, FALSE);
5531 /* get the highest order byte into a */
5532 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5533 if (AOP_TYPE (result) == AOP_CRY)
5535 emitcode ("rlc", "a");
5540 emitcode ("rl", "a");
5541 emitcode ("anl", "a,#0x01");
5546 freeAsmop (left, NULL, ic, TRUE);
5547 freeAsmop (result, NULL, ic, TRUE);
5550 /*-----------------------------------------------------------------*/
5551 /* AccRol - rotate left accumulator by known count */
5552 /*-----------------------------------------------------------------*/
5554 AccRol (int shCount)
5556 shCount &= 0x0007; // shCount : 0..7
5563 emitcode ("rl", "a");
5566 emitcode ("rl", "a");
5567 emitcode ("rl", "a");
5570 emitcode ("swap", "a");
5571 emitcode ("rr", "a");
5574 emitcode ("swap", "a");
5577 emitcode ("swap", "a");
5578 emitcode ("rl", "a");
5581 emitcode ("rr", "a");
5582 emitcode ("rr", "a");
5585 emitcode ("rr", "a");
5590 /*-----------------------------------------------------------------*/
5591 /* AccLsh - left shift accumulator by known count */
5592 /*-----------------------------------------------------------------*/
5594 AccLsh (int shCount)
5599 emitcode ("add", "a,acc");
5600 else if (shCount == 2)
5602 emitcode ("add", "a,acc");
5603 emitcode ("add", "a,acc");
5607 /* rotate left accumulator */
5609 /* and kill the lower order bits */
5610 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5615 /*-----------------------------------------------------------------*/
5616 /* AccRsh - right shift accumulator by known count */
5617 /*-----------------------------------------------------------------*/
5619 AccRsh (int shCount)
5626 emitcode ("rrc", "a");
5630 /* rotate right accumulator */
5631 AccRol (8 - shCount);
5632 /* and kill the higher order bits */
5633 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5638 /*-----------------------------------------------------------------*/
5639 /* AccSRsh - signed right shift accumulator by known count */
5640 /*-----------------------------------------------------------------*/
5642 AccSRsh (int shCount)
5649 emitcode ("mov", "c,acc.7");
5650 emitcode ("rrc", "a");
5652 else if (shCount == 2)
5654 emitcode ("mov", "c,acc.7");
5655 emitcode ("rrc", "a");
5656 emitcode ("mov", "c,acc.7");
5657 emitcode ("rrc", "a");
5661 tlbl = newiTempLabel (NULL);
5662 /* rotate right accumulator */
5663 AccRol (8 - shCount);
5664 /* and kill the higher order bits */
5665 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5666 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5667 emitcode ("orl", "a,#0x%02x",
5668 (unsigned char) ~SRMask[shCount]);
5669 emitcode ("", "%05d$:", tlbl->key + 100);
5674 /*-----------------------------------------------------------------*/
5675 /* shiftR1Left2Result - shift right one byte from left to result */
5676 /*-----------------------------------------------------------------*/
5678 shiftR1Left2Result (operand * left, int offl,
5679 operand * result, int offr,
5680 int shCount, int sign)
5682 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5683 /* shift right accumulator */
5688 aopPut (AOP (result), "a", offr);
5691 /*-----------------------------------------------------------------*/
5692 /* shiftL1Left2Result - shift left one byte from left to result */
5693 /*-----------------------------------------------------------------*/
5695 shiftL1Left2Result (operand * left, int offl,
5696 operand * result, int offr, int shCount)
5699 l = aopGet (AOP (left), offl, FALSE, FALSE);
5701 /* shift left accumulator */
5703 aopPut (AOP (result), "a", offr);
5706 /*-----------------------------------------------------------------*/
5707 /* movLeft2Result - move byte from left to result */
5708 /*-----------------------------------------------------------------*/
5710 movLeft2Result (operand * left, int offl,
5711 operand * result, int offr, int sign)
5714 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5716 l = aopGet (AOP (left), offl, FALSE, FALSE);
5718 if (*l == '@' && (IS_AOP_PREG (result)))
5720 emitcode ("mov", "a,%s", l);
5721 aopPut (AOP (result), "a", offr);
5726 aopPut (AOP (result), l, offr);
5729 /* MSB sign in acc.7 ! */
5730 if (getDataSize (left) == offl + 1)
5732 emitcode ("mov", "a,%s", l);
5733 aopPut (AOP (result), "a", offr);
5740 /*-----------------------------------------------------------------*/
5741 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5742 /*-----------------------------------------------------------------*/
5746 emitcode ("rrc", "a");
5747 emitcode ("xch", "a,%s", x);
5748 emitcode ("rrc", "a");
5749 emitcode ("xch", "a,%s", x);
5752 /*-----------------------------------------------------------------*/
5753 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5754 /*-----------------------------------------------------------------*/
5758 emitcode ("xch", "a,%s", x);
5759 emitcode ("rlc", "a");
5760 emitcode ("xch", "a,%s", x);
5761 emitcode ("rlc", "a");
5764 /*-----------------------------------------------------------------*/
5765 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5766 /*-----------------------------------------------------------------*/
5770 emitcode ("xch", "a,%s", x);
5771 emitcode ("add", "a,acc");
5772 emitcode ("xch", "a,%s", x);
5773 emitcode ("rlc", "a");
5776 /*-----------------------------------------------------------------*/
5777 /* AccAXLsh - left shift a:x by known count (0..7) */
5778 /*-----------------------------------------------------------------*/
5780 AccAXLsh (char *x, int shCount)
5795 case 5: // AAAAABBB:CCCCCDDD
5797 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5799 emitcode ("anl", "a,#0x%02x",
5800 SLMask[shCount]); // BBB00000:CCCCCDDD
5802 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5804 AccRol (shCount); // DDDCCCCC:BBB00000
5806 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5808 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5810 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5812 emitcode ("anl", "a,#0x%02x",
5813 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5815 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5817 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5820 case 6: // AAAAAABB:CCCCCCDD
5821 emitcode ("anl", "a,#0x%02x",
5822 SRMask[shCount]); // 000000BB:CCCCCCDD
5823 emitcode ("mov", "c,acc.0"); // c = B
5824 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5826 AccAXRrl1 (x); // BCCCCCCD:D000000B
5827 AccAXRrl1 (x); // BBCCCCCC:DD000000
5829 emitcode("rrc","a");
5830 emitcode("xch","a,%s", x);
5831 emitcode("rrc","a");
5832 emitcode("mov","c,acc.0"); //<< get correct bit
5833 emitcode("xch","a,%s", x);
5835 emitcode("rrc","a");
5836 emitcode("xch","a,%s", x);
5837 emitcode("rrc","a");
5838 emitcode("xch","a,%s", x);
5841 case 7: // a:x <<= 7
5843 emitcode ("anl", "a,#0x%02x",
5844 SRMask[shCount]); // 0000000B:CCCCCCCD
5846 emitcode ("mov", "c,acc.0"); // c = B
5848 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5850 AccAXRrl1 (x); // BCCCCCCC:D0000000
5858 /*-----------------------------------------------------------------*/
5859 /* AccAXRsh - right shift a:x known count (0..7) */
5860 /*-----------------------------------------------------------------*/
5862 AccAXRsh (char *x, int shCount)
5870 AccAXRrl1 (x); // 0->a:x
5875 AccAXRrl1 (x); // 0->a:x
5878 AccAXRrl1 (x); // 0->a:x
5883 case 5: // AAAAABBB:CCCCCDDD = a:x
5885 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5887 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5889 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5891 emitcode ("anl", "a,#0x%02x",
5892 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5894 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5896 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5898 emitcode ("anl", "a,#0x%02x",
5899 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5901 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5903 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5905 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5908 case 6: // AABBBBBB:CCDDDDDD
5910 emitcode ("mov", "c,acc.7");
5911 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5913 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5915 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5917 emitcode ("anl", "a,#0x%02x",
5918 SRMask[shCount]); // 000000AA:BBBBBBCC
5921 case 7: // ABBBBBBB:CDDDDDDD
5923 emitcode ("mov", "c,acc.7"); // c = A
5925 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5927 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5929 emitcode ("anl", "a,#0x%02x",
5930 SRMask[shCount]); // 0000000A:BBBBBBBC
5938 /*-----------------------------------------------------------------*/
5939 /* AccAXRshS - right shift signed a:x known count (0..7) */
5940 /*-----------------------------------------------------------------*/
5942 AccAXRshS (char *x, int shCount)
5950 emitcode ("mov", "c,acc.7");
5951 AccAXRrl1 (x); // s->a:x
5955 emitcode ("mov", "c,acc.7");
5956 AccAXRrl1 (x); // s->a:x
5958 emitcode ("mov", "c,acc.7");
5959 AccAXRrl1 (x); // s->a:x
5964 case 5: // AAAAABBB:CCCCCDDD = a:x
5966 tlbl = newiTempLabel (NULL);
5967 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5969 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5971 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5973 emitcode ("anl", "a,#0x%02x",
5974 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5976 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5978 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5980 emitcode ("anl", "a,#0x%02x",
5981 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5983 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5985 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5987 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5989 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5990 emitcode ("orl", "a,#0x%02x",
5991 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5993 emitcode ("", "%05d$:", tlbl->key + 100);
5994 break; // SSSSAAAA:BBBCCCCC
5996 case 6: // AABBBBBB:CCDDDDDD
5998 tlbl = newiTempLabel (NULL);
5999 emitcode ("mov", "c,acc.7");
6000 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6002 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6004 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6006 emitcode ("anl", "a,#0x%02x",
6007 SRMask[shCount]); // 000000AA:BBBBBBCC
6009 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6010 emitcode ("orl", "a,#0x%02x",
6011 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6013 emitcode ("", "%05d$:", tlbl->key + 100);
6015 case 7: // ABBBBBBB:CDDDDDDD
6017 tlbl = newiTempLabel (NULL);
6018 emitcode ("mov", "c,acc.7"); // c = A
6020 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6022 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6024 emitcode ("anl", "a,#0x%02x",
6025 SRMask[shCount]); // 0000000A:BBBBBBBC
6027 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6028 emitcode ("orl", "a,#0x%02x",
6029 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6031 emitcode ("", "%05d$:", tlbl->key + 100);
6038 /*-----------------------------------------------------------------*/
6039 /* shiftL2Left2Result - shift left two bytes from left to result */
6040 /*-----------------------------------------------------------------*/
6042 shiftL2Left2Result (operand * left, int offl,
6043 operand * result, int offr, int shCount)
6045 if (sameRegs (AOP (result), AOP (left)) &&
6046 ((offl + MSB16) == offr))
6048 /* don't crash result[offr] */
6049 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6050 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6054 movLeft2Result (left, offl, result, offr, 0);
6055 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6057 /* ax << shCount (x = lsb(result)) */
6058 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6059 aopPut (AOP (result), "a", offr + MSB16);
6063 /*-----------------------------------------------------------------*/
6064 /* shiftR2Left2Result - shift right two bytes from left to result */
6065 /*-----------------------------------------------------------------*/
6067 shiftR2Left2Result (operand * left, int offl,
6068 operand * result, int offr,
6069 int shCount, int sign)
6071 if (sameRegs (AOP (result), AOP (left)) &&
6072 ((offl + MSB16) == offr))
6074 /* don't crash result[offr] */
6075 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6076 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6080 movLeft2Result (left, offl, result, offr, 0);
6081 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6083 /* a:x >> shCount (x = lsb(result)) */
6085 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6087 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6088 if (getDataSize (result) > 1)
6089 aopPut (AOP (result), "a", offr + MSB16);
6092 /*-----------------------------------------------------------------*/
6093 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6094 /*-----------------------------------------------------------------*/
6096 shiftLLeftOrResult (operand * left, int offl,
6097 operand * result, int offr, int shCount)
6099 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6100 /* shift left accumulator */
6102 /* or with result */
6103 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6104 /* back to result */
6105 aopPut (AOP (result), "a", offr);
6108 /*-----------------------------------------------------------------*/
6109 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6110 /*-----------------------------------------------------------------*/
6112 shiftRLeftOrResult (operand * left, int offl,
6113 operand * result, int offr, int shCount)
6115 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6116 /* shift right accumulator */
6118 /* or with result */
6119 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6120 /* back to result */
6121 aopPut (AOP (result), "a", offr);
6124 /*-----------------------------------------------------------------*/
6125 /* genlshOne - left shift a one byte quantity by known count */
6126 /*-----------------------------------------------------------------*/
6128 genlshOne (operand * result, operand * left, int shCount)
6130 D(emitcode (";", "genlshOne"));
6132 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6135 /*-----------------------------------------------------------------*/
6136 /* genlshTwo - left shift two bytes by known amount != 0 */
6137 /*-----------------------------------------------------------------*/
6139 genlshTwo (operand * result, operand * left, int shCount)
6143 D(emitcode (";", "genlshTwo"));
6145 size = getDataSize (result);
6147 /* if shCount >= 8 */
6155 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6157 movLeft2Result (left, LSB, result, MSB16, 0);
6159 aopPut (AOP (result), zero, LSB);
6162 /* 1 <= shCount <= 7 */
6166 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6168 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6172 /*-----------------------------------------------------------------*/
6173 /* shiftLLong - shift left one long from left to result */
6174 /* offl = LSB or MSB16 */
6175 /*-----------------------------------------------------------------*/
6177 shiftLLong (operand * left, operand * result, int offr)
6180 int size = AOP_SIZE (result);
6182 if (size >= LSB + offr)
6184 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6186 emitcode ("add", "a,acc");
6187 if (sameRegs (AOP (left), AOP (result)) &&
6188 size >= MSB16 + offr && offr != LSB)
6189 emitcode ("xch", "a,%s",
6190 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6192 aopPut (AOP (result), "a", LSB + offr);
6195 if (size >= MSB16 + offr)
6197 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6199 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6202 emitcode ("rlc", "a");
6203 if (sameRegs (AOP (left), AOP (result)) &&
6204 size >= MSB24 + offr && offr != LSB)
6205 emitcode ("xch", "a,%s",
6206 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6208 aopPut (AOP (result), "a", MSB16 + offr);
6211 if (size >= MSB24 + offr)
6213 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6215 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6218 emitcode ("rlc", "a");
6219 if (sameRegs (AOP (left), AOP (result)) &&
6220 size >= MSB32 + offr && offr != LSB)
6221 emitcode ("xch", "a,%s",
6222 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6224 aopPut (AOP (result), "a", MSB24 + offr);
6227 if (size > MSB32 + offr)
6229 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6231 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6234 emitcode ("rlc", "a");
6235 aopPut (AOP (result), "a", MSB32 + offr);
6238 aopPut (AOP (result), zero, LSB);
6241 /*-----------------------------------------------------------------*/
6242 /* genlshFour - shift four byte by a known amount != 0 */
6243 /*-----------------------------------------------------------------*/
6245 genlshFour (operand * result, operand * left, int shCount)
6249 D(emitcode (";", "genlshFour"));
6251 size = AOP_SIZE (result);
6253 /* if shifting more that 3 bytes */
6258 /* lowest order of left goes to the highest
6259 order of the destination */
6260 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6262 movLeft2Result (left, LSB, result, MSB32, 0);
6263 aopPut (AOP (result), zero, LSB);
6264 aopPut (AOP (result), zero, MSB16);
6265 aopPut (AOP (result), zero, MSB24);
6269 /* more than two bytes */
6270 else if (shCount >= 16)
6272 /* lower order two bytes goes to higher order two bytes */
6274 /* if some more remaining */
6276 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6279 movLeft2Result (left, MSB16, result, MSB32, 0);
6280 movLeft2Result (left, LSB, result, MSB24, 0);
6282 aopPut (AOP (result), zero, MSB16);
6283 aopPut (AOP (result), zero, LSB);
6287 /* if more than 1 byte */
6288 else if (shCount >= 8)
6290 /* lower order three bytes goes to higher order three bytes */
6295 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6297 movLeft2Result (left, LSB, result, MSB16, 0);
6303 movLeft2Result (left, MSB24, result, MSB32, 0);
6304 movLeft2Result (left, MSB16, result, MSB24, 0);
6305 movLeft2Result (left, LSB, result, MSB16, 0);
6306 aopPut (AOP (result), zero, LSB);
6308 else if (shCount == 1)
6309 shiftLLong (left, result, MSB16);
6312 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6313 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6314 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6315 aopPut (AOP (result), zero, LSB);
6320 /* 1 <= shCount <= 7 */
6321 else if (shCount <= 2)
6323 shiftLLong (left, result, LSB);
6325 shiftLLong (result, result, LSB);
6327 /* 3 <= shCount <= 7, optimize */
6330 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6331 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6332 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6336 /*-----------------------------------------------------------------*/
6337 /* genLeftShiftLiteral - left shifting by known count */
6338 /*-----------------------------------------------------------------*/
6340 genLeftShiftLiteral (operand * left,
6345 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6348 D(emitcode (";", "genLeftShiftLiteral"));
6350 freeAsmop (right, NULL, ic, TRUE);
6352 aopOp (left, ic, FALSE);
6353 aopOp (result, ic, FALSE);
6355 size = getSize (operandType (result));
6358 emitcode ("; shift left ", "result %d, left %d", size,
6362 /* I suppose that the left size >= result size */
6367 movLeft2Result (left, size, result, size, 0);
6371 else if (shCount >= (size * 8))
6373 aopPut (AOP (result), zero, size);
6379 genlshOne (result, left, shCount);
6383 genlshTwo (result, left, shCount);
6387 genlshFour (result, left, shCount);
6390 fprintf(stderr, "*** ack! mystery literal shift!\n");
6394 freeAsmop (left, NULL, ic, TRUE);
6395 freeAsmop (result, NULL, ic, TRUE);
6398 /*-----------------------------------------------------------------*/
6399 /* genLeftShift - generates code for left shifting */
6400 /*-----------------------------------------------------------------*/
6402 genLeftShift (iCode * ic)
6404 operand *left, *right, *result;
6407 symbol *tlbl, *tlbl1;
6409 D(emitcode (";", "genLeftShift"));
6411 right = IC_RIGHT (ic);
6412 left = IC_LEFT (ic);
6413 result = IC_RESULT (ic);
6415 aopOp (right, ic, FALSE);
6417 /* if the shift count is known then do it
6418 as efficiently as possible */
6419 if (AOP_TYPE (right) == AOP_LIT)
6421 genLeftShiftLiteral (left, right, result, ic);
6425 /* shift count is unknown then we have to form
6426 a loop get the loop count in B : Note: we take
6427 only the lower order byte since shifting
6428 more that 32 bits make no sense anyway, ( the
6429 largest size of an object can be only 32 bits ) */
6431 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6432 emitcode ("inc", "b");
6433 freeAsmop (right, NULL, ic, TRUE);
6434 aopOp (left, ic, FALSE);
6435 aopOp (result, ic, FALSE);
6437 /* now move the left to the result if they are not the
6439 if (!sameRegs (AOP (left), AOP (result)) &&
6440 AOP_SIZE (result) > 1)
6443 size = AOP_SIZE (result);
6447 l = aopGet (AOP (left), offset, FALSE, TRUE);
6448 if (*l == '@' && (IS_AOP_PREG (result)))
6451 emitcode ("mov", "a,%s", l);
6452 aopPut (AOP (result), "a", offset);
6455 aopPut (AOP (result), l, offset);
6460 tlbl = newiTempLabel (NULL);
6461 size = AOP_SIZE (result);
6463 tlbl1 = newiTempLabel (NULL);
6465 /* if it is only one byte then */
6468 symbol *tlbl1 = newiTempLabel (NULL);
6470 l = aopGet (AOP (left), 0, FALSE, FALSE);
6472 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6473 emitcode ("", "%05d$:", tlbl->key + 100);
6474 emitcode ("add", "a,acc");
6475 emitcode ("", "%05d$:", tlbl1->key + 100);
6476 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6477 aopPut (AOP (result), "a", 0);
6481 reAdjustPreg (AOP (result));
6483 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6484 emitcode ("", "%05d$:", tlbl->key + 100);
6485 l = aopGet (AOP (result), offset, FALSE, FALSE);
6487 emitcode ("add", "a,acc");
6488 aopPut (AOP (result), "a", offset++);
6491 l = aopGet (AOP (result), offset, FALSE, FALSE);
6493 emitcode ("rlc", "a");
6494 aopPut (AOP (result), "a", offset++);
6496 reAdjustPreg (AOP (result));
6498 emitcode ("", "%05d$:", tlbl1->key + 100);
6499 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6501 freeAsmop (left, NULL, ic, TRUE);
6502 freeAsmop (result, NULL, ic, TRUE);
6505 /*-----------------------------------------------------------------*/
6506 /* genrshOne - right shift a one byte quantity by known count */
6507 /*-----------------------------------------------------------------*/
6509 genrshOne (operand * result, operand * left,
6510 int shCount, int sign)
6512 D(emitcode (";", "genrshOne"));
6514 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6517 /*-----------------------------------------------------------------*/
6518 /* genrshTwo - right shift two bytes by known amount != 0 */
6519 /*-----------------------------------------------------------------*/
6521 genrshTwo (operand * result, operand * left,
6522 int shCount, int sign)
6524 D(emitcode (";", "genrshTwo"));
6526 /* if shCount >= 8 */
6531 shiftR1Left2Result (left, MSB16, result, LSB,
6534 movLeft2Result (left, MSB16, result, LSB, sign);
6535 addSign (result, MSB16, sign);
6538 /* 1 <= shCount <= 7 */
6540 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6543 /*-----------------------------------------------------------------*/
6544 /* shiftRLong - shift right one long from left to result */
6545 /* offl = LSB or MSB16 */
6546 /*-----------------------------------------------------------------*/
6548 shiftRLong (operand * left, int offl,
6549 operand * result, int sign)
6551 int isSameRegs=sameRegs(AOP(left),AOP(result));
6553 if (isSameRegs && offl>1) {
6554 // we are in big trouble, but this shouldn't happen
6555 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6558 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6563 emitcode ("rlc", "a");
6564 emitcode ("subb", "a,acc");
6565 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6567 aopPut (AOP(result), zero, MSB32);
6572 emitcode ("clr", "c");
6574 emitcode ("mov", "c,acc.7");
6577 emitcode ("rrc", "a");
6579 if (isSameRegs && offl==MSB16) {
6580 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6582 aopPut (AOP (result), "a", MSB32);
6583 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6586 emitcode ("rrc", "a");
6587 if (isSameRegs && offl==1) {
6588 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6590 aopPut (AOP (result), "a", MSB24);
6591 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6593 emitcode ("rrc", "a");
6594 aopPut (AOP (result), "a", MSB16 - offl);
6598 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6599 emitcode ("rrc", "a");
6600 aopPut (AOP (result), "a", LSB);
6604 /*-----------------------------------------------------------------*/
6605 /* genrshFour - shift four byte by a known amount != 0 */
6606 /*-----------------------------------------------------------------*/
6608 genrshFour (operand * result, operand * left,
6609 int shCount, int sign)
6611 D(emitcode (";", "genrshFour"));
6613 /* if shifting more that 3 bytes */
6618 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6620 movLeft2Result (left, MSB32, result, LSB, sign);
6621 addSign (result, MSB16, sign);
6623 else if (shCount >= 16)
6627 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6630 movLeft2Result (left, MSB24, result, LSB, 0);
6631 movLeft2Result (left, MSB32, result, MSB16, sign);
6633 addSign (result, MSB24, sign);
6635 else if (shCount >= 8)
6639 shiftRLong (left, MSB16, result, sign);
6640 else if (shCount == 0)
6642 movLeft2Result (left, MSB16, result, LSB, 0);
6643 movLeft2Result (left, MSB24, result, MSB16, 0);
6644 movLeft2Result (left, MSB32, result, MSB24, sign);
6645 addSign (result, MSB32, sign);
6649 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6650 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6651 /* the last shift is signed */
6652 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6653 addSign (result, MSB32, sign);
6657 { /* 1 <= shCount <= 7 */
6660 shiftRLong (left, LSB, result, sign);
6662 shiftRLong (result, LSB, result, sign);
6666 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6667 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6668 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6673 /*-----------------------------------------------------------------*/
6674 /* genRightShiftLiteral - right shifting by known count */
6675 /*-----------------------------------------------------------------*/
6677 genRightShiftLiteral (operand * left,
6683 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6686 D(emitcode (";", "genRightShiftLiteral"));
6688 freeAsmop (right, NULL, ic, TRUE);
6690 aopOp (left, ic, FALSE);
6691 aopOp (result, ic, FALSE);
6694 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6698 size = getDataSize (left);
6699 /* test the LEFT size !!! */
6701 /* I suppose that the left size >= result size */
6704 size = getDataSize (result);
6706 movLeft2Result (left, size, result, size, 0);
6709 else if (shCount >= (size * 8))
6712 /* get sign in acc.7 */
6713 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6714 addSign (result, LSB, sign);
6721 genrshOne (result, left, shCount, sign);
6725 genrshTwo (result, left, shCount, sign);
6729 genrshFour (result, left, shCount, sign);
6735 freeAsmop (left, NULL, ic, TRUE);
6736 freeAsmop (result, NULL, ic, TRUE);
6740 /*-----------------------------------------------------------------*/
6741 /* genSignedRightShift - right shift of signed number */
6742 /*-----------------------------------------------------------------*/
6744 genSignedRightShift (iCode * ic)
6746 operand *right, *left, *result;
6749 symbol *tlbl, *tlbl1;
6751 D(emitcode (";", "genSignedRightShift"));
6753 /* we do it the hard way put the shift count in b
6754 and loop thru preserving the sign */
6756 right = IC_RIGHT (ic);
6757 left = IC_LEFT (ic);
6758 result = IC_RESULT (ic);
6760 aopOp (right, ic, FALSE);
6763 if (AOP_TYPE (right) == AOP_LIT)
6765 genRightShiftLiteral (left, right, result, ic, 1);
6768 /* shift count is unknown then we have to form
6769 a loop get the loop count in B : Note: we take
6770 only the lower order byte since shifting
6771 more that 32 bits make no sense anyway, ( the
6772 largest size of an object can be only 32 bits ) */
6774 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6775 emitcode ("inc", "b");
6776 freeAsmop (right, NULL, ic, TRUE);
6777 aopOp (left, ic, FALSE);
6778 aopOp (result, ic, FALSE);
6780 /* now move the left to the result if they are not the
6782 if (!sameRegs (AOP (left), AOP (result)) &&
6783 AOP_SIZE (result) > 1)
6786 size = AOP_SIZE (result);
6790 l = aopGet (AOP (left), offset, FALSE, TRUE);
6791 if (*l == '@' && IS_AOP_PREG (result))
6794 emitcode ("mov", "a,%s", l);
6795 aopPut (AOP (result), "a", offset);
6798 aopPut (AOP (result), l, offset);
6803 /* mov the highest order bit to OVR */
6804 tlbl = newiTempLabel (NULL);
6805 tlbl1 = newiTempLabel (NULL);
6807 size = AOP_SIZE (result);
6809 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6810 emitcode ("rlc", "a");
6811 emitcode ("mov", "ov,c");
6812 /* if it is only one byte then */
6815 l = aopGet (AOP (left), 0, FALSE, FALSE);
6817 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6818 emitcode ("", "%05d$:", tlbl->key + 100);
6819 emitcode ("mov", "c,ov");
6820 emitcode ("rrc", "a");
6821 emitcode ("", "%05d$:", tlbl1->key + 100);
6822 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6823 aopPut (AOP (result), "a", 0);
6827 reAdjustPreg (AOP (result));
6828 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6829 emitcode ("", "%05d$:", tlbl->key + 100);
6830 emitcode ("mov", "c,ov");
6833 l = aopGet (AOP (result), offset, FALSE, FALSE);
6835 emitcode ("rrc", "a");
6836 aopPut (AOP (result), "a", offset--);
6838 reAdjustPreg (AOP (result));
6839 emitcode ("", "%05d$:", tlbl1->key + 100);
6840 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6843 freeAsmop (left, NULL, ic, TRUE);
6844 freeAsmop (result, NULL, ic, TRUE);
6847 /*-----------------------------------------------------------------*/
6848 /* genRightShift - generate code for right shifting */
6849 /*-----------------------------------------------------------------*/
6851 genRightShift (iCode * ic)
6853 operand *right, *left, *result;
6857 symbol *tlbl, *tlbl1;
6859 D(emitcode (";", "genRightShift"));
6861 /* if signed then we do it the hard way preserve the
6862 sign bit moving it inwards */
6863 retype = getSpec (operandType (IC_RESULT (ic)));
6865 if (!SPEC_USIGN (retype))
6867 genSignedRightShift (ic);
6871 /* signed & unsigned types are treated the same : i.e. the
6872 signed is NOT propagated inwards : quoting from the
6873 ANSI - standard : "for E1 >> E2, is equivalent to division
6874 by 2**E2 if unsigned or if it has a non-negative value,
6875 otherwise the result is implementation defined ", MY definition
6876 is that the sign does not get propagated */
6878 right = IC_RIGHT (ic);
6879 left = IC_LEFT (ic);
6880 result = IC_RESULT (ic);
6882 aopOp (right, ic, FALSE);
6884 /* if the shift count is known then do it
6885 as efficiently as possible */
6886 if (AOP_TYPE (right) == AOP_LIT)
6888 genRightShiftLiteral (left, right, result, ic, 0);
6892 /* shift count is unknown then we have to form
6893 a loop get the loop count in B : Note: we take
6894 only the lower order byte since shifting
6895 more that 32 bits make no sense anyway, ( the
6896 largest size of an object can be only 32 bits ) */
6898 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6899 emitcode ("inc", "b");
6900 freeAsmop (right, NULL, ic, TRUE);
6901 aopOp (left, ic, FALSE);
6902 aopOp (result, ic, FALSE);
6904 /* now move the left to the result if they are not the
6906 if (!sameRegs (AOP (left), AOP (result)) &&
6907 AOP_SIZE (result) > 1)
6910 size = AOP_SIZE (result);
6914 l = aopGet (AOP (left), offset, FALSE, TRUE);
6915 if (*l == '@' && IS_AOP_PREG (result))
6918 emitcode ("mov", "a,%s", l);
6919 aopPut (AOP (result), "a", offset);
6922 aopPut (AOP (result), l, offset);
6927 tlbl = newiTempLabel (NULL);
6928 tlbl1 = newiTempLabel (NULL);
6929 size = AOP_SIZE (result);
6932 /* if it is only one byte then */
6935 l = aopGet (AOP (left), 0, FALSE, FALSE);
6937 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6938 emitcode ("", "%05d$:", tlbl->key + 100);
6940 emitcode ("rrc", "a");
6941 emitcode ("", "%05d$:", tlbl1->key + 100);
6942 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6943 aopPut (AOP (result), "a", 0);
6947 reAdjustPreg (AOP (result));
6948 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6949 emitcode ("", "%05d$:", tlbl->key + 100);
6953 l = aopGet (AOP (result), offset, FALSE, FALSE);
6955 emitcode ("rrc", "a");
6956 aopPut (AOP (result), "a", offset--);
6958 reAdjustPreg (AOP (result));
6960 emitcode ("", "%05d$:", tlbl1->key + 100);
6961 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6964 freeAsmop (left, NULL, ic, TRUE);
6965 freeAsmop (result, NULL, ic, TRUE);
6968 /*-----------------------------------------------------------------*/
6969 /* genUnpackBits - generates code for unpacking bits */
6970 /*-----------------------------------------------------------------*/
6972 genUnpackBits (operand * result, char *rname, int ptype)
6980 D(emitcode (";", "genUnpackBits"));
6982 etype = getSpec (operandType (result));
6983 rsize = getSize (operandType (result));
6984 /* read the first byte */
6990 emitcode ("mov", "a,@%s", rname);
6994 emitcode ("movx", "a,@%s", rname);
6998 emitcode ("movx", "a,@dptr");
7002 emitcode ("clr", "a");
7003 emitcode ("movc", "a,@a+dptr");
7007 emitcode ("lcall", "__gptrget");
7011 rlen = SPEC_BLEN (etype);
7013 /* if we have bitdisplacement then it fits */
7014 /* into this byte completely or if length is */
7015 /* less than a byte */
7016 if ((shCnt = SPEC_BSTR (etype)) ||
7017 (SPEC_BLEN (etype) <= 8))
7020 /* shift right acc */
7023 emitcode ("anl", "a,#0x%02x",
7024 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7025 aopPut (AOP (result), "a", offset++);
7029 /* bit field did not fit in a byte */
7030 aopPut (AOP (result), "a", offset++);
7039 emitcode ("inc", "%s", rname);
7040 emitcode ("mov", "a,@%s", rname);
7044 emitcode ("inc", "%s", rname);
7045 emitcode ("movx", "a,@%s", rname);
7049 emitcode ("inc", "dptr");
7050 emitcode ("movx", "a,@dptr");
7054 emitcode ("clr", "a");
7055 emitcode ("inc", "dptr");
7056 emitcode ("movc", "a,@a+dptr");
7060 emitcode ("inc", "dptr");
7061 emitcode ("lcall", "__gptrget");
7066 /* if we are done */
7070 aopPut (AOP (result), "a", offset++);
7076 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7078 aopPut (AOP (result), "a", offset++);
7086 aopPut (AOP (result), zero, offset++);
7092 /*-----------------------------------------------------------------*/
7093 /* genDataPointerGet - generates code when ptr offset is known */
7094 /*-----------------------------------------------------------------*/
7096 genDataPointerGet (operand * left,
7102 int size, offset = 0;
7104 D(emitcode (";", "genDataPointerGet"));
7106 aopOp (result, ic, TRUE);
7108 /* get the string representation of the name */
7109 l = aopGet (AOP (left), 0, FALSE, TRUE);
7110 size = AOP_SIZE (result);
7114 sprintf (buffer, "(%s + %d)", l + 1, offset);
7116 sprintf (buffer, "%s", l + 1);
7117 aopPut (AOP (result), buffer, offset++);
7120 freeAsmop (left, NULL, ic, TRUE);
7121 freeAsmop (result, NULL, ic, TRUE);
7124 /*-----------------------------------------------------------------*/
7125 /* genNearPointerGet - emitcode for near pointer fetch */
7126 /*-----------------------------------------------------------------*/
7128 genNearPointerGet (operand * left,
7136 sym_link *rtype, *retype;
7137 sym_link *ltype = operandType (left);
7140 D(emitcode (";", "genNearPointerGet"));
7142 rtype = operandType (result);
7143 retype = getSpec (rtype);
7145 aopOp (left, ic, FALSE);
7147 /* if left is rematerialisable and
7148 result is not bit variable type and
7149 the left is pointer to data space i.e
7150 lower 128 bytes of space */
7151 if (AOP_TYPE (left) == AOP_IMMD &&
7152 !IS_BITVAR (retype) &&
7153 DCL_TYPE (ltype) == POINTER)
7155 genDataPointerGet (left, result, ic);
7159 /* if the value is already in a pointer register
7160 then don't need anything more */
7161 if (!AOP_INPREG (AOP (left)))
7163 /* otherwise get a free pointer register */
7165 preg = getFreePtr (ic, &aop, FALSE);
7166 emitcode ("mov", "%s,%s",
7168 aopGet (AOP (left), 0, FALSE, TRUE));
7172 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7174 //aopOp (result, ic, FALSE);
7175 aopOp (result, ic, result?TRUE:FALSE);
7177 /* if bitfield then unpack the bits */
7178 if (IS_BITVAR (retype))
7179 genUnpackBits (result, rname, POINTER);
7182 /* we have can just get the values */
7183 int size = AOP_SIZE (result);
7188 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7191 emitcode ("mov", "a,@%s", rname);
7192 aopPut (AOP (result), "a", offset);
7196 sprintf (buffer, "@%s", rname);
7197 aopPut (AOP (result), buffer, offset);
7201 emitcode ("inc", "%s", rname);
7205 /* now some housekeeping stuff */
7206 if (aop) /* we had to allocate for this iCode */
7208 if (pi) { /* post increment present */
7209 aopPut(AOP ( left ),rname,0);
7211 freeAsmop (NULL, aop, ic, TRUE);
7215 /* we did not allocate which means left
7216 already in a pointer register, then
7217 if size > 0 && this could be used again
7218 we have to point it back to where it
7220 if ((AOP_SIZE (result) > 1 &&
7221 !OP_SYMBOL (left)->remat &&
7222 (OP_SYMBOL (left)->liveTo > ic->seq ||
7226 int size = AOP_SIZE (result) - 1;
7228 emitcode ("dec", "%s", rname);
7233 freeAsmop (left, NULL, ic, TRUE);
7234 freeAsmop (result, NULL, ic, TRUE);
7235 if (pi) pi->generated = 1;
7238 /*-----------------------------------------------------------------*/
7239 /* genPagedPointerGet - emitcode for paged pointer fetch */
7240 /*-----------------------------------------------------------------*/
7242 genPagedPointerGet (operand * left,
7250 sym_link *rtype, *retype;
7252 D(emitcode (";", "genPagedPointerGet"));
7254 rtype = operandType (result);
7255 retype = getSpec (rtype);
7257 aopOp (left, ic, FALSE);
7259 /* if the value is already in a pointer register
7260 then don't need anything more */
7261 if (!AOP_INPREG (AOP (left)))
7263 /* otherwise get a free pointer register */
7265 preg = getFreePtr (ic, &aop, FALSE);
7266 emitcode ("mov", "%s,%s",
7268 aopGet (AOP (left), 0, FALSE, TRUE));
7272 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7274 aopOp (result, ic, FALSE);
7276 /* if bitfield then unpack the bits */
7277 if (IS_BITVAR (retype))
7278 genUnpackBits (result, rname, PPOINTER);
7281 /* we have can just get the values */
7282 int size = AOP_SIZE (result);
7288 emitcode ("movx", "a,@%s", rname);
7289 aopPut (AOP (result), "a", offset);
7294 emitcode ("inc", "%s", rname);
7298 /* now some housekeeping stuff */
7299 if (aop) /* we had to allocate for this iCode */
7301 if (pi) aopPut ( AOP (left), rname, 0);
7302 freeAsmop (NULL, aop, ic, TRUE);
7306 /* we did not allocate which means left
7307 already in a pointer register, then
7308 if size > 0 && this could be used again
7309 we have to point it back to where it
7311 if ((AOP_SIZE (result) > 1 &&
7312 !OP_SYMBOL (left)->remat &&
7313 (OP_SYMBOL (left)->liveTo > ic->seq ||
7317 int size = AOP_SIZE (result) - 1;
7319 emitcode ("dec", "%s", rname);
7324 freeAsmop (left, NULL, ic, TRUE);
7325 freeAsmop (result, NULL, ic, TRUE);
7326 if (pi) pi->generated = 1;
7330 /*-----------------------------------------------------------------*/
7331 /* genFarPointerGet - gget value from far space */
7332 /*-----------------------------------------------------------------*/
7334 genFarPointerGet (operand * left,
7335 operand * result, iCode * ic, iCode * pi)
7338 sym_link *retype = getSpec (operandType (result));
7340 D(emitcode (";", "genFarPointerGet"));
7342 aopOp (left, ic, FALSE);
7344 /* if the operand is already in dptr
7345 then we do nothing else we move the value to dptr */
7346 if (AOP_TYPE (left) != AOP_STR)
7348 /* if this is remateriazable */
7349 if (AOP_TYPE (left) == AOP_IMMD)
7350 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7352 { /* we need to get it byte by byte */
7353 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7354 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7357 /* so dptr know contains the address */
7358 aopOp (result, ic, FALSE);
7360 /* if bit then unpack */
7361 if (IS_BITVAR (retype))
7362 genUnpackBits (result, "dptr", FPOINTER);
7365 size = AOP_SIZE (result);
7370 emitcode ("movx", "a,@dptr");
7371 aopPut (AOP (result), "a", offset++);
7373 emitcode ("inc", "dptr");
7377 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7378 aopPut ( AOP (left), "dpl", 0);
7379 aopPut ( AOP (left), "dph", 1);
7382 freeAsmop (left, NULL, ic, TRUE);
7383 freeAsmop (result, NULL, ic, TRUE);
7386 /*-----------------------------------------------------------------*/
7387 /* genCodePointerGet - gget value from code space */
7388 /*-----------------------------------------------------------------*/
7390 genCodePointerGet (operand * left,
7391 operand * result, iCode * ic, iCode *pi)
7394 sym_link *retype = getSpec (operandType (result));
7396 D(emitcode (";", "genCodePointerGet"));
7398 aopOp (left, ic, FALSE);
7400 /* if the operand is already in dptr
7401 then we do nothing else we move the value to dptr */
7402 if (AOP_TYPE (left) != AOP_STR)
7404 /* if this is remateriazable */
7405 if (AOP_TYPE (left) == AOP_IMMD)
7406 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7408 { /* we need to get it byte by byte */
7409 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7410 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7413 /* so dptr know contains the address */
7414 aopOp (result, ic, FALSE);
7416 /* if bit then unpack */
7417 if (IS_BITVAR (retype))
7418 genUnpackBits (result, "dptr", CPOINTER);
7421 size = AOP_SIZE (result);
7426 emitcode ("clr", "a");
7427 emitcode ("movc", "a,@a+dptr");
7428 aopPut (AOP (result), "a", offset++);
7430 emitcode ("inc", "dptr");
7434 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7435 aopPut ( AOP (left), "dpl", 0);
7436 aopPut ( AOP (left), "dph", 1);
7439 freeAsmop (left, NULL, ic, TRUE);
7440 freeAsmop (result, NULL, ic, TRUE);
7443 /*-----------------------------------------------------------------*/
7444 /* genGenPointerGet - gget value from generic pointer space */
7445 /*-----------------------------------------------------------------*/
7447 genGenPointerGet (operand * left,
7448 operand * result, iCode * ic, iCode *pi)
7451 sym_link *retype = getSpec (operandType (result));
7453 D(emitcode (";", "genGenPointerGet"));
7455 aopOp (left, ic, FALSE);
7457 /* if the operand is already in dptr
7458 then we do nothing else we move the value to dptr */
7459 if (AOP_TYPE (left) != AOP_STR)
7461 /* if this is remateriazable */
7462 if (AOP_TYPE (left) == AOP_IMMD)
7464 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7465 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7466 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7468 emitcode ("mov", "b,#%d", pointerCode (retype));
7471 { /* we need to get it byte by byte */
7472 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7473 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7474 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7477 /* so dptr know contains the address */
7478 aopOp (result, ic, FALSE);
7480 /* if bit then unpack */
7481 if (IS_BITVAR (retype))
7482 genUnpackBits (result, "dptr", GPOINTER);
7485 size = AOP_SIZE (result);
7490 emitcode ("lcall", "__gptrget");
7491 aopPut (AOP (result), "a", offset++);
7493 emitcode ("inc", "dptr");
7497 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7498 aopPut ( AOP (left), "dpl", 0);
7499 aopPut ( AOP (left), "dph", 1);
7500 aopPut ( AOP (left), "b", 2);
7503 freeAsmop (left, NULL, ic, TRUE);
7504 freeAsmop (result, NULL, ic, TRUE);
7507 /*-----------------------------------------------------------------*/
7508 /* genPointerGet - generate code for pointer get */
7509 /*-----------------------------------------------------------------*/
7511 genPointerGet (iCode * ic, iCode *pi)
7513 operand *left, *result;
7514 sym_link *type, *etype;
7517 D(emitcode (";", "genPointerGet"));
7519 left = IC_LEFT (ic);
7520 result = IC_RESULT (ic);
7522 /* depending on the type of pointer we need to
7523 move it to the correct pointer register */
7524 type = operandType (left);
7525 etype = getSpec (type);
7526 /* if left is of type of pointer then it is simple */
7527 if (IS_PTR (type) && !IS_FUNC (type->next))
7528 p_type = DCL_TYPE (type);
7531 /* we have to go by the storage class */
7532 p_type = PTR_TYPE (SPEC_OCLS (etype));
7535 /* special case when cast remat */
7536 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7537 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7538 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7539 type = type = operandType (left);
7540 p_type = DCL_TYPE (type);
7542 /* now that we have the pointer type we assign
7543 the pointer values */
7549 genNearPointerGet (left, result, ic, pi);
7553 genPagedPointerGet (left, result, ic, pi);
7557 genFarPointerGet (left, result, ic, pi);
7561 genCodePointerGet (left, result, ic, pi);
7565 genGenPointerGet (left, result, ic, pi);
7571 /*-----------------------------------------------------------------*/
7572 /* genPackBits - generates code for packed bit storage */
7573 /*-----------------------------------------------------------------*/
7575 genPackBits (sym_link * etype,
7577 char *rname, int p_type)
7585 D(emitcode (";", "genPackBits"));
7587 blen = SPEC_BLEN (etype);
7588 bstr = SPEC_BSTR (etype);
7590 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7593 /* if the bit lenth is less than or */
7594 /* it exactly fits a byte then */
7595 if (SPEC_BLEN (etype) <= 8)
7597 shCount = SPEC_BSTR (etype);
7599 /* shift left acc */
7602 if (SPEC_BLEN (etype) < 8)
7603 { /* if smaller than a byte */
7609 emitcode ("mov", "b,a");
7610 emitcode ("mov", "a,@%s", rname);
7614 emitcode ("mov", "b,a");
7615 emitcode ("movx", "a,@dptr");
7619 emitcode ("push", "b");
7620 emitcode ("push", "acc");
7621 emitcode ("lcall", "__gptrget");
7622 emitcode ("pop", "b");
7626 emitcode ("anl", "a,#0x%02x", (unsigned char)
7627 ((unsigned char) (0xFF << (blen + bstr)) |
7628 (unsigned char) (0xFF >> (8 - bstr))));
7629 emitcode ("orl", "a,b");
7630 if (p_type == GPOINTER)
7631 emitcode ("pop", "b");
7638 emitcode ("mov", "@%s,a", rname);
7642 emitcode ("movx", "@dptr,a");
7646 emitcode ("lcall", "__gptrput");
7651 if (SPEC_BLEN (etype) <= 8)
7654 emitcode ("inc", "%s", rname);
7655 rLen = SPEC_BLEN (etype);
7657 /* now generate for lengths greater than one byte */
7661 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7673 emitcode ("mov", "@%s,a", rname);
7676 emitcode ("mov", "@%s,%s", rname, l);
7681 emitcode ("movx", "@dptr,a");
7686 emitcode ("lcall", "__gptrput");
7689 emitcode ("inc", "%s", rname);
7694 /* last last was not complete */
7697 /* save the byte & read byte */
7701 emitcode ("mov", "b,a");
7702 emitcode ("mov", "a,@%s", rname);
7706 emitcode ("mov", "b,a");
7707 emitcode ("movx", "a,@dptr");
7711 emitcode ("push", "b");
7712 emitcode ("push", "acc");
7713 emitcode ("lcall", "__gptrget");
7714 emitcode ("pop", "b");
7718 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7719 emitcode ("orl", "a,b");
7722 if (p_type == GPOINTER)
7723 emitcode ("pop", "b");
7729 emitcode ("mov", "@%s,a", rname);
7733 emitcode ("movx", "@dptr,a");
7737 emitcode ("lcall", "__gptrput");
7741 /*-----------------------------------------------------------------*/
7742 /* genDataPointerSet - remat pointer to data space */
7743 /*-----------------------------------------------------------------*/
7745 genDataPointerSet (operand * right,
7749 int size, offset = 0;
7750 char *l, buffer[256];
7752 D(emitcode (";", "genDataPointerSet"));
7754 aopOp (right, ic, FALSE);
7756 l = aopGet (AOP (result), 0, FALSE, TRUE);
7757 size = AOP_SIZE (right);
7761 sprintf (buffer, "(%s + %d)", l + 1, offset);
7763 sprintf (buffer, "%s", l + 1);
7764 emitcode ("mov", "%s,%s", buffer,
7765 aopGet (AOP (right), offset++, FALSE, FALSE));
7768 freeAsmop (right, NULL, ic, TRUE);
7769 freeAsmop (result, NULL, ic, TRUE);
7772 /*-----------------------------------------------------------------*/
7773 /* genNearPointerSet - emitcode for near pointer put */
7774 /*-----------------------------------------------------------------*/
7776 genNearPointerSet (operand * right,
7784 sym_link *retype, *letype;
7785 sym_link *ptype = operandType (result);
7787 D(emitcode (";", "genNearPointerSet"));
7789 retype = getSpec (operandType (right));
7790 letype = getSpec (ptype);
7791 aopOp (result, ic, FALSE);
7793 /* if the result is rematerializable &
7794 in data space & not a bit variable */
7795 if (AOP_TYPE (result) == AOP_IMMD &&
7796 DCL_TYPE (ptype) == POINTER &&
7797 !IS_BITVAR (retype) &&
7798 !IS_BITVAR (letype))
7800 genDataPointerSet (right, result, ic);
7804 /* if the value is already in a pointer register
7805 then don't need anything more */
7806 if (!AOP_INPREG (AOP (result)))
7809 //AOP_TYPE (result) == AOP_STK
7813 // Aha, it is a pointer, just in disguise.
7814 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7817 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7818 __FILE__, __LINE__);
7823 rname++; // skip the '@'.
7828 /* otherwise get a free pointer register */
7830 preg = getFreePtr (ic, &aop, FALSE);
7831 emitcode ("mov", "%s,%s",
7833 aopGet (AOP (result), 0, FALSE, TRUE));
7839 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7842 aopOp (right, ic, FALSE);
7844 /* if bitfield then unpack the bits */
7845 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7846 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7849 /* we have can just get the values */
7850 int size = AOP_SIZE (right);
7855 l = aopGet (AOP (right), offset, FALSE, TRUE);
7859 emitcode ("mov", "@%s,a", rname);
7862 emitcode ("mov", "@%s,%s", rname, l);
7864 emitcode ("inc", "%s", rname);
7869 /* now some housekeeping stuff */
7870 if (aop) /* we had to allocate for this iCode */
7872 if (pi) aopPut (AOP (result),rname,0);
7873 freeAsmop (NULL, aop, ic, TRUE);
7877 /* we did not allocate which means left
7878 already in a pointer register, then
7879 if size > 0 && this could be used again
7880 we have to point it back to where it
7882 if ((AOP_SIZE (right) > 1 &&
7883 !OP_SYMBOL (result)->remat &&
7884 (OP_SYMBOL (result)->liveTo > ic->seq ||
7888 int size = AOP_SIZE (right) - 1;
7890 emitcode ("dec", "%s", rname);
7895 if (pi) pi->generated = 1;
7896 freeAsmop (result, NULL, ic, TRUE);
7897 freeAsmop (right, NULL, ic, TRUE);
7900 /*-----------------------------------------------------------------*/
7901 /* genPagedPointerSet - emitcode for Paged pointer put */
7902 /*-----------------------------------------------------------------*/
7904 genPagedPointerSet (operand * right,
7912 sym_link *retype, *letype;
7914 D(emitcode (";", "genPagedPointerSet"));
7916 retype = getSpec (operandType (right));
7917 letype = getSpec (operandType (result));
7919 aopOp (result, ic, FALSE);
7921 /* if the value is already in a pointer register
7922 then don't need anything more */
7923 if (!AOP_INPREG (AOP (result)))
7925 /* otherwise get a free pointer register */
7927 preg = getFreePtr (ic, &aop, FALSE);
7928 emitcode ("mov", "%s,%s",
7930 aopGet (AOP (result), 0, FALSE, TRUE));
7934 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7936 aopOp (right, ic, FALSE);
7938 /* if bitfield then unpack the bits */
7939 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7940 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7943 /* we have can just get the values */
7944 int size = AOP_SIZE (right);
7949 l = aopGet (AOP (right), offset, FALSE, TRUE);
7952 emitcode ("movx", "@%s,a", rname);
7955 emitcode ("inc", "%s", rname);
7961 /* now some housekeeping stuff */
7962 if (aop) /* we had to allocate for this iCode */
7964 if (pi) aopPut (AOP (result),rname,0);
7965 freeAsmop (NULL, aop, ic, TRUE);
7969 /* we did not allocate which means left
7970 already in a pointer register, then
7971 if size > 0 && this could be used again
7972 we have to point it back to where it
7974 if (AOP_SIZE (right) > 1 &&
7975 !OP_SYMBOL (result)->remat &&
7976 (OP_SYMBOL (result)->liveTo > ic->seq ||
7979 int size = AOP_SIZE (right) - 1;
7981 emitcode ("dec", "%s", rname);
7986 if (pi) pi->generated = 1;
7987 freeAsmop (result, NULL, ic, TRUE);
7988 freeAsmop (right, NULL, ic, TRUE);
7993 /*-----------------------------------------------------------------*/
7994 /* genFarPointerSet - set value from far space */
7995 /*-----------------------------------------------------------------*/
7997 genFarPointerSet (operand * right,
7998 operand * result, iCode * ic, iCode * pi)
8001 sym_link *retype = getSpec (operandType (right));
8002 sym_link *letype = getSpec (operandType (result));
8004 D(emitcode (";", "genFarPointerSet"));
8006 aopOp (result, ic, FALSE);
8008 /* if the operand is already in dptr
8009 then we do nothing else we move the value to dptr */
8010 if (AOP_TYPE (result) != AOP_STR)
8012 /* if this is remateriazable */
8013 if (AOP_TYPE (result) == AOP_IMMD)
8014 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8016 { /* we need to get it byte by byte */
8017 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8018 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8021 /* so dptr know contains the address */
8022 aopOp (right, ic, FALSE);
8024 /* if bit then unpack */
8025 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8026 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8029 size = AOP_SIZE (right);
8034 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8036 emitcode ("movx", "@dptr,a");
8038 emitcode ("inc", "dptr");
8041 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8042 aopPut (AOP(result),"dpl",0);
8043 aopPut (AOP(result),"dph",1);
8046 freeAsmop (result, NULL, ic, TRUE);
8047 freeAsmop (right, NULL, ic, TRUE);
8050 /*-----------------------------------------------------------------*/
8051 /* genGenPointerSet - set value from generic pointer space */
8052 /*-----------------------------------------------------------------*/
8054 genGenPointerSet (operand * right,
8055 operand * result, iCode * ic, iCode * pi)
8058 sym_link *retype = getSpec (operandType (right));
8059 sym_link *letype = getSpec (operandType (result));
8061 D(emitcode (";", "genGenPointerSet"));
8063 aopOp (result, ic, FALSE);
8065 /* if the operand is already in dptr
8066 then we do nothing else we move the value to dptr */
8067 if (AOP_TYPE (result) != AOP_STR)
8069 /* if this is remateriazable */
8070 if (AOP_TYPE (result) == AOP_IMMD)
8072 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8073 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8074 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8076 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8079 { /* we need to get it byte by byte */
8080 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8081 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8082 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8085 /* so dptr know contains the address */
8086 aopOp (right, ic, FALSE);
8088 /* if bit then unpack */
8089 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8090 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8093 size = AOP_SIZE (right);
8098 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8100 emitcode ("lcall", "__gptrput");
8102 emitcode ("inc", "dptr");
8106 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8107 aopPut (AOP(result),"dpl",0);
8108 aopPut (AOP(result),"dph",1);
8109 aopPut (AOP(result),"b",2);
8112 freeAsmop (result, NULL, ic, TRUE);
8113 freeAsmop (right, NULL, ic, TRUE);
8116 /*-----------------------------------------------------------------*/
8117 /* genPointerSet - stores the value into a pointer location */
8118 /*-----------------------------------------------------------------*/
8120 genPointerSet (iCode * ic, iCode *pi)
8122 operand *right, *result;
8123 sym_link *type, *etype;
8126 D(emitcode (";", "genPointerSet"));
8128 right = IC_RIGHT (ic);
8129 result = IC_RESULT (ic);
8131 /* depending on the type of pointer we need to
8132 move it to the correct pointer register */
8133 type = operandType (result);
8134 etype = getSpec (type);
8135 /* if left is of type of pointer then it is simple */
8136 if (IS_PTR (type) && !IS_FUNC (type->next))
8138 p_type = DCL_TYPE (type);
8142 /* we have to go by the storage class */
8143 p_type = PTR_TYPE (SPEC_OCLS (etype));
8146 /* special case when cast remat */
8147 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8148 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8149 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8150 type = type = operandType (result);
8151 p_type = DCL_TYPE (type);
8153 /* now that we have the pointer type we assign
8154 the pointer values */
8160 genNearPointerSet (right, result, ic, pi);
8164 genPagedPointerSet (right, result, ic, pi);
8168 genFarPointerSet (right, result, ic, pi);
8172 genGenPointerSet (right, result, ic, pi);
8178 /*-----------------------------------------------------------------*/
8179 /* genIfx - generate code for Ifx statement */
8180 /*-----------------------------------------------------------------*/
8182 genIfx (iCode * ic, iCode * popIc)
8184 operand *cond = IC_COND (ic);
8187 D(emitcode (";", "genIfx"));
8189 aopOp (cond, ic, FALSE);
8191 /* get the value into acc */
8192 if (AOP_TYPE (cond) != AOP_CRY)
8196 /* the result is now in the accumulator */
8197 freeAsmop (cond, NULL, ic, TRUE);
8199 /* if there was something to be popped then do it */
8203 /* if the condition is a bit variable */
8204 if (isbit && IS_ITEMP (cond) &&
8206 genIfxJump (ic, SPIL_LOC (cond)->rname);
8207 else if (isbit && !IS_ITEMP (cond))
8208 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8210 genIfxJump (ic, "a");
8215 /*-----------------------------------------------------------------*/
8216 /* genAddrOf - generates code for address of */
8217 /*-----------------------------------------------------------------*/
8219 genAddrOf (iCode * ic)
8221 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8224 D(emitcode (";", "genAddrOf"));
8226 aopOp (IC_RESULT (ic), ic, FALSE);
8228 /* if the operand is on the stack then we
8229 need to get the stack offset of this
8233 /* if it has an offset then we need to compute
8237 emitcode ("mov", "a,_bp");
8238 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8239 ((char) (sym->stack - _G.nRegsSaved)) :
8240 ((char) sym->stack)) & 0xff);
8241 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8245 /* we can just move _bp */
8246 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8248 /* fill the result with zero */
8249 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8254 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8260 /* object not on stack then we need the name */
8261 size = AOP_SIZE (IC_RESULT (ic));
8266 char s[SDCC_NAME_MAX];
8268 sprintf (s, "#(%s >> %d)",
8272 sprintf (s, "#%s", sym->rname);
8273 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8277 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8281 /*-----------------------------------------------------------------*/
8282 /* genFarFarAssign - assignment when both are in far space */
8283 /*-----------------------------------------------------------------*/
8285 genFarFarAssign (operand * result, operand * right, iCode * ic)
8287 int size = AOP_SIZE (right);
8291 D(emitcode (";", "genFarFarAssign"));
8293 /* first push the right side on to the stack */
8296 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8298 emitcode ("push", "acc");
8301 freeAsmop (right, NULL, ic, FALSE);
8302 /* now assign DPTR to result */
8303 aopOp (result, ic, FALSE);
8304 size = AOP_SIZE (result);
8307 emitcode ("pop", "acc");
8308 aopPut (AOP (result), "a", --offset);
8310 freeAsmop (result, NULL, ic, FALSE);
8314 /*-----------------------------------------------------------------*/
8315 /* genAssign - generate code for assignment */
8316 /*-----------------------------------------------------------------*/
8318 genAssign (iCode * ic)
8320 operand *result, *right;
8322 unsigned long lit = 0L;
8324 D(emitcode(";","genAssign"));
8326 result = IC_RESULT (ic);
8327 right = IC_RIGHT (ic);
8329 /* if they are the same */
8330 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8333 aopOp (right, ic, FALSE);
8335 /* special case both in far space */
8336 if (AOP_TYPE (right) == AOP_DPTR &&
8337 IS_TRUE_SYMOP (result) &&
8338 isOperandInFarSpace (result))
8341 genFarFarAssign (result, right, ic);
8345 aopOp (result, ic, TRUE);
8347 /* if they are the same registers */
8348 if (sameRegs (AOP (right), AOP (result)))
8351 /* if the result is a bit */
8352 if (AOP_TYPE (result) == AOP_CRY)
8355 /* if the right size is a literal then
8356 we know what the value is */
8357 if (AOP_TYPE (right) == AOP_LIT)
8359 if (((int) operandLitValue (right)))
8360 aopPut (AOP (result), one, 0);
8362 aopPut (AOP (result), zero, 0);
8366 /* the right is also a bit variable */
8367 if (AOP_TYPE (right) == AOP_CRY)
8369 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8370 aopPut (AOP (result), "c", 0);
8376 aopPut (AOP (result), "a", 0);
8380 /* bit variables done */
8382 size = AOP_SIZE (result);
8384 if (AOP_TYPE (right) == AOP_LIT)
8385 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8387 (AOP_TYPE (result) != AOP_REG) &&
8388 (AOP_TYPE (right) == AOP_LIT) &&
8389 !IS_FLOAT (operandType (right)) &&
8392 emitcode ("clr", "a");
8395 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8396 aopPut (AOP (result), "a", size);
8398 aopPut (AOP (result),
8399 aopGet (AOP (right), size, FALSE, FALSE),
8407 aopPut (AOP (result),
8408 aopGet (AOP (right), offset, FALSE, FALSE),
8415 freeAsmop (right, NULL, ic, TRUE);
8416 freeAsmop (result, NULL, ic, TRUE);
8419 /*-----------------------------------------------------------------*/
8420 /* genJumpTab - genrates code for jump table */
8421 /*-----------------------------------------------------------------*/
8423 genJumpTab (iCode * ic)
8428 D(emitcode (";", "genJumpTab"));
8430 aopOp (IC_JTCOND (ic), ic, FALSE);
8431 /* get the condition into accumulator */
8432 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8434 /* multiply by three */
8435 emitcode ("add", "a,acc");
8436 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8437 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8439 jtab = newiTempLabel (NULL);
8440 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8441 emitcode ("jmp", "@a+dptr");
8442 emitcode ("", "%05d$:", jtab->key + 100);
8443 /* now generate the jump labels */
8444 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8445 jtab = setNextItem (IC_JTLABELS (ic)))
8446 emitcode ("ljmp", "%05d$", jtab->key + 100);
8450 /*-----------------------------------------------------------------*/
8451 /* genCast - gen code for casting */
8452 /*-----------------------------------------------------------------*/
8454 genCast (iCode * ic)
8456 operand *result = IC_RESULT (ic);
8457 sym_link *ctype = operandType (IC_LEFT (ic));
8458 sym_link *rtype = operandType (IC_RIGHT (ic));
8459 operand *right = IC_RIGHT (ic);
8462 D(emitcode(";", "genCast"));
8464 /* if they are equivalent then do nothing */
8465 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8468 aopOp (right, ic, FALSE);
8469 aopOp (result, ic, FALSE);
8471 /* if the result is a bit */
8472 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8473 if (IS_BITVAR(OP_SYMBOL(result)->type))
8475 /* if the right size is a literal then
8476 we know what the value is */
8477 if (AOP_TYPE (right) == AOP_LIT)
8479 if (((int) operandLitValue (right)))
8480 aopPut (AOP (result), one, 0);
8482 aopPut (AOP (result), zero, 0);
8487 /* the right is also a bit variable */
8488 if (AOP_TYPE (right) == AOP_CRY)
8490 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8491 aopPut (AOP (result), "c", 0);
8497 aopPut (AOP (result), "a", 0);
8501 /* if they are the same size : or less */
8502 if (AOP_SIZE (result) <= AOP_SIZE (right))
8505 /* if they are in the same place */
8506 if (sameRegs (AOP (right), AOP (result)))
8509 /* if they in different places then copy */
8510 size = AOP_SIZE (result);
8514 aopPut (AOP (result),
8515 aopGet (AOP (right), offset, FALSE, FALSE),
8523 /* if the result is of type pointer */
8528 sym_link *type = operandType (right);
8529 sym_link *etype = getSpec (type);
8531 /* pointer to generic pointer */
8532 if (IS_GENPTR (ctype))
8537 p_type = DCL_TYPE (type);
8540 if (SPEC_SCLS(etype)==S_REGISTER) {
8541 // let's assume it is a generic pointer
8544 /* we have to go by the storage class */
8545 p_type = PTR_TYPE (SPEC_OCLS (etype));
8549 /* the first two bytes are known */
8550 size = GPTRSIZE - 1;
8554 aopPut (AOP (result),
8555 aopGet (AOP (right), offset, FALSE, FALSE),
8559 /* the last byte depending on type */
8575 case PPOINTER: // what the fck is this?
8580 /* this should never happen */
8581 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8582 "got unknown pointer type");
8585 aopPut (AOP (result), l, GPTRSIZE - 1);
8589 /* just copy the pointers */
8590 size = AOP_SIZE (result);
8594 aopPut (AOP (result),
8595 aopGet (AOP (right), offset, FALSE, FALSE),
8602 /* so we now know that the size of destination is greater
8603 than the size of the source */
8604 /* we move to result for the size of source */
8605 size = AOP_SIZE (right);
8609 aopPut (AOP (result),
8610 aopGet (AOP (right), offset, FALSE, FALSE),
8615 /* now depending on the sign of the source && destination */
8616 size = AOP_SIZE (result) - AOP_SIZE (right);
8617 /* if unsigned or not an integral type */
8618 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8621 aopPut (AOP (result), zero, offset++);
8625 /* we need to extend the sign :{ */
8626 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8629 emitcode ("rlc", "a");
8630 emitcode ("subb", "a,acc");
8632 aopPut (AOP (result), "a", offset++);
8635 /* we are done hurray !!!! */
8638 freeAsmop (right, NULL, ic, TRUE);
8639 freeAsmop (result, NULL, ic, TRUE);
8643 /*-----------------------------------------------------------------*/
8644 /* genDjnz - generate decrement & jump if not zero instrucion */
8645 /*-----------------------------------------------------------------*/
8647 genDjnz (iCode * ic, iCode * ifx)
8653 D(emitcode (";", "genDjnz"));
8655 /* if the if condition has a false label
8656 then we cannot save */
8660 /* if the minus is not of the form
8662 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8663 !IS_OP_LITERAL (IC_RIGHT (ic)))
8666 if (operandLitValue (IC_RIGHT (ic)) != 1)
8669 /* if the size of this greater than one then no
8671 if (getSize (operandType (IC_RESULT (ic))) > 1)
8674 /* otherwise we can save BIG */
8675 lbl = newiTempLabel (NULL);
8676 lbl1 = newiTempLabel (NULL);
8678 aopOp (IC_RESULT (ic), ic, FALSE);
8680 if (AOP_NEEDSACC(IC_RESULT(ic)))
8682 /* If the result is accessed indirectly via
8683 * the accumulator, we must explicitly write
8684 * it back after the decrement.
8686 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8688 if (strcmp(rByte, "a"))
8690 /* Something is hopelessly wrong */
8691 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8692 __FILE__, __LINE__);
8693 /* We can just give up; the generated code will be inefficient,
8696 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8699 emitcode ("dec", "%s", rByte);
8700 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8701 emitcode ("jnz", "%05d$", lbl->key + 100);
8703 else if (IS_AOP_PREG (IC_RESULT (ic)))
8705 emitcode ("dec", "%s",
8706 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8707 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8708 emitcode ("jnz", "%05d$", lbl->key + 100);
8712 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8715 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8716 emitcode ("", "%05d$:", lbl->key + 100);
8717 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8718 emitcode ("", "%05d$:", lbl1->key + 100);
8720 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8725 /*-----------------------------------------------------------------*/
8726 /* genReceive - generate code for a receive iCode */
8727 /*-----------------------------------------------------------------*/
8729 genReceive (iCode * ic)
8731 D(emitcode (";", "genReceive"));
8733 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8734 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8735 IS_TRUE_SYMOP (IC_RESULT (ic))))
8738 int size = getSize (operandType (IC_RESULT (ic)));
8739 int offset = fReturnSizeMCS51 - size;
8742 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8743 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8746 aopOp (IC_RESULT (ic), ic, FALSE);
8747 size = AOP_SIZE (IC_RESULT (ic));
8751 emitcode ("pop", "acc");
8752 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8759 aopOp (IC_RESULT (ic), ic, FALSE);
8761 assignResultValue (IC_RESULT (ic));
8764 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8767 /*-----------------------------------------------------------------*/
8768 /* gen51Code - generate code for 8051 based controllers */
8769 /*-----------------------------------------------------------------*/
8771 gen51Code (iCode * lic)
8776 lineHead = lineCurr = NULL;
8778 /* print the allocation information */
8780 printAllocInfo (currFunc, codeOutFile);
8781 /* if debug information required */
8782 if (options.debug && currFunc)
8784 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8786 if (IS_STATIC (currFunc->etype))
8787 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8789 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8792 /* stack pointer name */
8793 if (options.useXstack)
8799 for (ic = lic; ic; ic = ic->next)
8802 if (cln != ic->lineno)
8807 emitcode ("", "C$%s$%d$%d$%d ==.",
8808 FileBaseName (ic->filename), ic->lineno,
8809 ic->level, ic->block);
8812 emitcode (";", "%s %d", ic->filename, ic->lineno);
8815 /* if the result is marked as
8816 spilt and rematerializable or code for
8817 this has already been generated then
8819 if (resultRemat (ic) || ic->generated)
8822 /* depending on the operation */
8842 /* IPOP happens only when trying to restore a
8843 spilt live range, if there is an ifx statement
8844 following this pop then the if statement might
8845 be using some of the registers being popped which
8846 would destory the contents of the register so
8847 we need to check for this condition and handle it */
8849 ic->next->op == IFX &&
8850 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8851 genIfx (ic->next, ic);
8869 genEndFunction (ic);
8889 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8906 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8910 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8917 /* note these two are xlated by algebraic equivalence
8918 during parsing SDCC.y */
8919 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8920 "got '>=' or '<=' shouldn't have come here");
8924 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8936 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8940 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8944 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8971 case GET_VALUE_AT_ADDRESS:
8972 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_LEFT(ic)))));
8976 if (POINTER_SET (ic))
8977 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9003 addSet (&_G.sendSet, ic);
9012 /* now we are ready to call the
9013 peep hole optimizer */
9014 if (!options.nopeep)
9015 peepHole (&lineHead);
9017 /* now do the actual printing */
9018 printLine (lineHead, codeOutFile);