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)
299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300 "null iCode pointer");
307 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
310 size = getSize (OP_SYMBOL (op)->type);
315 else if (ic->op == JUMPTABLE)
318 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
321 size = getSize (OP_SYMBOL (op)->type);
329 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
332 size = getSize (OP_SYMBOL (op)->type);
337 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
340 size = getSize (OP_SYMBOL (op)->type);
353 /*-----------------------------------------------------------------*/
354 /* aopForSym - for a true symbol */
355 /*-----------------------------------------------------------------*/
357 aopForSym (iCode * ic, symbol * sym, bool result)
362 wassertl (ic != NULL, "Got a null iCode");
363 wassertl (sym != NULL, "Got a null symbol");
365 space = SPEC_OCLS (sym->etype);
367 /* if already has one */
371 /* assign depending on the storage class */
372 /* if it is on the stack or indirectly addressable */
373 /* space we need to assign either r0 or r1 to it */
374 if (sym->onStack || sym->iaccess)
376 sym->aop = aop = newAsmop (0);
377 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
378 aop->size = getSize (sym->type);
380 /* now assign the address of the variable to
381 the pointer register */
382 if (aop->type != AOP_STK)
387 if (_G.accInUse || leftRightUseAcc (ic))
388 emitcode ("push", "acc");
390 emitcode ("mov", "a,_bp");
391 emitcode ("add", "a,#0x%02x",
393 ((char) (sym->stack - _G.nRegsSaved)) :
394 ((char) sym->stack)) & 0xff);
395 emitcode ("mov", "%s,a",
396 aop->aopu.aop_ptr->name);
398 if (_G.accInUse || leftRightUseAcc (ic))
399 emitcode ("pop", "acc");
402 emitcode ("mov", "%s,#%s",
403 aop->aopu.aop_ptr->name,
405 aop->paged = space->paged;
408 aop->aopu.aop_stk = sym->stack;
412 /* if in bit space */
413 if (IN_BITSPACE (space))
415 sym->aop = aop = newAsmop (AOP_CRY);
416 aop->aopu.aop_dir = sym->rname;
417 aop->size = getSize (sym->type);
420 /* if it is in direct space */
421 if (IN_DIRSPACE (space))
423 sym->aop = aop = newAsmop (AOP_DIR);
424 aop->aopu.aop_dir = sym->rname;
425 aop->size = getSize (sym->type);
429 /* special case for a function */
430 if (IS_FUNC (sym->type))
432 sym->aop = aop = newAsmop (AOP_IMMD);
433 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
434 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
435 aop->size = FPTRSIZE;
439 /* only remaining is far space */
440 /* in which case DPTR gets the address */
441 sym->aop = aop = newAsmop (AOP_DPTR);
442 emitcode ("mov", "dptr,#%s", sym->rname);
443 aop->size = getSize (sym->type);
445 /* if it is in code space */
446 if (IN_CODESPACE (space))
452 /*-----------------------------------------------------------------*/
453 /* aopForRemat - rematerialzes an object */
454 /*-----------------------------------------------------------------*/
456 aopForRemat (symbol * sym)
458 iCode *ic = sym->rematiCode;
459 asmop *aop = newAsmop (AOP_IMMD);
466 val += (int) operandLitValue (IC_RIGHT (ic));
467 else if (ic->op == '-')
468 val -= (int) operandLitValue (IC_RIGHT (ic));
469 else if (IS_CAST_ICODE(ic)) {
470 sym_link *from_type = operandType(IC_RIGHT(ic));
471 aop->aopu.aop_immd.from_cast_remat = 1;
472 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
473 ptr_type = DCL_TYPE(from_type);
474 if (ptr_type == IPOINTER) {
481 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
485 sprintf (buffer, "(%s %c 0x%04x)",
486 OP_SYMBOL (IC_LEFT (ic))->rname,
487 val >= 0 ? '+' : '-',
490 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
492 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
493 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
494 /* set immd2 field if required */
495 if (aop->aopu.aop_immd.from_cast_remat) {
496 sprintf(buffer,"#0x%02x",ptr_type);
497 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
498 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
504 /*-----------------------------------------------------------------*/
505 /* regsInCommon - two operands have some registers in common */
506 /*-----------------------------------------------------------------*/
508 regsInCommon (operand * op1, operand * op2)
513 /* if they have registers in common */
514 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
517 sym1 = OP_SYMBOL (op1);
518 sym2 = OP_SYMBOL (op2);
520 if (sym1->nRegs == 0 || sym2->nRegs == 0)
523 for (i = 0; i < sym1->nRegs; i++)
529 for (j = 0; j < sym2->nRegs; j++)
534 if (sym2->regs[j] == sym1->regs[i])
542 /*-----------------------------------------------------------------*/
543 /* operandsEqu - equivalent */
544 /*-----------------------------------------------------------------*/
546 operandsEqu (operand * op1, operand * op2)
550 /* if they not symbols */
551 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
554 sym1 = OP_SYMBOL (op1);
555 sym2 = OP_SYMBOL (op2);
557 /* if both are itemps & one is spilt
558 and the other is not then false */
559 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
560 sym1->isspilt != sym2->isspilt)
563 /* if they are the same */
567 if (strcmp (sym1->rname, sym2->rname) == 0)
571 /* if left is a tmp & right is not */
572 if (IS_ITEMP (op1) &&
575 (sym1->usl.spillLoc == sym2))
578 if (IS_ITEMP (op2) &&
582 (sym2->usl.spillLoc == sym1))
588 /*-----------------------------------------------------------------*/
589 /* sameRegs - two asmops have the same registers */
590 /*-----------------------------------------------------------------*/
592 sameRegs (asmop * aop1, asmop * aop2)
599 if (aop1->type != AOP_REG ||
600 aop2->type != AOP_REG)
603 if (aop1->size != aop2->size)
606 for (i = 0; i < aop1->size; i++)
607 if (aop1->aopu.aop_reg[i] !=
608 aop2->aopu.aop_reg[i])
614 /*-----------------------------------------------------------------*/
615 /* aopOp - allocates an asmop for an operand : */
616 /*-----------------------------------------------------------------*/
618 aopOp (operand * op, iCode * ic, bool result)
627 /* if this a literal */
628 if (IS_OP_LITERAL (op))
630 op->aop = aop = newAsmop (AOP_LIT);
631 aop->aopu.aop_lit = op->operand.valOperand;
632 aop->size = getSize (operandType (op));
636 /* if already has a asmop then continue */
640 /* if the underlying symbol has a aop */
641 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
643 op->aop = OP_SYMBOL (op)->aop;
647 /* if this is a true symbol */
648 if (IS_TRUE_SYMOP (op))
650 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
654 /* this is a temporary : this has
660 e) can be a return use only */
662 sym = OP_SYMBOL (op);
664 /* if the type is a conditional */
665 if (sym->regType == REG_CND)
667 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
672 /* if it is spilt then two situations
674 b) has a spill location */
675 if (sym->isspilt || sym->nRegs == 0)
678 /* rematerialize it NOW */
681 sym->aop = op->aop = aop =
683 aop->size = getSize (sym->type);
690 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
691 aop->size = getSize (sym->type);
692 for (i = 0; i < 2; i++)
693 aop->aopu.aop_str[i] = accUse[i];
701 aop = op->aop = sym->aop = newAsmop (AOP_STR);
702 aop->size = getSize (sym->type);
703 for (i = 0; i < fReturnSizeMCS51; i++)
704 aop->aopu.aop_str[i] = fReturn[i];
708 /* else spill location */
709 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
710 /* force a new aop if sizes differ */
711 sym->usl.spillLoc->aop = NULL;
713 sym->aop = op->aop = aop =
714 aopForSym (ic, sym->usl.spillLoc, result);
715 aop->size = getSize (sym->type);
719 /* must be in a register */
720 sym->aop = op->aop = aop = newAsmop (AOP_REG);
721 aop->size = sym->nRegs;
722 for (i = 0; i < sym->nRegs; i++)
723 aop->aopu.aop_reg[i] = sym->regs[i];
726 /*-----------------------------------------------------------------*/
727 /* freeAsmop - free up the asmop given to an operand */
728 /*----------------------------------------------------------------*/
730 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
747 /* depending on the asmop type only three cases need work AOP_RO
748 , AOP_R1 && AOP_STK */
756 emitcode ("pop", "ar0");
760 bitVectUnSetBit (ic->rUsed, R0_IDX);
768 emitcode ("pop", "ar1");
772 bitVectUnSetBit (ic->rUsed, R1_IDX);
778 int stk = aop->aopu.aop_stk + aop->size - 1;
779 bitVectUnSetBit (ic->rUsed, R0_IDX);
780 bitVectUnSetBit (ic->rUsed, R1_IDX);
782 getFreePtr (ic, &aop, FALSE);
786 emitcode ("mov", "a,_bp");
787 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
788 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
792 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
797 emitcode ("pop", "acc");
798 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
801 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
804 freeAsmop (op, NULL, ic, TRUE);
807 emitcode ("pop", "ar1");
813 emitcode ("pop", "ar0");
820 /* all other cases just dealloc */
826 OP_SYMBOL (op)->aop = NULL;
827 /* if the symbol has a spill */
829 SPIL_LOC (op)->aop = NULL;
834 /*-----------------------------------------------------------------*/
835 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
836 /* clobber the accumulator */
837 /*-----------------------------------------------------------------*/
839 aopGetUsesAcc (asmop *aop, int offset)
841 if (offset > (aop->size - 1))
859 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
868 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
872 /* Error case --- will have been caught already */
879 /*-----------------------------------------------------------------*/
880 /* aopGet - for fetching value of the aop */
881 /*-----------------------------------------------------------------*/
883 aopGet (asmop * aop, int offset, bool bit16, bool dname)
888 /* offset is greater than
890 if (offset > (aop->size - 1) &&
891 aop->type != AOP_LIT)
894 /* depending on type */
900 /* if we need to increment it */
901 while (offset > aop->coff)
903 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
907 while (offset < aop->coff)
909 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
916 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
917 return (dname ? "acc" : "a");
919 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
920 rs = Safe_calloc (1, strlen (s) + 1);
925 if (aop->code && aop->coff==0 && offset>=1) {
926 emitcode ("mov", "a,#0x%02x", offset);
927 emitcode ("movc", "a,@a+dptr");
928 return (dname ? "acc" : "a");
931 while (offset > aop->coff)
933 emitcode ("inc", "dptr");
937 while (offset < aop->coff)
939 emitcode ("lcall", "__decdptr");
946 emitcode ("clr", "a");
947 emitcode ("movc", "a,@a+dptr");
951 emitcode ("movx", "a,@dptr");
953 return (dname ? "acc" : "a");
957 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
958 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
960 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
962 sprintf (s, "#(%s >> %d)",
963 aop->aopu.aop_immd.aop_immd1,
967 aop->aopu.aop_immd.aop_immd1);
968 rs = Safe_calloc (1, strlen (s) + 1);
974 sprintf (s, "(%s + %d)",
978 sprintf (s, "%s", aop->aopu.aop_dir);
979 rs = Safe_calloc (1, strlen (s) + 1);
985 return aop->aopu.aop_reg[offset]->dname;
987 return aop->aopu.aop_reg[offset]->name;
990 emitcode ("clr", "a");
991 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
992 emitcode ("rlc", "a");
993 return (dname ? "acc" : "a");
996 if (!offset && dname)
998 return aop->aopu.aop_str[offset];
1001 return aopLiteral (aop->aopu.aop_lit, offset);
1005 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1009 return aop->aopu.aop_str[offset];
1013 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1014 "aopget got unsupported aop->type");
1017 /*-----------------------------------------------------------------*/
1018 /* aopPut - puts a string for a aop */
1019 /*-----------------------------------------------------------------*/
1021 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1025 if (aop->size && offset > (aop->size - 1))
1027 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1028 "aopPut got offset > aop->size");
1032 /* will assign value to value */
1033 /* depending on where it is ofcourse */
1038 sprintf (d, "(%s + %d)",
1039 aop->aopu.aop_dir, offset);
1041 sprintf (d, "%s", aop->aopu.aop_dir);
1043 if (strcmp (d, s) ||
1045 emitcode ("mov", "%s,%s", d, s);
1050 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1051 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1054 strcmp (s, "r0") == 0 ||
1055 strcmp (s, "r1") == 0 ||
1056 strcmp (s, "r2") == 0 ||
1057 strcmp (s, "r3") == 0 ||
1058 strcmp (s, "r4") == 0 ||
1059 strcmp (s, "r5") == 0 ||
1060 strcmp (s, "r6") == 0 ||
1061 strcmp (s, "r7") == 0)
1062 emitcode ("mov", "%s,%s",
1063 aop->aopu.aop_reg[offset]->dname, s);
1065 emitcode ("mov", "%s,%s",
1066 aop->aopu.aop_reg[offset]->name, s);
1073 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1074 "aopPut writing to code space");
1078 while (offset > aop->coff)
1081 emitcode ("inc", "dptr");
1084 while (offset < aop->coff)
1087 emitcode ("lcall", "__decdptr");
1092 /* if not in accumulater */
1095 emitcode ("movx", "@dptr,a");
1100 while (offset > aop->coff)
1103 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1105 while (offset < aop->coff)
1108 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1115 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1121 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1123 else if (strcmp (s, "r0") == 0 ||
1124 strcmp (s, "r1") == 0 ||
1125 strcmp (s, "r2") == 0 ||
1126 strcmp (s, "r3") == 0 ||
1127 strcmp (s, "r4") == 0 ||
1128 strcmp (s, "r5") == 0 ||
1129 strcmp (s, "r6") == 0 ||
1130 strcmp (s, "r7") == 0)
1133 sprintf (buffer, "a%s", s);
1134 emitcode ("mov", "@%s,%s",
1135 aop->aopu.aop_ptr->name, buffer);
1138 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1143 if (strcmp (s, "a") == 0)
1144 emitcode ("push", "acc");
1148 emitcode ("push", "acc");
1150 emitcode ("push", s);
1156 /* if bit variable */
1157 if (!aop->aopu.aop_dir)
1159 emitcode ("clr", "a");
1160 emitcode ("rlc", "a");
1165 emitcode ("clr", "%s", aop->aopu.aop_dir);
1167 emitcode ("setb", "%s", aop->aopu.aop_dir);
1168 else if (!strcmp (s, "c"))
1169 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1172 if (strcmp (s, "a"))
1177 /* set C, if a >= 1 */
1178 emitcode ("add", "a,#0xff");
1179 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1187 if (strcmp (aop->aopu.aop_str[offset], s) ||
1189 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1194 if (!offset && (strcmp (s, "acc") == 0) &&
1198 if (strcmp (aop->aopu.aop_str[offset], s) &&
1200 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1204 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1205 "aopPut got unsupported aop->type");
1213 /*-----------------------------------------------------------------*/
1214 /* pointToEnd :- points to the last byte of the operand */
1215 /*-----------------------------------------------------------------*/
1217 pointToEnd (asmop * aop)
1223 aop->coff = count = (aop->size - 1);
1229 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1233 emitcode ("inc", "dptr");
1240 /*-----------------------------------------------------------------*/
1241 /* reAdjustPreg - points a register back to where it should */
1242 /*-----------------------------------------------------------------*/
1244 reAdjustPreg (asmop * aop)
1246 if ((aop->coff==0) || aop->size <= 1)
1254 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1259 emitcode ("lcall", "__decdptr");
1266 #define AOP(op) op->aop
1267 #define AOP_TYPE(op) AOP(op)->type
1268 #define AOP_SIZE(op) AOP(op)->size
1269 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1270 AOP_TYPE(x) == AOP_R0))
1272 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1273 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1275 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1276 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1277 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1280 /*-----------------------------------------------------------------*/
1281 /* opIsGptr: returns non-zero if the passed operand is */
1282 /* a generic pointer type. */
1283 /*-----------------------------------------------------------------*/
1285 opIsGptr (operand * op)
1287 sym_link *type = operandType (op);
1289 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1296 /*-----------------------------------------------------------------*/
1297 /* getDataSize - get the operand data size */
1298 /*-----------------------------------------------------------------*/
1300 getDataSize (operand * op)
1303 size = AOP_SIZE (op);
1304 if (size == GPTRSIZE)
1306 sym_link *type = operandType (op);
1307 if (IS_GENPTR (type))
1309 /* generic pointer; arithmetic operations
1310 * should ignore the high byte (pointer type).
1318 /*-----------------------------------------------------------------*/
1319 /* outAcc - output Acc */
1320 /*-----------------------------------------------------------------*/
1322 outAcc (operand * result)
1325 size = getDataSize (result);
1328 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1331 /* unsigned or positive */
1334 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1339 /*-----------------------------------------------------------------*/
1340 /* outBitC - output a bit C */
1341 /*-----------------------------------------------------------------*/
1343 outBitC (operand * result)
1345 /* if the result is bit */
1346 if (AOP_TYPE (result) == AOP_CRY)
1347 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1350 emitcode ("clr", "a");
1351 emitcode ("rlc", "a");
1356 /*-----------------------------------------------------------------*/
1357 /* toBoolean - emit code for orl a,operator(sizeop) */
1358 /*-----------------------------------------------------------------*/
1360 toBoolean (operand * oper)
1362 int size = AOP_SIZE (oper) - 1;
1364 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1366 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1370 /*-----------------------------------------------------------------*/
1371 /* genNot - generate code for ! operation */
1372 /*-----------------------------------------------------------------*/
1378 D(emitcode ("; genNot",""));
1380 /* assign asmOps to operand & result */
1381 aopOp (IC_LEFT (ic), ic, FALSE);
1382 aopOp (IC_RESULT (ic), ic, TRUE);
1384 /* if in bit space then a special case */
1385 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1387 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1388 emitcode ("cpl", "c");
1389 outBitC (IC_RESULT (ic));
1393 toBoolean (IC_LEFT (ic));
1395 tlbl = newiTempLabel (NULL);
1396 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1397 emitcode ("", "%05d$:", tlbl->key + 100);
1398 outBitC (IC_RESULT (ic));
1401 /* release the aops */
1402 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1403 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1407 /*-----------------------------------------------------------------*/
1408 /* genCpl - generate code for complement */
1409 /*-----------------------------------------------------------------*/
1417 D(emitcode ("; genCpl",""));
1419 /* assign asmOps to operand & result */
1420 aopOp (IC_LEFT (ic), ic, FALSE);
1421 aopOp (IC_RESULT (ic), ic, TRUE);
1423 /* special case if in bit space */
1424 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1425 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1426 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1427 emitcode ("cpl", "c");
1428 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1431 tlbl=newiTempLabel(NULL);
1432 emitcode ("cjne", "%s,#0x01,%05d$",
1433 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1434 emitcode ("", "%05d$:", tlbl->key+100);
1435 outBitC (IC_RESULT(ic));
1439 size = AOP_SIZE (IC_RESULT (ic));
1442 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1444 emitcode ("cpl", "a");
1445 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1450 /* release the aops */
1451 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1452 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1455 /*-----------------------------------------------------------------*/
1456 /* genUminusFloat - unary minus for floating points */
1457 /*-----------------------------------------------------------------*/
1459 genUminusFloat (operand * op, operand * result)
1461 int size, offset = 0;
1464 D(emitcode ("; genUminusFloat",""));
1466 /* for this we just copy and then flip the bit */
1468 size = AOP_SIZE (op) - 1;
1472 aopPut (AOP (result),
1473 aopGet (AOP (op), offset, FALSE, FALSE),
1475 isOperandVolatile (result, FALSE));
1479 l = aopGet (AOP (op), offset, FALSE, FALSE);
1483 emitcode ("cpl", "acc.7");
1484 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1487 /*-----------------------------------------------------------------*/
1488 /* genUminus - unary minus code generation */
1489 /*-----------------------------------------------------------------*/
1491 genUminus (iCode * ic)
1494 sym_link *optype, *rtype;
1497 D(emitcode ("; genUminus",""));
1500 aopOp (IC_LEFT (ic), ic, FALSE);
1501 aopOp (IC_RESULT (ic), ic, TRUE);
1503 /* if both in bit space then special
1505 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1506 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1509 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1510 emitcode ("cpl", "c");
1511 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1515 optype = operandType (IC_LEFT (ic));
1516 rtype = operandType (IC_RESULT (ic));
1518 /* if float then do float stuff */
1519 if (IS_FLOAT (optype))
1521 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1525 /* otherwise subtract from zero */
1526 size = AOP_SIZE (IC_LEFT (ic));
1531 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1532 if (!strcmp (l, "a"))
1536 emitcode ("cpl", "a");
1537 emitcode ("addc", "a,#0");
1543 emitcode ("clr", "a");
1544 emitcode ("subb", "a,%s", l);
1546 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1549 /* if any remaining bytes in the result */
1550 /* we just need to propagate the sign */
1551 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1553 emitcode ("rlc", "a");
1554 emitcode ("subb", "a,acc");
1556 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1560 /* release the aops */
1561 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1562 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1565 /*-----------------------------------------------------------------*/
1566 /* saveRegisters - will look for a call and save the registers */
1567 /*-----------------------------------------------------------------*/
1569 saveRegisters (iCode * lic)
1576 for (ic = lic; ic; ic = ic->next)
1577 if (ic->op == CALL || ic->op == PCALL)
1582 fprintf (stderr, "found parameter push with no function call\n");
1586 /* if the registers have been saved already or don't need to be then
1590 if (IS_SYMOP(IC_LEFT(ic)) &&
1591 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1592 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1595 /* safe the registers in use at this time but skip the
1596 ones for the result */
1597 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1598 mcs51_rUmaskForOp (IC_RESULT(ic)));
1601 if (options.useXstack)
1603 if (bitVectBitValue (rsave, R0_IDX))
1604 emitcode ("mov", "b,r0");
1605 emitcode ("mov", "r0,%s", spname);
1606 for (i = 0; i < mcs51_nRegs; i++)
1608 if (bitVectBitValue (rsave, i))
1611 emitcode ("mov", "a,b");
1613 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1614 emitcode ("movx", "@r0,a");
1615 emitcode ("inc", "r0");
1618 emitcode ("mov", "%s,r0", spname);
1619 if (bitVectBitValue (rsave, R0_IDX))
1620 emitcode ("mov", "r0,b");
1623 for (i = 0; i < mcs51_nRegs; i++)
1625 if (bitVectBitValue (rsave, i))
1626 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1630 /*-----------------------------------------------------------------*/
1631 /* unsaveRegisters - pop the pushed registers */
1632 /*-----------------------------------------------------------------*/
1634 unsaveRegisters (iCode * ic)
1639 /* restore the registers in use at this time but skip the
1640 ones for the result */
1641 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1642 mcs51_rUmaskForOp (IC_RESULT(ic)));
1644 if (options.useXstack)
1646 emitcode ("mov", "r0,%s", spname);
1647 for (i = mcs51_nRegs; i >= 0; i--)
1649 if (bitVectBitValue (rsave, i))
1651 emitcode ("dec", "r0");
1652 emitcode ("movx", "a,@r0");
1654 emitcode ("mov", "b,a");
1656 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1660 emitcode ("mov", "%s,r0", spname);
1661 if (bitVectBitValue (rsave, R0_IDX))
1662 emitcode ("mov", "r0,b");
1665 for (i = mcs51_nRegs; i >= 0; i--)
1667 if (bitVectBitValue (rsave, i))
1668 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1674 /*-----------------------------------------------------------------*/
1676 /*-----------------------------------------------------------------*/
1678 pushSide (operand * oper, int size)
1683 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1684 if (AOP_TYPE (oper) != AOP_REG &&
1685 AOP_TYPE (oper) != AOP_DIR &&
1688 emitcode ("mov", "a,%s", l);
1689 emitcode ("push", "acc");
1692 emitcode ("push", "%s", l);
1696 /*-----------------------------------------------------------------*/
1697 /* assignResultValue - */
1698 /*-----------------------------------------------------------------*/
1700 assignResultValue (operand * oper)
1703 int size = AOP_SIZE (oper);
1706 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1712 /*-----------------------------------------------------------------*/
1713 /* genXpush - pushes onto the external stack */
1714 /*-----------------------------------------------------------------*/
1716 genXpush (iCode * ic)
1718 asmop *aop = newAsmop (0);
1720 int size, offset = 0;
1722 D(emitcode ("; genXpush",""));
1724 aopOp (IC_LEFT (ic), ic, FALSE);
1725 r = getFreePtr (ic, &aop, FALSE);
1728 emitcode ("mov", "%s,_spx", r->name);
1730 size = AOP_SIZE (IC_LEFT (ic));
1734 char *l = aopGet (AOP (IC_LEFT (ic)),
1735 offset++, FALSE, FALSE);
1737 emitcode ("movx", "@%s,a", r->name);
1738 emitcode ("inc", "%s", r->name);
1743 emitcode ("mov", "_spx,%s", r->name);
1745 freeAsmop (NULL, aop, ic, TRUE);
1746 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1749 /*-----------------------------------------------------------------*/
1750 /* genIpush - genrate code for pushing this gets a little complex */
1751 /*-----------------------------------------------------------------*/
1753 genIpush (iCode * ic)
1755 int size, offset = 0;
1758 D(emitcode ("; genIpush",""));
1760 /* if this is not a parm push : ie. it is spill push
1761 and spill push is always done on the local stack */
1765 /* and the item is spilt then do nothing */
1766 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1769 aopOp (IC_LEFT (ic), ic, FALSE);
1770 size = AOP_SIZE (IC_LEFT (ic));
1771 /* push it on the stack */
1774 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1780 emitcode ("push", "%s", l);
1785 /* this is a paramter push: in this case we call
1786 the routine to find the call and save those
1787 registers that need to be saved */
1790 /* if use external stack then call the external
1791 stack pushing routine */
1792 if (options.useXstack)
1798 /* then do the push */
1799 aopOp (IC_LEFT (ic), ic, FALSE);
1802 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1803 size = AOP_SIZE (IC_LEFT (ic));
1807 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1808 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1809 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1812 emitcode ("mov", "a,%s", l);
1813 emitcode ("push", "acc");
1816 emitcode ("push", "%s", l);
1819 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1822 /*-----------------------------------------------------------------*/
1823 /* genIpop - recover the registers: can happen only for spilling */
1824 /*-----------------------------------------------------------------*/
1826 genIpop (iCode * ic)
1830 D(emitcode ("; genIpop",""));
1832 /* if the temp was not pushed then */
1833 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1836 aopOp (IC_LEFT (ic), ic, FALSE);
1837 size = AOP_SIZE (IC_LEFT (ic));
1838 offset = (size - 1);
1840 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1843 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1846 /*-----------------------------------------------------------------*/
1847 /* unsaveRBank - restores the resgister bank from stack */
1848 /*-----------------------------------------------------------------*/
1850 unsaveRBank (int bank, iCode * ic, bool popPsw)
1856 if (options.useXstack)
1860 /* Assume r0 is available for use. */
1861 r = mcs51_regWithIdx (R0_IDX);;
1866 r = getFreePtr (ic, &aop, FALSE);
1868 emitcode ("mov", "%s,_spx", r->name);
1873 if (options.useXstack)
1875 emitcode ("movx", "a,@%s", r->name);
1876 emitcode ("mov", "psw,a");
1877 emitcode ("dec", "%s", r->name);
1881 emitcode ("pop", "psw");
1885 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1887 if (options.useXstack)
1889 emitcode ("movx", "a,@%s", r->name);
1890 emitcode ("mov", "(%s+%d),a",
1891 regs8051[i].base, 8 * bank + regs8051[i].offset);
1892 emitcode ("dec", "%s", r->name);
1896 emitcode ("pop", "(%s+%d)",
1897 regs8051[i].base, 8 * bank + regs8051[i].offset);
1900 if (options.useXstack)
1902 emitcode ("mov", "_spx,%s", r->name);
1907 freeAsmop (NULL, aop, ic, TRUE);
1911 /*-----------------------------------------------------------------*/
1912 /* saveRBank - saves an entire register bank on the stack */
1913 /*-----------------------------------------------------------------*/
1915 saveRBank (int bank, iCode * ic, bool pushPsw)
1921 if (options.useXstack)
1925 /* Assume r0 is available for use. */
1926 r = mcs51_regWithIdx (R0_IDX);;
1931 r = getFreePtr (ic, &aop, FALSE);
1933 emitcode ("mov", "%s,_spx", r->name);
1936 for (i = 0; i < mcs51_nRegs; i++)
1938 if (options.useXstack)
1940 emitcode ("inc", "%s", r->name);
1941 emitcode ("mov", "a,(%s+%d)",
1942 regs8051[i].base, 8 * bank + regs8051[i].offset);
1943 emitcode ("movx", "@%s,a", r->name);
1946 emitcode ("push", "(%s+%d)",
1947 regs8051[i].base, 8 * bank + regs8051[i].offset);
1952 if (options.useXstack)
1954 emitcode ("mov", "a,psw");
1955 emitcode ("movx", "@%s,a", r->name);
1956 emitcode ("inc", "%s", r->name);
1957 emitcode ("mov", "_spx,%s", r->name);
1962 emitcode ("push", "psw");
1965 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1970 freeAsmop (NULL, aop, ic, TRUE);
1979 /*-----------------------------------------------------------------*/
1980 /* genSend - gen code for SEND */
1981 /*-----------------------------------------------------------------*/
1982 static void genSend(set *sendSet)
1987 for (sic = setFirstItem (_G.sendSet); sic;
1988 sic = setNextItem (_G.sendSet)) {
1989 int size, offset = 0;
1990 aopOp (IC_LEFT (sic), sic, FALSE);
1991 size = AOP_SIZE (IC_LEFT (sic));
1993 if (sic->argreg == 1) {
1995 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1997 if (strcmp (l, fReturn[offset]))
1998 emitcode ("mov", "%s,%s", fReturn[offset], l);
2004 emitcode ("mov","b1_%d,%s",rb1_count++,
2005 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2008 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genCall - generates a call statement */
2014 /*-----------------------------------------------------------------*/
2016 genCall (iCode * ic)
2019 // bool restoreBank = FALSE;
2020 bool swapBanks = FALSE;
2022 D(emitcode("; genCall",""));
2024 dtype = operandType (IC_LEFT (ic));
2025 /* if send set is not empty the assign */
2028 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2029 genSend(reverseSet(_G.sendSet));
2031 genSend(_G.sendSet);
2037 /* if we are calling a not _naked function that is not using
2038 the same register bank then we need to save the
2039 destination registers on the stack */
2040 dtype = operandType (IC_LEFT (ic));
2041 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2042 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2043 !IFFUNC_ISISR (dtype))
2048 /* if caller saves & we have not saved then */
2054 emitcode ("mov", "psw,#0x%02x",
2055 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2059 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2060 OP_SYMBOL (IC_LEFT (ic))->rname :
2061 OP_SYMBOL (IC_LEFT (ic))->name));
2065 emitcode ("mov", "psw,#0x%02x",
2066 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2069 /* if we need assign a result value */
2070 if ((IS_ITEMP (IC_RESULT (ic)) &&
2071 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2072 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2073 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2074 IS_TRUE_SYMOP (IC_RESULT (ic)))
2078 aopOp (IC_RESULT (ic), ic, FALSE);
2081 assignResultValue (IC_RESULT (ic));
2083 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2086 /* adjust the stack for parameters if
2091 if (ic->parmBytes > 3)
2093 emitcode ("mov", "a,%s", spname);
2094 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2095 emitcode ("mov", "%s,a", spname);
2098 for (i = 0; i < ic->parmBytes; i++)
2099 emitcode ("dec", "%s", spname);
2102 /* if we hade saved some registers then unsave them */
2103 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2104 unsaveRegisters (ic);
2106 // /* if register bank was saved then pop them */
2108 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2111 /*-----------------------------------------------------------------*/
2112 /* -10l - generates a call by pointer statement */
2113 /*-----------------------------------------------------------------*/
2115 genPcall (iCode * ic)
2118 symbol *rlbl = newiTempLabel (NULL);
2119 // bool restoreBank=FALSE;
2120 bool swapBanks = FALSE;
2122 D(emitcode("; genPCall",""));
2124 /* if caller saves & we have not saved then */
2128 /* if we are calling a not _naked function that is not using
2129 the same register bank then we need to save the
2130 destination registers on the stack */
2131 dtype = operandType (IC_LEFT (ic))->next;
2132 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2133 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2134 !IFFUNC_ISISR (dtype))
2136 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2137 // restoreBank=TRUE;
2139 // need caution message to user here
2142 /* push the return address on to the stack */
2143 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2144 emitcode ("push", "acc");
2145 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2146 emitcode ("push", "acc");
2148 /* now push the calling address */
2149 aopOp (IC_LEFT (ic), ic, FALSE);
2151 pushSide (IC_LEFT (ic), FPTRSIZE);
2153 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2155 /* if send set is not empty the assign */
2158 genSend(reverseSet(_G.sendSet));
2164 emitcode ("mov", "psw,#0x%02x",
2165 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2169 emitcode ("ret", "");
2170 emitcode ("", "%05d$:", (rlbl->key + 100));
2175 emitcode ("mov", "psw,#0x%02x",
2176 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2179 /* if we need assign a result value */
2180 if ((IS_ITEMP (IC_RESULT (ic)) &&
2181 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2182 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2183 IS_TRUE_SYMOP (IC_RESULT (ic)))
2187 aopOp (IC_RESULT (ic), ic, FALSE);
2190 assignResultValue (IC_RESULT (ic));
2192 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2195 /* adjust the stack for parameters if
2200 if (ic->parmBytes > 3)
2202 emitcode ("mov", "a,%s", spname);
2203 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2204 emitcode ("mov", "%s,a", spname);
2207 for (i = 0; i < ic->parmBytes; i++)
2208 emitcode ("dec", "%s", spname);
2212 // /* if register bank was saved then unsave them */
2214 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2216 /* if we hade saved some registers then
2218 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2219 unsaveRegisters (ic);
2222 /*-----------------------------------------------------------------*/
2223 /* resultRemat - result is rematerializable */
2224 /*-----------------------------------------------------------------*/
2226 resultRemat (iCode * ic)
2228 if (SKIP_IC (ic) || ic->op == IFX)
2231 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2233 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2234 if (sym->remat && !POINTER_SET (ic))
2241 #if defined(__BORLANDC__) || defined(_MSC_VER)
2242 #define STRCASECMP stricmp
2244 #define STRCASECMP strcasecmp
2247 /*-----------------------------------------------------------------*/
2248 /* inExcludeList - return 1 if the string is in exclude Reg list */
2249 /*-----------------------------------------------------------------*/
2251 regsCmp(void *p1, void *p2)
2253 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2257 inExcludeList (char *s)
2259 const char *p = setFirstItem(options.excludeRegsSet);
2261 if (p == NULL || STRCASECMP(p, "none") == 0)
2265 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2268 /*-----------------------------------------------------------------*/
2269 /* genFunction - generated code for function entry */
2270 /*-----------------------------------------------------------------*/
2272 genFunction (iCode * ic)
2276 bool switchedPSW = FALSE;
2277 int calleesaves_saved_register = -1;
2280 /* create the function header */
2281 emitcode (";", "-----------------------------------------");
2282 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2283 emitcode (";", "-----------------------------------------");
2285 emitcode ("", "%s:", sym->rname);
2286 ftype = operandType (IC_LEFT (ic));
2288 if (IFFUNC_ISNAKED(ftype))
2290 emitcode(";", "naked function: no prologue.");
2294 /* here we need to generate the equates for the
2295 register bank if required */
2296 if (FUNC_REGBANK (ftype) != rbank)
2300 rbank = FUNC_REGBANK (ftype);
2301 for (i = 0; i < mcs51_nRegs; i++)
2303 if (strcmp (regs8051[i].base, "0") == 0)
2304 emitcode ("", "%s = 0x%02x",
2306 8 * rbank + regs8051[i].offset);
2308 emitcode ("", "%s = %s + 0x%02x",
2311 8 * rbank + regs8051[i].offset);
2315 /* if this is an interrupt service routine then
2316 save acc, b, dpl, dph */
2317 if (IFFUNC_ISISR (sym->type))
2320 if (!inExcludeList ("acc"))
2321 emitcode ("push", "acc");
2322 if (!inExcludeList ("b"))
2323 emitcode ("push", "b");
2324 if (!inExcludeList ("dpl"))
2325 emitcode ("push", "dpl");
2326 if (!inExcludeList ("dph"))
2327 emitcode ("push", "dph");
2328 /* if this isr has no bank i.e. is going to
2329 run with bank 0 , then we need to save more
2331 if (!FUNC_REGBANK (sym->type))
2334 /* if this function does not call any other
2335 function then we can be economical and
2336 save only those registers that are used */
2337 if (!IFFUNC_HASFCALL(sym->type))
2341 /* if any registers used */
2344 /* save the registers used */
2345 for (i = 0; i < sym->regsUsed->size; i++)
2347 if (bitVectBitValue (sym->regsUsed, i) ||
2348 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2349 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2357 /* this function has a function call cannot
2358 determines register usage so we will have to push the
2360 saveRBank (0, ic, FALSE);
2361 if (options.parms_in_bank1) {
2363 for (i=0; i < 8 ; i++ ) {
2364 emitcode ("push","%s",rb1regs[i]);
2371 /* This ISR uses a non-zero bank.
2373 * We assume that the bank is available for our
2376 * However, if this ISR calls a function which uses some
2377 * other bank, we must save that bank entirely.
2379 unsigned long banksToSave = 0;
2381 if (IFFUNC_HASFCALL(sym->type))
2384 #define MAX_REGISTER_BANKS 4
2389 for (i = ic; i; i = i->next)
2391 if (i->op == ENDFUNCTION)
2393 /* we got to the end OK. */
2401 dtype = operandType (IC_LEFT(i));
2403 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2405 /* Mark this bank for saving. */
2406 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2408 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2412 banksToSave |= (1 << FUNC_REGBANK(dtype));
2415 /* And note that we don't need to do it in
2423 /* This is a mess; we have no idea what
2424 * register bank the called function might
2427 * The only thing I can think of to do is
2428 * throw a warning and hope.
2430 werror(W_FUNCPTR_IN_USING_ISR);
2434 if (banksToSave && options.useXstack)
2436 /* Since we aren't passing it an ic,
2437 * saveRBank will assume r0 is available to abuse.
2439 * So switch to our (trashable) bank now, so
2440 * the caller's R0 isn't trashed.
2442 emitcode ("push", "psw");
2443 emitcode ("mov", "psw,#0x%02x",
2444 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2448 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2450 if (banksToSave & (1 << ix))
2452 saveRBank(ix, NULL, FALSE);
2456 // TODO: this needs a closer look
2457 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2462 /* if callee-save to be used for this function
2463 then save the registers being used in this function */
2464 if (IFFUNC_CALLEESAVES(sym->type))
2468 /* if any registers used */
2471 /* save the registers used */
2472 for (i = 0; i < sym->regsUsed->size; i++)
2474 if (bitVectBitValue (sym->regsUsed, i) ||
2475 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2477 /* remember one saved register for later usage */
2478 if (calleesaves_saved_register < 0)
2479 calleesaves_saved_register = i;
2480 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2488 /* set the register bank to the desired value */
2489 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2492 emitcode ("push", "psw");
2493 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2496 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2499 if (options.useXstack)
2501 emitcode ("mov", "r0,%s", spname);
2502 emitcode ("mov", "a,_bp");
2503 emitcode ("movx", "@r0,a");
2504 emitcode ("inc", "%s", spname);
2508 /* set up the stack */
2509 emitcode ("push", "_bp"); /* save the callers stack */
2511 emitcode ("mov", "_bp,%s", spname);
2514 /* adjust the stack for the function */
2520 werror (W_STACK_OVERFLOW, sym->name);
2522 if (i > 3 && sym->recvSize < 4)
2525 emitcode ("mov", "a,sp");
2526 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2527 emitcode ("mov", "sp,a");
2532 if (IFFUNC_CALLEESAVES(sym->type))
2534 /* if it's a callee-saves function we need a saved register */
2535 if (calleesaves_saved_register >= 0)
2537 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2538 emitcode ("mov", "a,sp");
2539 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2540 emitcode ("mov", "sp,a");
2541 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2544 /* do it the hard way */
2546 emitcode ("inc", "sp");
2550 /* not callee-saves, we can clobber r0 */
2551 emitcode ("mov", "r0,a");
2552 emitcode ("mov", "a,sp");
2553 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2554 emitcode ("mov", "sp,a");
2555 emitcode ("mov", "a,r0");
2560 emitcode ("inc", "sp");
2566 emitcode ("mov", "a,_spx");
2567 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2568 emitcode ("mov", "_spx,a");
2571 /* if critical function then turn interrupts off */
2572 if (IFFUNC_ISCRITICAL (ftype))
2574 emitcode ("mov", "c,ea");
2575 emitcode ("push", "psw"); /* save old ea via c in psw */
2576 emitcode ("clr", "ea");
2580 /*-----------------------------------------------------------------*/
2581 /* genEndFunction - generates epilogue for functions */
2582 /*-----------------------------------------------------------------*/
2584 genEndFunction (iCode * ic)
2586 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2588 if (IFFUNC_ISNAKED(sym->type))
2590 emitcode(";", "naked function: no epilogue.");
2594 if (IFFUNC_ISCRITICAL (sym->type))
2596 emitcode ("pop", "psw"); /* restore ea via c in psw */
2597 emitcode ("mov", "ea,c");
2600 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2602 emitcode ("mov", "%s,_bp", spname);
2605 /* if use external stack but some variables were
2606 added to the local stack then decrement the
2608 if (options.useXstack && sym->stack)
2610 emitcode ("mov", "a,sp");
2611 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2612 emitcode ("mov", "sp,a");
2616 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2618 if (options.useXstack)
2620 emitcode ("mov", "r0,%s", spname);
2621 emitcode ("movx", "a,@r0");
2622 emitcode ("mov", "_bp,a");
2623 emitcode ("dec", "%s", spname);
2627 emitcode ("pop", "_bp");
2631 /* restore the register bank */
2632 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2634 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2635 || !options.useXstack)
2637 /* Special case of ISR using non-zero bank with useXstack
2640 emitcode ("pop", "psw");
2644 if (IFFUNC_ISISR (sym->type))
2647 /* now we need to restore the registers */
2648 /* if this isr has no bank i.e. is going to
2649 run with bank 0 , then we need to save more
2651 if (!FUNC_REGBANK (sym->type))
2653 /* if this function does not call any other
2654 function then we can be economical and
2655 save only those registers that are used */
2656 if (!IFFUNC_HASFCALL(sym->type))
2660 /* if any registers used */
2663 /* save the registers used */
2664 for (i = sym->regsUsed->size; i >= 0; i--)
2666 if (bitVectBitValue (sym->regsUsed, i) ||
2667 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2668 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2675 if (options.parms_in_bank1) {
2677 for (i = 7 ; i >= 0 ; i-- ) {
2678 emitcode ("pop","%s",rb1regs[i]);
2681 /* this function has a function call cannot
2682 determines register usage so we will have to pop the
2684 unsaveRBank (0, ic, FALSE);
2689 /* This ISR uses a non-zero bank.
2691 * Restore any register banks saved by genFunction
2694 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2697 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2699 if (savedBanks & (1 << ix))
2701 unsaveRBank(ix, NULL, FALSE);
2705 if (options.useXstack)
2707 /* Restore bank AFTER calling unsaveRBank,
2708 * since it can trash r0.
2710 emitcode ("pop", "psw");
2714 if (!inExcludeList ("dph"))
2715 emitcode ("pop", "dph");
2716 if (!inExcludeList ("dpl"))
2717 emitcode ("pop", "dpl");
2718 if (!inExcludeList ("b"))
2719 emitcode ("pop", "b");
2720 if (!inExcludeList ("acc"))
2721 emitcode ("pop", "acc");
2723 /* if debug then send end of function */
2724 if (options.debug && currFunc)
2727 emitcode ("", "C$%s$%d$%d$%d ==.",
2728 FileBaseName (ic->filename), currFunc->lastLine,
2729 ic->level, ic->block);
2730 if (IS_STATIC (currFunc->etype))
2731 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2733 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2737 emitcode ("reti", "");
2741 if (IFFUNC_CALLEESAVES(sym->type))
2745 /* if any registers used */
2748 /* save the registers used */
2749 for (i = sym->regsUsed->size; i >= 0; i--)
2751 if (bitVectBitValue (sym->regsUsed, i) ||
2752 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2753 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2759 /* if debug then send end of function */
2760 if (options.debug && currFunc)
2763 emitcode ("", "C$%s$%d$%d$%d ==.",
2764 FileBaseName (ic->filename), currFunc->lastLine,
2765 ic->level, ic->block);
2766 if (IS_STATIC (currFunc->etype))
2767 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2769 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2773 emitcode ("ret", "");
2778 /*-----------------------------------------------------------------*/
2779 /* genRet - generate code for return statement */
2780 /*-----------------------------------------------------------------*/
2784 int size, offset = 0, pushed = 0;
2786 D(emitcode ("; genRet",""));
2788 /* if we have no return value then
2789 just generate the "ret" */
2793 /* we have something to return then
2794 move the return value into place */
2795 aopOp (IC_LEFT (ic), ic, FALSE);
2796 size = AOP_SIZE (IC_LEFT (ic));
2801 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2804 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2806 emitcode ("push", "%s", l);
2811 l = aopGet (AOP (IC_LEFT (ic)), offset,
2813 if (strcmp (fReturn[offset], l))
2814 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2823 if (strcmp (fReturn[pushed], "a"))
2824 emitcode ("pop", fReturn[pushed]);
2826 emitcode ("pop", "acc");
2829 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2832 /* generate a jump to the return label
2833 if the next is not the return statement */
2834 if (!(ic->next && ic->next->op == LABEL &&
2835 IC_LABEL (ic->next) == returnLabel))
2837 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2841 /*-----------------------------------------------------------------*/
2842 /* genLabel - generates a label */
2843 /*-----------------------------------------------------------------*/
2845 genLabel (iCode * ic)
2847 /* special case never generate */
2848 if (IC_LABEL (ic) == entryLabel)
2851 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2854 /*-----------------------------------------------------------------*/
2855 /* genGoto - generates a ljmp */
2856 /*-----------------------------------------------------------------*/
2858 genGoto (iCode * ic)
2860 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2863 /*-----------------------------------------------------------------*/
2864 /* findLabelBackwards: walks back through the iCode chain looking */
2865 /* for the given label. Returns number of iCode instructions */
2866 /* between that label and given ic. */
2867 /* Returns zero if label not found. */
2868 /*-----------------------------------------------------------------*/
2870 findLabelBackwards (iCode * ic, int key)
2879 /* If we have any pushes or pops, we cannot predict the distance.
2880 I don't like this at all, this should be dealt with in the
2882 if (ic->op == IPUSH || ic->op == IPOP) {
2886 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2895 /*-----------------------------------------------------------------*/
2896 /* genPlusIncr :- does addition with increment if possible */
2897 /*-----------------------------------------------------------------*/
2899 genPlusIncr (iCode * ic)
2901 unsigned int icount;
2902 unsigned int size = getDataSize (IC_RESULT (ic));
2904 /* will try to generate an increment */
2905 /* if the right side is not a literal
2907 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2910 /* if the literal value of the right hand side
2911 is greater than 4 then it is not worth it */
2912 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2915 D(emitcode ("; genPlusIncr",""));
2917 /* if increment >=16 bits in register or direct space */
2918 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2919 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2927 /* If the next instruction is a goto and the goto target
2928 * is < 10 instructions previous to this, we can generate
2929 * jumps straight to that target.
2931 if (ic->next && ic->next->op == GOTO
2932 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2933 && labelRange <= 10)
2935 emitcode (";", "tail increment optimized");
2936 tlbl = IC_LABEL (ic->next);
2941 tlbl = newiTempLabel (NULL);
2944 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2945 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2946 IS_AOP_PREG (IC_RESULT (ic)))
2947 emitcode ("cjne", "%s,#0x00,%05d$",
2948 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2952 emitcode ("clr", "a");
2953 emitcode ("cjne", "a,%s,%05d$",
2954 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2958 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2961 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2962 IS_AOP_PREG (IC_RESULT (ic)))
2963 emitcode ("cjne", "%s,#0x00,%05d$",
2964 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2967 emitcode ("cjne", "a,%s,%05d$",
2968 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2971 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2975 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2976 IS_AOP_PREG (IC_RESULT (ic)))
2977 emitcode ("cjne", "%s,#0x00,%05d$",
2978 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2982 emitcode ("cjne", "a,%s,%05d$",
2983 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2986 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2991 emitcode ("", "%05d$:", tlbl->key + 100);
2996 /* if the sizes are greater than 1 then we cannot */
2997 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2998 AOP_SIZE (IC_LEFT (ic)) > 1)
3001 /* we can if the aops of the left & result match or
3002 if they are in registers and the registers are the
3004 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3009 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3010 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3011 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3017 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3026 /*-----------------------------------------------------------------*/
3027 /* outBitAcc - output a bit in acc */
3028 /*-----------------------------------------------------------------*/
3030 outBitAcc (operand * result)
3032 symbol *tlbl = newiTempLabel (NULL);
3033 /* if the result is a bit */
3034 if (AOP_TYPE (result) == AOP_CRY)
3036 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3040 emitcode ("jz", "%05d$", tlbl->key + 100);
3041 emitcode ("mov", "a,%s", one);
3042 emitcode ("", "%05d$:", tlbl->key + 100);
3047 /*-----------------------------------------------------------------*/
3048 /* genPlusBits - generates code for addition of two bits */
3049 /*-----------------------------------------------------------------*/
3051 genPlusBits (iCode * ic)
3053 D(emitcode ("; genPlusBits",""));
3055 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3057 symbol *lbl = newiTempLabel (NULL);
3058 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3059 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3060 emitcode ("cpl", "c");
3061 emitcode ("", "%05d$:", (lbl->key + 100));
3062 outBitC (IC_RESULT (ic));
3066 emitcode ("clr", "a");
3067 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3068 emitcode ("rlc", "a");
3069 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3070 emitcode ("addc", "a,#0x00");
3071 outAcc (IC_RESULT (ic));
3076 /* This is the original version of this code.
3078 * This is being kept around for reference,
3079 * because I am not entirely sure I got it right...
3082 adjustArithmeticResult (iCode * ic)
3084 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3085 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3086 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3087 aopPut (AOP (IC_RESULT (ic)),
3088 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3090 isOperandVolatile (IC_RESULT (ic), FALSE));
3092 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3093 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3094 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3095 aopPut (AOP (IC_RESULT (ic)),
3096 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3098 isOperandVolatile (IC_RESULT (ic), FALSE));
3100 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3101 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3102 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3103 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3104 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3107 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3108 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3112 /* This is the pure and virtuous version of this code.
3113 * I'm pretty certain it's right, but not enough to toss the old
3117 adjustArithmeticResult (iCode * ic)
3119 if (opIsGptr (IC_RESULT (ic)) &&
3120 opIsGptr (IC_LEFT (ic)) &&
3121 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3123 aopPut (AOP (IC_RESULT (ic)),
3124 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3126 isOperandVolatile (IC_RESULT (ic), FALSE));
3129 if (opIsGptr (IC_RESULT (ic)) &&
3130 opIsGptr (IC_RIGHT (ic)) &&
3131 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3133 aopPut (AOP (IC_RESULT (ic)),
3134 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3136 isOperandVolatile (IC_RESULT (ic), FALSE));
3139 if (opIsGptr (IC_RESULT (ic)) &&
3140 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3141 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3142 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3143 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3146 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3147 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3152 /*-----------------------------------------------------------------*/
3153 /* genPlus - generates code for addition */
3154 /*-----------------------------------------------------------------*/
3156 genPlus (iCode * ic)
3158 int size, offset = 0;
3160 asmop *leftOp, *rightOp;
3162 /* special cases :- */
3164 D(emitcode ("; genPlus",""));
3166 aopOp (IC_LEFT (ic), ic, FALSE);
3167 aopOp (IC_RIGHT (ic), ic, FALSE);
3168 aopOp (IC_RESULT (ic), ic, TRUE);
3170 /* if literal, literal on the right or
3171 if left requires ACC or right is already
3173 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3174 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3175 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3177 operand *t = IC_RIGHT (ic);
3178 IC_RIGHT (ic) = IC_LEFT (ic);
3182 /* if both left & right are in bit
3184 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3185 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3191 /* if left in bit space & right literal */
3192 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3193 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3195 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3196 /* if result in bit space */
3197 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3199 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3200 emitcode ("cpl", "c");
3201 outBitC (IC_RESULT (ic));
3205 size = getDataSize (IC_RESULT (ic));
3208 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3209 emitcode ("addc", "a,#00");
3210 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3216 /* if I can do an increment instead
3217 of add then GOOD for ME */
3218 if (genPlusIncr (ic) == TRUE)
3221 size = getDataSize (IC_RESULT (ic));
3223 leftOp = AOP(IC_LEFT(ic));
3224 rightOp = AOP(IC_RIGHT(ic));
3229 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3231 emitcode("mov", "b,a");
3232 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3233 emitcode("xch", "a,b");
3234 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3235 emitcode (add, "a,b");
3237 else if (aopGetUsesAcc (leftOp, offset))
3239 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3240 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3244 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3245 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3247 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3248 add = "addc"; /* further adds must propagate carry */
3251 adjustArithmeticResult (ic);
3254 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3255 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3256 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3259 /*-----------------------------------------------------------------*/
3260 /* genMinusDec :- does subtraction with deccrement if possible */
3261 /*-----------------------------------------------------------------*/
3263 genMinusDec (iCode * ic)
3265 unsigned int icount;
3266 unsigned int size = getDataSize (IC_RESULT (ic));
3268 /* will try to generate an increment */
3269 /* if the right side is not a literal
3271 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3274 /* if the literal value of the right hand side
3275 is greater than 4 then it is not worth it */
3276 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3279 D(emitcode ("; genMinusDec",""));
3281 /* if decrement >=16 bits in register or direct space */
3282 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3283 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3291 /* If the next instruction is a goto and the goto target
3292 * is <= 10 instructions previous to this, we can generate
3293 * jumps straight to that target.
3295 if (ic->next && ic->next->op == GOTO
3296 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3297 && labelRange <= 10)
3299 emitcode (";", "tail decrement optimized");
3300 tlbl = IC_LABEL (ic->next);
3305 tlbl = newiTempLabel (NULL);
3309 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3310 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3311 IS_AOP_PREG (IC_RESULT (ic)))
3312 emitcode ("cjne", "%s,#0xff,%05d$"
3313 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3317 emitcode ("mov", "a,#0xff");
3318 emitcode ("cjne", "a,%s,%05d$"
3319 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3322 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3325 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3326 IS_AOP_PREG (IC_RESULT (ic)))
3327 emitcode ("cjne", "%s,#0xff,%05d$"
3328 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3332 emitcode ("cjne", "a,%s,%05d$"
3333 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3336 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3340 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3341 IS_AOP_PREG (IC_RESULT (ic)))
3342 emitcode ("cjne", "%s,#0xff,%05d$"
3343 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3347 emitcode ("cjne", "a,%s,%05d$"
3348 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3351 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3355 emitcode ("", "%05d$:", tlbl->key + 100);
3360 /* if the sizes are greater than 1 then we cannot */
3361 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3362 AOP_SIZE (IC_LEFT (ic)) > 1)
3365 /* we can if the aops of the left & result match or
3366 if they are in registers and the registers are the
3368 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3372 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3380 /*-----------------------------------------------------------------*/
3381 /* addSign - complete with sign */
3382 /*-----------------------------------------------------------------*/
3384 addSign (operand * result, int offset, int sign)
3386 int size = (getDataSize (result) - offset);
3391 emitcode ("rlc", "a");
3392 emitcode ("subb", "a,acc");
3394 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3398 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3402 /*-----------------------------------------------------------------*/
3403 /* genMinusBits - generates code for subtraction of two bits */
3404 /*-----------------------------------------------------------------*/
3406 genMinusBits (iCode * ic)
3408 symbol *lbl = newiTempLabel (NULL);
3410 D(emitcode ("; genMinusBits",""));
3412 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3414 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3415 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3416 emitcode ("cpl", "c");
3417 emitcode ("", "%05d$:", (lbl->key + 100));
3418 outBitC (IC_RESULT (ic));
3422 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3423 emitcode ("subb", "a,acc");
3424 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3425 emitcode ("inc", "a");
3426 emitcode ("", "%05d$:", (lbl->key + 100));
3427 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3428 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3432 /*-----------------------------------------------------------------*/
3433 /* genMinus - generates code for subtraction */
3434 /*-----------------------------------------------------------------*/
3436 genMinus (iCode * ic)
3438 int size, offset = 0;
3440 D(emitcode ("; genMinus",""));
3442 aopOp (IC_LEFT (ic), ic, FALSE);
3443 aopOp (IC_RIGHT (ic), ic, FALSE);
3444 aopOp (IC_RESULT (ic), ic, TRUE);
3446 /* special cases :- */
3447 /* if both left & right are in bit space */
3448 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3449 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3455 /* if I can do an decrement instead
3456 of subtract then GOOD for ME */
3457 if (genMinusDec (ic) == TRUE)
3460 size = getDataSize (IC_RESULT (ic));
3462 /* if literal, add a,#-lit, else normal subb */
3463 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3465 unsigned long lit = 0L;
3467 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3472 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3473 /* first add without previous c */
3475 if (!size && lit== (unsigned long) -1) {
3476 emitcode ("dec", "a");
3478 emitcode ("add", "a,#0x%02x",
3479 (unsigned int) (lit & 0x0FFL));
3482 emitcode ("addc", "a,#0x%02x",
3483 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3485 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3490 asmop *leftOp, *rightOp;
3492 leftOp = AOP(IC_LEFT(ic));
3493 rightOp = AOP(IC_RIGHT(ic));
3497 if (aopGetUsesAcc(rightOp, offset)) {
3498 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3499 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3501 emitcode( "setb", "c");
3503 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3504 emitcode("cpl", "a");
3506 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3509 emitcode ("subb", "a,%s",
3510 aopGet(rightOp, offset, FALSE, TRUE));
3513 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3518 adjustArithmeticResult (ic);
3521 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3522 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3523 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3527 /*-----------------------------------------------------------------*/
3528 /* genMultbits :- multiplication of bits */
3529 /*-----------------------------------------------------------------*/
3531 genMultbits (operand * left,
3535 D(emitcode ("; genMultbits",""));
3537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3538 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3543 /*-----------------------------------------------------------------*/
3544 /* genMultOneByte : 8*8=8/16 bit multiplication */
3545 /*-----------------------------------------------------------------*/
3547 genMultOneByte (operand * left,
3551 sym_link *opetype = operandType (result);
3553 int size=AOP_SIZE(result);
3555 D(emitcode ("; genMultOneByte",""));
3557 if (size<1 || size>2) {
3558 // this should never happen
3559 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3560 AOP_SIZE(result), __FILE__, lineno);
3564 /* (if two literals: the value is computed before) */
3565 /* if one literal, literal on the right */
3566 if (AOP_TYPE (left) == AOP_LIT)
3571 //emitcode (";", "swapped left and right");
3574 if (SPEC_USIGN(opetype)
3575 // ignore the sign of left and right, what else can we do?
3576 || (SPEC_USIGN(operandType(left)) &&
3577 SPEC_USIGN(operandType(right)))) {
3578 // just an unsigned 8*8=8/16 multiply
3579 //emitcode (";","unsigned");
3580 // TODO: check for accumulator clash between left & right aops?
3581 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3582 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3583 emitcode ("mul", "ab");
3584 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3586 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3591 // we have to do a signed multiply
3593 //emitcode (";", "signed");
3594 emitcode ("clr", "F0"); // reset sign flag
3595 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3597 lbl=newiTempLabel(NULL);
3598 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3599 // left side is negative, 8-bit two's complement, this fails for -128
3600 emitcode ("setb", "F0"); // set sign flag
3601 emitcode ("cpl", "a");
3602 emitcode ("inc", "a");
3604 emitcode ("", "%05d$:", lbl->key+100);
3607 if (AOP_TYPE(right)==AOP_LIT) {
3608 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3609 /* AND literal negative */
3611 emitcode ("cpl", "F0"); // complement sign flag
3612 emitcode ("mov", "b,#0x%02x", -val);
3614 emitcode ("mov", "b,#0x%02x", val);
3617 lbl=newiTempLabel(NULL);
3618 emitcode ("mov", "b,a");
3619 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3620 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3621 // right side is negative, 8-bit two's complement
3622 emitcode ("cpl", "F0"); // complement sign flag
3623 emitcode ("cpl", "a");
3624 emitcode ("inc", "a");
3625 emitcode ("", "%05d$:", lbl->key+100);
3627 emitcode ("mul", "ab");
3629 lbl=newiTempLabel(NULL);
3630 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3631 // only ONE op was negative, we have to do a 8/16-bit two's complement
3632 emitcode ("cpl", "a"); // lsb
3634 emitcode ("inc", "a");
3636 emitcode ("add", "a,#1");
3637 emitcode ("xch", "a,b");
3638 emitcode ("cpl", "a"); // msb
3639 emitcode ("addc", "a,#0");
3640 emitcode ("xch", "a,b");
3643 emitcode ("", "%05d$:", lbl->key+100);
3644 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3646 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3650 /*-----------------------------------------------------------------*/
3651 /* genMult - generates code for multiplication */
3652 /*-----------------------------------------------------------------*/
3654 genMult (iCode * ic)
3656 operand *left = IC_LEFT (ic);
3657 operand *right = IC_RIGHT (ic);
3658 operand *result = IC_RESULT (ic);
3660 D(emitcode ("; genMult",""));
3662 /* assign the amsops */
3663 aopOp (left, ic, FALSE);
3664 aopOp (right, ic, FALSE);
3665 aopOp (result, ic, TRUE);
3667 /* special cases first */
3669 if (AOP_TYPE (left) == AOP_CRY &&
3670 AOP_TYPE (right) == AOP_CRY)
3672 genMultbits (left, right, result);
3676 /* if both are of size == 1 */
3677 #if 0 // one of them can be a sloc shared with the result
3678 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3680 if (getSize(operandType(left)) == 1 &&
3681 getSize(operandType(right)) == 1)
3684 genMultOneByte (left, right, result);
3688 /* should have been converted to function call */
3689 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3690 getSize(OP_SYMBOL(right)->type));
3694 freeAsmop (result, NULL, ic, TRUE);
3695 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3696 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3699 /*-----------------------------------------------------------------*/
3700 /* genDivbits :- division of bits */
3701 /*-----------------------------------------------------------------*/
3703 genDivbits (operand * left,
3710 D(emitcode ("; genDivbits",""));
3712 /* the result must be bit */
3713 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3714 l = aopGet (AOP (left), 0, FALSE, FALSE);
3718 emitcode ("div", "ab");
3719 emitcode ("rrc", "a");
3720 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3723 /*-----------------------------------------------------------------*/
3724 /* genDivOneByte : 8 bit division */
3725 /*-----------------------------------------------------------------*/
3727 genDivOneByte (operand * left,
3731 sym_link *opetype = operandType (result);
3736 D(emitcode ("; genDivOneByte",""));
3738 size = AOP_SIZE (result) - 1;
3740 /* signed or unsigned */
3741 if (SPEC_USIGN (opetype))
3743 /* unsigned is easy */
3744 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3745 l = aopGet (AOP (left), 0, FALSE, FALSE);
3747 emitcode ("div", "ab");
3748 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3750 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3754 /* signed is a little bit more difficult */
3756 /* save the signs of the operands */
3757 l = aopGet (AOP (left), 0, FALSE, FALSE);
3759 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3760 emitcode ("push", "acc"); /* save it on the stack */
3762 /* now sign adjust for both left & right */
3763 l = aopGet (AOP (right), 0, FALSE, FALSE);
3765 lbl = newiTempLabel (NULL);
3766 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3767 emitcode ("cpl", "a");
3768 emitcode ("inc", "a");
3769 emitcode ("", "%05d$:", (lbl->key + 100));
3770 emitcode ("mov", "b,a");
3772 /* sign adjust left side */
3773 l = aopGet (AOP (left), 0, FALSE, FALSE);
3776 lbl = newiTempLabel (NULL);
3777 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3778 emitcode ("cpl", "a");
3779 emitcode ("inc", "a");
3780 emitcode ("", "%05d$:", (lbl->key + 100));
3782 /* now the division */
3783 emitcode ("div", "ab");
3784 /* we are interested in the lower order
3786 emitcode ("mov", "b,a");
3787 lbl = newiTempLabel (NULL);
3788 emitcode ("pop", "acc");
3789 /* if there was an over flow we don't
3790 adjust the sign of the result */
3791 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3792 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3794 emitcode ("clr", "a");
3795 emitcode ("subb", "a,b");
3796 emitcode ("mov", "b,a");
3797 emitcode ("", "%05d$:", (lbl->key + 100));
3799 /* now we are done */
3800 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3803 emitcode ("mov", "c,b.7");
3804 emitcode ("subb", "a,acc");
3807 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3811 /*-----------------------------------------------------------------*/
3812 /* genDiv - generates code for division */
3813 /*-----------------------------------------------------------------*/
3817 operand *left = IC_LEFT (ic);
3818 operand *right = IC_RIGHT (ic);
3819 operand *result = IC_RESULT (ic);
3821 D(emitcode ("; genDiv",""));
3823 /* assign the amsops */
3824 aopOp (left, ic, FALSE);
3825 aopOp (right, ic, FALSE);
3826 aopOp (result, ic, TRUE);
3828 /* special cases first */
3830 if (AOP_TYPE (left) == AOP_CRY &&
3831 AOP_TYPE (right) == AOP_CRY)
3833 genDivbits (left, right, result);
3837 /* if both are of size == 1 */
3838 if (AOP_SIZE (left) == 1 &&
3839 AOP_SIZE (right) == 1)
3841 genDivOneByte (left, right, result);
3845 /* should have been converted to function call */
3848 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3849 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3850 freeAsmop (result, NULL, ic, TRUE);
3853 /*-----------------------------------------------------------------*/
3854 /* genModbits :- modulus of bits */
3855 /*-----------------------------------------------------------------*/
3857 genModbits (operand * left,
3864 D(emitcode ("; genModbits",""));
3866 /* the result must be bit */
3867 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3868 l = aopGet (AOP (left), 0, FALSE, FALSE);
3872 emitcode ("div", "ab");
3873 emitcode ("mov", "a,b");
3874 emitcode ("rrc", "a");
3875 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3878 /*-----------------------------------------------------------------*/
3879 /* genModOneByte : 8 bit modulus */
3880 /*-----------------------------------------------------------------*/
3882 genModOneByte (operand * left,
3886 sym_link *opetype = operandType (result);
3890 D(emitcode ("; genModOneByte",""));
3892 /* signed or unsigned */
3893 if (SPEC_USIGN (opetype))
3895 /* unsigned is easy */
3896 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3897 l = aopGet (AOP (left), 0, FALSE, FALSE);
3899 emitcode ("div", "ab");
3900 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3904 /* signed is a little bit more difficult */
3906 /* save the signs of the operands */
3907 l = aopGet (AOP (left), 0, FALSE, FALSE);
3910 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3911 emitcode ("push", "acc"); /* save it on the stack */
3913 /* now sign adjust for both left & right */
3914 l = aopGet (AOP (right), 0, FALSE, FALSE);
3917 lbl = newiTempLabel (NULL);
3918 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3919 emitcode ("cpl", "a");
3920 emitcode ("inc", "a");
3921 emitcode ("", "%05d$:", (lbl->key + 100));
3922 emitcode ("mov", "b,a");
3924 /* sign adjust left side */
3925 l = aopGet (AOP (left), 0, FALSE, FALSE);
3928 lbl = newiTempLabel (NULL);
3929 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3930 emitcode ("cpl", "a");
3931 emitcode ("inc", "a");
3932 emitcode ("", "%05d$:", (lbl->key + 100));
3934 /* now the multiplication */
3935 emitcode ("div", "ab");
3936 /* we are interested in the lower order
3938 lbl = newiTempLabel (NULL);
3939 emitcode ("pop", "acc");
3940 /* if there was an over flow we don't
3941 adjust the sign of the result */
3942 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3943 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3945 emitcode ("clr", "a");
3946 emitcode ("subb", "a,b");
3947 emitcode ("mov", "b,a");
3948 emitcode ("", "%05d$:", (lbl->key + 100));
3950 /* now we are done */
3951 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3955 /*-----------------------------------------------------------------*/
3956 /* genMod - generates code for division */
3957 /*-----------------------------------------------------------------*/
3961 operand *left = IC_LEFT (ic);
3962 operand *right = IC_RIGHT (ic);
3963 operand *result = IC_RESULT (ic);
3965 D(emitcode ("; genMod",""));
3967 /* assign the amsops */
3968 aopOp (left, ic, FALSE);
3969 aopOp (right, ic, FALSE);
3970 aopOp (result, ic, TRUE);
3972 /* special cases first */
3974 if (AOP_TYPE (left) == AOP_CRY &&
3975 AOP_TYPE (right) == AOP_CRY)
3977 genModbits (left, right, result);
3981 /* if both are of size == 1 */
3982 if (AOP_SIZE (left) == 1 &&
3983 AOP_SIZE (right) == 1)
3985 genModOneByte (left, right, result);
3989 /* should have been converted to function call */
3993 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3994 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3995 freeAsmop (result, NULL, ic, TRUE);
3998 /*-----------------------------------------------------------------*/
3999 /* genIfxJump :- will create a jump depending on the ifx */
4000 /*-----------------------------------------------------------------*/
4002 genIfxJump (iCode * ic, char *jval)
4005 symbol *tlbl = newiTempLabel (NULL);
4008 D(emitcode ("; genIfxJump",""));
4010 /* if true label then we jump if condition
4014 jlbl = IC_TRUE (ic);
4015 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4016 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4020 /* false label is present */
4021 jlbl = IC_FALSE (ic);
4022 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4023 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4025 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4026 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4028 emitcode (inst, "%05d$", tlbl->key + 100);
4029 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4030 emitcode ("", "%05d$:", tlbl->key + 100);
4032 /* mark the icode as generated */
4036 /*-----------------------------------------------------------------*/
4037 /* genCmp :- greater or less than comparison */
4038 /*-----------------------------------------------------------------*/
4040 genCmp (operand * left, operand * right,
4041 operand * result, iCode * ifx, int sign, iCode *ic)
4043 int size, offset = 0;
4044 unsigned long lit = 0L;
4047 D(emitcode ("; genCmp",""));
4049 /* if left & right are bit variables */
4050 if (AOP_TYPE (left) == AOP_CRY &&
4051 AOP_TYPE (right) == AOP_CRY)
4053 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4054 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4058 /* subtract right from left if at the
4059 end the carry flag is set then we know that
4060 left is greater than right */
4061 size = max (AOP_SIZE (left), AOP_SIZE (right));
4063 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4064 if ((size == 1) && !sign &&
4065 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4067 symbol *lbl = newiTempLabel (NULL);
4068 emitcode ("cjne", "%s,%s,%05d$",
4069 aopGet (AOP (left), offset, FALSE, FALSE),
4070 aopGet (AOP (right), offset, FALSE, FALSE),
4072 emitcode ("", "%05d$:", lbl->key + 100);
4076 if (AOP_TYPE (right) == AOP_LIT)
4078 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4079 /* optimize if(x < 0) or if(x >= 0) */
4088 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4089 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4091 genIfxJump (ifx, "acc.7");
4095 emitcode ("rlc", "a");
4103 rightInB = aopGetUsesAcc(AOP (right), offset);
4105 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4106 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4107 if (sign && size == 0)
4109 emitcode ("xrl", "a,#0x80");
4110 if (AOP_TYPE (right) == AOP_LIT)
4112 unsigned long lit = (unsigned long)
4113 floatFromVal (AOP (right)->aopu.aop_lit);
4114 emitcode ("subb", "a,#0x%02x",
4115 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4120 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4121 emitcode ("xrl", "b,#0x80");
4122 emitcode ("subb", "a,b");
4128 emitcode ("subb", "a,b");
4130 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4138 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4139 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4140 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4146 /* if the result is used in the next
4147 ifx conditional branch then generate
4148 code a little differently */
4150 genIfxJump (ifx, "c");
4153 /* leave the result in acc */
4157 /*-----------------------------------------------------------------*/
4158 /* genCmpGt :- greater than comparison */
4159 /*-----------------------------------------------------------------*/
4161 genCmpGt (iCode * ic, iCode * ifx)
4163 operand *left, *right, *result;
4164 sym_link *letype, *retype;
4167 D(emitcode ("; genCmpGt",""));
4169 left = IC_LEFT (ic);
4170 right = IC_RIGHT (ic);
4171 result = IC_RESULT (ic);
4173 letype = getSpec (operandType (left));
4174 retype = getSpec (operandType (right));
4175 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4176 /* assign the amsops */
4177 aopOp (left, ic, FALSE);
4178 aopOp (right, ic, FALSE);
4179 aopOp (result, ic, TRUE);
4181 genCmp (right, left, result, ifx, sign,ic);
4183 freeAsmop (result, NULL, ic, TRUE);
4186 /*-----------------------------------------------------------------*/
4187 /* genCmpLt - less than comparisons */
4188 /*-----------------------------------------------------------------*/
4190 genCmpLt (iCode * ic, iCode * ifx)
4192 operand *left, *right, *result;
4193 sym_link *letype, *retype;
4196 D(emitcode ("; genCmpLt",""));
4198 left = IC_LEFT (ic);
4199 right = IC_RIGHT (ic);
4200 result = IC_RESULT (ic);
4202 letype = getSpec (operandType (left));
4203 retype = getSpec (operandType (right));
4204 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4206 /* assign the amsops */
4207 aopOp (left, ic, FALSE);
4208 aopOp (right, ic, FALSE);
4209 aopOp (result, ic, TRUE);
4211 genCmp (left, right, result, ifx, sign,ic);
4213 freeAsmop (result, NULL, ic, TRUE);
4216 /*-----------------------------------------------------------------*/
4217 /* gencjneshort - compare and jump if not equal */
4218 /*-----------------------------------------------------------------*/
4220 gencjneshort (operand * left, operand * right, symbol * lbl)
4222 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4224 unsigned long lit = 0L;
4226 /* if the left side is a literal or
4227 if the right is in a pointer register and left
4229 if ((AOP_TYPE (left) == AOP_LIT) ||
4230 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4236 if (AOP_TYPE (right) == AOP_LIT)
4237 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4239 /* if the right side is a literal then anything goes */
4240 if (AOP_TYPE (right) == AOP_LIT &&
4241 AOP_TYPE (left) != AOP_DIR &&
4242 AOP_TYPE (left) != AOP_IMMD)
4246 emitcode ("cjne", "%s,%s,%05d$",
4247 aopGet (AOP (left), offset, FALSE, FALSE),
4248 aopGet (AOP (right), offset, FALSE, FALSE),
4254 /* if the right side is in a register or in direct space or
4255 if the left is a pointer register & right is not */
4256 else if (AOP_TYPE (right) == AOP_REG ||
4257 AOP_TYPE (right) == AOP_DIR ||
4258 AOP_TYPE (right) == AOP_LIT ||
4259 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4260 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4264 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4265 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4266 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4267 emitcode ("jnz", "%05d$", lbl->key + 100);
4269 emitcode ("cjne", "a,%s,%05d$",
4270 aopGet (AOP (right), offset, FALSE, TRUE),
4277 /* right is a pointer reg need both a & b */
4280 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4281 if (strcmp (l, "b"))
4282 emitcode ("mov", "b,%s", l);
4283 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4284 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4290 /*-----------------------------------------------------------------*/
4291 /* gencjne - compare and jump if not equal */
4292 /*-----------------------------------------------------------------*/
4294 gencjne (operand * left, operand * right, symbol * lbl)
4296 symbol *tlbl = newiTempLabel (NULL);
4298 gencjneshort (left, right, lbl);
4300 emitcode ("mov", "a,%s", one);
4301 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4302 emitcode ("", "%05d$:", lbl->key + 100);
4303 emitcode ("clr", "a");
4304 emitcode ("", "%05d$:", tlbl->key + 100);
4307 /*-----------------------------------------------------------------*/
4308 /* genCmpEq - generates code for equal to */
4309 /*-----------------------------------------------------------------*/
4311 genCmpEq (iCode * ic, iCode * ifx)
4313 operand *left, *right, *result;
4315 D(emitcode ("; genCmpEq",""));
4317 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4318 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4319 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4321 /* if literal, literal on the right or
4322 if the right is in a pointer register and left
4324 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4325 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4327 operand *t = IC_RIGHT (ic);
4328 IC_RIGHT (ic) = IC_LEFT (ic);
4332 if (ifx && !AOP_SIZE (result))
4335 /* if they are both bit variables */
4336 if (AOP_TYPE (left) == AOP_CRY &&
4337 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4339 if (AOP_TYPE (right) == AOP_LIT)
4341 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4344 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4345 emitcode ("cpl", "c");
4349 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4353 emitcode ("clr", "c");
4355 /* AOP_TYPE(right) == AOP_CRY */
4359 symbol *lbl = newiTempLabel (NULL);
4360 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4361 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4362 emitcode ("cpl", "c");
4363 emitcode ("", "%05d$:", (lbl->key + 100));
4365 /* if true label then we jump if condition
4367 tlbl = newiTempLabel (NULL);
4370 emitcode ("jnc", "%05d$", tlbl->key + 100);
4371 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4375 emitcode ("jc", "%05d$", tlbl->key + 100);
4376 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4378 emitcode ("", "%05d$:", tlbl->key + 100);
4382 tlbl = newiTempLabel (NULL);
4383 gencjneshort (left, right, tlbl);
4386 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4387 emitcode ("", "%05d$:", tlbl->key + 100);
4391 symbol *lbl = newiTempLabel (NULL);
4392 emitcode ("sjmp", "%05d$", lbl->key + 100);
4393 emitcode ("", "%05d$:", tlbl->key + 100);
4394 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4395 emitcode ("", "%05d$:", lbl->key + 100);
4398 /* mark the icode as generated */
4403 /* if they are both bit variables */
4404 if (AOP_TYPE (left) == AOP_CRY &&
4405 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4407 if (AOP_TYPE (right) == AOP_LIT)
4409 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4412 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4413 emitcode ("cpl", "c");
4417 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4421 emitcode ("clr", "c");
4423 /* AOP_TYPE(right) == AOP_CRY */
4427 symbol *lbl = newiTempLabel (NULL);
4428 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4429 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4430 emitcode ("cpl", "c");
4431 emitcode ("", "%05d$:", (lbl->key + 100));
4434 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4441 genIfxJump (ifx, "c");
4444 /* if the result is used in an arithmetic operation
4445 then put the result in place */
4450 gencjne (left, right, newiTempLabel (NULL));
4451 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4453 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4458 genIfxJump (ifx, "a");
4461 /* if the result is used in an arithmetic operation
4462 then put the result in place */
4463 if (AOP_TYPE (result) != AOP_CRY)
4465 /* leave the result in acc */
4469 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4470 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4471 freeAsmop (result, NULL, ic, TRUE);
4474 /*-----------------------------------------------------------------*/
4475 /* ifxForOp - returns the icode containing the ifx for operand */
4476 /*-----------------------------------------------------------------*/
4478 ifxForOp (operand * op, iCode * ic)
4480 /* if true symbol then needs to be assigned */
4481 if (IS_TRUE_SYMOP (op))
4484 /* if this has register type condition and
4485 the next instruction is ifx with the same operand
4486 and live to of the operand is upto the ifx only then */
4488 ic->next->op == IFX &&
4489 IC_COND (ic->next)->key == op->key &&
4490 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4496 /*-----------------------------------------------------------------*/
4497 /* hasInc - operand is incremented before any other use */
4498 /*-----------------------------------------------------------------*/
4500 hasInc (operand *op, iCode *ic,int osize)
4502 sym_link *type = operandType(op);
4503 sym_link *retype = getSpec (type);
4504 iCode *lic = ic->next;
4507 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4508 if (!IS_SYMOP(op)) return NULL;
4510 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4511 if (IS_AGGREGATE(type->next)) return NULL;
4512 if (osize != (isize = getSize(type->next))) return NULL;
4515 /* if operand of the form op = op + <sizeof *op> */
4516 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4517 isOperandEqual(IC_RESULT(lic),op) &&
4518 isOperandLiteral(IC_RIGHT(lic)) &&
4519 operandLitValue(IC_RIGHT(lic)) == isize) {
4522 /* if the operand used or deffed */
4523 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4526 /* if GOTO or IFX */
4527 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4533 /*-----------------------------------------------------------------*/
4534 /* genAndOp - for && operation */
4535 /*-----------------------------------------------------------------*/
4537 genAndOp (iCode * ic)
4539 operand *left, *right, *result;
4542 D(emitcode ("; genAndOp",""));
4544 /* note here that && operations that are in an
4545 if statement are taken away by backPatchLabels
4546 only those used in arthmetic operations remain */
4547 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4548 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4549 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4551 /* if both are bit variables */
4552 if (AOP_TYPE (left) == AOP_CRY &&
4553 AOP_TYPE (right) == AOP_CRY)
4555 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4556 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4561 tlbl = newiTempLabel (NULL);
4563 emitcode ("jz", "%05d$", tlbl->key + 100);
4565 emitcode ("", "%05d$:", tlbl->key + 100);
4569 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4571 freeAsmop (result, NULL, ic, TRUE);
4575 /*-----------------------------------------------------------------*/
4576 /* genOrOp - for || operation */
4577 /*-----------------------------------------------------------------*/
4579 genOrOp (iCode * ic)
4581 operand *left, *right, *result;
4584 D(emitcode ("; genOrOp",""));
4586 /* note here that || operations that are in an
4587 if statement are taken away by backPatchLabels
4588 only those used in arthmetic operations remain */
4589 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4590 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4591 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4593 /* if both are bit variables */
4594 if (AOP_TYPE (left) == AOP_CRY &&
4595 AOP_TYPE (right) == AOP_CRY)
4597 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4598 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4603 tlbl = newiTempLabel (NULL);
4605 emitcode ("jnz", "%05d$", tlbl->key + 100);
4607 emitcode ("", "%05d$:", tlbl->key + 100);
4611 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4612 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4613 freeAsmop (result, NULL, ic, TRUE);
4616 /*-----------------------------------------------------------------*/
4617 /* isLiteralBit - test if lit == 2^n */
4618 /*-----------------------------------------------------------------*/
4620 isLiteralBit (unsigned long lit)
4622 unsigned long pw[32] =
4623 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4624 0x100L, 0x200L, 0x400L, 0x800L,
4625 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4626 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4627 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4628 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4629 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4632 for (idx = 0; idx < 32; idx++)
4638 /*-----------------------------------------------------------------*/
4639 /* continueIfTrue - */
4640 /*-----------------------------------------------------------------*/
4642 continueIfTrue (iCode * ic)
4645 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4649 /*-----------------------------------------------------------------*/
4651 /*-----------------------------------------------------------------*/
4653 jumpIfTrue (iCode * ic)
4656 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4660 /*-----------------------------------------------------------------*/
4661 /* jmpTrueOrFalse - */
4662 /*-----------------------------------------------------------------*/
4664 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4666 // ugly but optimized by peephole
4669 symbol *nlbl = newiTempLabel (NULL);
4670 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4671 emitcode ("", "%05d$:", tlbl->key + 100);
4672 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4673 emitcode ("", "%05d$:", nlbl->key + 100);
4677 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4678 emitcode ("", "%05d$:", tlbl->key + 100);
4683 /*-----------------------------------------------------------------*/
4684 /* genAnd - code for and */
4685 /*-----------------------------------------------------------------*/
4687 genAnd (iCode * ic, iCode * ifx)
4689 operand *left, *right, *result;
4690 int size, offset = 0;
4691 unsigned long lit = 0L;
4695 D(emitcode ("; genAnd",""));
4697 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4698 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4699 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4702 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4704 AOP_TYPE (left), AOP_TYPE (right));
4705 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4707 AOP_SIZE (left), AOP_SIZE (right));
4710 /* if left is a literal & right is not then exchange them */
4711 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4712 AOP_NEEDSACC (left))
4714 operand *tmp = right;
4719 /* if result = right then exchange them */
4720 if (sameRegs (AOP (result), AOP (right)))
4722 operand *tmp = right;
4727 /* if right is bit then exchange them */
4728 if (AOP_TYPE (right) == AOP_CRY &&
4729 AOP_TYPE (left) != AOP_CRY)
4731 operand *tmp = right;
4735 if (AOP_TYPE (right) == AOP_LIT)
4736 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4738 size = AOP_SIZE (result);
4741 // result = bit & yy;
4742 if (AOP_TYPE (left) == AOP_CRY)
4744 // c = bit & literal;
4745 if (AOP_TYPE (right) == AOP_LIT)
4749 if (size && sameRegs (AOP (result), AOP (left)))
4752 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4757 if (size && (AOP_TYPE (result) == AOP_CRY))
4759 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4762 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4767 emitcode ("clr", "c");
4772 if (AOP_TYPE (right) == AOP_CRY)
4775 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4776 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4781 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4783 emitcode ("rrc", "a");
4784 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4792 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4793 genIfxJump (ifx, "c");
4797 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4798 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4799 if ((AOP_TYPE (right) == AOP_LIT) &&
4800 (AOP_TYPE (result) == AOP_CRY) &&
4801 (AOP_TYPE (left) != AOP_CRY))
4803 int posbit = isLiteralBit (lit);
4808 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4811 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4817 sprintf (buffer, "acc.%d", posbit & 0x07);
4818 genIfxJump (ifx, buffer);
4825 symbol *tlbl = newiTempLabel (NULL);
4826 int sizel = AOP_SIZE (left);
4828 emitcode ("setb", "c");
4831 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4833 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4835 if ((posbit = isLiteralBit (bytelit)) != 0)
4836 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4839 if (bytelit != 0x0FFL)
4840 emitcode ("anl", "a,%s",
4841 aopGet (AOP (right), offset, FALSE, TRUE));
4842 emitcode ("jnz", "%05d$", tlbl->key + 100);
4847 // bit = left & literal
4850 emitcode ("clr", "c");
4851 emitcode ("", "%05d$:", tlbl->key + 100);
4853 // if(left & literal)
4857 jmpTrueOrFalse (ifx, tlbl);
4865 /* if left is same as result */
4866 if (sameRegs (AOP (result), AOP (left)))
4868 for (; size--; offset++)
4870 if (AOP_TYPE (right) == AOP_LIT)
4872 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4874 else if (bytelit == 0)
4876 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4878 else if (IS_AOP_PREG (result))
4880 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4881 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4882 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4885 emitcode ("anl", "%s,%s",
4886 aopGet (AOP (left), offset, FALSE, TRUE),
4887 aopGet (AOP (right), offset, FALSE, FALSE));
4891 if (AOP_TYPE (left) == AOP_ACC)
4892 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4895 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4896 if (IS_AOP_PREG (result))
4898 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4899 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4903 emitcode ("anl", "%s,a",
4904 aopGet (AOP (left), offset, FALSE, TRUE));
4911 // left & result in different registers
4912 if (AOP_TYPE (result) == AOP_CRY)
4915 // if(size), result in bit
4916 // if(!size && ifx), conditional oper: if(left & right)
4917 symbol *tlbl = newiTempLabel (NULL);
4918 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4920 emitcode ("setb", "c");
4923 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4924 emitcode ("anl", "a,%s",
4925 aopGet (AOP (right), offset, FALSE, FALSE));
4927 if (AOP_TYPE(left)==AOP_ACC) {
4928 emitcode("mov", "b,a");
4929 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4930 emitcode("anl", "a,b");
4932 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4933 emitcode ("anl", "a,%s",
4934 aopGet (AOP (left), offset, FALSE, FALSE));
4937 emitcode ("jnz", "%05d$", tlbl->key + 100);
4943 emitcode ("", "%05d$:", tlbl->key + 100);
4947 jmpTrueOrFalse (ifx, tlbl);
4951 for (; (size--); offset++)
4954 // result = left & right
4955 if (AOP_TYPE (right) == AOP_LIT)
4957 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4959 aopPut (AOP (result),
4960 aopGet (AOP (left), offset, FALSE, FALSE),
4962 isOperandVolatile (result, FALSE));
4965 else if (bytelit == 0)
4967 /* dummy read of volatile operand */
4968 if (isOperandVolatile (left, FALSE))
4969 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4970 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4974 // faster than result <- left, anl result,right
4975 // and better if result is SFR
4976 if (AOP_TYPE (left) == AOP_ACC)
4977 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4980 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4981 emitcode ("anl", "a,%s",
4982 aopGet (AOP (left), offset, FALSE, FALSE));
4984 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4990 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4991 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4992 freeAsmop (result, NULL, ic, TRUE);
4995 /*-----------------------------------------------------------------*/
4996 /* genOr - code for or */
4997 /*-----------------------------------------------------------------*/
4999 genOr (iCode * ic, iCode * ifx)
5001 operand *left, *right, *result;
5002 int size, offset = 0;
5003 unsigned long lit = 0L;
5005 D(emitcode ("; genOr",""));
5007 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5008 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5009 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5012 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5014 AOP_TYPE (left), AOP_TYPE (right));
5015 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5017 AOP_SIZE (left), AOP_SIZE (right));
5020 /* if left is a literal & right is not then exchange them */
5021 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5022 AOP_NEEDSACC (left))
5024 operand *tmp = right;
5029 /* if result = right then exchange them */
5030 if (sameRegs (AOP (result), AOP (right)))
5032 operand *tmp = right;
5037 /* if right is bit then exchange them */
5038 if (AOP_TYPE (right) == AOP_CRY &&
5039 AOP_TYPE (left) != AOP_CRY)
5041 operand *tmp = right;
5045 if (AOP_TYPE (right) == AOP_LIT)
5046 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5048 size = AOP_SIZE (result);
5052 if (AOP_TYPE (left) == AOP_CRY)
5054 if (AOP_TYPE (right) == AOP_LIT)
5056 // c = bit | literal;
5059 // lit != 0 => result = 1
5060 if (AOP_TYPE (result) == AOP_CRY)
5063 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5065 continueIfTrue (ifx);
5068 emitcode ("setb", "c");
5072 // lit == 0 => result = left
5073 if (size && sameRegs (AOP (result), AOP (left)))
5075 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5080 if (AOP_TYPE (right) == AOP_CRY)
5083 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5084 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5089 symbol *tlbl = newiTempLabel (NULL);
5090 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5091 emitcode ("setb", "c");
5092 emitcode ("jb", "%s,%05d$",
5093 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5095 emitcode ("jnz", "%05d$", tlbl->key + 100);
5096 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5098 jmpTrueOrFalse (ifx, tlbl);
5104 emitcode ("", "%05d$:", tlbl->key + 100);
5113 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5114 genIfxJump (ifx, "c");
5118 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5119 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5120 if ((AOP_TYPE (right) == AOP_LIT) &&
5121 (AOP_TYPE (result) == AOP_CRY) &&
5122 (AOP_TYPE (left) != AOP_CRY))
5128 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5130 continueIfTrue (ifx);
5135 // lit = 0, result = boolean(left)
5137 emitcode ("setb", "c");
5141 symbol *tlbl = newiTempLabel (NULL);
5142 emitcode ("jnz", "%05d$", tlbl->key + 100);
5144 emitcode ("", "%05d$:", tlbl->key + 100);
5148 genIfxJump (ifx, "a");
5156 /* if left is same as result */
5157 if (sameRegs (AOP (result), AOP (left)))
5159 for (; size--; offset++)
5161 if (AOP_TYPE (right) == AOP_LIT)
5163 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5165 /* dummy read of volatile operand */
5166 if (isOperandVolatile (left, FALSE))
5167 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5171 else if (IS_AOP_PREG (left))
5173 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5174 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5175 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5178 emitcode ("orl", "%s,%s",
5179 aopGet (AOP (left), offset, FALSE, TRUE),
5180 aopGet (AOP (right), offset, FALSE, FALSE));
5184 if (AOP_TYPE (left) == AOP_ACC)
5185 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5188 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5189 if (IS_AOP_PREG (left))
5191 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5192 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5195 emitcode ("orl", "%s,a",
5196 aopGet (AOP (left), offset, FALSE, TRUE));
5203 // left & result in different registers
5204 if (AOP_TYPE (result) == AOP_CRY)
5207 // if(size), result in bit
5208 // if(!size && ifx), conditional oper: if(left | right)
5209 symbol *tlbl = newiTempLabel (NULL);
5210 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5212 emitcode ("setb", "c");
5215 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5216 emitcode ("orl", "a,%s",
5217 aopGet (AOP (right), offset, FALSE, FALSE));
5219 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5220 emitcode ("orl", "a,%s",
5221 aopGet (AOP (left), offset, FALSE, FALSE));
5223 emitcode ("jnz", "%05d$", tlbl->key + 100);
5229 emitcode ("", "%05d$:", tlbl->key + 100);
5233 jmpTrueOrFalse (ifx, tlbl);
5236 for (; (size--); offset++)
5239 // result = left & right
5240 if (AOP_TYPE (right) == AOP_LIT)
5242 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5244 aopPut (AOP (result),
5245 aopGet (AOP (left), offset, FALSE, FALSE),
5247 isOperandVolatile (result, FALSE));
5251 // faster than result <- left, anl result,right
5252 // and better if result is SFR
5253 if (AOP_TYPE (left) == AOP_ACC)
5254 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5257 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5258 emitcode ("orl", "a,%s",
5259 aopGet (AOP (left), offset, FALSE, FALSE));
5261 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5266 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5268 freeAsmop (result, NULL, ic, TRUE);
5271 /*-----------------------------------------------------------------*/
5272 /* genXor - code for xclusive or */
5273 /*-----------------------------------------------------------------*/
5275 genXor (iCode * ic, iCode * ifx)
5277 operand *left, *right, *result;
5278 int size, offset = 0;
5279 unsigned long lit = 0L;
5281 D(emitcode ("; genXor",""));
5283 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5284 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5285 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5288 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5290 AOP_TYPE (left), AOP_TYPE (right));
5291 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5293 AOP_SIZE (left), AOP_SIZE (right));
5296 /* if left is a literal & right is not ||
5297 if left needs acc & right does not */
5298 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5299 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5301 operand *tmp = right;
5306 /* if result = right then exchange them */
5307 if (sameRegs (AOP (result), AOP (right)))
5309 operand *tmp = right;
5314 /* if right is bit then exchange them */
5315 if (AOP_TYPE (right) == AOP_CRY &&
5316 AOP_TYPE (left) != AOP_CRY)
5318 operand *tmp = right;
5322 if (AOP_TYPE (right) == AOP_LIT)
5323 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5325 size = AOP_SIZE (result);
5329 if (AOP_TYPE (left) == AOP_CRY)
5331 if (AOP_TYPE (right) == AOP_LIT)
5333 // c = bit & literal;
5336 // lit>>1 != 0 => result = 1
5337 if (AOP_TYPE (result) == AOP_CRY)
5340 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5342 continueIfTrue (ifx);
5345 emitcode ("setb", "c");
5352 // lit == 0, result = left
5353 if (size && sameRegs (AOP (result), AOP (left)))
5355 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5359 // lit == 1, result = not(left)
5360 if (size && sameRegs (AOP (result), AOP (left)))
5362 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5367 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5368 emitcode ("cpl", "c");
5377 symbol *tlbl = newiTempLabel (NULL);
5378 if (AOP_TYPE (right) == AOP_CRY)
5381 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5385 int sizer = AOP_SIZE (right);
5387 // if val>>1 != 0, result = 1
5388 emitcode ("setb", "c");
5391 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5393 // test the msb of the lsb
5394 emitcode ("anl", "a,#0xfe");
5395 emitcode ("jnz", "%05d$", tlbl->key + 100);
5399 emitcode ("rrc", "a");
5401 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5402 emitcode ("cpl", "c");
5403 emitcode ("", "%05d$:", (tlbl->key + 100));
5410 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5411 genIfxJump (ifx, "c");
5415 if (sameRegs (AOP (result), AOP (left)))
5417 /* if left is same as result */
5418 for (; size--; offset++)
5420 if (AOP_TYPE (right) == AOP_LIT)
5422 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5424 else if (IS_AOP_PREG (left))
5426 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5427 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5428 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5431 emitcode ("xrl", "%s,%s",
5432 aopGet (AOP (left), offset, FALSE, TRUE),
5433 aopGet (AOP (right), offset, FALSE, FALSE));
5437 if (AOP_TYPE (left) == AOP_ACC)
5438 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5441 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5442 if (IS_AOP_PREG (left))
5444 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5445 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5448 emitcode ("xrl", "%s,a",
5449 aopGet (AOP (left), offset, FALSE, TRUE));
5456 // left & result in different registers
5457 if (AOP_TYPE (result) == AOP_CRY)
5460 // if(size), result in bit
5461 // if(!size && ifx), conditional oper: if(left ^ right)
5462 symbol *tlbl = newiTempLabel (NULL);
5463 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5465 emitcode ("setb", "c");
5468 if ((AOP_TYPE (right) == AOP_LIT) &&
5469 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5471 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5475 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5476 emitcode ("xrl", "a,%s",
5477 aopGet (AOP (right), offset, FALSE, FALSE));
5479 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5480 emitcode ("xrl", "a,%s",
5481 aopGet (AOP (left), offset, FALSE, FALSE));
5484 emitcode ("jnz", "%05d$", tlbl->key + 100);
5490 emitcode ("", "%05d$:", tlbl->key + 100);
5494 jmpTrueOrFalse (ifx, tlbl);
5497 for (; (size--); offset++)
5500 // result = left & right
5501 if (AOP_TYPE (right) == AOP_LIT)
5503 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5505 aopPut (AOP (result),
5506 aopGet (AOP (left), offset, FALSE, FALSE),
5508 isOperandVolatile (result, FALSE));
5512 // faster than result <- left, anl result,right
5513 // and better if result is SFR
5514 if (AOP_TYPE (left) == AOP_ACC)
5515 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5518 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5519 emitcode ("xrl", "a,%s",
5520 aopGet (AOP (left), offset, FALSE, TRUE));
5522 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5527 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5528 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5529 freeAsmop (result, NULL, ic, TRUE);
5532 /*-----------------------------------------------------------------*/
5533 /* genInline - write the inline code out */
5534 /*-----------------------------------------------------------------*/
5536 genInline (iCode * ic)
5538 char *buffer, *bp, *bp1;
5540 D(emitcode ("; genInline",""));
5542 _G.inLine += (!options.asmpeep);
5544 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5545 strcpy (buffer, IC_INLINE (ic));
5547 /* emit each line as a code */
5572 /* emitcode("",buffer); */
5573 _G.inLine -= (!options.asmpeep);
5576 /*-----------------------------------------------------------------*/
5577 /* genRRC - rotate right with carry */
5578 /*-----------------------------------------------------------------*/
5582 operand *left, *result;
5583 int size, offset = 0;
5586 D(emitcode ("; genRRC",""));
5588 /* rotate right with carry */
5589 left = IC_LEFT (ic);
5590 result = IC_RESULT (ic);
5591 aopOp (left, ic, FALSE);
5592 aopOp (result, ic, FALSE);
5594 /* move it to the result */
5595 size = AOP_SIZE (result);
5597 if (size == 1) { /* special case for 1 byte */
5598 l = aopGet (AOP (left), offset, FALSE, FALSE);
5600 emitcode ("rr", "a");
5606 l = aopGet (AOP (left), offset, FALSE, FALSE);
5608 emitcode ("rrc", "a");
5609 if (AOP_SIZE (result) > 1)
5610 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5612 /* now we need to put the carry into the
5613 highest order byte of the result */
5614 if (AOP_SIZE (result) > 1)
5616 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5619 emitcode ("mov", "acc.7,c");
5621 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5622 freeAsmop (left, NULL, ic, TRUE);
5623 freeAsmop (result, NULL, ic, TRUE);
5626 /*-----------------------------------------------------------------*/
5627 /* genRLC - generate code for rotate left with carry */
5628 /*-----------------------------------------------------------------*/
5632 operand *left, *result;
5633 int size, offset = 0;
5636 D(emitcode ("; genRLC",""));
5638 /* rotate right with carry */
5639 left = IC_LEFT (ic);
5640 result = IC_RESULT (ic);
5641 aopOp (left, ic, FALSE);
5642 aopOp (result, ic, FALSE);
5644 /* move it to the result */
5645 size = AOP_SIZE (result);
5649 l = aopGet (AOP (left), offset, FALSE, FALSE);
5651 if (size == 0) { /* special case for 1 byte */
5655 emitcode ("add", "a,acc");
5656 if (AOP_SIZE (result) > 1)
5657 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5660 l = aopGet (AOP (left), offset, FALSE, FALSE);
5662 emitcode ("rlc", "a");
5663 if (AOP_SIZE (result) > 1)
5664 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5667 /* now we need to put the carry into the
5668 highest order byte of the result */
5669 if (AOP_SIZE (result) > 1)
5671 l = aopGet (AOP (result), 0, FALSE, FALSE);
5674 emitcode ("mov", "acc.0,c");
5676 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5677 freeAsmop (left, NULL, ic, TRUE);
5678 freeAsmop (result, NULL, ic, TRUE);
5681 /*-----------------------------------------------------------------*/
5682 /* genGetHbit - generates code get highest order bit */
5683 /*-----------------------------------------------------------------*/
5685 genGetHbit (iCode * ic)
5687 operand *left, *result;
5689 D(emitcode ("; genGetHbit",""));
5691 left = IC_LEFT (ic);
5692 result = IC_RESULT (ic);
5693 aopOp (left, ic, FALSE);
5694 aopOp (result, ic, FALSE);
5696 /* get the highest order byte into a */
5697 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5698 if (AOP_TYPE (result) == AOP_CRY)
5700 emitcode ("rlc", "a");
5705 emitcode ("rl", "a");
5706 emitcode ("anl", "a,#0x01");
5711 freeAsmop (left, NULL, ic, TRUE);
5712 freeAsmop (result, NULL, ic, TRUE);
5715 /*-----------------------------------------------------------------*/
5716 /* AccRol - rotate left accumulator by known count */
5717 /*-----------------------------------------------------------------*/
5719 AccRol (int shCount)
5721 shCount &= 0x0007; // shCount : 0..7
5728 emitcode ("rl", "a");
5731 emitcode ("rl", "a");
5732 emitcode ("rl", "a");
5735 emitcode ("swap", "a");
5736 emitcode ("rr", "a");
5739 emitcode ("swap", "a");
5742 emitcode ("swap", "a");
5743 emitcode ("rl", "a");
5746 emitcode ("rr", "a");
5747 emitcode ("rr", "a");
5750 emitcode ("rr", "a");
5755 /*-----------------------------------------------------------------*/
5756 /* AccLsh - left shift accumulator by known count */
5757 /*-----------------------------------------------------------------*/
5759 AccLsh (int shCount)
5764 emitcode ("add", "a,acc");
5765 else if (shCount == 2)
5767 emitcode ("add", "a,acc");
5768 emitcode ("add", "a,acc");
5772 /* rotate left accumulator */
5774 /* and kill the lower order bits */
5775 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5780 /*-----------------------------------------------------------------*/
5781 /* AccRsh - right shift accumulator by known count */
5782 /*-----------------------------------------------------------------*/
5784 AccRsh (int shCount)
5791 emitcode ("rrc", "a");
5795 /* rotate right accumulator */
5796 AccRol (8 - shCount);
5797 /* and kill the higher order bits */
5798 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5803 /*-----------------------------------------------------------------*/
5804 /* AccSRsh - signed right shift accumulator by known count */
5805 /*-----------------------------------------------------------------*/
5807 AccSRsh (int shCount)
5814 emitcode ("mov", "c,acc.7");
5815 emitcode ("rrc", "a");
5817 else if (shCount == 2)
5819 emitcode ("mov", "c,acc.7");
5820 emitcode ("rrc", "a");
5821 emitcode ("mov", "c,acc.7");
5822 emitcode ("rrc", "a");
5826 tlbl = newiTempLabel (NULL);
5827 /* rotate right accumulator */
5828 AccRol (8 - shCount);
5829 /* and kill the higher order bits */
5830 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5831 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5832 emitcode ("orl", "a,#0x%02x",
5833 (unsigned char) ~SRMask[shCount]);
5834 emitcode ("", "%05d$:", tlbl->key + 100);
5839 /*-----------------------------------------------------------------*/
5840 /* shiftR1Left2Result - shift right one byte from left to result */
5841 /*-----------------------------------------------------------------*/
5843 shiftR1Left2Result (operand * left, int offl,
5844 operand * result, int offr,
5845 int shCount, int sign)
5847 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5848 /* shift right accumulator */
5853 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5856 /*-----------------------------------------------------------------*/
5857 /* shiftL1Left2Result - shift left one byte from left to result */
5858 /*-----------------------------------------------------------------*/
5860 shiftL1Left2Result (operand * left, int offl,
5861 operand * result, int offr, int shCount)
5864 l = aopGet (AOP (left), offl, FALSE, FALSE);
5866 /* shift left accumulator */
5868 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5871 /*-----------------------------------------------------------------*/
5872 /* movLeft2Result - move byte from left to result */
5873 /*-----------------------------------------------------------------*/
5875 movLeft2Result (operand * left, int offl,
5876 operand * result, int offr, int sign)
5879 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5881 l = aopGet (AOP (left), offl, FALSE, FALSE);
5883 if (*l == '@' && (IS_AOP_PREG (result)))
5885 emitcode ("mov", "a,%s", l);
5886 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5891 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5894 /* MSB sign in acc.7 ! */
5895 if (getDataSize (left) == offl + 1)
5897 emitcode ("mov", "a,%s", l);
5898 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5905 /*-----------------------------------------------------------------*/
5906 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5907 /*-----------------------------------------------------------------*/
5911 emitcode ("rrc", "a");
5912 emitcode ("xch", "a,%s", x);
5913 emitcode ("rrc", "a");
5914 emitcode ("xch", "a,%s", x);
5917 /*-----------------------------------------------------------------*/
5918 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5919 /*-----------------------------------------------------------------*/
5923 emitcode ("xch", "a,%s", x);
5924 emitcode ("rlc", "a");
5925 emitcode ("xch", "a,%s", x);
5926 emitcode ("rlc", "a");
5929 /*-----------------------------------------------------------------*/
5930 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5931 /*-----------------------------------------------------------------*/
5935 emitcode ("xch", "a,%s", x);
5936 emitcode ("add", "a,acc");
5937 emitcode ("xch", "a,%s", x);
5938 emitcode ("rlc", "a");
5941 /*-----------------------------------------------------------------*/
5942 /* AccAXLsh - left shift a:x by known count (0..7) */
5943 /*-----------------------------------------------------------------*/
5945 AccAXLsh (char *x, int shCount)
5960 case 5: // AAAAABBB:CCCCCDDD
5962 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5964 emitcode ("anl", "a,#0x%02x",
5965 SLMask[shCount]); // BBB00000:CCCCCDDD
5967 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5969 AccRol (shCount); // DDDCCCCC:BBB00000
5971 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5973 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5975 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5977 emitcode ("anl", "a,#0x%02x",
5978 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5980 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5982 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5985 case 6: // AAAAAABB:CCCCCCDD
5986 emitcode ("anl", "a,#0x%02x",
5987 SRMask[shCount]); // 000000BB:CCCCCCDD
5988 emitcode ("mov", "c,acc.0"); // c = B
5989 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5991 AccAXRrl1 (x); // BCCCCCCD:D000000B
5992 AccAXRrl1 (x); // BBCCCCCC:DD000000
5994 emitcode("rrc","a");
5995 emitcode("xch","a,%s", x);
5996 emitcode("rrc","a");
5997 emitcode("mov","c,acc.0"); //<< get correct bit
5998 emitcode("xch","a,%s", x);
6000 emitcode("rrc","a");
6001 emitcode("xch","a,%s", x);
6002 emitcode("rrc","a");
6003 emitcode("xch","a,%s", x);
6006 case 7: // a:x <<= 7
6008 emitcode ("anl", "a,#0x%02x",
6009 SRMask[shCount]); // 0000000B:CCCCCCCD
6011 emitcode ("mov", "c,acc.0"); // c = B
6013 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6015 AccAXRrl1 (x); // BCCCCCCC:D0000000
6023 /*-----------------------------------------------------------------*/
6024 /* AccAXRsh - right shift a:x known count (0..7) */
6025 /*-----------------------------------------------------------------*/
6027 AccAXRsh (char *x, int shCount)
6035 AccAXRrl1 (x); // 0->a:x
6040 AccAXRrl1 (x); // 0->a:x
6043 AccAXRrl1 (x); // 0->a:x
6048 case 5: // AAAAABBB:CCCCCDDD = a:x
6050 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6052 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6054 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6056 emitcode ("anl", "a,#0x%02x",
6057 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6059 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6061 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6063 emitcode ("anl", "a,#0x%02x",
6064 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6066 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6068 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6070 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6073 case 6: // AABBBBBB:CCDDDDDD
6075 emitcode ("mov", "c,acc.7");
6076 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6078 emitcode ("mov", "c,acc.7");
6079 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6081 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6083 emitcode ("anl", "a,#0x%02x",
6084 SRMask[shCount]); // 000000AA:BBBBBBCC
6087 case 7: // ABBBBBBB:CDDDDDDD
6089 emitcode ("mov", "c,acc.7"); // c = A
6091 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6093 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6095 emitcode ("anl", "a,#0x%02x",
6096 SRMask[shCount]); // 0000000A:BBBBBBBC
6104 /*-----------------------------------------------------------------*/
6105 /* AccAXRshS - right shift signed a:x known count (0..7) */
6106 /*-----------------------------------------------------------------*/
6108 AccAXRshS (char *x, int shCount)
6116 emitcode ("mov", "c,acc.7");
6117 AccAXRrl1 (x); // s->a:x
6121 emitcode ("mov", "c,acc.7");
6122 AccAXRrl1 (x); // s->a:x
6124 emitcode ("mov", "c,acc.7");
6125 AccAXRrl1 (x); // s->a:x
6130 case 5: // AAAAABBB:CCCCCDDD = a:x
6132 tlbl = newiTempLabel (NULL);
6133 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6135 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6137 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6139 emitcode ("anl", "a,#0x%02x",
6140 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6142 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6144 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6146 emitcode ("anl", "a,#0x%02x",
6147 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6149 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6151 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6153 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6155 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6156 emitcode ("orl", "a,#0x%02x",
6157 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6159 emitcode ("", "%05d$:", tlbl->key + 100);
6160 break; // SSSSAAAA:BBBCCCCC
6162 case 6: // AABBBBBB:CCDDDDDD
6164 tlbl = newiTempLabel (NULL);
6165 emitcode ("mov", "c,acc.7");
6166 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6168 emitcode ("mov", "c,acc.7");
6169 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6171 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6173 emitcode ("anl", "a,#0x%02x",
6174 SRMask[shCount]); // 000000AA:BBBBBBCC
6176 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6177 emitcode ("orl", "a,#0x%02x",
6178 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6180 emitcode ("", "%05d$:", tlbl->key + 100);
6182 case 7: // ABBBBBBB:CDDDDDDD
6184 tlbl = newiTempLabel (NULL);
6185 emitcode ("mov", "c,acc.7"); // c = A
6187 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6189 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6191 emitcode ("anl", "a,#0x%02x",
6192 SRMask[shCount]); // 0000000A:BBBBBBBC
6194 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6195 emitcode ("orl", "a,#0x%02x",
6196 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6198 emitcode ("", "%05d$:", tlbl->key + 100);
6205 /*-----------------------------------------------------------------*/
6206 /* shiftL2Left2Result - shift left two bytes from left to result */
6207 /*-----------------------------------------------------------------*/
6209 shiftL2Left2Result (operand * left, int offl,
6210 operand * result, int offr, int shCount)
6212 if (sameRegs (AOP (result), AOP (left)) &&
6213 ((offl + MSB16) == offr))
6215 /* don't crash result[offr] */
6216 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6217 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6221 movLeft2Result (left, offl, result, offr, 0);
6222 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6224 /* ax << shCount (x = lsb(result)) */
6225 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6226 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6230 /*-----------------------------------------------------------------*/
6231 /* shiftR2Left2Result - shift right two bytes from left to result */
6232 /*-----------------------------------------------------------------*/
6234 shiftR2Left2Result (operand * left, int offl,
6235 operand * result, int offr,
6236 int shCount, int sign)
6238 if (sameRegs (AOP (result), AOP (left)) &&
6239 ((offl + MSB16) == offr))
6241 /* don't crash result[offr] */
6242 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6243 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6247 movLeft2Result (left, offl, result, offr, 0);
6248 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6250 /* a:x >> shCount (x = lsb(result)) */
6252 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6254 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6255 if (getDataSize (result) > 1)
6256 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6259 /*-----------------------------------------------------------------*/
6260 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6261 /*-----------------------------------------------------------------*/
6263 shiftLLeftOrResult (operand * left, int offl,
6264 operand * result, int offr, int shCount)
6266 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6267 /* shift left accumulator */
6269 /* or with result */
6270 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6271 /* back to result */
6272 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6275 /*-----------------------------------------------------------------*/
6276 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6277 /*-----------------------------------------------------------------*/
6279 shiftRLeftOrResult (operand * left, int offl,
6280 operand * result, int offr, int shCount)
6282 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6283 /* shift right accumulator */
6285 /* or with result */
6286 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6287 /* back to result */
6288 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6291 /*-----------------------------------------------------------------*/
6292 /* genlshOne - left shift a one byte quantity by known count */
6293 /*-----------------------------------------------------------------*/
6295 genlshOne (operand * result, operand * left, int shCount)
6297 D(emitcode ("; genlshOne",""));
6299 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6302 /*-----------------------------------------------------------------*/
6303 /* genlshTwo - left shift two bytes by known amount != 0 */
6304 /*-----------------------------------------------------------------*/
6306 genlshTwo (operand * result, operand * left, int shCount)
6310 D(emitcode ("; genlshTwo",""));
6312 size = getDataSize (result);
6314 /* if shCount >= 8 */
6322 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6324 movLeft2Result (left, LSB, result, MSB16, 0);
6326 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6329 /* 1 <= shCount <= 7 */
6333 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6335 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6339 /*-----------------------------------------------------------------*/
6340 /* shiftLLong - shift left one long from left to result */
6341 /* offl = LSB or MSB16 */
6342 /*-----------------------------------------------------------------*/
6344 shiftLLong (operand * left, operand * result, int offr)
6347 int size = AOP_SIZE (result);
6349 if (size >= LSB + offr)
6351 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6353 emitcode ("add", "a,acc");
6354 if (sameRegs (AOP (left), AOP (result)) &&
6355 size >= MSB16 + offr && offr != LSB)
6356 emitcode ("xch", "a,%s",
6357 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6359 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6362 if (size >= MSB16 + offr)
6364 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6366 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6369 emitcode ("rlc", "a");
6370 if (sameRegs (AOP (left), AOP (result)) &&
6371 size >= MSB24 + offr && offr != LSB)
6372 emitcode ("xch", "a,%s",
6373 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6375 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6378 if (size >= MSB24 + offr)
6380 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6382 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6385 emitcode ("rlc", "a");
6386 if (sameRegs (AOP (left), AOP (result)) &&
6387 size >= MSB32 + offr && offr != LSB)
6388 emitcode ("xch", "a,%s",
6389 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6391 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6394 if (size > MSB32 + offr)
6396 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6398 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6401 emitcode ("rlc", "a");
6402 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6405 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6408 /*-----------------------------------------------------------------*/
6409 /* genlshFour - shift four byte by a known amount != 0 */
6410 /*-----------------------------------------------------------------*/
6412 genlshFour (operand * result, operand * left, int shCount)
6416 D(emitcode ("; genlshFour",""));
6418 size = AOP_SIZE (result);
6420 /* if shifting more that 3 bytes */
6425 /* lowest order of left goes to the highest
6426 order of the destination */
6427 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6429 movLeft2Result (left, LSB, result, MSB32, 0);
6430 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6431 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6432 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6436 /* more than two bytes */
6437 else if (shCount >= 16)
6439 /* lower order two bytes goes to higher order two bytes */
6441 /* if some more remaining */
6443 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6446 movLeft2Result (left, MSB16, result, MSB32, 0);
6447 movLeft2Result (left, LSB, result, MSB24, 0);
6449 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6450 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6454 /* if more than 1 byte */
6455 else if (shCount >= 8)
6457 /* lower order three bytes goes to higher order three bytes */
6462 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6464 movLeft2Result (left, LSB, result, MSB16, 0);
6470 movLeft2Result (left, MSB24, result, MSB32, 0);
6471 movLeft2Result (left, MSB16, result, MSB24, 0);
6472 movLeft2Result (left, LSB, result, MSB16, 0);
6473 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6475 else if (shCount == 1)
6476 shiftLLong (left, result, MSB16);
6479 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6480 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6481 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6482 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6487 /* 1 <= shCount <= 7 */
6488 else if (shCount <= 2)
6490 shiftLLong (left, result, LSB);
6492 shiftLLong (result, result, LSB);
6494 /* 3 <= shCount <= 7, optimize */
6497 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6498 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6499 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6503 /*-----------------------------------------------------------------*/
6504 /* genLeftShiftLiteral - left shifting by known count */
6505 /*-----------------------------------------------------------------*/
6507 genLeftShiftLiteral (operand * left,
6512 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6515 D(emitcode ("; genLeftShiftLiteral",""));
6517 freeAsmop (right, NULL, ic, TRUE);
6519 aopOp (left, ic, FALSE);
6520 aopOp (result, ic, FALSE);
6522 size = getSize (operandType (result));
6525 emitcode ("; shift left ", "result %d, left %d", size,
6529 /* I suppose that the left size >= result size */
6534 movLeft2Result (left, size, result, size, 0);
6538 else if (shCount >= (size * 8))
6540 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6546 genlshOne (result, left, shCount);
6550 genlshTwo (result, left, shCount);
6554 genlshFour (result, left, shCount);
6557 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6558 "*** ack! mystery literal shift!\n");
6562 freeAsmop (left, NULL, ic, TRUE);
6563 freeAsmop (result, NULL, ic, TRUE);
6566 /*-----------------------------------------------------------------*/
6567 /* genLeftShift - generates code for left shifting */
6568 /*-----------------------------------------------------------------*/
6570 genLeftShift (iCode * ic)
6572 operand *left, *right, *result;
6575 symbol *tlbl, *tlbl1;
6577 D(emitcode ("; genLeftShift",""));
6579 right = IC_RIGHT (ic);
6580 left = IC_LEFT (ic);
6581 result = IC_RESULT (ic);
6583 aopOp (right, ic, FALSE);
6585 /* if the shift count is known then do it
6586 as efficiently as possible */
6587 if (AOP_TYPE (right) == AOP_LIT)
6589 genLeftShiftLiteral (left, right, result, ic);
6593 /* shift count is unknown then we have to form
6594 a loop get the loop count in B : Note: we take
6595 only the lower order byte since shifting
6596 more that 32 bits make no sense anyway, ( the
6597 largest size of an object can be only 32 bits ) */
6599 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6600 emitcode ("inc", "b");
6601 freeAsmop (right, NULL, ic, TRUE);
6602 aopOp (left, ic, FALSE);
6603 aopOp (result, ic, FALSE);
6605 /* now move the left to the result if they are not the
6607 if (!sameRegs (AOP (left), AOP (result)) &&
6608 AOP_SIZE (result) > 1)
6611 size = AOP_SIZE (result);
6615 l = aopGet (AOP (left), offset, FALSE, TRUE);
6616 if (*l == '@' && (IS_AOP_PREG (result)))
6619 emitcode ("mov", "a,%s", l);
6620 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6623 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6628 tlbl = newiTempLabel (NULL);
6629 size = AOP_SIZE (result);
6631 tlbl1 = newiTempLabel (NULL);
6633 /* if it is only one byte then */
6636 symbol *tlbl1 = newiTempLabel (NULL);
6638 l = aopGet (AOP (left), 0, FALSE, FALSE);
6640 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6641 emitcode ("", "%05d$:", tlbl->key + 100);
6642 emitcode ("add", "a,acc");
6643 emitcode ("", "%05d$:", tlbl1->key + 100);
6644 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6645 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6649 reAdjustPreg (AOP (result));
6651 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6652 emitcode ("", "%05d$:", tlbl->key + 100);
6653 l = aopGet (AOP (result), offset, FALSE, FALSE);
6655 emitcode ("add", "a,acc");
6656 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6659 l = aopGet (AOP (result), offset, FALSE, FALSE);
6661 emitcode ("rlc", "a");
6662 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6664 reAdjustPreg (AOP (result));
6666 emitcode ("", "%05d$:", tlbl1->key + 100);
6667 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6669 freeAsmop (left, NULL, ic, TRUE);
6670 freeAsmop (result, NULL, ic, TRUE);
6673 /*-----------------------------------------------------------------*/
6674 /* genrshOne - right shift a one byte quantity by known count */
6675 /*-----------------------------------------------------------------*/
6677 genrshOne (operand * result, operand * left,
6678 int shCount, int sign)
6680 D(emitcode ("; genrshOne",""));
6682 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6685 /*-----------------------------------------------------------------*/
6686 /* genrshTwo - right shift two bytes by known amount != 0 */
6687 /*-----------------------------------------------------------------*/
6689 genrshTwo (operand * result, operand * left,
6690 int shCount, int sign)
6692 D(emitcode ("; genrshTwo",""));
6694 /* if shCount >= 8 */
6699 shiftR1Left2Result (left, MSB16, result, LSB,
6702 movLeft2Result (left, MSB16, result, LSB, sign);
6703 addSign (result, MSB16, sign);
6706 /* 1 <= shCount <= 7 */
6708 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6711 /*-----------------------------------------------------------------*/
6712 /* shiftRLong - shift right one long from left to result */
6713 /* offl = LSB or MSB16 */
6714 /*-----------------------------------------------------------------*/
6716 shiftRLong (operand * left, int offl,
6717 operand * result, int sign)
6719 int isSameRegs=sameRegs(AOP(left),AOP(result));
6721 if (isSameRegs && offl>1) {
6722 // we are in big trouble, but this shouldn't happen
6723 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6726 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6731 emitcode ("rlc", "a");
6732 emitcode ("subb", "a,acc");
6734 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6736 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6737 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6740 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6745 emitcode ("clr", "c");
6747 emitcode ("mov", "c,acc.7");
6750 emitcode ("rrc", "a");
6752 if (isSameRegs && offl==MSB16) {
6753 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6755 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6756 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6759 emitcode ("rrc", "a");
6760 if (isSameRegs && offl==1) {
6761 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6763 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6764 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6766 emitcode ("rrc", "a");
6767 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6771 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6772 emitcode ("rrc", "a");
6773 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6777 /*-----------------------------------------------------------------*/
6778 /* genrshFour - shift four byte by a known amount != 0 */
6779 /*-----------------------------------------------------------------*/
6781 genrshFour (operand * result, operand * left,
6782 int shCount, int sign)
6784 D(emitcode ("; genrshFour",""));
6786 /* if shifting more that 3 bytes */
6791 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6793 movLeft2Result (left, MSB32, result, LSB, sign);
6794 addSign (result, MSB16, sign);
6796 else if (shCount >= 16)
6800 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6803 movLeft2Result (left, MSB24, result, LSB, 0);
6804 movLeft2Result (left, MSB32, result, MSB16, sign);
6806 addSign (result, MSB24, sign);
6808 else if (shCount >= 8)
6812 shiftRLong (left, MSB16, result, sign);
6813 else if (shCount == 0)
6815 movLeft2Result (left, MSB16, result, LSB, 0);
6816 movLeft2Result (left, MSB24, result, MSB16, 0);
6817 movLeft2Result (left, MSB32, result, MSB24, sign);
6818 addSign (result, MSB32, sign);
6822 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6823 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6824 /* the last shift is signed */
6825 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6826 addSign (result, MSB32, sign);
6830 { /* 1 <= shCount <= 7 */
6833 shiftRLong (left, LSB, result, sign);
6835 shiftRLong (result, LSB, result, sign);
6839 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6840 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6841 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6846 /*-----------------------------------------------------------------*/
6847 /* genRightShiftLiteral - right shifting by known count */
6848 /*-----------------------------------------------------------------*/
6850 genRightShiftLiteral (operand * left,
6856 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6859 D(emitcode ("; genRightShiftLiteral",""));
6861 freeAsmop (right, NULL, ic, TRUE);
6863 aopOp (left, ic, FALSE);
6864 aopOp (result, ic, FALSE);
6867 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6871 size = getDataSize (left);
6872 /* test the LEFT size !!! */
6874 /* I suppose that the left size >= result size */
6877 size = getDataSize (result);
6879 movLeft2Result (left, size, result, size, 0);
6882 else if (shCount >= (size * 8))
6885 /* get sign in acc.7 */
6886 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6888 addSign (result, LSB, sign);
6895 genrshOne (result, left, shCount, sign);
6899 genrshTwo (result, left, shCount, sign);
6903 genrshFour (result, left, shCount, sign);
6909 freeAsmop (left, NULL, ic, TRUE);
6910 freeAsmop (result, NULL, ic, TRUE);
6913 /*-----------------------------------------------------------------*/
6914 /* genSignedRightShift - right shift of signed number */
6915 /*-----------------------------------------------------------------*/
6917 genSignedRightShift (iCode * ic)
6919 operand *right, *left, *result;
6922 symbol *tlbl, *tlbl1;
6924 D(emitcode ("; genSignedRightShift",""));
6926 /* we do it the hard way put the shift count in b
6927 and loop thru preserving the sign */
6929 right = IC_RIGHT (ic);
6930 left = IC_LEFT (ic);
6931 result = IC_RESULT (ic);
6933 aopOp (right, ic, FALSE);
6936 if (AOP_TYPE (right) == AOP_LIT)
6938 genRightShiftLiteral (left, right, result, ic, 1);
6941 /* shift count is unknown then we have to form
6942 a loop get the loop count in B : Note: we take
6943 only the lower order byte since shifting
6944 more that 32 bits make no sense anyway, ( the
6945 largest size of an object can be only 32 bits ) */
6947 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6948 emitcode ("inc", "b");
6949 freeAsmop (right, NULL, ic, TRUE);
6950 aopOp (left, ic, FALSE);
6951 aopOp (result, ic, FALSE);
6953 /* now move the left to the result if they are not the
6955 if (!sameRegs (AOP (left), AOP (result)) &&
6956 AOP_SIZE (result) > 1)
6959 size = AOP_SIZE (result);
6963 l = aopGet (AOP (left), offset, FALSE, TRUE);
6964 if (*l == '@' && IS_AOP_PREG (result))
6967 emitcode ("mov", "a,%s", l);
6968 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6971 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6976 /* mov the highest order bit to OVR */
6977 tlbl = newiTempLabel (NULL);
6978 tlbl1 = newiTempLabel (NULL);
6980 size = AOP_SIZE (result);
6982 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6983 emitcode ("rlc", "a");
6984 emitcode ("mov", "ov,c");
6985 /* if it is only one byte then */
6988 l = aopGet (AOP (left), 0, FALSE, FALSE);
6990 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6991 emitcode ("", "%05d$:", tlbl->key + 100);
6992 emitcode ("mov", "c,ov");
6993 emitcode ("rrc", "a");
6994 emitcode ("", "%05d$:", tlbl1->key + 100);
6995 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6996 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7000 reAdjustPreg (AOP (result));
7001 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7002 emitcode ("", "%05d$:", tlbl->key + 100);
7003 emitcode ("mov", "c,ov");
7006 l = aopGet (AOP (result), offset, FALSE, FALSE);
7008 emitcode ("rrc", "a");
7009 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7011 reAdjustPreg (AOP (result));
7012 emitcode ("", "%05d$:", tlbl1->key + 100);
7013 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7016 freeAsmop (left, NULL, ic, TRUE);
7017 freeAsmop (result, NULL, ic, TRUE);
7020 /*-----------------------------------------------------------------*/
7021 /* genRightShift - generate code for right shifting */
7022 /*-----------------------------------------------------------------*/
7024 genRightShift (iCode * ic)
7026 operand *right, *left, *result;
7030 symbol *tlbl, *tlbl1;
7032 D(emitcode ("; genRightShift",""));
7034 /* if signed then we do it the hard way preserve the
7035 sign bit moving it inwards */
7036 retype = getSpec (operandType (IC_RESULT (ic)));
7038 if (!SPEC_USIGN (retype))
7040 genSignedRightShift (ic);
7044 /* signed & unsigned types are treated the same : i.e. the
7045 signed is NOT propagated inwards : quoting from the
7046 ANSI - standard : "for E1 >> E2, is equivalent to division
7047 by 2**E2 if unsigned or if it has a non-negative value,
7048 otherwise the result is implementation defined ", MY definition
7049 is that the sign does not get propagated */
7051 right = IC_RIGHT (ic);
7052 left = IC_LEFT (ic);
7053 result = IC_RESULT (ic);
7055 aopOp (right, ic, FALSE);
7057 /* if the shift count is known then do it
7058 as efficiently as possible */
7059 if (AOP_TYPE (right) == AOP_LIT)
7061 genRightShiftLiteral (left, right, result, ic, 0);
7065 /* shift count is unknown then we have to form
7066 a loop get the loop count in B : Note: we take
7067 only the lower order byte since shifting
7068 more that 32 bits make no sense anyway, ( the
7069 largest size of an object can be only 32 bits ) */
7071 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7072 emitcode ("inc", "b");
7073 freeAsmop (right, NULL, ic, TRUE);
7074 aopOp (left, ic, FALSE);
7075 aopOp (result, ic, FALSE);
7077 /* now move the left to the result if they are not the
7079 if (!sameRegs (AOP (left), AOP (result)) &&
7080 AOP_SIZE (result) > 1)
7083 size = AOP_SIZE (result);
7087 l = aopGet (AOP (left), offset, FALSE, TRUE);
7088 if (*l == '@' && IS_AOP_PREG (result))
7091 emitcode ("mov", "a,%s", l);
7092 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7095 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7100 tlbl = newiTempLabel (NULL);
7101 tlbl1 = newiTempLabel (NULL);
7102 size = AOP_SIZE (result);
7105 /* if it is only one byte then */
7108 l = aopGet (AOP (left), 0, FALSE, FALSE);
7110 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7111 emitcode ("", "%05d$:", tlbl->key + 100);
7113 emitcode ("rrc", "a");
7114 emitcode ("", "%05d$:", tlbl1->key + 100);
7115 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7116 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7120 reAdjustPreg (AOP (result));
7121 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7122 emitcode ("", "%05d$:", tlbl->key + 100);
7126 l = aopGet (AOP (result), offset, FALSE, FALSE);
7128 emitcode ("rrc", "a");
7129 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7131 reAdjustPreg (AOP (result));
7133 emitcode ("", "%05d$:", tlbl1->key + 100);
7134 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7137 freeAsmop (left, NULL, ic, TRUE);
7138 freeAsmop (result, NULL, ic, TRUE);
7141 /*-----------------------------------------------------------------*/
7142 /* emitPtrByteGet - emits code to get a byte into A through a */
7143 /* pointer register (R0, R1, or DPTR). The */
7144 /* original value of A can be preserved in B. */
7145 /*-----------------------------------------------------------------*/
7147 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7154 emitcode ("mov", "b,a");
7155 emitcode ("mov", "a,@%s", rname);
7160 emitcode ("mov", "b,a");
7161 emitcode ("movx", "a,@%s", rname);
7166 emitcode ("mov", "b,a");
7167 emitcode ("movx", "a,@dptr");
7172 emitcode ("mov", "b,a");
7173 emitcode ("clr", "a");
7174 emitcode ("movc", "a,@a+dptr");
7180 emitcode ("push", "b");
7181 emitcode ("push", "acc");
7183 emitcode ("lcall", "__gptrget");
7185 emitcode ("pop", "b");
7190 /*-----------------------------------------------------------------*/
7191 /* emitPtrByteSet - emits code to set a byte from src through a */
7192 /* pointer register (R0, R1, or DPTR). */
7193 /*-----------------------------------------------------------------*/
7195 emitPtrByteSet (char *rname, int p_type, char *src)
7204 emitcode ("mov", "@%s,a", rname);
7207 emitcode ("mov", "@%s,%s", rname, src);
7212 emitcode ("movx", "@%s,a", rname);
7217 emitcode ("movx", "@dptr,a");
7222 emitcode ("lcall", "__gptrput");
7227 /*-----------------------------------------------------------------*/
7228 /* genUnpackBits - generates code for unpacking bits */
7229 /*-----------------------------------------------------------------*/
7231 genUnpackBits (operand * result, char *rname, int ptype)
7233 int offset = 0; /* result byte offset */
7234 int rsize; /* result size */
7235 int rlen = 0; /* remaining bitfield length */
7236 sym_link *etype; /* bitfield type information */
7237 int blen; /* bitfield length */
7238 int bstr; /* bitfield starting bit within byte */
7240 D(emitcode ("; genUnpackBits",""));
7242 etype = getSpec (operandType (result));
7243 rsize = getSize (operandType (result));
7244 blen = SPEC_BLEN (etype);
7245 bstr = SPEC_BSTR (etype);
7247 /* If the bitfield length is less than a byte */
7250 emitPtrByteGet (rname, ptype, FALSE);
7252 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7253 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7257 /* Bit field did not fit in a byte. Copy all
7258 but the partial byte at the end. */
7259 for (rlen=blen;rlen>=8;rlen-=8)
7261 emitPtrByteGet (rname, ptype, FALSE);
7262 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7264 emitcode ("inc", "%s", rname);
7267 /* Handle the partial byte at the end */
7270 emitPtrByteGet (rname, ptype, FALSE);
7271 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7272 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7280 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7285 /*-----------------------------------------------------------------*/
7286 /* genDataPointerGet - generates code when ptr offset is known */
7287 /*-----------------------------------------------------------------*/
7289 genDataPointerGet (operand * left,
7295 int size, offset = 0;
7297 D(emitcode ("; genDataPointerGet",""));
7299 aopOp (result, ic, TRUE);
7301 /* get the string representation of the name */
7302 l = aopGet (AOP (left), 0, FALSE, TRUE);
7303 size = AOP_SIZE (result);
7307 sprintf (buffer, "(%s + %d)", l + 1, offset);
7309 sprintf (buffer, "%s", l + 1);
7310 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7313 freeAsmop (left, NULL, ic, TRUE);
7314 freeAsmop (result, NULL, ic, TRUE);
7317 /*-----------------------------------------------------------------*/
7318 /* genNearPointerGet - emitcode for near pointer fetch */
7319 /*-----------------------------------------------------------------*/
7321 genNearPointerGet (operand * left,
7329 sym_link *rtype, *retype;
7330 sym_link *ltype = operandType (left);
7333 D(emitcode ("; genNearPointerGet",""));
7335 rtype = operandType (result);
7336 retype = getSpec (rtype);
7338 aopOp (left, ic, FALSE);
7340 /* if left is rematerialisable and
7341 result is not bit variable type and
7342 the left is pointer to data space i.e
7343 lower 128 bytes of space */
7344 if (AOP_TYPE (left) == AOP_IMMD &&
7345 !IS_BITVAR (retype) &&
7346 DCL_TYPE (ltype) == POINTER)
7348 genDataPointerGet (left, result, ic);
7352 /* if the value is already in a pointer register
7353 then don't need anything more */
7354 if (!AOP_INPREG (AOP (left)))
7356 if (IS_AOP_PREG (left))
7358 // Aha, it is a pointer, just in disguise.
7359 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7362 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7363 __FILE__, __LINE__);
7368 emitcode ("mov", "a%s,%s", rname + 1, rname);
7369 rname++; // skip the '@'.
7374 /* otherwise get a free pointer register */
7376 preg = getFreePtr (ic, &aop, FALSE);
7377 emitcode ("mov", "%s,%s",
7379 aopGet (AOP (left), 0, FALSE, TRUE));
7384 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7386 //aopOp (result, ic, FALSE);
7387 aopOp (result, ic, result?TRUE:FALSE);
7389 /* if bitfield then unpack the bits */
7390 if (IS_BITVAR (retype))
7391 genUnpackBits (result, rname, POINTER);
7394 /* we have can just get the values */
7395 int size = AOP_SIZE (result);
7400 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7403 emitcode ("mov", "a,@%s", rname);
7404 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7408 sprintf (buffer, "@%s", rname);
7409 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7413 emitcode ("inc", "%s", rname);
7417 /* now some housekeeping stuff */
7418 if (aop) /* we had to allocate for this iCode */
7420 if (pi) { /* post increment present */
7421 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7423 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7427 /* we did not allocate which means left
7428 already in a pointer register, then
7429 if size > 0 && this could be used again
7430 we have to point it back to where it
7432 if ((AOP_SIZE (result) > 1 &&
7433 !OP_SYMBOL (left)->remat &&
7434 (OP_SYMBOL (left)->liveTo > ic->seq ||
7438 int size = AOP_SIZE (result) - 1;
7440 emitcode ("dec", "%s", rname);
7445 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7446 freeAsmop (left, NULL, ic, TRUE);
7447 if (pi) pi->generated = 1;
7450 /*-----------------------------------------------------------------*/
7451 /* genPagedPointerGet - emitcode for paged pointer fetch */
7452 /*-----------------------------------------------------------------*/
7454 genPagedPointerGet (operand * left,
7462 sym_link *rtype, *retype;
7464 D(emitcode ("; genPagedPointerGet",""));
7466 rtype = operandType (result);
7467 retype = getSpec (rtype);
7469 aopOp (left, ic, FALSE);
7471 /* if the value is already in a pointer register
7472 then don't need anything more */
7473 if (!AOP_INPREG (AOP (left)))
7475 /* otherwise get a free pointer register */
7477 preg = getFreePtr (ic, &aop, FALSE);
7478 emitcode ("mov", "%s,%s",
7480 aopGet (AOP (left), 0, FALSE, TRUE));
7484 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7486 aopOp (result, ic, FALSE);
7488 /* if bitfield then unpack the bits */
7489 if (IS_BITVAR (retype))
7490 genUnpackBits (result, rname, PPOINTER);
7493 /* we have can just get the values */
7494 int size = AOP_SIZE (result);
7500 emitcode ("movx", "a,@%s", rname);
7501 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7506 emitcode ("inc", "%s", rname);
7510 /* now some housekeeping stuff */
7511 if (aop) /* we had to allocate for this iCode */
7513 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7514 freeAsmop (NULL, aop, ic, TRUE);
7518 /* we did not allocate which means left
7519 already in a pointer register, then
7520 if size > 0 && this could be used again
7521 we have to point it back to where it
7523 if ((AOP_SIZE (result) > 1 &&
7524 !OP_SYMBOL (left)->remat &&
7525 (OP_SYMBOL (left)->liveTo > ic->seq ||
7529 int size = AOP_SIZE (result) - 1;
7531 emitcode ("dec", "%s", rname);
7536 freeAsmop (left, NULL, ic, TRUE);
7537 freeAsmop (result, NULL, ic, TRUE);
7538 if (pi) pi->generated = 1;
7542 /*-----------------------------------------------------------------*/
7543 /* genFarPointerGet - gget value from far space */
7544 /*-----------------------------------------------------------------*/
7546 genFarPointerGet (operand * left,
7547 operand * result, iCode * ic, iCode * pi)
7550 sym_link *retype = getSpec (operandType (result));
7552 D(emitcode ("; genFarPointerGet",""));
7554 aopOp (left, ic, FALSE);
7556 /* if the operand is already in dptr
7557 then we do nothing else we move the value to dptr */
7558 if (AOP_TYPE (left) != AOP_STR)
7560 /* if this is remateriazable */
7561 if (AOP_TYPE (left) == AOP_IMMD)
7562 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7564 { /* we need to get it byte by byte */
7565 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7566 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7569 /* so dptr know contains the address */
7570 aopOp (result, ic, FALSE);
7572 /* if bit then unpack */
7573 if (IS_BITVAR (retype))
7574 genUnpackBits (result, "dptr", FPOINTER);
7577 size = AOP_SIZE (result);
7582 emitcode ("movx", "a,@dptr");
7583 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7585 emitcode ("inc", "dptr");
7589 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7590 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7591 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7594 freeAsmop (left, NULL, ic, TRUE);
7595 freeAsmop (result, NULL, ic, TRUE);
7598 /*-----------------------------------------------------------------*/
7599 /* genCodePointerGet - gget value from code space */
7600 /*-----------------------------------------------------------------*/
7602 genCodePointerGet (operand * left,
7603 operand * result, iCode * ic, iCode *pi)
7606 sym_link *retype = getSpec (operandType (result));
7608 D(emitcode ("; genCodePointerGet",""));
7610 aopOp (left, ic, FALSE);
7612 /* if the operand is already in dptr
7613 then we do nothing else we move the value to dptr */
7614 if (AOP_TYPE (left) != AOP_STR)
7616 /* if this is remateriazable */
7617 if (AOP_TYPE (left) == AOP_IMMD)
7618 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7620 { /* we need to get it byte by byte */
7621 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7622 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7625 /* so dptr know contains the address */
7626 aopOp (result, ic, FALSE);
7628 /* if bit then unpack */
7629 if (IS_BITVAR (retype))
7630 genUnpackBits (result, "dptr", CPOINTER);
7633 size = AOP_SIZE (result);
7640 emitcode ("clr", "a");
7641 emitcode ("movc", "a,@a+dptr");
7642 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7643 emitcode ("inc", "dptr");
7647 emitcode ("mov", "a,#0x%02x", offset);
7648 emitcode ("movc", "a,@a+dptr");
7649 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7654 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7655 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7656 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7659 freeAsmop (left, NULL, ic, TRUE);
7660 freeAsmop (result, NULL, ic, TRUE);
7663 /*-----------------------------------------------------------------*/
7664 /* genGenPointerGet - gget value from generic pointer space */
7665 /*-----------------------------------------------------------------*/
7667 genGenPointerGet (operand * left,
7668 operand * result, iCode * ic, iCode *pi)
7671 sym_link *retype = getSpec (operandType (result));
7673 D(emitcode ("; genGenPointerGet",""));
7675 aopOp (left, ic, FALSE);
7677 /* if the operand is already in dptr
7678 then we do nothing else we move the value to dptr */
7679 if (AOP_TYPE (left) != AOP_STR)
7681 /* if this is remateriazable */
7682 if (AOP_TYPE (left) == AOP_IMMD)
7684 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7685 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7686 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7688 emitcode ("mov", "b,#%d", pointerCode (retype));
7691 { /* we need to get it byte by byte */
7692 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7693 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7694 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7697 /* so dptr know contains the address */
7698 aopOp (result, ic, FALSE);
7700 /* if bit then unpack */
7701 if (IS_BITVAR (retype))
7702 genUnpackBits (result, "dptr", GPOINTER);
7705 size = AOP_SIZE (result);
7710 emitcode ("lcall", "__gptrget");
7711 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7713 emitcode ("inc", "dptr");
7717 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7718 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7719 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7722 freeAsmop (left, NULL, ic, TRUE);
7723 freeAsmop (result, NULL, ic, TRUE);
7726 /*-----------------------------------------------------------------*/
7727 /* genPointerGet - generate code for pointer get */
7728 /*-----------------------------------------------------------------*/
7730 genPointerGet (iCode * ic, iCode *pi)
7732 operand *left, *result;
7733 sym_link *type, *etype;
7736 D(emitcode ("; genPointerGet",""));
7738 left = IC_LEFT (ic);
7739 result = IC_RESULT (ic);
7741 /* depending on the type of pointer we need to
7742 move it to the correct pointer register */
7743 type = operandType (left);
7744 etype = getSpec (type);
7745 /* if left is of type of pointer then it is simple */
7746 if (IS_PTR (type) && !IS_FUNC (type->next))
7747 p_type = DCL_TYPE (type);
7750 /* we have to go by the storage class */
7751 p_type = PTR_TYPE (SPEC_OCLS (etype));
7754 /* special case when cast remat */
7755 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7756 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7757 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7758 type = operandType (left);
7759 p_type = DCL_TYPE (type);
7761 /* now that we have the pointer type we assign
7762 the pointer values */
7768 genNearPointerGet (left, result, ic, pi);
7772 genPagedPointerGet (left, result, ic, pi);
7776 genFarPointerGet (left, result, ic, pi);
7780 genCodePointerGet (left, result, ic, pi);
7784 genGenPointerGet (left, result, ic, pi);
7792 /*-----------------------------------------------------------------*/
7793 /* genPackBits - generates code for packed bit storage */
7794 /*-----------------------------------------------------------------*/
7796 genPackBits (sym_link * etype,
7798 char *rname, int p_type)
7800 int offset = 0; /* source byte offset */
7801 int rlen = 0; /* remaining bitfield length */
7802 int blen; /* bitfield length */
7803 int bstr; /* bitfield starting bit within byte */
7804 int litval; /* source literal value (if AOP_LIT) */
7805 unsigned char mask; /* bitmask within current byte */
7807 D(emitcode ("; genPackBits",""));
7809 blen = SPEC_BLEN (etype);
7810 bstr = SPEC_BSTR (etype);
7812 /* If the bitfield length is less than a byte */
7815 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7816 (unsigned char) (0xFF >> (8 - bstr)));
7818 if (AOP_TYPE (right) == AOP_LIT)
7820 /* Case with a bitfield length <8 and literal source
7822 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
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 if ((blen==1) && (p_type!=GPOINTER))
7835 /* Case with a bitfield length == 1 and no generic pointer
7837 if (AOP_TYPE (right) == AOP_CRY)
7838 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7841 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7842 emitcode ("rrc","a");
7844 emitPtrByteGet (rname, p_type, FALSE);
7845 emitcode ("mov","acc.%d,c",bstr);
7849 /* Case with a bitfield length < 8 and arbitrary source
7851 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7852 /* shift and mask source value */
7854 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7856 /* transfer A to B and get next byte */
7857 emitPtrByteGet (rname, p_type, TRUE);
7859 emitcode ("anl", "a,#0x%02x", mask);
7860 emitcode ("orl", "a,b");
7861 if (p_type == GPOINTER)
7862 emitcode ("pop", "b");
7866 emitPtrByteSet (rname, p_type, "a");
7870 /* Bit length is greater than 7 bits. In this case, copy */
7871 /* all except the partial byte at the end */
7872 for (rlen=blen;rlen>=8;rlen-=8)
7874 emitPtrByteSet (rname, p_type,
7875 aopGet (AOP (right), offset++, FALSE, TRUE) );
7877 emitcode ("inc", "%s", rname);
7880 /* If there was a partial byte at the end */
7883 mask = (((unsigned char) -1 << rlen) & 0xff);
7885 if (AOP_TYPE (right) == AOP_LIT)
7887 /* Case with partial byte and literal source
7889 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7890 litval >>= (blen-rlen);
7891 litval &= (~mask) & 0xff;
7892 emitPtrByteGet (rname, p_type, FALSE);
7893 if ((mask|litval)!=0xff)
7894 emitcode ("anl","a,#0x%02x", mask);
7896 emitcode ("orl","a,#0x%02x", litval);
7900 /* Case with partial byte and arbitrary source
7902 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7903 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7905 /* transfer A to B and get next byte */
7906 emitPtrByteGet (rname, p_type, TRUE);
7908 emitcode ("anl", "a,#0x%02x", mask);
7909 emitcode ("orl", "a,b");
7910 if (p_type == GPOINTER)
7911 emitcode ("pop", "b");
7913 emitPtrByteSet (rname, p_type, "a");
7919 /*-----------------------------------------------------------------*/
7920 /* genDataPointerSet - remat pointer to data space */
7921 /*-----------------------------------------------------------------*/
7923 genDataPointerSet (operand * right,
7927 int size, offset = 0;
7928 char *l, buffer[256];
7930 D(emitcode ("; genDataPointerSet",""));
7932 aopOp (right, ic, FALSE);
7934 l = aopGet (AOP (result), 0, FALSE, TRUE);
7935 size = AOP_SIZE (right);
7939 sprintf (buffer, "(%s + %d)", l + 1, offset);
7941 sprintf (buffer, "%s", l + 1);
7942 emitcode ("mov", "%s,%s", buffer,
7943 aopGet (AOP (right), offset++, FALSE, FALSE));
7946 freeAsmop (right, NULL, ic, TRUE);
7947 freeAsmop (result, NULL, ic, TRUE);
7950 /*-----------------------------------------------------------------*/
7951 /* genNearPointerSet - emitcode for near pointer put */
7952 /*-----------------------------------------------------------------*/
7954 genNearPointerSet (operand * right,
7962 sym_link *retype, *letype;
7963 sym_link *ptype = operandType (result);
7965 D(emitcode ("; genNearPointerSet",""));
7967 retype = getSpec (operandType (right));
7968 letype = getSpec (ptype);
7969 aopOp (result, ic, FALSE);
7971 /* if the result is rematerializable &
7972 in data space & not a bit variable */
7973 if (AOP_TYPE (result) == AOP_IMMD &&
7974 DCL_TYPE (ptype) == POINTER &&
7975 !IS_BITVAR (retype) &&
7976 !IS_BITVAR (letype))
7978 genDataPointerSet (right, result, ic);
7982 /* if the value is already in a pointer register
7983 then don't need anything more */
7984 if (!AOP_INPREG (AOP (result)))
7987 //AOP_TYPE (result) == AOP_STK
7991 // Aha, it is a pointer, just in disguise.
7992 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7995 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7996 __FILE__, __LINE__);
8001 emitcode ("mov", "a%s,%s", rname + 1, rname);
8002 rname++; // skip the '@'.
8007 /* otherwise get a free pointer register */
8009 preg = getFreePtr (ic, &aop, FALSE);
8010 emitcode ("mov", "%s,%s",
8012 aopGet (AOP (result), 0, FALSE, TRUE));
8018 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8021 aopOp (right, ic, FALSE);
8023 /* if bitfield then unpack the bits */
8024 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8025 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8028 /* we have can just get the values */
8029 int size = AOP_SIZE (right);
8034 l = aopGet (AOP (right), offset, FALSE, TRUE);
8038 emitcode ("mov", "@%s,a", rname);
8041 emitcode ("mov", "@%s,%s", rname, l);
8043 emitcode ("inc", "%s", rname);
8048 /* now some housekeeping stuff */
8049 if (aop) /* we had to allocate for this iCode */
8052 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8053 freeAsmop (NULL, aop, ic, TRUE);
8057 /* we did not allocate which means left
8058 already in a pointer register, then
8059 if size > 0 && this could be used again
8060 we have to point it back to where it
8062 if ((AOP_SIZE (right) > 1 &&
8063 !OP_SYMBOL (result)->remat &&
8064 (OP_SYMBOL (result)->liveTo > ic->seq ||
8068 int size = AOP_SIZE (right) - 1;
8070 emitcode ("dec", "%s", rname);
8075 if (pi) pi->generated = 1;
8076 freeAsmop (result, NULL, ic, TRUE);
8077 freeAsmop (right, NULL, ic, TRUE);
8080 /*-----------------------------------------------------------------*/
8081 /* genPagedPointerSet - emitcode for Paged pointer put */
8082 /*-----------------------------------------------------------------*/
8084 genPagedPointerSet (operand * right,
8092 sym_link *retype, *letype;
8094 D(emitcode ("; genPagedPointerSet",""));
8096 retype = getSpec (operandType (right));
8097 letype = getSpec (operandType (result));
8099 aopOp (result, ic, FALSE);
8101 /* if the value is already in a pointer register
8102 then don't need anything more */
8103 if (!AOP_INPREG (AOP (result)))
8105 /* otherwise get a free pointer register */
8107 preg = getFreePtr (ic, &aop, FALSE);
8108 emitcode ("mov", "%s,%s",
8110 aopGet (AOP (result), 0, FALSE, TRUE));
8114 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8116 aopOp (right, ic, FALSE);
8118 /* if bitfield then unpack the bits */
8119 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8120 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8123 /* we have can just get the values */
8124 int size = AOP_SIZE (right);
8129 l = aopGet (AOP (right), offset, FALSE, TRUE);
8132 emitcode ("movx", "@%s,a", rname);
8135 emitcode ("inc", "%s", rname);
8141 /* now some housekeeping stuff */
8142 if (aop) /* we had to allocate for this iCode */
8145 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8146 freeAsmop (NULL, aop, ic, TRUE);
8150 /* we did not allocate which means left
8151 already in a pointer register, then
8152 if size > 0 && this could be used again
8153 we have to point it back to where it
8155 if (AOP_SIZE (right) > 1 &&
8156 !OP_SYMBOL (result)->remat &&
8157 (OP_SYMBOL (result)->liveTo > ic->seq ||
8160 int size = AOP_SIZE (right) - 1;
8162 emitcode ("dec", "%s", rname);
8167 if (pi) pi->generated = 1;
8168 freeAsmop (result, NULL, ic, TRUE);
8169 freeAsmop (right, NULL, ic, TRUE);
8174 /*-----------------------------------------------------------------*/
8175 /* genFarPointerSet - set value from far space */
8176 /*-----------------------------------------------------------------*/
8178 genFarPointerSet (operand * right,
8179 operand * result, iCode * ic, iCode * pi)
8182 sym_link *retype = getSpec (operandType (right));
8183 sym_link *letype = getSpec (operandType (result));
8185 D(emitcode ("; genFarPointerSet",""));
8187 aopOp (result, ic, FALSE);
8189 /* if the operand is already in dptr
8190 then we do nothing else we move the value to dptr */
8191 if (AOP_TYPE (result) != AOP_STR)
8193 /* if this is remateriazable */
8194 if (AOP_TYPE (result) == AOP_IMMD)
8195 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8197 { /* we need to get it byte by byte */
8198 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8199 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8202 /* so dptr know contains the address */
8203 aopOp (right, ic, FALSE);
8205 /* if bit then unpack */
8206 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8207 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8210 size = AOP_SIZE (right);
8215 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8217 emitcode ("movx", "@dptr,a");
8219 emitcode ("inc", "dptr");
8222 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8223 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8224 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8227 freeAsmop (result, NULL, ic, TRUE);
8228 freeAsmop (right, NULL, ic, TRUE);
8231 /*-----------------------------------------------------------------*/
8232 /* genGenPointerSet - set value from generic pointer space */
8233 /*-----------------------------------------------------------------*/
8235 genGenPointerSet (operand * right,
8236 operand * result, iCode * ic, iCode * pi)
8239 sym_link *retype = getSpec (operandType (right));
8240 sym_link *letype = getSpec (operandType (result));
8242 D(emitcode ("; genGenPointerSet",""));
8244 aopOp (result, ic, FALSE);
8246 /* if the operand is already in dptr
8247 then we do nothing else we move the value to dptr */
8248 if (AOP_TYPE (result) != AOP_STR)
8250 /* if this is remateriazable */
8251 if (AOP_TYPE (result) == AOP_IMMD)
8253 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8254 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8255 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8257 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8260 { /* we need to get it byte by byte */
8261 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8262 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8263 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8266 /* so dptr know contains the address */
8267 aopOp (right, ic, FALSE);
8269 /* if bit then unpack */
8270 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8271 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8274 size = AOP_SIZE (right);
8279 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8281 emitcode ("lcall", "__gptrput");
8283 emitcode ("inc", "dptr");
8287 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8288 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8289 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8292 freeAsmop (result, NULL, ic, TRUE);
8293 freeAsmop (right, NULL, ic, TRUE);
8296 /*-----------------------------------------------------------------*/
8297 /* genPointerSet - stores the value into a pointer location */
8298 /*-----------------------------------------------------------------*/
8300 genPointerSet (iCode * ic, iCode *pi)
8302 operand *right, *result;
8303 sym_link *type, *etype;
8306 D(emitcode ("; genPointerSet",""));
8308 right = IC_RIGHT (ic);
8309 result = IC_RESULT (ic);
8311 /* depending on the type of pointer we need to
8312 move it to the correct pointer register */
8313 type = operandType (result);
8314 etype = getSpec (type);
8315 /* if left is of type of pointer then it is simple */
8316 if (IS_PTR (type) && !IS_FUNC (type->next))
8318 p_type = DCL_TYPE (type);
8322 /* we have to go by the storage class */
8323 p_type = PTR_TYPE (SPEC_OCLS (etype));
8326 /* special case when cast remat */
8327 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8328 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8329 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8330 type = operandType (result);
8331 p_type = DCL_TYPE (type);
8333 /* now that we have the pointer type we assign
8334 the pointer values */
8340 genNearPointerSet (right, result, ic, pi);
8344 genPagedPointerSet (right, result, ic, pi);
8348 genFarPointerSet (right, result, ic, pi);
8352 genGenPointerSet (right, result, ic, pi);
8356 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8357 "genPointerSet: illegal pointer type");
8362 /*-----------------------------------------------------------------*/
8363 /* genIfx - generate code for Ifx statement */
8364 /*-----------------------------------------------------------------*/
8366 genIfx (iCode * ic, iCode * popIc)
8368 operand *cond = IC_COND (ic);
8371 D(emitcode ("; genIfx",""));
8373 aopOp (cond, ic, FALSE);
8375 /* get the value into acc */
8376 if (AOP_TYPE (cond) != AOP_CRY)
8380 /* the result is now in the accumulator */
8381 freeAsmop (cond, NULL, ic, TRUE);
8383 /* if there was something to be popped then do it */
8387 /* if the condition is a bit variable */
8388 if (isbit && IS_ITEMP (cond) &&
8390 genIfxJump (ic, SPIL_LOC (cond)->rname);
8391 else if (isbit && !IS_ITEMP (cond))
8392 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8394 genIfxJump (ic, "a");
8399 /*-----------------------------------------------------------------*/
8400 /* genAddrOf - generates code for address of */
8401 /*-----------------------------------------------------------------*/
8403 genAddrOf (iCode * ic)
8405 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8408 D(emitcode ("; genAddrOf",""));
8410 aopOp (IC_RESULT (ic), ic, FALSE);
8412 /* if the operand is on the stack then we
8413 need to get the stack offset of this
8417 /* if it has an offset then we need to compute
8421 emitcode ("mov", "a,_bp");
8422 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8423 ((char) (sym->stack - _G.nRegsSaved)) :
8424 ((char) sym->stack)) & 0xff);
8425 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8429 /* we can just move _bp */
8430 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8432 /* fill the result with zero */
8433 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8438 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8444 /* object not on stack then we need the name */
8445 size = AOP_SIZE (IC_RESULT (ic));
8450 char s[SDCC_NAME_MAX];
8452 sprintf (s, "#(%s >> %d)",
8456 sprintf (s, "#%s", sym->rname);
8457 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8461 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8465 /*-----------------------------------------------------------------*/
8466 /* genFarFarAssign - assignment when both are in far space */
8467 /*-----------------------------------------------------------------*/
8469 genFarFarAssign (operand * result, operand * right, iCode * ic)
8471 int size = AOP_SIZE (right);
8475 D(emitcode ("; genFarFarAssign",""));
8477 /* first push the right side on to the stack */
8480 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8482 emitcode ("push", "acc");
8485 freeAsmop (right, NULL, ic, FALSE);
8486 /* now assign DPTR to result */
8487 aopOp (result, ic, FALSE);
8488 size = AOP_SIZE (result);
8491 emitcode ("pop", "acc");
8492 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8494 freeAsmop (result, NULL, ic, FALSE);
8498 /*-----------------------------------------------------------------*/
8499 /* genAssign - generate code for assignment */
8500 /*-----------------------------------------------------------------*/
8502 genAssign (iCode * ic)
8504 operand *result, *right;
8506 unsigned long lit = 0L;
8508 D(emitcode("; genAssign",""));
8510 result = IC_RESULT (ic);
8511 right = IC_RIGHT (ic);
8513 /* if they are the same */
8514 if (operandsEqu (result, right) &&
8515 !isOperandVolatile (result, FALSE) &&
8516 !isOperandVolatile (right, FALSE))
8519 aopOp (right, ic, FALSE);
8521 /* special case both in far space */
8522 if (AOP_TYPE (right) == AOP_DPTR &&
8523 IS_TRUE_SYMOP (result) &&
8524 isOperandInFarSpace (result))
8527 genFarFarAssign (result, right, ic);
8531 aopOp (result, ic, TRUE);
8533 /* if they are the same registers */
8534 if (sameRegs (AOP (right), AOP (result)) &&
8535 !isOperandVolatile (result, FALSE) &&
8536 !isOperandVolatile (right, FALSE))
8539 /* if the result is a bit */
8540 if (AOP_TYPE (result) == AOP_CRY)
8543 /* if the right size is a literal then
8544 we know what the value is */
8545 if (AOP_TYPE (right) == AOP_LIT)
8547 if (((int) operandLitValue (right)))
8548 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8550 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8554 /* the right is also a bit variable */
8555 if (AOP_TYPE (right) == AOP_CRY)
8557 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8558 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8564 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8568 /* bit variables done */
8570 size = AOP_SIZE (result);
8572 if (AOP_TYPE (right) == AOP_LIT)
8573 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8575 (AOP_TYPE (result) != AOP_REG) &&
8576 (AOP_TYPE (right) == AOP_LIT) &&
8577 !IS_FLOAT (operandType (right)) &&
8580 emitcode ("clr", "a");
8583 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8584 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8586 aopPut (AOP (result),
8587 aopGet (AOP (right), size, FALSE, FALSE),
8589 isOperandVolatile (result, FALSE));
8596 aopPut (AOP (result),
8597 aopGet (AOP (right), offset, FALSE, FALSE),
8599 isOperandVolatile (result, FALSE));
8605 freeAsmop (right, NULL, ic, TRUE);
8606 freeAsmop (result, NULL, ic, TRUE);
8609 /*-----------------------------------------------------------------*/
8610 /* genJumpTab - genrates code for jump table */
8611 /*-----------------------------------------------------------------*/
8613 genJumpTab (iCode * ic)
8618 D(emitcode ("; genJumpTab",""));
8620 aopOp (IC_JTCOND (ic), ic, FALSE);
8621 /* get the condition into accumulator */
8622 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8624 /* multiply by three */
8625 emitcode ("add", "a,acc");
8626 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8627 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8629 jtab = newiTempLabel (NULL);
8630 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8631 emitcode ("jmp", "@a+dptr");
8632 emitcode ("", "%05d$:", jtab->key + 100);
8633 /* now generate the jump labels */
8634 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8635 jtab = setNextItem (IC_JTLABELS (ic)))
8636 emitcode ("ljmp", "%05d$", jtab->key + 100);
8640 /*-----------------------------------------------------------------*/
8641 /* genCast - gen code for casting */
8642 /*-----------------------------------------------------------------*/
8644 genCast (iCode * ic)
8646 operand *result = IC_RESULT (ic);
8647 sym_link *ctype = operandType (IC_LEFT (ic));
8648 sym_link *rtype = operandType (IC_RIGHT (ic));
8649 operand *right = IC_RIGHT (ic);
8652 D(emitcode("; genCast",""));
8654 /* if they are equivalent then do nothing */
8655 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8658 aopOp (right, ic, FALSE);
8659 aopOp (result, ic, FALSE);
8661 /* if the result is a bit (and not a bitfield) */
8662 // if (AOP_TYPE (result) == AOP_CRY)
8663 if (IS_BITVAR (OP_SYMBOL (result)->type)
8664 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8666 /* if the right size is a literal then
8667 we know what the value is */
8668 if (AOP_TYPE (right) == AOP_LIT)
8670 if (((int) operandLitValue (right)))
8671 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8673 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8678 /* the right is also a bit variable */
8679 if (AOP_TYPE (right) == AOP_CRY)
8681 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8682 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8688 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8693 /* if they are the same size : or less */
8694 if (AOP_SIZE (result) <= AOP_SIZE (right))
8697 /* if they are in the same place */
8698 if (sameRegs (AOP (right), AOP (result)))
8701 /* if they in different places then copy */
8702 size = AOP_SIZE (result);
8706 aopPut (AOP (result),
8707 aopGet (AOP (right), offset, FALSE, FALSE),
8709 isOperandVolatile (result, FALSE));
8716 /* if the result is of type pointer */
8721 sym_link *type = operandType (right);
8722 sym_link *etype = getSpec (type);
8724 /* pointer to generic pointer */
8725 if (IS_GENPTR (ctype))
8728 p_type = DCL_TYPE (type);
8731 if (SPEC_SCLS(etype)==S_REGISTER) {
8732 // let's assume it is a generic pointer
8735 /* we have to go by the storage class */
8736 p_type = PTR_TYPE (SPEC_OCLS (etype));
8740 /* the first two bytes are known */
8741 size = GPTRSIZE - 1;
8745 aopPut (AOP (result),
8746 aopGet (AOP (right), offset, FALSE, FALSE),
8748 isOperandVolatile (result, FALSE));
8751 /* the last byte depending on type */
8753 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8758 // pointerTypeToGPByte will have bitched.
8762 sprintf(gpValStr, "#0x%d", gpVal);
8763 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8768 /* just copy the pointers */
8769 size = AOP_SIZE (result);
8773 aopPut (AOP (result),
8774 aopGet (AOP (right), offset, FALSE, FALSE),
8776 isOperandVolatile (result, FALSE));
8782 /* so we now know that the size of destination is greater
8783 than the size of the source */
8784 /* we move to result for the size of source */
8785 size = AOP_SIZE (right);
8789 aopPut (AOP (result),
8790 aopGet (AOP (right), offset, FALSE, FALSE),
8792 isOperandVolatile (result, FALSE));
8796 /* now depending on the sign of the source && destination */
8797 size = AOP_SIZE (result) - AOP_SIZE (right);
8798 /* if unsigned or not an integral type */
8799 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8802 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8806 /* we need to extend the sign :{ */
8807 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8810 emitcode ("rlc", "a");
8811 emitcode ("subb", "a,acc");
8813 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8816 /* we are done hurray !!!! */
8819 freeAsmop (right, NULL, ic, TRUE);
8820 freeAsmop (result, NULL, ic, TRUE);
8824 /*-----------------------------------------------------------------*/
8825 /* genDjnz - generate decrement & jump if not zero instrucion */
8826 /*-----------------------------------------------------------------*/
8828 genDjnz (iCode * ic, iCode * ifx)
8834 D(emitcode ("; genDjnz",""));
8836 /* if the if condition has a false label
8837 then we cannot save */
8841 /* if the minus is not of the form
8843 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8844 !IS_OP_LITERAL (IC_RIGHT (ic)))
8847 if (operandLitValue (IC_RIGHT (ic)) != 1)
8850 /* if the size of this greater than one then no
8852 if (getSize (operandType (IC_RESULT (ic))) > 1)
8855 /* otherwise we can save BIG */
8856 lbl = newiTempLabel (NULL);
8857 lbl1 = newiTempLabel (NULL);
8859 aopOp (IC_RESULT (ic), ic, FALSE);
8861 if (AOP_NEEDSACC(IC_RESULT(ic)))
8863 /* If the result is accessed indirectly via
8864 * the accumulator, we must explicitly write
8865 * it back after the decrement.
8867 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8869 if (strcmp(rByte, "a"))
8871 /* Something is hopelessly wrong */
8872 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8873 __FILE__, __LINE__);
8874 /* We can just give up; the generated code will be inefficient,
8877 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8880 emitcode ("dec", "%s", rByte);
8881 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8882 emitcode ("jnz", "%05d$", lbl->key + 100);
8884 else if (IS_AOP_PREG (IC_RESULT (ic)))
8886 emitcode ("dec", "%s",
8887 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8888 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8889 emitcode ("jnz", "%05d$", lbl->key + 100);
8893 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8896 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8897 emitcode ("", "%05d$:", lbl->key + 100);
8898 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8899 emitcode ("", "%05d$:", lbl1->key + 100);
8901 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8906 /*-----------------------------------------------------------------*/
8907 /* genReceive - generate code for a receive iCode */
8908 /*-----------------------------------------------------------------*/
8910 genReceive (iCode * ic)
8912 int size = getSize (operandType (IC_RESULT (ic)));
8914 D(emitcode ("; genReceive",""));
8916 if (ic->argreg == 1) { /* first parameter */
8917 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8918 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8919 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8921 offset = fReturnSizeMCS51 - size;
8923 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8924 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8927 aopOp (IC_RESULT (ic), ic, FALSE);
8928 size = AOP_SIZE (IC_RESULT (ic));
8931 emitcode ("pop", "acc");
8932 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8937 aopOp (IC_RESULT (ic), ic, FALSE);
8939 assignResultValue (IC_RESULT (ic));
8941 } else { /* second receive onwards */
8943 aopOp (IC_RESULT (ic), ic, FALSE);
8944 rb1off = ic->argreg;
8946 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8949 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8952 /*-----------------------------------------------------------------*/
8953 /* genDummyRead - generate code for dummy read of volatiles */
8954 /*-----------------------------------------------------------------*/
8956 genDummyRead (iCode * ic)
8961 D(emitcode("; genDummyRead",""));
8963 right = IC_RIGHT (ic);
8965 aopOp (right, ic, FALSE);
8967 /* if the result is a bit */
8968 if (AOP_TYPE (right) == AOP_CRY)
8970 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8974 /* bit variables done */
8976 size = AOP_SIZE (right);
8980 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8985 freeAsmop (right, NULL, ic, TRUE);
8988 /*-----------------------------------------------------------------*/
8989 /* gen51Code - generate code for 8051 based controllers */
8990 /*-----------------------------------------------------------------*/
8992 gen51Code (iCode * lic)
8997 lineHead = lineCurr = NULL;
8999 /* print the allocation information */
9000 if (allocInfo && currFunc)
9001 printAllocInfo (currFunc, codeOutFile);
9002 /* if debug information required */
9003 if (options.debug && currFunc)
9005 debugFile->writeFunction(currFunc);
9007 if (IS_STATIC (currFunc->etype))
9008 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9010 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9013 /* stack pointer name */
9014 if (options.useXstack)
9020 for (ic = lic; ic; ic = ic->next)
9022 _G.current_iCode = ic;
9024 if (ic->lineno && cln != ic->lineno)
9029 emitcode ("", "C$%s$%d$%d$%d ==.",
9030 FileBaseName (ic->filename), ic->lineno,
9031 ic->level, ic->block);
9034 if (!options.noCcodeInAsm) {
9035 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9036 printCLine(ic->filename, ic->lineno));
9040 if (options.iCodeInAsm) {
9044 for (i=0; i<8; i++) {
9045 sprintf (®sInUse[i],
9046 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9049 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9051 /* if the result is marked as
9052 spilt and rematerializable or code for
9053 this has already been generated then
9055 if (resultRemat (ic) || ic->generated)
9058 /* depending on the operation */
9078 /* IPOP happens only when trying to restore a
9079 spilt live range, if there is an ifx statement
9080 following this pop then the if statement might
9081 be using some of the registers being popped which
9082 would destory the contents of the register so
9083 we need to check for this condition and handle it */
9085 ic->next->op == IFX &&
9086 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9087 genIfx (ic->next, ic);
9105 genEndFunction (ic);
9125 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9142 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9146 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9153 /* note these two are xlated by algebraic equivalence
9154 during parsing SDCC.y */
9155 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9156 "got '>=' or '<=' shouldn't have come here");
9160 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9172 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9176 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9180 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9207 case GET_VALUE_AT_ADDRESS:
9208 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9212 if (POINTER_SET (ic))
9213 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9239 addSet (&_G.sendSet, ic);
9242 case DUMMY_READ_VOLATILE:
9251 _G.current_iCode = NULL;
9253 /* now we are ready to call the
9254 peep hole optimizer */
9255 if (!options.nopeep)
9256 peepHole (&lineHead);
9258 /* now do the actual printing */
9259 printLine (lineHead, codeOutFile);