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;
80 static char *rb1regs[] = {
81 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
84 extern int mcs51_ptrRegReq;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
93 #define CLRC emitcode("clr","c")
94 #define SETC emitcode("setb","c")
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] =
100 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
101 0xE0, 0xC0, 0x80, 0x00};
102 static unsigned char SRMask[] =
103 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, const char *fmt,...)
118 char lb[INITIAL_INLINEASM];
126 sprintf (lb, "%s\t", inst);
128 sprintf (lb, "%s", inst);
129 vsprintf (lb + (strlen (lb)), fmt, ap);
132 vsprintf (lb, fmt, ap);
134 while (isspace (*lbp))
138 lineCurr = (lineCurr ?
139 connectLine (lineCurr, newLineNode (lb)) :
140 (lineHead = newLineNode (lb)));
141 lineCurr->isInline = _G.inLine;
142 lineCurr->isDebug = _G.debugLine;
143 lineCurr->ic = _G.current_iCode;
144 lineCurr->isComment = (*lbp==';');
148 /*-----------------------------------------------------------------*/
149 /* mova - moves specified value into accumulator */
150 /*-----------------------------------------------------------------*/
154 /* do some early peephole optimization */
155 if (!strcmp(x, "a") || !strcmp(x, "acc"))
158 emitcode("mov","a,%s", x);
161 /*-----------------------------------------------------------------*/
162 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
163 /*-----------------------------------------------------------------*/
165 getFreePtr (iCode * ic, asmop ** aopp, bool result)
167 bool r0iu = FALSE, r1iu = FALSE;
168 bool r0ou = FALSE, r1ou = FALSE;
170 /* the logic: if r0 & r1 used in the instruction
171 then we are in trouble otherwise */
173 /* first check if r0 & r1 are used by this
174 instruction, in which case we are in trouble */
175 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
176 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
181 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
182 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
184 /* if no usage of r0 then return it */
187 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
193 /* if no usage of r1 then return it */
196 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
197 (*aopp)->type = AOP_R1;
199 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
202 /* now we know they both have usage */
203 /* if r0 not used in this instruction */
206 /* push it if not already pushed */
209 emitcode ("push", "%s",
210 mcs51_regWithIdx (R0_IDX)->dname);
214 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
215 (*aopp)->type = AOP_R0;
217 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
220 /* if r1 not used then */
224 /* push it if not already pushed */
227 emitcode ("push", "%s",
228 mcs51_regWithIdx (R1_IDX)->dname);
232 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
233 (*aopp)->type = AOP_R1;
234 return mcs51_regWithIdx (R1_IDX);
237 /* I said end of world, but not quite end of world yet */
239 /* we can push it on the stack */
240 (*aopp)->type = AOP_STK;
243 /* in the case that result AND left AND right needs a pointer reg
244 we can safely use the result's */
245 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
246 (*aopp)->type = AOP_R0;
247 return mcs51_regWithIdx (R0_IDX);
249 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
250 (*aopp)->type = AOP_R1;
251 return mcs51_regWithIdx (R1_IDX);
255 /* now this is REALLY the end of the world */
256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
257 "getFreePtr should never reach here");
261 /*-----------------------------------------------------------------*/
262 /* newAsmop - creates a new asmOp */
263 /*-----------------------------------------------------------------*/
265 newAsmop (short type)
269 aop = Safe_calloc (1, sizeof (asmop));
274 /*-----------------------------------------------------------------*/
275 /* pointerCode - returns the code for a pointer type */
276 /*-----------------------------------------------------------------*/
278 pointerCode (sym_link * etype)
281 return PTR_TYPE (SPEC_OCLS (etype));
286 /*-----------------------------------------------------------------*/
287 /* leftRightUseAcc - returns size of accumulator use by operands */
288 /*-----------------------------------------------------------------*/
290 leftRightUseAcc(iCode *ic)
294 if (ic && IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))
295 && OP_SYMBOL (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->accuse)
296 accuse = (accuse < OP_SYMBOL (IC_LEFT (ic))->nRegs)
297 ? OP_SYMBOL (IC_LEFT (ic))->nRegs : accuse;
299 if (ic && IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))
300 && OP_SYMBOL (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic))->accuse)
301 accuse = (accuse < OP_SYMBOL (IC_RIGHT (ic))->nRegs)
302 ? OP_SYMBOL (IC_RIGHT (ic))->nRegs : accuse;
308 /*-----------------------------------------------------------------*/
309 /* aopForSym - for a true symbol */
310 /*-----------------------------------------------------------------*/
312 aopForSym (iCode * ic, symbol * sym, bool result)
317 wassertl (ic != NULL, "Got a null iCode");
318 wassertl (sym != NULL, "Got a null symbol");
320 space = SPEC_OCLS (sym->etype);
322 /* if already has one */
326 /* assign depending on the storage class */
327 /* if it is on the stack or indirectly addressable */
328 /* space we need to assign either r0 or r1 to it */
329 if (sym->onStack || sym->iaccess)
331 sym->aop = aop = newAsmop (0);
332 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
333 aop->size = getSize (sym->type);
335 /* now assign the address of the variable to
336 the pointer register */
337 if (aop->type != AOP_STK)
342 if (_G.accInUse || leftRightUseAcc (ic))
343 emitcode ("push", "acc");
345 emitcode ("mov", "a,_bp");
346 emitcode ("add", "a,#0x%02x",
348 ((char) (sym->stack - _G.nRegsSaved)) :
349 ((char) sym->stack)) & 0xff);
350 emitcode ("mov", "%s,a",
351 aop->aopu.aop_ptr->name);
353 if (_G.accInUse || leftRightUseAcc (ic))
354 emitcode ("pop", "acc");
357 emitcode ("mov", "%s,#%s",
358 aop->aopu.aop_ptr->name,
360 aop->paged = space->paged;
363 aop->aopu.aop_stk = sym->stack;
367 /* if in bit space */
368 if (IN_BITSPACE (space))
370 sym->aop = aop = newAsmop (AOP_CRY);
371 aop->aopu.aop_dir = sym->rname;
372 aop->size = getSize (sym->type);
375 /* if it is in direct space */
376 if (IN_DIRSPACE (space))
378 sym->aop = aop = newAsmop (AOP_DIR);
379 aop->aopu.aop_dir = sym->rname;
380 aop->size = getSize (sym->type);
384 /* special case for a function */
385 if (IS_FUNC (sym->type))
387 sym->aop = aop = newAsmop (AOP_IMMD);
388 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
389 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
390 aop->size = FPTRSIZE;
394 /* only remaining is far space */
395 /* in which case DPTR gets the address */
396 sym->aop = aop = newAsmop (AOP_DPTR);
397 emitcode ("mov", "dptr,#%s", sym->rname);
398 aop->size = getSize (sym->type);
400 /* if it is in code space */
401 if (IN_CODESPACE (space))
407 /*-----------------------------------------------------------------*/
408 /* aopForRemat - rematerialzes an object */
409 /*-----------------------------------------------------------------*/
411 aopForRemat (symbol * sym)
413 iCode *ic = sym->rematiCode;
414 asmop *aop = newAsmop (AOP_IMMD);
421 val += (int) operandLitValue (IC_RIGHT (ic));
422 else if (ic->op == '-')
423 val -= (int) operandLitValue (IC_RIGHT (ic));
424 else if (IS_CAST_ICODE(ic)) {
425 sym_link *from_type = operandType(IC_RIGHT(ic));
426 aop->aopu.aop_immd.from_cast_remat = 1;
427 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
428 ptr_type = DCL_TYPE(from_type);
429 if (ptr_type == IPOINTER) {
436 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
440 sprintf (buffer, "(%s %c 0x%04x)",
441 OP_SYMBOL (IC_LEFT (ic))->rname,
442 val >= 0 ? '+' : '-',
445 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
447 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
448 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
449 /* set immd2 field if required */
450 if (aop->aopu.aop_immd.from_cast_remat) {
451 sprintf(buffer,"#0x%02x",ptr_type);
452 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
453 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
459 /*-----------------------------------------------------------------*/
460 /* regsInCommon - two operands have some registers in common */
461 /*-----------------------------------------------------------------*/
463 regsInCommon (operand * op1, operand * op2)
468 /* if they have registers in common */
469 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
472 sym1 = OP_SYMBOL (op1);
473 sym2 = OP_SYMBOL (op2);
475 if (sym1->nRegs == 0 || sym2->nRegs == 0)
478 for (i = 0; i < sym1->nRegs; i++)
484 for (j = 0; j < sym2->nRegs; j++)
489 if (sym2->regs[j] == sym1->regs[i])
497 /*-----------------------------------------------------------------*/
498 /* operandsEqu - equivalent */
499 /*-----------------------------------------------------------------*/
501 operandsEqu (operand * op1, operand * op2)
505 /* if they not symbols */
506 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
509 sym1 = OP_SYMBOL (op1);
510 sym2 = OP_SYMBOL (op2);
512 /* if both are itemps & one is spilt
513 and the other is not then false */
514 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
515 sym1->isspilt != sym2->isspilt)
518 /* if they are the same */
522 if (strcmp (sym1->rname, sym2->rname) == 0)
526 /* if left is a tmp & right is not */
527 if (IS_ITEMP (op1) &&
530 (sym1->usl.spillLoc == sym2))
533 if (IS_ITEMP (op2) &&
537 (sym2->usl.spillLoc == sym1))
543 /*-----------------------------------------------------------------*/
544 /* sameRegs - two asmops have the same registers */
545 /*-----------------------------------------------------------------*/
547 sameRegs (asmop * aop1, asmop * aop2)
554 if (aop1->type != AOP_REG ||
555 aop2->type != AOP_REG)
558 if (aop1->size != aop2->size)
561 for (i = 0; i < aop1->size; i++)
562 if (aop1->aopu.aop_reg[i] !=
563 aop2->aopu.aop_reg[i])
569 /*-----------------------------------------------------------------*/
570 /* aopOp - allocates an asmop for an operand : */
571 /*-----------------------------------------------------------------*/
573 aopOp (operand * op, iCode * ic, bool result)
582 /* if this a literal */
583 if (IS_OP_LITERAL (op))
585 op->aop = aop = newAsmop (AOP_LIT);
586 aop->aopu.aop_lit = op->operand.valOperand;
587 aop->size = getSize (operandType (op));
591 /* if already has a asmop then continue */
595 /* if the underlying symbol has a aop */
596 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
598 op->aop = OP_SYMBOL (op)->aop;
602 /* if this is a true symbol */
603 if (IS_TRUE_SYMOP (op))
605 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
609 /* this is a temporary : this has
615 e) can be a return use only */
617 sym = OP_SYMBOL (op);
619 /* if the type is a conditional */
620 if (sym->regType == REG_CND)
622 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
627 /* if it is spilt then two situations
629 b) has a spill location */
630 if (sym->isspilt || sym->nRegs == 0)
633 /* rematerialize it NOW */
636 sym->aop = op->aop = aop =
638 aop->size = getSize (sym->type);
645 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
646 aop->size = getSize (sym->type);
647 for (i = 0; i < 2; i++)
648 aop->aopu.aop_str[i] = accUse[i];
656 aop = op->aop = sym->aop = newAsmop (AOP_STR);
657 aop->size = getSize (sym->type);
658 for (i = 0; i < fReturnSizeMCS51; i++)
659 aop->aopu.aop_str[i] = fReturn[i];
663 /* else spill location */
664 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
665 /* force a new aop if sizes differ */
666 sym->usl.spillLoc->aop = NULL;
668 sym->aop = op->aop = aop =
669 aopForSym (ic, sym->usl.spillLoc, result);
670 aop->size = getSize (sym->type);
674 /* must be in a register */
675 sym->aop = op->aop = aop = newAsmop (AOP_REG);
676 aop->size = sym->nRegs;
677 for (i = 0; i < sym->nRegs; i++)
678 aop->aopu.aop_reg[i] = sym->regs[i];
681 /*-----------------------------------------------------------------*/
682 /* freeAsmop - free up the asmop given to an operand */
683 /*----------------------------------------------------------------*/
685 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
702 /* depending on the asmop type only three cases need work AOP_RO
703 , AOP_R1 && AOP_STK */
711 emitcode ("pop", "ar0");
715 bitVectUnSetBit (ic->rUsed, R0_IDX);
723 emitcode ("pop", "ar1");
727 bitVectUnSetBit (ic->rUsed, R1_IDX);
733 int stk = aop->aopu.aop_stk + aop->size;
734 bitVectUnSetBit (ic->rUsed, R0_IDX);
735 bitVectUnSetBit (ic->rUsed, R1_IDX);
737 getFreePtr (ic, &aop, FALSE);
741 emitcode ("mov", "a,_bp");
742 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
743 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
747 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
752 emitcode ("pop", "acc");
753 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
756 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
759 freeAsmop (op, NULL, ic, TRUE);
762 emitcode ("pop", "ar0");
768 emitcode ("pop", "ar1");
775 /* all other cases just dealloc */
781 OP_SYMBOL (op)->aop = NULL;
782 /* if the symbol has a spill */
784 SPIL_LOC (op)->aop = NULL;
789 /*-----------------------------------------------------------------*/
790 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
791 /* clobber the accumulator */
792 /*-----------------------------------------------------------------*/
794 aopGetUsesAcc (asmop *aop, int offset)
796 if (offset > (aop->size - 1))
814 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
823 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
827 /* Error case --- will have been caught already */
834 /*-----------------------------------------------------------------*/
835 /* aopGet - for fetching value of the aop */
836 /*-----------------------------------------------------------------*/
838 aopGet (asmop * aop, int offset, bool bit16, bool dname)
843 /* offset is greater than
845 if (offset > (aop->size - 1) &&
846 aop->type != AOP_LIT)
849 /* depending on type */
855 /* if we need to increment it */
856 while (offset > aop->coff)
858 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
862 while (offset < aop->coff)
864 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
871 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
872 return (dname ? "acc" : "a");
874 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
875 rs = Safe_calloc (1, strlen (s) + 1);
880 if (aop->code && aop->coff==0 && offset>=1) {
881 emitcode ("mov", "a,#0x%02x", offset);
882 emitcode ("movc", "a,@a+dptr");
883 return (dname ? "acc" : "a");
886 while (offset > aop->coff)
888 emitcode ("inc", "dptr");
892 while (offset < aop->coff)
894 emitcode ("lcall", "__decdptr");
901 emitcode ("clr", "a");
902 emitcode ("movc", "a,@a+dptr");
906 emitcode ("movx", "a,@dptr");
908 return (dname ? "acc" : "a");
912 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
913 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
915 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
917 sprintf (s, "#(%s >> %d)",
918 aop->aopu.aop_immd.aop_immd1,
922 aop->aopu.aop_immd.aop_immd1);
923 rs = Safe_calloc (1, strlen (s) + 1);
929 sprintf (s, "(%s + %d)",
933 sprintf (s, "%s", aop->aopu.aop_dir);
934 rs = Safe_calloc (1, strlen (s) + 1);
940 return aop->aopu.aop_reg[offset]->dname;
942 return aop->aopu.aop_reg[offset]->name;
945 emitcode ("clr", "a");
946 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
947 emitcode ("rlc", "a");
948 return (dname ? "acc" : "a");
951 if (!offset && dname)
953 return aop->aopu.aop_str[offset];
956 return aopLiteral (aop->aopu.aop_lit, offset);
960 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
964 return aop->aopu.aop_str[offset];
968 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
969 "aopget got unsupported aop->type");
972 /*-----------------------------------------------------------------*/
973 /* aopPut - puts a string for a aop */
974 /*-----------------------------------------------------------------*/
976 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
980 if (aop->size && offset > (aop->size - 1))
982 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
983 "aopPut got offset > aop->size");
987 /* will assign value to value */
988 /* depending on where it is ofcourse */
993 sprintf (d, "(%s + %d)",
994 aop->aopu.aop_dir, offset);
996 sprintf (d, "%s", aop->aopu.aop_dir);
1000 emitcode ("mov", "%s,%s", d, s);
1005 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1006 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1009 strcmp (s, "r0") == 0 ||
1010 strcmp (s, "r1") == 0 ||
1011 strcmp (s, "r2") == 0 ||
1012 strcmp (s, "r3") == 0 ||
1013 strcmp (s, "r4") == 0 ||
1014 strcmp (s, "r5") == 0 ||
1015 strcmp (s, "r6") == 0 ||
1016 strcmp (s, "r7") == 0)
1017 emitcode ("mov", "%s,%s",
1018 aop->aopu.aop_reg[offset]->dname, s);
1020 emitcode ("mov", "%s,%s",
1021 aop->aopu.aop_reg[offset]->name, s);
1028 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1029 "aopPut writing to code space");
1033 while (offset > aop->coff)
1036 emitcode ("inc", "dptr");
1039 while (offset < aop->coff)
1042 emitcode ("lcall", "__decdptr");
1047 /* if not in accumulater */
1050 emitcode ("movx", "@dptr,a");
1055 while (offset > aop->coff)
1058 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1060 while (offset < aop->coff)
1063 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1070 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1076 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1078 else if (strcmp (s, "r0") == 0 ||
1079 strcmp (s, "r1") == 0 ||
1080 strcmp (s, "r2") == 0 ||
1081 strcmp (s, "r3") == 0 ||
1082 strcmp (s, "r4") == 0 ||
1083 strcmp (s, "r5") == 0 ||
1084 strcmp (s, "r6") == 0 ||
1085 strcmp (s, "r7") == 0)
1088 sprintf (buffer, "a%s", s);
1089 emitcode ("mov", "@%s,%s",
1090 aop->aopu.aop_ptr->name, buffer);
1093 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1098 if (strcmp (s, "a") == 0)
1099 emitcode ("push", "acc");
1103 emitcode ("push", "acc");
1105 emitcode ("push", s);
1111 /* if bit variable */
1112 if (!aop->aopu.aop_dir)
1114 emitcode ("clr", "a");
1115 emitcode ("rlc", "a");
1120 emitcode ("clr", "%s", aop->aopu.aop_dir);
1122 emitcode ("setb", "%s", aop->aopu.aop_dir);
1123 else if (!strcmp (s, "c"))
1124 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1127 if (strcmp (s, "a"))
1132 /* set C, if a >= 1 */
1133 emitcode ("add", "a,#0xff");
1134 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1142 if (strcmp (aop->aopu.aop_str[offset], s) ||
1144 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1149 if (!offset && (strcmp (s, "acc") == 0) &&
1153 if (strcmp (aop->aopu.aop_str[offset], s) &&
1155 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1159 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1160 "aopPut got unsupported aop->type");
1168 /*-----------------------------------------------------------------*/
1169 /* pointToEnd :- points to the last byte of the operand */
1170 /*-----------------------------------------------------------------*/
1172 pointToEnd (asmop * aop)
1178 aop->coff = count = (aop->size - 1);
1184 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1188 emitcode ("inc", "dptr");
1195 /*-----------------------------------------------------------------*/
1196 /* reAdjustPreg - points a register back to where it should */
1197 /*-----------------------------------------------------------------*/
1199 reAdjustPreg (asmop * aop)
1201 if ((aop->coff==0) || aop->size <= 1)
1209 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1214 emitcode ("lcall", "__decdptr");
1221 #define AOP(op) op->aop
1222 #define AOP_TYPE(op) AOP(op)->type
1223 #define AOP_SIZE(op) AOP(op)->size
1224 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1225 AOP_TYPE(x) == AOP_R0))
1227 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1228 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1230 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1231 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1232 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1235 /*-----------------------------------------------------------------*/
1236 /* opIsGptr: returns non-zero if the passed operand is */
1237 /* a generic pointer type. */
1238 /*-----------------------------------------------------------------*/
1240 opIsGptr (operand * op)
1242 sym_link *type = operandType (op);
1244 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1251 /*-----------------------------------------------------------------*/
1252 /* getDataSize - get the operand data size */
1253 /*-----------------------------------------------------------------*/
1255 getDataSize (operand * op)
1258 size = AOP_SIZE (op);
1259 if (size == GPTRSIZE)
1261 sym_link *type = operandType (op);
1262 if (IS_GENPTR (type))
1264 /* generic pointer; arithmetic operations
1265 * should ignore the high byte (pointer type).
1273 /*-----------------------------------------------------------------*/
1274 /* outAcc - output Acc */
1275 /*-----------------------------------------------------------------*/
1277 outAcc (operand * result)
1280 size = getDataSize (result);
1283 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1286 /* unsigned or positive */
1289 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1294 /*-----------------------------------------------------------------*/
1295 /* outBitC - output a bit C */
1296 /*-----------------------------------------------------------------*/
1298 outBitC (operand * result)
1300 /* if the result is bit */
1301 if (AOP_TYPE (result) == AOP_CRY)
1302 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1305 emitcode ("clr", "a");
1306 emitcode ("rlc", "a");
1311 /*-----------------------------------------------------------------*/
1312 /* toBoolean - emit code for orl a,operator(sizeop) */
1313 /*-----------------------------------------------------------------*/
1315 toBoolean (operand * oper)
1317 int size = AOP_SIZE (oper) - 1;
1319 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1321 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1325 /*-----------------------------------------------------------------*/
1326 /* genNot - generate code for ! operation */
1327 /*-----------------------------------------------------------------*/
1333 D(emitcode ("; genNot",""));
1335 /* assign asmOps to operand & result */
1336 aopOp (IC_LEFT (ic), ic, FALSE);
1337 aopOp (IC_RESULT (ic), ic, TRUE);
1339 /* if in bit space then a special case */
1340 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1342 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1343 emitcode ("cpl", "c");
1344 outBitC (IC_RESULT (ic));
1348 toBoolean (IC_LEFT (ic));
1350 tlbl = newiTempLabel (NULL);
1351 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1352 emitcode ("", "%05d$:", tlbl->key + 100);
1353 outBitC (IC_RESULT (ic));
1356 /* release the aops */
1357 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1358 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1362 /*-----------------------------------------------------------------*/
1363 /* genCpl - generate code for complement */
1364 /*-----------------------------------------------------------------*/
1372 D(emitcode ("; genCpl",""));
1374 /* assign asmOps to operand & result */
1375 aopOp (IC_LEFT (ic), ic, FALSE);
1376 aopOp (IC_RESULT (ic), ic, TRUE);
1378 /* special case if in bit space */
1379 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1380 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1381 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1382 emitcode ("cpl", "c");
1383 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1386 tlbl=newiTempLabel(NULL);
1387 emitcode ("cjne", "%s,#0x01,%05d$",
1388 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1389 emitcode ("", "%05d$:", tlbl->key+100);
1390 outBitC (IC_RESULT(ic));
1394 size = AOP_SIZE (IC_RESULT (ic));
1397 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1399 emitcode ("cpl", "a");
1400 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1405 /* release the aops */
1406 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1407 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1410 /*-----------------------------------------------------------------*/
1411 /* genUminusFloat - unary minus for floating points */
1412 /*-----------------------------------------------------------------*/
1414 genUminusFloat (operand * op, operand * result)
1416 int size, offset = 0;
1419 D(emitcode ("; genUminusFloat",""));
1421 /* for this we just copy and then flip the bit */
1423 size = AOP_SIZE (op) - 1;
1427 aopPut (AOP (result),
1428 aopGet (AOP (op), offset, FALSE, FALSE),
1430 isOperandVolatile (result, FALSE));
1434 l = aopGet (AOP (op), offset, FALSE, FALSE);
1438 emitcode ("cpl", "acc.7");
1439 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1442 /*-----------------------------------------------------------------*/
1443 /* genUminus - unary minus code generation */
1444 /*-----------------------------------------------------------------*/
1446 genUminus (iCode * ic)
1449 sym_link *optype, *rtype;
1452 D(emitcode ("; genUminus",""));
1455 aopOp (IC_LEFT (ic), ic, FALSE);
1456 aopOp (IC_RESULT (ic), ic, TRUE);
1458 /* if both in bit space then special
1460 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1461 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1464 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1465 emitcode ("cpl", "c");
1466 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1470 optype = operandType (IC_LEFT (ic));
1471 rtype = operandType (IC_RESULT (ic));
1473 /* if float then do float stuff */
1474 if (IS_FLOAT (optype))
1476 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1480 /* otherwise subtract from zero */
1481 size = AOP_SIZE (IC_LEFT (ic));
1486 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1487 if (!strcmp (l, "a"))
1491 emitcode ("cpl", "a");
1492 emitcode ("addc", "a,#0");
1498 emitcode ("clr", "a");
1499 emitcode ("subb", "a,%s", l);
1501 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1504 /* if any remaining bytes in the result */
1505 /* we just need to propagate the sign */
1506 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1508 emitcode ("rlc", "a");
1509 emitcode ("subb", "a,acc");
1511 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1515 /* release the aops */
1516 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1517 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1520 /*-----------------------------------------------------------------*/
1521 /* saveRegisters - will look for a call and save the registers */
1522 /*-----------------------------------------------------------------*/
1524 saveRegisters (iCode * lic)
1531 for (ic = lic; ic; ic = ic->next)
1532 if (ic->op == CALL || ic->op == PCALL)
1537 fprintf (stderr, "found parameter push with no function call\n");
1541 /* if the registers have been saved already or don't need to be then
1545 if (IS_SYMOP(IC_LEFT(ic)) &&
1546 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1547 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1550 /* safe the registers in use at this time but skip the
1551 ones for the result */
1552 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1553 mcs51_rUmaskForOp (IC_RESULT(ic)));
1556 if (options.useXstack)
1558 if (bitVectBitValue (rsave, R0_IDX))
1559 emitcode ("mov", "b,r0");
1560 emitcode ("mov", "r0,%s", spname);
1561 for (i = 0; i < mcs51_nRegs; i++)
1563 if (bitVectBitValue (rsave, i))
1566 emitcode ("mov", "a,b");
1568 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1569 emitcode ("movx", "@r0,a");
1570 emitcode ("inc", "r0");
1573 emitcode ("mov", "%s,r0", spname);
1574 if (bitVectBitValue (rsave, R0_IDX))
1575 emitcode ("mov", "r0,b");
1578 for (i = 0; i < mcs51_nRegs; i++)
1580 if (bitVectBitValue (rsave, i))
1581 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1585 /*-----------------------------------------------------------------*/
1586 /* unsaveRegisters - pop the pushed registers */
1587 /*-----------------------------------------------------------------*/
1589 unsaveRegisters (iCode * ic)
1594 /* restore the registers in use at this time but skip the
1595 ones for the result */
1596 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1597 mcs51_rUmaskForOp (IC_RESULT(ic)));
1599 if (options.useXstack)
1601 emitcode ("mov", "r0,%s", spname);
1602 for (i = mcs51_nRegs; i >= 0; i--)
1604 if (bitVectBitValue (rsave, i))
1606 emitcode ("dec", "r0");
1607 emitcode ("movx", "a,@r0");
1609 emitcode ("mov", "b,a");
1611 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1615 emitcode ("mov", "%s,r0", spname);
1616 if (bitVectBitValue (rsave, R0_IDX))
1617 emitcode ("mov", "r0,b");
1620 for (i = mcs51_nRegs; i >= 0; i--)
1622 if (bitVectBitValue (rsave, i))
1623 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1629 /*-----------------------------------------------------------------*/
1631 /*-----------------------------------------------------------------*/
1633 pushSide (operand * oper, int size)
1638 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1639 if (AOP_TYPE (oper) != AOP_REG &&
1640 AOP_TYPE (oper) != AOP_DIR &&
1643 emitcode ("mov", "a,%s", l);
1644 emitcode ("push", "acc");
1647 emitcode ("push", "%s", l);
1651 /*-----------------------------------------------------------------*/
1652 /* assignResultValue - */
1653 /*-----------------------------------------------------------------*/
1655 assignResultValue (operand * oper)
1658 int size = AOP_SIZE (oper);
1661 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1667 /*-----------------------------------------------------------------*/
1668 /* genXpush - pushes onto the external stack */
1669 /*-----------------------------------------------------------------*/
1671 genXpush (iCode * ic)
1673 asmop *aop = newAsmop (0);
1675 int size, offset = 0;
1677 D(emitcode ("; genXpush",""));
1679 aopOp (IC_LEFT (ic), ic, FALSE);
1680 r = getFreePtr (ic, &aop, FALSE);
1683 emitcode ("mov", "%s,_spx", r->name);
1685 size = AOP_SIZE (IC_LEFT (ic));
1689 char *l = aopGet (AOP (IC_LEFT (ic)),
1690 offset++, FALSE, FALSE);
1692 emitcode ("movx", "@%s,a", r->name);
1693 emitcode ("inc", "%s", r->name);
1698 emitcode ("mov", "_spx,%s", r->name);
1700 freeAsmop (NULL, aop, ic, TRUE);
1701 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1704 /*-----------------------------------------------------------------*/
1705 /* genIpush - genrate code for pushing this gets a little complex */
1706 /*-----------------------------------------------------------------*/
1708 genIpush (iCode * ic)
1710 int size, offset = 0;
1713 D(emitcode ("; genIpush",""));
1715 /* if this is not a parm push : ie. it is spill push
1716 and spill push is always done on the local stack */
1720 /* and the item is spilt then do nothing */
1721 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1724 aopOp (IC_LEFT (ic), ic, FALSE);
1725 size = AOP_SIZE (IC_LEFT (ic));
1726 /* push it on the stack */
1729 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1735 emitcode ("push", "%s", l);
1740 /* this is a paramter push: in this case we call
1741 the routine to find the call and save those
1742 registers that need to be saved */
1745 /* if use external stack then call the external
1746 stack pushing routine */
1747 if (options.useXstack)
1753 /* then do the push */
1754 aopOp (IC_LEFT (ic), ic, FALSE);
1757 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1758 size = AOP_SIZE (IC_LEFT (ic));
1762 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1763 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1764 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1767 emitcode ("mov", "a,%s", l);
1768 emitcode ("push", "acc");
1771 emitcode ("push", "%s", l);
1774 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1777 /*-----------------------------------------------------------------*/
1778 /* genIpop - recover the registers: can happen only for spilling */
1779 /*-----------------------------------------------------------------*/
1781 genIpop (iCode * ic)
1785 D(emitcode ("; genIpop",""));
1787 /* if the temp was not pushed then */
1788 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1791 aopOp (IC_LEFT (ic), ic, FALSE);
1792 size = AOP_SIZE (IC_LEFT (ic));
1793 offset = (size - 1);
1795 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1798 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1801 /*-----------------------------------------------------------------*/
1802 /* unsaveRBank - restores the resgister bank from stack */
1803 /*-----------------------------------------------------------------*/
1805 unsaveRBank (int bank, iCode * ic, bool popPsw)
1811 if (options.useXstack)
1815 /* Assume r0 is available for use. */
1816 r = mcs51_regWithIdx (R0_IDX);;
1821 r = getFreePtr (ic, &aop, FALSE);
1823 emitcode ("mov", "%s,_spx", r->name);
1828 if (options.useXstack)
1830 emitcode ("movx", "a,@%s", r->name);
1831 emitcode ("mov", "psw,a");
1832 emitcode ("dec", "%s", r->name);
1836 emitcode ("pop", "psw");
1840 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1842 if (options.useXstack)
1844 emitcode ("movx", "a,@%s", r->name);
1845 emitcode ("mov", "(%s+%d),a",
1846 regs8051[i].base, 8 * bank + regs8051[i].offset);
1847 emitcode ("dec", "%s", r->name);
1851 emitcode ("pop", "(%s+%d)",
1852 regs8051[i].base, 8 * bank + regs8051[i].offset);
1855 if (options.useXstack)
1857 emitcode ("mov", "_spx,%s", r->name);
1862 freeAsmop (NULL, aop, ic, TRUE);
1866 /*-----------------------------------------------------------------*/
1867 /* saveRBank - saves an entire register bank on the stack */
1868 /*-----------------------------------------------------------------*/
1870 saveRBank (int bank, iCode * ic, bool pushPsw)
1876 if (options.useXstack)
1880 /* Assume r0 is available for use. */
1881 r = mcs51_regWithIdx (R0_IDX);;
1886 r = getFreePtr (ic, &aop, FALSE);
1888 emitcode ("mov", "%s,_spx", r->name);
1891 for (i = 0; i < mcs51_nRegs; i++)
1893 if (options.useXstack)
1895 emitcode ("inc", "%s", r->name);
1896 emitcode ("mov", "a,(%s+%d)",
1897 regs8051[i].base, 8 * bank + regs8051[i].offset);
1898 emitcode ("movx", "@%s,a", r->name);
1901 emitcode ("push", "(%s+%d)",
1902 regs8051[i].base, 8 * bank + regs8051[i].offset);
1907 if (options.useXstack)
1909 emitcode ("mov", "a,psw");
1910 emitcode ("movx", "@%s,a", r->name);
1911 emitcode ("inc", "%s", r->name);
1912 emitcode ("mov", "_spx,%s", r->name);
1917 emitcode ("push", "psw");
1920 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1925 freeAsmop (NULL, aop, ic, TRUE);
1934 /*-----------------------------------------------------------------*/
1935 /* genSend - gen code for SEND */
1936 /*-----------------------------------------------------------------*/
1937 static void genSend(set *sendSet)
1942 for (sic = setFirstItem (_G.sendSet); sic;
1943 sic = setNextItem (_G.sendSet)) {
1944 int size, offset = 0;
1945 aopOp (IC_LEFT (sic), sic, FALSE);
1946 size = AOP_SIZE (IC_LEFT (sic));
1948 if (sic->argreg == 1) {
1950 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1952 if (strcmp (l, fReturn[offset]))
1953 emitcode ("mov", "%s,%s", fReturn[offset], l);
1959 emitcode ("mov","b1_%d,%s",rb1_count++,
1960 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1963 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1967 /*-----------------------------------------------------------------*/
1968 /* genCall - generates a call statement */
1969 /*-----------------------------------------------------------------*/
1971 genCall (iCode * ic)
1974 // bool restoreBank = FALSE;
1975 bool swapBanks = FALSE;
1977 D(emitcode("; genCall",""));
1979 dtype = operandType (IC_LEFT (ic));
1980 /* if send set is not empty the assign */
1983 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1984 genSend(reverseSet(_G.sendSet));
1986 genSend(_G.sendSet);
1992 /* if we are calling a not _naked function that is not using
1993 the same register bank then we need to save the
1994 destination registers on the stack */
1995 dtype = operandType (IC_LEFT (ic));
1996 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1997 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1998 !IFFUNC_ISISR (dtype))
2003 /* if caller saves & we have not saved then */
2009 emitcode ("mov", "psw,#0x%02x",
2010 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2014 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2015 OP_SYMBOL (IC_LEFT (ic))->rname :
2016 OP_SYMBOL (IC_LEFT (ic))->name));
2020 emitcode ("mov", "psw,#0x%02x",
2021 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2024 /* if we need assign a result value */
2025 if ((IS_ITEMP (IC_RESULT (ic)) &&
2026 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2027 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2028 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2029 IS_TRUE_SYMOP (IC_RESULT (ic)))
2033 aopOp (IC_RESULT (ic), ic, FALSE);
2036 assignResultValue (IC_RESULT (ic));
2038 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2041 /* adjust the stack for parameters if
2046 if (ic->parmBytes > 3)
2048 emitcode ("mov", "a,%s", spname);
2049 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2050 emitcode ("mov", "%s,a", spname);
2053 for (i = 0; i < ic->parmBytes; i++)
2054 emitcode ("dec", "%s", spname);
2057 /* if we hade saved some registers then unsave them */
2058 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2059 unsaveRegisters (ic);
2061 // /* if register bank was saved then pop them */
2063 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2066 /*-----------------------------------------------------------------*/
2067 /* -10l - generates a call by pointer statement */
2068 /*-----------------------------------------------------------------*/
2070 genPcall (iCode * ic)
2073 symbol *rlbl = newiTempLabel (NULL);
2074 // bool restoreBank=FALSE;
2075 bool swapBanks = FALSE;
2077 D(emitcode("; genPCall",""));
2079 /* if caller saves & we have not saved then */
2083 /* if we are calling a not _naked function that is not using
2084 the same register bank then we need to save the
2085 destination registers on the stack */
2086 dtype = operandType (IC_LEFT (ic))->next;
2087 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2088 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2089 !IFFUNC_ISISR (dtype))
2091 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2092 // restoreBank=TRUE;
2094 // need caution message to user here
2097 /* push the return address on to the stack */
2098 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2099 emitcode ("push", "acc");
2100 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2101 emitcode ("push", "acc");
2103 /* now push the calling address */
2104 aopOp (IC_LEFT (ic), ic, FALSE);
2106 pushSide (IC_LEFT (ic), FPTRSIZE);
2108 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2110 /* if send set is not empty the assign */
2113 genSend(reverseSet(_G.sendSet));
2119 emitcode ("mov", "psw,#0x%02x",
2120 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2124 emitcode ("ret", "");
2125 emitcode ("", "%05d$:", (rlbl->key + 100));
2130 emitcode ("mov", "psw,#0x%02x",
2131 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2134 /* if we need assign a result value */
2135 if ((IS_ITEMP (IC_RESULT (ic)) &&
2136 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2137 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2138 IS_TRUE_SYMOP (IC_RESULT (ic)))
2142 aopOp (IC_RESULT (ic), ic, FALSE);
2145 assignResultValue (IC_RESULT (ic));
2147 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2150 /* adjust the stack for parameters if
2155 if (ic->parmBytes > 3)
2157 emitcode ("mov", "a,%s", spname);
2158 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2159 emitcode ("mov", "%s,a", spname);
2162 for (i = 0; i < ic->parmBytes; i++)
2163 emitcode ("dec", "%s", spname);
2167 // /* if register bank was saved then unsave them */
2169 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2171 /* if we hade saved some registers then
2173 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2174 unsaveRegisters (ic);
2177 /*-----------------------------------------------------------------*/
2178 /* resultRemat - result is rematerializable */
2179 /*-----------------------------------------------------------------*/
2181 resultRemat (iCode * ic)
2183 if (SKIP_IC (ic) || ic->op == IFX)
2186 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2188 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2189 if (sym->remat && !POINTER_SET (ic))
2196 #if defined(__BORLANDC__) || defined(_MSC_VER)
2197 #define STRCASECMP stricmp
2199 #define STRCASECMP strcasecmp
2202 /*-----------------------------------------------------------------*/
2203 /* inExcludeList - return 1 if the string is in exclude Reg list */
2204 /*-----------------------------------------------------------------*/
2206 regsCmp(void *p1, void *p2)
2208 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2212 inExcludeList (char *s)
2214 const char *p = setFirstItem(options.excludeRegsSet);
2216 if (p == NULL || STRCASECMP(p, "none") == 0)
2220 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2223 /*-----------------------------------------------------------------*/
2224 /* genFunction - generated code for function entry */
2225 /*-----------------------------------------------------------------*/
2227 genFunction (iCode * ic)
2231 bool switchedPSW = FALSE;
2232 int calleesaves_saved_register = -1;
2235 /* create the function header */
2236 emitcode (";", "-----------------------------------------");
2237 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2238 emitcode (";", "-----------------------------------------");
2240 emitcode ("", "%s:", sym->rname);
2241 ftype = operandType (IC_LEFT (ic));
2243 if (IFFUNC_ISNAKED(ftype))
2245 emitcode(";", "naked function: no prologue.");
2249 /* if critical function then turn interrupts off */
2250 if (IFFUNC_ISCRITICAL (ftype))
2251 emitcode ("clr", "ea");
2253 /* here we need to generate the equates for the
2254 register bank if required */
2255 if (FUNC_REGBANK (ftype) != rbank)
2259 rbank = FUNC_REGBANK (ftype);
2260 for (i = 0; i < mcs51_nRegs; i++)
2262 if (strcmp (regs8051[i].base, "0") == 0)
2263 emitcode ("", "%s = 0x%02x",
2265 8 * rbank + regs8051[i].offset);
2267 emitcode ("", "%s = %s + 0x%02x",
2270 8 * rbank + regs8051[i].offset);
2274 /* if this is an interrupt service routine then
2275 save acc, b, dpl, dph */
2276 if (IFFUNC_ISISR (sym->type))
2279 if (!inExcludeList ("acc"))
2280 emitcode ("push", "acc");
2281 if (!inExcludeList ("b"))
2282 emitcode ("push", "b");
2283 if (!inExcludeList ("dpl"))
2284 emitcode ("push", "dpl");
2285 if (!inExcludeList ("dph"))
2286 emitcode ("push", "dph");
2287 /* if this isr has no bank i.e. is going to
2288 run with bank 0 , then we need to save more
2290 if (!FUNC_REGBANK (sym->type))
2293 /* if this function does not call any other
2294 function then we can be economical and
2295 save only those registers that are used */
2296 if (!IFFUNC_HASFCALL(sym->type))
2300 /* if any registers used */
2303 /* save the registers used */
2304 for (i = 0; i < sym->regsUsed->size; i++)
2306 if (bitVectBitValue (sym->regsUsed, i) ||
2307 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2308 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2316 /* this function has a function call cannot
2317 determines register usage so we will have to push the
2319 saveRBank (0, ic, FALSE);
2320 if (options.parms_in_bank1) {
2322 for (i=0; i < 8 ; i++ ) {
2323 emitcode ("push","%s",rb1regs[i]);
2330 /* This ISR uses a non-zero bank.
2332 * We assume that the bank is available for our
2335 * However, if this ISR calls a function which uses some
2336 * other bank, we must save that bank entirely.
2338 unsigned long banksToSave = 0;
2340 if (IFFUNC_HASFCALL(sym->type))
2343 #define MAX_REGISTER_BANKS 4
2348 for (i = ic; i; i = i->next)
2350 if (i->op == ENDFUNCTION)
2352 /* we got to the end OK. */
2360 dtype = operandType (IC_LEFT(i));
2362 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2364 /* Mark this bank for saving. */
2365 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2367 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2371 banksToSave |= (1 << FUNC_REGBANK(dtype));
2374 /* And note that we don't need to do it in
2382 /* This is a mess; we have no idea what
2383 * register bank the called function might
2386 * The only thing I can think of to do is
2387 * throw a warning and hope.
2389 werror(W_FUNCPTR_IN_USING_ISR);
2393 if (banksToSave && options.useXstack)
2395 /* Since we aren't passing it an ic,
2396 * saveRBank will assume r0 is available to abuse.
2398 * So switch to our (trashable) bank now, so
2399 * the caller's R0 isn't trashed.
2401 emitcode ("push", "psw");
2402 emitcode ("mov", "psw,#0x%02x",
2403 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2407 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2409 if (banksToSave & (1 << ix))
2411 saveRBank(ix, NULL, FALSE);
2415 // TODO: this needs a closer look
2416 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2421 /* if callee-save to be used for this function
2422 then save the registers being used in this function */
2423 if (IFFUNC_CALLEESAVES(sym->type))
2427 /* if any registers used */
2430 /* save the registers used */
2431 for (i = 0; i < sym->regsUsed->size; i++)
2433 if (bitVectBitValue (sym->regsUsed, i) ||
2434 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2436 /* remember one saved register for later usage */
2437 if (calleesaves_saved_register < 0)
2438 calleesaves_saved_register = i;
2439 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2447 /* set the register bank to the desired value */
2448 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2451 emitcode ("push", "psw");
2452 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2455 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2458 if (options.useXstack)
2460 emitcode ("mov", "r0,%s", spname);
2461 emitcode ("mov", "a,_bp");
2462 emitcode ("movx", "@r0,a");
2463 emitcode ("inc", "%s", spname);
2467 /* set up the stack */
2468 emitcode ("push", "_bp"); /* save the callers stack */
2470 emitcode ("mov", "_bp,%s", spname);
2473 /* adjust the stack for the function */
2479 werror (W_STACK_OVERFLOW, sym->name);
2481 if (i > 3 && sym->recvSize < 4)
2484 emitcode ("mov", "a,sp");
2485 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2486 emitcode ("mov", "sp,a");
2491 if (IFFUNC_CALLEESAVES(sym->type))
2493 /* if it's a callee-saves function we need a saved register */
2494 if (calleesaves_saved_register >= 0)
2496 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2497 emitcode ("mov", "a,sp");
2498 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2499 emitcode ("mov", "sp,a");
2500 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2503 /* do it the hard way */
2505 emitcode ("inc", "sp");
2509 /* not callee-saves, we can clobber r0 */
2510 emitcode ("mov", "r0,a");
2511 emitcode ("mov", "a,sp");
2512 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2513 emitcode ("mov", "sp,a");
2514 emitcode ("mov", "a,r0");
2519 emitcode ("inc", "sp");
2525 emitcode ("mov", "a,_spx");
2526 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2527 emitcode ("mov", "_spx,a");
2532 /*-----------------------------------------------------------------*/
2533 /* genEndFunction - generates epilogue for functions */
2534 /*-----------------------------------------------------------------*/
2536 genEndFunction (iCode * ic)
2538 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2540 if (IFFUNC_ISNAKED(sym->type))
2542 emitcode(";", "naked function: no epilogue.");
2546 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2548 emitcode ("mov", "%s,_bp", spname);
2551 /* if use external stack but some variables were
2552 added to the local stack then decrement the
2554 if (options.useXstack && sym->stack)
2556 emitcode ("mov", "a,sp");
2557 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2558 emitcode ("mov", "sp,a");
2562 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2564 if (options.useXstack)
2566 emitcode ("mov", "r0,%s", spname);
2567 emitcode ("movx", "a,@r0");
2568 emitcode ("mov", "_bp,a");
2569 emitcode ("dec", "%s", spname);
2573 emitcode ("pop", "_bp");
2577 /* restore the register bank */
2578 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2580 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2581 || !options.useXstack)
2583 /* Special case of ISR using non-zero bank with useXstack
2586 emitcode ("pop", "psw");
2590 if (IFFUNC_ISISR (sym->type))
2593 /* now we need to restore the registers */
2594 /* if this isr has no bank i.e. is going to
2595 run with bank 0 , then we need to save more
2597 if (!FUNC_REGBANK (sym->type))
2599 /* if this function does not call any other
2600 function then we can be economical and
2601 save only those registers that are used */
2602 if (!IFFUNC_HASFCALL(sym->type))
2606 /* if any registers used */
2609 /* save the registers used */
2610 for (i = sym->regsUsed->size; i >= 0; i--)
2612 if (bitVectBitValue (sym->regsUsed, i) ||
2613 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2614 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2621 if (options.parms_in_bank1) {
2623 for (i = 7 ; i >= 0 ; i-- ) {
2624 emitcode ("pop","%s",rb1regs[i]);
2627 /* this function has a function call cannot
2628 determines register usage so we will have to pop the
2630 unsaveRBank (0, ic, FALSE);
2635 /* This ISR uses a non-zero bank.
2637 * Restore any register banks saved by genFunction
2640 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2643 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2645 if (savedBanks & (1 << ix))
2647 unsaveRBank(ix, NULL, FALSE);
2651 if (options.useXstack)
2653 /* Restore bank AFTER calling unsaveRBank,
2654 * since it can trash r0.
2656 emitcode ("pop", "psw");
2660 if (!inExcludeList ("dph"))
2661 emitcode ("pop", "dph");
2662 if (!inExcludeList ("dpl"))
2663 emitcode ("pop", "dpl");
2664 if (!inExcludeList ("b"))
2665 emitcode ("pop", "b");
2666 if (!inExcludeList ("acc"))
2667 emitcode ("pop", "acc");
2669 if (IFFUNC_ISCRITICAL (sym->type))
2670 emitcode ("setb", "ea");
2672 /* if debug then send end of function */
2673 if (options.debug && currFunc)
2676 emitcode ("", "C$%s$%d$%d$%d ==.",
2677 FileBaseName (ic->filename), currFunc->lastLine,
2678 ic->level, ic->block);
2679 if (IS_STATIC (currFunc->etype))
2680 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2682 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2686 emitcode ("reti", "");
2690 if (IFFUNC_ISCRITICAL (sym->type))
2691 emitcode ("setb", "ea");
2693 if (IFFUNC_CALLEESAVES(sym->type))
2697 /* if any registers used */
2700 /* save the registers used */
2701 for (i = sym->regsUsed->size; i >= 0; i--)
2703 if (bitVectBitValue (sym->regsUsed, i) ||
2704 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2705 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2711 /* if debug then send end of function */
2712 if (options.debug && currFunc)
2715 emitcode ("", "C$%s$%d$%d$%d ==.",
2716 FileBaseName (ic->filename), currFunc->lastLine,
2717 ic->level, ic->block);
2718 if (IS_STATIC (currFunc->etype))
2719 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2721 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2725 emitcode ("ret", "");
2730 /*-----------------------------------------------------------------*/
2731 /* genRet - generate code for return statement */
2732 /*-----------------------------------------------------------------*/
2736 int size, offset = 0, pushed = 0;
2738 D(emitcode ("; genRet",""));
2740 /* if we have no return value then
2741 just generate the "ret" */
2745 /* we have something to return then
2746 move the return value into place */
2747 aopOp (IC_LEFT (ic), ic, FALSE);
2748 size = AOP_SIZE (IC_LEFT (ic));
2753 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2756 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2758 emitcode ("push", "%s", l);
2763 l = aopGet (AOP (IC_LEFT (ic)), offset,
2765 if (strcmp (fReturn[offset], l))
2766 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2775 if (strcmp (fReturn[pushed], "a"))
2776 emitcode ("pop", fReturn[pushed]);
2778 emitcode ("pop", "acc");
2781 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2784 /* generate a jump to the return label
2785 if the next is not the return statement */
2786 if (!(ic->next && ic->next->op == LABEL &&
2787 IC_LABEL (ic->next) == returnLabel))
2789 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2793 /*-----------------------------------------------------------------*/
2794 /* genLabel - generates a label */
2795 /*-----------------------------------------------------------------*/
2797 genLabel (iCode * ic)
2799 /* special case never generate */
2800 if (IC_LABEL (ic) == entryLabel)
2803 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2806 /*-----------------------------------------------------------------*/
2807 /* genGoto - generates a ljmp */
2808 /*-----------------------------------------------------------------*/
2810 genGoto (iCode * ic)
2812 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2815 /*-----------------------------------------------------------------*/
2816 /* findLabelBackwards: walks back through the iCode chain looking */
2817 /* for the given label. Returns number of iCode instructions */
2818 /* between that label and given ic. */
2819 /* Returns zero if label not found. */
2820 /*-----------------------------------------------------------------*/
2822 findLabelBackwards (iCode * ic, int key)
2831 /* If we have any pushes or pops, we cannot predict the distance.
2832 I don't like this at all, this should be dealt with in the
2834 if (ic->op == IPUSH || ic->op == IPOP) {
2838 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2847 /*-----------------------------------------------------------------*/
2848 /* genPlusIncr :- does addition with increment if possible */
2849 /*-----------------------------------------------------------------*/
2851 genPlusIncr (iCode * ic)
2853 unsigned int icount;
2854 unsigned int size = getDataSize (IC_RESULT (ic));
2856 /* will try to generate an increment */
2857 /* if the right side is not a literal
2859 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2862 /* if the literal value of the right hand side
2863 is greater than 4 then it is not worth it */
2864 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2867 D(emitcode ("; genPlusIncr",""));
2869 /* if increment >=16 bits in register or direct space */
2870 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2871 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2879 /* If the next instruction is a goto and the goto target
2880 * is < 10 instructions previous to this, we can generate
2881 * jumps straight to that target.
2883 if (ic->next && ic->next->op == GOTO
2884 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2885 && labelRange <= 10)
2887 emitcode (";", "tail increment optimized");
2888 tlbl = IC_LABEL (ic->next);
2893 tlbl = newiTempLabel (NULL);
2896 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2897 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2898 IS_AOP_PREG (IC_RESULT (ic)))
2899 emitcode ("cjne", "%s,#0x00,%05d$",
2900 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2904 emitcode ("clr", "a");
2905 emitcode ("cjne", "a,%s,%05d$",
2906 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2910 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2913 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2914 IS_AOP_PREG (IC_RESULT (ic)))
2915 emitcode ("cjne", "%s,#0x00,%05d$",
2916 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2919 emitcode ("cjne", "a,%s,%05d$",
2920 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2923 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2927 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2928 IS_AOP_PREG (IC_RESULT (ic)))
2929 emitcode ("cjne", "%s,#0x00,%05d$",
2930 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2934 emitcode ("cjne", "a,%s,%05d$",
2935 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2938 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2943 emitcode ("", "%05d$:", tlbl->key + 100);
2948 /* if the sizes are greater than 1 then we cannot */
2949 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2950 AOP_SIZE (IC_LEFT (ic)) > 1)
2953 /* we can if the aops of the left & result match or
2954 if they are in registers and the registers are the
2956 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2961 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2962 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2963 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
2969 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2978 /*-----------------------------------------------------------------*/
2979 /* outBitAcc - output a bit in acc */
2980 /*-----------------------------------------------------------------*/
2982 outBitAcc (operand * result)
2984 symbol *tlbl = newiTempLabel (NULL);
2985 /* if the result is a bit */
2986 if (AOP_TYPE (result) == AOP_CRY)
2988 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
2992 emitcode ("jz", "%05d$", tlbl->key + 100);
2993 emitcode ("mov", "a,%s", one);
2994 emitcode ("", "%05d$:", tlbl->key + 100);
2999 /*-----------------------------------------------------------------*/
3000 /* genPlusBits - generates code for addition of two bits */
3001 /*-----------------------------------------------------------------*/
3003 genPlusBits (iCode * ic)
3005 D(emitcode ("; genPlusBits",""));
3007 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3009 symbol *lbl = newiTempLabel (NULL);
3010 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3011 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3012 emitcode ("cpl", "c");
3013 emitcode ("", "%05d$:", (lbl->key + 100));
3014 outBitC (IC_RESULT (ic));
3018 emitcode ("clr", "a");
3019 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3020 emitcode ("rlc", "a");
3021 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3022 emitcode ("addc", "a,#0x00");
3023 outAcc (IC_RESULT (ic));
3028 /* This is the original version of this code.
3030 * This is being kept around for reference,
3031 * because I am not entirely sure I got it right...
3034 adjustArithmeticResult (iCode * ic)
3036 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3037 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3038 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3039 aopPut (AOP (IC_RESULT (ic)),
3040 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3042 isOperandVolatile (IC_RESULT (ic), FALSE));
3044 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3045 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3046 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3047 aopPut (AOP (IC_RESULT (ic)),
3048 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3050 isOperandVolatile (IC_RESULT (ic), FALSE));
3052 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3053 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3054 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3055 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3056 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3059 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3060 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3064 /* This is the pure and virtuous version of this code.
3065 * I'm pretty certain it's right, but not enough to toss the old
3069 adjustArithmeticResult (iCode * ic)
3071 if (opIsGptr (IC_RESULT (ic)) &&
3072 opIsGptr (IC_LEFT (ic)) &&
3073 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3075 aopPut (AOP (IC_RESULT (ic)),
3076 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3078 isOperandVolatile (IC_RESULT (ic), FALSE));
3081 if (opIsGptr (IC_RESULT (ic)) &&
3082 opIsGptr (IC_RIGHT (ic)) &&
3083 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3085 aopPut (AOP (IC_RESULT (ic)),
3086 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3088 isOperandVolatile (IC_RESULT (ic), FALSE));
3091 if (opIsGptr (IC_RESULT (ic)) &&
3092 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3093 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3094 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3095 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3098 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3099 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3104 /*-----------------------------------------------------------------*/
3105 /* genPlus - generates code for addition */
3106 /*-----------------------------------------------------------------*/
3108 genPlus (iCode * ic)
3110 int size, offset = 0;
3112 asmop *leftOp, *rightOp;
3114 /* special cases :- */
3116 D(emitcode ("; genPlus",""));
3118 aopOp (IC_LEFT (ic), ic, FALSE);
3119 aopOp (IC_RIGHT (ic), ic, FALSE);
3120 aopOp (IC_RESULT (ic), ic, TRUE);
3122 /* if literal, literal on the right or
3123 if left requires ACC or right is already
3125 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3126 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3127 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3129 operand *t = IC_RIGHT (ic);
3130 IC_RIGHT (ic) = IC_LEFT (ic);
3134 /* if both left & right are in bit
3136 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3137 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3143 /* if left in bit space & right literal */
3144 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3145 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3147 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3148 /* if result in bit space */
3149 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3151 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3152 emitcode ("cpl", "c");
3153 outBitC (IC_RESULT (ic));
3157 size = getDataSize (IC_RESULT (ic));
3160 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3161 emitcode ("addc", "a,#00");
3162 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3168 /* if I can do an increment instead
3169 of add then GOOD for ME */
3170 if (genPlusIncr (ic) == TRUE)
3173 size = getDataSize (IC_RESULT (ic));
3175 leftOp = AOP(IC_LEFT(ic));
3176 rightOp = AOP(IC_RIGHT(ic));
3181 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3183 emitcode("mov", "b,a");
3184 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3185 emitcode("xch", "a,b");
3186 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3187 emitcode (add, "a,b");
3189 else if (aopGetUsesAcc (leftOp, offset))
3191 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3192 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3196 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3197 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3199 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3200 add = "addc"; /* further adds must propagate carry */
3203 adjustArithmeticResult (ic);
3206 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3207 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3211 /*-----------------------------------------------------------------*/
3212 /* genMinusDec :- does subtraction with deccrement if possible */
3213 /*-----------------------------------------------------------------*/
3215 genMinusDec (iCode * ic)
3217 unsigned int icount;
3218 unsigned int size = getDataSize (IC_RESULT (ic));
3220 /* will try to generate an increment */
3221 /* if the right side is not a literal
3223 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3226 /* if the literal value of the right hand side
3227 is greater than 4 then it is not worth it */
3228 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3231 D(emitcode ("; genMinusDec",""));
3233 /* if decrement >=16 bits in register or direct space */
3234 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3235 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3243 /* If the next instruction is a goto and the goto target
3244 * is <= 10 instructions previous to this, we can generate
3245 * jumps straight to that target.
3247 if (ic->next && ic->next->op == GOTO
3248 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3249 && labelRange <= 10)
3251 emitcode (";", "tail decrement optimized");
3252 tlbl = IC_LABEL (ic->next);
3257 tlbl = newiTempLabel (NULL);
3261 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3262 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3263 IS_AOP_PREG (IC_RESULT (ic)))
3264 emitcode ("cjne", "%s,#0xff,%05d$"
3265 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3269 emitcode ("mov", "a,#0xff");
3270 emitcode ("cjne", "a,%s,%05d$"
3271 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3274 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3277 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3278 IS_AOP_PREG (IC_RESULT (ic)))
3279 emitcode ("cjne", "%s,#0xff,%05d$"
3280 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3284 emitcode ("cjne", "a,%s,%05d$"
3285 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3288 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3292 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3293 IS_AOP_PREG (IC_RESULT (ic)))
3294 emitcode ("cjne", "%s,#0xff,%05d$"
3295 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3299 emitcode ("cjne", "a,%s,%05d$"
3300 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3303 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3307 emitcode ("", "%05d$:", tlbl->key + 100);
3312 /* if the sizes are greater than 1 then we cannot */
3313 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3314 AOP_SIZE (IC_LEFT (ic)) > 1)
3317 /* we can if the aops of the left & result match or
3318 if they are in registers and the registers are the
3320 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3324 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3332 /*-----------------------------------------------------------------*/
3333 /* addSign - complete with sign */
3334 /*-----------------------------------------------------------------*/
3336 addSign (operand * result, int offset, int sign)
3338 int size = (getDataSize (result) - offset);
3343 emitcode ("rlc", "a");
3344 emitcode ("subb", "a,acc");
3346 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3350 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3354 /*-----------------------------------------------------------------*/
3355 /* genMinusBits - generates code for subtraction of two bits */
3356 /*-----------------------------------------------------------------*/
3358 genMinusBits (iCode * ic)
3360 symbol *lbl = newiTempLabel (NULL);
3362 D(emitcode ("; genMinusBits",""));
3364 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3366 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3367 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3368 emitcode ("cpl", "c");
3369 emitcode ("", "%05d$:", (lbl->key + 100));
3370 outBitC (IC_RESULT (ic));
3374 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3375 emitcode ("subb", "a,acc");
3376 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3377 emitcode ("inc", "a");
3378 emitcode ("", "%05d$:", (lbl->key + 100));
3379 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3380 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3384 /*-----------------------------------------------------------------*/
3385 /* genMinus - generates code for subtraction */
3386 /*-----------------------------------------------------------------*/
3388 genMinus (iCode * ic)
3390 int size, offset = 0;
3392 D(emitcode ("; genMinus",""));
3394 aopOp (IC_LEFT (ic), ic, FALSE);
3395 aopOp (IC_RIGHT (ic), ic, FALSE);
3396 aopOp (IC_RESULT (ic), ic, TRUE);
3398 /* special cases :- */
3399 /* if both left & right are in bit space */
3400 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3401 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3407 /* if I can do an decrement instead
3408 of subtract then GOOD for ME */
3409 if (genMinusDec (ic) == TRUE)
3412 size = getDataSize (IC_RESULT (ic));
3414 /* if literal, add a,#-lit, else normal subb */
3415 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3417 unsigned long lit = 0L;
3419 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3424 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3425 /* first add without previous c */
3427 if (!size && lit== (unsigned long) -1) {
3428 emitcode ("dec", "a");
3430 emitcode ("add", "a,#0x%02x",
3431 (unsigned int) (lit & 0x0FFL));
3434 emitcode ("addc", "a,#0x%02x",
3435 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3437 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3442 asmop *leftOp, *rightOp;
3444 leftOp = AOP(IC_LEFT(ic));
3445 rightOp = AOP(IC_RIGHT(ic));
3449 if (aopGetUsesAcc(rightOp, offset)) {
3450 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3451 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3453 emitcode( "setb", "c");
3455 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3456 emitcode("cpl", "a");
3458 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3461 emitcode ("subb", "a,%s",
3462 aopGet(rightOp, offset, FALSE, TRUE));
3465 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3470 adjustArithmeticResult (ic);
3473 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3474 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3475 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3479 /*-----------------------------------------------------------------*/
3480 /* genMultbits :- multiplication of bits */
3481 /*-----------------------------------------------------------------*/
3483 genMultbits (operand * left,
3487 D(emitcode ("; genMultbits",""));
3489 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3490 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3495 /*-----------------------------------------------------------------*/
3496 /* genMultOneByte : 8*8=8/16 bit multiplication */
3497 /*-----------------------------------------------------------------*/
3499 genMultOneByte (operand * left,
3503 sym_link *opetype = operandType (result);
3505 int size=AOP_SIZE(result);
3507 D(emitcode ("; genMultOneByte",""));
3509 if (size<1 || size>2) {
3510 // this should never happen
3511 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3512 AOP_SIZE(result), __FILE__, lineno);
3516 /* (if two literals: the value is computed before) */
3517 /* if one literal, literal on the right */
3518 if (AOP_TYPE (left) == AOP_LIT)
3523 //emitcode (";", "swapped left and right");
3526 if (SPEC_USIGN(opetype)
3527 // ignore the sign of left and right, what else can we do?
3528 || (SPEC_USIGN(operandType(left)) &&
3529 SPEC_USIGN(operandType(right)))) {
3530 // just an unsigned 8*8=8/16 multiply
3531 //emitcode (";","unsigned");
3532 // TODO: check for accumulator clash between left & right aops?
3533 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3534 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3535 emitcode ("mul", "ab");
3536 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3538 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3543 // we have to do a signed multiply
3545 //emitcode (";", "signed");
3546 emitcode ("clr", "F0"); // reset sign flag
3547 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3549 lbl=newiTempLabel(NULL);
3550 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3551 // left side is negative, 8-bit two's complement, this fails for -128
3552 emitcode ("setb", "F0"); // set sign flag
3553 emitcode ("cpl", "a");
3554 emitcode ("inc", "a");
3556 emitcode ("", "%05d$:", lbl->key+100);
3559 if (AOP_TYPE(right)==AOP_LIT) {
3560 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3561 /* AND literal negative */
3563 emitcode ("cpl", "F0"); // complement sign flag
3564 emitcode ("mov", "b,#0x%02x", -val);
3566 emitcode ("mov", "b,#0x%02x", val);
3569 lbl=newiTempLabel(NULL);
3570 emitcode ("mov", "b,a");
3571 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3572 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3573 // right side is negative, 8-bit two's complement
3574 emitcode ("cpl", "F0"); // complement sign flag
3575 emitcode ("cpl", "a");
3576 emitcode ("inc", "a");
3577 emitcode ("", "%05d$:", lbl->key+100);
3579 emitcode ("mul", "ab");
3581 lbl=newiTempLabel(NULL);
3582 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3583 // only ONE op was negative, we have to do a 8/16-bit two's complement
3584 emitcode ("cpl", "a"); // lsb
3586 emitcode ("inc", "a");
3588 emitcode ("add", "a,#1");
3589 emitcode ("xch", "a,b");
3590 emitcode ("cpl", "a"); // msb
3591 emitcode ("addc", "a,#0");
3592 emitcode ("xch", "a,b");
3595 emitcode ("", "%05d$:", lbl->key+100);
3596 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3598 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3602 /*-----------------------------------------------------------------*/
3603 /* genMult - generates code for multiplication */
3604 /*-----------------------------------------------------------------*/
3606 genMult (iCode * ic)
3608 operand *left = IC_LEFT (ic);
3609 operand *right = IC_RIGHT (ic);
3610 operand *result = IC_RESULT (ic);
3612 D(emitcode ("; genMult",""));
3614 /* assign the amsops */
3615 aopOp (left, ic, FALSE);
3616 aopOp (right, ic, FALSE);
3617 aopOp (result, ic, TRUE);
3619 /* special cases first */
3621 if (AOP_TYPE (left) == AOP_CRY &&
3622 AOP_TYPE (right) == AOP_CRY)
3624 genMultbits (left, right, result);
3628 /* if both are of size == 1 */
3629 #if 0 // one of them can be a sloc shared with the result
3630 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3632 if (getSize(operandType(left)) == 1 &&
3633 getSize(operandType(right)) == 1)
3636 genMultOneByte (left, right, result);
3640 /* should have been converted to function call */
3641 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3642 getSize(OP_SYMBOL(right)->type));
3646 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3647 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3648 freeAsmop (result, NULL, ic, TRUE);
3651 /*-----------------------------------------------------------------*/
3652 /* genDivbits :- division of bits */
3653 /*-----------------------------------------------------------------*/
3655 genDivbits (operand * left,
3662 D(emitcode ("; genDivbits",""));
3664 /* the result must be bit */
3665 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3666 l = aopGet (AOP (left), 0, FALSE, FALSE);
3670 emitcode ("div", "ab");
3671 emitcode ("rrc", "a");
3672 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3675 /*-----------------------------------------------------------------*/
3676 /* genDivOneByte : 8 bit division */
3677 /*-----------------------------------------------------------------*/
3679 genDivOneByte (operand * left,
3683 sym_link *opetype = operandType (result);
3688 D(emitcode ("; genDivOneByte",""));
3690 size = AOP_SIZE (result) - 1;
3692 /* signed or unsigned */
3693 if (SPEC_USIGN (opetype))
3695 /* unsigned is easy */
3696 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3697 l = aopGet (AOP (left), 0, FALSE, FALSE);
3699 emitcode ("div", "ab");
3700 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3702 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3706 /* signed is a little bit more difficult */
3708 /* save the signs of the operands */
3709 l = aopGet (AOP (left), 0, FALSE, FALSE);
3711 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3712 emitcode ("push", "acc"); /* save it on the stack */
3714 /* now sign adjust for both left & right */
3715 l = aopGet (AOP (right), 0, FALSE, FALSE);
3717 lbl = newiTempLabel (NULL);
3718 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3719 emitcode ("cpl", "a");
3720 emitcode ("inc", "a");
3721 emitcode ("", "%05d$:", (lbl->key + 100));
3722 emitcode ("mov", "b,a");
3724 /* sign adjust left side */
3725 l = aopGet (AOP (left), 0, FALSE, FALSE);
3728 lbl = newiTempLabel (NULL);
3729 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3730 emitcode ("cpl", "a");
3731 emitcode ("inc", "a");
3732 emitcode ("", "%05d$:", (lbl->key + 100));
3734 /* now the division */
3735 emitcode ("div", "ab");
3736 /* we are interested in the lower order
3738 emitcode ("mov", "b,a");
3739 lbl = newiTempLabel (NULL);
3740 emitcode ("pop", "acc");
3741 /* if there was an over flow we don't
3742 adjust the sign of the result */
3743 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3744 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3746 emitcode ("clr", "a");
3747 emitcode ("subb", "a,b");
3748 emitcode ("mov", "b,a");
3749 emitcode ("", "%05d$:", (lbl->key + 100));
3751 /* now we are done */
3752 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3755 emitcode ("mov", "c,b.7");
3756 emitcode ("subb", "a,acc");
3759 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3763 /*-----------------------------------------------------------------*/
3764 /* genDiv - generates code for division */
3765 /*-----------------------------------------------------------------*/
3769 operand *left = IC_LEFT (ic);
3770 operand *right = IC_RIGHT (ic);
3771 operand *result = IC_RESULT (ic);
3773 D(emitcode ("; genDiv",""));
3775 /* assign the amsops */
3776 aopOp (left, ic, FALSE);
3777 aopOp (right, ic, FALSE);
3778 aopOp (result, ic, TRUE);
3780 /* special cases first */
3782 if (AOP_TYPE (left) == AOP_CRY &&
3783 AOP_TYPE (right) == AOP_CRY)
3785 genDivbits (left, right, result);
3789 /* if both are of size == 1 */
3790 if (AOP_SIZE (left) == 1 &&
3791 AOP_SIZE (right) == 1)
3793 genDivOneByte (left, right, result);
3797 /* should have been converted to function call */
3800 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3801 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3802 freeAsmop (result, NULL, ic, TRUE);
3805 /*-----------------------------------------------------------------*/
3806 /* genModbits :- modulus of bits */
3807 /*-----------------------------------------------------------------*/
3809 genModbits (operand * left,
3816 D(emitcode ("; genModbits",""));
3818 /* the result must be bit */
3819 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3820 l = aopGet (AOP (left), 0, FALSE, FALSE);
3824 emitcode ("div", "ab");
3825 emitcode ("mov", "a,b");
3826 emitcode ("rrc", "a");
3827 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3830 /*-----------------------------------------------------------------*/
3831 /* genModOneByte : 8 bit modulus */
3832 /*-----------------------------------------------------------------*/
3834 genModOneByte (operand * left,
3838 sym_link *opetype = operandType (result);
3842 D(emitcode ("; genModOneByte",""));
3844 /* signed or unsigned */
3845 if (SPEC_USIGN (opetype))
3847 /* unsigned is easy */
3848 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3849 l = aopGet (AOP (left), 0, FALSE, FALSE);
3851 emitcode ("div", "ab");
3852 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3856 /* signed is a little bit more difficult */
3858 /* save the signs of the operands */
3859 l = aopGet (AOP (left), 0, FALSE, FALSE);
3862 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3863 emitcode ("push", "acc"); /* save it on the stack */
3865 /* now sign adjust for both left & right */
3866 l = aopGet (AOP (right), 0, FALSE, FALSE);
3869 lbl = newiTempLabel (NULL);
3870 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3871 emitcode ("cpl", "a");
3872 emitcode ("inc", "a");
3873 emitcode ("", "%05d$:", (lbl->key + 100));
3874 emitcode ("mov", "b,a");
3876 /* sign adjust left side */
3877 l = aopGet (AOP (left), 0, FALSE, FALSE);
3880 lbl = newiTempLabel (NULL);
3881 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3882 emitcode ("cpl", "a");
3883 emitcode ("inc", "a");
3884 emitcode ("", "%05d$:", (lbl->key + 100));
3886 /* now the multiplication */
3887 emitcode ("div", "ab");
3888 /* we are interested in the lower order
3890 lbl = newiTempLabel (NULL);
3891 emitcode ("pop", "acc");
3892 /* if there was an over flow we don't
3893 adjust the sign of the result */
3894 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3895 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3897 emitcode ("clr", "a");
3898 emitcode ("subb", "a,b");
3899 emitcode ("mov", "b,a");
3900 emitcode ("", "%05d$:", (lbl->key + 100));
3902 /* now we are done */
3903 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3907 /*-----------------------------------------------------------------*/
3908 /* genMod - generates code for division */
3909 /*-----------------------------------------------------------------*/
3913 operand *left = IC_LEFT (ic);
3914 operand *right = IC_RIGHT (ic);
3915 operand *result = IC_RESULT (ic);
3917 D(emitcode ("; genMod",""));
3919 /* assign the amsops */
3920 aopOp (left, ic, FALSE);
3921 aopOp (right, ic, FALSE);
3922 aopOp (result, ic, TRUE);
3924 /* special cases first */
3926 if (AOP_TYPE (left) == AOP_CRY &&
3927 AOP_TYPE (right) == AOP_CRY)
3929 genModbits (left, right, result);
3933 /* if both are of size == 1 */
3934 if (AOP_SIZE (left) == 1 &&
3935 AOP_SIZE (right) == 1)
3937 genModOneByte (left, right, result);
3941 /* should have been converted to function call */
3945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3946 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3947 freeAsmop (result, NULL, ic, TRUE);
3950 /*-----------------------------------------------------------------*/
3951 /* genIfxJump :- will create a jump depending on the ifx */
3952 /*-----------------------------------------------------------------*/
3954 genIfxJump (iCode * ic, char *jval)
3957 symbol *tlbl = newiTempLabel (NULL);
3960 D(emitcode ("; genIfxJump",""));
3962 /* if true label then we jump if condition
3966 jlbl = IC_TRUE (ic);
3967 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3968 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3972 /* false label is present */
3973 jlbl = IC_FALSE (ic);
3974 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3975 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3977 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3978 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3980 emitcode (inst, "%05d$", tlbl->key + 100);
3981 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3982 emitcode ("", "%05d$:", tlbl->key + 100);
3984 /* mark the icode as generated */
3988 /*-----------------------------------------------------------------*/
3989 /* genCmp :- greater or less than comparison */
3990 /*-----------------------------------------------------------------*/
3992 genCmp (operand * left, operand * right,
3993 operand * result, iCode * ifx, int sign, iCode *ic)
3995 int size, offset = 0;
3996 unsigned long lit = 0L;
3999 D(emitcode ("; genCmp",""));
4001 /* if left & right are bit variables */
4002 if (AOP_TYPE (left) == AOP_CRY &&
4003 AOP_TYPE (right) == AOP_CRY)
4005 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4006 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4010 /* subtract right from left if at the
4011 end the carry flag is set then we know that
4012 left is greater than right */
4013 size = max (AOP_SIZE (left), AOP_SIZE (right));
4015 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4016 if ((size == 1) && !sign &&
4017 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4019 symbol *lbl = newiTempLabel (NULL);
4020 emitcode ("cjne", "%s,%s,%05d$",
4021 aopGet (AOP (left), offset, FALSE, FALSE),
4022 aopGet (AOP (right), offset, FALSE, FALSE),
4024 emitcode ("", "%05d$:", lbl->key + 100);
4028 if (AOP_TYPE (right) == AOP_LIT)
4030 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4031 /* optimize if(x < 0) or if(x >= 0) */
4040 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4041 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4043 genIfxJump (ifx, "acc.7");
4047 emitcode ("rlc", "a");
4055 rightInB = aopGetUsesAcc(AOP (right), offset);
4057 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4058 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4059 if (sign && size == 0)
4061 emitcode ("xrl", "a,#0x80");
4062 if (AOP_TYPE (right) == AOP_LIT)
4064 unsigned long lit = (unsigned long)
4065 floatFromVal (AOP (right)->aopu.aop_lit);
4066 emitcode ("subb", "a,#0x%02x",
4067 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4072 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4073 emitcode ("xrl", "b,#0x80");
4074 emitcode ("subb", "a,b");
4080 emitcode ("subb", "a,b");
4082 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4090 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4091 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4092 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4098 /* if the result is used in the next
4099 ifx conditional branch then generate
4100 code a little differently */
4102 genIfxJump (ifx, "c");
4105 /* leave the result in acc */
4109 /*-----------------------------------------------------------------*/
4110 /* genCmpGt :- greater than comparison */
4111 /*-----------------------------------------------------------------*/
4113 genCmpGt (iCode * ic, iCode * ifx)
4115 operand *left, *right, *result;
4116 sym_link *letype, *retype;
4119 D(emitcode ("; genCmpGt",""));
4121 left = IC_LEFT (ic);
4122 right = IC_RIGHT (ic);
4123 result = IC_RESULT (ic);
4125 letype = getSpec (operandType (left));
4126 retype = getSpec (operandType (right));
4127 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4128 /* assign the amsops */
4129 aopOp (left, ic, FALSE);
4130 aopOp (right, ic, FALSE);
4131 aopOp (result, ic, TRUE);
4133 genCmp (right, left, result, ifx, sign,ic);
4135 freeAsmop (result, NULL, ic, TRUE);
4138 /*-----------------------------------------------------------------*/
4139 /* genCmpLt - less than comparisons */
4140 /*-----------------------------------------------------------------*/
4142 genCmpLt (iCode * ic, iCode * ifx)
4144 operand *left, *right, *result;
4145 sym_link *letype, *retype;
4148 D(emitcode ("; genCmpLt",""));
4150 left = IC_LEFT (ic);
4151 right = IC_RIGHT (ic);
4152 result = IC_RESULT (ic);
4154 letype = getSpec (operandType (left));
4155 retype = getSpec (operandType (right));
4156 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4158 /* assign the amsops */
4159 aopOp (left, ic, FALSE);
4160 aopOp (right, ic, FALSE);
4161 aopOp (result, ic, TRUE);
4163 genCmp (left, right, result, ifx, sign,ic);
4165 freeAsmop (result, NULL, ic, TRUE);
4168 /*-----------------------------------------------------------------*/
4169 /* gencjneshort - compare and jump if not equal */
4170 /*-----------------------------------------------------------------*/
4172 gencjneshort (operand * left, operand * right, symbol * lbl)
4174 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4176 unsigned long lit = 0L;
4178 /* if the left side is a literal or
4179 if the right is in a pointer register and left
4181 if ((AOP_TYPE (left) == AOP_LIT) ||
4182 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4188 if (AOP_TYPE (right) == AOP_LIT)
4189 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4191 /* if the right side is a literal then anything goes */
4192 if (AOP_TYPE (right) == AOP_LIT &&
4193 AOP_TYPE (left) != AOP_DIR &&
4194 AOP_TYPE (left) != AOP_IMMD)
4198 emitcode ("cjne", "%s,%s,%05d$",
4199 aopGet (AOP (left), offset, FALSE, FALSE),
4200 aopGet (AOP (right), offset, FALSE, FALSE),
4206 /* if the right side is in a register or in direct space or
4207 if the left is a pointer register & right is not */
4208 else if (AOP_TYPE (right) == AOP_REG ||
4209 AOP_TYPE (right) == AOP_DIR ||
4210 AOP_TYPE (right) == AOP_LIT ||
4211 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4212 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4216 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4217 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4218 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4219 emitcode ("jnz", "%05d$", lbl->key + 100);
4221 emitcode ("cjne", "a,%s,%05d$",
4222 aopGet (AOP (right), offset, FALSE, TRUE),
4229 /* right is a pointer reg need both a & b */
4232 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4233 if (strcmp (l, "b"))
4234 emitcode ("mov", "b,%s", l);
4235 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4236 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4242 /*-----------------------------------------------------------------*/
4243 /* gencjne - compare and jump if not equal */
4244 /*-----------------------------------------------------------------*/
4246 gencjne (operand * left, operand * right, symbol * lbl)
4248 symbol *tlbl = newiTempLabel (NULL);
4250 gencjneshort (left, right, lbl);
4252 emitcode ("mov", "a,%s", one);
4253 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4254 emitcode ("", "%05d$:", lbl->key + 100);
4255 emitcode ("clr", "a");
4256 emitcode ("", "%05d$:", tlbl->key + 100);
4259 /*-----------------------------------------------------------------*/
4260 /* genCmpEq - generates code for equal to */
4261 /*-----------------------------------------------------------------*/
4263 genCmpEq (iCode * ic, iCode * ifx)
4265 operand *left, *right, *result;
4267 D(emitcode ("; genCmpEq",""));
4269 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4270 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4271 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4273 /* if literal, literal on the right or
4274 if the right is in a pointer register and left
4276 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4277 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4279 operand *t = IC_RIGHT (ic);
4280 IC_RIGHT (ic) = IC_LEFT (ic);
4284 if (ifx && !AOP_SIZE (result))
4287 /* if they are both bit variables */
4288 if (AOP_TYPE (left) == AOP_CRY &&
4289 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4291 if (AOP_TYPE (right) == AOP_LIT)
4293 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4297 emitcode ("cpl", "c");
4301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4305 emitcode ("clr", "c");
4307 /* AOP_TYPE(right) == AOP_CRY */
4311 symbol *lbl = newiTempLabel (NULL);
4312 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4313 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4314 emitcode ("cpl", "c");
4315 emitcode ("", "%05d$:", (lbl->key + 100));
4317 /* if true label then we jump if condition
4319 tlbl = newiTempLabel (NULL);
4322 emitcode ("jnc", "%05d$", tlbl->key + 100);
4323 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4327 emitcode ("jc", "%05d$", tlbl->key + 100);
4328 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4330 emitcode ("", "%05d$:", tlbl->key + 100);
4334 tlbl = newiTempLabel (NULL);
4335 gencjneshort (left, right, tlbl);
4338 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4339 emitcode ("", "%05d$:", tlbl->key + 100);
4343 symbol *lbl = newiTempLabel (NULL);
4344 emitcode ("sjmp", "%05d$", lbl->key + 100);
4345 emitcode ("", "%05d$:", tlbl->key + 100);
4346 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4347 emitcode ("", "%05d$:", lbl->key + 100);
4350 /* mark the icode as generated */
4355 /* if they are both bit variables */
4356 if (AOP_TYPE (left) == AOP_CRY &&
4357 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4359 if (AOP_TYPE (right) == AOP_LIT)
4361 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4364 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4365 emitcode ("cpl", "c");
4369 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4373 emitcode ("clr", "c");
4375 /* AOP_TYPE(right) == AOP_CRY */
4379 symbol *lbl = newiTempLabel (NULL);
4380 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4381 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4382 emitcode ("cpl", "c");
4383 emitcode ("", "%05d$:", (lbl->key + 100));
4386 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4393 genIfxJump (ifx, "c");
4396 /* if the result is used in an arithmetic operation
4397 then put the result in place */
4402 gencjne (left, right, newiTempLabel (NULL));
4403 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4405 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4410 genIfxJump (ifx, "a");
4413 /* if the result is used in an arithmetic operation
4414 then put the result in place */
4415 if (AOP_TYPE (result) != AOP_CRY)
4417 /* leave the result in acc */
4421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4423 freeAsmop (result, NULL, ic, TRUE);
4426 /*-----------------------------------------------------------------*/
4427 /* ifxForOp - returns the icode containing the ifx for operand */
4428 /*-----------------------------------------------------------------*/
4430 ifxForOp (operand * op, iCode * ic)
4432 /* if true symbol then needs to be assigned */
4433 if (IS_TRUE_SYMOP (op))
4436 /* if this has register type condition and
4437 the next instruction is ifx with the same operand
4438 and live to of the operand is upto the ifx only then */
4440 ic->next->op == IFX &&
4441 IC_COND (ic->next)->key == op->key &&
4442 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4448 /*-----------------------------------------------------------------*/
4449 /* hasInc - operand is incremented before any other use */
4450 /*-----------------------------------------------------------------*/
4452 hasInc (operand *op, iCode *ic,int osize)
4454 sym_link *type = operandType(op);
4455 sym_link *retype = getSpec (type);
4456 iCode *lic = ic->next;
4459 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4460 if (!IS_SYMOP(op)) return NULL;
4462 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4463 if (IS_AGGREGATE(type->next)) return NULL;
4464 if (osize != (isize = getSize(type->next))) return NULL;
4467 /* if operand of the form op = op + <sizeof *op> */
4468 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4469 isOperandEqual(IC_RESULT(lic),op) &&
4470 isOperandLiteral(IC_RIGHT(lic)) &&
4471 operandLitValue(IC_RIGHT(lic)) == isize) {
4474 /* if the operand used or deffed */
4475 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4478 /* if GOTO or IFX */
4479 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4485 /*-----------------------------------------------------------------*/
4486 /* genAndOp - for && operation */
4487 /*-----------------------------------------------------------------*/
4489 genAndOp (iCode * ic)
4491 operand *left, *right, *result;
4494 D(emitcode ("; genAndOp",""));
4496 /* note here that && operations that are in an
4497 if statement are taken away by backPatchLabels
4498 only those used in arthmetic operations remain */
4499 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4500 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4501 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4503 /* if both are bit variables */
4504 if (AOP_TYPE (left) == AOP_CRY &&
4505 AOP_TYPE (right) == AOP_CRY)
4507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4508 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4513 tlbl = newiTempLabel (NULL);
4515 emitcode ("jz", "%05d$", tlbl->key + 100);
4517 emitcode ("", "%05d$:", tlbl->key + 100);
4521 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4522 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4523 freeAsmop (result, NULL, ic, TRUE);
4527 /*-----------------------------------------------------------------*/
4528 /* genOrOp - for || operation */
4529 /*-----------------------------------------------------------------*/
4531 genOrOp (iCode * ic)
4533 operand *left, *right, *result;
4536 D(emitcode ("; genOrOp",""));
4538 /* note here that || operations that are in an
4539 if statement are taken away by backPatchLabels
4540 only those used in arthmetic operations remain */
4541 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4542 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4543 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4545 /* if both are bit variables */
4546 if (AOP_TYPE (left) == AOP_CRY &&
4547 AOP_TYPE (right) == AOP_CRY)
4549 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4550 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4555 tlbl = newiTempLabel (NULL);
4557 emitcode ("jnz", "%05d$", tlbl->key + 100);
4559 emitcode ("", "%05d$:", tlbl->key + 100);
4563 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4564 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4565 freeAsmop (result, NULL, ic, TRUE);
4568 /*-----------------------------------------------------------------*/
4569 /* isLiteralBit - test if lit == 2^n */
4570 /*-----------------------------------------------------------------*/
4572 isLiteralBit (unsigned long lit)
4574 unsigned long pw[32] =
4575 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4576 0x100L, 0x200L, 0x400L, 0x800L,
4577 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4578 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4579 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4580 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4581 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4584 for (idx = 0; idx < 32; idx++)
4590 /*-----------------------------------------------------------------*/
4591 /* continueIfTrue - */
4592 /*-----------------------------------------------------------------*/
4594 continueIfTrue (iCode * ic)
4597 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4601 /*-----------------------------------------------------------------*/
4603 /*-----------------------------------------------------------------*/
4605 jumpIfTrue (iCode * ic)
4608 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4612 /*-----------------------------------------------------------------*/
4613 /* jmpTrueOrFalse - */
4614 /*-----------------------------------------------------------------*/
4616 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4618 // ugly but optimized by peephole
4621 symbol *nlbl = newiTempLabel (NULL);
4622 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4623 emitcode ("", "%05d$:", tlbl->key + 100);
4624 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4625 emitcode ("", "%05d$:", nlbl->key + 100);
4629 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4630 emitcode ("", "%05d$:", tlbl->key + 100);
4635 /*-----------------------------------------------------------------*/
4636 /* genAnd - code for and */
4637 /*-----------------------------------------------------------------*/
4639 genAnd (iCode * ic, iCode * ifx)
4641 operand *left, *right, *result;
4642 int size, offset = 0;
4643 unsigned long lit = 0L;
4647 D(emitcode ("; genAnd",""));
4649 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4650 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4651 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4654 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4656 AOP_TYPE (left), AOP_TYPE (right));
4657 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4659 AOP_SIZE (left), AOP_SIZE (right));
4662 /* if left is a literal & right is not then exchange them */
4663 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4664 AOP_NEEDSACC (left))
4666 operand *tmp = right;
4671 /* if result = right then exchange them */
4672 if (sameRegs (AOP (result), AOP (right)))
4674 operand *tmp = right;
4679 /* if right is bit then exchange them */
4680 if (AOP_TYPE (right) == AOP_CRY &&
4681 AOP_TYPE (left) != AOP_CRY)
4683 operand *tmp = right;
4687 if (AOP_TYPE (right) == AOP_LIT)
4688 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4690 size = AOP_SIZE (result);
4693 // result = bit & yy;
4694 if (AOP_TYPE (left) == AOP_CRY)
4696 // c = bit & literal;
4697 if (AOP_TYPE (right) == AOP_LIT)
4701 if (size && sameRegs (AOP (result), AOP (left)))
4704 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4709 if (size && (AOP_TYPE (result) == AOP_CRY))
4711 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4714 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4719 emitcode ("clr", "c");
4724 if (AOP_TYPE (right) == AOP_CRY)
4727 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4728 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4733 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4735 emitcode ("rrc", "a");
4736 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4744 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4745 genIfxJump (ifx, "c");
4749 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4750 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4751 if ((AOP_TYPE (right) == AOP_LIT) &&
4752 (AOP_TYPE (result) == AOP_CRY) &&
4753 (AOP_TYPE (left) != AOP_CRY))
4755 int posbit = isLiteralBit (lit);
4760 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4763 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4769 sprintf (buffer, "acc.%d", posbit & 0x07);
4770 genIfxJump (ifx, buffer);
4777 symbol *tlbl = newiTempLabel (NULL);
4778 int sizel = AOP_SIZE (left);
4780 emitcode ("setb", "c");
4783 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4785 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4787 if ((posbit = isLiteralBit (bytelit)) != 0)
4788 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4791 if (bytelit != 0x0FFL)
4792 emitcode ("anl", "a,%s",
4793 aopGet (AOP (right), offset, FALSE, TRUE));
4794 emitcode ("jnz", "%05d$", tlbl->key + 100);
4799 // bit = left & literal
4802 emitcode ("clr", "c");
4803 emitcode ("", "%05d$:", tlbl->key + 100);
4805 // if(left & literal)
4809 jmpTrueOrFalse (ifx, tlbl);
4817 /* if left is same as result */
4818 if (sameRegs (AOP (result), AOP (left)))
4820 for (; size--; offset++)
4822 if (AOP_TYPE (right) == AOP_LIT)
4824 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4826 else if (bytelit == 0)
4828 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4830 else if (IS_AOP_PREG (result))
4832 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4833 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4834 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4837 emitcode ("anl", "%s,%s",
4838 aopGet (AOP (left), offset, FALSE, TRUE),
4839 aopGet (AOP (right), offset, FALSE, FALSE));
4843 if (AOP_TYPE (left) == AOP_ACC)
4844 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4847 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4848 if (IS_AOP_PREG (result))
4850 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4851 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4855 emitcode ("anl", "%s,a",
4856 aopGet (AOP (left), offset, FALSE, TRUE));
4863 // left & result in different registers
4864 if (AOP_TYPE (result) == AOP_CRY)
4867 // if(size), result in bit
4868 // if(!size && ifx), conditional oper: if(left & right)
4869 symbol *tlbl = newiTempLabel (NULL);
4870 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4872 emitcode ("setb", "c");
4875 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4876 emitcode ("anl", "a,%s",
4877 aopGet (AOP (right), offset, FALSE, FALSE));
4879 if (AOP_TYPE(left)==AOP_ACC) {
4880 emitcode("mov", "b,a");
4881 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4882 emitcode("anl", "a,b");
4884 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4885 emitcode ("anl", "a,%s",
4886 aopGet (AOP (left), offset, FALSE, FALSE));
4889 emitcode ("jnz", "%05d$", tlbl->key + 100);
4895 emitcode ("", "%05d$:", tlbl->key + 100);
4899 jmpTrueOrFalse (ifx, tlbl);
4903 for (; (size--); offset++)
4906 // result = left & right
4907 if (AOP_TYPE (right) == AOP_LIT)
4909 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4911 aopPut (AOP (result),
4912 aopGet (AOP (left), offset, FALSE, FALSE),
4914 isOperandVolatile (result, FALSE));
4917 else if (bytelit == 0)
4919 /* dummy read of volatile operand */
4920 if (isOperandVolatile (left, FALSE))
4921 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4922 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4926 // faster than result <- left, anl result,right
4927 // and better if result is SFR
4928 if (AOP_TYPE (left) == AOP_ACC)
4929 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4932 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4933 emitcode ("anl", "a,%s",
4934 aopGet (AOP (left), offset, FALSE, FALSE));
4936 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4942 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 freeAsmop (result, NULL, ic, TRUE);
4947 /*-----------------------------------------------------------------*/
4948 /* genOr - code for or */
4949 /*-----------------------------------------------------------------*/
4951 genOr (iCode * ic, iCode * ifx)
4953 operand *left, *right, *result;
4954 int size, offset = 0;
4955 unsigned long lit = 0L;
4957 D(emitcode ("; genOr",""));
4959 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4960 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4961 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4964 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4966 AOP_TYPE (left), AOP_TYPE (right));
4967 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4969 AOP_SIZE (left), AOP_SIZE (right));
4972 /* if left is a literal & right is not then exchange them */
4973 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4974 AOP_NEEDSACC (left))
4976 operand *tmp = right;
4981 /* if result = right then exchange them */
4982 if (sameRegs (AOP (result), AOP (right)))
4984 operand *tmp = right;
4989 /* if right is bit then exchange them */
4990 if (AOP_TYPE (right) == AOP_CRY &&
4991 AOP_TYPE (left) != AOP_CRY)
4993 operand *tmp = right;
4997 if (AOP_TYPE (right) == AOP_LIT)
4998 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5000 size = AOP_SIZE (result);
5004 if (AOP_TYPE (left) == AOP_CRY)
5006 if (AOP_TYPE (right) == AOP_LIT)
5008 // c = bit | literal;
5011 // lit != 0 => result = 1
5012 if (AOP_TYPE (result) == AOP_CRY)
5015 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5017 continueIfTrue (ifx);
5020 emitcode ("setb", "c");
5024 // lit == 0 => result = left
5025 if (size && sameRegs (AOP (result), AOP (left)))
5027 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5032 if (AOP_TYPE (right) == AOP_CRY)
5035 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5036 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5041 symbol *tlbl = newiTempLabel (NULL);
5042 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5043 emitcode ("setb", "c");
5044 emitcode ("jb", "%s,%05d$",
5045 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5047 emitcode ("jnz", "%05d$", tlbl->key + 100);
5048 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5050 jmpTrueOrFalse (ifx, tlbl);
5056 emitcode ("", "%05d$:", tlbl->key + 100);
5065 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5066 genIfxJump (ifx, "c");
5070 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5071 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5072 if ((AOP_TYPE (right) == AOP_LIT) &&
5073 (AOP_TYPE (result) == AOP_CRY) &&
5074 (AOP_TYPE (left) != AOP_CRY))
5080 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5082 continueIfTrue (ifx);
5087 // lit = 0, result = boolean(left)
5089 emitcode ("setb", "c");
5093 symbol *tlbl = newiTempLabel (NULL);
5094 emitcode ("jnz", "%05d$", tlbl->key + 100);
5096 emitcode ("", "%05d$:", tlbl->key + 100);
5100 genIfxJump (ifx, "a");
5108 /* if left is same as result */
5109 if (sameRegs (AOP (result), AOP (left)))
5111 for (; size--; offset++)
5113 if (AOP_TYPE (right) == AOP_LIT)
5115 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5117 /* dummy read of volatile operand */
5118 if (isOperandVolatile (left, FALSE))
5119 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5123 else if (IS_AOP_PREG (left))
5125 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5126 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5127 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5130 emitcode ("orl", "%s,%s",
5131 aopGet (AOP (left), offset, FALSE, TRUE),
5132 aopGet (AOP (right), offset, FALSE, FALSE));
5136 if (AOP_TYPE (left) == AOP_ACC)
5137 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5140 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5141 if (IS_AOP_PREG (left))
5143 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5144 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5147 emitcode ("orl", "%s,a",
5148 aopGet (AOP (left), offset, FALSE, TRUE));
5155 // left & result in different registers
5156 if (AOP_TYPE (result) == AOP_CRY)
5159 // if(size), result in bit
5160 // if(!size && ifx), conditional oper: if(left | right)
5161 symbol *tlbl = newiTempLabel (NULL);
5162 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5164 emitcode ("setb", "c");
5167 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5168 emitcode ("orl", "a,%s",
5169 aopGet (AOP (right), offset, FALSE, FALSE));
5171 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5172 emitcode ("orl", "a,%s",
5173 aopGet (AOP (left), offset, FALSE, FALSE));
5175 emitcode ("jnz", "%05d$", tlbl->key + 100);
5181 emitcode ("", "%05d$:", tlbl->key + 100);
5185 jmpTrueOrFalse (ifx, tlbl);
5188 for (; (size--); offset++)
5191 // result = left & right
5192 if (AOP_TYPE (right) == AOP_LIT)
5194 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5196 aopPut (AOP (result),
5197 aopGet (AOP (left), offset, FALSE, FALSE),
5199 isOperandVolatile (result, FALSE));
5203 // faster than result <- left, anl result,right
5204 // and better if result is SFR
5205 if (AOP_TYPE (left) == AOP_ACC)
5206 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5209 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5210 emitcode ("orl", "a,%s",
5211 aopGet (AOP (left), offset, FALSE, FALSE));
5213 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5218 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5219 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5220 freeAsmop (result, NULL, ic, TRUE);
5223 /*-----------------------------------------------------------------*/
5224 /* genXor - code for xclusive or */
5225 /*-----------------------------------------------------------------*/
5227 genXor (iCode * ic, iCode * ifx)
5229 operand *left, *right, *result;
5230 int size, offset = 0;
5231 unsigned long lit = 0L;
5233 D(emitcode ("; genXor",""));
5235 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5236 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5237 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5240 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5242 AOP_TYPE (left), AOP_TYPE (right));
5243 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5245 AOP_SIZE (left), AOP_SIZE (right));
5248 /* if left is a literal & right is not ||
5249 if left needs acc & right does not */
5250 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5251 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5253 operand *tmp = right;
5258 /* if result = right then exchange them */
5259 if (sameRegs (AOP (result), AOP (right)))
5261 operand *tmp = right;
5266 /* if right is bit then exchange them */
5267 if (AOP_TYPE (right) == AOP_CRY &&
5268 AOP_TYPE (left) != AOP_CRY)
5270 operand *tmp = right;
5274 if (AOP_TYPE (right) == AOP_LIT)
5275 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5277 size = AOP_SIZE (result);
5281 if (AOP_TYPE (left) == AOP_CRY)
5283 if (AOP_TYPE (right) == AOP_LIT)
5285 // c = bit & literal;
5288 // lit>>1 != 0 => result = 1
5289 if (AOP_TYPE (result) == AOP_CRY)
5292 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5294 continueIfTrue (ifx);
5297 emitcode ("setb", "c");
5304 // lit == 0, result = left
5305 if (size && sameRegs (AOP (result), AOP (left)))
5307 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5311 // lit == 1, result = not(left)
5312 if (size && sameRegs (AOP (result), AOP (left)))
5314 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5320 emitcode ("cpl", "c");
5329 symbol *tlbl = newiTempLabel (NULL);
5330 if (AOP_TYPE (right) == AOP_CRY)
5333 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5337 int sizer = AOP_SIZE (right);
5339 // if val>>1 != 0, result = 1
5340 emitcode ("setb", "c");
5343 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5345 // test the msb of the lsb
5346 emitcode ("anl", "a,#0xfe");
5347 emitcode ("jnz", "%05d$", tlbl->key + 100);
5351 emitcode ("rrc", "a");
5353 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5354 emitcode ("cpl", "c");
5355 emitcode ("", "%05d$:", (tlbl->key + 100));
5362 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5363 genIfxJump (ifx, "c");
5367 if (sameRegs (AOP (result), AOP (left)))
5369 /* if left is same as result */
5370 for (; size--; offset++)
5372 if (AOP_TYPE (right) == AOP_LIT)
5374 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5376 else if (IS_AOP_PREG (left))
5378 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5379 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5380 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5383 emitcode ("xrl", "%s,%s",
5384 aopGet (AOP (left), offset, FALSE, TRUE),
5385 aopGet (AOP (right), offset, FALSE, FALSE));
5389 if (AOP_TYPE (left) == AOP_ACC)
5390 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5393 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5394 if (IS_AOP_PREG (left))
5396 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5397 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5400 emitcode ("xrl", "%s,a",
5401 aopGet (AOP (left), offset, FALSE, TRUE));
5408 // left & result in different registers
5409 if (AOP_TYPE (result) == AOP_CRY)
5412 // if(size), result in bit
5413 // if(!size && ifx), conditional oper: if(left ^ right)
5414 symbol *tlbl = newiTempLabel (NULL);
5415 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5417 emitcode ("setb", "c");
5420 if ((AOP_TYPE (right) == AOP_LIT) &&
5421 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5423 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5427 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5428 emitcode ("xrl", "a,%s",
5429 aopGet (AOP (right), offset, FALSE, FALSE));
5431 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5432 emitcode ("xrl", "a,%s",
5433 aopGet (AOP (left), offset, FALSE, FALSE));
5436 emitcode ("jnz", "%05d$", tlbl->key + 100);
5442 emitcode ("", "%05d$:", tlbl->key + 100);
5446 jmpTrueOrFalse (ifx, tlbl);
5449 for (; (size--); offset++)
5452 // result = left & right
5453 if (AOP_TYPE (right) == AOP_LIT)
5455 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5457 aopPut (AOP (result),
5458 aopGet (AOP (left), offset, FALSE, FALSE),
5460 isOperandVolatile (result, FALSE));
5464 // faster than result <- left, anl result,right
5465 // and better if result is SFR
5466 if (AOP_TYPE (left) == AOP_ACC)
5467 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5470 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5471 emitcode ("xrl", "a,%s",
5472 aopGet (AOP (left), offset, FALSE, TRUE));
5474 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5479 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5480 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5481 freeAsmop (result, NULL, ic, TRUE);
5484 /*-----------------------------------------------------------------*/
5485 /* genInline - write the inline code out */
5486 /*-----------------------------------------------------------------*/
5488 genInline (iCode * ic)
5490 char *buffer, *bp, *bp1;
5492 D(emitcode ("; genInline",""));
5494 _G.inLine += (!options.asmpeep);
5496 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5497 strcpy (buffer, IC_INLINE (ic));
5499 /* emit each line as a code */
5524 /* emitcode("",buffer); */
5525 _G.inLine -= (!options.asmpeep);
5528 /*-----------------------------------------------------------------*/
5529 /* genRRC - rotate right with carry */
5530 /*-----------------------------------------------------------------*/
5534 operand *left, *result;
5535 int size, offset = 0;
5538 D(emitcode ("; genRRC",""));
5540 /* rotate right with carry */
5541 left = IC_LEFT (ic);
5542 result = IC_RESULT (ic);
5543 aopOp (left, ic, FALSE);
5544 aopOp (result, ic, FALSE);
5546 /* move it to the result */
5547 size = AOP_SIZE (result);
5549 if (size == 1) { /* special case for 1 byte */
5550 l = aopGet (AOP (left), offset, FALSE, FALSE);
5552 emitcode ("rr", "a");
5558 l = aopGet (AOP (left), offset, FALSE, FALSE);
5560 emitcode ("rrc", "a");
5561 if (AOP_SIZE (result) > 1)
5562 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5564 /* now we need to put the carry into the
5565 highest order byte of the result */
5566 if (AOP_SIZE (result) > 1)
5568 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5571 emitcode ("mov", "acc.7,c");
5573 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5574 freeAsmop (left, NULL, ic, TRUE);
5575 freeAsmop (result, NULL, ic, TRUE);
5578 /*-----------------------------------------------------------------*/
5579 /* genRLC - generate code for rotate left with carry */
5580 /*-----------------------------------------------------------------*/
5584 operand *left, *result;
5585 int size, offset = 0;
5588 D(emitcode ("; genRLC",""));
5590 /* rotate right with carry */
5591 left = IC_LEFT (ic);
5592 result = IC_RESULT (ic);
5593 aopOp (left, ic, FALSE);
5594 aopOp (result, ic, FALSE);
5596 /* move it to the result */
5597 size = AOP_SIZE (result);
5601 l = aopGet (AOP (left), offset, FALSE, FALSE);
5603 if (size == 0) { /* special case for 1 byte */
5607 emitcode ("add", "a,acc");
5608 if (AOP_SIZE (result) > 1)
5609 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5612 l = aopGet (AOP (left), offset, FALSE, FALSE);
5614 emitcode ("rlc", "a");
5615 if (AOP_SIZE (result) > 1)
5616 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5619 /* now we need to put the carry into the
5620 highest order byte of the result */
5621 if (AOP_SIZE (result) > 1)
5623 l = aopGet (AOP (result), 0, FALSE, FALSE);
5626 emitcode ("mov", "acc.0,c");
5628 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5629 freeAsmop (left, NULL, ic, TRUE);
5630 freeAsmop (result, NULL, ic, TRUE);
5633 /*-----------------------------------------------------------------*/
5634 /* genGetHbit - generates code get highest order bit */
5635 /*-----------------------------------------------------------------*/
5637 genGetHbit (iCode * ic)
5639 operand *left, *result;
5641 D(emitcode ("; genGetHbit",""));
5643 left = IC_LEFT (ic);
5644 result = IC_RESULT (ic);
5645 aopOp (left, ic, FALSE);
5646 aopOp (result, ic, FALSE);
5648 /* get the highest order byte into a */
5649 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5650 if (AOP_TYPE (result) == AOP_CRY)
5652 emitcode ("rlc", "a");
5657 emitcode ("rl", "a");
5658 emitcode ("anl", "a,#0x01");
5663 freeAsmop (left, NULL, ic, TRUE);
5664 freeAsmop (result, NULL, ic, TRUE);
5667 /*-----------------------------------------------------------------*/
5668 /* AccRol - rotate left accumulator by known count */
5669 /*-----------------------------------------------------------------*/
5671 AccRol (int shCount)
5673 shCount &= 0x0007; // shCount : 0..7
5680 emitcode ("rl", "a");
5683 emitcode ("rl", "a");
5684 emitcode ("rl", "a");
5687 emitcode ("swap", "a");
5688 emitcode ("rr", "a");
5691 emitcode ("swap", "a");
5694 emitcode ("swap", "a");
5695 emitcode ("rl", "a");
5698 emitcode ("rr", "a");
5699 emitcode ("rr", "a");
5702 emitcode ("rr", "a");
5707 /*-----------------------------------------------------------------*/
5708 /* AccLsh - left shift accumulator by known count */
5709 /*-----------------------------------------------------------------*/
5711 AccLsh (int shCount)
5716 emitcode ("add", "a,acc");
5717 else if (shCount == 2)
5719 emitcode ("add", "a,acc");
5720 emitcode ("add", "a,acc");
5724 /* rotate left accumulator */
5726 /* and kill the lower order bits */
5727 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5732 /*-----------------------------------------------------------------*/
5733 /* AccRsh - right shift accumulator by known count */
5734 /*-----------------------------------------------------------------*/
5736 AccRsh (int shCount)
5743 emitcode ("rrc", "a");
5747 /* rotate right accumulator */
5748 AccRol (8 - shCount);
5749 /* and kill the higher order bits */
5750 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5755 /*-----------------------------------------------------------------*/
5756 /* AccSRsh - signed right shift accumulator by known count */
5757 /*-----------------------------------------------------------------*/
5759 AccSRsh (int shCount)
5766 emitcode ("mov", "c,acc.7");
5767 emitcode ("rrc", "a");
5769 else if (shCount == 2)
5771 emitcode ("mov", "c,acc.7");
5772 emitcode ("rrc", "a");
5773 emitcode ("mov", "c,acc.7");
5774 emitcode ("rrc", "a");
5778 tlbl = newiTempLabel (NULL);
5779 /* rotate right accumulator */
5780 AccRol (8 - shCount);
5781 /* and kill the higher order bits */
5782 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5783 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5784 emitcode ("orl", "a,#0x%02x",
5785 (unsigned char) ~SRMask[shCount]);
5786 emitcode ("", "%05d$:", tlbl->key + 100);
5791 /*-----------------------------------------------------------------*/
5792 /* shiftR1Left2Result - shift right one byte from left to result */
5793 /*-----------------------------------------------------------------*/
5795 shiftR1Left2Result (operand * left, int offl,
5796 operand * result, int offr,
5797 int shCount, int sign)
5799 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5800 /* shift right accumulator */
5805 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5808 /*-----------------------------------------------------------------*/
5809 /* shiftL1Left2Result - shift left one byte from left to result */
5810 /*-----------------------------------------------------------------*/
5812 shiftL1Left2Result (operand * left, int offl,
5813 operand * result, int offr, int shCount)
5816 l = aopGet (AOP (left), offl, FALSE, FALSE);
5818 /* shift left accumulator */
5820 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5823 /*-----------------------------------------------------------------*/
5824 /* movLeft2Result - move byte from left to result */
5825 /*-----------------------------------------------------------------*/
5827 movLeft2Result (operand * left, int offl,
5828 operand * result, int offr, int sign)
5831 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5833 l = aopGet (AOP (left), offl, FALSE, FALSE);
5835 if (*l == '@' && (IS_AOP_PREG (result)))
5837 emitcode ("mov", "a,%s", l);
5838 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5843 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5846 /* MSB sign in acc.7 ! */
5847 if (getDataSize (left) == offl + 1)
5849 emitcode ("mov", "a,%s", l);
5850 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5857 /*-----------------------------------------------------------------*/
5858 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5859 /*-----------------------------------------------------------------*/
5863 emitcode ("rrc", "a");
5864 emitcode ("xch", "a,%s", x);
5865 emitcode ("rrc", "a");
5866 emitcode ("xch", "a,%s", x);
5869 /*-----------------------------------------------------------------*/
5870 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5871 /*-----------------------------------------------------------------*/
5875 emitcode ("xch", "a,%s", x);
5876 emitcode ("rlc", "a");
5877 emitcode ("xch", "a,%s", x);
5878 emitcode ("rlc", "a");
5881 /*-----------------------------------------------------------------*/
5882 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5883 /*-----------------------------------------------------------------*/
5887 emitcode ("xch", "a,%s", x);
5888 emitcode ("add", "a,acc");
5889 emitcode ("xch", "a,%s", x);
5890 emitcode ("rlc", "a");
5893 /*-----------------------------------------------------------------*/
5894 /* AccAXLsh - left shift a:x by known count (0..7) */
5895 /*-----------------------------------------------------------------*/
5897 AccAXLsh (char *x, int shCount)
5912 case 5: // AAAAABBB:CCCCCDDD
5914 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5916 emitcode ("anl", "a,#0x%02x",
5917 SLMask[shCount]); // BBB00000:CCCCCDDD
5919 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5921 AccRol (shCount); // DDDCCCCC:BBB00000
5923 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5925 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5927 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5929 emitcode ("anl", "a,#0x%02x",
5930 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5932 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5934 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5937 case 6: // AAAAAABB:CCCCCCDD
5938 emitcode ("anl", "a,#0x%02x",
5939 SRMask[shCount]); // 000000BB:CCCCCCDD
5940 emitcode ("mov", "c,acc.0"); // c = B
5941 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5943 AccAXRrl1 (x); // BCCCCCCD:D000000B
5944 AccAXRrl1 (x); // BBCCCCCC:DD000000
5946 emitcode("rrc","a");
5947 emitcode("xch","a,%s", x);
5948 emitcode("rrc","a");
5949 emitcode("mov","c,acc.0"); //<< get correct bit
5950 emitcode("xch","a,%s", x);
5952 emitcode("rrc","a");
5953 emitcode("xch","a,%s", x);
5954 emitcode("rrc","a");
5955 emitcode("xch","a,%s", x);
5958 case 7: // a:x <<= 7
5960 emitcode ("anl", "a,#0x%02x",
5961 SRMask[shCount]); // 0000000B:CCCCCCCD
5963 emitcode ("mov", "c,acc.0"); // c = B
5965 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5967 AccAXRrl1 (x); // BCCCCCCC:D0000000
5975 /*-----------------------------------------------------------------*/
5976 /* AccAXRsh - right shift a:x known count (0..7) */
5977 /*-----------------------------------------------------------------*/
5979 AccAXRsh (char *x, int shCount)
5987 AccAXRrl1 (x); // 0->a:x
5992 AccAXRrl1 (x); // 0->a:x
5995 AccAXRrl1 (x); // 0->a:x
6000 case 5: // AAAAABBB:CCCCCDDD = a:x
6002 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6004 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6006 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6008 emitcode ("anl", "a,#0x%02x",
6009 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6011 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6013 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6015 emitcode ("anl", "a,#0x%02x",
6016 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6018 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6020 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6022 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6025 case 6: // AABBBBBB:CCDDDDDD
6027 emitcode ("mov", "c,acc.7");
6028 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6030 emitcode ("mov", "c,acc.7");
6031 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6033 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6035 emitcode ("anl", "a,#0x%02x",
6036 SRMask[shCount]); // 000000AA:BBBBBBCC
6039 case 7: // ABBBBBBB:CDDDDDDD
6041 emitcode ("mov", "c,acc.7"); // c = A
6043 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6045 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6047 emitcode ("anl", "a,#0x%02x",
6048 SRMask[shCount]); // 0000000A:BBBBBBBC
6056 /*-----------------------------------------------------------------*/
6057 /* AccAXRshS - right shift signed a:x known count (0..7) */
6058 /*-----------------------------------------------------------------*/
6060 AccAXRshS (char *x, int shCount)
6068 emitcode ("mov", "c,acc.7");
6069 AccAXRrl1 (x); // s->a:x
6073 emitcode ("mov", "c,acc.7");
6074 AccAXRrl1 (x); // s->a:x
6076 emitcode ("mov", "c,acc.7");
6077 AccAXRrl1 (x); // s->a:x
6082 case 5: // AAAAABBB:CCCCCDDD = a:x
6084 tlbl = newiTempLabel (NULL);
6085 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6087 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6089 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6091 emitcode ("anl", "a,#0x%02x",
6092 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6094 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6096 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6098 emitcode ("anl", "a,#0x%02x",
6099 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6101 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6103 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6105 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6107 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6108 emitcode ("orl", "a,#0x%02x",
6109 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6111 emitcode ("", "%05d$:", tlbl->key + 100);
6112 break; // SSSSAAAA:BBBCCCCC
6114 case 6: // AABBBBBB:CCDDDDDD
6116 tlbl = newiTempLabel (NULL);
6117 emitcode ("mov", "c,acc.7");
6118 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6120 emitcode ("mov", "c,acc.7");
6121 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6123 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6125 emitcode ("anl", "a,#0x%02x",
6126 SRMask[shCount]); // 000000AA:BBBBBBCC
6128 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6129 emitcode ("orl", "a,#0x%02x",
6130 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6132 emitcode ("", "%05d$:", tlbl->key + 100);
6134 case 7: // ABBBBBBB:CDDDDDDD
6136 tlbl = newiTempLabel (NULL);
6137 emitcode ("mov", "c,acc.7"); // c = A
6139 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6141 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6143 emitcode ("anl", "a,#0x%02x",
6144 SRMask[shCount]); // 0000000A:BBBBBBBC
6146 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6147 emitcode ("orl", "a,#0x%02x",
6148 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6150 emitcode ("", "%05d$:", tlbl->key + 100);
6157 /*-----------------------------------------------------------------*/
6158 /* shiftL2Left2Result - shift left two bytes from left to result */
6159 /*-----------------------------------------------------------------*/
6161 shiftL2Left2Result (operand * left, int offl,
6162 operand * result, int offr, int shCount)
6164 if (sameRegs (AOP (result), AOP (left)) &&
6165 ((offl + MSB16) == offr))
6167 /* don't crash result[offr] */
6168 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6169 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6173 movLeft2Result (left, offl, result, offr, 0);
6174 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6176 /* ax << shCount (x = lsb(result)) */
6177 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6178 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6182 /*-----------------------------------------------------------------*/
6183 /* shiftR2Left2Result - shift right two bytes from left to result */
6184 /*-----------------------------------------------------------------*/
6186 shiftR2Left2Result (operand * left, int offl,
6187 operand * result, int offr,
6188 int shCount, int sign)
6190 if (sameRegs (AOP (result), AOP (left)) &&
6191 ((offl + MSB16) == offr))
6193 /* don't crash result[offr] */
6194 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6195 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6199 movLeft2Result (left, offl, result, offr, 0);
6200 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6202 /* a:x >> shCount (x = lsb(result)) */
6204 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6206 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6207 if (getDataSize (result) > 1)
6208 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6211 /*-----------------------------------------------------------------*/
6212 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6213 /*-----------------------------------------------------------------*/
6215 shiftLLeftOrResult (operand * left, int offl,
6216 operand * result, int offr, int shCount)
6218 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6219 /* shift left accumulator */
6221 /* or with result */
6222 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6223 /* back to result */
6224 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6227 /*-----------------------------------------------------------------*/
6228 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6229 /*-----------------------------------------------------------------*/
6231 shiftRLeftOrResult (operand * left, int offl,
6232 operand * result, int offr, int shCount)
6234 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6235 /* shift right accumulator */
6237 /* or with result */
6238 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6239 /* back to result */
6240 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6243 /*-----------------------------------------------------------------*/
6244 /* genlshOne - left shift a one byte quantity by known count */
6245 /*-----------------------------------------------------------------*/
6247 genlshOne (operand * result, operand * left, int shCount)
6249 D(emitcode ("; genlshOne",""));
6251 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6254 /*-----------------------------------------------------------------*/
6255 /* genlshTwo - left shift two bytes by known amount != 0 */
6256 /*-----------------------------------------------------------------*/
6258 genlshTwo (operand * result, operand * left, int shCount)
6262 D(emitcode ("; genlshTwo",""));
6264 size = getDataSize (result);
6266 /* if shCount >= 8 */
6274 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6276 movLeft2Result (left, LSB, result, MSB16, 0);
6278 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6281 /* 1 <= shCount <= 7 */
6285 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6287 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6291 /*-----------------------------------------------------------------*/
6292 /* shiftLLong - shift left one long from left to result */
6293 /* offl = LSB or MSB16 */
6294 /*-----------------------------------------------------------------*/
6296 shiftLLong (operand * left, operand * result, int offr)
6299 int size = AOP_SIZE (result);
6301 if (size >= LSB + offr)
6303 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6305 emitcode ("add", "a,acc");
6306 if (sameRegs (AOP (left), AOP (result)) &&
6307 size >= MSB16 + offr && offr != LSB)
6308 emitcode ("xch", "a,%s",
6309 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6311 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6314 if (size >= MSB16 + offr)
6316 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6318 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6321 emitcode ("rlc", "a");
6322 if (sameRegs (AOP (left), AOP (result)) &&
6323 size >= MSB24 + offr && offr != LSB)
6324 emitcode ("xch", "a,%s",
6325 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6327 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6330 if (size >= MSB24 + offr)
6332 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6334 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6337 emitcode ("rlc", "a");
6338 if (sameRegs (AOP (left), AOP (result)) &&
6339 size >= MSB32 + offr && offr != LSB)
6340 emitcode ("xch", "a,%s",
6341 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6343 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6346 if (size > MSB32 + offr)
6348 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6350 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6353 emitcode ("rlc", "a");
6354 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6357 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6360 /*-----------------------------------------------------------------*/
6361 /* genlshFour - shift four byte by a known amount != 0 */
6362 /*-----------------------------------------------------------------*/
6364 genlshFour (operand * result, operand * left, int shCount)
6368 D(emitcode ("; genlshFour",""));
6370 size = AOP_SIZE (result);
6372 /* if shifting more that 3 bytes */
6377 /* lowest order of left goes to the highest
6378 order of the destination */
6379 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6381 movLeft2Result (left, LSB, result, MSB32, 0);
6382 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6383 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6384 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6388 /* more than two bytes */
6389 else if (shCount >= 16)
6391 /* lower order two bytes goes to higher order two bytes */
6393 /* if some more remaining */
6395 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6398 movLeft2Result (left, MSB16, result, MSB32, 0);
6399 movLeft2Result (left, LSB, result, MSB24, 0);
6401 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6402 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6406 /* if more than 1 byte */
6407 else if (shCount >= 8)
6409 /* lower order three bytes goes to higher order three bytes */
6414 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6416 movLeft2Result (left, LSB, result, MSB16, 0);
6422 movLeft2Result (left, MSB24, result, MSB32, 0);
6423 movLeft2Result (left, MSB16, result, MSB24, 0);
6424 movLeft2Result (left, LSB, result, MSB16, 0);
6425 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6427 else if (shCount == 1)
6428 shiftLLong (left, result, MSB16);
6431 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6432 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6433 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6434 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6439 /* 1 <= shCount <= 7 */
6440 else if (shCount <= 2)
6442 shiftLLong (left, result, LSB);
6444 shiftLLong (result, result, LSB);
6446 /* 3 <= shCount <= 7, optimize */
6449 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6450 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6451 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6455 /*-----------------------------------------------------------------*/
6456 /* genLeftShiftLiteral - left shifting by known count */
6457 /*-----------------------------------------------------------------*/
6459 genLeftShiftLiteral (operand * left,
6464 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6467 D(emitcode ("; genLeftShiftLiteral",""));
6469 freeAsmop (right, NULL, ic, TRUE);
6471 aopOp (left, ic, FALSE);
6472 aopOp (result, ic, FALSE);
6474 size = getSize (operandType (result));
6477 emitcode ("; shift left ", "result %d, left %d", size,
6481 /* I suppose that the left size >= result size */
6486 movLeft2Result (left, size, result, size, 0);
6490 else if (shCount >= (size * 8))
6492 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6498 genlshOne (result, left, shCount);
6502 genlshTwo (result, left, shCount);
6506 genlshFour (result, left, shCount);
6509 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6510 "*** ack! mystery literal shift!\n");
6514 freeAsmop (left, NULL, ic, TRUE);
6515 freeAsmop (result, NULL, ic, TRUE);
6518 /*-----------------------------------------------------------------*/
6519 /* genLeftShift - generates code for left shifting */
6520 /*-----------------------------------------------------------------*/
6522 genLeftShift (iCode * ic)
6524 operand *left, *right, *result;
6527 symbol *tlbl, *tlbl1;
6529 D(emitcode ("; genLeftShift",""));
6531 right = IC_RIGHT (ic);
6532 left = IC_LEFT (ic);
6533 result = IC_RESULT (ic);
6535 aopOp (right, ic, FALSE);
6537 /* if the shift count is known then do it
6538 as efficiently as possible */
6539 if (AOP_TYPE (right) == AOP_LIT)
6541 genLeftShiftLiteral (left, right, result, ic);
6545 /* shift count is unknown then we have to form
6546 a loop get the loop count in B : Note: we take
6547 only the lower order byte since shifting
6548 more that 32 bits make no sense anyway, ( the
6549 largest size of an object can be only 32 bits ) */
6551 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6552 emitcode ("inc", "b");
6553 freeAsmop (right, NULL, ic, TRUE);
6554 aopOp (left, ic, FALSE);
6555 aopOp (result, ic, FALSE);
6557 /* now move the left to the result if they are not the
6559 if (!sameRegs (AOP (left), AOP (result)) &&
6560 AOP_SIZE (result) > 1)
6563 size = AOP_SIZE (result);
6567 l = aopGet (AOP (left), offset, FALSE, TRUE);
6568 if (*l == '@' && (IS_AOP_PREG (result)))
6571 emitcode ("mov", "a,%s", l);
6572 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6575 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6580 tlbl = newiTempLabel (NULL);
6581 size = AOP_SIZE (result);
6583 tlbl1 = newiTempLabel (NULL);
6585 /* if it is only one byte then */
6588 symbol *tlbl1 = newiTempLabel (NULL);
6590 l = aopGet (AOP (left), 0, FALSE, FALSE);
6592 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6593 emitcode ("", "%05d$:", tlbl->key + 100);
6594 emitcode ("add", "a,acc");
6595 emitcode ("", "%05d$:", tlbl1->key + 100);
6596 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6597 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6601 reAdjustPreg (AOP (result));
6603 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6604 emitcode ("", "%05d$:", tlbl->key + 100);
6605 l = aopGet (AOP (result), offset, FALSE, FALSE);
6607 emitcode ("add", "a,acc");
6608 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6611 l = aopGet (AOP (result), offset, FALSE, FALSE);
6613 emitcode ("rlc", "a");
6614 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6616 reAdjustPreg (AOP (result));
6618 emitcode ("", "%05d$:", tlbl1->key + 100);
6619 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6621 freeAsmop (left, NULL, ic, TRUE);
6622 freeAsmop (result, NULL, ic, TRUE);
6625 /*-----------------------------------------------------------------*/
6626 /* genrshOne - right shift a one byte quantity by known count */
6627 /*-----------------------------------------------------------------*/
6629 genrshOne (operand * result, operand * left,
6630 int shCount, int sign)
6632 D(emitcode ("; genrshOne",""));
6634 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6637 /*-----------------------------------------------------------------*/
6638 /* genrshTwo - right shift two bytes by known amount != 0 */
6639 /*-----------------------------------------------------------------*/
6641 genrshTwo (operand * result, operand * left,
6642 int shCount, int sign)
6644 D(emitcode ("; genrshTwo",""));
6646 /* if shCount >= 8 */
6651 shiftR1Left2Result (left, MSB16, result, LSB,
6654 movLeft2Result (left, MSB16, result, LSB, sign);
6655 addSign (result, MSB16, sign);
6658 /* 1 <= shCount <= 7 */
6660 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6663 /*-----------------------------------------------------------------*/
6664 /* shiftRLong - shift right one long from left to result */
6665 /* offl = LSB or MSB16 */
6666 /*-----------------------------------------------------------------*/
6668 shiftRLong (operand * left, int offl,
6669 operand * result, int sign)
6671 int isSameRegs=sameRegs(AOP(left),AOP(result));
6673 if (isSameRegs && offl>1) {
6674 // we are in big trouble, but this shouldn't happen
6675 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6678 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6683 emitcode ("rlc", "a");
6684 emitcode ("subb", "a,acc");
6686 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6688 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6689 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6692 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6697 emitcode ("clr", "c");
6699 emitcode ("mov", "c,acc.7");
6702 emitcode ("rrc", "a");
6704 if (isSameRegs && offl==MSB16) {
6705 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6707 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6708 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6711 emitcode ("rrc", "a");
6712 if (isSameRegs && offl==1) {
6713 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6715 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6716 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6718 emitcode ("rrc", "a");
6719 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6723 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6724 emitcode ("rrc", "a");
6725 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6729 /*-----------------------------------------------------------------*/
6730 /* genrshFour - shift four byte by a known amount != 0 */
6731 /*-----------------------------------------------------------------*/
6733 genrshFour (operand * result, operand * left,
6734 int shCount, int sign)
6736 D(emitcode ("; genrshFour",""));
6738 /* if shifting more that 3 bytes */
6743 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6745 movLeft2Result (left, MSB32, result, LSB, sign);
6746 addSign (result, MSB16, sign);
6748 else if (shCount >= 16)
6752 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6755 movLeft2Result (left, MSB24, result, LSB, 0);
6756 movLeft2Result (left, MSB32, result, MSB16, sign);
6758 addSign (result, MSB24, sign);
6760 else if (shCount >= 8)
6764 shiftRLong (left, MSB16, result, sign);
6765 else if (shCount == 0)
6767 movLeft2Result (left, MSB16, result, LSB, 0);
6768 movLeft2Result (left, MSB24, result, MSB16, 0);
6769 movLeft2Result (left, MSB32, result, MSB24, sign);
6770 addSign (result, MSB32, sign);
6774 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6775 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6776 /* the last shift is signed */
6777 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6778 addSign (result, MSB32, sign);
6782 { /* 1 <= shCount <= 7 */
6785 shiftRLong (left, LSB, result, sign);
6787 shiftRLong (result, LSB, result, sign);
6791 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6792 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6793 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6798 /*-----------------------------------------------------------------*/
6799 /* genRightShiftLiteral - right shifting by known count */
6800 /*-----------------------------------------------------------------*/
6802 genRightShiftLiteral (operand * left,
6808 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6811 D(emitcode ("; genRightShiftLiteral",""));
6813 freeAsmop (right, NULL, ic, TRUE);
6815 aopOp (left, ic, FALSE);
6816 aopOp (result, ic, FALSE);
6819 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6823 size = getDataSize (left);
6824 /* test the LEFT size !!! */
6826 /* I suppose that the left size >= result size */
6829 size = getDataSize (result);
6831 movLeft2Result (left, size, result, size, 0);
6834 else if (shCount >= (size * 8))
6837 /* get sign in acc.7 */
6838 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6840 addSign (result, LSB, sign);
6847 genrshOne (result, left, shCount, sign);
6851 genrshTwo (result, left, shCount, sign);
6855 genrshFour (result, left, shCount, sign);
6861 freeAsmop (left, NULL, ic, TRUE);
6862 freeAsmop (result, NULL, ic, TRUE);
6865 /*-----------------------------------------------------------------*/
6866 /* genSignedRightShift - right shift of signed number */
6867 /*-----------------------------------------------------------------*/
6869 genSignedRightShift (iCode * ic)
6871 operand *right, *left, *result;
6874 symbol *tlbl, *tlbl1;
6876 D(emitcode ("; genSignedRightShift",""));
6878 /* we do it the hard way put the shift count in b
6879 and loop thru preserving the sign */
6881 right = IC_RIGHT (ic);
6882 left = IC_LEFT (ic);
6883 result = IC_RESULT (ic);
6885 aopOp (right, ic, FALSE);
6888 if (AOP_TYPE (right) == AOP_LIT)
6890 genRightShiftLiteral (left, right, result, ic, 1);
6893 /* shift count is unknown then we have to form
6894 a loop get the loop count in B : Note: we take
6895 only the lower order byte since shifting
6896 more that 32 bits make no sense anyway, ( the
6897 largest size of an object can be only 32 bits ) */
6899 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6900 emitcode ("inc", "b");
6901 freeAsmop (right, NULL, ic, TRUE);
6902 aopOp (left, ic, FALSE);
6903 aopOp (result, ic, FALSE);
6905 /* now move the left to the result if they are not the
6907 if (!sameRegs (AOP (left), AOP (result)) &&
6908 AOP_SIZE (result) > 1)
6911 size = AOP_SIZE (result);
6915 l = aopGet (AOP (left), offset, FALSE, TRUE);
6916 if (*l == '@' && IS_AOP_PREG (result))
6919 emitcode ("mov", "a,%s", l);
6920 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6923 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6928 /* mov the highest order bit to OVR */
6929 tlbl = newiTempLabel (NULL);
6930 tlbl1 = newiTempLabel (NULL);
6932 size = AOP_SIZE (result);
6934 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6935 emitcode ("rlc", "a");
6936 emitcode ("mov", "ov,c");
6937 /* if it is only one byte then */
6940 l = aopGet (AOP (left), 0, FALSE, FALSE);
6942 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6943 emitcode ("", "%05d$:", tlbl->key + 100);
6944 emitcode ("mov", "c,ov");
6945 emitcode ("rrc", "a");
6946 emitcode ("", "%05d$:", tlbl1->key + 100);
6947 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6948 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6952 reAdjustPreg (AOP (result));
6953 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6954 emitcode ("", "%05d$:", tlbl->key + 100);
6955 emitcode ("mov", "c,ov");
6958 l = aopGet (AOP (result), offset, FALSE, FALSE);
6960 emitcode ("rrc", "a");
6961 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6963 reAdjustPreg (AOP (result));
6964 emitcode ("", "%05d$:", tlbl1->key + 100);
6965 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6968 freeAsmop (left, NULL, ic, TRUE);
6969 freeAsmop (result, NULL, ic, TRUE);
6972 /*-----------------------------------------------------------------*/
6973 /* genRightShift - generate code for right shifting */
6974 /*-----------------------------------------------------------------*/
6976 genRightShift (iCode * ic)
6978 operand *right, *left, *result;
6982 symbol *tlbl, *tlbl1;
6984 D(emitcode ("; genRightShift",""));
6986 /* if signed then we do it the hard way preserve the
6987 sign bit moving it inwards */
6988 retype = getSpec (operandType (IC_RESULT (ic)));
6990 if (!SPEC_USIGN (retype))
6992 genSignedRightShift (ic);
6996 /* signed & unsigned types are treated the same : i.e. the
6997 signed is NOT propagated inwards : quoting from the
6998 ANSI - standard : "for E1 >> E2, is equivalent to division
6999 by 2**E2 if unsigned or if it has a non-negative value,
7000 otherwise the result is implementation defined ", MY definition
7001 is that the sign does not get propagated */
7003 right = IC_RIGHT (ic);
7004 left = IC_LEFT (ic);
7005 result = IC_RESULT (ic);
7007 aopOp (right, ic, FALSE);
7009 /* if the shift count is known then do it
7010 as efficiently as possible */
7011 if (AOP_TYPE (right) == AOP_LIT)
7013 genRightShiftLiteral (left, right, result, ic, 0);
7017 /* shift count is unknown then we have to form
7018 a loop get the loop count in B : Note: we take
7019 only the lower order byte since shifting
7020 more that 32 bits make no sense anyway, ( the
7021 largest size of an object can be only 32 bits ) */
7023 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7024 emitcode ("inc", "b");
7025 freeAsmop (right, NULL, ic, TRUE);
7026 aopOp (left, ic, FALSE);
7027 aopOp (result, ic, FALSE);
7029 /* now move the left to the result if they are not the
7031 if (!sameRegs (AOP (left), AOP (result)) &&
7032 AOP_SIZE (result) > 1)
7035 size = AOP_SIZE (result);
7039 l = aopGet (AOP (left), offset, FALSE, TRUE);
7040 if (*l == '@' && IS_AOP_PREG (result))
7043 emitcode ("mov", "a,%s", l);
7044 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7047 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7052 tlbl = newiTempLabel (NULL);
7053 tlbl1 = newiTempLabel (NULL);
7054 size = AOP_SIZE (result);
7057 /* if it is only one byte then */
7060 l = aopGet (AOP (left), 0, FALSE, FALSE);
7062 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7063 emitcode ("", "%05d$:", tlbl->key + 100);
7065 emitcode ("rrc", "a");
7066 emitcode ("", "%05d$:", tlbl1->key + 100);
7067 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7068 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7072 reAdjustPreg (AOP (result));
7073 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7074 emitcode ("", "%05d$:", tlbl->key + 100);
7078 l = aopGet (AOP (result), offset, FALSE, FALSE);
7080 emitcode ("rrc", "a");
7081 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7083 reAdjustPreg (AOP (result));
7085 emitcode ("", "%05d$:", tlbl1->key + 100);
7086 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7089 freeAsmop (left, NULL, ic, TRUE);
7090 freeAsmop (result, NULL, ic, TRUE);
7093 /*-----------------------------------------------------------------*/
7094 /* emitPtrByteGet - emits code to get a byte into A through a */
7095 /* pointer register (R0, R1, or DPTR). The */
7096 /* original value of A can be preserved in B. */
7097 /*-----------------------------------------------------------------*/
7099 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7106 emitcode ("mov", "b,a");
7107 emitcode ("mov", "a,@%s", rname);
7112 emitcode ("mov", "b,a");
7113 emitcode ("movx", "a,@%s", rname);
7118 emitcode ("mov", "b,a");
7119 emitcode ("movx", "a,@dptr");
7124 emitcode ("mov", "b,a");
7125 emitcode ("clr", "a");
7126 emitcode ("movc", "a,@a+dptr");
7132 emitcode ("push", "b");
7133 emitcode ("push", "acc");
7135 emitcode ("lcall", "__gptrget");
7137 emitcode ("pop", "b");
7142 /*-----------------------------------------------------------------*/
7143 /* emitPtrByteSet - emits code to set a byte from src through a */
7144 /* pointer register (R0, R1, or DPTR). */
7145 /*-----------------------------------------------------------------*/
7147 emitPtrByteSet (char *rname, int p_type, char *src)
7156 emitcode ("mov", "@%s,a", rname);
7159 emitcode ("mov", "@%s,%s", rname, src);
7164 emitcode ("movx", "@%s,a", rname);
7169 emitcode ("movx", "@dptr,a");
7174 emitcode ("lcall", "__gptrput");
7179 /*-----------------------------------------------------------------*/
7180 /* genUnpackBits - generates code for unpacking bits */
7181 /*-----------------------------------------------------------------*/
7183 genUnpackBits (operand * result, char *rname, int ptype)
7185 int offset = 0; /* result byte offset */
7186 int rsize; /* result size */
7187 int rlen = 0; /* remaining bitfield length */
7188 sym_link *etype; /* bitfield type information */
7189 int blen; /* bitfield length */
7190 int bstr; /* bitfield starting bit within byte */
7192 D(emitcode ("; genUnpackBits",""));
7194 etype = getSpec (operandType (result));
7195 rsize = getSize (operandType (result));
7196 blen = SPEC_BLEN (etype);
7197 bstr = SPEC_BSTR (etype);
7199 /* If the bitfield length is less than a byte */
7202 emitPtrByteGet (rname, ptype, FALSE);
7204 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7205 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7209 /* Bit field did not fit in a byte. Copy all
7210 but the partial byte at the end. */
7211 for (rlen=blen;rlen>=8;rlen-=8)
7213 emitPtrByteGet (rname, ptype, FALSE);
7214 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7216 emitcode ("inc", "%s", rname);
7219 /* Handle the partial byte at the end */
7222 emitPtrByteGet (rname, ptype, FALSE);
7223 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7224 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7232 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7237 /*-----------------------------------------------------------------*/
7238 /* genDataPointerGet - generates code when ptr offset is known */
7239 /*-----------------------------------------------------------------*/
7241 genDataPointerGet (operand * left,
7247 int size, offset = 0;
7249 D(emitcode ("; genDataPointerGet",""));
7251 aopOp (result, ic, TRUE);
7253 /* get the string representation of the name */
7254 l = aopGet (AOP (left), 0, FALSE, TRUE);
7255 size = AOP_SIZE (result);
7259 sprintf (buffer, "(%s + %d)", l + 1, offset);
7261 sprintf (buffer, "%s", l + 1);
7262 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7265 freeAsmop (left, NULL, ic, TRUE);
7266 freeAsmop (result, NULL, ic, TRUE);
7269 /*-----------------------------------------------------------------*/
7270 /* genNearPointerGet - emitcode for near pointer fetch */
7271 /*-----------------------------------------------------------------*/
7273 genNearPointerGet (operand * left,
7281 sym_link *rtype, *retype;
7282 sym_link *ltype = operandType (left);
7285 D(emitcode ("; genNearPointerGet",""));
7287 rtype = operandType (result);
7288 retype = getSpec (rtype);
7290 aopOp (left, ic, FALSE);
7292 /* if left is rematerialisable and
7293 result is not bit variable type and
7294 the left is pointer to data space i.e
7295 lower 128 bytes of space */
7296 if (AOP_TYPE (left) == AOP_IMMD &&
7297 !IS_BITVAR (retype) &&
7298 DCL_TYPE (ltype) == POINTER)
7300 genDataPointerGet (left, result, ic);
7304 /* if the value is already in a pointer register
7305 then don't need anything more */
7306 if (!AOP_INPREG (AOP (left)))
7308 /* otherwise get a free pointer register */
7310 preg = getFreePtr (ic, &aop, FALSE);
7311 emitcode ("mov", "%s,%s",
7313 aopGet (AOP (left), 0, FALSE, TRUE));
7317 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7319 //aopOp (result, ic, FALSE);
7320 aopOp (result, ic, result?TRUE:FALSE);
7322 /* if bitfield then unpack the bits */
7323 if (IS_BITVAR (retype))
7324 genUnpackBits (result, rname, POINTER);
7327 /* we have can just get the values */
7328 int size = AOP_SIZE (result);
7333 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7336 emitcode ("mov", "a,@%s", rname);
7337 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7341 sprintf (buffer, "@%s", rname);
7342 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7346 emitcode ("inc", "%s", rname);
7350 /* now some housekeeping stuff */
7351 if (aop) /* we had to allocate for this iCode */
7353 if (pi) { /* post increment present */
7354 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7356 freeAsmop (NULL, aop, ic, TRUE);
7360 /* we did not allocate which means left
7361 already in a pointer register, then
7362 if size > 0 && this could be used again
7363 we have to point it back to where it
7365 if ((AOP_SIZE (result) > 1 &&
7366 !OP_SYMBOL (left)->remat &&
7367 (OP_SYMBOL (left)->liveTo > ic->seq ||
7371 int size = AOP_SIZE (result) - 1;
7373 emitcode ("dec", "%s", rname);
7378 freeAsmop (left, NULL, ic, TRUE);
7379 freeAsmop (result, NULL, ic, TRUE);
7380 if (pi) pi->generated = 1;
7383 /*-----------------------------------------------------------------*/
7384 /* genPagedPointerGet - emitcode for paged pointer fetch */
7385 /*-----------------------------------------------------------------*/
7387 genPagedPointerGet (operand * left,
7395 sym_link *rtype, *retype;
7397 D(emitcode ("; genPagedPointerGet",""));
7399 rtype = operandType (result);
7400 retype = getSpec (rtype);
7402 aopOp (left, ic, FALSE);
7404 /* if the value is already in a pointer register
7405 then don't need anything more */
7406 if (!AOP_INPREG (AOP (left)))
7408 /* otherwise get a free pointer register */
7410 preg = getFreePtr (ic, &aop, FALSE);
7411 emitcode ("mov", "%s,%s",
7413 aopGet (AOP (left), 0, FALSE, TRUE));
7417 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7419 aopOp (result, ic, FALSE);
7421 /* if bitfield then unpack the bits */
7422 if (IS_BITVAR (retype))
7423 genUnpackBits (result, rname, PPOINTER);
7426 /* we have can just get the values */
7427 int size = AOP_SIZE (result);
7433 emitcode ("movx", "a,@%s", rname);
7434 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7439 emitcode ("inc", "%s", rname);
7443 /* now some housekeeping stuff */
7444 if (aop) /* we had to allocate for this iCode */
7446 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7447 freeAsmop (NULL, aop, ic, TRUE);
7451 /* we did not allocate which means left
7452 already in a pointer register, then
7453 if size > 0 && this could be used again
7454 we have to point it back to where it
7456 if ((AOP_SIZE (result) > 1 &&
7457 !OP_SYMBOL (left)->remat &&
7458 (OP_SYMBOL (left)->liveTo > ic->seq ||
7462 int size = AOP_SIZE (result) - 1;
7464 emitcode ("dec", "%s", rname);
7469 freeAsmop (left, NULL, ic, TRUE);
7470 freeAsmop (result, NULL, ic, TRUE);
7471 if (pi) pi->generated = 1;
7475 /*-----------------------------------------------------------------*/
7476 /* genFarPointerGet - gget value from far space */
7477 /*-----------------------------------------------------------------*/
7479 genFarPointerGet (operand * left,
7480 operand * result, iCode * ic, iCode * pi)
7483 sym_link *retype = getSpec (operandType (result));
7485 D(emitcode ("; genFarPointerGet",""));
7487 aopOp (left, ic, FALSE);
7489 /* if the operand is already in dptr
7490 then we do nothing else we move the value to dptr */
7491 if (AOP_TYPE (left) != AOP_STR)
7493 /* if this is remateriazable */
7494 if (AOP_TYPE (left) == AOP_IMMD)
7495 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7497 { /* we need to get it byte by byte */
7498 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7499 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7502 /* so dptr know contains the address */
7503 aopOp (result, ic, FALSE);
7505 /* if bit then unpack */
7506 if (IS_BITVAR (retype))
7507 genUnpackBits (result, "dptr", FPOINTER);
7510 size = AOP_SIZE (result);
7515 emitcode ("movx", "a,@dptr");
7516 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7518 emitcode ("inc", "dptr");
7522 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7523 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7524 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7527 freeAsmop (left, NULL, ic, TRUE);
7528 freeAsmop (result, NULL, ic, TRUE);
7531 /*-----------------------------------------------------------------*/
7532 /* genCodePointerGet - gget value from code space */
7533 /*-----------------------------------------------------------------*/
7535 genCodePointerGet (operand * left,
7536 operand * result, iCode * ic, iCode *pi)
7539 sym_link *retype = getSpec (operandType (result));
7541 D(emitcode ("; genCodePointerGet",""));
7543 aopOp (left, ic, FALSE);
7545 /* if the operand is already in dptr
7546 then we do nothing else we move the value to dptr */
7547 if (AOP_TYPE (left) != AOP_STR)
7549 /* if this is remateriazable */
7550 if (AOP_TYPE (left) == AOP_IMMD)
7551 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7553 { /* we need to get it byte by byte */
7554 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7555 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7558 /* so dptr know contains the address */
7559 aopOp (result, ic, FALSE);
7561 /* if bit then unpack */
7562 if (IS_BITVAR (retype))
7563 genUnpackBits (result, "dptr", CPOINTER);
7566 size = AOP_SIZE (result);
7573 emitcode ("clr", "a");
7574 emitcode ("movc", "a,@a+dptr");
7575 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7576 emitcode ("inc", "dptr");
7580 emitcode ("mov", "a,#0x%02x", offset);
7581 emitcode ("movc", "a,@a+dptr");
7582 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7587 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7588 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7589 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7592 freeAsmop (left, NULL, ic, TRUE);
7593 freeAsmop (result, NULL, ic, TRUE);
7596 /*-----------------------------------------------------------------*/
7597 /* genGenPointerGet - gget value from generic pointer space */
7598 /*-----------------------------------------------------------------*/
7600 genGenPointerGet (operand * left,
7601 operand * result, iCode * ic, iCode *pi)
7604 sym_link *retype = getSpec (operandType (result));
7606 D(emitcode ("; genGenPointerGet",""));
7608 aopOp (left, ic, FALSE);
7610 /* if the operand is already in dptr
7611 then we do nothing else we move the value to dptr */
7612 if (AOP_TYPE (left) != AOP_STR)
7614 /* if this is remateriazable */
7615 if (AOP_TYPE (left) == AOP_IMMD)
7617 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7618 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7619 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7621 emitcode ("mov", "b,#%d", pointerCode (retype));
7624 { /* we need to get it byte by byte */
7625 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7626 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7627 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7630 /* so dptr know contains the address */
7631 aopOp (result, ic, FALSE);
7633 /* if bit then unpack */
7634 if (IS_BITVAR (retype))
7635 genUnpackBits (result, "dptr", GPOINTER);
7638 size = AOP_SIZE (result);
7643 emitcode ("lcall", "__gptrget");
7644 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7646 emitcode ("inc", "dptr");
7650 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7651 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7652 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7655 freeAsmop (left, NULL, ic, TRUE);
7656 freeAsmop (result, NULL, ic, TRUE);
7659 /*-----------------------------------------------------------------*/
7660 /* genPointerGet - generate code for pointer get */
7661 /*-----------------------------------------------------------------*/
7663 genPointerGet (iCode * ic, iCode *pi)
7665 operand *left, *result;
7666 sym_link *type, *etype;
7669 D(emitcode ("; genPointerGet",""));
7671 left = IC_LEFT (ic);
7672 result = IC_RESULT (ic);
7674 /* depending on the type of pointer we need to
7675 move it to the correct pointer register */
7676 type = operandType (left);
7677 etype = getSpec (type);
7678 /* if left is of type of pointer then it is simple */
7679 if (IS_PTR (type) && !IS_FUNC (type->next))
7680 p_type = DCL_TYPE (type);
7683 /* we have to go by the storage class */
7684 p_type = PTR_TYPE (SPEC_OCLS (etype));
7687 /* special case when cast remat */
7688 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7689 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7690 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7691 type = operandType (left);
7692 p_type = DCL_TYPE (type);
7694 /* now that we have the pointer type we assign
7695 the pointer values */
7701 genNearPointerGet (left, result, ic, pi);
7705 genPagedPointerGet (left, result, ic, pi);
7709 genFarPointerGet (left, result, ic, pi);
7713 genCodePointerGet (left, result, ic, pi);
7717 genGenPointerGet (left, result, ic, pi);
7725 /*-----------------------------------------------------------------*/
7726 /* genPackBits - generates code for packed bit storage */
7727 /*-----------------------------------------------------------------*/
7729 genPackBits (sym_link * etype,
7731 char *rname, int p_type)
7733 int offset = 0; /* source byte offset */
7734 int rlen = 0; /* remaining bitfield length */
7735 int blen; /* bitfield length */
7736 int bstr; /* bitfield starting bit within byte */
7737 int litval; /* source literal value (if AOP_LIT) */
7738 unsigned char mask; /* bitmask within current byte */
7740 D(emitcode ("; genPackBits",""));
7742 blen = SPEC_BLEN (etype);
7743 bstr = SPEC_BSTR (etype);
7745 /* If the bitfield length is less than a byte */
7748 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7749 (unsigned char) (0xFF >> (8 - bstr)));
7751 if (AOP_TYPE (right) == AOP_LIT)
7753 /* Case with a bitfield length <8 and literal source
7755 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7757 litval &= (~mask) & 0xff;
7758 emitPtrByteGet (rname, p_type, FALSE);
7759 if ((mask|litval)!=0xff)
7760 emitcode ("anl","a,#0x%02x", mask);
7762 emitcode ("orl","a,#0x%02x", litval);
7766 if ((blen==1) && (p_type!=GPOINTER))
7768 /* Case with a bitfield length == 1 and no generic pointer
7770 if (AOP_TYPE (right) == AOP_CRY)
7771 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7774 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7775 emitcode ("rrc","a");
7777 emitPtrByteGet (rname, p_type, FALSE);
7778 emitcode ("mov","acc.%d,c",bstr);
7782 /* Case with a bitfield length < 8 and arbitrary source
7784 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7785 /* shift and mask source value */
7787 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7789 /* transfer A to B and get next byte */
7790 emitPtrByteGet (rname, p_type, TRUE);
7792 emitcode ("anl", "a,#0x%02x", mask);
7793 emitcode ("orl", "a,b");
7794 if (p_type == GPOINTER)
7795 emitcode ("pop", "b");
7799 emitPtrByteSet (rname, p_type, "a");
7803 /* Bit length is greater than 7 bits. In this case, copy */
7804 /* all except the partial byte at the end */
7805 for (rlen=blen;rlen>=8;rlen-=8)
7807 emitPtrByteSet (rname, p_type,
7808 aopGet (AOP (right), offset++, FALSE, TRUE) );
7810 emitcode ("inc", "%s", rname);
7813 /* If there was a partial byte at the end */
7816 mask = (((unsigned char) -1 << rlen) & 0xff);
7818 if (AOP_TYPE (right) == AOP_LIT)
7820 /* Case with partial byte and literal source
7822 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7823 litval >>= (blen-rlen);
7824 litval &= (~mask) & 0xff;
7825 emitPtrByteGet (rname, p_type, FALSE);
7826 if ((mask|litval)!=0xff)
7827 emitcode ("anl","a,#0x%02x", mask);
7829 emitcode ("orl","a,#0x%02x", litval);
7833 /* Case with partial byte and arbitrary source
7835 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7836 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7838 /* transfer A to B and get next byte */
7839 emitPtrByteGet (rname, p_type, TRUE);
7841 emitcode ("anl", "a,#0x%02x", mask);
7842 emitcode ("orl", "a,b");
7843 if (p_type == GPOINTER)
7844 emitcode ("pop", "b");
7846 emitPtrByteSet (rname, p_type, "a");
7852 /*-----------------------------------------------------------------*/
7853 /* genDataPointerSet - remat pointer to data space */
7854 /*-----------------------------------------------------------------*/
7856 genDataPointerSet (operand * right,
7860 int size, offset = 0;
7861 char *l, buffer[256];
7863 D(emitcode ("; genDataPointerSet",""));
7865 aopOp (right, ic, FALSE);
7867 l = aopGet (AOP (result), 0, FALSE, TRUE);
7868 size = AOP_SIZE (right);
7872 sprintf (buffer, "(%s + %d)", l + 1, offset);
7874 sprintf (buffer, "%s", l + 1);
7875 emitcode ("mov", "%s,%s", buffer,
7876 aopGet (AOP (right), offset++, FALSE, FALSE));
7879 freeAsmop (right, NULL, ic, TRUE);
7880 freeAsmop (result, NULL, ic, TRUE);
7883 /*-----------------------------------------------------------------*/
7884 /* genNearPointerSet - emitcode for near pointer put */
7885 /*-----------------------------------------------------------------*/
7887 genNearPointerSet (operand * right,
7895 sym_link *retype, *letype;
7896 sym_link *ptype = operandType (result);
7898 D(emitcode ("; genNearPointerSet",""));
7900 retype = getSpec (operandType (right));
7901 letype = getSpec (ptype);
7902 aopOp (result, ic, FALSE);
7904 /* if the result is rematerializable &
7905 in data space & not a bit variable */
7906 if (AOP_TYPE (result) == AOP_IMMD &&
7907 DCL_TYPE (ptype) == POINTER &&
7908 !IS_BITVAR (retype) &&
7909 !IS_BITVAR (letype))
7911 genDataPointerSet (right, result, ic);
7915 /* if the value is already in a pointer register
7916 then don't need anything more */
7917 if (!AOP_INPREG (AOP (result)))
7920 //AOP_TYPE (result) == AOP_STK
7924 // Aha, it is a pointer, just in disguise.
7925 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7928 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7929 __FILE__, __LINE__);
7934 rname++; // skip the '@'.
7939 /* otherwise get a free pointer register */
7941 preg = getFreePtr (ic, &aop, FALSE);
7942 emitcode ("mov", "%s,%s",
7944 aopGet (AOP (result), 0, FALSE, TRUE));
7950 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7953 aopOp (right, ic, FALSE);
7955 /* if bitfield then unpack the bits */
7956 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7957 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7960 /* we have can just get the values */
7961 int size = AOP_SIZE (right);
7966 l = aopGet (AOP (right), offset, FALSE, TRUE);
7970 emitcode ("mov", "@%s,a", rname);
7973 emitcode ("mov", "@%s,%s", rname, l);
7975 emitcode ("inc", "%s", rname);
7980 /* now some housekeeping stuff */
7981 if (aop) /* we had to allocate for this iCode */
7984 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
7985 freeAsmop (NULL, aop, ic, TRUE);
7989 /* we did not allocate which means left
7990 already in a pointer register, then
7991 if size > 0 && this could be used again
7992 we have to point it back to where it
7994 if ((AOP_SIZE (right) > 1 &&
7995 !OP_SYMBOL (result)->remat &&
7996 (OP_SYMBOL (result)->liveTo > ic->seq ||
8000 int size = AOP_SIZE (right) - 1;
8002 emitcode ("dec", "%s", rname);
8007 if (pi) pi->generated = 1;
8008 freeAsmop (result, NULL, ic, TRUE);
8009 freeAsmop (right, NULL, ic, TRUE);
8012 /*-----------------------------------------------------------------*/
8013 /* genPagedPointerSet - emitcode for Paged pointer put */
8014 /*-----------------------------------------------------------------*/
8016 genPagedPointerSet (operand * right,
8024 sym_link *retype, *letype;
8026 D(emitcode ("; genPagedPointerSet",""));
8028 retype = getSpec (operandType (right));
8029 letype = getSpec (operandType (result));
8031 aopOp (result, ic, FALSE);
8033 /* if the value is already in a pointer register
8034 then don't need anything more */
8035 if (!AOP_INPREG (AOP (result)))
8037 /* otherwise get a free pointer register */
8039 preg = getFreePtr (ic, &aop, FALSE);
8040 emitcode ("mov", "%s,%s",
8042 aopGet (AOP (result), 0, FALSE, TRUE));
8046 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8048 aopOp (right, ic, FALSE);
8050 /* if bitfield then unpack the bits */
8051 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8052 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8055 /* we have can just get the values */
8056 int size = AOP_SIZE (right);
8061 l = aopGet (AOP (right), offset, FALSE, TRUE);
8064 emitcode ("movx", "@%s,a", rname);
8067 emitcode ("inc", "%s", rname);
8073 /* now some housekeeping stuff */
8074 if (aop) /* we had to allocate for this iCode */
8077 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8078 freeAsmop (NULL, aop, ic, TRUE);
8082 /* we did not allocate which means left
8083 already in a pointer register, then
8084 if size > 0 && this could be used again
8085 we have to point it back to where it
8087 if (AOP_SIZE (right) > 1 &&
8088 !OP_SYMBOL (result)->remat &&
8089 (OP_SYMBOL (result)->liveTo > ic->seq ||
8092 int size = AOP_SIZE (right) - 1;
8094 emitcode ("dec", "%s", rname);
8099 if (pi) pi->generated = 1;
8100 freeAsmop (result, NULL, ic, TRUE);
8101 freeAsmop (right, NULL, ic, TRUE);
8106 /*-----------------------------------------------------------------*/
8107 /* genFarPointerSet - set value from far space */
8108 /*-----------------------------------------------------------------*/
8110 genFarPointerSet (operand * right,
8111 operand * result, iCode * ic, iCode * pi)
8114 sym_link *retype = getSpec (operandType (right));
8115 sym_link *letype = getSpec (operandType (result));
8117 D(emitcode ("; genFarPointerSet",""));
8119 aopOp (result, ic, FALSE);
8121 /* if the operand is already in dptr
8122 then we do nothing else we move the value to dptr */
8123 if (AOP_TYPE (result) != AOP_STR)
8125 /* if this is remateriazable */
8126 if (AOP_TYPE (result) == AOP_IMMD)
8127 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8129 { /* we need to get it byte by byte */
8130 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8131 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8134 /* so dptr know contains the address */
8135 aopOp (right, ic, FALSE);
8137 /* if bit then unpack */
8138 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8139 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8142 size = AOP_SIZE (right);
8147 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8149 emitcode ("movx", "@dptr,a");
8151 emitcode ("inc", "dptr");
8154 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8155 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8156 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8159 freeAsmop (result, NULL, ic, TRUE);
8160 freeAsmop (right, NULL, ic, TRUE);
8163 /*-----------------------------------------------------------------*/
8164 /* genGenPointerSet - set value from generic pointer space */
8165 /*-----------------------------------------------------------------*/
8167 genGenPointerSet (operand * right,
8168 operand * result, iCode * ic, iCode * pi)
8171 sym_link *retype = getSpec (operandType (right));
8172 sym_link *letype = getSpec (operandType (result));
8174 D(emitcode ("; genGenPointerSet",""));
8176 aopOp (result, ic, FALSE);
8178 /* if the operand is already in dptr
8179 then we do nothing else we move the value to dptr */
8180 if (AOP_TYPE (result) != AOP_STR)
8182 /* if this is remateriazable */
8183 if (AOP_TYPE (result) == AOP_IMMD)
8185 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8186 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8187 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8189 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8192 { /* we need to get it byte by byte */
8193 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8194 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8195 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8198 /* so dptr know contains the address */
8199 aopOp (right, ic, FALSE);
8201 /* if bit then unpack */
8202 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8203 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8206 size = AOP_SIZE (right);
8211 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8213 emitcode ("lcall", "__gptrput");
8215 emitcode ("inc", "dptr");
8219 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8220 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8221 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8224 freeAsmop (result, NULL, ic, TRUE);
8225 freeAsmop (right, NULL, ic, TRUE);
8228 /*-----------------------------------------------------------------*/
8229 /* genPointerSet - stores the value into a pointer location */
8230 /*-----------------------------------------------------------------*/
8232 genPointerSet (iCode * ic, iCode *pi)
8234 operand *right, *result;
8235 sym_link *type, *etype;
8238 D(emitcode ("; genPointerSet",""));
8240 right = IC_RIGHT (ic);
8241 result = IC_RESULT (ic);
8243 /* depending on the type of pointer we need to
8244 move it to the correct pointer register */
8245 type = operandType (result);
8246 etype = getSpec (type);
8247 /* if left is of type of pointer then it is simple */
8248 if (IS_PTR (type) && !IS_FUNC (type->next))
8250 p_type = DCL_TYPE (type);
8254 /* we have to go by the storage class */
8255 p_type = PTR_TYPE (SPEC_OCLS (etype));
8258 /* special case when cast remat */
8259 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8260 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8261 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8262 type = operandType (result);
8263 p_type = DCL_TYPE (type);
8265 /* now that we have the pointer type we assign
8266 the pointer values */
8272 genNearPointerSet (right, result, ic, pi);
8276 genPagedPointerSet (right, result, ic, pi);
8280 genFarPointerSet (right, result, ic, pi);
8284 genGenPointerSet (right, result, ic, pi);
8288 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8289 "genPointerSet: illegal pointer type");
8294 /*-----------------------------------------------------------------*/
8295 /* genIfx - generate code for Ifx statement */
8296 /*-----------------------------------------------------------------*/
8298 genIfx (iCode * ic, iCode * popIc)
8300 operand *cond = IC_COND (ic);
8303 D(emitcode ("; genIfx",""));
8305 aopOp (cond, ic, FALSE);
8307 /* get the value into acc */
8308 if (AOP_TYPE (cond) != AOP_CRY)
8312 /* the result is now in the accumulator */
8313 freeAsmop (cond, NULL, ic, TRUE);
8315 /* if there was something to be popped then do it */
8319 /* if the condition is a bit variable */
8320 if (isbit && IS_ITEMP (cond) &&
8322 genIfxJump (ic, SPIL_LOC (cond)->rname);
8323 else if (isbit && !IS_ITEMP (cond))
8324 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8326 genIfxJump (ic, "a");
8331 /*-----------------------------------------------------------------*/
8332 /* genAddrOf - generates code for address of */
8333 /*-----------------------------------------------------------------*/
8335 genAddrOf (iCode * ic)
8337 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8340 D(emitcode ("; genAddrOf",""));
8342 aopOp (IC_RESULT (ic), ic, FALSE);
8344 /* if the operand is on the stack then we
8345 need to get the stack offset of this
8349 /* if it has an offset then we need to compute
8353 emitcode ("mov", "a,_bp");
8354 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8355 ((char) (sym->stack - _G.nRegsSaved)) :
8356 ((char) sym->stack)) & 0xff);
8357 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8361 /* we can just move _bp */
8362 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8364 /* fill the result with zero */
8365 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8370 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8376 /* object not on stack then we need the name */
8377 size = AOP_SIZE (IC_RESULT (ic));
8382 char s[SDCC_NAME_MAX];
8384 sprintf (s, "#(%s >> %d)",
8388 sprintf (s, "#%s", sym->rname);
8389 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8393 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8397 /*-----------------------------------------------------------------*/
8398 /* genFarFarAssign - assignment when both are in far space */
8399 /*-----------------------------------------------------------------*/
8401 genFarFarAssign (operand * result, operand * right, iCode * ic)
8403 int size = AOP_SIZE (right);
8407 D(emitcode ("; genFarFarAssign",""));
8409 /* first push the right side on to the stack */
8412 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8414 emitcode ("push", "acc");
8417 freeAsmop (right, NULL, ic, FALSE);
8418 /* now assign DPTR to result */
8419 aopOp (result, ic, FALSE);
8420 size = AOP_SIZE (result);
8423 emitcode ("pop", "acc");
8424 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8426 freeAsmop (result, NULL, ic, FALSE);
8430 /*-----------------------------------------------------------------*/
8431 /* genAssign - generate code for assignment */
8432 /*-----------------------------------------------------------------*/
8434 genAssign (iCode * ic)
8436 operand *result, *right;
8438 unsigned long lit = 0L;
8440 D(emitcode("; genAssign",""));
8442 result = IC_RESULT (ic);
8443 right = IC_RIGHT (ic);
8445 /* if they are the same */
8446 if (operandsEqu (result, right) &&
8447 !isOperandVolatile (result, FALSE) &&
8448 !isOperandVolatile (right, FALSE))
8451 aopOp (right, ic, FALSE);
8453 /* special case both in far space */
8454 if (AOP_TYPE (right) == AOP_DPTR &&
8455 IS_TRUE_SYMOP (result) &&
8456 isOperandInFarSpace (result))
8459 genFarFarAssign (result, right, ic);
8463 aopOp (result, ic, TRUE);
8465 /* if they are the same registers */
8466 if (sameRegs (AOP (right), AOP (result)) &&
8467 !isOperandVolatile (result, FALSE) &&
8468 !isOperandVolatile (right, FALSE))
8471 /* if the result is a bit */
8472 if (AOP_TYPE (result) == AOP_CRY)
8475 /* if the right size is a literal then
8476 we know what the value is */
8477 if (AOP_TYPE (right) == AOP_LIT)
8479 if (((int) operandLitValue (right)))
8480 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8482 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8486 /* the right is also a bit variable */
8487 if (AOP_TYPE (right) == AOP_CRY)
8489 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8490 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8496 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8500 /* bit variables done */
8502 size = AOP_SIZE (result);
8504 if (AOP_TYPE (right) == AOP_LIT)
8505 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8507 (AOP_TYPE (result) != AOP_REG) &&
8508 (AOP_TYPE (right) == AOP_LIT) &&
8509 !IS_FLOAT (operandType (right)) &&
8512 emitcode ("clr", "a");
8515 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8516 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8518 aopPut (AOP (result),
8519 aopGet (AOP (right), size, FALSE, FALSE),
8521 isOperandVolatile (result, FALSE));
8528 aopPut (AOP (result),
8529 aopGet (AOP (right), offset, FALSE, FALSE),
8531 isOperandVolatile (result, FALSE));
8537 freeAsmop (right, NULL, ic, TRUE);
8538 freeAsmop (result, NULL, ic, TRUE);
8541 /*-----------------------------------------------------------------*/
8542 /* genJumpTab - genrates code for jump table */
8543 /*-----------------------------------------------------------------*/
8545 genJumpTab (iCode * ic)
8550 D(emitcode ("; genJumpTab",""));
8552 aopOp (IC_JTCOND (ic), ic, FALSE);
8553 /* get the condition into accumulator */
8554 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8556 /* multiply by three */
8557 emitcode ("add", "a,acc");
8558 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8559 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8561 jtab = newiTempLabel (NULL);
8562 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8563 emitcode ("jmp", "@a+dptr");
8564 emitcode ("", "%05d$:", jtab->key + 100);
8565 /* now generate the jump labels */
8566 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8567 jtab = setNextItem (IC_JTLABELS (ic)))
8568 emitcode ("ljmp", "%05d$", jtab->key + 100);
8572 /*-----------------------------------------------------------------*/
8573 /* genCast - gen code for casting */
8574 /*-----------------------------------------------------------------*/
8576 genCast (iCode * ic)
8578 operand *result = IC_RESULT (ic);
8579 sym_link *ctype = operandType (IC_LEFT (ic));
8580 sym_link *rtype = operandType (IC_RIGHT (ic));
8581 operand *right = IC_RIGHT (ic);
8584 D(emitcode("; genCast",""));
8586 /* if they are equivalent then do nothing */
8587 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8590 aopOp (right, ic, FALSE);
8591 aopOp (result, ic, FALSE);
8593 /* if the result is a bit (and not a bitfield) */
8594 // if (AOP_TYPE (result) == AOP_CRY)
8595 if (IS_BITVAR (OP_SYMBOL (result)->type)
8596 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8598 /* if the right size is a literal then
8599 we know what the value is */
8600 if (AOP_TYPE (right) == AOP_LIT)
8602 if (((int) operandLitValue (right)))
8603 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8605 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8610 /* the right is also a bit variable */
8611 if (AOP_TYPE (right) == AOP_CRY)
8613 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8614 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8620 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8625 /* if they are the same size : or less */
8626 if (AOP_SIZE (result) <= AOP_SIZE (right))
8629 /* if they are in the same place */
8630 if (sameRegs (AOP (right), AOP (result)))
8633 /* if they in different places then copy */
8634 size = AOP_SIZE (result);
8638 aopPut (AOP (result),
8639 aopGet (AOP (right), offset, FALSE, FALSE),
8641 isOperandVolatile (result, FALSE));
8648 /* if the result is of type pointer */
8653 sym_link *type = operandType (right);
8654 sym_link *etype = getSpec (type);
8656 /* pointer to generic pointer */
8657 if (IS_GENPTR (ctype))
8660 p_type = DCL_TYPE (type);
8663 if (SPEC_SCLS(etype)==S_REGISTER) {
8664 // let's assume it is a generic pointer
8667 /* we have to go by the storage class */
8668 p_type = PTR_TYPE (SPEC_OCLS (etype));
8672 /* the first two bytes are known */
8673 size = GPTRSIZE - 1;
8677 aopPut (AOP (result),
8678 aopGet (AOP (right), offset, FALSE, FALSE),
8680 isOperandVolatile (result, FALSE));
8683 /* the last byte depending on type */
8685 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8690 // pointerTypeToGPByte will have bitched.
8694 sprintf(gpValStr, "#0x%d", gpVal);
8695 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8700 /* just copy the pointers */
8701 size = AOP_SIZE (result);
8705 aopPut (AOP (result),
8706 aopGet (AOP (right), offset, FALSE, FALSE),
8708 isOperandVolatile (result, FALSE));
8714 /* so we now know that the size of destination is greater
8715 than the size of the source */
8716 /* we move to result for the size of source */
8717 size = AOP_SIZE (right);
8721 aopPut (AOP (result),
8722 aopGet (AOP (right), offset, FALSE, FALSE),
8724 isOperandVolatile (result, FALSE));
8728 /* now depending on the sign of the source && destination */
8729 size = AOP_SIZE (result) - AOP_SIZE (right);
8730 /* if unsigned or not an integral type */
8731 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8734 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8738 /* we need to extend the sign :{ */
8739 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8742 emitcode ("rlc", "a");
8743 emitcode ("subb", "a,acc");
8745 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8748 /* we are done hurray !!!! */
8751 freeAsmop (right, NULL, ic, TRUE);
8752 freeAsmop (result, NULL, ic, TRUE);
8756 /*-----------------------------------------------------------------*/
8757 /* genDjnz - generate decrement & jump if not zero instrucion */
8758 /*-----------------------------------------------------------------*/
8760 genDjnz (iCode * ic, iCode * ifx)
8766 D(emitcode ("; genDjnz",""));
8768 /* if the if condition has a false label
8769 then we cannot save */
8773 /* if the minus is not of the form
8775 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8776 !IS_OP_LITERAL (IC_RIGHT (ic)))
8779 if (operandLitValue (IC_RIGHT (ic)) != 1)
8782 /* if the size of this greater than one then no
8784 if (getSize (operandType (IC_RESULT (ic))) > 1)
8787 /* otherwise we can save BIG */
8788 lbl = newiTempLabel (NULL);
8789 lbl1 = newiTempLabel (NULL);
8791 aopOp (IC_RESULT (ic), ic, FALSE);
8793 if (AOP_NEEDSACC(IC_RESULT(ic)))
8795 /* If the result is accessed indirectly via
8796 * the accumulator, we must explicitly write
8797 * it back after the decrement.
8799 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8801 if (strcmp(rByte, "a"))
8803 /* Something is hopelessly wrong */
8804 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8805 __FILE__, __LINE__);
8806 /* We can just give up; the generated code will be inefficient,
8809 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8812 emitcode ("dec", "%s", rByte);
8813 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8814 emitcode ("jnz", "%05d$", lbl->key + 100);
8816 else if (IS_AOP_PREG (IC_RESULT (ic)))
8818 emitcode ("dec", "%s",
8819 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8820 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8821 emitcode ("jnz", "%05d$", lbl->key + 100);
8825 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8828 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8829 emitcode ("", "%05d$:", lbl->key + 100);
8830 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8831 emitcode ("", "%05d$:", lbl1->key + 100);
8833 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8838 /*-----------------------------------------------------------------*/
8839 /* genReceive - generate code for a receive iCode */
8840 /*-----------------------------------------------------------------*/
8842 genReceive (iCode * ic)
8844 int size = getSize (operandType (IC_RESULT (ic)));
8846 D(emitcode ("; genReceive",""));
8848 if (ic->argreg == 1) { /* first parameter */
8849 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8850 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8851 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8853 offset = fReturnSizeMCS51 - size;
8855 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8856 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8859 aopOp (IC_RESULT (ic), ic, FALSE);
8860 size = AOP_SIZE (IC_RESULT (ic));
8863 emitcode ("pop", "acc");
8864 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8869 aopOp (IC_RESULT (ic), ic, FALSE);
8871 assignResultValue (IC_RESULT (ic));
8873 } else { /* second receive onwards */
8875 aopOp (IC_RESULT (ic), ic, FALSE);
8876 rb1off = ic->argreg;
8878 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8881 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8884 /*-----------------------------------------------------------------*/
8885 /* genDummyRead - generate code for dummy read of volatiles */
8886 /*-----------------------------------------------------------------*/
8888 genDummyRead (iCode * ic)
8893 D(emitcode("; genDummyRead",""));
8895 right = IC_RIGHT (ic);
8897 aopOp (right, ic, FALSE);
8899 /* if the result is a bit */
8900 if (AOP_TYPE (right) == AOP_CRY)
8902 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8906 /* bit variables done */
8908 size = AOP_SIZE (right);
8912 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8917 freeAsmop (right, NULL, ic, TRUE);
8920 /*-----------------------------------------------------------------*/
8921 /* gen51Code - generate code for 8051 based controllers */
8922 /*-----------------------------------------------------------------*/
8924 gen51Code (iCode * lic)
8929 lineHead = lineCurr = NULL;
8931 /* print the allocation information */
8932 if (allocInfo && currFunc)
8933 printAllocInfo (currFunc, codeOutFile);
8934 /* if debug information required */
8935 if (options.debug && currFunc)
8937 debugFile->writeFunction(currFunc);
8939 if (IS_STATIC (currFunc->etype))
8940 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8942 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8945 /* stack pointer name */
8946 if (options.useXstack)
8952 for (ic = lic; ic; ic = ic->next)
8954 _G.current_iCode = ic;
8956 if (ic->lineno && cln != ic->lineno)
8961 emitcode ("", "C$%s$%d$%d$%d ==.",
8962 FileBaseName (ic->filename), ic->lineno,
8963 ic->level, ic->block);
8966 if (!options.noCcodeInAsm) {
8967 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8968 printCLine(ic->filename, ic->lineno));
8972 if (options.iCodeInAsm) {
8976 for (i=0; i<8; i++) {
8977 sprintf (®sInUse[i],
8978 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8981 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8983 /* if the result is marked as
8984 spilt and rematerializable or code for
8985 this has already been generated then
8987 if (resultRemat (ic) || ic->generated)
8990 /* depending on the operation */
9010 /* IPOP happens only when trying to restore a
9011 spilt live range, if there is an ifx statement
9012 following this pop then the if statement might
9013 be using some of the registers being popped which
9014 would destory the contents of the register so
9015 we need to check for this condition and handle it */
9017 ic->next->op == IFX &&
9018 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9019 genIfx (ic->next, ic);
9037 genEndFunction (ic);
9057 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9074 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9078 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9085 /* note these two are xlated by algebraic equivalence
9086 during parsing SDCC.y */
9087 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9088 "got '>=' or '<=' shouldn't have come here");
9092 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9104 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9108 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9112 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9139 case GET_VALUE_AT_ADDRESS:
9140 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9144 if (POINTER_SET (ic))
9145 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9171 addSet (&_G.sendSet, ic);
9174 case DUMMY_READ_VOLATILE:
9183 _G.current_iCode = NULL;
9185 /* now we are ready to call the
9186 peep hole optimizer */
9187 if (!options.nopeep)
9188 peepHole (&lineHead);
9190 /* now do the actual printing */
9191 printLine (lineHead, codeOutFile);