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 /* if critical function then turn interrupts off */
2295 if (IFFUNC_ISCRITICAL (ftype))
2296 emitcode ("clr", "ea");
2298 /* here we need to generate the equates for the
2299 register bank if required */
2300 if (FUNC_REGBANK (ftype) != rbank)
2304 rbank = FUNC_REGBANK (ftype);
2305 for (i = 0; i < mcs51_nRegs; i++)
2307 if (strcmp (regs8051[i].base, "0") == 0)
2308 emitcode ("", "%s = 0x%02x",
2310 8 * rbank + regs8051[i].offset);
2312 emitcode ("", "%s = %s + 0x%02x",
2315 8 * rbank + regs8051[i].offset);
2319 /* if this is an interrupt service routine then
2320 save acc, b, dpl, dph */
2321 if (IFFUNC_ISISR (sym->type))
2324 if (!inExcludeList ("acc"))
2325 emitcode ("push", "acc");
2326 if (!inExcludeList ("b"))
2327 emitcode ("push", "b");
2328 if (!inExcludeList ("dpl"))
2329 emitcode ("push", "dpl");
2330 if (!inExcludeList ("dph"))
2331 emitcode ("push", "dph");
2332 /* if this isr has no bank i.e. is going to
2333 run with bank 0 , then we need to save more
2335 if (!FUNC_REGBANK (sym->type))
2338 /* if this function does not call any other
2339 function then we can be economical and
2340 save only those registers that are used */
2341 if (!IFFUNC_HASFCALL(sym->type))
2345 /* if any registers used */
2348 /* save the registers used */
2349 for (i = 0; i < sym->regsUsed->size; i++)
2351 if (bitVectBitValue (sym->regsUsed, i) ||
2352 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2353 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2361 /* this function has a function call cannot
2362 determines register usage so we will have to push the
2364 saveRBank (0, ic, FALSE);
2365 if (options.parms_in_bank1) {
2367 for (i=0; i < 8 ; i++ ) {
2368 emitcode ("push","%s",rb1regs[i]);
2375 /* This ISR uses a non-zero bank.
2377 * We assume that the bank is available for our
2380 * However, if this ISR calls a function which uses some
2381 * other bank, we must save that bank entirely.
2383 unsigned long banksToSave = 0;
2385 if (IFFUNC_HASFCALL(sym->type))
2388 #define MAX_REGISTER_BANKS 4
2393 for (i = ic; i; i = i->next)
2395 if (i->op == ENDFUNCTION)
2397 /* we got to the end OK. */
2405 dtype = operandType (IC_LEFT(i));
2407 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2409 /* Mark this bank for saving. */
2410 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2412 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2416 banksToSave |= (1 << FUNC_REGBANK(dtype));
2419 /* And note that we don't need to do it in
2427 /* This is a mess; we have no idea what
2428 * register bank the called function might
2431 * The only thing I can think of to do is
2432 * throw a warning and hope.
2434 werror(W_FUNCPTR_IN_USING_ISR);
2438 if (banksToSave && options.useXstack)
2440 /* Since we aren't passing it an ic,
2441 * saveRBank will assume r0 is available to abuse.
2443 * So switch to our (trashable) bank now, so
2444 * the caller's R0 isn't trashed.
2446 emitcode ("push", "psw");
2447 emitcode ("mov", "psw,#0x%02x",
2448 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2452 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2454 if (banksToSave & (1 << ix))
2456 saveRBank(ix, NULL, FALSE);
2460 // TODO: this needs a closer look
2461 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2466 /* if callee-save to be used for this function
2467 then save the registers being used in this function */
2468 if (IFFUNC_CALLEESAVES(sym->type))
2472 /* if any registers used */
2475 /* save the registers used */
2476 for (i = 0; i < sym->regsUsed->size; i++)
2478 if (bitVectBitValue (sym->regsUsed, i) ||
2479 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2481 /* remember one saved register for later usage */
2482 if (calleesaves_saved_register < 0)
2483 calleesaves_saved_register = i;
2484 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2492 /* set the register bank to the desired value */
2493 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2496 emitcode ("push", "psw");
2497 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2500 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2503 if (options.useXstack)
2505 emitcode ("mov", "r0,%s", spname);
2506 emitcode ("mov", "a,_bp");
2507 emitcode ("movx", "@r0,a");
2508 emitcode ("inc", "%s", spname);
2512 /* set up the stack */
2513 emitcode ("push", "_bp"); /* save the callers stack */
2515 emitcode ("mov", "_bp,%s", spname);
2518 /* adjust the stack for the function */
2524 werror (W_STACK_OVERFLOW, sym->name);
2526 if (i > 3 && sym->recvSize < 4)
2529 emitcode ("mov", "a,sp");
2530 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2531 emitcode ("mov", "sp,a");
2536 if (IFFUNC_CALLEESAVES(sym->type))
2538 /* if it's a callee-saves function we need a saved register */
2539 if (calleesaves_saved_register >= 0)
2541 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2542 emitcode ("mov", "a,sp");
2543 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2544 emitcode ("mov", "sp,a");
2545 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2548 /* do it the hard way */
2550 emitcode ("inc", "sp");
2554 /* not callee-saves, we can clobber r0 */
2555 emitcode ("mov", "r0,a");
2556 emitcode ("mov", "a,sp");
2557 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2558 emitcode ("mov", "sp,a");
2559 emitcode ("mov", "a,r0");
2564 emitcode ("inc", "sp");
2570 emitcode ("mov", "a,_spx");
2571 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2572 emitcode ("mov", "_spx,a");
2577 /*-----------------------------------------------------------------*/
2578 /* genEndFunction - generates epilogue for functions */
2579 /*-----------------------------------------------------------------*/
2581 genEndFunction (iCode * ic)
2583 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2585 if (IFFUNC_ISNAKED(sym->type))
2587 emitcode(";", "naked function: no epilogue.");
2591 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2593 emitcode ("mov", "%s,_bp", spname);
2596 /* if use external stack but some variables were
2597 added to the local stack then decrement the
2599 if (options.useXstack && sym->stack)
2601 emitcode ("mov", "a,sp");
2602 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2603 emitcode ("mov", "sp,a");
2607 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2609 if (options.useXstack)
2611 emitcode ("mov", "r0,%s", spname);
2612 emitcode ("movx", "a,@r0");
2613 emitcode ("mov", "_bp,a");
2614 emitcode ("dec", "%s", spname);
2618 emitcode ("pop", "_bp");
2622 /* restore the register bank */
2623 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2625 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2626 || !options.useXstack)
2628 /* Special case of ISR using non-zero bank with useXstack
2631 emitcode ("pop", "psw");
2635 if (IFFUNC_ISISR (sym->type))
2638 /* now we need to restore the registers */
2639 /* if this isr has no bank i.e. is going to
2640 run with bank 0 , then we need to save more
2642 if (!FUNC_REGBANK (sym->type))
2644 /* if this function does not call any other
2645 function then we can be economical and
2646 save only those registers that are used */
2647 if (!IFFUNC_HASFCALL(sym->type))
2651 /* if any registers used */
2654 /* save the registers used */
2655 for (i = sym->regsUsed->size; i >= 0; i--)
2657 if (bitVectBitValue (sym->regsUsed, i) ||
2658 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2659 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2666 if (options.parms_in_bank1) {
2668 for (i = 7 ; i >= 0 ; i-- ) {
2669 emitcode ("pop","%s",rb1regs[i]);
2672 /* this function has a function call cannot
2673 determines register usage so we will have to pop the
2675 unsaveRBank (0, ic, FALSE);
2680 /* This ISR uses a non-zero bank.
2682 * Restore any register banks saved by genFunction
2685 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2688 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2690 if (savedBanks & (1 << ix))
2692 unsaveRBank(ix, NULL, FALSE);
2696 if (options.useXstack)
2698 /* Restore bank AFTER calling unsaveRBank,
2699 * since it can trash r0.
2701 emitcode ("pop", "psw");
2705 if (!inExcludeList ("dph"))
2706 emitcode ("pop", "dph");
2707 if (!inExcludeList ("dpl"))
2708 emitcode ("pop", "dpl");
2709 if (!inExcludeList ("b"))
2710 emitcode ("pop", "b");
2711 if (!inExcludeList ("acc"))
2712 emitcode ("pop", "acc");
2714 if (IFFUNC_ISCRITICAL (sym->type))
2715 emitcode ("setb", "ea");
2717 /* if debug then send end of function */
2718 if (options.debug && currFunc)
2721 emitcode ("", "C$%s$%d$%d$%d ==.",
2722 FileBaseName (ic->filename), currFunc->lastLine,
2723 ic->level, ic->block);
2724 if (IS_STATIC (currFunc->etype))
2725 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2727 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2731 emitcode ("reti", "");
2735 if (IFFUNC_ISCRITICAL (sym->type))
2736 emitcode ("setb", "ea");
2738 if (IFFUNC_CALLEESAVES(sym->type))
2742 /* if any registers used */
2745 /* save the registers used */
2746 for (i = sym->regsUsed->size; i >= 0; i--)
2748 if (bitVectBitValue (sym->regsUsed, i) ||
2749 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2750 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2756 /* if debug then send end of function */
2757 if (options.debug && currFunc)
2760 emitcode ("", "C$%s$%d$%d$%d ==.",
2761 FileBaseName (ic->filename), currFunc->lastLine,
2762 ic->level, ic->block);
2763 if (IS_STATIC (currFunc->etype))
2764 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2766 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2770 emitcode ("ret", "");
2775 /*-----------------------------------------------------------------*/
2776 /* genRet - generate code for return statement */
2777 /*-----------------------------------------------------------------*/
2781 int size, offset = 0, pushed = 0;
2783 D(emitcode ("; genRet",""));
2785 /* if we have no return value then
2786 just generate the "ret" */
2790 /* we have something to return then
2791 move the return value into place */
2792 aopOp (IC_LEFT (ic), ic, FALSE);
2793 size = AOP_SIZE (IC_LEFT (ic));
2798 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2801 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2803 emitcode ("push", "%s", l);
2808 l = aopGet (AOP (IC_LEFT (ic)), offset,
2810 if (strcmp (fReturn[offset], l))
2811 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2820 if (strcmp (fReturn[pushed], "a"))
2821 emitcode ("pop", fReturn[pushed]);
2823 emitcode ("pop", "acc");
2826 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2829 /* generate a jump to the return label
2830 if the next is not the return statement */
2831 if (!(ic->next && ic->next->op == LABEL &&
2832 IC_LABEL (ic->next) == returnLabel))
2834 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2838 /*-----------------------------------------------------------------*/
2839 /* genLabel - generates a label */
2840 /*-----------------------------------------------------------------*/
2842 genLabel (iCode * ic)
2844 /* special case never generate */
2845 if (IC_LABEL (ic) == entryLabel)
2848 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2851 /*-----------------------------------------------------------------*/
2852 /* genGoto - generates a ljmp */
2853 /*-----------------------------------------------------------------*/
2855 genGoto (iCode * ic)
2857 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2860 /*-----------------------------------------------------------------*/
2861 /* findLabelBackwards: walks back through the iCode chain looking */
2862 /* for the given label. Returns number of iCode instructions */
2863 /* between that label and given ic. */
2864 /* Returns zero if label not found. */
2865 /*-----------------------------------------------------------------*/
2867 findLabelBackwards (iCode * ic, int key)
2876 /* If we have any pushes or pops, we cannot predict the distance.
2877 I don't like this at all, this should be dealt with in the
2879 if (ic->op == IPUSH || ic->op == IPOP) {
2883 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2892 /*-----------------------------------------------------------------*/
2893 /* genPlusIncr :- does addition with increment if possible */
2894 /*-----------------------------------------------------------------*/
2896 genPlusIncr (iCode * ic)
2898 unsigned int icount;
2899 unsigned int size = getDataSize (IC_RESULT (ic));
2901 /* will try to generate an increment */
2902 /* if the right side is not a literal
2904 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2907 /* if the literal value of the right hand side
2908 is greater than 4 then it is not worth it */
2909 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2912 D(emitcode ("; genPlusIncr",""));
2914 /* if increment >=16 bits in register or direct space */
2915 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2916 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2924 /* If the next instruction is a goto and the goto target
2925 * is < 10 instructions previous to this, we can generate
2926 * jumps straight to that target.
2928 if (ic->next && ic->next->op == GOTO
2929 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2930 && labelRange <= 10)
2932 emitcode (";", "tail increment optimized");
2933 tlbl = IC_LABEL (ic->next);
2938 tlbl = newiTempLabel (NULL);
2941 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2942 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2943 IS_AOP_PREG (IC_RESULT (ic)))
2944 emitcode ("cjne", "%s,#0x00,%05d$",
2945 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2949 emitcode ("clr", "a");
2950 emitcode ("cjne", "a,%s,%05d$",
2951 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2955 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2958 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2959 IS_AOP_PREG (IC_RESULT (ic)))
2960 emitcode ("cjne", "%s,#0x00,%05d$",
2961 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2964 emitcode ("cjne", "a,%s,%05d$",
2965 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2968 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2972 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2973 IS_AOP_PREG (IC_RESULT (ic)))
2974 emitcode ("cjne", "%s,#0x00,%05d$",
2975 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2979 emitcode ("cjne", "a,%s,%05d$",
2980 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2983 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2988 emitcode ("", "%05d$:", tlbl->key + 100);
2993 /* if the sizes are greater than 1 then we cannot */
2994 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2995 AOP_SIZE (IC_LEFT (ic)) > 1)
2998 /* we can if the aops of the left & result match or
2999 if they are in registers and the registers are the
3001 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3006 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3007 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3008 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3014 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3023 /*-----------------------------------------------------------------*/
3024 /* outBitAcc - output a bit in acc */
3025 /*-----------------------------------------------------------------*/
3027 outBitAcc (operand * result)
3029 symbol *tlbl = newiTempLabel (NULL);
3030 /* if the result is a bit */
3031 if (AOP_TYPE (result) == AOP_CRY)
3033 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3037 emitcode ("jz", "%05d$", tlbl->key + 100);
3038 emitcode ("mov", "a,%s", one);
3039 emitcode ("", "%05d$:", tlbl->key + 100);
3044 /*-----------------------------------------------------------------*/
3045 /* genPlusBits - generates code for addition of two bits */
3046 /*-----------------------------------------------------------------*/
3048 genPlusBits (iCode * ic)
3050 D(emitcode ("; genPlusBits",""));
3052 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3054 symbol *lbl = newiTempLabel (NULL);
3055 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3056 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3057 emitcode ("cpl", "c");
3058 emitcode ("", "%05d$:", (lbl->key + 100));
3059 outBitC (IC_RESULT (ic));
3063 emitcode ("clr", "a");
3064 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3065 emitcode ("rlc", "a");
3066 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3067 emitcode ("addc", "a,#0x00");
3068 outAcc (IC_RESULT (ic));
3073 /* This is the original version of this code.
3075 * This is being kept around for reference,
3076 * because I am not entirely sure I got it right...
3079 adjustArithmeticResult (iCode * ic)
3081 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3082 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3083 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3084 aopPut (AOP (IC_RESULT (ic)),
3085 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3087 isOperandVolatile (IC_RESULT (ic), FALSE));
3089 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3090 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3091 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3092 aopPut (AOP (IC_RESULT (ic)),
3093 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3095 isOperandVolatile (IC_RESULT (ic), FALSE));
3097 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3098 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3099 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3100 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3101 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3104 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3105 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3109 /* This is the pure and virtuous version of this code.
3110 * I'm pretty certain it's right, but not enough to toss the old
3114 adjustArithmeticResult (iCode * ic)
3116 if (opIsGptr (IC_RESULT (ic)) &&
3117 opIsGptr (IC_LEFT (ic)) &&
3118 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3120 aopPut (AOP (IC_RESULT (ic)),
3121 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3123 isOperandVolatile (IC_RESULT (ic), FALSE));
3126 if (opIsGptr (IC_RESULT (ic)) &&
3127 opIsGptr (IC_RIGHT (ic)) &&
3128 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3130 aopPut (AOP (IC_RESULT (ic)),
3131 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3133 isOperandVolatile (IC_RESULT (ic), FALSE));
3136 if (opIsGptr (IC_RESULT (ic)) &&
3137 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3138 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3139 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3140 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3143 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3144 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3149 /*-----------------------------------------------------------------*/
3150 /* genPlus - generates code for addition */
3151 /*-----------------------------------------------------------------*/
3153 genPlus (iCode * ic)
3155 int size, offset = 0;
3157 asmop *leftOp, *rightOp;
3159 /* special cases :- */
3161 D(emitcode ("; genPlus",""));
3163 aopOp (IC_LEFT (ic), ic, FALSE);
3164 aopOp (IC_RIGHT (ic), ic, FALSE);
3165 aopOp (IC_RESULT (ic), ic, TRUE);
3167 /* if literal, literal on the right or
3168 if left requires ACC or right is already
3170 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3171 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3172 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3174 operand *t = IC_RIGHT (ic);
3175 IC_RIGHT (ic) = IC_LEFT (ic);
3179 /* if both left & right are in bit
3181 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3182 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3188 /* if left in bit space & right literal */
3189 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3190 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3192 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3193 /* if result in bit space */
3194 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3196 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3197 emitcode ("cpl", "c");
3198 outBitC (IC_RESULT (ic));
3202 size = getDataSize (IC_RESULT (ic));
3205 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3206 emitcode ("addc", "a,#00");
3207 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3213 /* if I can do an increment instead
3214 of add then GOOD for ME */
3215 if (genPlusIncr (ic) == TRUE)
3218 size = getDataSize (IC_RESULT (ic));
3220 leftOp = AOP(IC_LEFT(ic));
3221 rightOp = AOP(IC_RIGHT(ic));
3226 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3228 emitcode("mov", "b,a");
3229 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3230 emitcode("xch", "a,b");
3231 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3232 emitcode (add, "a,b");
3234 else if (aopGetUsesAcc (leftOp, offset))
3236 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3237 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3241 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3242 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3244 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3245 add = "addc"; /* further adds must propagate carry */
3248 adjustArithmeticResult (ic);
3251 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3252 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3253 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3256 /*-----------------------------------------------------------------*/
3257 /* genMinusDec :- does subtraction with deccrement if possible */
3258 /*-----------------------------------------------------------------*/
3260 genMinusDec (iCode * ic)
3262 unsigned int icount;
3263 unsigned int size = getDataSize (IC_RESULT (ic));
3265 /* will try to generate an increment */
3266 /* if the right side is not a literal
3268 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3271 /* if the literal value of the right hand side
3272 is greater than 4 then it is not worth it */
3273 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3276 D(emitcode ("; genMinusDec",""));
3278 /* if decrement >=16 bits in register or direct space */
3279 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3280 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3288 /* If the next instruction is a goto and the goto target
3289 * is <= 10 instructions previous to this, we can generate
3290 * jumps straight to that target.
3292 if (ic->next && ic->next->op == GOTO
3293 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3294 && labelRange <= 10)
3296 emitcode (";", "tail decrement optimized");
3297 tlbl = IC_LABEL (ic->next);
3302 tlbl = newiTempLabel (NULL);
3306 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3307 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3308 IS_AOP_PREG (IC_RESULT (ic)))
3309 emitcode ("cjne", "%s,#0xff,%05d$"
3310 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3314 emitcode ("mov", "a,#0xff");
3315 emitcode ("cjne", "a,%s,%05d$"
3316 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3319 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3322 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3323 IS_AOP_PREG (IC_RESULT (ic)))
3324 emitcode ("cjne", "%s,#0xff,%05d$"
3325 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3329 emitcode ("cjne", "a,%s,%05d$"
3330 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3333 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3337 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3338 IS_AOP_PREG (IC_RESULT (ic)))
3339 emitcode ("cjne", "%s,#0xff,%05d$"
3340 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3344 emitcode ("cjne", "a,%s,%05d$"
3345 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3348 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3352 emitcode ("", "%05d$:", tlbl->key + 100);
3357 /* if the sizes are greater than 1 then we cannot */
3358 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3359 AOP_SIZE (IC_LEFT (ic)) > 1)
3362 /* we can if the aops of the left & result match or
3363 if they are in registers and the registers are the
3365 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3369 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3377 /*-----------------------------------------------------------------*/
3378 /* addSign - complete with sign */
3379 /*-----------------------------------------------------------------*/
3381 addSign (operand * result, int offset, int sign)
3383 int size = (getDataSize (result) - offset);
3388 emitcode ("rlc", "a");
3389 emitcode ("subb", "a,acc");
3391 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3395 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3399 /*-----------------------------------------------------------------*/
3400 /* genMinusBits - generates code for subtraction of two bits */
3401 /*-----------------------------------------------------------------*/
3403 genMinusBits (iCode * ic)
3405 symbol *lbl = newiTempLabel (NULL);
3407 D(emitcode ("; genMinusBits",""));
3409 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3411 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3412 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3413 emitcode ("cpl", "c");
3414 emitcode ("", "%05d$:", (lbl->key + 100));
3415 outBitC (IC_RESULT (ic));
3419 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3420 emitcode ("subb", "a,acc");
3421 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3422 emitcode ("inc", "a");
3423 emitcode ("", "%05d$:", (lbl->key + 100));
3424 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3425 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3429 /*-----------------------------------------------------------------*/
3430 /* genMinus - generates code for subtraction */
3431 /*-----------------------------------------------------------------*/
3433 genMinus (iCode * ic)
3435 int size, offset = 0;
3437 D(emitcode ("; genMinus",""));
3439 aopOp (IC_LEFT (ic), ic, FALSE);
3440 aopOp (IC_RIGHT (ic), ic, FALSE);
3441 aopOp (IC_RESULT (ic), ic, TRUE);
3443 /* special cases :- */
3444 /* if both left & right are in bit space */
3445 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3446 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3452 /* if I can do an decrement instead
3453 of subtract then GOOD for ME */
3454 if (genMinusDec (ic) == TRUE)
3457 size = getDataSize (IC_RESULT (ic));
3459 /* if literal, add a,#-lit, else normal subb */
3460 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3462 unsigned long lit = 0L;
3464 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3469 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3470 /* first add without previous c */
3472 if (!size && lit== (unsigned long) -1) {
3473 emitcode ("dec", "a");
3475 emitcode ("add", "a,#0x%02x",
3476 (unsigned int) (lit & 0x0FFL));
3479 emitcode ("addc", "a,#0x%02x",
3480 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3482 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3487 asmop *leftOp, *rightOp;
3489 leftOp = AOP(IC_LEFT(ic));
3490 rightOp = AOP(IC_RIGHT(ic));
3494 if (aopGetUsesAcc(rightOp, offset)) {
3495 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3496 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3498 emitcode( "setb", "c");
3500 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3501 emitcode("cpl", "a");
3503 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3506 emitcode ("subb", "a,%s",
3507 aopGet(rightOp, offset, FALSE, TRUE));
3510 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3515 adjustArithmeticResult (ic);
3518 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3519 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3520 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3524 /*-----------------------------------------------------------------*/
3525 /* genMultbits :- multiplication of bits */
3526 /*-----------------------------------------------------------------*/
3528 genMultbits (operand * left,
3532 D(emitcode ("; genMultbits",""));
3534 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3535 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3540 /*-----------------------------------------------------------------*/
3541 /* genMultOneByte : 8*8=8/16 bit multiplication */
3542 /*-----------------------------------------------------------------*/
3544 genMultOneByte (operand * left,
3548 sym_link *opetype = operandType (result);
3550 int size=AOP_SIZE(result);
3552 D(emitcode ("; genMultOneByte",""));
3554 if (size<1 || size>2) {
3555 // this should never happen
3556 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3557 AOP_SIZE(result), __FILE__, lineno);
3561 /* (if two literals: the value is computed before) */
3562 /* if one literal, literal on the right */
3563 if (AOP_TYPE (left) == AOP_LIT)
3568 //emitcode (";", "swapped left and right");
3571 if (SPEC_USIGN(opetype)
3572 // ignore the sign of left and right, what else can we do?
3573 || (SPEC_USIGN(operandType(left)) &&
3574 SPEC_USIGN(operandType(right)))) {
3575 // just an unsigned 8*8=8/16 multiply
3576 //emitcode (";","unsigned");
3577 // TODO: check for accumulator clash between left & right aops?
3578 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3579 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3580 emitcode ("mul", "ab");
3581 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3583 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3588 // we have to do a signed multiply
3590 //emitcode (";", "signed");
3591 emitcode ("clr", "F0"); // reset sign flag
3592 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3594 lbl=newiTempLabel(NULL);
3595 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3596 // left side is negative, 8-bit two's complement, this fails for -128
3597 emitcode ("setb", "F0"); // set sign flag
3598 emitcode ("cpl", "a");
3599 emitcode ("inc", "a");
3601 emitcode ("", "%05d$:", lbl->key+100);
3604 if (AOP_TYPE(right)==AOP_LIT) {
3605 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3606 /* AND literal negative */
3608 emitcode ("cpl", "F0"); // complement sign flag
3609 emitcode ("mov", "b,#0x%02x", -val);
3611 emitcode ("mov", "b,#0x%02x", val);
3614 lbl=newiTempLabel(NULL);
3615 emitcode ("mov", "b,a");
3616 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3617 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3618 // right side is negative, 8-bit two's complement
3619 emitcode ("cpl", "F0"); // complement sign flag
3620 emitcode ("cpl", "a");
3621 emitcode ("inc", "a");
3622 emitcode ("", "%05d$:", lbl->key+100);
3624 emitcode ("mul", "ab");
3626 lbl=newiTempLabel(NULL);
3627 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3628 // only ONE op was negative, we have to do a 8/16-bit two's complement
3629 emitcode ("cpl", "a"); // lsb
3631 emitcode ("inc", "a");
3633 emitcode ("add", "a,#1");
3634 emitcode ("xch", "a,b");
3635 emitcode ("cpl", "a"); // msb
3636 emitcode ("addc", "a,#0");
3637 emitcode ("xch", "a,b");
3640 emitcode ("", "%05d$:", lbl->key+100);
3641 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3643 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3647 /*-----------------------------------------------------------------*/
3648 /* genMult - generates code for multiplication */
3649 /*-----------------------------------------------------------------*/
3651 genMult (iCode * ic)
3653 operand *left = IC_LEFT (ic);
3654 operand *right = IC_RIGHT (ic);
3655 operand *result = IC_RESULT (ic);
3657 D(emitcode ("; genMult",""));
3659 /* assign the amsops */
3660 aopOp (left, ic, FALSE);
3661 aopOp (right, ic, FALSE);
3662 aopOp (result, ic, TRUE);
3664 /* special cases first */
3666 if (AOP_TYPE (left) == AOP_CRY &&
3667 AOP_TYPE (right) == AOP_CRY)
3669 genMultbits (left, right, result);
3673 /* if both are of size == 1 */
3674 #if 0 // one of them can be a sloc shared with the result
3675 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3677 if (getSize(operandType(left)) == 1 &&
3678 getSize(operandType(right)) == 1)
3681 genMultOneByte (left, right, result);
3685 /* should have been converted to function call */
3686 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3687 getSize(OP_SYMBOL(right)->type));
3691 freeAsmop (result, NULL, ic, TRUE);
3692 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3693 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3696 /*-----------------------------------------------------------------*/
3697 /* genDivbits :- division of bits */
3698 /*-----------------------------------------------------------------*/
3700 genDivbits (operand * left,
3707 D(emitcode ("; genDivbits",""));
3709 /* the result must be bit */
3710 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3711 l = aopGet (AOP (left), 0, FALSE, FALSE);
3715 emitcode ("div", "ab");
3716 emitcode ("rrc", "a");
3717 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3720 /*-----------------------------------------------------------------*/
3721 /* genDivOneByte : 8 bit division */
3722 /*-----------------------------------------------------------------*/
3724 genDivOneByte (operand * left,
3728 sym_link *opetype = operandType (result);
3733 D(emitcode ("; genDivOneByte",""));
3735 size = AOP_SIZE (result) - 1;
3737 /* signed or unsigned */
3738 if (SPEC_USIGN (opetype))
3740 /* unsigned is easy */
3741 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3742 l = aopGet (AOP (left), 0, FALSE, FALSE);
3744 emitcode ("div", "ab");
3745 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3747 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3751 /* signed is a little bit more difficult */
3753 /* save the signs of the operands */
3754 l = aopGet (AOP (left), 0, FALSE, FALSE);
3756 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3757 emitcode ("push", "acc"); /* save it on the stack */
3759 /* now sign adjust for both left & right */
3760 l = aopGet (AOP (right), 0, FALSE, FALSE);
3762 lbl = newiTempLabel (NULL);
3763 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3764 emitcode ("cpl", "a");
3765 emitcode ("inc", "a");
3766 emitcode ("", "%05d$:", (lbl->key + 100));
3767 emitcode ("mov", "b,a");
3769 /* sign adjust left side */
3770 l = aopGet (AOP (left), 0, FALSE, FALSE);
3773 lbl = newiTempLabel (NULL);
3774 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3775 emitcode ("cpl", "a");
3776 emitcode ("inc", "a");
3777 emitcode ("", "%05d$:", (lbl->key + 100));
3779 /* now the division */
3780 emitcode ("div", "ab");
3781 /* we are interested in the lower order
3783 emitcode ("mov", "b,a");
3784 lbl = newiTempLabel (NULL);
3785 emitcode ("pop", "acc");
3786 /* if there was an over flow we don't
3787 adjust the sign of the result */
3788 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3789 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3791 emitcode ("clr", "a");
3792 emitcode ("subb", "a,b");
3793 emitcode ("mov", "b,a");
3794 emitcode ("", "%05d$:", (lbl->key + 100));
3796 /* now we are done */
3797 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3800 emitcode ("mov", "c,b.7");
3801 emitcode ("subb", "a,acc");
3804 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3808 /*-----------------------------------------------------------------*/
3809 /* genDiv - generates code for division */
3810 /*-----------------------------------------------------------------*/
3814 operand *left = IC_LEFT (ic);
3815 operand *right = IC_RIGHT (ic);
3816 operand *result = IC_RESULT (ic);
3818 D(emitcode ("; genDiv",""));
3820 /* assign the amsops */
3821 aopOp (left, ic, FALSE);
3822 aopOp (right, ic, FALSE);
3823 aopOp (result, ic, TRUE);
3825 /* special cases first */
3827 if (AOP_TYPE (left) == AOP_CRY &&
3828 AOP_TYPE (right) == AOP_CRY)
3830 genDivbits (left, right, result);
3834 /* if both are of size == 1 */
3835 if (AOP_SIZE (left) == 1 &&
3836 AOP_SIZE (right) == 1)
3838 genDivOneByte (left, right, result);
3842 /* should have been converted to function call */
3845 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3846 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3847 freeAsmop (result, NULL, ic, TRUE);
3850 /*-----------------------------------------------------------------*/
3851 /* genModbits :- modulus of bits */
3852 /*-----------------------------------------------------------------*/
3854 genModbits (operand * left,
3861 D(emitcode ("; genModbits",""));
3863 /* the result must be bit */
3864 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3865 l = aopGet (AOP (left), 0, FALSE, FALSE);
3869 emitcode ("div", "ab");
3870 emitcode ("mov", "a,b");
3871 emitcode ("rrc", "a");
3872 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3875 /*-----------------------------------------------------------------*/
3876 /* genModOneByte : 8 bit modulus */
3877 /*-----------------------------------------------------------------*/
3879 genModOneByte (operand * left,
3883 sym_link *opetype = operandType (result);
3887 D(emitcode ("; genModOneByte",""));
3889 /* signed or unsigned */
3890 if (SPEC_USIGN (opetype))
3892 /* unsigned is easy */
3893 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3894 l = aopGet (AOP (left), 0, FALSE, FALSE);
3896 emitcode ("div", "ab");
3897 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3901 /* signed is a little bit more difficult */
3903 /* save the signs of the operands */
3904 l = aopGet (AOP (left), 0, FALSE, FALSE);
3907 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3908 emitcode ("push", "acc"); /* save it on the stack */
3910 /* now sign adjust for both left & right */
3911 l = aopGet (AOP (right), 0, FALSE, FALSE);
3914 lbl = newiTempLabel (NULL);
3915 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3916 emitcode ("cpl", "a");
3917 emitcode ("inc", "a");
3918 emitcode ("", "%05d$:", (lbl->key + 100));
3919 emitcode ("mov", "b,a");
3921 /* sign adjust left side */
3922 l = aopGet (AOP (left), 0, FALSE, FALSE);
3925 lbl = newiTempLabel (NULL);
3926 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3927 emitcode ("cpl", "a");
3928 emitcode ("inc", "a");
3929 emitcode ("", "%05d$:", (lbl->key + 100));
3931 /* now the multiplication */
3932 emitcode ("div", "ab");
3933 /* we are interested in the lower order
3935 lbl = newiTempLabel (NULL);
3936 emitcode ("pop", "acc");
3937 /* if there was an over flow we don't
3938 adjust the sign of the result */
3939 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3940 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3942 emitcode ("clr", "a");
3943 emitcode ("subb", "a,b");
3944 emitcode ("mov", "b,a");
3945 emitcode ("", "%05d$:", (lbl->key + 100));
3947 /* now we are done */
3948 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3952 /*-----------------------------------------------------------------*/
3953 /* genMod - generates code for division */
3954 /*-----------------------------------------------------------------*/
3958 operand *left = IC_LEFT (ic);
3959 operand *right = IC_RIGHT (ic);
3960 operand *result = IC_RESULT (ic);
3962 D(emitcode ("; genMod",""));
3964 /* assign the amsops */
3965 aopOp (left, ic, FALSE);
3966 aopOp (right, ic, FALSE);
3967 aopOp (result, ic, TRUE);
3969 /* special cases first */
3971 if (AOP_TYPE (left) == AOP_CRY &&
3972 AOP_TYPE (right) == AOP_CRY)
3974 genModbits (left, right, result);
3978 /* if both are of size == 1 */
3979 if (AOP_SIZE (left) == 1 &&
3980 AOP_SIZE (right) == 1)
3982 genModOneByte (left, right, result);
3986 /* should have been converted to function call */
3990 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3991 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3992 freeAsmop (result, NULL, ic, TRUE);
3995 /*-----------------------------------------------------------------*/
3996 /* genIfxJump :- will create a jump depending on the ifx */
3997 /*-----------------------------------------------------------------*/
3999 genIfxJump (iCode * ic, char *jval)
4002 symbol *tlbl = newiTempLabel (NULL);
4005 D(emitcode ("; genIfxJump",""));
4007 /* if true label then we jump if condition
4011 jlbl = IC_TRUE (ic);
4012 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4013 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4017 /* false label is present */
4018 jlbl = IC_FALSE (ic);
4019 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4020 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4022 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4023 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4025 emitcode (inst, "%05d$", tlbl->key + 100);
4026 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4027 emitcode ("", "%05d$:", tlbl->key + 100);
4029 /* mark the icode as generated */
4033 /*-----------------------------------------------------------------*/
4034 /* genCmp :- greater or less than comparison */
4035 /*-----------------------------------------------------------------*/
4037 genCmp (operand * left, operand * right,
4038 operand * result, iCode * ifx, int sign, iCode *ic)
4040 int size, offset = 0;
4041 unsigned long lit = 0L;
4044 D(emitcode ("; genCmp",""));
4046 /* if left & right are bit variables */
4047 if (AOP_TYPE (left) == AOP_CRY &&
4048 AOP_TYPE (right) == AOP_CRY)
4050 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4051 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4055 /* subtract right from left if at the
4056 end the carry flag is set then we know that
4057 left is greater than right */
4058 size = max (AOP_SIZE (left), AOP_SIZE (right));
4060 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4061 if ((size == 1) && !sign &&
4062 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4064 symbol *lbl = newiTempLabel (NULL);
4065 emitcode ("cjne", "%s,%s,%05d$",
4066 aopGet (AOP (left), offset, FALSE, FALSE),
4067 aopGet (AOP (right), offset, FALSE, FALSE),
4069 emitcode ("", "%05d$:", lbl->key + 100);
4073 if (AOP_TYPE (right) == AOP_LIT)
4075 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4076 /* optimize if(x < 0) or if(x >= 0) */
4085 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4086 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4088 genIfxJump (ifx, "acc.7");
4092 emitcode ("rlc", "a");
4100 rightInB = aopGetUsesAcc(AOP (right), offset);
4102 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4103 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4104 if (sign && size == 0)
4106 emitcode ("xrl", "a,#0x80");
4107 if (AOP_TYPE (right) == AOP_LIT)
4109 unsigned long lit = (unsigned long)
4110 floatFromVal (AOP (right)->aopu.aop_lit);
4111 emitcode ("subb", "a,#0x%02x",
4112 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4117 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4118 emitcode ("xrl", "b,#0x80");
4119 emitcode ("subb", "a,b");
4125 emitcode ("subb", "a,b");
4127 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4135 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4136 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4137 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4143 /* if the result is used in the next
4144 ifx conditional branch then generate
4145 code a little differently */
4147 genIfxJump (ifx, "c");
4150 /* leave the result in acc */
4154 /*-----------------------------------------------------------------*/
4155 /* genCmpGt :- greater than comparison */
4156 /*-----------------------------------------------------------------*/
4158 genCmpGt (iCode * ic, iCode * ifx)
4160 operand *left, *right, *result;
4161 sym_link *letype, *retype;
4164 D(emitcode ("; genCmpGt",""));
4166 left = IC_LEFT (ic);
4167 right = IC_RIGHT (ic);
4168 result = IC_RESULT (ic);
4170 letype = getSpec (operandType (left));
4171 retype = getSpec (operandType (right));
4172 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4173 /* assign the amsops */
4174 aopOp (left, ic, FALSE);
4175 aopOp (right, ic, FALSE);
4176 aopOp (result, ic, TRUE);
4178 genCmp (right, left, result, ifx, sign,ic);
4180 freeAsmop (result, NULL, ic, TRUE);
4183 /*-----------------------------------------------------------------*/
4184 /* genCmpLt - less than comparisons */
4185 /*-----------------------------------------------------------------*/
4187 genCmpLt (iCode * ic, iCode * ifx)
4189 operand *left, *right, *result;
4190 sym_link *letype, *retype;
4193 D(emitcode ("; genCmpLt",""));
4195 left = IC_LEFT (ic);
4196 right = IC_RIGHT (ic);
4197 result = IC_RESULT (ic);
4199 letype = getSpec (operandType (left));
4200 retype = getSpec (operandType (right));
4201 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4203 /* assign the amsops */
4204 aopOp (left, ic, FALSE);
4205 aopOp (right, ic, FALSE);
4206 aopOp (result, ic, TRUE);
4208 genCmp (left, right, result, ifx, sign,ic);
4210 freeAsmop (result, NULL, ic, TRUE);
4213 /*-----------------------------------------------------------------*/
4214 /* gencjneshort - compare and jump if not equal */
4215 /*-----------------------------------------------------------------*/
4217 gencjneshort (operand * left, operand * right, symbol * lbl)
4219 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4221 unsigned long lit = 0L;
4223 /* if the left side is a literal or
4224 if the right is in a pointer register and left
4226 if ((AOP_TYPE (left) == AOP_LIT) ||
4227 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4233 if (AOP_TYPE (right) == AOP_LIT)
4234 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4236 /* if the right side is a literal then anything goes */
4237 if (AOP_TYPE (right) == AOP_LIT &&
4238 AOP_TYPE (left) != AOP_DIR &&
4239 AOP_TYPE (left) != AOP_IMMD)
4243 emitcode ("cjne", "%s,%s,%05d$",
4244 aopGet (AOP (left), offset, FALSE, FALSE),
4245 aopGet (AOP (right), offset, FALSE, FALSE),
4251 /* if the right side is in a register or in direct space or
4252 if the left is a pointer register & right is not */
4253 else if (AOP_TYPE (right) == AOP_REG ||
4254 AOP_TYPE (right) == AOP_DIR ||
4255 AOP_TYPE (right) == AOP_LIT ||
4256 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4257 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4261 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4262 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4263 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4264 emitcode ("jnz", "%05d$", lbl->key + 100);
4266 emitcode ("cjne", "a,%s,%05d$",
4267 aopGet (AOP (right), offset, FALSE, TRUE),
4274 /* right is a pointer reg need both a & b */
4277 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4278 if (strcmp (l, "b"))
4279 emitcode ("mov", "b,%s", l);
4280 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4281 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4287 /*-----------------------------------------------------------------*/
4288 /* gencjne - compare and jump if not equal */
4289 /*-----------------------------------------------------------------*/
4291 gencjne (operand * left, operand * right, symbol * lbl)
4293 symbol *tlbl = newiTempLabel (NULL);
4295 gencjneshort (left, right, lbl);
4297 emitcode ("mov", "a,%s", one);
4298 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4299 emitcode ("", "%05d$:", lbl->key + 100);
4300 emitcode ("clr", "a");
4301 emitcode ("", "%05d$:", tlbl->key + 100);
4304 /*-----------------------------------------------------------------*/
4305 /* genCmpEq - generates code for equal to */
4306 /*-----------------------------------------------------------------*/
4308 genCmpEq (iCode * ic, iCode * ifx)
4310 operand *left, *right, *result;
4312 D(emitcode ("; genCmpEq",""));
4314 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4315 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4316 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4318 /* if literal, literal on the right or
4319 if the right is in a pointer register and left
4321 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4322 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4324 operand *t = IC_RIGHT (ic);
4325 IC_RIGHT (ic) = IC_LEFT (ic);
4329 if (ifx && !AOP_SIZE (result))
4332 /* if they are both bit variables */
4333 if (AOP_TYPE (left) == AOP_CRY &&
4334 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4336 if (AOP_TYPE (right) == AOP_LIT)
4338 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4341 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4342 emitcode ("cpl", "c");
4346 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4350 emitcode ("clr", "c");
4352 /* AOP_TYPE(right) == AOP_CRY */
4356 symbol *lbl = newiTempLabel (NULL);
4357 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4358 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4359 emitcode ("cpl", "c");
4360 emitcode ("", "%05d$:", (lbl->key + 100));
4362 /* if true label then we jump if condition
4364 tlbl = newiTempLabel (NULL);
4367 emitcode ("jnc", "%05d$", tlbl->key + 100);
4368 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4372 emitcode ("jc", "%05d$", tlbl->key + 100);
4373 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4375 emitcode ("", "%05d$:", tlbl->key + 100);
4379 tlbl = newiTempLabel (NULL);
4380 gencjneshort (left, right, tlbl);
4383 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4384 emitcode ("", "%05d$:", tlbl->key + 100);
4388 symbol *lbl = newiTempLabel (NULL);
4389 emitcode ("sjmp", "%05d$", lbl->key + 100);
4390 emitcode ("", "%05d$:", tlbl->key + 100);
4391 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4392 emitcode ("", "%05d$:", lbl->key + 100);
4395 /* mark the icode as generated */
4400 /* if they are both bit variables */
4401 if (AOP_TYPE (left) == AOP_CRY &&
4402 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4404 if (AOP_TYPE (right) == AOP_LIT)
4406 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4409 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4410 emitcode ("cpl", "c");
4414 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4418 emitcode ("clr", "c");
4420 /* AOP_TYPE(right) == AOP_CRY */
4424 symbol *lbl = newiTempLabel (NULL);
4425 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4426 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4427 emitcode ("cpl", "c");
4428 emitcode ("", "%05d$:", (lbl->key + 100));
4431 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4438 genIfxJump (ifx, "c");
4441 /* if the result is used in an arithmetic operation
4442 then put the result in place */
4447 gencjne (left, right, newiTempLabel (NULL));
4448 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4450 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4455 genIfxJump (ifx, "a");
4458 /* if the result is used in an arithmetic operation
4459 then put the result in place */
4460 if (AOP_TYPE (result) != AOP_CRY)
4462 /* leave the result in acc */
4466 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4467 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4468 freeAsmop (result, NULL, ic, TRUE);
4471 /*-----------------------------------------------------------------*/
4472 /* ifxForOp - returns the icode containing the ifx for operand */
4473 /*-----------------------------------------------------------------*/
4475 ifxForOp (operand * op, iCode * ic)
4477 /* if true symbol then needs to be assigned */
4478 if (IS_TRUE_SYMOP (op))
4481 /* if this has register type condition and
4482 the next instruction is ifx with the same operand
4483 and live to of the operand is upto the ifx only then */
4485 ic->next->op == IFX &&
4486 IC_COND (ic->next)->key == op->key &&
4487 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4493 /*-----------------------------------------------------------------*/
4494 /* hasInc - operand is incremented before any other use */
4495 /*-----------------------------------------------------------------*/
4497 hasInc (operand *op, iCode *ic,int osize)
4499 sym_link *type = operandType(op);
4500 sym_link *retype = getSpec (type);
4501 iCode *lic = ic->next;
4504 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4505 if (!IS_SYMOP(op)) return NULL;
4507 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4508 if (IS_AGGREGATE(type->next)) return NULL;
4509 if (osize != (isize = getSize(type->next))) return NULL;
4512 /* if operand of the form op = op + <sizeof *op> */
4513 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4514 isOperandEqual(IC_RESULT(lic),op) &&
4515 isOperandLiteral(IC_RIGHT(lic)) &&
4516 operandLitValue(IC_RIGHT(lic)) == isize) {
4519 /* if the operand used or deffed */
4520 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4523 /* if GOTO or IFX */
4524 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4530 /*-----------------------------------------------------------------*/
4531 /* genAndOp - for && operation */
4532 /*-----------------------------------------------------------------*/
4534 genAndOp (iCode * ic)
4536 operand *left, *right, *result;
4539 D(emitcode ("; genAndOp",""));
4541 /* note here that && operations that are in an
4542 if statement are taken away by backPatchLabels
4543 only those used in arthmetic operations remain */
4544 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4545 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4546 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4548 /* if both are bit variables */
4549 if (AOP_TYPE (left) == AOP_CRY &&
4550 AOP_TYPE (right) == AOP_CRY)
4552 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4553 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4558 tlbl = newiTempLabel (NULL);
4560 emitcode ("jz", "%05d$", tlbl->key + 100);
4562 emitcode ("", "%05d$:", tlbl->key + 100);
4566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4567 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4568 freeAsmop (result, NULL, ic, TRUE);
4572 /*-----------------------------------------------------------------*/
4573 /* genOrOp - for || operation */
4574 /*-----------------------------------------------------------------*/
4576 genOrOp (iCode * ic)
4578 operand *left, *right, *result;
4581 D(emitcode ("; genOrOp",""));
4583 /* note here that || operations that are in an
4584 if statement are taken away by backPatchLabels
4585 only those used in arthmetic operations remain */
4586 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4587 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4588 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4590 /* if both are bit variables */
4591 if (AOP_TYPE (left) == AOP_CRY &&
4592 AOP_TYPE (right) == AOP_CRY)
4594 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4595 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4600 tlbl = newiTempLabel (NULL);
4602 emitcode ("jnz", "%05d$", tlbl->key + 100);
4604 emitcode ("", "%05d$:", tlbl->key + 100);
4608 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4609 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610 freeAsmop (result, NULL, ic, TRUE);
4613 /*-----------------------------------------------------------------*/
4614 /* isLiteralBit - test if lit == 2^n */
4615 /*-----------------------------------------------------------------*/
4617 isLiteralBit (unsigned long lit)
4619 unsigned long pw[32] =
4620 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4621 0x100L, 0x200L, 0x400L, 0x800L,
4622 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4623 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4624 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4625 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4626 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4629 for (idx = 0; idx < 32; idx++)
4635 /*-----------------------------------------------------------------*/
4636 /* continueIfTrue - */
4637 /*-----------------------------------------------------------------*/
4639 continueIfTrue (iCode * ic)
4642 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4646 /*-----------------------------------------------------------------*/
4648 /*-----------------------------------------------------------------*/
4650 jumpIfTrue (iCode * ic)
4653 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4657 /*-----------------------------------------------------------------*/
4658 /* jmpTrueOrFalse - */
4659 /*-----------------------------------------------------------------*/
4661 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4663 // ugly but optimized by peephole
4666 symbol *nlbl = newiTempLabel (NULL);
4667 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4668 emitcode ("", "%05d$:", tlbl->key + 100);
4669 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4670 emitcode ("", "%05d$:", nlbl->key + 100);
4674 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4675 emitcode ("", "%05d$:", tlbl->key + 100);
4680 /*-----------------------------------------------------------------*/
4681 /* genAnd - code for and */
4682 /*-----------------------------------------------------------------*/
4684 genAnd (iCode * ic, iCode * ifx)
4686 operand *left, *right, *result;
4687 int size, offset = 0;
4688 unsigned long lit = 0L;
4692 D(emitcode ("; genAnd",""));
4694 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4695 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4696 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4699 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4701 AOP_TYPE (left), AOP_TYPE (right));
4702 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4704 AOP_SIZE (left), AOP_SIZE (right));
4707 /* if left is a literal & right is not then exchange them */
4708 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4709 AOP_NEEDSACC (left))
4711 operand *tmp = right;
4716 /* if result = right then exchange them */
4717 if (sameRegs (AOP (result), AOP (right)))
4719 operand *tmp = right;
4724 /* if right is bit then exchange them */
4725 if (AOP_TYPE (right) == AOP_CRY &&
4726 AOP_TYPE (left) != AOP_CRY)
4728 operand *tmp = right;
4732 if (AOP_TYPE (right) == AOP_LIT)
4733 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4735 size = AOP_SIZE (result);
4738 // result = bit & yy;
4739 if (AOP_TYPE (left) == AOP_CRY)
4741 // c = bit & literal;
4742 if (AOP_TYPE (right) == AOP_LIT)
4746 if (size && sameRegs (AOP (result), AOP (left)))
4749 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4754 if (size && (AOP_TYPE (result) == AOP_CRY))
4756 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4759 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4764 emitcode ("clr", "c");
4769 if (AOP_TYPE (right) == AOP_CRY)
4772 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4773 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4778 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4780 emitcode ("rrc", "a");
4781 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4789 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4790 genIfxJump (ifx, "c");
4794 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4795 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4796 if ((AOP_TYPE (right) == AOP_LIT) &&
4797 (AOP_TYPE (result) == AOP_CRY) &&
4798 (AOP_TYPE (left) != AOP_CRY))
4800 int posbit = isLiteralBit (lit);
4805 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4808 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4814 sprintf (buffer, "acc.%d", posbit & 0x07);
4815 genIfxJump (ifx, buffer);
4822 symbol *tlbl = newiTempLabel (NULL);
4823 int sizel = AOP_SIZE (left);
4825 emitcode ("setb", "c");
4828 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4830 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4832 if ((posbit = isLiteralBit (bytelit)) != 0)
4833 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4836 if (bytelit != 0x0FFL)
4837 emitcode ("anl", "a,%s",
4838 aopGet (AOP (right), offset, FALSE, TRUE));
4839 emitcode ("jnz", "%05d$", tlbl->key + 100);
4844 // bit = left & literal
4847 emitcode ("clr", "c");
4848 emitcode ("", "%05d$:", tlbl->key + 100);
4850 // if(left & literal)
4854 jmpTrueOrFalse (ifx, tlbl);
4862 /* if left is same as result */
4863 if (sameRegs (AOP (result), AOP (left)))
4865 for (; size--; offset++)
4867 if (AOP_TYPE (right) == AOP_LIT)
4869 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4871 else if (bytelit == 0)
4873 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4875 else if (IS_AOP_PREG (result))
4877 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4878 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4879 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4882 emitcode ("anl", "%s,%s",
4883 aopGet (AOP (left), offset, FALSE, TRUE),
4884 aopGet (AOP (right), offset, FALSE, FALSE));
4888 if (AOP_TYPE (left) == AOP_ACC)
4889 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4892 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4893 if (IS_AOP_PREG (result))
4895 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4896 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4900 emitcode ("anl", "%s,a",
4901 aopGet (AOP (left), offset, FALSE, TRUE));
4908 // left & result in different registers
4909 if (AOP_TYPE (result) == AOP_CRY)
4912 // if(size), result in bit
4913 // if(!size && ifx), conditional oper: if(left & right)
4914 symbol *tlbl = newiTempLabel (NULL);
4915 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4917 emitcode ("setb", "c");
4920 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4921 emitcode ("anl", "a,%s",
4922 aopGet (AOP (right), offset, FALSE, FALSE));
4924 if (AOP_TYPE(left)==AOP_ACC) {
4925 emitcode("mov", "b,a");
4926 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4927 emitcode("anl", "a,b");
4929 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4930 emitcode ("anl", "a,%s",
4931 aopGet (AOP (left), offset, FALSE, FALSE));
4934 emitcode ("jnz", "%05d$", tlbl->key + 100);
4940 emitcode ("", "%05d$:", tlbl->key + 100);
4944 jmpTrueOrFalse (ifx, tlbl);
4948 for (; (size--); offset++)
4951 // result = left & right
4952 if (AOP_TYPE (right) == AOP_LIT)
4954 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4956 aopPut (AOP (result),
4957 aopGet (AOP (left), offset, FALSE, FALSE),
4959 isOperandVolatile (result, FALSE));
4962 else if (bytelit == 0)
4964 /* dummy read of volatile operand */
4965 if (isOperandVolatile (left, FALSE))
4966 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4967 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4971 // faster than result <- left, anl result,right
4972 // and better if result is SFR
4973 if (AOP_TYPE (left) == AOP_ACC)
4974 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4977 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4978 emitcode ("anl", "a,%s",
4979 aopGet (AOP (left), offset, FALSE, FALSE));
4981 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4987 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4988 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4989 freeAsmop (result, NULL, ic, TRUE);
4992 /*-----------------------------------------------------------------*/
4993 /* genOr - code for or */
4994 /*-----------------------------------------------------------------*/
4996 genOr (iCode * ic, iCode * ifx)
4998 operand *left, *right, *result;
4999 int size, offset = 0;
5000 unsigned long lit = 0L;
5002 D(emitcode ("; genOr",""));
5004 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5005 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5006 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5009 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5011 AOP_TYPE (left), AOP_TYPE (right));
5012 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5014 AOP_SIZE (left), AOP_SIZE (right));
5017 /* if left is a literal & right is not then exchange them */
5018 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5019 AOP_NEEDSACC (left))
5021 operand *tmp = right;
5026 /* if result = right then exchange them */
5027 if (sameRegs (AOP (result), AOP (right)))
5029 operand *tmp = right;
5034 /* if right is bit then exchange them */
5035 if (AOP_TYPE (right) == AOP_CRY &&
5036 AOP_TYPE (left) != AOP_CRY)
5038 operand *tmp = right;
5042 if (AOP_TYPE (right) == AOP_LIT)
5043 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5045 size = AOP_SIZE (result);
5049 if (AOP_TYPE (left) == AOP_CRY)
5051 if (AOP_TYPE (right) == AOP_LIT)
5053 // c = bit | literal;
5056 // lit != 0 => result = 1
5057 if (AOP_TYPE (result) == AOP_CRY)
5060 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5062 continueIfTrue (ifx);
5065 emitcode ("setb", "c");
5069 // lit == 0 => result = left
5070 if (size && sameRegs (AOP (result), AOP (left)))
5072 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5077 if (AOP_TYPE (right) == AOP_CRY)
5080 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5081 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5086 symbol *tlbl = newiTempLabel (NULL);
5087 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5088 emitcode ("setb", "c");
5089 emitcode ("jb", "%s,%05d$",
5090 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5092 emitcode ("jnz", "%05d$", tlbl->key + 100);
5093 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5095 jmpTrueOrFalse (ifx, tlbl);
5101 emitcode ("", "%05d$:", tlbl->key + 100);
5110 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5111 genIfxJump (ifx, "c");
5115 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5116 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5117 if ((AOP_TYPE (right) == AOP_LIT) &&
5118 (AOP_TYPE (result) == AOP_CRY) &&
5119 (AOP_TYPE (left) != AOP_CRY))
5125 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5127 continueIfTrue (ifx);
5132 // lit = 0, result = boolean(left)
5134 emitcode ("setb", "c");
5138 symbol *tlbl = newiTempLabel (NULL);
5139 emitcode ("jnz", "%05d$", tlbl->key + 100);
5141 emitcode ("", "%05d$:", tlbl->key + 100);
5145 genIfxJump (ifx, "a");
5153 /* if left is same as result */
5154 if (sameRegs (AOP (result), AOP (left)))
5156 for (; size--; offset++)
5158 if (AOP_TYPE (right) == AOP_LIT)
5160 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5162 /* dummy read of volatile operand */
5163 if (isOperandVolatile (left, FALSE))
5164 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5168 else if (IS_AOP_PREG (left))
5170 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5171 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5172 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5175 emitcode ("orl", "%s,%s",
5176 aopGet (AOP (left), offset, FALSE, TRUE),
5177 aopGet (AOP (right), offset, FALSE, FALSE));
5181 if (AOP_TYPE (left) == AOP_ACC)
5182 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5185 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5186 if (IS_AOP_PREG (left))
5188 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5189 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5192 emitcode ("orl", "%s,a",
5193 aopGet (AOP (left), offset, FALSE, TRUE));
5200 // left & result in different registers
5201 if (AOP_TYPE (result) == AOP_CRY)
5204 // if(size), result in bit
5205 // if(!size && ifx), conditional oper: if(left | right)
5206 symbol *tlbl = newiTempLabel (NULL);
5207 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5209 emitcode ("setb", "c");
5212 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5213 emitcode ("orl", "a,%s",
5214 aopGet (AOP (right), offset, FALSE, FALSE));
5216 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5217 emitcode ("orl", "a,%s",
5218 aopGet (AOP (left), offset, FALSE, FALSE));
5220 emitcode ("jnz", "%05d$", tlbl->key + 100);
5226 emitcode ("", "%05d$:", tlbl->key + 100);
5230 jmpTrueOrFalse (ifx, tlbl);
5233 for (; (size--); offset++)
5236 // result = left & right
5237 if (AOP_TYPE (right) == AOP_LIT)
5239 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5241 aopPut (AOP (result),
5242 aopGet (AOP (left), offset, FALSE, FALSE),
5244 isOperandVolatile (result, FALSE));
5248 // faster than result <- left, anl result,right
5249 // and better if result is SFR
5250 if (AOP_TYPE (left) == AOP_ACC)
5251 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5254 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5255 emitcode ("orl", "a,%s",
5256 aopGet (AOP (left), offset, FALSE, FALSE));
5258 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5263 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5264 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5265 freeAsmop (result, NULL, ic, TRUE);
5268 /*-----------------------------------------------------------------*/
5269 /* genXor - code for xclusive or */
5270 /*-----------------------------------------------------------------*/
5272 genXor (iCode * ic, iCode * ifx)
5274 operand *left, *right, *result;
5275 int size, offset = 0;
5276 unsigned long lit = 0L;
5278 D(emitcode ("; genXor",""));
5280 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5281 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5282 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5285 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5287 AOP_TYPE (left), AOP_TYPE (right));
5288 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5290 AOP_SIZE (left), AOP_SIZE (right));
5293 /* if left is a literal & right is not ||
5294 if left needs acc & right does not */
5295 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5296 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5298 operand *tmp = right;
5303 /* if result = right then exchange them */
5304 if (sameRegs (AOP (result), AOP (right)))
5306 operand *tmp = right;
5311 /* if right is bit then exchange them */
5312 if (AOP_TYPE (right) == AOP_CRY &&
5313 AOP_TYPE (left) != AOP_CRY)
5315 operand *tmp = right;
5319 if (AOP_TYPE (right) == AOP_LIT)
5320 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5322 size = AOP_SIZE (result);
5326 if (AOP_TYPE (left) == AOP_CRY)
5328 if (AOP_TYPE (right) == AOP_LIT)
5330 // c = bit & literal;
5333 // lit>>1 != 0 => result = 1
5334 if (AOP_TYPE (result) == AOP_CRY)
5337 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5339 continueIfTrue (ifx);
5342 emitcode ("setb", "c");
5349 // lit == 0, result = left
5350 if (size && sameRegs (AOP (result), AOP (left)))
5352 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5356 // lit == 1, result = not(left)
5357 if (size && sameRegs (AOP (result), AOP (left)))
5359 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5364 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5365 emitcode ("cpl", "c");
5374 symbol *tlbl = newiTempLabel (NULL);
5375 if (AOP_TYPE (right) == AOP_CRY)
5378 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5382 int sizer = AOP_SIZE (right);
5384 // if val>>1 != 0, result = 1
5385 emitcode ("setb", "c");
5388 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5390 // test the msb of the lsb
5391 emitcode ("anl", "a,#0xfe");
5392 emitcode ("jnz", "%05d$", tlbl->key + 100);
5396 emitcode ("rrc", "a");
5398 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5399 emitcode ("cpl", "c");
5400 emitcode ("", "%05d$:", (tlbl->key + 100));
5407 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5408 genIfxJump (ifx, "c");
5412 if (sameRegs (AOP (result), AOP (left)))
5414 /* if left is same as result */
5415 for (; size--; offset++)
5417 if (AOP_TYPE (right) == AOP_LIT)
5419 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5421 else if (IS_AOP_PREG (left))
5423 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5424 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5425 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5428 emitcode ("xrl", "%s,%s",
5429 aopGet (AOP (left), offset, FALSE, TRUE),
5430 aopGet (AOP (right), offset, FALSE, FALSE));
5434 if (AOP_TYPE (left) == AOP_ACC)
5435 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5438 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5439 if (IS_AOP_PREG (left))
5441 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5442 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5445 emitcode ("xrl", "%s,a",
5446 aopGet (AOP (left), offset, FALSE, TRUE));
5453 // left & result in different registers
5454 if (AOP_TYPE (result) == AOP_CRY)
5457 // if(size), result in bit
5458 // if(!size && ifx), conditional oper: if(left ^ right)
5459 symbol *tlbl = newiTempLabel (NULL);
5460 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5462 emitcode ("setb", "c");
5465 if ((AOP_TYPE (right) == AOP_LIT) &&
5466 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5468 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5472 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5473 emitcode ("xrl", "a,%s",
5474 aopGet (AOP (right), offset, FALSE, FALSE));
5476 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5477 emitcode ("xrl", "a,%s",
5478 aopGet (AOP (left), offset, FALSE, FALSE));
5481 emitcode ("jnz", "%05d$", tlbl->key + 100);
5487 emitcode ("", "%05d$:", tlbl->key + 100);
5491 jmpTrueOrFalse (ifx, tlbl);
5494 for (; (size--); offset++)
5497 // result = left & right
5498 if (AOP_TYPE (right) == AOP_LIT)
5500 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5502 aopPut (AOP (result),
5503 aopGet (AOP (left), offset, FALSE, FALSE),
5505 isOperandVolatile (result, FALSE));
5509 // faster than result <- left, anl result,right
5510 // and better if result is SFR
5511 if (AOP_TYPE (left) == AOP_ACC)
5512 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5515 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5516 emitcode ("xrl", "a,%s",
5517 aopGet (AOP (left), offset, FALSE, TRUE));
5519 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5524 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5525 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 freeAsmop (result, NULL, ic, TRUE);
5529 /*-----------------------------------------------------------------*/
5530 /* genInline - write the inline code out */
5531 /*-----------------------------------------------------------------*/
5533 genInline (iCode * ic)
5535 char *buffer, *bp, *bp1;
5537 D(emitcode ("; genInline",""));
5539 _G.inLine += (!options.asmpeep);
5541 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5542 strcpy (buffer, IC_INLINE (ic));
5544 /* emit each line as a code */
5569 /* emitcode("",buffer); */
5570 _G.inLine -= (!options.asmpeep);
5573 /*-----------------------------------------------------------------*/
5574 /* genRRC - rotate right with carry */
5575 /*-----------------------------------------------------------------*/
5579 operand *left, *result;
5580 int size, offset = 0;
5583 D(emitcode ("; genRRC",""));
5585 /* rotate right with carry */
5586 left = IC_LEFT (ic);
5587 result = IC_RESULT (ic);
5588 aopOp (left, ic, FALSE);
5589 aopOp (result, ic, FALSE);
5591 /* move it to the result */
5592 size = AOP_SIZE (result);
5594 if (size == 1) { /* special case for 1 byte */
5595 l = aopGet (AOP (left), offset, FALSE, FALSE);
5597 emitcode ("rr", "a");
5603 l = aopGet (AOP (left), offset, FALSE, FALSE);
5605 emitcode ("rrc", "a");
5606 if (AOP_SIZE (result) > 1)
5607 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5609 /* now we need to put the carry into the
5610 highest order byte of the result */
5611 if (AOP_SIZE (result) > 1)
5613 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5616 emitcode ("mov", "acc.7,c");
5618 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5619 freeAsmop (left, NULL, ic, TRUE);
5620 freeAsmop (result, NULL, ic, TRUE);
5623 /*-----------------------------------------------------------------*/
5624 /* genRLC - generate code for rotate left with carry */
5625 /*-----------------------------------------------------------------*/
5629 operand *left, *result;
5630 int size, offset = 0;
5633 D(emitcode ("; genRLC",""));
5635 /* rotate right with carry */
5636 left = IC_LEFT (ic);
5637 result = IC_RESULT (ic);
5638 aopOp (left, ic, FALSE);
5639 aopOp (result, ic, FALSE);
5641 /* move it to the result */
5642 size = AOP_SIZE (result);
5646 l = aopGet (AOP (left), offset, FALSE, FALSE);
5648 if (size == 0) { /* special case for 1 byte */
5652 emitcode ("add", "a,acc");
5653 if (AOP_SIZE (result) > 1)
5654 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5657 l = aopGet (AOP (left), offset, FALSE, FALSE);
5659 emitcode ("rlc", "a");
5660 if (AOP_SIZE (result) > 1)
5661 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5664 /* now we need to put the carry into the
5665 highest order byte of the result */
5666 if (AOP_SIZE (result) > 1)
5668 l = aopGet (AOP (result), 0, FALSE, FALSE);
5671 emitcode ("mov", "acc.0,c");
5673 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5674 freeAsmop (left, NULL, ic, TRUE);
5675 freeAsmop (result, NULL, ic, TRUE);
5678 /*-----------------------------------------------------------------*/
5679 /* genGetHbit - generates code get highest order bit */
5680 /*-----------------------------------------------------------------*/
5682 genGetHbit (iCode * ic)
5684 operand *left, *result;
5686 D(emitcode ("; genGetHbit",""));
5688 left = IC_LEFT (ic);
5689 result = IC_RESULT (ic);
5690 aopOp (left, ic, FALSE);
5691 aopOp (result, ic, FALSE);
5693 /* get the highest order byte into a */
5694 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5695 if (AOP_TYPE (result) == AOP_CRY)
5697 emitcode ("rlc", "a");
5702 emitcode ("rl", "a");
5703 emitcode ("anl", "a,#0x01");
5708 freeAsmop (left, NULL, ic, TRUE);
5709 freeAsmop (result, NULL, ic, TRUE);
5712 /*-----------------------------------------------------------------*/
5713 /* AccRol - rotate left accumulator by known count */
5714 /*-----------------------------------------------------------------*/
5716 AccRol (int shCount)
5718 shCount &= 0x0007; // shCount : 0..7
5725 emitcode ("rl", "a");
5728 emitcode ("rl", "a");
5729 emitcode ("rl", "a");
5732 emitcode ("swap", "a");
5733 emitcode ("rr", "a");
5736 emitcode ("swap", "a");
5739 emitcode ("swap", "a");
5740 emitcode ("rl", "a");
5743 emitcode ("rr", "a");
5744 emitcode ("rr", "a");
5747 emitcode ("rr", "a");
5752 /*-----------------------------------------------------------------*/
5753 /* AccLsh - left shift accumulator by known count */
5754 /*-----------------------------------------------------------------*/
5756 AccLsh (int shCount)
5761 emitcode ("add", "a,acc");
5762 else if (shCount == 2)
5764 emitcode ("add", "a,acc");
5765 emitcode ("add", "a,acc");
5769 /* rotate left accumulator */
5771 /* and kill the lower order bits */
5772 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5777 /*-----------------------------------------------------------------*/
5778 /* AccRsh - right shift accumulator by known count */
5779 /*-----------------------------------------------------------------*/
5781 AccRsh (int shCount)
5788 emitcode ("rrc", "a");
5792 /* rotate right accumulator */
5793 AccRol (8 - shCount);
5794 /* and kill the higher order bits */
5795 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5800 /*-----------------------------------------------------------------*/
5801 /* AccSRsh - signed right shift accumulator by known count */
5802 /*-----------------------------------------------------------------*/
5804 AccSRsh (int shCount)
5811 emitcode ("mov", "c,acc.7");
5812 emitcode ("rrc", "a");
5814 else if (shCount == 2)
5816 emitcode ("mov", "c,acc.7");
5817 emitcode ("rrc", "a");
5818 emitcode ("mov", "c,acc.7");
5819 emitcode ("rrc", "a");
5823 tlbl = newiTempLabel (NULL);
5824 /* rotate right accumulator */
5825 AccRol (8 - shCount);
5826 /* and kill the higher order bits */
5827 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5828 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5829 emitcode ("orl", "a,#0x%02x",
5830 (unsigned char) ~SRMask[shCount]);
5831 emitcode ("", "%05d$:", tlbl->key + 100);
5836 /*-----------------------------------------------------------------*/
5837 /* shiftR1Left2Result - shift right one byte from left to result */
5838 /*-----------------------------------------------------------------*/
5840 shiftR1Left2Result (operand * left, int offl,
5841 operand * result, int offr,
5842 int shCount, int sign)
5844 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5845 /* shift right accumulator */
5850 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5853 /*-----------------------------------------------------------------*/
5854 /* shiftL1Left2Result - shift left one byte from left to result */
5855 /*-----------------------------------------------------------------*/
5857 shiftL1Left2Result (operand * left, int offl,
5858 operand * result, int offr, int shCount)
5861 l = aopGet (AOP (left), offl, FALSE, FALSE);
5863 /* shift left accumulator */
5865 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5868 /*-----------------------------------------------------------------*/
5869 /* movLeft2Result - move byte from left to result */
5870 /*-----------------------------------------------------------------*/
5872 movLeft2Result (operand * left, int offl,
5873 operand * result, int offr, int sign)
5876 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5878 l = aopGet (AOP (left), offl, FALSE, FALSE);
5880 if (*l == '@' && (IS_AOP_PREG (result)))
5882 emitcode ("mov", "a,%s", l);
5883 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5888 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5891 /* MSB sign in acc.7 ! */
5892 if (getDataSize (left) == offl + 1)
5894 emitcode ("mov", "a,%s", l);
5895 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5902 /*-----------------------------------------------------------------*/
5903 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5904 /*-----------------------------------------------------------------*/
5908 emitcode ("rrc", "a");
5909 emitcode ("xch", "a,%s", x);
5910 emitcode ("rrc", "a");
5911 emitcode ("xch", "a,%s", x);
5914 /*-----------------------------------------------------------------*/
5915 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5916 /*-----------------------------------------------------------------*/
5920 emitcode ("xch", "a,%s", x);
5921 emitcode ("rlc", "a");
5922 emitcode ("xch", "a,%s", x);
5923 emitcode ("rlc", "a");
5926 /*-----------------------------------------------------------------*/
5927 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5928 /*-----------------------------------------------------------------*/
5932 emitcode ("xch", "a,%s", x);
5933 emitcode ("add", "a,acc");
5934 emitcode ("xch", "a,%s", x);
5935 emitcode ("rlc", "a");
5938 /*-----------------------------------------------------------------*/
5939 /* AccAXLsh - left shift a:x by known count (0..7) */
5940 /*-----------------------------------------------------------------*/
5942 AccAXLsh (char *x, int shCount)
5957 case 5: // AAAAABBB:CCCCCDDD
5959 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5961 emitcode ("anl", "a,#0x%02x",
5962 SLMask[shCount]); // BBB00000:CCCCCDDD
5964 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5966 AccRol (shCount); // DDDCCCCC:BBB00000
5968 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5970 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5972 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5974 emitcode ("anl", "a,#0x%02x",
5975 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5977 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5979 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5982 case 6: // AAAAAABB:CCCCCCDD
5983 emitcode ("anl", "a,#0x%02x",
5984 SRMask[shCount]); // 000000BB:CCCCCCDD
5985 emitcode ("mov", "c,acc.0"); // c = B
5986 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5988 AccAXRrl1 (x); // BCCCCCCD:D000000B
5989 AccAXRrl1 (x); // BBCCCCCC:DD000000
5991 emitcode("rrc","a");
5992 emitcode("xch","a,%s", x);
5993 emitcode("rrc","a");
5994 emitcode("mov","c,acc.0"); //<< get correct bit
5995 emitcode("xch","a,%s", x);
5997 emitcode("rrc","a");
5998 emitcode("xch","a,%s", x);
5999 emitcode("rrc","a");
6000 emitcode("xch","a,%s", x);
6003 case 7: // a:x <<= 7
6005 emitcode ("anl", "a,#0x%02x",
6006 SRMask[shCount]); // 0000000B:CCCCCCCD
6008 emitcode ("mov", "c,acc.0"); // c = B
6010 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6012 AccAXRrl1 (x); // BCCCCCCC:D0000000
6020 /*-----------------------------------------------------------------*/
6021 /* AccAXRsh - right shift a:x known count (0..7) */
6022 /*-----------------------------------------------------------------*/
6024 AccAXRsh (char *x, int shCount)
6032 AccAXRrl1 (x); // 0->a:x
6037 AccAXRrl1 (x); // 0->a:x
6040 AccAXRrl1 (x); // 0->a:x
6045 case 5: // AAAAABBB:CCCCCDDD = a:x
6047 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6049 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6051 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6053 emitcode ("anl", "a,#0x%02x",
6054 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6056 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6058 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6060 emitcode ("anl", "a,#0x%02x",
6061 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6063 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6065 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6067 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6070 case 6: // AABBBBBB:CCDDDDDD
6072 emitcode ("mov", "c,acc.7");
6073 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6075 emitcode ("mov", "c,acc.7");
6076 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6078 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6080 emitcode ("anl", "a,#0x%02x",
6081 SRMask[shCount]); // 000000AA:BBBBBBCC
6084 case 7: // ABBBBBBB:CDDDDDDD
6086 emitcode ("mov", "c,acc.7"); // c = A
6088 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6090 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6092 emitcode ("anl", "a,#0x%02x",
6093 SRMask[shCount]); // 0000000A:BBBBBBBC
6101 /*-----------------------------------------------------------------*/
6102 /* AccAXRshS - right shift signed a:x known count (0..7) */
6103 /*-----------------------------------------------------------------*/
6105 AccAXRshS (char *x, int shCount)
6113 emitcode ("mov", "c,acc.7");
6114 AccAXRrl1 (x); // s->a:x
6118 emitcode ("mov", "c,acc.7");
6119 AccAXRrl1 (x); // s->a:x
6121 emitcode ("mov", "c,acc.7");
6122 AccAXRrl1 (x); // s->a:x
6127 case 5: // AAAAABBB:CCCCCDDD = a:x
6129 tlbl = newiTempLabel (NULL);
6130 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6132 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6134 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6136 emitcode ("anl", "a,#0x%02x",
6137 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6139 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6141 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6143 emitcode ("anl", "a,#0x%02x",
6144 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6146 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6148 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6150 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6152 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6153 emitcode ("orl", "a,#0x%02x",
6154 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6156 emitcode ("", "%05d$:", tlbl->key + 100);
6157 break; // SSSSAAAA:BBBCCCCC
6159 case 6: // AABBBBBB:CCDDDDDD
6161 tlbl = newiTempLabel (NULL);
6162 emitcode ("mov", "c,acc.7");
6163 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6165 emitcode ("mov", "c,acc.7");
6166 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6168 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6170 emitcode ("anl", "a,#0x%02x",
6171 SRMask[shCount]); // 000000AA:BBBBBBCC
6173 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6174 emitcode ("orl", "a,#0x%02x",
6175 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6177 emitcode ("", "%05d$:", tlbl->key + 100);
6179 case 7: // ABBBBBBB:CDDDDDDD
6181 tlbl = newiTempLabel (NULL);
6182 emitcode ("mov", "c,acc.7"); // c = A
6184 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6186 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6188 emitcode ("anl", "a,#0x%02x",
6189 SRMask[shCount]); // 0000000A:BBBBBBBC
6191 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6192 emitcode ("orl", "a,#0x%02x",
6193 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6195 emitcode ("", "%05d$:", tlbl->key + 100);
6202 /*-----------------------------------------------------------------*/
6203 /* shiftL2Left2Result - shift left two bytes from left to result */
6204 /*-----------------------------------------------------------------*/
6206 shiftL2Left2Result (operand * left, int offl,
6207 operand * result, int offr, int shCount)
6209 if (sameRegs (AOP (result), AOP (left)) &&
6210 ((offl + MSB16) == offr))
6212 /* don't crash result[offr] */
6213 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6214 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6218 movLeft2Result (left, offl, result, offr, 0);
6219 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6221 /* ax << shCount (x = lsb(result)) */
6222 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6223 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6227 /*-----------------------------------------------------------------*/
6228 /* shiftR2Left2Result - shift right two bytes from left to result */
6229 /*-----------------------------------------------------------------*/
6231 shiftR2Left2Result (operand * left, int offl,
6232 operand * result, int offr,
6233 int shCount, int sign)
6235 if (sameRegs (AOP (result), AOP (left)) &&
6236 ((offl + MSB16) == offr))
6238 /* don't crash result[offr] */
6239 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6240 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6244 movLeft2Result (left, offl, result, offr, 0);
6245 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6247 /* a:x >> shCount (x = lsb(result)) */
6249 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6251 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6252 if (getDataSize (result) > 1)
6253 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6256 /*-----------------------------------------------------------------*/
6257 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6258 /*-----------------------------------------------------------------*/
6260 shiftLLeftOrResult (operand * left, int offl,
6261 operand * result, int offr, int shCount)
6263 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6264 /* shift left accumulator */
6266 /* or with result */
6267 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6268 /* back to result */
6269 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6272 /*-----------------------------------------------------------------*/
6273 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6274 /*-----------------------------------------------------------------*/
6276 shiftRLeftOrResult (operand * left, int offl,
6277 operand * result, int offr, int shCount)
6279 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6280 /* shift right accumulator */
6282 /* or with result */
6283 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6284 /* back to result */
6285 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6288 /*-----------------------------------------------------------------*/
6289 /* genlshOne - left shift a one byte quantity by known count */
6290 /*-----------------------------------------------------------------*/
6292 genlshOne (operand * result, operand * left, int shCount)
6294 D(emitcode ("; genlshOne",""));
6296 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6299 /*-----------------------------------------------------------------*/
6300 /* genlshTwo - left shift two bytes by known amount != 0 */
6301 /*-----------------------------------------------------------------*/
6303 genlshTwo (operand * result, operand * left, int shCount)
6307 D(emitcode ("; genlshTwo",""));
6309 size = getDataSize (result);
6311 /* if shCount >= 8 */
6319 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6321 movLeft2Result (left, LSB, result, MSB16, 0);
6323 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6326 /* 1 <= shCount <= 7 */
6330 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6332 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6336 /*-----------------------------------------------------------------*/
6337 /* shiftLLong - shift left one long from left to result */
6338 /* offl = LSB or MSB16 */
6339 /*-----------------------------------------------------------------*/
6341 shiftLLong (operand * left, operand * result, int offr)
6344 int size = AOP_SIZE (result);
6346 if (size >= LSB + offr)
6348 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6350 emitcode ("add", "a,acc");
6351 if (sameRegs (AOP (left), AOP (result)) &&
6352 size >= MSB16 + offr && offr != LSB)
6353 emitcode ("xch", "a,%s",
6354 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6356 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6359 if (size >= MSB16 + offr)
6361 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6363 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6366 emitcode ("rlc", "a");
6367 if (sameRegs (AOP (left), AOP (result)) &&
6368 size >= MSB24 + offr && offr != LSB)
6369 emitcode ("xch", "a,%s",
6370 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6372 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6375 if (size >= MSB24 + offr)
6377 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6379 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6382 emitcode ("rlc", "a");
6383 if (sameRegs (AOP (left), AOP (result)) &&
6384 size >= MSB32 + offr && offr != LSB)
6385 emitcode ("xch", "a,%s",
6386 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6388 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6391 if (size > MSB32 + offr)
6393 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6395 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6398 emitcode ("rlc", "a");
6399 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6402 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6405 /*-----------------------------------------------------------------*/
6406 /* genlshFour - shift four byte by a known amount != 0 */
6407 /*-----------------------------------------------------------------*/
6409 genlshFour (operand * result, operand * left, int shCount)
6413 D(emitcode ("; genlshFour",""));
6415 size = AOP_SIZE (result);
6417 /* if shifting more that 3 bytes */
6422 /* lowest order of left goes to the highest
6423 order of the destination */
6424 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6426 movLeft2Result (left, LSB, result, MSB32, 0);
6427 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6428 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6429 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6433 /* more than two bytes */
6434 else if (shCount >= 16)
6436 /* lower order two bytes goes to higher order two bytes */
6438 /* if some more remaining */
6440 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6443 movLeft2Result (left, MSB16, result, MSB32, 0);
6444 movLeft2Result (left, LSB, result, MSB24, 0);
6446 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6447 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6451 /* if more than 1 byte */
6452 else if (shCount >= 8)
6454 /* lower order three bytes goes to higher order three bytes */
6459 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6461 movLeft2Result (left, LSB, result, MSB16, 0);
6467 movLeft2Result (left, MSB24, result, MSB32, 0);
6468 movLeft2Result (left, MSB16, result, MSB24, 0);
6469 movLeft2Result (left, LSB, result, MSB16, 0);
6470 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6472 else if (shCount == 1)
6473 shiftLLong (left, result, MSB16);
6476 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6477 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6478 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6479 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6484 /* 1 <= shCount <= 7 */
6485 else if (shCount <= 2)
6487 shiftLLong (left, result, LSB);
6489 shiftLLong (result, result, LSB);
6491 /* 3 <= shCount <= 7, optimize */
6494 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6495 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6496 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6500 /*-----------------------------------------------------------------*/
6501 /* genLeftShiftLiteral - left shifting by known count */
6502 /*-----------------------------------------------------------------*/
6504 genLeftShiftLiteral (operand * left,
6509 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6512 D(emitcode ("; genLeftShiftLiteral",""));
6514 freeAsmop (right, NULL, ic, TRUE);
6516 aopOp (left, ic, FALSE);
6517 aopOp (result, ic, FALSE);
6519 size = getSize (operandType (result));
6522 emitcode ("; shift left ", "result %d, left %d", size,
6526 /* I suppose that the left size >= result size */
6531 movLeft2Result (left, size, result, size, 0);
6535 else if (shCount >= (size * 8))
6537 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6543 genlshOne (result, left, shCount);
6547 genlshTwo (result, left, shCount);
6551 genlshFour (result, left, shCount);
6554 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6555 "*** ack! mystery literal shift!\n");
6559 freeAsmop (left, NULL, ic, TRUE);
6560 freeAsmop (result, NULL, ic, TRUE);
6563 /*-----------------------------------------------------------------*/
6564 /* genLeftShift - generates code for left shifting */
6565 /*-----------------------------------------------------------------*/
6567 genLeftShift (iCode * ic)
6569 operand *left, *right, *result;
6572 symbol *tlbl, *tlbl1;
6574 D(emitcode ("; genLeftShift",""));
6576 right = IC_RIGHT (ic);
6577 left = IC_LEFT (ic);
6578 result = IC_RESULT (ic);
6580 aopOp (right, ic, FALSE);
6582 /* if the shift count is known then do it
6583 as efficiently as possible */
6584 if (AOP_TYPE (right) == AOP_LIT)
6586 genLeftShiftLiteral (left, right, result, ic);
6590 /* shift count is unknown then we have to form
6591 a loop get the loop count in B : Note: we take
6592 only the lower order byte since shifting
6593 more that 32 bits make no sense anyway, ( the
6594 largest size of an object can be only 32 bits ) */
6596 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6597 emitcode ("inc", "b");
6598 freeAsmop (right, NULL, ic, TRUE);
6599 aopOp (left, ic, FALSE);
6600 aopOp (result, ic, FALSE);
6602 /* now move the left to the result if they are not the
6604 if (!sameRegs (AOP (left), AOP (result)) &&
6605 AOP_SIZE (result) > 1)
6608 size = AOP_SIZE (result);
6612 l = aopGet (AOP (left), offset, FALSE, TRUE);
6613 if (*l == '@' && (IS_AOP_PREG (result)))
6616 emitcode ("mov", "a,%s", l);
6617 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6620 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6625 tlbl = newiTempLabel (NULL);
6626 size = AOP_SIZE (result);
6628 tlbl1 = newiTempLabel (NULL);
6630 /* if it is only one byte then */
6633 symbol *tlbl1 = newiTempLabel (NULL);
6635 l = aopGet (AOP (left), 0, FALSE, FALSE);
6637 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6638 emitcode ("", "%05d$:", tlbl->key + 100);
6639 emitcode ("add", "a,acc");
6640 emitcode ("", "%05d$:", tlbl1->key + 100);
6641 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6642 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6646 reAdjustPreg (AOP (result));
6648 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6649 emitcode ("", "%05d$:", tlbl->key + 100);
6650 l = aopGet (AOP (result), offset, FALSE, FALSE);
6652 emitcode ("add", "a,acc");
6653 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6656 l = aopGet (AOP (result), offset, FALSE, FALSE);
6658 emitcode ("rlc", "a");
6659 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6661 reAdjustPreg (AOP (result));
6663 emitcode ("", "%05d$:", tlbl1->key + 100);
6664 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6666 freeAsmop (left, NULL, ic, TRUE);
6667 freeAsmop (result, NULL, ic, TRUE);
6670 /*-----------------------------------------------------------------*/
6671 /* genrshOne - right shift a one byte quantity by known count */
6672 /*-----------------------------------------------------------------*/
6674 genrshOne (operand * result, operand * left,
6675 int shCount, int sign)
6677 D(emitcode ("; genrshOne",""));
6679 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6682 /*-----------------------------------------------------------------*/
6683 /* genrshTwo - right shift two bytes by known amount != 0 */
6684 /*-----------------------------------------------------------------*/
6686 genrshTwo (operand * result, operand * left,
6687 int shCount, int sign)
6689 D(emitcode ("; genrshTwo",""));
6691 /* if shCount >= 8 */
6696 shiftR1Left2Result (left, MSB16, result, LSB,
6699 movLeft2Result (left, MSB16, result, LSB, sign);
6700 addSign (result, MSB16, sign);
6703 /* 1 <= shCount <= 7 */
6705 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6708 /*-----------------------------------------------------------------*/
6709 /* shiftRLong - shift right one long from left to result */
6710 /* offl = LSB or MSB16 */
6711 /*-----------------------------------------------------------------*/
6713 shiftRLong (operand * left, int offl,
6714 operand * result, int sign)
6716 int isSameRegs=sameRegs(AOP(left),AOP(result));
6718 if (isSameRegs && offl>1) {
6719 // we are in big trouble, but this shouldn't happen
6720 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6723 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6728 emitcode ("rlc", "a");
6729 emitcode ("subb", "a,acc");
6731 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6733 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6734 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6737 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6742 emitcode ("clr", "c");
6744 emitcode ("mov", "c,acc.7");
6747 emitcode ("rrc", "a");
6749 if (isSameRegs && offl==MSB16) {
6750 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6752 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6753 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6756 emitcode ("rrc", "a");
6757 if (isSameRegs && offl==1) {
6758 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6760 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6761 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6763 emitcode ("rrc", "a");
6764 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6768 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6769 emitcode ("rrc", "a");
6770 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6774 /*-----------------------------------------------------------------*/
6775 /* genrshFour - shift four byte by a known amount != 0 */
6776 /*-----------------------------------------------------------------*/
6778 genrshFour (operand * result, operand * left,
6779 int shCount, int sign)
6781 D(emitcode ("; genrshFour",""));
6783 /* if shifting more that 3 bytes */
6788 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6790 movLeft2Result (left, MSB32, result, LSB, sign);
6791 addSign (result, MSB16, sign);
6793 else if (shCount >= 16)
6797 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6800 movLeft2Result (left, MSB24, result, LSB, 0);
6801 movLeft2Result (left, MSB32, result, MSB16, sign);
6803 addSign (result, MSB24, sign);
6805 else if (shCount >= 8)
6809 shiftRLong (left, MSB16, result, sign);
6810 else if (shCount == 0)
6812 movLeft2Result (left, MSB16, result, LSB, 0);
6813 movLeft2Result (left, MSB24, result, MSB16, 0);
6814 movLeft2Result (left, MSB32, result, MSB24, sign);
6815 addSign (result, MSB32, sign);
6819 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6820 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6821 /* the last shift is signed */
6822 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6823 addSign (result, MSB32, sign);
6827 { /* 1 <= shCount <= 7 */
6830 shiftRLong (left, LSB, result, sign);
6832 shiftRLong (result, LSB, result, sign);
6836 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6837 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6838 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6843 /*-----------------------------------------------------------------*/
6844 /* genRightShiftLiteral - right shifting by known count */
6845 /*-----------------------------------------------------------------*/
6847 genRightShiftLiteral (operand * left,
6853 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6856 D(emitcode ("; genRightShiftLiteral",""));
6858 freeAsmop (right, NULL, ic, TRUE);
6860 aopOp (left, ic, FALSE);
6861 aopOp (result, ic, FALSE);
6864 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6868 size = getDataSize (left);
6869 /* test the LEFT size !!! */
6871 /* I suppose that the left size >= result size */
6874 size = getDataSize (result);
6876 movLeft2Result (left, size, result, size, 0);
6879 else if (shCount >= (size * 8))
6882 /* get sign in acc.7 */
6883 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6885 addSign (result, LSB, sign);
6892 genrshOne (result, left, shCount, sign);
6896 genrshTwo (result, left, shCount, sign);
6900 genrshFour (result, left, shCount, sign);
6906 freeAsmop (left, NULL, ic, TRUE);
6907 freeAsmop (result, NULL, ic, TRUE);
6910 /*-----------------------------------------------------------------*/
6911 /* genSignedRightShift - right shift of signed number */
6912 /*-----------------------------------------------------------------*/
6914 genSignedRightShift (iCode * ic)
6916 operand *right, *left, *result;
6919 symbol *tlbl, *tlbl1;
6921 D(emitcode ("; genSignedRightShift",""));
6923 /* we do it the hard way put the shift count in b
6924 and loop thru preserving the sign */
6926 right = IC_RIGHT (ic);
6927 left = IC_LEFT (ic);
6928 result = IC_RESULT (ic);
6930 aopOp (right, ic, FALSE);
6933 if (AOP_TYPE (right) == AOP_LIT)
6935 genRightShiftLiteral (left, right, result, ic, 1);
6938 /* shift count is unknown then we have to form
6939 a loop get the loop count in B : Note: we take
6940 only the lower order byte since shifting
6941 more that 32 bits make no sense anyway, ( the
6942 largest size of an object can be only 32 bits ) */
6944 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6945 emitcode ("inc", "b");
6946 freeAsmop (right, NULL, ic, TRUE);
6947 aopOp (left, ic, FALSE);
6948 aopOp (result, ic, FALSE);
6950 /* now move the left to the result if they are not the
6952 if (!sameRegs (AOP (left), AOP (result)) &&
6953 AOP_SIZE (result) > 1)
6956 size = AOP_SIZE (result);
6960 l = aopGet (AOP (left), offset, FALSE, TRUE);
6961 if (*l == '@' && IS_AOP_PREG (result))
6964 emitcode ("mov", "a,%s", l);
6965 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6968 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6973 /* mov the highest order bit to OVR */
6974 tlbl = newiTempLabel (NULL);
6975 tlbl1 = newiTempLabel (NULL);
6977 size = AOP_SIZE (result);
6979 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6980 emitcode ("rlc", "a");
6981 emitcode ("mov", "ov,c");
6982 /* if it is only one byte then */
6985 l = aopGet (AOP (left), 0, FALSE, FALSE);
6987 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6988 emitcode ("", "%05d$:", tlbl->key + 100);
6989 emitcode ("mov", "c,ov");
6990 emitcode ("rrc", "a");
6991 emitcode ("", "%05d$:", tlbl1->key + 100);
6992 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6993 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6997 reAdjustPreg (AOP (result));
6998 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6999 emitcode ("", "%05d$:", tlbl->key + 100);
7000 emitcode ("mov", "c,ov");
7003 l = aopGet (AOP (result), offset, FALSE, FALSE);
7005 emitcode ("rrc", "a");
7006 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7008 reAdjustPreg (AOP (result));
7009 emitcode ("", "%05d$:", tlbl1->key + 100);
7010 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7013 freeAsmop (left, NULL, ic, TRUE);
7014 freeAsmop (result, NULL, ic, TRUE);
7017 /*-----------------------------------------------------------------*/
7018 /* genRightShift - generate code for right shifting */
7019 /*-----------------------------------------------------------------*/
7021 genRightShift (iCode * ic)
7023 operand *right, *left, *result;
7027 symbol *tlbl, *tlbl1;
7029 D(emitcode ("; genRightShift",""));
7031 /* if signed then we do it the hard way preserve the
7032 sign bit moving it inwards */
7033 retype = getSpec (operandType (IC_RESULT (ic)));
7035 if (!SPEC_USIGN (retype))
7037 genSignedRightShift (ic);
7041 /* signed & unsigned types are treated the same : i.e. the
7042 signed is NOT propagated inwards : quoting from the
7043 ANSI - standard : "for E1 >> E2, is equivalent to division
7044 by 2**E2 if unsigned or if it has a non-negative value,
7045 otherwise the result is implementation defined ", MY definition
7046 is that the sign does not get propagated */
7048 right = IC_RIGHT (ic);
7049 left = IC_LEFT (ic);
7050 result = IC_RESULT (ic);
7052 aopOp (right, ic, FALSE);
7054 /* if the shift count is known then do it
7055 as efficiently as possible */
7056 if (AOP_TYPE (right) == AOP_LIT)
7058 genRightShiftLiteral (left, right, result, ic, 0);
7062 /* shift count is unknown then we have to form
7063 a loop get the loop count in B : Note: we take
7064 only the lower order byte since shifting
7065 more that 32 bits make no sense anyway, ( the
7066 largest size of an object can be only 32 bits ) */
7068 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7069 emitcode ("inc", "b");
7070 freeAsmop (right, NULL, ic, TRUE);
7071 aopOp (left, ic, FALSE);
7072 aopOp (result, ic, FALSE);
7074 /* now move the left to the result if they are not the
7076 if (!sameRegs (AOP (left), AOP (result)) &&
7077 AOP_SIZE (result) > 1)
7080 size = AOP_SIZE (result);
7084 l = aopGet (AOP (left), offset, FALSE, TRUE);
7085 if (*l == '@' && IS_AOP_PREG (result))
7088 emitcode ("mov", "a,%s", l);
7089 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7092 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7097 tlbl = newiTempLabel (NULL);
7098 tlbl1 = newiTempLabel (NULL);
7099 size = AOP_SIZE (result);
7102 /* if it is only one byte then */
7105 l = aopGet (AOP (left), 0, FALSE, FALSE);
7107 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7108 emitcode ("", "%05d$:", tlbl->key + 100);
7110 emitcode ("rrc", "a");
7111 emitcode ("", "%05d$:", tlbl1->key + 100);
7112 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7113 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7117 reAdjustPreg (AOP (result));
7118 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7119 emitcode ("", "%05d$:", tlbl->key + 100);
7123 l = aopGet (AOP (result), offset, FALSE, FALSE);
7125 emitcode ("rrc", "a");
7126 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7128 reAdjustPreg (AOP (result));
7130 emitcode ("", "%05d$:", tlbl1->key + 100);
7131 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7134 freeAsmop (left, NULL, ic, TRUE);
7135 freeAsmop (result, NULL, ic, TRUE);
7138 /*-----------------------------------------------------------------*/
7139 /* emitPtrByteGet - emits code to get a byte into A through a */
7140 /* pointer register (R0, R1, or DPTR). The */
7141 /* original value of A can be preserved in B. */
7142 /*-----------------------------------------------------------------*/
7144 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7151 emitcode ("mov", "b,a");
7152 emitcode ("mov", "a,@%s", rname);
7157 emitcode ("mov", "b,a");
7158 emitcode ("movx", "a,@%s", rname);
7163 emitcode ("mov", "b,a");
7164 emitcode ("movx", "a,@dptr");
7169 emitcode ("mov", "b,a");
7170 emitcode ("clr", "a");
7171 emitcode ("movc", "a,@a+dptr");
7177 emitcode ("push", "b");
7178 emitcode ("push", "acc");
7180 emitcode ("lcall", "__gptrget");
7182 emitcode ("pop", "b");
7187 /*-----------------------------------------------------------------*/
7188 /* emitPtrByteSet - emits code to set a byte from src through a */
7189 /* pointer register (R0, R1, or DPTR). */
7190 /*-----------------------------------------------------------------*/
7192 emitPtrByteSet (char *rname, int p_type, char *src)
7201 emitcode ("mov", "@%s,a", rname);
7204 emitcode ("mov", "@%s,%s", rname, src);
7209 emitcode ("movx", "@%s,a", rname);
7214 emitcode ("movx", "@dptr,a");
7219 emitcode ("lcall", "__gptrput");
7224 /*-----------------------------------------------------------------*/
7225 /* genUnpackBits - generates code for unpacking bits */
7226 /*-----------------------------------------------------------------*/
7228 genUnpackBits (operand * result, char *rname, int ptype)
7230 int offset = 0; /* result byte offset */
7231 int rsize; /* result size */
7232 int rlen = 0; /* remaining bitfield length */
7233 sym_link *etype; /* bitfield type information */
7234 int blen; /* bitfield length */
7235 int bstr; /* bitfield starting bit within byte */
7237 D(emitcode ("; genUnpackBits",""));
7239 etype = getSpec (operandType (result));
7240 rsize = getSize (operandType (result));
7241 blen = SPEC_BLEN (etype);
7242 bstr = SPEC_BSTR (etype);
7244 /* If the bitfield length is less than a byte */
7247 emitPtrByteGet (rname, ptype, FALSE);
7249 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7250 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7254 /* Bit field did not fit in a byte. Copy all
7255 but the partial byte at the end. */
7256 for (rlen=blen;rlen>=8;rlen-=8)
7258 emitPtrByteGet (rname, ptype, FALSE);
7259 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7261 emitcode ("inc", "%s", rname);
7264 /* Handle the partial byte at the end */
7267 emitPtrByteGet (rname, ptype, FALSE);
7268 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7269 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7277 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7282 /*-----------------------------------------------------------------*/
7283 /* genDataPointerGet - generates code when ptr offset is known */
7284 /*-----------------------------------------------------------------*/
7286 genDataPointerGet (operand * left,
7292 int size, offset = 0;
7294 D(emitcode ("; genDataPointerGet",""));
7296 aopOp (result, ic, TRUE);
7298 /* get the string representation of the name */
7299 l = aopGet (AOP (left), 0, FALSE, TRUE);
7300 size = AOP_SIZE (result);
7304 sprintf (buffer, "(%s + %d)", l + 1, offset);
7306 sprintf (buffer, "%s", l + 1);
7307 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7310 freeAsmop (left, NULL, ic, TRUE);
7311 freeAsmop (result, NULL, ic, TRUE);
7314 /*-----------------------------------------------------------------*/
7315 /* genNearPointerGet - emitcode for near pointer fetch */
7316 /*-----------------------------------------------------------------*/
7318 genNearPointerGet (operand * left,
7326 sym_link *rtype, *retype;
7327 sym_link *ltype = operandType (left);
7330 D(emitcode ("; genNearPointerGet",""));
7332 rtype = operandType (result);
7333 retype = getSpec (rtype);
7335 aopOp (left, ic, FALSE);
7337 /* if left is rematerialisable and
7338 result is not bit variable type and
7339 the left is pointer to data space i.e
7340 lower 128 bytes of space */
7341 if (AOP_TYPE (left) == AOP_IMMD &&
7342 !IS_BITVAR (retype) &&
7343 DCL_TYPE (ltype) == POINTER)
7345 genDataPointerGet (left, result, ic);
7349 /* if the value is already in a pointer register
7350 then don't need anything more */
7351 if (!AOP_INPREG (AOP (left)))
7353 if (IS_AOP_PREG (left))
7355 // Aha, it is a pointer, just in disguise.
7356 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7359 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7360 __FILE__, __LINE__);
7365 emitcode ("mov", "a%s,%s", rname + 1, rname);
7366 rname++; // skip the '@'.
7371 /* otherwise get a free pointer register */
7373 preg = getFreePtr (ic, &aop, FALSE);
7374 emitcode ("mov", "%s,%s",
7376 aopGet (AOP (left), 0, FALSE, TRUE));
7381 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7383 //aopOp (result, ic, FALSE);
7384 aopOp (result, ic, result?TRUE:FALSE);
7386 /* if bitfield then unpack the bits */
7387 if (IS_BITVAR (retype))
7388 genUnpackBits (result, rname, POINTER);
7391 /* we have can just get the values */
7392 int size = AOP_SIZE (result);
7397 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7400 emitcode ("mov", "a,@%s", rname);
7401 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7405 sprintf (buffer, "@%s", rname);
7406 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7410 emitcode ("inc", "%s", rname);
7414 /* now some housekeeping stuff */
7415 if (aop) /* we had to allocate for this iCode */
7417 if (pi) { /* post increment present */
7418 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7420 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7424 /* we did not allocate which means left
7425 already in a pointer register, then
7426 if size > 0 && this could be used again
7427 we have to point it back to where it
7429 if ((AOP_SIZE (result) > 1 &&
7430 !OP_SYMBOL (left)->remat &&
7431 (OP_SYMBOL (left)->liveTo > ic->seq ||
7435 int size = AOP_SIZE (result) - 1;
7437 emitcode ("dec", "%s", rname);
7442 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7443 freeAsmop (left, NULL, ic, TRUE);
7444 if (pi) pi->generated = 1;
7447 /*-----------------------------------------------------------------*/
7448 /* genPagedPointerGet - emitcode for paged pointer fetch */
7449 /*-----------------------------------------------------------------*/
7451 genPagedPointerGet (operand * left,
7459 sym_link *rtype, *retype;
7461 D(emitcode ("; genPagedPointerGet",""));
7463 rtype = operandType (result);
7464 retype = getSpec (rtype);
7466 aopOp (left, ic, FALSE);
7468 /* if the value is already in a pointer register
7469 then don't need anything more */
7470 if (!AOP_INPREG (AOP (left)))
7472 /* otherwise get a free pointer register */
7474 preg = getFreePtr (ic, &aop, FALSE);
7475 emitcode ("mov", "%s,%s",
7477 aopGet (AOP (left), 0, FALSE, TRUE));
7481 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7483 aopOp (result, ic, FALSE);
7485 /* if bitfield then unpack the bits */
7486 if (IS_BITVAR (retype))
7487 genUnpackBits (result, rname, PPOINTER);
7490 /* we have can just get the values */
7491 int size = AOP_SIZE (result);
7497 emitcode ("movx", "a,@%s", rname);
7498 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7503 emitcode ("inc", "%s", rname);
7507 /* now some housekeeping stuff */
7508 if (aop) /* we had to allocate for this iCode */
7510 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7511 freeAsmop (NULL, aop, ic, TRUE);
7515 /* we did not allocate which means left
7516 already in a pointer register, then
7517 if size > 0 && this could be used again
7518 we have to point it back to where it
7520 if ((AOP_SIZE (result) > 1 &&
7521 !OP_SYMBOL (left)->remat &&
7522 (OP_SYMBOL (left)->liveTo > ic->seq ||
7526 int size = AOP_SIZE (result) - 1;
7528 emitcode ("dec", "%s", rname);
7533 freeAsmop (left, NULL, ic, TRUE);
7534 freeAsmop (result, NULL, ic, TRUE);
7535 if (pi) pi->generated = 1;
7539 /*-----------------------------------------------------------------*/
7540 /* genFarPointerGet - gget value from far space */
7541 /*-----------------------------------------------------------------*/
7543 genFarPointerGet (operand * left,
7544 operand * result, iCode * ic, iCode * pi)
7547 sym_link *retype = getSpec (operandType (result));
7549 D(emitcode ("; genFarPointerGet",""));
7551 aopOp (left, ic, FALSE);
7553 /* if the operand is already in dptr
7554 then we do nothing else we move the value to dptr */
7555 if (AOP_TYPE (left) != AOP_STR)
7557 /* if this is remateriazable */
7558 if (AOP_TYPE (left) == AOP_IMMD)
7559 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7561 { /* we need to get it byte by byte */
7562 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7563 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7566 /* so dptr know contains the address */
7567 aopOp (result, ic, FALSE);
7569 /* if bit then unpack */
7570 if (IS_BITVAR (retype))
7571 genUnpackBits (result, "dptr", FPOINTER);
7574 size = AOP_SIZE (result);
7579 emitcode ("movx", "a,@dptr");
7580 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7582 emitcode ("inc", "dptr");
7586 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7587 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7588 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7591 freeAsmop (left, NULL, ic, TRUE);
7592 freeAsmop (result, NULL, ic, TRUE);
7595 /*-----------------------------------------------------------------*/
7596 /* genCodePointerGet - gget value from code space */
7597 /*-----------------------------------------------------------------*/
7599 genCodePointerGet (operand * left,
7600 operand * result, iCode * ic, iCode *pi)
7603 sym_link *retype = getSpec (operandType (result));
7605 D(emitcode ("; genCodePointerGet",""));
7607 aopOp (left, ic, FALSE);
7609 /* if the operand is already in dptr
7610 then we do nothing else we move the value to dptr */
7611 if (AOP_TYPE (left) != AOP_STR)
7613 /* if this is remateriazable */
7614 if (AOP_TYPE (left) == AOP_IMMD)
7615 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7617 { /* we need to get it byte by byte */
7618 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7619 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7622 /* so dptr know contains the address */
7623 aopOp (result, ic, FALSE);
7625 /* if bit then unpack */
7626 if (IS_BITVAR (retype))
7627 genUnpackBits (result, "dptr", CPOINTER);
7630 size = AOP_SIZE (result);
7637 emitcode ("clr", "a");
7638 emitcode ("movc", "a,@a+dptr");
7639 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7640 emitcode ("inc", "dptr");
7644 emitcode ("mov", "a,#0x%02x", offset);
7645 emitcode ("movc", "a,@a+dptr");
7646 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7651 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7652 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7653 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7656 freeAsmop (left, NULL, ic, TRUE);
7657 freeAsmop (result, NULL, ic, TRUE);
7660 /*-----------------------------------------------------------------*/
7661 /* genGenPointerGet - gget value from generic pointer space */
7662 /*-----------------------------------------------------------------*/
7664 genGenPointerGet (operand * left,
7665 operand * result, iCode * ic, iCode *pi)
7668 sym_link *retype = getSpec (operandType (result));
7670 D(emitcode ("; genGenPointerGet",""));
7672 aopOp (left, ic, FALSE);
7674 /* if the operand is already in dptr
7675 then we do nothing else we move the value to dptr */
7676 if (AOP_TYPE (left) != AOP_STR)
7678 /* if this is remateriazable */
7679 if (AOP_TYPE (left) == AOP_IMMD)
7681 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7682 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7683 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7685 emitcode ("mov", "b,#%d", pointerCode (retype));
7688 { /* we need to get it byte by byte */
7689 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7690 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7691 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7694 /* so dptr know contains the address */
7695 aopOp (result, ic, FALSE);
7697 /* if bit then unpack */
7698 if (IS_BITVAR (retype))
7699 genUnpackBits (result, "dptr", GPOINTER);
7702 size = AOP_SIZE (result);
7707 emitcode ("lcall", "__gptrget");
7708 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7710 emitcode ("inc", "dptr");
7714 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7715 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7716 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7719 freeAsmop (left, NULL, ic, TRUE);
7720 freeAsmop (result, NULL, ic, TRUE);
7723 /*-----------------------------------------------------------------*/
7724 /* genPointerGet - generate code for pointer get */
7725 /*-----------------------------------------------------------------*/
7727 genPointerGet (iCode * ic, iCode *pi)
7729 operand *left, *result;
7730 sym_link *type, *etype;
7733 D(emitcode ("; genPointerGet",""));
7735 left = IC_LEFT (ic);
7736 result = IC_RESULT (ic);
7738 /* depending on the type of pointer we need to
7739 move it to the correct pointer register */
7740 type = operandType (left);
7741 etype = getSpec (type);
7742 /* if left is of type of pointer then it is simple */
7743 if (IS_PTR (type) && !IS_FUNC (type->next))
7744 p_type = DCL_TYPE (type);
7747 /* we have to go by the storage class */
7748 p_type = PTR_TYPE (SPEC_OCLS (etype));
7751 /* special case when cast remat */
7752 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7753 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7754 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7755 type = operandType (left);
7756 p_type = DCL_TYPE (type);
7758 /* now that we have the pointer type we assign
7759 the pointer values */
7765 genNearPointerGet (left, result, ic, pi);
7769 genPagedPointerGet (left, result, ic, pi);
7773 genFarPointerGet (left, result, ic, pi);
7777 genCodePointerGet (left, result, ic, pi);
7781 genGenPointerGet (left, result, ic, pi);
7789 /*-----------------------------------------------------------------*/
7790 /* genPackBits - generates code for packed bit storage */
7791 /*-----------------------------------------------------------------*/
7793 genPackBits (sym_link * etype,
7795 char *rname, int p_type)
7797 int offset = 0; /* source byte offset */
7798 int rlen = 0; /* remaining bitfield length */
7799 int blen; /* bitfield length */
7800 int bstr; /* bitfield starting bit within byte */
7801 int litval; /* source literal value (if AOP_LIT) */
7802 unsigned char mask; /* bitmask within current byte */
7804 D(emitcode ("; genPackBits",""));
7806 blen = SPEC_BLEN (etype);
7807 bstr = SPEC_BSTR (etype);
7809 /* If the bitfield length is less than a byte */
7812 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7813 (unsigned char) (0xFF >> (8 - bstr)));
7815 if (AOP_TYPE (right) == AOP_LIT)
7817 /* Case with a bitfield length <8 and literal source
7819 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7821 litval &= (~mask) & 0xff;
7822 emitPtrByteGet (rname, p_type, FALSE);
7823 if ((mask|litval)!=0xff)
7824 emitcode ("anl","a,#0x%02x", mask);
7826 emitcode ("orl","a,#0x%02x", litval);
7830 if ((blen==1) && (p_type!=GPOINTER))
7832 /* Case with a bitfield length == 1 and no generic pointer
7834 if (AOP_TYPE (right) == AOP_CRY)
7835 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7838 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7839 emitcode ("rrc","a");
7841 emitPtrByteGet (rname, p_type, FALSE);
7842 emitcode ("mov","acc.%d,c",bstr);
7846 /* Case with a bitfield length < 8 and arbitrary source
7848 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7849 /* shift and mask source value */
7851 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7853 /* transfer A to B and get next byte */
7854 emitPtrByteGet (rname, p_type, TRUE);
7856 emitcode ("anl", "a,#0x%02x", mask);
7857 emitcode ("orl", "a,b");
7858 if (p_type == GPOINTER)
7859 emitcode ("pop", "b");
7863 emitPtrByteSet (rname, p_type, "a");
7867 /* Bit length is greater than 7 bits. In this case, copy */
7868 /* all except the partial byte at the end */
7869 for (rlen=blen;rlen>=8;rlen-=8)
7871 emitPtrByteSet (rname, p_type,
7872 aopGet (AOP (right), offset++, FALSE, TRUE) );
7874 emitcode ("inc", "%s", rname);
7877 /* If there was a partial byte at the end */
7880 mask = (((unsigned char) -1 << rlen) & 0xff);
7882 if (AOP_TYPE (right) == AOP_LIT)
7884 /* Case with partial byte and literal source
7886 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7887 litval >>= (blen-rlen);
7888 litval &= (~mask) & 0xff;
7889 emitPtrByteGet (rname, p_type, FALSE);
7890 if ((mask|litval)!=0xff)
7891 emitcode ("anl","a,#0x%02x", mask);
7893 emitcode ("orl","a,#0x%02x", litval);
7897 /* Case with partial byte and arbitrary source
7899 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7900 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7902 /* transfer A to B and get next byte */
7903 emitPtrByteGet (rname, p_type, TRUE);
7905 emitcode ("anl", "a,#0x%02x", mask);
7906 emitcode ("orl", "a,b");
7907 if (p_type == GPOINTER)
7908 emitcode ("pop", "b");
7910 emitPtrByteSet (rname, p_type, "a");
7916 /*-----------------------------------------------------------------*/
7917 /* genDataPointerSet - remat pointer to data space */
7918 /*-----------------------------------------------------------------*/
7920 genDataPointerSet (operand * right,
7924 int size, offset = 0;
7925 char *l, buffer[256];
7927 D(emitcode ("; genDataPointerSet",""));
7929 aopOp (right, ic, FALSE);
7931 l = aopGet (AOP (result), 0, FALSE, TRUE);
7932 size = AOP_SIZE (right);
7936 sprintf (buffer, "(%s + %d)", l + 1, offset);
7938 sprintf (buffer, "%s", l + 1);
7939 emitcode ("mov", "%s,%s", buffer,
7940 aopGet (AOP (right), offset++, FALSE, FALSE));
7943 freeAsmop (right, NULL, ic, TRUE);
7944 freeAsmop (result, NULL, ic, TRUE);
7947 /*-----------------------------------------------------------------*/
7948 /* genNearPointerSet - emitcode for near pointer put */
7949 /*-----------------------------------------------------------------*/
7951 genNearPointerSet (operand * right,
7959 sym_link *retype, *letype;
7960 sym_link *ptype = operandType (result);
7962 D(emitcode ("; genNearPointerSet",""));
7964 retype = getSpec (operandType (right));
7965 letype = getSpec (ptype);
7966 aopOp (result, ic, FALSE);
7968 /* if the result is rematerializable &
7969 in data space & not a bit variable */
7970 if (AOP_TYPE (result) == AOP_IMMD &&
7971 DCL_TYPE (ptype) == POINTER &&
7972 !IS_BITVAR (retype) &&
7973 !IS_BITVAR (letype))
7975 genDataPointerSet (right, result, ic);
7979 /* if the value is already in a pointer register
7980 then don't need anything more */
7981 if (!AOP_INPREG (AOP (result)))
7984 //AOP_TYPE (result) == AOP_STK
7988 // Aha, it is a pointer, just in disguise.
7989 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7992 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7993 __FILE__, __LINE__);
7998 emitcode ("mov", "a%s,%s", rname + 1, rname);
7999 rname++; // skip the '@'.
8004 /* otherwise get a free pointer register */
8006 preg = getFreePtr (ic, &aop, FALSE);
8007 emitcode ("mov", "%s,%s",
8009 aopGet (AOP (result), 0, FALSE, TRUE));
8015 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8018 aopOp (right, ic, FALSE);
8020 /* if bitfield then unpack the bits */
8021 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8022 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8025 /* we have can just get the values */
8026 int size = AOP_SIZE (right);
8031 l = aopGet (AOP (right), offset, FALSE, TRUE);
8035 emitcode ("mov", "@%s,a", rname);
8038 emitcode ("mov", "@%s,%s", rname, l);
8040 emitcode ("inc", "%s", rname);
8045 /* now some housekeeping stuff */
8046 if (aop) /* we had to allocate for this iCode */
8049 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8050 freeAsmop (NULL, aop, ic, TRUE);
8054 /* we did not allocate which means left
8055 already in a pointer register, then
8056 if size > 0 && this could be used again
8057 we have to point it back to where it
8059 if ((AOP_SIZE (right) > 1 &&
8060 !OP_SYMBOL (result)->remat &&
8061 (OP_SYMBOL (result)->liveTo > ic->seq ||
8065 int size = AOP_SIZE (right) - 1;
8067 emitcode ("dec", "%s", rname);
8072 if (pi) pi->generated = 1;
8073 freeAsmop (result, NULL, ic, TRUE);
8074 freeAsmop (right, NULL, ic, TRUE);
8077 /*-----------------------------------------------------------------*/
8078 /* genPagedPointerSet - emitcode for Paged pointer put */
8079 /*-----------------------------------------------------------------*/
8081 genPagedPointerSet (operand * right,
8089 sym_link *retype, *letype;
8091 D(emitcode ("; genPagedPointerSet",""));
8093 retype = getSpec (operandType (right));
8094 letype = getSpec (operandType (result));
8096 aopOp (result, ic, FALSE);
8098 /* if the value is already in a pointer register
8099 then don't need anything more */
8100 if (!AOP_INPREG (AOP (result)))
8102 /* otherwise get a free pointer register */
8104 preg = getFreePtr (ic, &aop, FALSE);
8105 emitcode ("mov", "%s,%s",
8107 aopGet (AOP (result), 0, FALSE, TRUE));
8111 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8113 aopOp (right, ic, FALSE);
8115 /* if bitfield then unpack the bits */
8116 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8117 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8120 /* we have can just get the values */
8121 int size = AOP_SIZE (right);
8126 l = aopGet (AOP (right), offset, FALSE, TRUE);
8129 emitcode ("movx", "@%s,a", rname);
8132 emitcode ("inc", "%s", rname);
8138 /* now some housekeeping stuff */
8139 if (aop) /* we had to allocate for this iCode */
8142 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8143 freeAsmop (NULL, aop, ic, TRUE);
8147 /* we did not allocate which means left
8148 already in a pointer register, then
8149 if size > 0 && this could be used again
8150 we have to point it back to where it
8152 if (AOP_SIZE (right) > 1 &&
8153 !OP_SYMBOL (result)->remat &&
8154 (OP_SYMBOL (result)->liveTo > ic->seq ||
8157 int size = AOP_SIZE (right) - 1;
8159 emitcode ("dec", "%s", rname);
8164 if (pi) pi->generated = 1;
8165 freeAsmop (result, NULL, ic, TRUE);
8166 freeAsmop (right, NULL, ic, TRUE);
8171 /*-----------------------------------------------------------------*/
8172 /* genFarPointerSet - set value from far space */
8173 /*-----------------------------------------------------------------*/
8175 genFarPointerSet (operand * right,
8176 operand * result, iCode * ic, iCode * pi)
8179 sym_link *retype = getSpec (operandType (right));
8180 sym_link *letype = getSpec (operandType (result));
8182 D(emitcode ("; genFarPointerSet",""));
8184 aopOp (result, ic, FALSE);
8186 /* if the operand is already in dptr
8187 then we do nothing else we move the value to dptr */
8188 if (AOP_TYPE (result) != AOP_STR)
8190 /* if this is remateriazable */
8191 if (AOP_TYPE (result) == AOP_IMMD)
8192 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8194 { /* we need to get it byte by byte */
8195 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8196 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8199 /* so dptr know contains the address */
8200 aopOp (right, ic, FALSE);
8202 /* if bit then unpack */
8203 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8204 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8207 size = AOP_SIZE (right);
8212 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8214 emitcode ("movx", "@dptr,a");
8216 emitcode ("inc", "dptr");
8219 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8220 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8221 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8224 freeAsmop (result, NULL, ic, TRUE);
8225 freeAsmop (right, NULL, ic, TRUE);
8228 /*-----------------------------------------------------------------*/
8229 /* genGenPointerSet - set value from generic pointer space */
8230 /*-----------------------------------------------------------------*/
8232 genGenPointerSet (operand * right,
8233 operand * result, iCode * ic, iCode * pi)
8236 sym_link *retype = getSpec (operandType (right));
8237 sym_link *letype = getSpec (operandType (result));
8239 D(emitcode ("; genGenPointerSet",""));
8241 aopOp (result, ic, FALSE);
8243 /* if the operand is already in dptr
8244 then we do nothing else we move the value to dptr */
8245 if (AOP_TYPE (result) != AOP_STR)
8247 /* if this is remateriazable */
8248 if (AOP_TYPE (result) == AOP_IMMD)
8250 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8251 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8252 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8254 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8257 { /* we need to get it byte by byte */
8258 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8259 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8260 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8263 /* so dptr know contains the address */
8264 aopOp (right, ic, FALSE);
8266 /* if bit then unpack */
8267 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8268 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8271 size = AOP_SIZE (right);
8276 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8278 emitcode ("lcall", "__gptrput");
8280 emitcode ("inc", "dptr");
8284 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8285 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8286 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8289 freeAsmop (result, NULL, ic, TRUE);
8290 freeAsmop (right, NULL, ic, TRUE);
8293 /*-----------------------------------------------------------------*/
8294 /* genPointerSet - stores the value into a pointer location */
8295 /*-----------------------------------------------------------------*/
8297 genPointerSet (iCode * ic, iCode *pi)
8299 operand *right, *result;
8300 sym_link *type, *etype;
8303 D(emitcode ("; genPointerSet",""));
8305 right = IC_RIGHT (ic);
8306 result = IC_RESULT (ic);
8308 /* depending on the type of pointer we need to
8309 move it to the correct pointer register */
8310 type = operandType (result);
8311 etype = getSpec (type);
8312 /* if left is of type of pointer then it is simple */
8313 if (IS_PTR (type) && !IS_FUNC (type->next))
8315 p_type = DCL_TYPE (type);
8319 /* we have to go by the storage class */
8320 p_type = PTR_TYPE (SPEC_OCLS (etype));
8323 /* special case when cast remat */
8324 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8325 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8326 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8327 type = operandType (result);
8328 p_type = DCL_TYPE (type);
8330 /* now that we have the pointer type we assign
8331 the pointer values */
8337 genNearPointerSet (right, result, ic, pi);
8341 genPagedPointerSet (right, result, ic, pi);
8345 genFarPointerSet (right, result, ic, pi);
8349 genGenPointerSet (right, result, ic, pi);
8353 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8354 "genPointerSet: illegal pointer type");
8359 /*-----------------------------------------------------------------*/
8360 /* genIfx - generate code for Ifx statement */
8361 /*-----------------------------------------------------------------*/
8363 genIfx (iCode * ic, iCode * popIc)
8365 operand *cond = IC_COND (ic);
8368 D(emitcode ("; genIfx",""));
8370 aopOp (cond, ic, FALSE);
8372 /* get the value into acc */
8373 if (AOP_TYPE (cond) != AOP_CRY)
8377 /* the result is now in the accumulator */
8378 freeAsmop (cond, NULL, ic, TRUE);
8380 /* if there was something to be popped then do it */
8384 /* if the condition is a bit variable */
8385 if (isbit && IS_ITEMP (cond) &&
8387 genIfxJump (ic, SPIL_LOC (cond)->rname);
8388 else if (isbit && !IS_ITEMP (cond))
8389 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8391 genIfxJump (ic, "a");
8396 /*-----------------------------------------------------------------*/
8397 /* genAddrOf - generates code for address of */
8398 /*-----------------------------------------------------------------*/
8400 genAddrOf (iCode * ic)
8402 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8405 D(emitcode ("; genAddrOf",""));
8407 aopOp (IC_RESULT (ic), ic, FALSE);
8409 /* if the operand is on the stack then we
8410 need to get the stack offset of this
8414 /* if it has an offset then we need to compute
8418 emitcode ("mov", "a,_bp");
8419 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8420 ((char) (sym->stack - _G.nRegsSaved)) :
8421 ((char) sym->stack)) & 0xff);
8422 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8426 /* we can just move _bp */
8427 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8429 /* fill the result with zero */
8430 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8435 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8441 /* object not on stack then we need the name */
8442 size = AOP_SIZE (IC_RESULT (ic));
8447 char s[SDCC_NAME_MAX];
8449 sprintf (s, "#(%s >> %d)",
8453 sprintf (s, "#%s", sym->rname);
8454 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8458 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8462 /*-----------------------------------------------------------------*/
8463 /* genFarFarAssign - assignment when both are in far space */
8464 /*-----------------------------------------------------------------*/
8466 genFarFarAssign (operand * result, operand * right, iCode * ic)
8468 int size = AOP_SIZE (right);
8472 D(emitcode ("; genFarFarAssign",""));
8474 /* first push the right side on to the stack */
8477 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8479 emitcode ("push", "acc");
8482 freeAsmop (right, NULL, ic, FALSE);
8483 /* now assign DPTR to result */
8484 aopOp (result, ic, FALSE);
8485 size = AOP_SIZE (result);
8488 emitcode ("pop", "acc");
8489 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8491 freeAsmop (result, NULL, ic, FALSE);
8495 /*-----------------------------------------------------------------*/
8496 /* genAssign - generate code for assignment */
8497 /*-----------------------------------------------------------------*/
8499 genAssign (iCode * ic)
8501 operand *result, *right;
8503 unsigned long lit = 0L;
8505 D(emitcode("; genAssign",""));
8507 result = IC_RESULT (ic);
8508 right = IC_RIGHT (ic);
8510 /* if they are the same */
8511 if (operandsEqu (result, right) &&
8512 !isOperandVolatile (result, FALSE) &&
8513 !isOperandVolatile (right, FALSE))
8516 aopOp (right, ic, FALSE);
8518 /* special case both in far space */
8519 if (AOP_TYPE (right) == AOP_DPTR &&
8520 IS_TRUE_SYMOP (result) &&
8521 isOperandInFarSpace (result))
8524 genFarFarAssign (result, right, ic);
8528 aopOp (result, ic, TRUE);
8530 /* if they are the same registers */
8531 if (sameRegs (AOP (right), AOP (result)) &&
8532 !isOperandVolatile (result, FALSE) &&
8533 !isOperandVolatile (right, FALSE))
8536 /* if the result is a bit */
8537 if (AOP_TYPE (result) == AOP_CRY)
8540 /* if the right size is a literal then
8541 we know what the value is */
8542 if (AOP_TYPE (right) == AOP_LIT)
8544 if (((int) operandLitValue (right)))
8545 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8547 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8551 /* the right is also a bit variable */
8552 if (AOP_TYPE (right) == AOP_CRY)
8554 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8555 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8561 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8565 /* bit variables done */
8567 size = AOP_SIZE (result);
8569 if (AOP_TYPE (right) == AOP_LIT)
8570 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8572 (AOP_TYPE (result) != AOP_REG) &&
8573 (AOP_TYPE (right) == AOP_LIT) &&
8574 !IS_FLOAT (operandType (right)) &&
8577 emitcode ("clr", "a");
8580 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8581 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8583 aopPut (AOP (result),
8584 aopGet (AOP (right), size, FALSE, FALSE),
8586 isOperandVolatile (result, FALSE));
8593 aopPut (AOP (result),
8594 aopGet (AOP (right), offset, FALSE, FALSE),
8596 isOperandVolatile (result, FALSE));
8602 freeAsmop (right, NULL, ic, TRUE);
8603 freeAsmop (result, NULL, ic, TRUE);
8606 /*-----------------------------------------------------------------*/
8607 /* genJumpTab - genrates code for jump table */
8608 /*-----------------------------------------------------------------*/
8610 genJumpTab (iCode * ic)
8615 D(emitcode ("; genJumpTab",""));
8617 aopOp (IC_JTCOND (ic), ic, FALSE);
8618 /* get the condition into accumulator */
8619 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8621 /* multiply by three */
8622 emitcode ("add", "a,acc");
8623 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8624 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8626 jtab = newiTempLabel (NULL);
8627 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8628 emitcode ("jmp", "@a+dptr");
8629 emitcode ("", "%05d$:", jtab->key + 100);
8630 /* now generate the jump labels */
8631 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8632 jtab = setNextItem (IC_JTLABELS (ic)))
8633 emitcode ("ljmp", "%05d$", jtab->key + 100);
8637 /*-----------------------------------------------------------------*/
8638 /* genCast - gen code for casting */
8639 /*-----------------------------------------------------------------*/
8641 genCast (iCode * ic)
8643 operand *result = IC_RESULT (ic);
8644 sym_link *ctype = operandType (IC_LEFT (ic));
8645 sym_link *rtype = operandType (IC_RIGHT (ic));
8646 operand *right = IC_RIGHT (ic);
8649 D(emitcode("; genCast",""));
8651 /* if they are equivalent then do nothing */
8652 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8655 aopOp (right, ic, FALSE);
8656 aopOp (result, ic, FALSE);
8658 /* if the result is a bit (and not a bitfield) */
8659 // if (AOP_TYPE (result) == AOP_CRY)
8660 if (IS_BITVAR (OP_SYMBOL (result)->type)
8661 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8663 /* if the right size is a literal then
8664 we know what the value is */
8665 if (AOP_TYPE (right) == AOP_LIT)
8667 if (((int) operandLitValue (right)))
8668 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8670 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8675 /* the right is also a bit variable */
8676 if (AOP_TYPE (right) == AOP_CRY)
8678 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8679 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8685 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8690 /* if they are the same size : or less */
8691 if (AOP_SIZE (result) <= AOP_SIZE (right))
8694 /* if they are in the same place */
8695 if (sameRegs (AOP (right), AOP (result)))
8698 /* if they in different places then copy */
8699 size = AOP_SIZE (result);
8703 aopPut (AOP (result),
8704 aopGet (AOP (right), offset, FALSE, FALSE),
8706 isOperandVolatile (result, FALSE));
8713 /* if the result is of type pointer */
8718 sym_link *type = operandType (right);
8719 sym_link *etype = getSpec (type);
8721 /* pointer to generic pointer */
8722 if (IS_GENPTR (ctype))
8725 p_type = DCL_TYPE (type);
8728 if (SPEC_SCLS(etype)==S_REGISTER) {
8729 // let's assume it is a generic pointer
8732 /* we have to go by the storage class */
8733 p_type = PTR_TYPE (SPEC_OCLS (etype));
8737 /* the first two bytes are known */
8738 size = GPTRSIZE - 1;
8742 aopPut (AOP (result),
8743 aopGet (AOP (right), offset, FALSE, FALSE),
8745 isOperandVolatile (result, FALSE));
8748 /* the last byte depending on type */
8750 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8755 // pointerTypeToGPByte will have bitched.
8759 sprintf(gpValStr, "#0x%d", gpVal);
8760 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8765 /* just copy the pointers */
8766 size = AOP_SIZE (result);
8770 aopPut (AOP (result),
8771 aopGet (AOP (right), offset, FALSE, FALSE),
8773 isOperandVolatile (result, FALSE));
8779 /* so we now know that the size of destination is greater
8780 than the size of the source */
8781 /* we move to result for the size of source */
8782 size = AOP_SIZE (right);
8786 aopPut (AOP (result),
8787 aopGet (AOP (right), offset, FALSE, FALSE),
8789 isOperandVolatile (result, FALSE));
8793 /* now depending on the sign of the source && destination */
8794 size = AOP_SIZE (result) - AOP_SIZE (right);
8795 /* if unsigned or not an integral type */
8796 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8799 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8803 /* we need to extend the sign :{ */
8804 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8807 emitcode ("rlc", "a");
8808 emitcode ("subb", "a,acc");
8810 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8813 /* we are done hurray !!!! */
8816 freeAsmop (right, NULL, ic, TRUE);
8817 freeAsmop (result, NULL, ic, TRUE);
8821 /*-----------------------------------------------------------------*/
8822 /* genDjnz - generate decrement & jump if not zero instrucion */
8823 /*-----------------------------------------------------------------*/
8825 genDjnz (iCode * ic, iCode * ifx)
8831 D(emitcode ("; genDjnz",""));
8833 /* if the if condition has a false label
8834 then we cannot save */
8838 /* if the minus is not of the form
8840 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8841 !IS_OP_LITERAL (IC_RIGHT (ic)))
8844 if (operandLitValue (IC_RIGHT (ic)) != 1)
8847 /* if the size of this greater than one then no
8849 if (getSize (operandType (IC_RESULT (ic))) > 1)
8852 /* otherwise we can save BIG */
8853 lbl = newiTempLabel (NULL);
8854 lbl1 = newiTempLabel (NULL);
8856 aopOp (IC_RESULT (ic), ic, FALSE);
8858 if (AOP_NEEDSACC(IC_RESULT(ic)))
8860 /* If the result is accessed indirectly via
8861 * the accumulator, we must explicitly write
8862 * it back after the decrement.
8864 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8866 if (strcmp(rByte, "a"))
8868 /* Something is hopelessly wrong */
8869 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8870 __FILE__, __LINE__);
8871 /* We can just give up; the generated code will be inefficient,
8874 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8877 emitcode ("dec", "%s", rByte);
8878 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8879 emitcode ("jnz", "%05d$", lbl->key + 100);
8881 else if (IS_AOP_PREG (IC_RESULT (ic)))
8883 emitcode ("dec", "%s",
8884 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8885 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8886 emitcode ("jnz", "%05d$", lbl->key + 100);
8890 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8893 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8894 emitcode ("", "%05d$:", lbl->key + 100);
8895 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8896 emitcode ("", "%05d$:", lbl1->key + 100);
8898 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8903 /*-----------------------------------------------------------------*/
8904 /* genReceive - generate code for a receive iCode */
8905 /*-----------------------------------------------------------------*/
8907 genReceive (iCode * ic)
8909 int size = getSize (operandType (IC_RESULT (ic)));
8911 D(emitcode ("; genReceive",""));
8913 if (ic->argreg == 1) { /* first parameter */
8914 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8915 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8916 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8918 offset = fReturnSizeMCS51 - size;
8920 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8921 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8924 aopOp (IC_RESULT (ic), ic, FALSE);
8925 size = AOP_SIZE (IC_RESULT (ic));
8928 emitcode ("pop", "acc");
8929 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8934 aopOp (IC_RESULT (ic), ic, FALSE);
8936 assignResultValue (IC_RESULT (ic));
8938 } else { /* second receive onwards */
8940 aopOp (IC_RESULT (ic), ic, FALSE);
8941 rb1off = ic->argreg;
8943 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8946 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8949 /*-----------------------------------------------------------------*/
8950 /* genDummyRead - generate code for dummy read of volatiles */
8951 /*-----------------------------------------------------------------*/
8953 genDummyRead (iCode * ic)
8958 D(emitcode("; genDummyRead",""));
8960 right = IC_RIGHT (ic);
8962 aopOp (right, ic, FALSE);
8964 /* if the result is a bit */
8965 if (AOP_TYPE (right) == AOP_CRY)
8967 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8971 /* bit variables done */
8973 size = AOP_SIZE (right);
8977 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8982 freeAsmop (right, NULL, ic, TRUE);
8985 /*-----------------------------------------------------------------*/
8986 /* gen51Code - generate code for 8051 based controllers */
8987 /*-----------------------------------------------------------------*/
8989 gen51Code (iCode * lic)
8994 lineHead = lineCurr = NULL;
8996 /* print the allocation information */
8997 if (allocInfo && currFunc)
8998 printAllocInfo (currFunc, codeOutFile);
8999 /* if debug information required */
9000 if (options.debug && currFunc)
9002 debugFile->writeFunction(currFunc);
9004 if (IS_STATIC (currFunc->etype))
9005 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9007 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9010 /* stack pointer name */
9011 if (options.useXstack)
9017 for (ic = lic; ic; ic = ic->next)
9019 _G.current_iCode = ic;
9021 if (ic->lineno && cln != ic->lineno)
9026 emitcode ("", "C$%s$%d$%d$%d ==.",
9027 FileBaseName (ic->filename), ic->lineno,
9028 ic->level, ic->block);
9031 if (!options.noCcodeInAsm) {
9032 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9033 printCLine(ic->filename, ic->lineno));
9037 if (options.iCodeInAsm) {
9041 for (i=0; i<8; i++) {
9042 sprintf (®sInUse[i],
9043 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9046 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9048 /* if the result is marked as
9049 spilt and rematerializable or code for
9050 this has already been generated then
9052 if (resultRemat (ic) || ic->generated)
9055 /* depending on the operation */
9075 /* IPOP happens only when trying to restore a
9076 spilt live range, if there is an ifx statement
9077 following this pop then the if statement might
9078 be using some of the registers being popped which
9079 would destory the contents of the register so
9080 we need to check for this condition and handle it */
9082 ic->next->op == IFX &&
9083 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9084 genIfx (ic->next, ic);
9102 genEndFunction (ic);
9122 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9139 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9143 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9150 /* note these two are xlated by algebraic equivalence
9151 during parsing SDCC.y */
9152 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9153 "got '>=' or '<=' shouldn't have come here");
9157 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9169 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9173 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9177 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9204 case GET_VALUE_AT_ADDRESS:
9205 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9209 if (POINTER_SET (ic))
9210 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9236 addSet (&_G.sendSet, ic);
9239 case DUMMY_READ_VOLATILE:
9248 _G.current_iCode = NULL;
9250 /* now we are ready to call the
9251 peep hole optimizer */
9252 if (!options.nopeep)
9253 peepHole (&lineHead);
9255 /* now do the actual printing */
9256 printLine (lineHead, codeOutFile);