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"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
79 static char *rb1regs[] = {
80 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
83 extern int mcs51_ptrRegReq;
84 extern int mcs51_nRegs;
85 extern FILE *codeOutFile;
86 static void saveRBank (int, iCode *, bool);
87 #define RESULTONSTACK(x) \
88 (IC_RESULT(x) && IC_RESULT(x)->aop && \
89 IC_RESULT(x)->aop->type == AOP_STK )
91 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
92 #define CLRC emitcode("clr","c")
93 #define SETC emitcode("setb","c")
95 static lineNode *lineHead = NULL;
96 static lineNode *lineCurr = NULL;
98 static unsigned char SLMask[] =
99 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
100 0xE0, 0xC0, 0x80, 0x00};
101 static unsigned char SRMask[] =
102 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00};
110 /*-----------------------------------------------------------------*/
111 /* emitcode - writes the code into a file : for now it is simple */
112 /*-----------------------------------------------------------------*/
114 emitcode (char *inst, const char *fmt,...)
117 char lb[INITIAL_INLINEASM];
125 sprintf (lb, "%s\t", inst);
127 sprintf (lb, "%s", inst);
128 vsprintf (lb + (strlen (lb)), fmt, ap);
131 vsprintf (lb, fmt, ap);
133 while (isspace (*lbp))
135 // printf ("%s\n", lb); // EEP - debugging
138 lineCurr = (lineCurr ?
139 connectLine (lineCurr, newLineNode (lb)) :
140 (lineHead = newLineNode (lb)));
141 lineCurr->isInline = _G.inLine;
142 lineCurr->isDebug = _G.debugLine;
146 /*-----------------------------------------------------------------*/
147 /* mova - moves specified value into accumulator */
148 /*-----------------------------------------------------------------*/
152 /* do some early peephole optimization */
153 if (!strcmp(x, "a") || !strcmp(x, "acc"))
156 emitcode("mov","a,%s", x);
159 /*-----------------------------------------------------------------*/
160 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
161 /*-----------------------------------------------------------------*/
163 getFreePtr (iCode * ic, asmop ** aopp, bool result)
165 bool r0iu = FALSE, r1iu = FALSE;
166 bool r0ou = FALSE, r1ou = FALSE;
168 /* the logic: if r0 & r1 used in the instruction
169 then we are in trouble otherwise */
171 /* first check if r0 & r1 are used by this
172 instruction, in which case we are in trouble */
173 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
174 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
179 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
180 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
182 /* if no usage of r0 then return it */
185 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
186 (*aopp)->type = AOP_R0;
188 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
191 /* if no usage of r1 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
195 (*aopp)->type = AOP_R1;
197 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
200 /* now we know they both have usage */
201 /* if r0 not used in this instruction */
204 /* push it if not already pushed */
207 emitcode ("push", "%s",
208 mcs51_regWithIdx (R0_IDX)->dname);
212 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
213 (*aopp)->type = AOP_R0;
215 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
218 /* if r1 not used then */
222 /* push it if not already pushed */
225 emitcode ("push", "%s",
226 mcs51_regWithIdx (R1_IDX)->dname);
230 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
231 (*aopp)->type = AOP_R1;
232 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world, but not quite end of world yet */
237 /* we can push it on the stack */
238 (*aopp)->type = AOP_STK;
241 /* in the case that result AND left AND right needs a pointer reg
242 we can safely use the result's */
243 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
244 (*aopp)->type = AOP_R0;
245 return mcs51_regWithIdx (R0_IDX);
247 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
248 (*aopp)->type = AOP_R1;
249 return mcs51_regWithIdx (R1_IDX);
253 /* now this is REALLY the end of the world */
254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255 "getFreePtr should never reach here");
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp */
261 /*-----------------------------------------------------------------*/
263 newAsmop (short type)
267 aop = Safe_calloc (1, sizeof (asmop));
272 /*-----------------------------------------------------------------*/
273 /* pointerCode - returns the code for a pointer type */
274 /*-----------------------------------------------------------------*/
276 pointerCode (sym_link * etype)
279 return PTR_TYPE (SPEC_OCLS (etype));
284 /*-----------------------------------------------------------------*/
285 /* leftRightUseAcc - returns size of accumulator use by operands */
286 /*-----------------------------------------------------------------*/
288 leftRightUseAcc(iCode *ic)
292 if (ic && IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))
293 && OP_SYMBOL (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->accuse)
294 accuse = (accuse < OP_SYMBOL (IC_LEFT (ic))->nRegs)
295 ? OP_SYMBOL (IC_LEFT (ic))->nRegs : accuse;
297 if (ic && IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))
298 && OP_SYMBOL (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic))->accuse)
299 accuse = (accuse < OP_SYMBOL (IC_RIGHT (ic))->nRegs)
300 ? OP_SYMBOL (IC_RIGHT (ic))->nRegs : accuse;
306 /*-----------------------------------------------------------------*/
307 /* aopForSym - for a true symbol */
308 /*-----------------------------------------------------------------*/
310 aopForSym (iCode * ic, symbol * sym, bool result)
315 wassertl (ic != NULL, "Got a null iCode");
316 wassertl (sym != NULL, "Got a null symbol");
318 space = SPEC_OCLS (sym->etype);
320 /* if already has one */
324 /* assign depending on the storage class */
325 /* if it is on the stack or indirectly addressable */
326 /* space we need to assign either r0 or r1 to it */
327 if (sym->onStack || sym->iaccess)
329 sym->aop = aop = newAsmop (0);
330 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
331 aop->size = getSize (sym->type);
333 /* now assign the address of the variable to
334 the pointer register */
335 if (aop->type != AOP_STK)
340 if (_G.accInUse || leftRightUseAcc (ic))
341 emitcode ("push", "acc");
343 emitcode ("mov", "a,_bp");
344 emitcode ("add", "a,#0x%02x",
346 ((char) (sym->stack - _G.nRegsSaved)) :
347 ((char) sym->stack)) & 0xff);
348 emitcode ("mov", "%s,a",
349 aop->aopu.aop_ptr->name);
351 if (_G.accInUse || leftRightUseAcc (ic))
352 emitcode ("pop", "acc");
355 emitcode ("mov", "%s,#%s",
356 aop->aopu.aop_ptr->name,
358 aop->paged = space->paged;
361 aop->aopu.aop_stk = sym->stack;
365 /* if in bit space */
366 if (IN_BITSPACE (space))
368 sym->aop = aop = newAsmop (AOP_CRY);
369 aop->aopu.aop_dir = sym->rname;
370 aop->size = getSize (sym->type);
373 /* if it is in direct space */
374 if (IN_DIRSPACE (space))
376 sym->aop = aop = newAsmop (AOP_DIR);
377 aop->aopu.aop_dir = sym->rname;
378 aop->size = getSize (sym->type);
382 /* special case for a function */
383 if (IS_FUNC (sym->type))
385 sym->aop = aop = newAsmop (AOP_IMMD);
386 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
387 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
388 aop->size = FPTRSIZE;
392 /* only remaining is far space */
393 /* in which case DPTR gets the address */
394 sym->aop = aop = newAsmop (AOP_DPTR);
395 emitcode ("mov", "dptr,#%s", sym->rname);
396 aop->size = getSize (sym->type);
398 /* if it is in code space */
399 if (IN_CODESPACE (space))
405 /*-----------------------------------------------------------------*/
406 /* aopForRemat - rematerialzes an object */
407 /*-----------------------------------------------------------------*/
409 aopForRemat (symbol * sym)
411 iCode *ic = sym->rematiCode;
412 asmop *aop = newAsmop (AOP_IMMD);
419 val += (int) operandLitValue (IC_RIGHT (ic));
420 else if (ic->op == '-')
421 val -= (int) operandLitValue (IC_RIGHT (ic));
422 else if (IS_CAST_ICODE(ic)) {
423 sym_link *from_type = operandType(IC_RIGHT(ic));
424 aop->aopu.aop_immd.from_cast_remat = 1;
425 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
426 ptr_type = DCL_TYPE(from_type);
427 if (ptr_type == IPOINTER) {
434 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
438 sprintf (buffer, "(%s %c 0x%04x)",
439 OP_SYMBOL (IC_LEFT (ic))->rname,
440 val >= 0 ? '+' : '-',
443 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
445 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
446 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
447 /* set immd2 field if required */
448 if (aop->aopu.aop_immd.from_cast_remat) {
449 sprintf(buffer,"#0x%02x",ptr_type);
450 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
451 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
457 /*-----------------------------------------------------------------*/
458 /* regsInCommon - two operands have some registers in common */
459 /*-----------------------------------------------------------------*/
461 regsInCommon (operand * op1, operand * op2)
466 /* if they have registers in common */
467 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
470 sym1 = OP_SYMBOL (op1);
471 sym2 = OP_SYMBOL (op2);
473 if (sym1->nRegs == 0 || sym2->nRegs == 0)
476 for (i = 0; i < sym1->nRegs; i++)
482 for (j = 0; j < sym2->nRegs; j++)
487 if (sym2->regs[j] == sym1->regs[i])
495 /*-----------------------------------------------------------------*/
496 /* operandsEqu - equivalent */
497 /*-----------------------------------------------------------------*/
499 operandsEqu (operand * op1, operand * op2)
503 /* if they not symbols */
504 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
507 sym1 = OP_SYMBOL (op1);
508 sym2 = OP_SYMBOL (op2);
510 /* if both are itemps & one is spilt
511 and the other is not then false */
512 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
513 sym1->isspilt != sym2->isspilt)
516 /* if they are the same */
520 if (strcmp (sym1->rname, sym2->rname) == 0)
524 /* if left is a tmp & right is not */
525 if (IS_ITEMP (op1) &&
528 (sym1->usl.spillLoc == sym2))
531 if (IS_ITEMP (op2) &&
535 (sym2->usl.spillLoc == sym1))
541 /*-----------------------------------------------------------------*/
542 /* sameRegs - two asmops have the same registers */
543 /*-----------------------------------------------------------------*/
545 sameRegs (asmop * aop1, asmop * aop2)
552 if (aop1->type != AOP_REG ||
553 aop2->type != AOP_REG)
556 if (aop1->size != aop2->size)
559 for (i = 0; i < aop1->size; i++)
560 if (aop1->aopu.aop_reg[i] !=
561 aop2->aopu.aop_reg[i])
567 /*-----------------------------------------------------------------*/
568 /* aopOp - allocates an asmop for an operand : */
569 /*-----------------------------------------------------------------*/
571 aopOp (operand * op, iCode * ic, bool result)
580 /* if this a literal */
581 if (IS_OP_LITERAL (op))
583 op->aop = aop = newAsmop (AOP_LIT);
584 aop->aopu.aop_lit = op->operand.valOperand;
585 aop->size = getSize (operandType (op));
589 /* if already has a asmop then continue */
593 /* if the underlying symbol has a aop */
594 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
596 op->aop = OP_SYMBOL (op)->aop;
600 /* if this is a true symbol */
601 if (IS_TRUE_SYMOP (op))
603 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
607 /* this is a temporary : this has
613 e) can be a return use only */
615 sym = OP_SYMBOL (op);
617 /* if the type is a conditional */
618 if (sym->regType == REG_CND)
620 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
625 /* if it is spilt then two situations
627 b) has a spill location */
628 if (sym->isspilt || sym->nRegs == 0)
631 /* rematerialize it NOW */
634 sym->aop = op->aop = aop =
636 aop->size = getSize (sym->type);
643 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
644 aop->size = getSize (sym->type);
645 for (i = 0; i < 2; i++)
646 aop->aopu.aop_str[i] = accUse[i];
654 aop = op->aop = sym->aop = newAsmop (AOP_STR);
655 aop->size = getSize (sym->type);
656 for (i = 0; i < fReturnSizeMCS51; i++)
657 aop->aopu.aop_str[i] = fReturn[i];
661 /* else spill location */
662 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
663 /* force a new aop if sizes differ */
664 sym->usl.spillLoc->aop = NULL;
666 sym->aop = op->aop = aop =
667 aopForSym (ic, sym->usl.spillLoc, result);
668 aop->size = getSize (sym->type);
672 /* must be in a register */
673 sym->aop = op->aop = aop = newAsmop (AOP_REG);
674 aop->size = sym->nRegs;
675 for (i = 0; i < sym->nRegs; i++)
676 aop->aopu.aop_reg[i] = sym->regs[i];
679 /*-----------------------------------------------------------------*/
680 /* freeAsmop - free up the asmop given to an operand */
681 /*----------------------------------------------------------------*/
683 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
700 /* depending on the asmop type only three cases need work AOP_RO
701 , AOP_R1 && AOP_STK */
709 emitcode ("pop", "ar0");
713 bitVectUnSetBit (ic->rUsed, R0_IDX);
721 emitcode ("pop", "ar1");
725 bitVectUnSetBit (ic->rUsed, R1_IDX);
731 int stk = aop->aopu.aop_stk + aop->size;
732 bitVectUnSetBit (ic->rUsed, R0_IDX);
733 bitVectUnSetBit (ic->rUsed, R1_IDX);
735 getFreePtr (ic, &aop, FALSE);
739 emitcode ("mov", "a,_bp");
740 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
741 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
745 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
750 emitcode ("pop", "acc");
751 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
754 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
757 freeAsmop (op, NULL, ic, TRUE);
760 emitcode ("pop", "ar0");
766 emitcode ("pop", "ar1");
773 /* all other cases just dealloc */
779 OP_SYMBOL (op)->aop = NULL;
780 /* if the symbol has a spill */
782 SPIL_LOC (op)->aop = NULL;
787 /*-----------------------------------------------------------------*/
788 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
789 /* clobber the accumulator */
790 /*-----------------------------------------------------------------*/
792 aopGetUsesAcc (asmop *aop, int offset)
794 if (offset > (aop->size - 1))
812 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
821 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
825 /* Error case --- will have been caught already */
832 /*-----------------------------------------------------------------*/
833 /* aopGet - for fetching value of the aop */
834 /*-----------------------------------------------------------------*/
836 aopGet (asmop * aop, int offset, bool bit16, bool dname)
841 /* offset is greater than
843 if (offset > (aop->size - 1) &&
844 aop->type != AOP_LIT)
847 /* depending on type */
853 /* if we need to increment it */
854 while (offset > aop->coff)
856 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
860 while (offset < aop->coff)
862 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
869 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
870 return (dname ? "acc" : "a");
872 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
873 rs = Safe_calloc (1, strlen (s) + 1);
878 if (aop->code && aop->coff==0 && offset>=1) {
879 emitcode ("mov", "a,#0x%02x", offset);
880 emitcode ("movc", "a,@a+dptr");
881 return (dname ? "acc" : "a");
884 while (offset > aop->coff)
886 emitcode ("inc", "dptr");
890 while (offset < aop->coff)
892 emitcode ("lcall", "__decdptr");
899 emitcode ("clr", "a");
900 emitcode ("movc", "a,@a+dptr");
904 emitcode ("movx", "a,@dptr");
906 return (dname ? "acc" : "a");
910 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
911 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
913 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
915 sprintf (s, "#(%s >> %d)",
916 aop->aopu.aop_immd.aop_immd1,
920 aop->aopu.aop_immd.aop_immd1);
921 rs = Safe_calloc (1, strlen (s) + 1);
927 sprintf (s, "(%s + %d)",
931 sprintf (s, "%s", aop->aopu.aop_dir);
932 rs = Safe_calloc (1, strlen (s) + 1);
938 return aop->aopu.aop_reg[offset]->dname;
940 return aop->aopu.aop_reg[offset]->name;
943 emitcode ("clr", "a");
944 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
945 emitcode ("rlc", "a");
946 return (dname ? "acc" : "a");
949 if (!offset && dname)
951 return aop->aopu.aop_str[offset];
954 return aopLiteral (aop->aopu.aop_lit, offset);
958 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
962 return aop->aopu.aop_str[offset];
966 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
967 "aopget got unsupported aop->type");
970 /*-----------------------------------------------------------------*/
971 /* aopPut - puts a string for a aop */
972 /*-----------------------------------------------------------------*/
974 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
978 if (aop->size && offset > (aop->size - 1))
980 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
981 "aopPut got offset > aop->size");
985 /* will assign value to value */
986 /* depending on where it is ofcourse */
991 sprintf (d, "(%s + %d)",
992 aop->aopu.aop_dir, offset);
994 sprintf (d, "%s", aop->aopu.aop_dir);
998 emitcode ("mov", "%s,%s", d, s);
1003 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1004 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1007 strcmp (s, "r0") == 0 ||
1008 strcmp (s, "r1") == 0 ||
1009 strcmp (s, "r2") == 0 ||
1010 strcmp (s, "r3") == 0 ||
1011 strcmp (s, "r4") == 0 ||
1012 strcmp (s, "r5") == 0 ||
1013 strcmp (s, "r6") == 0 ||
1014 strcmp (s, "r7") == 0)
1015 emitcode ("mov", "%s,%s",
1016 aop->aopu.aop_reg[offset]->dname, s);
1018 emitcode ("mov", "%s,%s",
1019 aop->aopu.aop_reg[offset]->name, s);
1026 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1027 "aopPut writing to code space");
1031 while (offset > aop->coff)
1034 emitcode ("inc", "dptr");
1037 while (offset < aop->coff)
1040 emitcode ("lcall", "__decdptr");
1045 /* if not in accumulater */
1048 emitcode ("movx", "@dptr,a");
1053 while (offset > aop->coff)
1056 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1058 while (offset < aop->coff)
1061 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1068 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1074 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1076 else if (strcmp (s, "r0") == 0 ||
1077 strcmp (s, "r1") == 0 ||
1078 strcmp (s, "r2") == 0 ||
1079 strcmp (s, "r3") == 0 ||
1080 strcmp (s, "r4") == 0 ||
1081 strcmp (s, "r5") == 0 ||
1082 strcmp (s, "r6") == 0 ||
1083 strcmp (s, "r7") == 0)
1086 sprintf (buffer, "a%s", s);
1087 emitcode ("mov", "@%s,%s",
1088 aop->aopu.aop_ptr->name, buffer);
1091 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1096 if (strcmp (s, "a") == 0)
1097 emitcode ("push", "acc");
1101 emitcode ("push", "acc");
1103 emitcode ("push", s);
1109 /* if bit variable */
1110 if (!aop->aopu.aop_dir)
1112 emitcode ("clr", "a");
1113 emitcode ("rlc", "a");
1118 emitcode ("clr", "%s", aop->aopu.aop_dir);
1120 emitcode ("setb", "%s", aop->aopu.aop_dir);
1121 else if (!strcmp (s, "c"))
1122 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1125 if (strcmp (s, "a"))
1130 /* set C, if a >= 1 */
1131 emitcode ("add", "a,#0xff");
1132 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1140 if (strcmp (aop->aopu.aop_str[offset], s) ||
1142 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1147 if (!offset && (strcmp (s, "acc") == 0) &&
1151 if (strcmp (aop->aopu.aop_str[offset], s) &&
1153 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1157 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1158 "aopPut got unsupported aop->type");
1166 /*-----------------------------------------------------------------*/
1167 /* pointToEnd :- points to the last byte of the operand */
1168 /*-----------------------------------------------------------------*/
1170 pointToEnd (asmop * aop)
1176 aop->coff = count = (aop->size - 1);
1182 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1186 emitcode ("inc", "dptr");
1193 /*-----------------------------------------------------------------*/
1194 /* reAdjustPreg - points a register back to where it should */
1195 /*-----------------------------------------------------------------*/
1197 reAdjustPreg (asmop * aop)
1199 if ((aop->coff==0) || aop->size <= 1)
1207 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1212 emitcode ("lcall", "__decdptr");
1219 #define AOP(op) op->aop
1220 #define AOP_TYPE(op) AOP(op)->type
1221 #define AOP_SIZE(op) AOP(op)->size
1222 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1223 AOP_TYPE(x) == AOP_R0))
1225 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1226 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1228 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1229 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1230 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1233 /*-----------------------------------------------------------------*/
1234 /* opIsGptr: returns non-zero if the passed operand is */
1235 /* a generic pointer type. */
1236 /*-----------------------------------------------------------------*/
1238 opIsGptr (operand * op)
1240 sym_link *type = operandType (op);
1242 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1249 /*-----------------------------------------------------------------*/
1250 /* getDataSize - get the operand data size */
1251 /*-----------------------------------------------------------------*/
1253 getDataSize (operand * op)
1256 size = AOP_SIZE (op);
1257 if (size == GPTRSIZE)
1259 sym_link *type = operandType (op);
1260 if (IS_GENPTR (type))
1262 /* generic pointer; arithmetic operations
1263 * should ignore the high byte (pointer type).
1271 /*-----------------------------------------------------------------*/
1272 /* outAcc - output Acc */
1273 /*-----------------------------------------------------------------*/
1275 outAcc (operand * result)
1278 size = getDataSize (result);
1281 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1284 /* unsigned or positive */
1287 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1292 /*-----------------------------------------------------------------*/
1293 /* outBitC - output a bit C */
1294 /*-----------------------------------------------------------------*/
1296 outBitC (operand * result)
1298 /* if the result is bit */
1299 if (AOP_TYPE (result) == AOP_CRY)
1300 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1303 emitcode ("clr", "a");
1304 emitcode ("rlc", "a");
1309 /*-----------------------------------------------------------------*/
1310 /* toBoolean - emit code for orl a,operator(sizeop) */
1311 /*-----------------------------------------------------------------*/
1313 toBoolean (operand * oper)
1315 int size = AOP_SIZE (oper) - 1;
1317 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1319 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1323 /*-----------------------------------------------------------------*/
1324 /* genNot - generate code for ! operation */
1325 /*-----------------------------------------------------------------*/
1331 D(emitcode ("; genNot",""));
1333 /* assign asmOps to operand & result */
1334 aopOp (IC_LEFT (ic), ic, FALSE);
1335 aopOp (IC_RESULT (ic), ic, TRUE);
1337 /* if in bit space then a special case */
1338 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1340 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1341 emitcode ("cpl", "c");
1342 outBitC (IC_RESULT (ic));
1346 toBoolean (IC_LEFT (ic));
1348 tlbl = newiTempLabel (NULL);
1349 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1350 emitcode ("", "%05d$:", tlbl->key + 100);
1351 outBitC (IC_RESULT (ic));
1354 /* release the aops */
1355 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1356 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1360 /*-----------------------------------------------------------------*/
1361 /* genCpl - generate code for complement */
1362 /*-----------------------------------------------------------------*/
1370 D(emitcode ("; genCpl",""));
1372 /* assign asmOps to operand & result */
1373 aopOp (IC_LEFT (ic), ic, FALSE);
1374 aopOp (IC_RESULT (ic), ic, TRUE);
1376 /* special case if in bit space */
1377 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1378 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1379 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1380 emitcode ("cpl", "c");
1381 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1384 tlbl=newiTempLabel(NULL);
1385 emitcode ("cjne", "%s,#0x01,%05d$",
1386 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1387 emitcode ("", "%05d$:", tlbl->key+100);
1388 outBitC (IC_RESULT(ic));
1392 size = AOP_SIZE (IC_RESULT (ic));
1395 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1397 emitcode ("cpl", "a");
1398 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1403 /* release the aops */
1404 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1405 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1408 /*-----------------------------------------------------------------*/
1409 /* genUminusFloat - unary minus for floating points */
1410 /*-----------------------------------------------------------------*/
1412 genUminusFloat (operand * op, operand * result)
1414 int size, offset = 0;
1417 D(emitcode ("; genUminusFloat",""));
1419 /* for this we just copy and then flip the bit */
1421 size = AOP_SIZE (op) - 1;
1425 aopPut (AOP (result),
1426 aopGet (AOP (op), offset, FALSE, FALSE),
1428 isOperandVolatile (result, FALSE));
1432 l = aopGet (AOP (op), offset, FALSE, FALSE);
1436 emitcode ("cpl", "acc.7");
1437 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1440 /*-----------------------------------------------------------------*/
1441 /* genUminus - unary minus code generation */
1442 /*-----------------------------------------------------------------*/
1444 genUminus (iCode * ic)
1447 sym_link *optype, *rtype;
1450 D(emitcode ("; genUminus",""));
1453 aopOp (IC_LEFT (ic), ic, FALSE);
1454 aopOp (IC_RESULT (ic), ic, TRUE);
1456 /* if both in bit space then special
1458 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1459 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1462 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1463 emitcode ("cpl", "c");
1464 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1468 optype = operandType (IC_LEFT (ic));
1469 rtype = operandType (IC_RESULT (ic));
1471 /* if float then do float stuff */
1472 if (IS_FLOAT (optype))
1474 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1478 /* otherwise subtract from zero */
1479 size = AOP_SIZE (IC_LEFT (ic));
1484 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1485 if (!strcmp (l, "a"))
1489 emitcode ("cpl", "a");
1490 emitcode ("addc", "a,#0");
1496 emitcode ("clr", "a");
1497 emitcode ("subb", "a,%s", l);
1499 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1502 /* if any remaining bytes in the result */
1503 /* we just need to propagate the sign */
1504 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1506 emitcode ("rlc", "a");
1507 emitcode ("subb", "a,acc");
1509 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1513 /* release the aops */
1514 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1515 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1518 /*-----------------------------------------------------------------*/
1519 /* saveRegisters - will look for a call and save the registers */
1520 /*-----------------------------------------------------------------*/
1522 saveRegisters (iCode * lic)
1529 for (ic = lic; ic; ic = ic->next)
1530 if (ic->op == CALL || ic->op == PCALL)
1535 fprintf (stderr, "found parameter push with no function call\n");
1539 /* if the registers have been saved already or don't need to be then
1543 if (IS_SYMOP(IC_LEFT(ic)) &&
1544 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1545 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1548 /* safe the registers in use at this time but skip the
1549 ones for the result */
1550 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1551 mcs51_rUmaskForOp (IC_RESULT(ic)));
1554 if (options.useXstack)
1556 if (bitVectBitValue (rsave, R0_IDX))
1557 emitcode ("mov", "b,r0");
1558 emitcode ("mov", "r0,%s", spname);
1559 for (i = 0; i < mcs51_nRegs; i++)
1561 if (bitVectBitValue (rsave, i))
1564 emitcode ("mov", "a,b");
1566 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1567 emitcode ("movx", "@r0,a");
1568 emitcode ("inc", "r0");
1571 emitcode ("mov", "%s,r0", spname);
1572 if (bitVectBitValue (rsave, R0_IDX))
1573 emitcode ("mov", "r0,b");
1576 for (i = 0; i < mcs51_nRegs; i++)
1578 if (bitVectBitValue (rsave, i))
1579 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1583 /*-----------------------------------------------------------------*/
1584 /* unsaveRegisters - pop the pushed registers */
1585 /*-----------------------------------------------------------------*/
1587 unsaveRegisters (iCode * ic)
1592 /* restore the registers in use at this time but skip the
1593 ones for the result */
1594 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1595 mcs51_rUmaskForOp (IC_RESULT(ic)));
1597 if (options.useXstack)
1599 emitcode ("mov", "r0,%s", spname);
1600 for (i = mcs51_nRegs; i >= 0; i--)
1602 if (bitVectBitValue (rsave, i))
1604 emitcode ("dec", "r0");
1605 emitcode ("movx", "a,@r0");
1607 emitcode ("mov", "b,a");
1609 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1613 emitcode ("mov", "%s,r0", spname);
1614 if (bitVectBitValue (rsave, R0_IDX))
1615 emitcode ("mov", "r0,b");
1618 for (i = mcs51_nRegs; i >= 0; i--)
1620 if (bitVectBitValue (rsave, i))
1621 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1627 /*-----------------------------------------------------------------*/
1629 /*-----------------------------------------------------------------*/
1631 pushSide (operand * oper, int size)
1636 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1637 if (AOP_TYPE (oper) != AOP_REG &&
1638 AOP_TYPE (oper) != AOP_DIR &&
1641 emitcode ("mov", "a,%s", l);
1642 emitcode ("push", "acc");
1645 emitcode ("push", "%s", l);
1649 /*-----------------------------------------------------------------*/
1650 /* assignResultValue - */
1651 /*-----------------------------------------------------------------*/
1653 assignResultValue (operand * oper)
1656 int size = AOP_SIZE (oper);
1659 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1665 /*-----------------------------------------------------------------*/
1666 /* genXpush - pushes onto the external stack */
1667 /*-----------------------------------------------------------------*/
1669 genXpush (iCode * ic)
1671 asmop *aop = newAsmop (0);
1673 int size, offset = 0;
1675 D(emitcode ("; genXpush",""));
1677 aopOp (IC_LEFT (ic), ic, FALSE);
1678 r = getFreePtr (ic, &aop, FALSE);
1681 emitcode ("mov", "%s,_spx", r->name);
1683 size = AOP_SIZE (IC_LEFT (ic));
1687 char *l = aopGet (AOP (IC_LEFT (ic)),
1688 offset++, FALSE, FALSE);
1690 emitcode ("movx", "@%s,a", r->name);
1691 emitcode ("inc", "%s", r->name);
1696 emitcode ("mov", "_spx,%s", r->name);
1698 freeAsmop (NULL, aop, ic, TRUE);
1699 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1702 /*-----------------------------------------------------------------*/
1703 /* genIpush - genrate code for pushing this gets a little complex */
1704 /*-----------------------------------------------------------------*/
1706 genIpush (iCode * ic)
1708 int size, offset = 0;
1711 D(emitcode ("; genIpush",""));
1713 /* if this is not a parm push : ie. it is spill push
1714 and spill push is always done on the local stack */
1718 /* and the item is spilt then do nothing */
1719 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1722 aopOp (IC_LEFT (ic), ic, FALSE);
1723 size = AOP_SIZE (IC_LEFT (ic));
1724 /* push it on the stack */
1727 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1733 emitcode ("push", "%s", l);
1738 /* this is a paramter push: in this case we call
1739 the routine to find the call and save those
1740 registers that need to be saved */
1743 /* if use external stack then call the external
1744 stack pushing routine */
1745 if (options.useXstack)
1751 /* then do the push */
1752 aopOp (IC_LEFT (ic), ic, FALSE);
1755 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1756 size = AOP_SIZE (IC_LEFT (ic));
1760 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1761 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1762 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1765 emitcode ("mov", "a,%s", l);
1766 emitcode ("push", "acc");
1769 emitcode ("push", "%s", l);
1772 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1775 /*-----------------------------------------------------------------*/
1776 /* genIpop - recover the registers: can happen only for spilling */
1777 /*-----------------------------------------------------------------*/
1779 genIpop (iCode * ic)
1783 D(emitcode ("; genIpop",""));
1785 /* if the temp was not pushed then */
1786 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1789 aopOp (IC_LEFT (ic), ic, FALSE);
1790 size = AOP_SIZE (IC_LEFT (ic));
1791 offset = (size - 1);
1793 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1799 /*-----------------------------------------------------------------*/
1800 /* unsaveRBank - restores the resgister bank from stack */
1801 /*-----------------------------------------------------------------*/
1803 unsaveRBank (int bank, iCode * ic, bool popPsw)
1809 if (options.useXstack)
1813 /* Assume r0 is available for use. */
1814 r = mcs51_regWithIdx (R0_IDX);;
1819 r = getFreePtr (ic, &aop, FALSE);
1821 emitcode ("mov", "%s,_spx", r->name);
1826 if (options.useXstack)
1828 emitcode ("movx", "a,@%s", r->name);
1829 emitcode ("mov", "psw,a");
1830 emitcode ("dec", "%s", r->name);
1834 emitcode ("pop", "psw");
1838 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1840 if (options.useXstack)
1842 emitcode ("movx", "a,@%s", r->name);
1843 emitcode ("mov", "(%s+%d),a",
1844 regs8051[i].base, 8 * bank + regs8051[i].offset);
1845 emitcode ("dec", "%s", r->name);
1849 emitcode ("pop", "(%s+%d)",
1850 regs8051[i].base, 8 * bank + regs8051[i].offset);
1853 if (options.useXstack)
1855 emitcode ("mov", "_spx,%s", r->name);
1860 freeAsmop (NULL, aop, ic, TRUE);
1864 /*-----------------------------------------------------------------*/
1865 /* saveRBank - saves an entire register bank on the stack */
1866 /*-----------------------------------------------------------------*/
1868 saveRBank (int bank, iCode * ic, bool pushPsw)
1874 if (options.useXstack)
1878 /* Assume r0 is available for use. */
1879 r = mcs51_regWithIdx (R0_IDX);;
1884 r = getFreePtr (ic, &aop, FALSE);
1886 emitcode ("mov", "%s,_spx", r->name);
1889 for (i = 0; i < mcs51_nRegs; i++)
1891 if (options.useXstack)
1893 emitcode ("inc", "%s", r->name);
1894 emitcode ("mov", "a,(%s+%d)",
1895 regs8051[i].base, 8 * bank + regs8051[i].offset);
1896 emitcode ("movx", "@%s,a", r->name);
1899 emitcode ("push", "(%s+%d)",
1900 regs8051[i].base, 8 * bank + regs8051[i].offset);
1905 if (options.useXstack)
1907 emitcode ("mov", "a,psw");
1908 emitcode ("movx", "@%s,a", r->name);
1909 emitcode ("inc", "%s", r->name);
1910 emitcode ("mov", "_spx,%s", r->name);
1915 emitcode ("push", "psw");
1918 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1923 freeAsmop (NULL, aop, ic, TRUE);
1932 /*-----------------------------------------------------------------*/
1933 /* genSend - gen code for SEND */
1934 /*-----------------------------------------------------------------*/
1935 static void genSend(set *sendSet)
1940 for (sic = setFirstItem (_G.sendSet); sic;
1941 sic = setNextItem (_G.sendSet)) {
1942 int size, offset = 0;
1943 aopOp (IC_LEFT (sic), sic, FALSE);
1944 size = AOP_SIZE (IC_LEFT (sic));
1946 if (sic->argreg == 1) {
1948 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1950 if (strcmp (l, fReturn[offset]))
1951 emitcode ("mov", "%s,%s", fReturn[offset], l);
1957 emitcode ("mov","b1_%d,%s",rb1_count++,
1958 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1961 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1965 /*-----------------------------------------------------------------*/
1966 /* genCall - generates a call statement */
1967 /*-----------------------------------------------------------------*/
1969 genCall (iCode * ic)
1972 // bool restoreBank = FALSE;
1973 bool swapBanks = FALSE;
1975 D(emitcode("; genCall",""));
1977 dtype = operandType (IC_LEFT (ic));
1978 /* if send set is not empty the assign */
1981 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1982 genSend(reverseSet(_G.sendSet));
1984 genSend(_G.sendSet);
1990 /* if we are calling a not _naked function that is not using
1991 the same register bank then we need to save the
1992 destination registers on the stack */
1993 dtype = operandType (IC_LEFT (ic));
1994 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1995 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1996 !IFFUNC_ISISR (dtype))
2001 /* if caller saves & we have not saved then */
2007 emitcode ("mov", "psw,#0x%02x",
2008 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2012 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2013 OP_SYMBOL (IC_LEFT (ic))->rname :
2014 OP_SYMBOL (IC_LEFT (ic))->name));
2018 emitcode ("mov", "psw,#0x%02x",
2019 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2022 /* if we need assign a result value */
2023 if ((IS_ITEMP (IC_RESULT (ic)) &&
2024 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2025 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2026 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2027 IS_TRUE_SYMOP (IC_RESULT (ic)))
2031 aopOp (IC_RESULT (ic), ic, FALSE);
2034 assignResultValue (IC_RESULT (ic));
2036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2039 /* adjust the stack for parameters if
2044 if (ic->parmBytes > 3)
2046 emitcode ("mov", "a,%s", spname);
2047 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2048 emitcode ("mov", "%s,a", spname);
2051 for (i = 0; i < ic->parmBytes; i++)
2052 emitcode ("dec", "%s", spname);
2055 /* if we hade saved some registers then unsave them */
2056 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2057 unsaveRegisters (ic);
2059 // /* if register bank was saved then pop them */
2061 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2064 /*-----------------------------------------------------------------*/
2065 /* -10l - generates a call by pointer statement */
2066 /*-----------------------------------------------------------------*/
2068 genPcall (iCode * ic)
2071 symbol *rlbl = newiTempLabel (NULL);
2072 // bool restoreBank=FALSE;
2073 bool swapBanks = FALSE;
2075 D(emitcode("; genPCall",""));
2077 /* if caller saves & we have not saved then */
2081 /* if we are calling a not _naked function that is not using
2082 the same register bank then we need to save the
2083 destination registers on the stack */
2084 dtype = operandType (IC_LEFT (ic))->next;
2085 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2086 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2087 !IFFUNC_ISISR (dtype))
2089 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2090 // restoreBank=TRUE;
2092 // need caution message to user here
2095 /* push the return address on to the stack */
2096 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2097 emitcode ("push", "acc");
2098 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2099 emitcode ("push", "acc");
2101 /* now push the calling address */
2102 aopOp (IC_LEFT (ic), ic, FALSE);
2104 pushSide (IC_LEFT (ic), FPTRSIZE);
2106 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2108 /* if send set is not empty the assign */
2111 genSend(reverseSet(_G.sendSet));
2117 emitcode ("mov", "psw,#0x%02x",
2118 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2122 emitcode ("ret", "");
2123 emitcode ("", "%05d$:", (rlbl->key + 100));
2128 emitcode ("mov", "psw,#0x%02x",
2129 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2132 /* if we need assign a result value */
2133 if ((IS_ITEMP (IC_RESULT (ic)) &&
2134 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2135 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2136 IS_TRUE_SYMOP (IC_RESULT (ic)))
2140 aopOp (IC_RESULT (ic), ic, FALSE);
2143 assignResultValue (IC_RESULT (ic));
2145 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2148 /* adjust the stack for parameters if
2153 if (ic->parmBytes > 3)
2155 emitcode ("mov", "a,%s", spname);
2156 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2157 emitcode ("mov", "%s,a", spname);
2160 for (i = 0; i < ic->parmBytes; i++)
2161 emitcode ("dec", "%s", spname);
2165 // /* if register bank was saved then unsave them */
2167 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2169 /* if we hade saved some registers then
2171 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2172 unsaveRegisters (ic);
2175 /*-----------------------------------------------------------------*/
2176 /* resultRemat - result is rematerializable */
2177 /*-----------------------------------------------------------------*/
2179 resultRemat (iCode * ic)
2181 if (SKIP_IC (ic) || ic->op == IFX)
2184 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2186 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2187 if (sym->remat && !POINTER_SET (ic))
2194 #if defined(__BORLANDC__) || defined(_MSC_VER)
2195 #define STRCASECMP stricmp
2197 #define STRCASECMP strcasecmp
2200 /*-----------------------------------------------------------------*/
2201 /* inExcludeList - return 1 if the string is in exclude Reg list */
2202 /*-----------------------------------------------------------------*/
2204 regsCmp(void *p1, void *p2)
2206 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2210 inExcludeList (char *s)
2212 const char *p = setFirstItem(options.excludeRegsSet);
2214 if (p == NULL || STRCASECMP(p, "none") == 0)
2218 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2221 /*-----------------------------------------------------------------*/
2222 /* genFunction - generated code for function entry */
2223 /*-----------------------------------------------------------------*/
2225 genFunction (iCode * ic)
2229 bool switchedPSW = FALSE;
2230 int calleesaves_saved_register = -1;
2233 /* create the function header */
2234 emitcode (";", "-----------------------------------------");
2235 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2236 emitcode (";", "-----------------------------------------");
2238 emitcode ("", "%s:", sym->rname);
2239 ftype = operandType (IC_LEFT (ic));
2241 if (IFFUNC_ISNAKED(ftype))
2243 emitcode(";", "naked function: no prologue.");
2247 /* if critical function then turn interrupts off */
2248 if (IFFUNC_ISCRITICAL (ftype))
2249 emitcode ("clr", "ea");
2251 /* here we need to generate the equates for the
2252 register bank if required */
2253 if (FUNC_REGBANK (ftype) != rbank)
2257 rbank = FUNC_REGBANK (ftype);
2258 for (i = 0; i < mcs51_nRegs; i++)
2260 if (strcmp (regs8051[i].base, "0") == 0)
2261 emitcode ("", "%s = 0x%02x",
2263 8 * rbank + regs8051[i].offset);
2265 emitcode ("", "%s = %s + 0x%02x",
2268 8 * rbank + regs8051[i].offset);
2272 /* if this is an interrupt service routine then
2273 save acc, b, dpl, dph */
2274 if (IFFUNC_ISISR (sym->type))
2277 if (!inExcludeList ("acc"))
2278 emitcode ("push", "acc");
2279 if (!inExcludeList ("b"))
2280 emitcode ("push", "b");
2281 if (!inExcludeList ("dpl"))
2282 emitcode ("push", "dpl");
2283 if (!inExcludeList ("dph"))
2284 emitcode ("push", "dph");
2285 /* if this isr has no bank i.e. is going to
2286 run with bank 0 , then we need to save more
2288 if (!FUNC_REGBANK (sym->type))
2291 /* if this function does not call any other
2292 function then we can be economical and
2293 save only those registers that are used */
2294 if (!IFFUNC_HASFCALL(sym->type))
2298 /* if any registers used */
2301 /* save the registers used */
2302 for (i = 0; i < sym->regsUsed->size; i++)
2304 if (bitVectBitValue (sym->regsUsed, i) ||
2305 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2306 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2314 /* this function has a function call cannot
2315 determines register usage so we will have to push the
2317 saveRBank (0, ic, FALSE);
2318 if (options.parms_in_bank1) {
2320 for (i=0; i < 8 ; i++ ) {
2321 emitcode ("push","%s",rb1regs[i]);
2328 /* This ISR uses a non-zero bank.
2330 * We assume that the bank is available for our
2333 * However, if this ISR calls a function which uses some
2334 * other bank, we must save that bank entirely.
2336 unsigned long banksToSave = 0;
2338 if (IFFUNC_HASFCALL(sym->type))
2341 #define MAX_REGISTER_BANKS 4
2346 for (i = ic; i; i = i->next)
2348 if (i->op == ENDFUNCTION)
2350 /* we got to the end OK. */
2358 dtype = operandType (IC_LEFT(i));
2360 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2362 /* Mark this bank for saving. */
2363 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2365 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2369 banksToSave |= (1 << FUNC_REGBANK(dtype));
2372 /* And note that we don't need to do it in
2380 /* This is a mess; we have no idea what
2381 * register bank the called function might
2384 * The only thing I can think of to do is
2385 * throw a warning and hope.
2387 werror(W_FUNCPTR_IN_USING_ISR);
2391 if (banksToSave && options.useXstack)
2393 /* Since we aren't passing it an ic,
2394 * saveRBank will assume r0 is available to abuse.
2396 * So switch to our (trashable) bank now, so
2397 * the caller's R0 isn't trashed.
2399 emitcode ("push", "psw");
2400 emitcode ("mov", "psw,#0x%02x",
2401 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2405 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2407 if (banksToSave & (1 << ix))
2409 saveRBank(ix, NULL, FALSE);
2413 // TODO: this needs a closer look
2414 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2419 /* if callee-save to be used for this function
2420 then save the registers being used in this function */
2421 if (IFFUNC_CALLEESAVES(sym->type))
2425 /* if any registers used */
2428 /* save the registers used */
2429 for (i = 0; i < sym->regsUsed->size; i++)
2431 if (bitVectBitValue (sym->regsUsed, i) ||
2432 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2434 /* remember one saved register for later usage */
2435 if (calleesaves_saved_register < 0)
2436 calleesaves_saved_register = i;
2437 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2445 /* set the register bank to the desired value */
2446 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2449 emitcode ("push", "psw");
2450 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2453 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2456 if (options.useXstack)
2458 emitcode ("mov", "r0,%s", spname);
2459 emitcode ("mov", "a,_bp");
2460 emitcode ("movx", "@r0,a");
2461 emitcode ("inc", "%s", spname);
2465 /* set up the stack */
2466 emitcode ("push", "_bp"); /* save the callers stack */
2468 emitcode ("mov", "_bp,%s", spname);
2471 /* adjust the stack for the function */
2477 werror (W_STACK_OVERFLOW, sym->name);
2479 if (i > 3 && sym->recvSize < 4)
2482 emitcode ("mov", "a,sp");
2483 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2484 emitcode ("mov", "sp,a");
2489 if (IFFUNC_CALLEESAVES(sym->type))
2491 /* if it's a callee-saves function we need a saved register */
2492 if (calleesaves_saved_register >= 0)
2494 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2495 emitcode ("mov", "a,sp");
2496 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2497 emitcode ("mov", "sp,a");
2498 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2501 /* do it the hard way */
2503 emitcode ("inc", "sp");
2507 /* not callee-saves, we can clobber r0 */
2508 emitcode ("mov", "r0,a");
2509 emitcode ("mov", "a,sp");
2510 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2511 emitcode ("mov", "sp,a");
2512 emitcode ("mov", "a,r0");
2517 emitcode ("inc", "sp");
2523 emitcode ("mov", "a,_spx");
2524 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2525 emitcode ("mov", "_spx,a");
2530 /*-----------------------------------------------------------------*/
2531 /* genEndFunction - generates epilogue for functions */
2532 /*-----------------------------------------------------------------*/
2534 genEndFunction (iCode * ic)
2536 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2538 if (IFFUNC_ISNAKED(sym->type))
2540 emitcode(";", "naked function: no epilogue.");
2544 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2546 emitcode ("mov", "%s,_bp", spname);
2549 /* if use external stack but some variables were
2550 added to the local stack then decrement the
2552 if (options.useXstack && sym->stack)
2554 emitcode ("mov", "a,sp");
2555 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2556 emitcode ("mov", "sp,a");
2560 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2562 if (options.useXstack)
2564 emitcode ("mov", "r0,%s", spname);
2565 emitcode ("movx", "a,@r0");
2566 emitcode ("mov", "_bp,a");
2567 emitcode ("dec", "%s", spname);
2571 emitcode ("pop", "_bp");
2575 /* restore the register bank */
2576 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2578 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2579 || !options.useXstack)
2581 /* Special case of ISR using non-zero bank with useXstack
2584 emitcode ("pop", "psw");
2588 if (IFFUNC_ISISR (sym->type))
2591 /* now we need to restore the registers */
2592 /* if this isr has no bank i.e. is going to
2593 run with bank 0 , then we need to save more
2595 if (!FUNC_REGBANK (sym->type))
2597 /* if this function does not call any other
2598 function then we can be economical and
2599 save only those registers that are used */
2600 if (!IFFUNC_HASFCALL(sym->type))
2604 /* if any registers used */
2607 /* save the registers used */
2608 for (i = sym->regsUsed->size; i >= 0; i--)
2610 if (bitVectBitValue (sym->regsUsed, i) ||
2611 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2612 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2619 if (options.parms_in_bank1) {
2621 for (i = 7 ; i >= 0 ; i-- ) {
2622 emitcode ("pop","%s",rb1regs[i]);
2625 /* this function has a function call cannot
2626 determines register usage so we will have to pop the
2628 unsaveRBank (0, ic, FALSE);
2633 /* This ISR uses a non-zero bank.
2635 * Restore any register banks saved by genFunction
2638 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2641 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2643 if (savedBanks & (1 << ix))
2645 unsaveRBank(ix, NULL, FALSE);
2649 if (options.useXstack)
2651 /* Restore bank AFTER calling unsaveRBank,
2652 * since it can trash r0.
2654 emitcode ("pop", "psw");
2658 if (!inExcludeList ("dph"))
2659 emitcode ("pop", "dph");
2660 if (!inExcludeList ("dpl"))
2661 emitcode ("pop", "dpl");
2662 if (!inExcludeList ("b"))
2663 emitcode ("pop", "b");
2664 if (!inExcludeList ("acc"))
2665 emitcode ("pop", "acc");
2667 if (IFFUNC_ISCRITICAL (sym->type))
2668 emitcode ("setb", "ea");
2670 /* if debug then send end of function */
2671 if (options.debug && currFunc)
2674 emitcode ("", "C$%s$%d$%d$%d ==.",
2675 FileBaseName (ic->filename), currFunc->lastLine,
2676 ic->level, ic->block);
2677 if (IS_STATIC (currFunc->etype))
2678 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2680 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2684 emitcode ("reti", "");
2688 if (IFFUNC_ISCRITICAL (sym->type))
2689 emitcode ("setb", "ea");
2691 if (IFFUNC_CALLEESAVES(sym->type))
2695 /* if any registers used */
2698 /* save the registers used */
2699 for (i = sym->regsUsed->size; i >= 0; i--)
2701 if (bitVectBitValue (sym->regsUsed, i) ||
2702 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2703 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2709 /* if debug then send end of function */
2710 if (options.debug && currFunc)
2713 emitcode ("", "C$%s$%d$%d$%d ==.",
2714 FileBaseName (ic->filename), currFunc->lastLine,
2715 ic->level, ic->block);
2716 if (IS_STATIC (currFunc->etype))
2717 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2719 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2723 emitcode ("ret", "");
2728 /*-----------------------------------------------------------------*/
2729 /* genRet - generate code for return statement */
2730 /*-----------------------------------------------------------------*/
2734 int size, offset = 0, pushed = 0;
2736 D(emitcode ("; genRet",""));
2738 /* if we have no return value then
2739 just generate the "ret" */
2743 /* we have something to return then
2744 move the return value into place */
2745 aopOp (IC_LEFT (ic), ic, FALSE);
2746 size = AOP_SIZE (IC_LEFT (ic));
2751 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2754 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2756 emitcode ("push", "%s", l);
2761 l = aopGet (AOP (IC_LEFT (ic)), offset,
2763 if (strcmp (fReturn[offset], l))
2764 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2773 if (strcmp (fReturn[pushed], "a"))
2774 emitcode ("pop", fReturn[pushed]);
2776 emitcode ("pop", "acc");
2779 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2782 /* generate a jump to the return label
2783 if the next is not the return statement */
2784 if (!(ic->next && ic->next->op == LABEL &&
2785 IC_LABEL (ic->next) == returnLabel))
2787 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2791 /*-----------------------------------------------------------------*/
2792 /* genLabel - generates a label */
2793 /*-----------------------------------------------------------------*/
2795 genLabel (iCode * ic)
2797 /* special case never generate */
2798 if (IC_LABEL (ic) == entryLabel)
2801 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2804 /*-----------------------------------------------------------------*/
2805 /* genGoto - generates a ljmp */
2806 /*-----------------------------------------------------------------*/
2808 genGoto (iCode * ic)
2810 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2813 /*-----------------------------------------------------------------*/
2814 /* findLabelBackwards: walks back through the iCode chain looking */
2815 /* for the given label. Returns number of iCode instructions */
2816 /* between that label and given ic. */
2817 /* Returns zero if label not found. */
2818 /*-----------------------------------------------------------------*/
2820 findLabelBackwards (iCode * ic, int key)
2829 /* If we have any pushes or pops, we cannot predict the distance.
2830 I don't like this at all, this should be dealt with in the
2832 if (ic->op == IPUSH || ic->op == IPOP) {
2836 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2845 /*-----------------------------------------------------------------*/
2846 /* genPlusIncr :- does addition with increment if possible */
2847 /*-----------------------------------------------------------------*/
2849 genPlusIncr (iCode * ic)
2851 unsigned int icount;
2852 unsigned int size = getDataSize (IC_RESULT (ic));
2854 /* will try to generate an increment */
2855 /* if the right side is not a literal
2857 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2860 /* if the literal value of the right hand side
2861 is greater than 4 then it is not worth it */
2862 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2865 D(emitcode ("; genPlusIncr",""));
2867 /* if increment >=16 bits in register or direct space */
2868 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2869 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2877 /* If the next instruction is a goto and the goto target
2878 * is < 10 instructions previous to this, we can generate
2879 * jumps straight to that target.
2881 if (ic->next && ic->next->op == GOTO
2882 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2883 && labelRange <= 10)
2885 emitcode (";", "tail increment optimized");
2886 tlbl = IC_LABEL (ic->next);
2891 tlbl = newiTempLabel (NULL);
2894 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2895 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2896 IS_AOP_PREG (IC_RESULT (ic)))
2897 emitcode ("cjne", "%s,#0x00,%05d$",
2898 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2902 emitcode ("clr", "a");
2903 emitcode ("cjne", "a,%s,%05d$",
2904 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2908 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2911 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2912 IS_AOP_PREG (IC_RESULT (ic)))
2913 emitcode ("cjne", "%s,#0x00,%05d$",
2914 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2917 emitcode ("cjne", "a,%s,%05d$",
2918 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2921 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2925 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2926 IS_AOP_PREG (IC_RESULT (ic)))
2927 emitcode ("cjne", "%s,#0x00,%05d$",
2928 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2932 emitcode ("cjne", "a,%s,%05d$",
2933 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2936 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2941 emitcode ("", "%05d$:", tlbl->key + 100);
2946 /* if the sizes are greater than 1 then we cannot */
2947 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2948 AOP_SIZE (IC_LEFT (ic)) > 1)
2951 /* we can if the aops of the left & result match or
2952 if they are in registers and the registers are the
2954 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2959 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2960 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2961 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
2967 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2976 /*-----------------------------------------------------------------*/
2977 /* outBitAcc - output a bit in acc */
2978 /*-----------------------------------------------------------------*/
2980 outBitAcc (operand * result)
2982 symbol *tlbl = newiTempLabel (NULL);
2983 /* if the result is a bit */
2984 if (AOP_TYPE (result) == AOP_CRY)
2986 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
2990 emitcode ("jz", "%05d$", tlbl->key + 100);
2991 emitcode ("mov", "a,%s", one);
2992 emitcode ("", "%05d$:", tlbl->key + 100);
2997 /*-----------------------------------------------------------------*/
2998 /* genPlusBits - generates code for addition of two bits */
2999 /*-----------------------------------------------------------------*/
3001 genPlusBits (iCode * ic)
3003 D(emitcode ("; genPlusBits",""));
3005 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3007 symbol *lbl = newiTempLabel (NULL);
3008 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3009 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3010 emitcode ("cpl", "c");
3011 emitcode ("", "%05d$:", (lbl->key + 100));
3012 outBitC (IC_RESULT (ic));
3016 emitcode ("clr", "a");
3017 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3018 emitcode ("rlc", "a");
3019 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3020 emitcode ("addc", "a,#0x00");
3021 outAcc (IC_RESULT (ic));
3026 /* This is the original version of this code.
3028 * This is being kept around for reference,
3029 * because I am not entirely sure I got it right...
3032 adjustArithmeticResult (iCode * ic)
3034 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3035 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3036 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3037 aopPut (AOP (IC_RESULT (ic)),
3038 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3040 isOperandVolatile (IC_RESULT (ic), FALSE));
3042 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3043 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3044 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3045 aopPut (AOP (IC_RESULT (ic)),
3046 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3048 isOperandVolatile (IC_RESULT (ic), FALSE));
3050 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3051 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3052 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3053 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3054 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3057 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3058 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3062 /* This is the pure and virtuous version of this code.
3063 * I'm pretty certain it's right, but not enough to toss the old
3067 adjustArithmeticResult (iCode * ic)
3069 if (opIsGptr (IC_RESULT (ic)) &&
3070 opIsGptr (IC_LEFT (ic)) &&
3071 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3073 aopPut (AOP (IC_RESULT (ic)),
3074 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3076 isOperandVolatile (IC_RESULT (ic), FALSE));
3079 if (opIsGptr (IC_RESULT (ic)) &&
3080 opIsGptr (IC_RIGHT (ic)) &&
3081 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3083 aopPut (AOP (IC_RESULT (ic)),
3084 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3086 isOperandVolatile (IC_RESULT (ic), FALSE));
3089 if (opIsGptr (IC_RESULT (ic)) &&
3090 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3091 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3092 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3093 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3096 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3097 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3102 /*-----------------------------------------------------------------*/
3103 /* genPlus - generates code for addition */
3104 /*-----------------------------------------------------------------*/
3106 genPlus (iCode * ic)
3108 int size, offset = 0;
3110 asmop *leftOp, *rightOp;
3112 /* special cases :- */
3114 D(emitcode ("; genPlus",""));
3116 aopOp (IC_LEFT (ic), ic, FALSE);
3117 aopOp (IC_RIGHT (ic), ic, FALSE);
3118 aopOp (IC_RESULT (ic), ic, TRUE);
3120 /* if literal, literal on the right or
3121 if left requires ACC or right is already
3123 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3124 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3125 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3127 operand *t = IC_RIGHT (ic);
3128 IC_RIGHT (ic) = IC_LEFT (ic);
3132 /* if both left & right are in bit
3134 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3135 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3141 /* if left in bit space & right literal */
3142 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3143 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3145 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3146 /* if result in bit space */
3147 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3149 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3150 emitcode ("cpl", "c");
3151 outBitC (IC_RESULT (ic));
3155 size = getDataSize (IC_RESULT (ic));
3158 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3159 emitcode ("addc", "a,#00");
3160 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3166 /* if I can do an increment instead
3167 of add then GOOD for ME */
3168 if (genPlusIncr (ic) == TRUE)
3171 size = getDataSize (IC_RESULT (ic));
3173 leftOp = AOP(IC_LEFT(ic));
3174 rightOp = AOP(IC_RIGHT(ic));
3179 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3181 emitcode("mov", "b,a");
3182 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3183 emitcode("xch", "a,b");
3184 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3185 emitcode (add, "a,b");
3187 else if (aopGetUsesAcc (leftOp, offset))
3189 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3190 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3194 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3195 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3197 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3198 add = "addc"; /* further adds must propagate carry */
3201 adjustArithmeticResult (ic);
3204 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3205 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3206 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3209 /*-----------------------------------------------------------------*/
3210 /* genMinusDec :- does subtraction with deccrement if possible */
3211 /*-----------------------------------------------------------------*/
3213 genMinusDec (iCode * ic)
3215 unsigned int icount;
3216 unsigned int size = getDataSize (IC_RESULT (ic));
3218 /* will try to generate an increment */
3219 /* if the right side is not a literal
3221 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3224 /* if the literal value of the right hand side
3225 is greater than 4 then it is not worth it */
3226 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3229 D(emitcode ("; genMinusDec",""));
3231 /* if decrement >=16 bits in register or direct space */
3232 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3233 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3241 /* If the next instruction is a goto and the goto target
3242 * is <= 10 instructions previous to this, we can generate
3243 * jumps straight to that target.
3245 if (ic->next && ic->next->op == GOTO
3246 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3247 && labelRange <= 10)
3249 emitcode (";", "tail decrement optimized");
3250 tlbl = IC_LABEL (ic->next);
3255 tlbl = newiTempLabel (NULL);
3259 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3260 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3261 IS_AOP_PREG (IC_RESULT (ic)))
3262 emitcode ("cjne", "%s,#0xff,%05d$"
3263 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3267 emitcode ("mov", "a,#0xff");
3268 emitcode ("cjne", "a,%s,%05d$"
3269 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3272 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3275 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3276 IS_AOP_PREG (IC_RESULT (ic)))
3277 emitcode ("cjne", "%s,#0xff,%05d$"
3278 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3282 emitcode ("cjne", "a,%s,%05d$"
3283 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3286 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3290 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3291 IS_AOP_PREG (IC_RESULT (ic)))
3292 emitcode ("cjne", "%s,#0xff,%05d$"
3293 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3297 emitcode ("cjne", "a,%s,%05d$"
3298 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3301 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3305 emitcode ("", "%05d$:", tlbl->key + 100);
3310 /* if the sizes are greater than 1 then we cannot */
3311 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3312 AOP_SIZE (IC_LEFT (ic)) > 1)
3315 /* we can if the aops of the left & result match or
3316 if they are in registers and the registers are the
3318 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3322 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3330 /*-----------------------------------------------------------------*/
3331 /* addSign - complete with sign */
3332 /*-----------------------------------------------------------------*/
3334 addSign (operand * result, int offset, int sign)
3336 int size = (getDataSize (result) - offset);
3341 emitcode ("rlc", "a");
3342 emitcode ("subb", "a,acc");
3344 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3348 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3352 /*-----------------------------------------------------------------*/
3353 /* genMinusBits - generates code for subtraction of two bits */
3354 /*-----------------------------------------------------------------*/
3356 genMinusBits (iCode * ic)
3358 symbol *lbl = newiTempLabel (NULL);
3360 D(emitcode ("; genMinusBits",""));
3362 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3364 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3365 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3366 emitcode ("cpl", "c");
3367 emitcode ("", "%05d$:", (lbl->key + 100));
3368 outBitC (IC_RESULT (ic));
3372 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3373 emitcode ("subb", "a,acc");
3374 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3375 emitcode ("inc", "a");
3376 emitcode ("", "%05d$:", (lbl->key + 100));
3377 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3378 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3382 /*-----------------------------------------------------------------*/
3383 /* genMinus - generates code for subtraction */
3384 /*-----------------------------------------------------------------*/
3386 genMinus (iCode * ic)
3388 int size, offset = 0;
3390 D(emitcode ("; genMinus",""));
3392 aopOp (IC_LEFT (ic), ic, FALSE);
3393 aopOp (IC_RIGHT (ic), ic, FALSE);
3394 aopOp (IC_RESULT (ic), ic, TRUE);
3396 /* special cases :- */
3397 /* if both left & right are in bit space */
3398 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3399 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3405 /* if I can do an decrement instead
3406 of subtract then GOOD for ME */
3407 if (genMinusDec (ic) == TRUE)
3410 size = getDataSize (IC_RESULT (ic));
3412 /* if literal, add a,#-lit, else normal subb */
3413 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3415 unsigned long lit = 0L;
3417 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3422 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3423 /* first add without previous c */
3425 if (!size && lit== (unsigned long) -1) {
3426 emitcode ("dec", "a");
3428 emitcode ("add", "a,#0x%02x",
3429 (unsigned int) (lit & 0x0FFL));
3432 emitcode ("addc", "a,#0x%02x",
3433 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3435 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3440 asmop *leftOp, *rightOp;
3442 leftOp = AOP(IC_LEFT(ic));
3443 rightOp = AOP(IC_RIGHT(ic));
3447 if (aopGetUsesAcc(rightOp, offset)) {
3448 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3449 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3451 emitcode( "setb", "c");
3453 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3454 emitcode("cpl", "a");
3456 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3459 emitcode ("subb", "a,%s",
3460 aopGet(rightOp, offset, FALSE, TRUE));
3463 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3468 adjustArithmeticResult (ic);
3471 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3472 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3473 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3477 /*-----------------------------------------------------------------*/
3478 /* genMultbits :- multiplication of bits */
3479 /*-----------------------------------------------------------------*/
3481 genMultbits (operand * left,
3485 D(emitcode ("; genMultbits",""));
3487 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3488 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3493 /*-----------------------------------------------------------------*/
3494 /* genMultOneByte : 8*8=8/16 bit multiplication */
3495 /*-----------------------------------------------------------------*/
3497 genMultOneByte (operand * left,
3501 sym_link *opetype = operandType (result);
3503 int size=AOP_SIZE(result);
3505 D(emitcode ("; genMultOneByte",""));
3507 if (size<1 || size>2) {
3508 // this should never happen
3509 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3510 AOP_SIZE(result), __FILE__, lineno);
3514 /* (if two literals: the value is computed before) */
3515 /* if one literal, literal on the right */
3516 if (AOP_TYPE (left) == AOP_LIT)
3521 //emitcode (";", "swapped left and right");
3524 if (SPEC_USIGN(opetype)
3525 // ignore the sign of left and right, what else can we do?
3526 || (SPEC_USIGN(operandType(left)) &&
3527 SPEC_USIGN(operandType(right)))) {
3528 // just an unsigned 8*8=8/16 multiply
3529 //emitcode (";","unsigned");
3530 // TODO: check for accumulator clash between left & right aops?
3531 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3532 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3533 emitcode ("mul", "ab");
3534 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3536 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3541 // we have to do a signed multiply
3543 //emitcode (";", "signed");
3544 emitcode ("clr", "F0"); // reset sign flag
3545 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3547 lbl=newiTempLabel(NULL);
3548 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3549 // left side is negative, 8-bit two's complement, this fails for -128
3550 emitcode ("setb", "F0"); // set sign flag
3551 emitcode ("cpl", "a");
3552 emitcode ("inc", "a");
3554 emitcode ("", "%05d$:", lbl->key+100);
3557 if (AOP_TYPE(right)==AOP_LIT) {
3558 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3559 /* AND literal negative */
3561 emitcode ("cpl", "F0"); // complement sign flag
3562 emitcode ("mov", "b,#0x%02x", -val);
3564 emitcode ("mov", "b,#0x%02x", val);
3567 lbl=newiTempLabel(NULL);
3568 emitcode ("mov", "b,a");
3569 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3570 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3571 // right side is negative, 8-bit two's complement
3572 emitcode ("cpl", "F0"); // complement sign flag
3573 emitcode ("cpl", "a");
3574 emitcode ("inc", "a");
3575 emitcode ("", "%05d$:", lbl->key+100);
3577 emitcode ("mul", "ab");
3579 lbl=newiTempLabel(NULL);
3580 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3581 // only ONE op was negative, we have to do a 8/16-bit two's complement
3582 emitcode ("cpl", "a"); // lsb
3584 emitcode ("inc", "a");
3586 emitcode ("add", "a,#1");
3587 emitcode ("xch", "a,b");
3588 emitcode ("cpl", "a"); // msb
3589 emitcode ("addc", "a,#0");
3590 emitcode ("xch", "a,b");
3593 emitcode ("", "%05d$:", lbl->key+100);
3594 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3596 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3600 /*-----------------------------------------------------------------*/
3601 /* genMult - generates code for multiplication */
3602 /*-----------------------------------------------------------------*/
3604 genMult (iCode * ic)
3606 operand *left = IC_LEFT (ic);
3607 operand *right = IC_RIGHT (ic);
3608 operand *result = IC_RESULT (ic);
3610 D(emitcode ("; genMult",""));
3612 /* assign the amsops */
3613 aopOp (left, ic, FALSE);
3614 aopOp (right, ic, FALSE);
3615 aopOp (result, ic, TRUE);
3617 /* special cases first */
3619 if (AOP_TYPE (left) == AOP_CRY &&
3620 AOP_TYPE (right) == AOP_CRY)
3622 genMultbits (left, right, result);
3626 /* if both are of size == 1 */
3627 #if 0 // one of them can be a sloc shared with the result
3628 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3630 if (getSize(operandType(left)) == 1 &&
3631 getSize(operandType(right)) == 1)
3634 genMultOneByte (left, right, result);
3638 /* should have been converted to function call */
3639 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3640 getSize(OP_SYMBOL(right)->type));
3644 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3645 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3646 freeAsmop (result, NULL, ic, TRUE);
3649 /*-----------------------------------------------------------------*/
3650 /* genDivbits :- division of bits */
3651 /*-----------------------------------------------------------------*/
3653 genDivbits (operand * left,
3660 D(emitcode ("; genDivbits",""));
3662 /* the result must be bit */
3663 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3664 l = aopGet (AOP (left), 0, FALSE, FALSE);
3668 emitcode ("div", "ab");
3669 emitcode ("rrc", "a");
3670 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3673 /*-----------------------------------------------------------------*/
3674 /* genDivOneByte : 8 bit division */
3675 /*-----------------------------------------------------------------*/
3677 genDivOneByte (operand * left,
3681 sym_link *opetype = operandType (result);
3686 D(emitcode ("; genDivOneByte",""));
3688 size = AOP_SIZE (result) - 1;
3690 /* signed or unsigned */
3691 if (SPEC_USIGN (opetype))
3693 /* unsigned is easy */
3694 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3695 l = aopGet (AOP (left), 0, FALSE, FALSE);
3697 emitcode ("div", "ab");
3698 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3700 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3704 /* signed is a little bit more difficult */
3706 /* save the signs of the operands */
3707 l = aopGet (AOP (left), 0, FALSE, FALSE);
3709 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3710 emitcode ("push", "acc"); /* save it on the stack */
3712 /* now sign adjust for both left & right */
3713 l = aopGet (AOP (right), 0, FALSE, FALSE);
3715 lbl = newiTempLabel (NULL);
3716 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3717 emitcode ("cpl", "a");
3718 emitcode ("inc", "a");
3719 emitcode ("", "%05d$:", (lbl->key + 100));
3720 emitcode ("mov", "b,a");
3722 /* sign adjust left side */
3723 l = aopGet (AOP (left), 0, FALSE, FALSE);
3726 lbl = newiTempLabel (NULL);
3727 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3728 emitcode ("cpl", "a");
3729 emitcode ("inc", "a");
3730 emitcode ("", "%05d$:", (lbl->key + 100));
3732 /* now the division */
3733 emitcode ("div", "ab");
3734 /* we are interested in the lower order
3736 emitcode ("mov", "b,a");
3737 lbl = newiTempLabel (NULL);
3738 emitcode ("pop", "acc");
3739 /* if there was an over flow we don't
3740 adjust the sign of the result */
3741 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3742 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3744 emitcode ("clr", "a");
3745 emitcode ("subb", "a,b");
3746 emitcode ("mov", "b,a");
3747 emitcode ("", "%05d$:", (lbl->key + 100));
3749 /* now we are done */
3750 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3753 emitcode ("mov", "c,b.7");
3754 emitcode ("subb", "a,acc");
3757 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3761 /*-----------------------------------------------------------------*/
3762 /* genDiv - generates code for division */
3763 /*-----------------------------------------------------------------*/
3767 operand *left = IC_LEFT (ic);
3768 operand *right = IC_RIGHT (ic);
3769 operand *result = IC_RESULT (ic);
3771 D(emitcode ("; genDiv",""));
3773 /* assign the amsops */
3774 aopOp (left, ic, FALSE);
3775 aopOp (right, ic, FALSE);
3776 aopOp (result, ic, TRUE);
3778 /* special cases first */
3780 if (AOP_TYPE (left) == AOP_CRY &&
3781 AOP_TYPE (right) == AOP_CRY)
3783 genDivbits (left, right, result);
3787 /* if both are of size == 1 */
3788 if (AOP_SIZE (left) == 1 &&
3789 AOP_SIZE (right) == 1)
3791 genDivOneByte (left, right, result);
3795 /* should have been converted to function call */
3798 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3799 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3800 freeAsmop (result, NULL, ic, TRUE);
3803 /*-----------------------------------------------------------------*/
3804 /* genModbits :- modulus of bits */
3805 /*-----------------------------------------------------------------*/
3807 genModbits (operand * left,
3814 D(emitcode ("; genModbits",""));
3816 /* the result must be bit */
3817 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3818 l = aopGet (AOP (left), 0, FALSE, FALSE);
3822 emitcode ("div", "ab");
3823 emitcode ("mov", "a,b");
3824 emitcode ("rrc", "a");
3825 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3828 /*-----------------------------------------------------------------*/
3829 /* genModOneByte : 8 bit modulus */
3830 /*-----------------------------------------------------------------*/
3832 genModOneByte (operand * left,
3836 sym_link *opetype = operandType (result);
3840 D(emitcode ("; genModOneByte",""));
3842 /* signed or unsigned */
3843 if (SPEC_USIGN (opetype))
3845 /* unsigned is easy */
3846 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3847 l = aopGet (AOP (left), 0, FALSE, FALSE);
3849 emitcode ("div", "ab");
3850 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3854 /* signed is a little bit more difficult */
3856 /* save the signs of the operands */
3857 l = aopGet (AOP (left), 0, FALSE, FALSE);
3860 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3861 emitcode ("push", "acc"); /* save it on the stack */
3863 /* now sign adjust for both left & right */
3864 l = aopGet (AOP (right), 0, FALSE, FALSE);
3867 lbl = newiTempLabel (NULL);
3868 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3869 emitcode ("cpl", "a");
3870 emitcode ("inc", "a");
3871 emitcode ("", "%05d$:", (lbl->key + 100));
3872 emitcode ("mov", "b,a");
3874 /* sign adjust left side */
3875 l = aopGet (AOP (left), 0, FALSE, FALSE);
3878 lbl = newiTempLabel (NULL);
3879 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3880 emitcode ("cpl", "a");
3881 emitcode ("inc", "a");
3882 emitcode ("", "%05d$:", (lbl->key + 100));
3884 /* now the multiplication */
3885 emitcode ("div", "ab");
3886 /* we are interested in the lower order
3888 lbl = newiTempLabel (NULL);
3889 emitcode ("pop", "acc");
3890 /* if there was an over flow we don't
3891 adjust the sign of the result */
3892 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3893 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3895 emitcode ("clr", "a");
3896 emitcode ("subb", "a,b");
3897 emitcode ("mov", "b,a");
3898 emitcode ("", "%05d$:", (lbl->key + 100));
3900 /* now we are done */
3901 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3905 /*-----------------------------------------------------------------*/
3906 /* genMod - generates code for division */
3907 /*-----------------------------------------------------------------*/
3911 operand *left = IC_LEFT (ic);
3912 operand *right = IC_RIGHT (ic);
3913 operand *result = IC_RESULT (ic);
3915 D(emitcode ("; genMod",""));
3917 /* assign the amsops */
3918 aopOp (left, ic, FALSE);
3919 aopOp (right, ic, FALSE);
3920 aopOp (result, ic, TRUE);
3922 /* special cases first */
3924 if (AOP_TYPE (left) == AOP_CRY &&
3925 AOP_TYPE (right) == AOP_CRY)
3927 genModbits (left, right, result);
3931 /* if both are of size == 1 */
3932 if (AOP_SIZE (left) == 1 &&
3933 AOP_SIZE (right) == 1)
3935 genModOneByte (left, right, result);
3939 /* should have been converted to function call */
3943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3945 freeAsmop (result, NULL, ic, TRUE);
3948 /*-----------------------------------------------------------------*/
3949 /* genIfxJump :- will create a jump depending on the ifx */
3950 /*-----------------------------------------------------------------*/
3952 genIfxJump (iCode * ic, char *jval)
3955 symbol *tlbl = newiTempLabel (NULL);
3958 D(emitcode ("; genIfxJump",""));
3960 /* if true label then we jump if condition
3964 jlbl = IC_TRUE (ic);
3965 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3966 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3970 /* false label is present */
3971 jlbl = IC_FALSE (ic);
3972 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3973 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3975 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3976 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3978 emitcode (inst, "%05d$", tlbl->key + 100);
3979 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3980 emitcode ("", "%05d$:", tlbl->key + 100);
3982 /* mark the icode as generated */
3986 /*-----------------------------------------------------------------*/
3987 /* genCmp :- greater or less than comparison */
3988 /*-----------------------------------------------------------------*/
3990 genCmp (operand * left, operand * right,
3991 operand * result, iCode * ifx, int sign, iCode *ic)
3993 int size, offset = 0;
3994 unsigned long lit = 0L;
3997 D(emitcode ("; genCmp",""));
3999 /* if left & right are bit variables */
4000 if (AOP_TYPE (left) == AOP_CRY &&
4001 AOP_TYPE (right) == AOP_CRY)
4003 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4004 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4008 /* subtract right from left if at the
4009 end the carry flag is set then we know that
4010 left is greater than right */
4011 size = max (AOP_SIZE (left), AOP_SIZE (right));
4013 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4014 if ((size == 1) && !sign &&
4015 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4017 symbol *lbl = newiTempLabel (NULL);
4018 emitcode ("cjne", "%s,%s,%05d$",
4019 aopGet (AOP (left), offset, FALSE, FALSE),
4020 aopGet (AOP (right), offset, FALSE, FALSE),
4022 emitcode ("", "%05d$:", lbl->key + 100);
4026 if (AOP_TYPE (right) == AOP_LIT)
4028 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4029 /* optimize if(x < 0) or if(x >= 0) */
4038 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4039 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4041 genIfxJump (ifx, "acc.7");
4045 emitcode ("rlc", "a");
4053 rightInB = aopGetUsesAcc(AOP (right), offset);
4055 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4056 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4057 if (sign && size == 0)
4059 emitcode ("xrl", "a,#0x80");
4060 if (AOP_TYPE (right) == AOP_LIT)
4062 unsigned long lit = (unsigned long)
4063 floatFromVal (AOP (right)->aopu.aop_lit);
4064 emitcode ("subb", "a,#0x%02x",
4065 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4070 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4071 emitcode ("xrl", "b,#0x80");
4072 emitcode ("subb", "a,b");
4078 emitcode ("subb", "a,b");
4080 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4088 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4089 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4090 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4096 /* if the result is used in the next
4097 ifx conditional branch then generate
4098 code a little differently */
4100 genIfxJump (ifx, "c");
4103 /* leave the result in acc */
4107 /*-----------------------------------------------------------------*/
4108 /* genCmpGt :- greater than comparison */
4109 /*-----------------------------------------------------------------*/
4111 genCmpGt (iCode * ic, iCode * ifx)
4113 operand *left, *right, *result;
4114 sym_link *letype, *retype;
4117 D(emitcode ("; genCmpGt",""));
4119 left = IC_LEFT (ic);
4120 right = IC_RIGHT (ic);
4121 result = IC_RESULT (ic);
4123 letype = getSpec (operandType (left));
4124 retype = getSpec (operandType (right));
4125 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4126 /* assign the amsops */
4127 aopOp (left, ic, FALSE);
4128 aopOp (right, ic, FALSE);
4129 aopOp (result, ic, TRUE);
4131 genCmp (right, left, result, ifx, sign,ic);
4133 freeAsmop (result, NULL, ic, TRUE);
4136 /*-----------------------------------------------------------------*/
4137 /* genCmpLt - less than comparisons */
4138 /*-----------------------------------------------------------------*/
4140 genCmpLt (iCode * ic, iCode * ifx)
4142 operand *left, *right, *result;
4143 sym_link *letype, *retype;
4146 D(emitcode ("; genCmpLt",""));
4148 left = IC_LEFT (ic);
4149 right = IC_RIGHT (ic);
4150 result = IC_RESULT (ic);
4152 letype = getSpec (operandType (left));
4153 retype = getSpec (operandType (right));
4154 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4156 /* assign the amsops */
4157 aopOp (left, ic, FALSE);
4158 aopOp (right, ic, FALSE);
4159 aopOp (result, ic, TRUE);
4161 genCmp (left, right, result, ifx, sign,ic);
4163 freeAsmop (result, NULL, ic, TRUE);
4166 /*-----------------------------------------------------------------*/
4167 /* gencjneshort - compare and jump if not equal */
4168 /*-----------------------------------------------------------------*/
4170 gencjneshort (operand * left, operand * right, symbol * lbl)
4172 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4174 unsigned long lit = 0L;
4176 /* if the left side is a literal or
4177 if the right is in a pointer register and left
4179 if ((AOP_TYPE (left) == AOP_LIT) ||
4180 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4186 if (AOP_TYPE (right) == AOP_LIT)
4187 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4189 /* if the right side is a literal then anything goes */
4190 if (AOP_TYPE (right) == AOP_LIT &&
4191 AOP_TYPE (left) != AOP_DIR &&
4192 AOP_TYPE (left) != AOP_IMMD)
4196 emitcode ("cjne", "%s,%s,%05d$",
4197 aopGet (AOP (left), offset, FALSE, FALSE),
4198 aopGet (AOP (right), offset, FALSE, FALSE),
4204 /* if the right side is in a register or in direct space or
4205 if the left is a pointer register & right is not */
4206 else if (AOP_TYPE (right) == AOP_REG ||
4207 AOP_TYPE (right) == AOP_DIR ||
4208 AOP_TYPE (right) == AOP_LIT ||
4209 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4210 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4214 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4215 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4216 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4217 emitcode ("jnz", "%05d$", lbl->key + 100);
4219 emitcode ("cjne", "a,%s,%05d$",
4220 aopGet (AOP (right), offset, FALSE, TRUE),
4227 /* right is a pointer reg need both a & b */
4230 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4231 if (strcmp (l, "b"))
4232 emitcode ("mov", "b,%s", l);
4233 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4234 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4240 /*-----------------------------------------------------------------*/
4241 /* gencjne - compare and jump if not equal */
4242 /*-----------------------------------------------------------------*/
4244 gencjne (operand * left, operand * right, symbol * lbl)
4246 symbol *tlbl = newiTempLabel (NULL);
4248 gencjneshort (left, right, lbl);
4250 emitcode ("mov", "a,%s", one);
4251 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4252 emitcode ("", "%05d$:", lbl->key + 100);
4253 emitcode ("clr", "a");
4254 emitcode ("", "%05d$:", tlbl->key + 100);
4257 /*-----------------------------------------------------------------*/
4258 /* genCmpEq - generates code for equal to */
4259 /*-----------------------------------------------------------------*/
4261 genCmpEq (iCode * ic, iCode * ifx)
4263 operand *left, *right, *result;
4265 D(emitcode ("; genCmpEq",""));
4267 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4268 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4269 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4271 /* if literal, literal on the right or
4272 if the right is in a pointer register and left
4274 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4275 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4277 operand *t = IC_RIGHT (ic);
4278 IC_RIGHT (ic) = IC_LEFT (ic);
4282 if (ifx && !AOP_SIZE (result))
4285 /* if they are both bit variables */
4286 if (AOP_TYPE (left) == AOP_CRY &&
4287 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4289 if (AOP_TYPE (right) == AOP_LIT)
4291 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4295 emitcode ("cpl", "c");
4299 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4303 emitcode ("clr", "c");
4305 /* AOP_TYPE(right) == AOP_CRY */
4309 symbol *lbl = newiTempLabel (NULL);
4310 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4311 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4312 emitcode ("cpl", "c");
4313 emitcode ("", "%05d$:", (lbl->key + 100));
4315 /* if true label then we jump if condition
4317 tlbl = newiTempLabel (NULL);
4320 emitcode ("jnc", "%05d$", tlbl->key + 100);
4321 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4325 emitcode ("jc", "%05d$", tlbl->key + 100);
4326 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4328 emitcode ("", "%05d$:", tlbl->key + 100);
4332 tlbl = newiTempLabel (NULL);
4333 gencjneshort (left, right, tlbl);
4336 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4337 emitcode ("", "%05d$:", tlbl->key + 100);
4341 symbol *lbl = newiTempLabel (NULL);
4342 emitcode ("sjmp", "%05d$", lbl->key + 100);
4343 emitcode ("", "%05d$:", tlbl->key + 100);
4344 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4345 emitcode ("", "%05d$:", lbl->key + 100);
4348 /* mark the icode as generated */
4353 /* if they are both bit variables */
4354 if (AOP_TYPE (left) == AOP_CRY &&
4355 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4357 if (AOP_TYPE (right) == AOP_LIT)
4359 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4362 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4363 emitcode ("cpl", "c");
4367 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4371 emitcode ("clr", "c");
4373 /* AOP_TYPE(right) == AOP_CRY */
4377 symbol *lbl = newiTempLabel (NULL);
4378 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4379 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4380 emitcode ("cpl", "c");
4381 emitcode ("", "%05d$:", (lbl->key + 100));
4384 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4391 genIfxJump (ifx, "c");
4394 /* if the result is used in an arithmetic operation
4395 then put the result in place */
4400 gencjne (left, right, newiTempLabel (NULL));
4401 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4403 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4408 genIfxJump (ifx, "a");
4411 /* if the result is used in an arithmetic operation
4412 then put the result in place */
4413 if (AOP_TYPE (result) != AOP_CRY)
4415 /* leave the result in acc */
4419 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4420 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4421 freeAsmop (result, NULL, ic, TRUE);
4424 /*-----------------------------------------------------------------*/
4425 /* ifxForOp - returns the icode containing the ifx for operand */
4426 /*-----------------------------------------------------------------*/
4428 ifxForOp (operand * op, iCode * ic)
4430 /* if true symbol then needs to be assigned */
4431 if (IS_TRUE_SYMOP (op))
4434 /* if this has register type condition and
4435 the next instruction is ifx with the same operand
4436 and live to of the operand is upto the ifx only then */
4438 ic->next->op == IFX &&
4439 IC_COND (ic->next)->key == op->key &&
4440 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4446 /*-----------------------------------------------------------------*/
4447 /* hasInc - operand is incremented before any other use */
4448 /*-----------------------------------------------------------------*/
4450 hasInc (operand *op, iCode *ic,int osize)
4452 sym_link *type = operandType(op);
4453 sym_link *retype = getSpec (type);
4454 iCode *lic = ic->next;
4457 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4458 if (!IS_SYMOP(op)) return NULL;
4460 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4461 if (IS_AGGREGATE(type->next)) return NULL;
4462 if (osize != (isize = getSize(type->next))) return NULL;
4465 /* if operand of the form op = op + <sizeof *op> */
4466 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4467 isOperandEqual(IC_RESULT(lic),op) &&
4468 isOperandLiteral(IC_RIGHT(lic)) &&
4469 operandLitValue(IC_RIGHT(lic)) == isize) {
4472 /* if the operand used or deffed */
4473 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4476 /* if GOTO or IFX */
4477 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4483 /*-----------------------------------------------------------------*/
4484 /* genAndOp - for && operation */
4485 /*-----------------------------------------------------------------*/
4487 genAndOp (iCode * ic)
4489 operand *left, *right, *result;
4492 D(emitcode ("; genAndOp",""));
4494 /* note here that && operations that are in an
4495 if statement are taken away by backPatchLabels
4496 only those used in arthmetic operations remain */
4497 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4498 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4499 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4501 /* if both are bit variables */
4502 if (AOP_TYPE (left) == AOP_CRY &&
4503 AOP_TYPE (right) == AOP_CRY)
4505 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4506 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4511 tlbl = newiTempLabel (NULL);
4513 emitcode ("jz", "%05d$", tlbl->key + 100);
4515 emitcode ("", "%05d$:", tlbl->key + 100);
4519 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4520 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521 freeAsmop (result, NULL, ic, TRUE);
4525 /*-----------------------------------------------------------------*/
4526 /* genOrOp - for || operation */
4527 /*-----------------------------------------------------------------*/
4529 genOrOp (iCode * ic)
4531 operand *left, *right, *result;
4534 D(emitcode ("; genOrOp",""));
4536 /* note here that || operations that are in an
4537 if statement are taken away by backPatchLabels
4538 only those used in arthmetic operations remain */
4539 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4540 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4541 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4543 /* if both are bit variables */
4544 if (AOP_TYPE (left) == AOP_CRY &&
4545 AOP_TYPE (right) == AOP_CRY)
4547 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4548 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4553 tlbl = newiTempLabel (NULL);
4555 emitcode ("jnz", "%05d$", tlbl->key + 100);
4557 emitcode ("", "%05d$:", tlbl->key + 100);
4561 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4562 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4563 freeAsmop (result, NULL, ic, TRUE);
4566 /*-----------------------------------------------------------------*/
4567 /* isLiteralBit - test if lit == 2^n */
4568 /*-----------------------------------------------------------------*/
4570 isLiteralBit (unsigned long lit)
4572 unsigned long pw[32] =
4573 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4574 0x100L, 0x200L, 0x400L, 0x800L,
4575 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4576 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4577 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4578 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4579 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4582 for (idx = 0; idx < 32; idx++)
4588 /*-----------------------------------------------------------------*/
4589 /* continueIfTrue - */
4590 /*-----------------------------------------------------------------*/
4592 continueIfTrue (iCode * ic)
4595 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4599 /*-----------------------------------------------------------------*/
4601 /*-----------------------------------------------------------------*/
4603 jumpIfTrue (iCode * ic)
4606 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4610 /*-----------------------------------------------------------------*/
4611 /* jmpTrueOrFalse - */
4612 /*-----------------------------------------------------------------*/
4614 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4616 // ugly but optimized by peephole
4619 symbol *nlbl = newiTempLabel (NULL);
4620 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4621 emitcode ("", "%05d$:", tlbl->key + 100);
4622 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4623 emitcode ("", "%05d$:", nlbl->key + 100);
4627 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4628 emitcode ("", "%05d$:", tlbl->key + 100);
4633 /*-----------------------------------------------------------------*/
4634 /* genAnd - code for and */
4635 /*-----------------------------------------------------------------*/
4637 genAnd (iCode * ic, iCode * ifx)
4639 operand *left, *right, *result;
4640 int size, offset = 0;
4641 unsigned long lit = 0L;
4645 D(emitcode ("; genAnd",""));
4647 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4648 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4649 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4652 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4654 AOP_TYPE (left), AOP_TYPE (right));
4655 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4657 AOP_SIZE (left), AOP_SIZE (right));
4660 /* if left is a literal & right is not then exchange them */
4661 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4662 AOP_NEEDSACC (left))
4664 operand *tmp = right;
4669 /* if result = right then exchange them */
4670 if (sameRegs (AOP (result), AOP (right)))
4672 operand *tmp = right;
4677 /* if right is bit then exchange them */
4678 if (AOP_TYPE (right) == AOP_CRY &&
4679 AOP_TYPE (left) != AOP_CRY)
4681 operand *tmp = right;
4685 if (AOP_TYPE (right) == AOP_LIT)
4686 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4688 size = AOP_SIZE (result);
4691 // result = bit & yy;
4692 if (AOP_TYPE (left) == AOP_CRY)
4694 // c = bit & literal;
4695 if (AOP_TYPE (right) == AOP_LIT)
4699 if (size && sameRegs (AOP (result), AOP (left)))
4702 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4707 if (size && (AOP_TYPE (result) == AOP_CRY))
4709 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4712 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4717 emitcode ("clr", "c");
4722 if (AOP_TYPE (right) == AOP_CRY)
4725 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4726 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4731 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4733 emitcode ("rrc", "a");
4734 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4742 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4743 genIfxJump (ifx, "c");
4747 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4748 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4749 if ((AOP_TYPE (right) == AOP_LIT) &&
4750 (AOP_TYPE (result) == AOP_CRY) &&
4751 (AOP_TYPE (left) != AOP_CRY))
4753 int posbit = isLiteralBit (lit);
4758 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4761 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4767 sprintf (buffer, "acc.%d", posbit & 0x07);
4768 genIfxJump (ifx, buffer);
4775 symbol *tlbl = newiTempLabel (NULL);
4776 int sizel = AOP_SIZE (left);
4778 emitcode ("setb", "c");
4781 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4783 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4785 if ((posbit = isLiteralBit (bytelit)) != 0)
4786 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4789 if (bytelit != 0x0FFL)
4790 emitcode ("anl", "a,%s",
4791 aopGet (AOP (right), offset, FALSE, TRUE));
4792 emitcode ("jnz", "%05d$", tlbl->key + 100);
4797 // bit = left & literal
4800 emitcode ("clr", "c");
4801 emitcode ("", "%05d$:", tlbl->key + 100);
4803 // if(left & literal)
4807 jmpTrueOrFalse (ifx, tlbl);
4815 /* if left is same as result */
4816 if (sameRegs (AOP (result), AOP (left)))
4818 for (; size--; offset++)
4820 if (AOP_TYPE (right) == AOP_LIT)
4822 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4824 else if (bytelit == 0)
4826 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4828 else if (IS_AOP_PREG (result))
4830 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4831 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4832 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4835 emitcode ("anl", "%s,%s",
4836 aopGet (AOP (left), offset, FALSE, TRUE),
4837 aopGet (AOP (right), offset, FALSE, FALSE));
4841 if (AOP_TYPE (left) == AOP_ACC)
4842 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4845 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4846 if (IS_AOP_PREG (result))
4848 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4849 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4853 emitcode ("anl", "%s,a",
4854 aopGet (AOP (left), offset, FALSE, TRUE));
4861 // left & result in different registers
4862 if (AOP_TYPE (result) == AOP_CRY)
4865 // if(size), result in bit
4866 // if(!size && ifx), conditional oper: if(left & right)
4867 symbol *tlbl = newiTempLabel (NULL);
4868 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4870 emitcode ("setb", "c");
4873 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4874 emitcode ("anl", "a,%s",
4875 aopGet (AOP (right), offset, FALSE, FALSE));
4877 if (AOP_TYPE(left)==AOP_ACC) {
4878 emitcode("mov", "b,a");
4879 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4880 emitcode("anl", "a,b");
4882 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4883 emitcode ("anl", "a,%s",
4884 aopGet (AOP (left), offset, FALSE, FALSE));
4887 emitcode ("jnz", "%05d$", tlbl->key + 100);
4893 emitcode ("", "%05d$:", tlbl->key + 100);
4897 jmpTrueOrFalse (ifx, tlbl);
4901 for (; (size--); offset++)
4904 // result = left & right
4905 if (AOP_TYPE (right) == AOP_LIT)
4907 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4909 aopPut (AOP (result),
4910 aopGet (AOP (left), offset, FALSE, FALSE),
4912 isOperandVolatile (result, FALSE));
4915 else if (bytelit == 0)
4917 /* dummy read of volatile operand */
4918 if (isOperandVolatile (left, FALSE))
4919 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4920 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4924 // faster than result <- left, anl result,right
4925 // and better if result is SFR
4926 if (AOP_TYPE (left) == AOP_ACC)
4927 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4930 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4931 emitcode ("anl", "a,%s",
4932 aopGet (AOP (left), offset, FALSE, FALSE));
4934 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4940 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4941 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4942 freeAsmop (result, NULL, ic, TRUE);
4945 /*-----------------------------------------------------------------*/
4946 /* genOr - code for or */
4947 /*-----------------------------------------------------------------*/
4949 genOr (iCode * ic, iCode * ifx)
4951 operand *left, *right, *result;
4952 int size, offset = 0;
4953 unsigned long lit = 0L;
4955 D(emitcode ("; genOr",""));
4957 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4958 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4959 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4962 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4964 AOP_TYPE (left), AOP_TYPE (right));
4965 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4967 AOP_SIZE (left), AOP_SIZE (right));
4970 /* if left is a literal & right is not then exchange them */
4971 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4972 AOP_NEEDSACC (left))
4974 operand *tmp = right;
4979 /* if result = right then exchange them */
4980 if (sameRegs (AOP (result), AOP (right)))
4982 operand *tmp = right;
4987 /* if right is bit then exchange them */
4988 if (AOP_TYPE (right) == AOP_CRY &&
4989 AOP_TYPE (left) != AOP_CRY)
4991 operand *tmp = right;
4995 if (AOP_TYPE (right) == AOP_LIT)
4996 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4998 size = AOP_SIZE (result);
5002 if (AOP_TYPE (left) == AOP_CRY)
5004 if (AOP_TYPE (right) == AOP_LIT)
5006 // c = bit | literal;
5009 // lit != 0 => result = 1
5010 if (AOP_TYPE (result) == AOP_CRY)
5013 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5015 continueIfTrue (ifx);
5018 emitcode ("setb", "c");
5022 // lit == 0 => result = left
5023 if (size && sameRegs (AOP (result), AOP (left)))
5025 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5030 if (AOP_TYPE (right) == AOP_CRY)
5033 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5034 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5039 symbol *tlbl = newiTempLabel (NULL);
5040 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5041 emitcode ("setb", "c");
5042 emitcode ("jb", "%s,%05d$",
5043 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5045 emitcode ("jnz", "%05d$", tlbl->key + 100);
5046 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5048 jmpTrueOrFalse (ifx, tlbl);
5054 emitcode ("", "%05d$:", tlbl->key + 100);
5063 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5064 genIfxJump (ifx, "c");
5068 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5069 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5070 if ((AOP_TYPE (right) == AOP_LIT) &&
5071 (AOP_TYPE (result) == AOP_CRY) &&
5072 (AOP_TYPE (left) != AOP_CRY))
5078 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5080 continueIfTrue (ifx);
5085 // lit = 0, result = boolean(left)
5087 emitcode ("setb", "c");
5091 symbol *tlbl = newiTempLabel (NULL);
5092 emitcode ("jnz", "%05d$", tlbl->key + 100);
5094 emitcode ("", "%05d$:", tlbl->key + 100);
5098 genIfxJump (ifx, "a");
5106 /* if left is same as result */
5107 if (sameRegs (AOP (result), AOP (left)))
5109 for (; size--; offset++)
5111 if (AOP_TYPE (right) == AOP_LIT)
5113 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5115 /* dummy read of volatile operand */
5116 if (isOperandVolatile (left, FALSE))
5117 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5121 else if (IS_AOP_PREG (left))
5123 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5124 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5125 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5128 emitcode ("orl", "%s,%s",
5129 aopGet (AOP (left), offset, FALSE, TRUE),
5130 aopGet (AOP (right), offset, FALSE, FALSE));
5134 if (AOP_TYPE (left) == AOP_ACC)
5135 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5138 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5139 if (IS_AOP_PREG (left))
5141 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5142 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5145 emitcode ("orl", "%s,a",
5146 aopGet (AOP (left), offset, FALSE, TRUE));
5153 // left & result in different registers
5154 if (AOP_TYPE (result) == AOP_CRY)
5157 // if(size), result in bit
5158 // if(!size && ifx), conditional oper: if(left | right)
5159 symbol *tlbl = newiTempLabel (NULL);
5160 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5162 emitcode ("setb", "c");
5165 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5166 emitcode ("orl", "a,%s",
5167 aopGet (AOP (right), offset, FALSE, FALSE));
5169 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5170 emitcode ("orl", "a,%s",
5171 aopGet (AOP (left), offset, FALSE, FALSE));
5173 emitcode ("jnz", "%05d$", tlbl->key + 100);
5179 emitcode ("", "%05d$:", tlbl->key + 100);
5183 jmpTrueOrFalse (ifx, tlbl);
5186 for (; (size--); offset++)
5189 // result = left & right
5190 if (AOP_TYPE (right) == AOP_LIT)
5192 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5194 aopPut (AOP (result),
5195 aopGet (AOP (left), offset, FALSE, FALSE),
5197 isOperandVolatile (result, FALSE));
5201 // faster than result <- left, anl result,right
5202 // and better if result is SFR
5203 if (AOP_TYPE (left) == AOP_ACC)
5204 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5207 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5208 emitcode ("orl", "a,%s",
5209 aopGet (AOP (left), offset, FALSE, FALSE));
5211 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5216 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5217 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5218 freeAsmop (result, NULL, ic, TRUE);
5221 /*-----------------------------------------------------------------*/
5222 /* genXor - code for xclusive or */
5223 /*-----------------------------------------------------------------*/
5225 genXor (iCode * ic, iCode * ifx)
5227 operand *left, *right, *result;
5228 int size, offset = 0;
5229 unsigned long lit = 0L;
5231 D(emitcode ("; genXor",""));
5233 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5234 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5235 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5238 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5240 AOP_TYPE (left), AOP_TYPE (right));
5241 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5243 AOP_SIZE (left), AOP_SIZE (right));
5246 /* if left is a literal & right is not ||
5247 if left needs acc & right does not */
5248 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5249 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5251 operand *tmp = right;
5256 /* if result = right then exchange them */
5257 if (sameRegs (AOP (result), AOP (right)))
5259 operand *tmp = right;
5264 /* if right is bit then exchange them */
5265 if (AOP_TYPE (right) == AOP_CRY &&
5266 AOP_TYPE (left) != AOP_CRY)
5268 operand *tmp = right;
5272 if (AOP_TYPE (right) == AOP_LIT)
5273 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5275 size = AOP_SIZE (result);
5279 if (AOP_TYPE (left) == AOP_CRY)
5281 if (AOP_TYPE (right) == AOP_LIT)
5283 // c = bit & literal;
5286 // lit>>1 != 0 => result = 1
5287 if (AOP_TYPE (result) == AOP_CRY)
5290 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5292 continueIfTrue (ifx);
5295 emitcode ("setb", "c");
5302 // lit == 0, result = left
5303 if (size && sameRegs (AOP (result), AOP (left)))
5305 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5309 // lit == 1, result = not(left)
5310 if (size && sameRegs (AOP (result), AOP (left)))
5312 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5317 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5318 emitcode ("cpl", "c");
5327 symbol *tlbl = newiTempLabel (NULL);
5328 if (AOP_TYPE (right) == AOP_CRY)
5331 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5335 int sizer = AOP_SIZE (right);
5337 // if val>>1 != 0, result = 1
5338 emitcode ("setb", "c");
5341 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5343 // test the msb of the lsb
5344 emitcode ("anl", "a,#0xfe");
5345 emitcode ("jnz", "%05d$", tlbl->key + 100);
5349 emitcode ("rrc", "a");
5351 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5352 emitcode ("cpl", "c");
5353 emitcode ("", "%05d$:", (tlbl->key + 100));
5360 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5361 genIfxJump (ifx, "c");
5365 if (sameRegs (AOP (result), AOP (left)))
5367 /* if left is same as result */
5368 for (; size--; offset++)
5370 if (AOP_TYPE (right) == AOP_LIT)
5372 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5374 else if (IS_AOP_PREG (left))
5376 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5377 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5378 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5381 emitcode ("xrl", "%s,%s",
5382 aopGet (AOP (left), offset, FALSE, TRUE),
5383 aopGet (AOP (right), offset, FALSE, FALSE));
5387 if (AOP_TYPE (left) == AOP_ACC)
5388 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5391 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5392 if (IS_AOP_PREG (left))
5394 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5395 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5398 emitcode ("xrl", "%s,a",
5399 aopGet (AOP (left), offset, FALSE, TRUE));
5406 // left & result in different registers
5407 if (AOP_TYPE (result) == AOP_CRY)
5410 // if(size), result in bit
5411 // if(!size && ifx), conditional oper: if(left ^ right)
5412 symbol *tlbl = newiTempLabel (NULL);
5413 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5415 emitcode ("setb", "c");
5418 if ((AOP_TYPE (right) == AOP_LIT) &&
5419 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5421 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5425 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5426 emitcode ("xrl", "a,%s",
5427 aopGet (AOP (right), offset, FALSE, FALSE));
5429 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5430 emitcode ("xrl", "a,%s",
5431 aopGet (AOP (left), offset, FALSE, FALSE));
5434 emitcode ("jnz", "%05d$", tlbl->key + 100);
5440 emitcode ("", "%05d$:", tlbl->key + 100);
5444 jmpTrueOrFalse (ifx, tlbl);
5447 for (; (size--); offset++)
5450 // result = left & right
5451 if (AOP_TYPE (right) == AOP_LIT)
5453 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5455 aopPut (AOP (result),
5456 aopGet (AOP (left), offset, FALSE, FALSE),
5458 isOperandVolatile (result, FALSE));
5462 // faster than result <- left, anl result,right
5463 // and better if result is SFR
5464 if (AOP_TYPE (left) == AOP_ACC)
5465 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5468 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5469 emitcode ("xrl", "a,%s",
5470 aopGet (AOP (left), offset, FALSE, TRUE));
5472 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5477 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5478 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5479 freeAsmop (result, NULL, ic, TRUE);
5482 /*-----------------------------------------------------------------*/
5483 /* genInline - write the inline code out */
5484 /*-----------------------------------------------------------------*/
5486 genInline (iCode * ic)
5488 char *buffer, *bp, *bp1;
5490 D(emitcode ("; genInline",""));
5492 _G.inLine += (!options.asmpeep);
5494 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5495 strcpy (buffer, IC_INLINE (ic));
5497 /* emit each line as a code */
5522 /* emitcode("",buffer); */
5523 _G.inLine -= (!options.asmpeep);
5526 /*-----------------------------------------------------------------*/
5527 /* genRRC - rotate right with carry */
5528 /*-----------------------------------------------------------------*/
5532 operand *left, *result;
5533 int size, offset = 0;
5536 D(emitcode ("; genRRC",""));
5538 /* rotate right with carry */
5539 left = IC_LEFT (ic);
5540 result = IC_RESULT (ic);
5541 aopOp (left, ic, FALSE);
5542 aopOp (result, ic, FALSE);
5544 /* move it to the result */
5545 size = AOP_SIZE (result);
5547 if (size == 1) { /* special case for 1 byte */
5548 l = aopGet (AOP (left), offset, FALSE, FALSE);
5550 emitcode ("rr", "a");
5556 l = aopGet (AOP (left), offset, FALSE, FALSE);
5558 emitcode ("rrc", "a");
5559 if (AOP_SIZE (result) > 1)
5560 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5562 /* now we need to put the carry into the
5563 highest order byte of the result */
5564 if (AOP_SIZE (result) > 1)
5566 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5569 emitcode ("mov", "acc.7,c");
5571 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5572 freeAsmop (left, NULL, ic, TRUE);
5573 freeAsmop (result, NULL, ic, TRUE);
5576 /*-----------------------------------------------------------------*/
5577 /* genRLC - generate code for rotate left with carry */
5578 /*-----------------------------------------------------------------*/
5582 operand *left, *result;
5583 int size, offset = 0;
5586 D(emitcode ("; genRLC",""));
5588 /* rotate right with carry */
5589 left = IC_LEFT (ic);
5590 result = IC_RESULT (ic);
5591 aopOp (left, ic, FALSE);
5592 aopOp (result, ic, FALSE);
5594 /* move it to the result */
5595 size = AOP_SIZE (result);
5599 l = aopGet (AOP (left), offset, FALSE, FALSE);
5601 if (size == 0) { /* special case for 1 byte */
5605 emitcode ("add", "a,acc");
5606 if (AOP_SIZE (result) > 1)
5607 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5610 l = aopGet (AOP (left), offset, FALSE, FALSE);
5612 emitcode ("rlc", "a");
5613 if (AOP_SIZE (result) > 1)
5614 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5617 /* now we need to put the carry into the
5618 highest order byte of the result */
5619 if (AOP_SIZE (result) > 1)
5621 l = aopGet (AOP (result), 0, FALSE, FALSE);
5624 emitcode ("mov", "acc.0,c");
5626 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5627 freeAsmop (left, NULL, ic, TRUE);
5628 freeAsmop (result, NULL, ic, TRUE);
5631 /*-----------------------------------------------------------------*/
5632 /* genGetHbit - generates code get highest order bit */
5633 /*-----------------------------------------------------------------*/
5635 genGetHbit (iCode * ic)
5637 operand *left, *result;
5639 D(emitcode ("; genGetHbit",""));
5641 left = IC_LEFT (ic);
5642 result = IC_RESULT (ic);
5643 aopOp (left, ic, FALSE);
5644 aopOp (result, ic, FALSE);
5646 /* get the highest order byte into a */
5647 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5648 if (AOP_TYPE (result) == AOP_CRY)
5650 emitcode ("rlc", "a");
5655 emitcode ("rl", "a");
5656 emitcode ("anl", "a,#0x01");
5661 freeAsmop (left, NULL, ic, TRUE);
5662 freeAsmop (result, NULL, ic, TRUE);
5665 /*-----------------------------------------------------------------*/
5666 /* AccRol - rotate left accumulator by known count */
5667 /*-----------------------------------------------------------------*/
5669 AccRol (int shCount)
5671 shCount &= 0x0007; // shCount : 0..7
5678 emitcode ("rl", "a");
5681 emitcode ("rl", "a");
5682 emitcode ("rl", "a");
5685 emitcode ("swap", "a");
5686 emitcode ("rr", "a");
5689 emitcode ("swap", "a");
5692 emitcode ("swap", "a");
5693 emitcode ("rl", "a");
5696 emitcode ("rr", "a");
5697 emitcode ("rr", "a");
5700 emitcode ("rr", "a");
5705 /*-----------------------------------------------------------------*/
5706 /* AccLsh - left shift accumulator by known count */
5707 /*-----------------------------------------------------------------*/
5709 AccLsh (int shCount)
5714 emitcode ("add", "a,acc");
5715 else if (shCount == 2)
5717 emitcode ("add", "a,acc");
5718 emitcode ("add", "a,acc");
5722 /* rotate left accumulator */
5724 /* and kill the lower order bits */
5725 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5730 /*-----------------------------------------------------------------*/
5731 /* AccRsh - right shift accumulator by known count */
5732 /*-----------------------------------------------------------------*/
5734 AccRsh (int shCount)
5741 emitcode ("rrc", "a");
5745 /* rotate right accumulator */
5746 AccRol (8 - shCount);
5747 /* and kill the higher order bits */
5748 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5753 /*-----------------------------------------------------------------*/
5754 /* AccSRsh - signed right shift accumulator by known count */
5755 /*-----------------------------------------------------------------*/
5757 AccSRsh (int shCount)
5764 emitcode ("mov", "c,acc.7");
5765 emitcode ("rrc", "a");
5767 else if (shCount == 2)
5769 emitcode ("mov", "c,acc.7");
5770 emitcode ("rrc", "a");
5771 emitcode ("mov", "c,acc.7");
5772 emitcode ("rrc", "a");
5776 tlbl = newiTempLabel (NULL);
5777 /* rotate right accumulator */
5778 AccRol (8 - shCount);
5779 /* and kill the higher order bits */
5780 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5781 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5782 emitcode ("orl", "a,#0x%02x",
5783 (unsigned char) ~SRMask[shCount]);
5784 emitcode ("", "%05d$:", tlbl->key + 100);
5789 /*-----------------------------------------------------------------*/
5790 /* shiftR1Left2Result - shift right one byte from left to result */
5791 /*-----------------------------------------------------------------*/
5793 shiftR1Left2Result (operand * left, int offl,
5794 operand * result, int offr,
5795 int shCount, int sign)
5797 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5798 /* shift right accumulator */
5803 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5806 /*-----------------------------------------------------------------*/
5807 /* shiftL1Left2Result - shift left one byte from left to result */
5808 /*-----------------------------------------------------------------*/
5810 shiftL1Left2Result (operand * left, int offl,
5811 operand * result, int offr, int shCount)
5814 l = aopGet (AOP (left), offl, FALSE, FALSE);
5816 /* shift left accumulator */
5818 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5821 /*-----------------------------------------------------------------*/
5822 /* movLeft2Result - move byte from left to result */
5823 /*-----------------------------------------------------------------*/
5825 movLeft2Result (operand * left, int offl,
5826 operand * result, int offr, int sign)
5829 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5831 l = aopGet (AOP (left), offl, FALSE, FALSE);
5833 if (*l == '@' && (IS_AOP_PREG (result)))
5835 emitcode ("mov", "a,%s", l);
5836 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5841 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5844 /* MSB sign in acc.7 ! */
5845 if (getDataSize (left) == offl + 1)
5847 emitcode ("mov", "a,%s", l);
5848 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5855 /*-----------------------------------------------------------------*/
5856 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5857 /*-----------------------------------------------------------------*/
5861 emitcode ("rrc", "a");
5862 emitcode ("xch", "a,%s", x);
5863 emitcode ("rrc", "a");
5864 emitcode ("xch", "a,%s", x);
5867 /*-----------------------------------------------------------------*/
5868 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5869 /*-----------------------------------------------------------------*/
5873 emitcode ("xch", "a,%s", x);
5874 emitcode ("rlc", "a");
5875 emitcode ("xch", "a,%s", x);
5876 emitcode ("rlc", "a");
5879 /*-----------------------------------------------------------------*/
5880 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5881 /*-----------------------------------------------------------------*/
5885 emitcode ("xch", "a,%s", x);
5886 emitcode ("add", "a,acc");
5887 emitcode ("xch", "a,%s", x);
5888 emitcode ("rlc", "a");
5891 /*-----------------------------------------------------------------*/
5892 /* AccAXLsh - left shift a:x by known count (0..7) */
5893 /*-----------------------------------------------------------------*/
5895 AccAXLsh (char *x, int shCount)
5910 case 5: // AAAAABBB:CCCCCDDD
5912 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5914 emitcode ("anl", "a,#0x%02x",
5915 SLMask[shCount]); // BBB00000:CCCCCDDD
5917 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5919 AccRol (shCount); // DDDCCCCC:BBB00000
5921 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5923 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5925 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5927 emitcode ("anl", "a,#0x%02x",
5928 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5930 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5932 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5935 case 6: // AAAAAABB:CCCCCCDD
5936 emitcode ("anl", "a,#0x%02x",
5937 SRMask[shCount]); // 000000BB:CCCCCCDD
5938 emitcode ("mov", "c,acc.0"); // c = B
5939 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5941 AccAXRrl1 (x); // BCCCCCCD:D000000B
5942 AccAXRrl1 (x); // BBCCCCCC:DD000000
5944 emitcode("rrc","a");
5945 emitcode("xch","a,%s", x);
5946 emitcode("rrc","a");
5947 emitcode("mov","c,acc.0"); //<< get correct bit
5948 emitcode("xch","a,%s", x);
5950 emitcode("rrc","a");
5951 emitcode("xch","a,%s", x);
5952 emitcode("rrc","a");
5953 emitcode("xch","a,%s", x);
5956 case 7: // a:x <<= 7
5958 emitcode ("anl", "a,#0x%02x",
5959 SRMask[shCount]); // 0000000B:CCCCCCCD
5961 emitcode ("mov", "c,acc.0"); // c = B
5963 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5965 AccAXRrl1 (x); // BCCCCCCC:D0000000
5973 /*-----------------------------------------------------------------*/
5974 /* AccAXRsh - right shift a:x known count (0..7) */
5975 /*-----------------------------------------------------------------*/
5977 AccAXRsh (char *x, int shCount)
5985 AccAXRrl1 (x); // 0->a:x
5990 AccAXRrl1 (x); // 0->a:x
5993 AccAXRrl1 (x); // 0->a:x
5998 case 5: // AAAAABBB:CCCCCDDD = a:x
6000 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6002 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6004 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6006 emitcode ("anl", "a,#0x%02x",
6007 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6009 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6011 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6013 emitcode ("anl", "a,#0x%02x",
6014 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6016 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6018 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6020 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6023 case 6: // AABBBBBB:CCDDDDDD
6025 emitcode ("mov", "c,acc.7");
6026 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6028 emitcode ("mov", "c,acc.7");
6029 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6031 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6033 emitcode ("anl", "a,#0x%02x",
6034 SRMask[shCount]); // 000000AA:BBBBBBCC
6037 case 7: // ABBBBBBB:CDDDDDDD
6039 emitcode ("mov", "c,acc.7"); // c = A
6041 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6043 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6045 emitcode ("anl", "a,#0x%02x",
6046 SRMask[shCount]); // 0000000A:BBBBBBBC
6054 /*-----------------------------------------------------------------*/
6055 /* AccAXRshS - right shift signed a:x known count (0..7) */
6056 /*-----------------------------------------------------------------*/
6058 AccAXRshS (char *x, int shCount)
6066 emitcode ("mov", "c,acc.7");
6067 AccAXRrl1 (x); // s->a:x
6071 emitcode ("mov", "c,acc.7");
6072 AccAXRrl1 (x); // s->a:x
6074 emitcode ("mov", "c,acc.7");
6075 AccAXRrl1 (x); // s->a:x
6080 case 5: // AAAAABBB:CCCCCDDD = a:x
6082 tlbl = newiTempLabel (NULL);
6083 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6085 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6087 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6089 emitcode ("anl", "a,#0x%02x",
6090 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6092 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6094 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6096 emitcode ("anl", "a,#0x%02x",
6097 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6099 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6101 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6103 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6105 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6106 emitcode ("orl", "a,#0x%02x",
6107 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6109 emitcode ("", "%05d$:", tlbl->key + 100);
6110 break; // SSSSAAAA:BBBCCCCC
6112 case 6: // AABBBBBB:CCDDDDDD
6114 tlbl = newiTempLabel (NULL);
6115 emitcode ("mov", "c,acc.7");
6116 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6118 emitcode ("mov", "c,acc.7");
6119 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6121 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6123 emitcode ("anl", "a,#0x%02x",
6124 SRMask[shCount]); // 000000AA:BBBBBBCC
6126 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6127 emitcode ("orl", "a,#0x%02x",
6128 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6130 emitcode ("", "%05d$:", tlbl->key + 100);
6132 case 7: // ABBBBBBB:CDDDDDDD
6134 tlbl = newiTempLabel (NULL);
6135 emitcode ("mov", "c,acc.7"); // c = A
6137 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6139 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6141 emitcode ("anl", "a,#0x%02x",
6142 SRMask[shCount]); // 0000000A:BBBBBBBC
6144 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6145 emitcode ("orl", "a,#0x%02x",
6146 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6148 emitcode ("", "%05d$:", tlbl->key + 100);
6155 /*-----------------------------------------------------------------*/
6156 /* shiftL2Left2Result - shift left two bytes from left to result */
6157 /*-----------------------------------------------------------------*/
6159 shiftL2Left2Result (operand * left, int offl,
6160 operand * result, int offr, int shCount)
6162 if (sameRegs (AOP (result), AOP (left)) &&
6163 ((offl + MSB16) == offr))
6165 /* don't crash result[offr] */
6166 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6167 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6171 movLeft2Result (left, offl, result, offr, 0);
6172 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6174 /* ax << shCount (x = lsb(result)) */
6175 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6176 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6180 /*-----------------------------------------------------------------*/
6181 /* shiftR2Left2Result - shift right two bytes from left to result */
6182 /*-----------------------------------------------------------------*/
6184 shiftR2Left2Result (operand * left, int offl,
6185 operand * result, int offr,
6186 int shCount, int sign)
6188 if (sameRegs (AOP (result), AOP (left)) &&
6189 ((offl + MSB16) == offr))
6191 /* don't crash result[offr] */
6192 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6193 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6197 movLeft2Result (left, offl, result, offr, 0);
6198 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6200 /* a:x >> shCount (x = lsb(result)) */
6202 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6204 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6205 if (getDataSize (result) > 1)
6206 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6209 /*-----------------------------------------------------------------*/
6210 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6211 /*-----------------------------------------------------------------*/
6213 shiftLLeftOrResult (operand * left, int offl,
6214 operand * result, int offr, int shCount)
6216 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6217 /* shift left accumulator */
6219 /* or with result */
6220 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6221 /* back to result */
6222 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6225 /*-----------------------------------------------------------------*/
6226 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6227 /*-----------------------------------------------------------------*/
6229 shiftRLeftOrResult (operand * left, int offl,
6230 operand * result, int offr, int shCount)
6232 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6233 /* shift right accumulator */
6235 /* or with result */
6236 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6237 /* back to result */
6238 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6241 /*-----------------------------------------------------------------*/
6242 /* genlshOne - left shift a one byte quantity by known count */
6243 /*-----------------------------------------------------------------*/
6245 genlshOne (operand * result, operand * left, int shCount)
6247 D(emitcode ("; genlshOne",""));
6249 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6252 /*-----------------------------------------------------------------*/
6253 /* genlshTwo - left shift two bytes by known amount != 0 */
6254 /*-----------------------------------------------------------------*/
6256 genlshTwo (operand * result, operand * left, int shCount)
6260 D(emitcode ("; genlshTwo",""));
6262 size = getDataSize (result);
6264 /* if shCount >= 8 */
6272 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6274 movLeft2Result (left, LSB, result, MSB16, 0);
6276 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6279 /* 1 <= shCount <= 7 */
6283 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6285 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6289 /*-----------------------------------------------------------------*/
6290 /* shiftLLong - shift left one long from left to result */
6291 /* offl = LSB or MSB16 */
6292 /*-----------------------------------------------------------------*/
6294 shiftLLong (operand * left, operand * result, int offr)
6297 int size = AOP_SIZE (result);
6299 if (size >= LSB + offr)
6301 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6303 emitcode ("add", "a,acc");
6304 if (sameRegs (AOP (left), AOP (result)) &&
6305 size >= MSB16 + offr && offr != LSB)
6306 emitcode ("xch", "a,%s",
6307 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6309 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6312 if (size >= MSB16 + offr)
6314 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6316 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6319 emitcode ("rlc", "a");
6320 if (sameRegs (AOP (left), AOP (result)) &&
6321 size >= MSB24 + offr && offr != LSB)
6322 emitcode ("xch", "a,%s",
6323 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6325 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6328 if (size >= MSB24 + offr)
6330 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6332 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6335 emitcode ("rlc", "a");
6336 if (sameRegs (AOP (left), AOP (result)) &&
6337 size >= MSB32 + offr && offr != LSB)
6338 emitcode ("xch", "a,%s",
6339 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6341 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6344 if (size > MSB32 + offr)
6346 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6348 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6351 emitcode ("rlc", "a");
6352 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6355 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6358 /*-----------------------------------------------------------------*/
6359 /* genlshFour - shift four byte by a known amount != 0 */
6360 /*-----------------------------------------------------------------*/
6362 genlshFour (operand * result, operand * left, int shCount)
6366 D(emitcode ("; genlshFour",""));
6368 size = AOP_SIZE (result);
6370 /* if shifting more that 3 bytes */
6375 /* lowest order of left goes to the highest
6376 order of the destination */
6377 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6379 movLeft2Result (left, LSB, result, MSB32, 0);
6380 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6381 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6382 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6386 /* more than two bytes */
6387 else if (shCount >= 16)
6389 /* lower order two bytes goes to higher order two bytes */
6391 /* if some more remaining */
6393 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6396 movLeft2Result (left, MSB16, result, MSB32, 0);
6397 movLeft2Result (left, LSB, result, MSB24, 0);
6399 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6400 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6404 /* if more than 1 byte */
6405 else if (shCount >= 8)
6407 /* lower order three bytes goes to higher order three bytes */
6412 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6414 movLeft2Result (left, LSB, result, MSB16, 0);
6420 movLeft2Result (left, MSB24, result, MSB32, 0);
6421 movLeft2Result (left, MSB16, result, MSB24, 0);
6422 movLeft2Result (left, LSB, result, MSB16, 0);
6423 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6425 else if (shCount == 1)
6426 shiftLLong (left, result, MSB16);
6429 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6430 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6431 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6432 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6437 /* 1 <= shCount <= 7 */
6438 else if (shCount <= 2)
6440 shiftLLong (left, result, LSB);
6442 shiftLLong (result, result, LSB);
6444 /* 3 <= shCount <= 7, optimize */
6447 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6448 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6449 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6453 /*-----------------------------------------------------------------*/
6454 /* genLeftShiftLiteral - left shifting by known count */
6455 /*-----------------------------------------------------------------*/
6457 genLeftShiftLiteral (operand * left,
6462 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6465 D(emitcode ("; genLeftShiftLiteral",""));
6467 freeAsmop (right, NULL, ic, TRUE);
6469 aopOp (left, ic, FALSE);
6470 aopOp (result, ic, FALSE);
6472 size = getSize (operandType (result));
6475 emitcode ("; shift left ", "result %d, left %d", size,
6479 /* I suppose that the left size >= result size */
6484 movLeft2Result (left, size, result, size, 0);
6488 else if (shCount >= (size * 8))
6490 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6496 genlshOne (result, left, shCount);
6500 genlshTwo (result, left, shCount);
6504 genlshFour (result, left, shCount);
6507 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6508 "*** ack! mystery literal shift!\n");
6512 freeAsmop (left, NULL, ic, TRUE);
6513 freeAsmop (result, NULL, ic, TRUE);
6516 /*-----------------------------------------------------------------*/
6517 /* genLeftShift - generates code for left shifting */
6518 /*-----------------------------------------------------------------*/
6520 genLeftShift (iCode * ic)
6522 operand *left, *right, *result;
6525 symbol *tlbl, *tlbl1;
6527 D(emitcode ("; genLeftShift",""));
6529 right = IC_RIGHT (ic);
6530 left = IC_LEFT (ic);
6531 result = IC_RESULT (ic);
6533 aopOp (right, ic, FALSE);
6535 /* if the shift count is known then do it
6536 as efficiently as possible */
6537 if (AOP_TYPE (right) == AOP_LIT)
6539 genLeftShiftLiteral (left, right, result, ic);
6543 /* shift count is unknown then we have to form
6544 a loop get the loop count in B : Note: we take
6545 only the lower order byte since shifting
6546 more that 32 bits make no sense anyway, ( the
6547 largest size of an object can be only 32 bits ) */
6549 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6550 emitcode ("inc", "b");
6551 freeAsmop (right, NULL, ic, TRUE);
6552 aopOp (left, ic, FALSE);
6553 aopOp (result, ic, FALSE);
6555 /* now move the left to the result if they are not the
6557 if (!sameRegs (AOP (left), AOP (result)) &&
6558 AOP_SIZE (result) > 1)
6561 size = AOP_SIZE (result);
6565 l = aopGet (AOP (left), offset, FALSE, TRUE);
6566 if (*l == '@' && (IS_AOP_PREG (result)))
6569 emitcode ("mov", "a,%s", l);
6570 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6573 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6578 tlbl = newiTempLabel (NULL);
6579 size = AOP_SIZE (result);
6581 tlbl1 = newiTempLabel (NULL);
6583 /* if it is only one byte then */
6586 symbol *tlbl1 = newiTempLabel (NULL);
6588 l = aopGet (AOP (left), 0, FALSE, FALSE);
6590 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6591 emitcode ("", "%05d$:", tlbl->key + 100);
6592 emitcode ("add", "a,acc");
6593 emitcode ("", "%05d$:", tlbl1->key + 100);
6594 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6595 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6599 reAdjustPreg (AOP (result));
6601 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6602 emitcode ("", "%05d$:", tlbl->key + 100);
6603 l = aopGet (AOP (result), offset, FALSE, FALSE);
6605 emitcode ("add", "a,acc");
6606 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6609 l = aopGet (AOP (result), offset, FALSE, FALSE);
6611 emitcode ("rlc", "a");
6612 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6614 reAdjustPreg (AOP (result));
6616 emitcode ("", "%05d$:", tlbl1->key + 100);
6617 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6619 freeAsmop (left, NULL, ic, TRUE);
6620 freeAsmop (result, NULL, ic, TRUE);
6623 /*-----------------------------------------------------------------*/
6624 /* genrshOne - right shift a one byte quantity by known count */
6625 /*-----------------------------------------------------------------*/
6627 genrshOne (operand * result, operand * left,
6628 int shCount, int sign)
6630 D(emitcode ("; genrshOne",""));
6632 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6635 /*-----------------------------------------------------------------*/
6636 /* genrshTwo - right shift two bytes by known amount != 0 */
6637 /*-----------------------------------------------------------------*/
6639 genrshTwo (operand * result, operand * left,
6640 int shCount, int sign)
6642 D(emitcode ("; genrshTwo",""));
6644 /* if shCount >= 8 */
6649 shiftR1Left2Result (left, MSB16, result, LSB,
6652 movLeft2Result (left, MSB16, result, LSB, sign);
6653 addSign (result, MSB16, sign);
6656 /* 1 <= shCount <= 7 */
6658 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6661 /*-----------------------------------------------------------------*/
6662 /* shiftRLong - shift right one long from left to result */
6663 /* offl = LSB or MSB16 */
6664 /*-----------------------------------------------------------------*/
6666 shiftRLong (operand * left, int offl,
6667 operand * result, int sign)
6669 int isSameRegs=sameRegs(AOP(left),AOP(result));
6671 if (isSameRegs && offl>1) {
6672 // we are in big trouble, but this shouldn't happen
6673 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6676 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6681 emitcode ("rlc", "a");
6682 emitcode ("subb", "a,acc");
6684 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6686 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6687 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6690 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6695 emitcode ("clr", "c");
6697 emitcode ("mov", "c,acc.7");
6700 emitcode ("rrc", "a");
6702 if (isSameRegs && offl==MSB16) {
6703 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6705 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6706 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6709 emitcode ("rrc", "a");
6710 if (isSameRegs && offl==1) {
6711 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6713 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6714 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6716 emitcode ("rrc", "a");
6717 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6721 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6722 emitcode ("rrc", "a");
6723 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6727 /*-----------------------------------------------------------------*/
6728 /* genrshFour - shift four byte by a known amount != 0 */
6729 /*-----------------------------------------------------------------*/
6731 genrshFour (operand * result, operand * left,
6732 int shCount, int sign)
6734 D(emitcode ("; genrshFour",""));
6736 /* if shifting more that 3 bytes */
6741 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6743 movLeft2Result (left, MSB32, result, LSB, sign);
6744 addSign (result, MSB16, sign);
6746 else if (shCount >= 16)
6750 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6753 movLeft2Result (left, MSB24, result, LSB, 0);
6754 movLeft2Result (left, MSB32, result, MSB16, sign);
6756 addSign (result, MSB24, sign);
6758 else if (shCount >= 8)
6762 shiftRLong (left, MSB16, result, sign);
6763 else if (shCount == 0)
6765 movLeft2Result (left, MSB16, result, LSB, 0);
6766 movLeft2Result (left, MSB24, result, MSB16, 0);
6767 movLeft2Result (left, MSB32, result, MSB24, sign);
6768 addSign (result, MSB32, sign);
6772 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6773 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6774 /* the last shift is signed */
6775 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6776 addSign (result, MSB32, sign);
6780 { /* 1 <= shCount <= 7 */
6783 shiftRLong (left, LSB, result, sign);
6785 shiftRLong (result, LSB, result, sign);
6789 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6790 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6791 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6796 /*-----------------------------------------------------------------*/
6797 /* genRightShiftLiteral - right shifting by known count */
6798 /*-----------------------------------------------------------------*/
6800 genRightShiftLiteral (operand * left,
6806 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6809 D(emitcode ("; genRightShiftLiteral",""));
6811 freeAsmop (right, NULL, ic, TRUE);
6813 aopOp (left, ic, FALSE);
6814 aopOp (result, ic, FALSE);
6817 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6821 size = getDataSize (left);
6822 /* test the LEFT size !!! */
6824 /* I suppose that the left size >= result size */
6827 size = getDataSize (result);
6829 movLeft2Result (left, size, result, size, 0);
6832 else if (shCount >= (size * 8))
6835 /* get sign in acc.7 */
6836 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6838 addSign (result, LSB, sign);
6845 genrshOne (result, left, shCount, sign);
6849 genrshTwo (result, left, shCount, sign);
6853 genrshFour (result, left, shCount, sign);
6859 freeAsmop (left, NULL, ic, TRUE);
6860 freeAsmop (result, NULL, ic, TRUE);
6863 /*-----------------------------------------------------------------*/
6864 /* genSignedRightShift - right shift of signed number */
6865 /*-----------------------------------------------------------------*/
6867 genSignedRightShift (iCode * ic)
6869 operand *right, *left, *result;
6872 symbol *tlbl, *tlbl1;
6874 D(emitcode ("; genSignedRightShift",""));
6876 /* we do it the hard way put the shift count in b
6877 and loop thru preserving the sign */
6879 right = IC_RIGHT (ic);
6880 left = IC_LEFT (ic);
6881 result = IC_RESULT (ic);
6883 aopOp (right, ic, FALSE);
6886 if (AOP_TYPE (right) == AOP_LIT)
6888 genRightShiftLiteral (left, right, result, ic, 1);
6891 /* shift count is unknown then we have to form
6892 a loop get the loop count in B : Note: we take
6893 only the lower order byte since shifting
6894 more that 32 bits make no sense anyway, ( the
6895 largest size of an object can be only 32 bits ) */
6897 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6898 emitcode ("inc", "b");
6899 freeAsmop (right, NULL, ic, TRUE);
6900 aopOp (left, ic, FALSE);
6901 aopOp (result, ic, FALSE);
6903 /* now move the left to the result if they are not the
6905 if (!sameRegs (AOP (left), AOP (result)) &&
6906 AOP_SIZE (result) > 1)
6909 size = AOP_SIZE (result);
6913 l = aopGet (AOP (left), offset, FALSE, TRUE);
6914 if (*l == '@' && IS_AOP_PREG (result))
6917 emitcode ("mov", "a,%s", l);
6918 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6921 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6926 /* mov the highest order bit to OVR */
6927 tlbl = newiTempLabel (NULL);
6928 tlbl1 = newiTempLabel (NULL);
6930 size = AOP_SIZE (result);
6932 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6933 emitcode ("rlc", "a");
6934 emitcode ("mov", "ov,c");
6935 /* if it is only one byte then */
6938 l = aopGet (AOP (left), 0, FALSE, FALSE);
6940 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6941 emitcode ("", "%05d$:", tlbl->key + 100);
6942 emitcode ("mov", "c,ov");
6943 emitcode ("rrc", "a");
6944 emitcode ("", "%05d$:", tlbl1->key + 100);
6945 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6946 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6950 reAdjustPreg (AOP (result));
6951 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6952 emitcode ("", "%05d$:", tlbl->key + 100);
6953 emitcode ("mov", "c,ov");
6956 l = aopGet (AOP (result), offset, FALSE, FALSE);
6958 emitcode ("rrc", "a");
6959 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6961 reAdjustPreg (AOP (result));
6962 emitcode ("", "%05d$:", tlbl1->key + 100);
6963 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6966 freeAsmop (left, NULL, ic, TRUE);
6967 freeAsmop (result, NULL, ic, TRUE);
6970 /*-----------------------------------------------------------------*/
6971 /* genRightShift - generate code for right shifting */
6972 /*-----------------------------------------------------------------*/
6974 genRightShift (iCode * ic)
6976 operand *right, *left, *result;
6980 symbol *tlbl, *tlbl1;
6982 D(emitcode ("; genRightShift",""));
6984 /* if signed then we do it the hard way preserve the
6985 sign bit moving it inwards */
6986 retype = getSpec (operandType (IC_RESULT (ic)));
6988 if (!SPEC_USIGN (retype))
6990 genSignedRightShift (ic);
6994 /* signed & unsigned types are treated the same : i.e. the
6995 signed is NOT propagated inwards : quoting from the
6996 ANSI - standard : "for E1 >> E2, is equivalent to division
6997 by 2**E2 if unsigned or if it has a non-negative value,
6998 otherwise the result is implementation defined ", MY definition
6999 is that the sign does not get propagated */
7001 right = IC_RIGHT (ic);
7002 left = IC_LEFT (ic);
7003 result = IC_RESULT (ic);
7005 aopOp (right, ic, FALSE);
7007 /* if the shift count is known then do it
7008 as efficiently as possible */
7009 if (AOP_TYPE (right) == AOP_LIT)
7011 genRightShiftLiteral (left, right, result, ic, 0);
7015 /* shift count is unknown then we have to form
7016 a loop get the loop count in B : Note: we take
7017 only the lower order byte since shifting
7018 more that 32 bits make no sense anyway, ( the
7019 largest size of an object can be only 32 bits ) */
7021 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7022 emitcode ("inc", "b");
7023 freeAsmop (right, NULL, ic, TRUE);
7024 aopOp (left, ic, FALSE);
7025 aopOp (result, ic, FALSE);
7027 /* now move the left to the result if they are not the
7029 if (!sameRegs (AOP (left), AOP (result)) &&
7030 AOP_SIZE (result) > 1)
7033 size = AOP_SIZE (result);
7037 l = aopGet (AOP (left), offset, FALSE, TRUE);
7038 if (*l == '@' && IS_AOP_PREG (result))
7041 emitcode ("mov", "a,%s", l);
7042 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7045 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7050 tlbl = newiTempLabel (NULL);
7051 tlbl1 = newiTempLabel (NULL);
7052 size = AOP_SIZE (result);
7055 /* if it is only one byte then */
7058 l = aopGet (AOP (left), 0, FALSE, FALSE);
7060 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7061 emitcode ("", "%05d$:", tlbl->key + 100);
7063 emitcode ("rrc", "a");
7064 emitcode ("", "%05d$:", tlbl1->key + 100);
7065 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7066 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7070 reAdjustPreg (AOP (result));
7071 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7072 emitcode ("", "%05d$:", tlbl->key + 100);
7076 l = aopGet (AOP (result), offset, FALSE, FALSE);
7078 emitcode ("rrc", "a");
7079 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7081 reAdjustPreg (AOP (result));
7083 emitcode ("", "%05d$:", tlbl1->key + 100);
7084 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7087 freeAsmop (left, NULL, ic, TRUE);
7088 freeAsmop (result, NULL, ic, TRUE);
7091 /*-----------------------------------------------------------------*/
7092 /* emitPtrByteGet - emits code to get a byte into A through a */
7093 /* pointer register (R0, R1, or DPTR). The */
7094 /* original value of A can be preserved in B. */
7095 /*-----------------------------------------------------------------*/
7097 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7104 emitcode ("mov", "b,a");
7105 emitcode ("mov", "a,@%s", rname);
7110 emitcode ("mov", "b,a");
7111 emitcode ("movx", "a,@%s", rname);
7116 emitcode ("mov", "b,a");
7117 emitcode ("movx", "a,@dptr");
7122 emitcode ("mov", "b,a");
7123 emitcode ("clr", "a");
7124 emitcode ("movc", "a,@a+dptr");
7130 emitcode ("push", "b");
7131 emitcode ("push", "acc");
7133 emitcode ("lcall", "__gptrget");
7135 emitcode ("pop", "b");
7140 /*-----------------------------------------------------------------*/
7141 /* emitPtrByteSet - emits code to set a byte from src through a */
7142 /* pointer register (R0, R1, or DPTR). */
7143 /*-----------------------------------------------------------------*/
7145 emitPtrByteSet (char *rname, int p_type, char *src)
7154 emitcode ("mov", "@%s,a", rname);
7157 emitcode ("mov", "@%s,%s", rname, src);
7162 emitcode ("movx", "@%s,a", rname);
7167 emitcode ("movx", "@dptr,a");
7172 emitcode ("lcall", "__gptrput");
7177 /*-----------------------------------------------------------------*/
7178 /* genUnpackBits - generates code for unpacking bits */
7179 /*-----------------------------------------------------------------*/
7181 genUnpackBits (operand * result, char *rname, int ptype)
7183 int offset = 0; /* result byte offset */
7184 int rsize; /* result size */
7185 int rlen = 0; /* remaining bitfield length */
7186 sym_link *etype; /* bitfield type information */
7187 int blen; /* bitfield length */
7188 int bstr; /* bitfield starting bit within byte */
7190 D(emitcode ("; genUnpackBits",""));
7192 etype = getSpec (operandType (result));
7193 rsize = getSize (operandType (result));
7194 blen = SPEC_BLEN (etype);
7195 bstr = SPEC_BSTR (etype);
7197 /* If the bitfield length is less than a byte */
7200 emitPtrByteGet (rname, ptype, FALSE);
7202 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7203 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7207 /* Bit field did not fit in a byte. Copy all
7208 but the partial byte at the end. */
7209 for (rlen=blen;rlen>=8;rlen-=8)
7211 emitPtrByteGet (rname, ptype, FALSE);
7212 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7214 emitcode ("inc", "%s", rname);
7217 /* Handle the partial byte at the end */
7220 emitPtrByteGet (rname, ptype, FALSE);
7221 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7222 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7230 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7235 /*-----------------------------------------------------------------*/
7236 /* genDataPointerGet - generates code when ptr offset is known */
7237 /*-----------------------------------------------------------------*/
7239 genDataPointerGet (operand * left,
7245 int size, offset = 0;
7247 D(emitcode ("; genDataPointerGet",""));
7249 aopOp (result, ic, TRUE);
7251 /* get the string representation of the name */
7252 l = aopGet (AOP (left), 0, FALSE, TRUE);
7253 size = AOP_SIZE (result);
7257 sprintf (buffer, "(%s + %d)", l + 1, offset);
7259 sprintf (buffer, "%s", l + 1);
7260 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7263 freeAsmop (left, NULL, ic, TRUE);
7264 freeAsmop (result, NULL, ic, TRUE);
7267 /*-----------------------------------------------------------------*/
7268 /* genNearPointerGet - emitcode for near pointer fetch */
7269 /*-----------------------------------------------------------------*/
7271 genNearPointerGet (operand * left,
7279 sym_link *rtype, *retype;
7280 sym_link *ltype = operandType (left);
7283 D(emitcode ("; genNearPointerGet",""));
7285 rtype = operandType (result);
7286 retype = getSpec (rtype);
7288 aopOp (left, ic, FALSE);
7290 /* if left is rematerialisable and
7291 result is not bit variable type and
7292 the left is pointer to data space i.e
7293 lower 128 bytes of space */
7294 if (AOP_TYPE (left) == AOP_IMMD &&
7295 !IS_BITVAR (retype) &&
7296 DCL_TYPE (ltype) == POINTER)
7298 genDataPointerGet (left, result, ic);
7302 /* if the value is already in a pointer register
7303 then don't need anything more */
7304 if (!AOP_INPREG (AOP (left)))
7306 /* otherwise get a free pointer register */
7308 preg = getFreePtr (ic, &aop, FALSE);
7309 emitcode ("mov", "%s,%s",
7311 aopGet (AOP (left), 0, FALSE, TRUE));
7315 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7317 //aopOp (result, ic, FALSE);
7318 aopOp (result, ic, result?TRUE:FALSE);
7320 /* if bitfield then unpack the bits */
7321 if (IS_BITVAR (retype))
7322 genUnpackBits (result, rname, POINTER);
7325 /* we have can just get the values */
7326 int size = AOP_SIZE (result);
7331 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7334 emitcode ("mov", "a,@%s", rname);
7335 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7339 sprintf (buffer, "@%s", rname);
7340 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7344 emitcode ("inc", "%s", rname);
7348 /* now some housekeeping stuff */
7349 if (aop) /* we had to allocate for this iCode */
7351 if (pi) { /* post increment present */
7352 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7354 freeAsmop (NULL, aop, ic, TRUE);
7358 /* we did not allocate which means left
7359 already in a pointer register, then
7360 if size > 0 && this could be used again
7361 we have to point it back to where it
7363 if ((AOP_SIZE (result) > 1 &&
7364 !OP_SYMBOL (left)->remat &&
7365 (OP_SYMBOL (left)->liveTo > ic->seq ||
7369 int size = AOP_SIZE (result) - 1;
7371 emitcode ("dec", "%s", rname);
7376 freeAsmop (left, NULL, ic, TRUE);
7377 freeAsmop (result, NULL, ic, TRUE);
7378 if (pi) pi->generated = 1;
7381 /*-----------------------------------------------------------------*/
7382 /* genPagedPointerGet - emitcode for paged pointer fetch */
7383 /*-----------------------------------------------------------------*/
7385 genPagedPointerGet (operand * left,
7393 sym_link *rtype, *retype;
7395 D(emitcode ("; genPagedPointerGet",""));
7397 rtype = operandType (result);
7398 retype = getSpec (rtype);
7400 aopOp (left, ic, FALSE);
7402 /* if the value is already in a pointer register
7403 then don't need anything more */
7404 if (!AOP_INPREG (AOP (left)))
7406 /* otherwise get a free pointer register */
7408 preg = getFreePtr (ic, &aop, FALSE);
7409 emitcode ("mov", "%s,%s",
7411 aopGet (AOP (left), 0, FALSE, TRUE));
7415 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7417 aopOp (result, ic, FALSE);
7419 /* if bitfield then unpack the bits */
7420 if (IS_BITVAR (retype))
7421 genUnpackBits (result, rname, PPOINTER);
7424 /* we have can just get the values */
7425 int size = AOP_SIZE (result);
7431 emitcode ("movx", "a,@%s", rname);
7432 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7437 emitcode ("inc", "%s", rname);
7441 /* now some housekeeping stuff */
7442 if (aop) /* we had to allocate for this iCode */
7444 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7445 freeAsmop (NULL, aop, ic, TRUE);
7449 /* we did not allocate which means left
7450 already in a pointer register, then
7451 if size > 0 && this could be used again
7452 we have to point it back to where it
7454 if ((AOP_SIZE (result) > 1 &&
7455 !OP_SYMBOL (left)->remat &&
7456 (OP_SYMBOL (left)->liveTo > ic->seq ||
7460 int size = AOP_SIZE (result) - 1;
7462 emitcode ("dec", "%s", rname);
7467 freeAsmop (left, NULL, ic, TRUE);
7468 freeAsmop (result, NULL, ic, TRUE);
7469 if (pi) pi->generated = 1;
7473 /*-----------------------------------------------------------------*/
7474 /* genFarPointerGet - gget value from far space */
7475 /*-----------------------------------------------------------------*/
7477 genFarPointerGet (operand * left,
7478 operand * result, iCode * ic, iCode * pi)
7481 sym_link *retype = getSpec (operandType (result));
7483 D(emitcode ("; genFarPointerGet",""));
7485 aopOp (left, ic, FALSE);
7487 /* if the operand is already in dptr
7488 then we do nothing else we move the value to dptr */
7489 if (AOP_TYPE (left) != AOP_STR)
7491 /* if this is remateriazable */
7492 if (AOP_TYPE (left) == AOP_IMMD)
7493 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7495 { /* we need to get it byte by byte */
7496 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7497 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7500 /* so dptr know contains the address */
7501 aopOp (result, ic, FALSE);
7503 /* if bit then unpack */
7504 if (IS_BITVAR (retype))
7505 genUnpackBits (result, "dptr", FPOINTER);
7508 size = AOP_SIZE (result);
7513 emitcode ("movx", "a,@dptr");
7514 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7516 emitcode ("inc", "dptr");
7520 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7521 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7522 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7525 freeAsmop (left, NULL, ic, TRUE);
7526 freeAsmop (result, NULL, ic, TRUE);
7529 /*-----------------------------------------------------------------*/
7530 /* genCodePointerGet - gget value from code space */
7531 /*-----------------------------------------------------------------*/
7533 genCodePointerGet (operand * left,
7534 operand * result, iCode * ic, iCode *pi)
7537 sym_link *retype = getSpec (operandType (result));
7539 D(emitcode ("; genCodePointerGet",""));
7541 aopOp (left, ic, FALSE);
7543 /* if the operand is already in dptr
7544 then we do nothing else we move the value to dptr */
7545 if (AOP_TYPE (left) != AOP_STR)
7547 /* if this is remateriazable */
7548 if (AOP_TYPE (left) == AOP_IMMD)
7549 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7551 { /* we need to get it byte by byte */
7552 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7553 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7556 /* so dptr know contains the address */
7557 aopOp (result, ic, FALSE);
7559 /* if bit then unpack */
7560 if (IS_BITVAR (retype))
7561 genUnpackBits (result, "dptr", CPOINTER);
7564 size = AOP_SIZE (result);
7571 emitcode ("clr", "a");
7572 emitcode ("movc", "a,@a+dptr");
7573 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7574 emitcode ("inc", "dptr");
7578 emitcode ("mov", "a,#0x%02x", offset);
7579 emitcode ("movc", "a,@a+dptr");
7580 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7585 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7586 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7587 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7590 freeAsmop (left, NULL, ic, TRUE);
7591 freeAsmop (result, NULL, ic, TRUE);
7594 /*-----------------------------------------------------------------*/
7595 /* genGenPointerGet - gget value from generic pointer space */
7596 /*-----------------------------------------------------------------*/
7598 genGenPointerGet (operand * left,
7599 operand * result, iCode * ic, iCode *pi)
7602 sym_link *retype = getSpec (operandType (result));
7604 D(emitcode ("; genGenPointerGet",""));
7606 aopOp (left, ic, FALSE);
7608 /* if the operand is already in dptr
7609 then we do nothing else we move the value to dptr */
7610 if (AOP_TYPE (left) != AOP_STR)
7612 /* if this is remateriazable */
7613 if (AOP_TYPE (left) == AOP_IMMD)
7615 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7616 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7617 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7619 emitcode ("mov", "b,#%d", pointerCode (retype));
7622 { /* we need to get it byte by byte */
7623 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7624 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7625 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7628 /* so dptr know contains the address */
7629 aopOp (result, ic, FALSE);
7631 /* if bit then unpack */
7632 if (IS_BITVAR (retype))
7633 genUnpackBits (result, "dptr", GPOINTER);
7636 size = AOP_SIZE (result);
7641 emitcode ("lcall", "__gptrget");
7642 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7644 emitcode ("inc", "dptr");
7648 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7649 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7650 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7653 freeAsmop (left, NULL, ic, TRUE);
7654 freeAsmop (result, NULL, ic, TRUE);
7657 /*-----------------------------------------------------------------*/
7658 /* genPointerGet - generate code for pointer get */
7659 /*-----------------------------------------------------------------*/
7661 genPointerGet (iCode * ic, iCode *pi)
7663 operand *left, *result;
7664 sym_link *type, *etype;
7667 D(emitcode ("; genPointerGet",""));
7669 left = IC_LEFT (ic);
7670 result = IC_RESULT (ic);
7672 /* depending on the type of pointer we need to
7673 move it to the correct pointer register */
7674 type = operandType (left);
7675 etype = getSpec (type);
7676 /* if left is of type of pointer then it is simple */
7677 if (IS_PTR (type) && !IS_FUNC (type->next))
7678 p_type = DCL_TYPE (type);
7681 /* we have to go by the storage class */
7682 p_type = PTR_TYPE (SPEC_OCLS (etype));
7685 /* special case when cast remat */
7686 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7687 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7688 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7689 type = operandType (left);
7690 p_type = DCL_TYPE (type);
7692 /* now that we have the pointer type we assign
7693 the pointer values */
7699 genNearPointerGet (left, result, ic, pi);
7703 genPagedPointerGet (left, result, ic, pi);
7707 genFarPointerGet (left, result, ic, pi);
7711 genCodePointerGet (left, result, ic, pi);
7715 genGenPointerGet (left, result, ic, pi);
7723 /*-----------------------------------------------------------------*/
7724 /* genPackBits - generates code for packed bit storage */
7725 /*-----------------------------------------------------------------*/
7727 genPackBits (sym_link * etype,
7729 char *rname, int p_type)
7731 int offset = 0; /* source byte offset */
7732 int rlen = 0; /* remaining bitfield length */
7733 int blen; /* bitfield length */
7734 int bstr; /* bitfield starting bit within byte */
7735 int litval; /* source literal value (if AOP_LIT) */
7736 unsigned char mask; /* bitmask within current byte */
7738 D(emitcode ("; genPackBits",""));
7740 blen = SPEC_BLEN (etype);
7741 bstr = SPEC_BSTR (etype);
7743 /* If the bitfield length is less than a byte */
7746 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7747 (unsigned char) (0xFF >> (8 - bstr)));
7749 if (AOP_TYPE (right) == AOP_LIT)
7751 /* Case with a bitfield length <8 and literal source
7753 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7755 litval &= (~mask) & 0xff;
7756 emitPtrByteGet (rname, p_type, FALSE);
7757 if ((mask|litval)!=0xff)
7758 emitcode ("anl","a,#0x%02x", mask);
7760 emitcode ("orl","a,#0x%02x", litval);
7764 if ((blen==1) && (p_type!=GPOINTER))
7766 /* Case with a bitfield length == 1 and no generic pointer
7768 if (AOP_TYPE (right) == AOP_CRY)
7769 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7772 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7773 emitcode ("rrc","a");
7775 emitPtrByteGet (rname, p_type, FALSE);
7776 emitcode ("mov","acc.%d,c",bstr);
7780 /* Case with a bitfield length < 8 and arbitrary source
7782 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7783 /* shift and mask source value */
7785 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7787 /* transfer A to B and get next byte */
7788 emitPtrByteGet (rname, p_type, TRUE);
7790 emitcode ("anl", "a,#0x%02x", mask);
7791 emitcode ("orl", "a,b");
7792 if (p_type == GPOINTER)
7793 emitcode ("pop", "b");
7797 emitPtrByteSet (rname, p_type, "a");
7801 /* Bit length is greater than 7 bits. In this case, copy */
7802 /* all except the partial byte at the end */
7803 for (rlen=blen;rlen>=8;rlen-=8)
7805 emitPtrByteSet (rname, p_type,
7806 aopGet (AOP (right), offset++, FALSE, TRUE) );
7808 emitcode ("inc", "%s", rname);
7811 /* If there was a partial byte at the end */
7814 mask = (((unsigned char) -1 << rlen) & 0xff);
7816 if (AOP_TYPE (right) == AOP_LIT)
7818 /* Case with partial byte and literal source
7820 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7821 litval >>= (blen-rlen);
7822 litval &= (~mask) & 0xff;
7823 emitPtrByteGet (rname, p_type, FALSE);
7824 if ((mask|litval)!=0xff)
7825 emitcode ("anl","a,#0x%02x", mask);
7827 emitcode ("orl","a,#0x%02x", litval);
7831 /* Case with partial byte and arbitrary source
7833 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7834 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7836 /* transfer A to B and get next byte */
7837 emitPtrByteGet (rname, p_type, TRUE);
7839 emitcode ("anl", "a,#0x%02x", mask);
7840 emitcode ("orl", "a,b");
7841 if (p_type == GPOINTER)
7842 emitcode ("pop", "b");
7844 emitPtrByteSet (rname, p_type, "a");
7850 /*-----------------------------------------------------------------*/
7851 /* genDataPointerSet - remat pointer to data space */
7852 /*-----------------------------------------------------------------*/
7854 genDataPointerSet (operand * right,
7858 int size, offset = 0;
7859 char *l, buffer[256];
7861 D(emitcode ("; genDataPointerSet",""));
7863 aopOp (right, ic, FALSE);
7865 l = aopGet (AOP (result), 0, FALSE, TRUE);
7866 size = AOP_SIZE (right);
7870 sprintf (buffer, "(%s + %d)", l + 1, offset);
7872 sprintf (buffer, "%s", l + 1);
7873 emitcode ("mov", "%s,%s", buffer,
7874 aopGet (AOP (right), offset++, FALSE, FALSE));
7877 freeAsmop (right, NULL, ic, TRUE);
7878 freeAsmop (result, NULL, ic, TRUE);
7881 /*-----------------------------------------------------------------*/
7882 /* genNearPointerSet - emitcode for near pointer put */
7883 /*-----------------------------------------------------------------*/
7885 genNearPointerSet (operand * right,
7893 sym_link *retype, *letype;
7894 sym_link *ptype = operandType (result);
7896 D(emitcode ("; genNearPointerSet",""));
7898 retype = getSpec (operandType (right));
7899 letype = getSpec (ptype);
7900 aopOp (result, ic, FALSE);
7902 /* if the result is rematerializable &
7903 in data space & not a bit variable */
7904 if (AOP_TYPE (result) == AOP_IMMD &&
7905 DCL_TYPE (ptype) == POINTER &&
7906 !IS_BITVAR (retype) &&
7907 !IS_BITVAR (letype))
7909 genDataPointerSet (right, result, ic);
7913 /* if the value is already in a pointer register
7914 then don't need anything more */
7915 if (!AOP_INPREG (AOP (result)))
7918 //AOP_TYPE (result) == AOP_STK
7922 // Aha, it is a pointer, just in disguise.
7923 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7926 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7927 __FILE__, __LINE__);
7932 rname++; // skip the '@'.
7937 /* otherwise get a free pointer register */
7939 preg = getFreePtr (ic, &aop, FALSE);
7940 emitcode ("mov", "%s,%s",
7942 aopGet (AOP (result), 0, FALSE, TRUE));
7948 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7951 aopOp (right, ic, FALSE);
7953 /* if bitfield then unpack the bits */
7954 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7955 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7958 /* we have can just get the values */
7959 int size = AOP_SIZE (right);
7964 l = aopGet (AOP (right), offset, FALSE, TRUE);
7968 emitcode ("mov", "@%s,a", rname);
7971 emitcode ("mov", "@%s,%s", rname, l);
7973 emitcode ("inc", "%s", rname);
7978 /* now some housekeeping stuff */
7979 if (aop) /* we had to allocate for this iCode */
7982 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
7983 freeAsmop (NULL, aop, ic, TRUE);
7987 /* we did not allocate which means left
7988 already in a pointer register, then
7989 if size > 0 && this could be used again
7990 we have to point it back to where it
7992 if ((AOP_SIZE (right) > 1 &&
7993 !OP_SYMBOL (result)->remat &&
7994 (OP_SYMBOL (result)->liveTo > ic->seq ||
7998 int size = AOP_SIZE (right) - 1;
8000 emitcode ("dec", "%s", rname);
8005 if (pi) pi->generated = 1;
8006 freeAsmop (result, NULL, ic, TRUE);
8007 freeAsmop (right, NULL, ic, TRUE);
8010 /*-----------------------------------------------------------------*/
8011 /* genPagedPointerSet - emitcode for Paged pointer put */
8012 /*-----------------------------------------------------------------*/
8014 genPagedPointerSet (operand * right,
8022 sym_link *retype, *letype;
8024 D(emitcode ("; genPagedPointerSet",""));
8026 retype = getSpec (operandType (right));
8027 letype = getSpec (operandType (result));
8029 aopOp (result, ic, FALSE);
8031 /* if the value is already in a pointer register
8032 then don't need anything more */
8033 if (!AOP_INPREG (AOP (result)))
8035 /* otherwise get a free pointer register */
8037 preg = getFreePtr (ic, &aop, FALSE);
8038 emitcode ("mov", "%s,%s",
8040 aopGet (AOP (result), 0, FALSE, TRUE));
8044 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8046 aopOp (right, ic, FALSE);
8048 /* if bitfield then unpack the bits */
8049 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8050 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8053 /* we have can just get the values */
8054 int size = AOP_SIZE (right);
8059 l = aopGet (AOP (right), offset, FALSE, TRUE);
8062 emitcode ("movx", "@%s,a", rname);
8065 emitcode ("inc", "%s", rname);
8071 /* now some housekeeping stuff */
8072 if (aop) /* we had to allocate for this iCode */
8075 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8076 freeAsmop (NULL, aop, ic, TRUE);
8080 /* we did not allocate which means left
8081 already in a pointer register, then
8082 if size > 0 && this could be used again
8083 we have to point it back to where it
8085 if (AOP_SIZE (right) > 1 &&
8086 !OP_SYMBOL (result)->remat &&
8087 (OP_SYMBOL (result)->liveTo > ic->seq ||
8090 int size = AOP_SIZE (right) - 1;
8092 emitcode ("dec", "%s", rname);
8097 if (pi) pi->generated = 1;
8098 freeAsmop (result, NULL, ic, TRUE);
8099 freeAsmop (right, NULL, ic, TRUE);
8104 /*-----------------------------------------------------------------*/
8105 /* genFarPointerSet - set value from far space */
8106 /*-----------------------------------------------------------------*/
8108 genFarPointerSet (operand * right,
8109 operand * result, iCode * ic, iCode * pi)
8112 sym_link *retype = getSpec (operandType (right));
8113 sym_link *letype = getSpec (operandType (result));
8115 D(emitcode ("; genFarPointerSet",""));
8117 aopOp (result, ic, FALSE);
8119 /* if the operand is already in dptr
8120 then we do nothing else we move the value to dptr */
8121 if (AOP_TYPE (result) != AOP_STR)
8123 /* if this is remateriazable */
8124 if (AOP_TYPE (result) == AOP_IMMD)
8125 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8127 { /* we need to get it byte by byte */
8128 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8129 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8132 /* so dptr know contains the address */
8133 aopOp (right, ic, FALSE);
8135 /* if bit then unpack */
8136 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8137 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8140 size = AOP_SIZE (right);
8145 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8147 emitcode ("movx", "@dptr,a");
8149 emitcode ("inc", "dptr");
8152 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8153 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8154 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8157 freeAsmop (result, NULL, ic, TRUE);
8158 freeAsmop (right, NULL, ic, TRUE);
8161 /*-----------------------------------------------------------------*/
8162 /* genGenPointerSet - set value from generic pointer space */
8163 /*-----------------------------------------------------------------*/
8165 genGenPointerSet (operand * right,
8166 operand * result, iCode * ic, iCode * pi)
8169 sym_link *retype = getSpec (operandType (right));
8170 sym_link *letype = getSpec (operandType (result));
8172 D(emitcode ("; genGenPointerSet",""));
8174 aopOp (result, ic, FALSE);
8176 /* if the operand is already in dptr
8177 then we do nothing else we move the value to dptr */
8178 if (AOP_TYPE (result) != AOP_STR)
8180 /* if this is remateriazable */
8181 if (AOP_TYPE (result) == AOP_IMMD)
8183 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8184 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8185 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8187 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8190 { /* we need to get it byte by byte */
8191 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8192 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8193 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8196 /* so dptr know contains the address */
8197 aopOp (right, ic, FALSE);
8199 /* if bit then unpack */
8200 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8201 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8204 size = AOP_SIZE (right);
8209 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8211 emitcode ("lcall", "__gptrput");
8213 emitcode ("inc", "dptr");
8217 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8218 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8219 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8222 freeAsmop (result, NULL, ic, TRUE);
8223 freeAsmop (right, NULL, ic, TRUE);
8226 /*-----------------------------------------------------------------*/
8227 /* genPointerSet - stores the value into a pointer location */
8228 /*-----------------------------------------------------------------*/
8230 genPointerSet (iCode * ic, iCode *pi)
8232 operand *right, *result;
8233 sym_link *type, *etype;
8236 D(emitcode ("; genPointerSet",""));
8238 right = IC_RIGHT (ic);
8239 result = IC_RESULT (ic);
8241 /* depending on the type of pointer we need to
8242 move it to the correct pointer register */
8243 type = operandType (result);
8244 etype = getSpec (type);
8245 /* if left is of type of pointer then it is simple */
8246 if (IS_PTR (type) && !IS_FUNC (type->next))
8248 p_type = DCL_TYPE (type);
8252 /* we have to go by the storage class */
8253 p_type = PTR_TYPE (SPEC_OCLS (etype));
8256 /* special case when cast remat */
8257 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8258 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8259 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8260 type = operandType (result);
8261 p_type = DCL_TYPE (type);
8263 /* now that we have the pointer type we assign
8264 the pointer values */
8270 genNearPointerSet (right, result, ic, pi);
8274 genPagedPointerSet (right, result, ic, pi);
8278 genFarPointerSet (right, result, ic, pi);
8282 genGenPointerSet (right, result, ic, pi);
8286 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8287 "genPointerSet: illegal pointer type");
8292 /*-----------------------------------------------------------------*/
8293 /* genIfx - generate code for Ifx statement */
8294 /*-----------------------------------------------------------------*/
8296 genIfx (iCode * ic, iCode * popIc)
8298 operand *cond = IC_COND (ic);
8301 D(emitcode ("; genIfx",""));
8303 aopOp (cond, ic, FALSE);
8305 /* get the value into acc */
8306 if (AOP_TYPE (cond) != AOP_CRY)
8310 /* the result is now in the accumulator */
8311 freeAsmop (cond, NULL, ic, TRUE);
8313 /* if there was something to be popped then do it */
8317 /* if the condition is a bit variable */
8318 if (isbit && IS_ITEMP (cond) &&
8320 genIfxJump (ic, SPIL_LOC (cond)->rname);
8321 else if (isbit && !IS_ITEMP (cond))
8322 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8324 genIfxJump (ic, "a");
8329 /*-----------------------------------------------------------------*/
8330 /* genAddrOf - generates code for address of */
8331 /*-----------------------------------------------------------------*/
8333 genAddrOf (iCode * ic)
8335 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8338 D(emitcode ("; genAddrOf",""));
8340 aopOp (IC_RESULT (ic), ic, FALSE);
8342 /* if the operand is on the stack then we
8343 need to get the stack offset of this
8347 /* if it has an offset then we need to compute
8351 emitcode ("mov", "a,_bp");
8352 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8353 ((char) (sym->stack - _G.nRegsSaved)) :
8354 ((char) sym->stack)) & 0xff);
8355 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8359 /* we can just move _bp */
8360 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8362 /* fill the result with zero */
8363 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8368 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8374 /* object not on stack then we need the name */
8375 size = AOP_SIZE (IC_RESULT (ic));
8380 char s[SDCC_NAME_MAX];
8382 sprintf (s, "#(%s >> %d)",
8386 sprintf (s, "#%s", sym->rname);
8387 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8391 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8395 /*-----------------------------------------------------------------*/
8396 /* genFarFarAssign - assignment when both are in far space */
8397 /*-----------------------------------------------------------------*/
8399 genFarFarAssign (operand * result, operand * right, iCode * ic)
8401 int size = AOP_SIZE (right);
8405 D(emitcode ("; genFarFarAssign",""));
8407 /* first push the right side on to the stack */
8410 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8412 emitcode ("push", "acc");
8415 freeAsmop (right, NULL, ic, FALSE);
8416 /* now assign DPTR to result */
8417 aopOp (result, ic, FALSE);
8418 size = AOP_SIZE (result);
8421 emitcode ("pop", "acc");
8422 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8424 freeAsmop (result, NULL, ic, FALSE);
8428 /*-----------------------------------------------------------------*/
8429 /* genAssign - generate code for assignment */
8430 /*-----------------------------------------------------------------*/
8432 genAssign (iCode * ic)
8434 operand *result, *right;
8436 unsigned long lit = 0L;
8438 D(emitcode("; genAssign",""));
8440 result = IC_RESULT (ic);
8441 right = IC_RIGHT (ic);
8443 /* if they are the same */
8444 if (operandsEqu (result, right) &&
8445 !isOperandVolatile (result, FALSE) &&
8446 !isOperandVolatile (right, FALSE))
8449 aopOp (right, ic, FALSE);
8451 /* special case both in far space */
8452 if (AOP_TYPE (right) == AOP_DPTR &&
8453 IS_TRUE_SYMOP (result) &&
8454 isOperandInFarSpace (result))
8457 genFarFarAssign (result, right, ic);
8461 aopOp (result, ic, TRUE);
8463 /* if they are the same registers */
8464 if (sameRegs (AOP (right), AOP (result)) &&
8465 !isOperandVolatile (result, FALSE) &&
8466 !isOperandVolatile (right, FALSE))
8469 /* if the result is a bit */
8470 if (AOP_TYPE (result) == AOP_CRY)
8473 /* if the right size is a literal then
8474 we know what the value is */
8475 if (AOP_TYPE (right) == AOP_LIT)
8477 if (((int) operandLitValue (right)))
8478 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8480 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8484 /* the right is also a bit variable */
8485 if (AOP_TYPE (right) == AOP_CRY)
8487 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8488 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8494 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8498 /* bit variables done */
8500 size = AOP_SIZE (result);
8502 if (AOP_TYPE (right) == AOP_LIT)
8503 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8505 (AOP_TYPE (result) != AOP_REG) &&
8506 (AOP_TYPE (right) == AOP_LIT) &&
8507 !IS_FLOAT (operandType (right)) &&
8510 emitcode ("clr", "a");
8513 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8514 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8516 aopPut (AOP (result),
8517 aopGet (AOP (right), size, FALSE, FALSE),
8519 isOperandVolatile (result, FALSE));
8526 aopPut (AOP (result),
8527 aopGet (AOP (right), offset, FALSE, FALSE),
8529 isOperandVolatile (result, FALSE));
8535 freeAsmop (right, NULL, ic, TRUE);
8536 freeAsmop (result, NULL, ic, TRUE);
8539 /*-----------------------------------------------------------------*/
8540 /* genJumpTab - genrates code for jump table */
8541 /*-----------------------------------------------------------------*/
8543 genJumpTab (iCode * ic)
8548 D(emitcode ("; genJumpTab",""));
8550 aopOp (IC_JTCOND (ic), ic, FALSE);
8551 /* get the condition into accumulator */
8552 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8554 /* multiply by three */
8555 emitcode ("add", "a,acc");
8556 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8557 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8559 jtab = newiTempLabel (NULL);
8560 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8561 emitcode ("jmp", "@a+dptr");
8562 emitcode ("", "%05d$:", jtab->key + 100);
8563 /* now generate the jump labels */
8564 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8565 jtab = setNextItem (IC_JTLABELS (ic)))
8566 emitcode ("ljmp", "%05d$", jtab->key + 100);
8570 /*-----------------------------------------------------------------*/
8571 /* genCast - gen code for casting */
8572 /*-----------------------------------------------------------------*/
8574 genCast (iCode * ic)
8576 operand *result = IC_RESULT (ic);
8577 sym_link *ctype = operandType (IC_LEFT (ic));
8578 sym_link *rtype = operandType (IC_RIGHT (ic));
8579 operand *right = IC_RIGHT (ic);
8582 D(emitcode("; genCast",""));
8584 /* if they are equivalent then do nothing */
8585 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8588 aopOp (right, ic, FALSE);
8589 aopOp (result, ic, FALSE);
8591 /* if the result is a bit (and not a bitfield) */
8592 // if (AOP_TYPE (result) == AOP_CRY)
8593 if (IS_BITVAR (OP_SYMBOL (result)->type)
8594 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8596 /* if the right size is a literal then
8597 we know what the value is */
8598 if (AOP_TYPE (right) == AOP_LIT)
8600 if (((int) operandLitValue (right)))
8601 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8603 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8608 /* the right is also a bit variable */
8609 if (AOP_TYPE (right) == AOP_CRY)
8611 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8612 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8618 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8623 /* if they are the same size : or less */
8624 if (AOP_SIZE (result) <= AOP_SIZE (right))
8627 /* if they are in the same place */
8628 if (sameRegs (AOP (right), AOP (result)))
8631 /* if they in different places then copy */
8632 size = AOP_SIZE (result);
8636 aopPut (AOP (result),
8637 aopGet (AOP (right), offset, FALSE, FALSE),
8639 isOperandVolatile (result, FALSE));
8646 /* if the result is of type pointer */
8651 sym_link *type = operandType (right);
8652 sym_link *etype = getSpec (type);
8654 /* pointer to generic pointer */
8655 if (IS_GENPTR (ctype))
8658 p_type = DCL_TYPE (type);
8661 if (SPEC_SCLS(etype)==S_REGISTER) {
8662 // let's assume it is a generic pointer
8665 /* we have to go by the storage class */
8666 p_type = PTR_TYPE (SPEC_OCLS (etype));
8670 /* the first two bytes are known */
8671 size = GPTRSIZE - 1;
8675 aopPut (AOP (result),
8676 aopGet (AOP (right), offset, FALSE, FALSE),
8678 isOperandVolatile (result, FALSE));
8681 /* the last byte depending on type */
8683 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8688 // pointerTypeToGPByte will have bitched.
8692 sprintf(gpValStr, "#0x%d", gpVal);
8693 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8698 /* just copy the pointers */
8699 size = AOP_SIZE (result);
8703 aopPut (AOP (result),
8704 aopGet (AOP (right), offset, FALSE, FALSE),
8706 isOperandVolatile (result, FALSE));
8712 /* so we now know that the size of destination is greater
8713 than the size of the source */
8714 /* we move to result for the size of source */
8715 size = AOP_SIZE (right);
8719 aopPut (AOP (result),
8720 aopGet (AOP (right), offset, FALSE, FALSE),
8722 isOperandVolatile (result, FALSE));
8726 /* now depending on the sign of the source && destination */
8727 size = AOP_SIZE (result) - AOP_SIZE (right);
8728 /* if unsigned or not an integral type */
8729 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8732 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8736 /* we need to extend the sign :{ */
8737 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8740 emitcode ("rlc", "a");
8741 emitcode ("subb", "a,acc");
8743 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8746 /* we are done hurray !!!! */
8749 freeAsmop (right, NULL, ic, TRUE);
8750 freeAsmop (result, NULL, ic, TRUE);
8754 /*-----------------------------------------------------------------*/
8755 /* genDjnz - generate decrement & jump if not zero instrucion */
8756 /*-----------------------------------------------------------------*/
8758 genDjnz (iCode * ic, iCode * ifx)
8764 D(emitcode ("; genDjnz",""));
8766 /* if the if condition has a false label
8767 then we cannot save */
8771 /* if the minus is not of the form
8773 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8774 !IS_OP_LITERAL (IC_RIGHT (ic)))
8777 if (operandLitValue (IC_RIGHT (ic)) != 1)
8780 /* if the size of this greater than one then no
8782 if (getSize (operandType (IC_RESULT (ic))) > 1)
8785 /* otherwise we can save BIG */
8786 lbl = newiTempLabel (NULL);
8787 lbl1 = newiTempLabel (NULL);
8789 aopOp (IC_RESULT (ic), ic, FALSE);
8791 if (AOP_NEEDSACC(IC_RESULT(ic)))
8793 /* If the result is accessed indirectly via
8794 * the accumulator, we must explicitly write
8795 * it back after the decrement.
8797 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8799 if (strcmp(rByte, "a"))
8801 /* Something is hopelessly wrong */
8802 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8803 __FILE__, __LINE__);
8804 /* We can just give up; the generated code will be inefficient,
8807 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8810 emitcode ("dec", "%s", rByte);
8811 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8812 emitcode ("jnz", "%05d$", lbl->key + 100);
8814 else if (IS_AOP_PREG (IC_RESULT (ic)))
8816 emitcode ("dec", "%s",
8817 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8818 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8819 emitcode ("jnz", "%05d$", lbl->key + 100);
8823 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8826 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8827 emitcode ("", "%05d$:", lbl->key + 100);
8828 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8829 emitcode ("", "%05d$:", lbl1->key + 100);
8831 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8836 /*-----------------------------------------------------------------*/
8837 /* genReceive - generate code for a receive iCode */
8838 /*-----------------------------------------------------------------*/
8840 genReceive (iCode * ic)
8842 int size = getSize (operandType (IC_RESULT (ic)));
8844 D(emitcode ("; genReceive",""));
8846 if (ic->argreg == 1) { /* first parameter */
8847 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8848 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8849 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8851 offset = fReturnSizeMCS51 - size;
8853 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8854 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8857 aopOp (IC_RESULT (ic), ic, FALSE);
8858 size = AOP_SIZE (IC_RESULT (ic));
8861 emitcode ("pop", "acc");
8862 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8867 aopOp (IC_RESULT (ic), ic, FALSE);
8869 assignResultValue (IC_RESULT (ic));
8871 } else { /* second receive onwards */
8873 aopOp (IC_RESULT (ic), ic, FALSE);
8874 rb1off = ic->argreg;
8876 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8879 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8882 /*-----------------------------------------------------------------*/
8883 /* genDummyRead - generate code for dummy read of volatiles */
8884 /*-----------------------------------------------------------------*/
8886 genDummyRead (iCode * ic)
8891 D(emitcode("; genDummyRead",""));
8893 right = IC_RIGHT (ic);
8895 aopOp (right, ic, FALSE);
8897 /* if the result is a bit */
8898 if (AOP_TYPE (right) == AOP_CRY)
8900 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8904 /* bit variables done */
8906 size = AOP_SIZE (right);
8910 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8915 freeAsmop (right, NULL, ic, TRUE);
8918 /*-----------------------------------------------------------------*/
8919 /* gen51Code - generate code for 8051 based controllers */
8920 /*-----------------------------------------------------------------*/
8922 gen51Code (iCode * lic)
8927 lineHead = lineCurr = NULL;
8929 /* print the allocation information */
8930 if (allocInfo && currFunc)
8931 printAllocInfo (currFunc, codeOutFile);
8932 /* if debug information required */
8933 if (options.debug && currFunc)
8935 debugFile->writeFunction(currFunc);
8937 if (IS_STATIC (currFunc->etype))
8938 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8940 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8943 /* stack pointer name */
8944 if (options.useXstack)
8950 for (ic = lic; ic; ic = ic->next)
8953 if (ic->lineno && cln != ic->lineno)
8958 emitcode ("", "C$%s$%d$%d$%d ==.",
8959 FileBaseName (ic->filename), ic->lineno,
8960 ic->level, ic->block);
8963 if (!options.noCcodeInAsm) {
8964 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8965 printCLine(ic->filename, ic->lineno));
8969 if (options.iCodeInAsm) {
8973 for (i=0; i<8; i++) {
8974 sprintf (®sInUse[i],
8975 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8978 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8980 /* if the result is marked as
8981 spilt and rematerializable or code for
8982 this has already been generated then
8984 if (resultRemat (ic) || ic->generated)
8987 /* depending on the operation */
9007 /* IPOP happens only when trying to restore a
9008 spilt live range, if there is an ifx statement
9009 following this pop then the if statement might
9010 be using some of the registers being popped which
9011 would destory the contents of the register so
9012 we need to check for this condition and handle it */
9014 ic->next->op == IFX &&
9015 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9016 genIfx (ic->next, ic);
9034 genEndFunction (ic);
9054 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9071 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9075 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9082 /* note these two are xlated by algebraic equivalence
9083 during parsing SDCC.y */
9084 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9085 "got '>=' or '<=' shouldn't have come here");
9089 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9101 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9105 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9109 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9136 case GET_VALUE_AT_ADDRESS:
9137 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9141 if (POINTER_SET (ic))
9142 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9168 addSet (&_G.sendSet, ic);
9171 case DUMMY_READ_VOLATILE:
9181 /* now we are ready to call the
9182 peep hole optimizer */
9183 if (!options.nopeep)
9184 peepHole (&lineHead);
9186 /* now do the actual printing */
9187 printLine (lineHead, codeOutFile);