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))
2297 emitcode ("mov", "c,ea");
2298 emitcode ("push", "psw"); /* save old ea via c in psw */
2299 emitcode ("clr", "ea");
2302 /* here we need to generate the equates for the
2303 register bank if required */
2304 if (FUNC_REGBANK (ftype) != rbank)
2308 rbank = FUNC_REGBANK (ftype);
2309 for (i = 0; i < mcs51_nRegs; i++)
2311 if (strcmp (regs8051[i].base, "0") == 0)
2312 emitcode ("", "%s = 0x%02x",
2314 8 * rbank + regs8051[i].offset);
2316 emitcode ("", "%s = %s + 0x%02x",
2319 8 * rbank + regs8051[i].offset);
2323 /* if this is an interrupt service routine then
2324 save acc, b, dpl, dph */
2325 if (IFFUNC_ISISR (sym->type))
2328 if (!inExcludeList ("acc"))
2329 emitcode ("push", "acc");
2330 if (!inExcludeList ("b"))
2331 emitcode ("push", "b");
2332 if (!inExcludeList ("dpl"))
2333 emitcode ("push", "dpl");
2334 if (!inExcludeList ("dph"))
2335 emitcode ("push", "dph");
2336 /* if this isr has no bank i.e. is going to
2337 run with bank 0 , then we need to save more
2339 if (!FUNC_REGBANK (sym->type))
2342 /* if this function does not call any other
2343 function then we can be economical and
2344 save only those registers that are used */
2345 if (!IFFUNC_HASFCALL(sym->type))
2349 /* if any registers used */
2352 /* save the registers used */
2353 for (i = 0; i < sym->regsUsed->size; i++)
2355 if (bitVectBitValue (sym->regsUsed, i) ||
2356 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2357 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2365 /* this function has a function call cannot
2366 determines register usage so we will have to push the
2368 saveRBank (0, ic, FALSE);
2369 if (options.parms_in_bank1) {
2371 for (i=0; i < 8 ; i++ ) {
2372 emitcode ("push","%s",rb1regs[i]);
2379 /* This ISR uses a non-zero bank.
2381 * We assume that the bank is available for our
2384 * However, if this ISR calls a function which uses some
2385 * other bank, we must save that bank entirely.
2387 unsigned long banksToSave = 0;
2389 if (IFFUNC_HASFCALL(sym->type))
2392 #define MAX_REGISTER_BANKS 4
2397 for (i = ic; i; i = i->next)
2399 if (i->op == ENDFUNCTION)
2401 /* we got to the end OK. */
2409 dtype = operandType (IC_LEFT(i));
2411 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2413 /* Mark this bank for saving. */
2414 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2416 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2420 banksToSave |= (1 << FUNC_REGBANK(dtype));
2423 /* And note that we don't need to do it in
2431 /* This is a mess; we have no idea what
2432 * register bank the called function might
2435 * The only thing I can think of to do is
2436 * throw a warning and hope.
2438 werror(W_FUNCPTR_IN_USING_ISR);
2442 if (banksToSave && options.useXstack)
2444 /* Since we aren't passing it an ic,
2445 * saveRBank will assume r0 is available to abuse.
2447 * So switch to our (trashable) bank now, so
2448 * the caller's R0 isn't trashed.
2450 emitcode ("push", "psw");
2451 emitcode ("mov", "psw,#0x%02x",
2452 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2456 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2458 if (banksToSave & (1 << ix))
2460 saveRBank(ix, NULL, FALSE);
2464 // TODO: this needs a closer look
2465 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2470 /* if callee-save to be used for this function
2471 then save the registers being used in this function */
2472 if (IFFUNC_CALLEESAVES(sym->type))
2476 /* if any registers used */
2479 /* save the registers used */
2480 for (i = 0; i < sym->regsUsed->size; i++)
2482 if (bitVectBitValue (sym->regsUsed, i) ||
2483 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2485 /* remember one saved register for later usage */
2486 if (calleesaves_saved_register < 0)
2487 calleesaves_saved_register = i;
2488 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2496 /* set the register bank to the desired value */
2497 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2500 emitcode ("push", "psw");
2501 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2504 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2507 if (options.useXstack)
2509 emitcode ("mov", "r0,%s", spname);
2510 emitcode ("mov", "a,_bp");
2511 emitcode ("movx", "@r0,a");
2512 emitcode ("inc", "%s", spname);
2516 /* set up the stack */
2517 emitcode ("push", "_bp"); /* save the callers stack */
2519 emitcode ("mov", "_bp,%s", spname);
2522 /* adjust the stack for the function */
2528 werror (W_STACK_OVERFLOW, sym->name);
2530 if (i > 3 && sym->recvSize < 4)
2533 emitcode ("mov", "a,sp");
2534 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2535 emitcode ("mov", "sp,a");
2540 if (IFFUNC_CALLEESAVES(sym->type))
2542 /* if it's a callee-saves function we need a saved register */
2543 if (calleesaves_saved_register >= 0)
2545 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2546 emitcode ("mov", "a,sp");
2547 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2548 emitcode ("mov", "sp,a");
2549 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2552 /* do it the hard way */
2554 emitcode ("inc", "sp");
2558 /* not callee-saves, we can clobber r0 */
2559 emitcode ("mov", "r0,a");
2560 emitcode ("mov", "a,sp");
2561 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2562 emitcode ("mov", "sp,a");
2563 emitcode ("mov", "a,r0");
2568 emitcode ("inc", "sp");
2574 emitcode ("mov", "a,_spx");
2575 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2576 emitcode ("mov", "_spx,a");
2581 /*-----------------------------------------------------------------*/
2582 /* genEndFunction - generates epilogue for functions */
2583 /*-----------------------------------------------------------------*/
2585 genEndFunction (iCode * ic)
2587 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2589 if (IFFUNC_ISNAKED(sym->type))
2591 emitcode(";", "naked function: no epilogue.");
2595 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2597 emitcode ("mov", "%s,_bp", spname);
2600 /* if use external stack but some variables were
2601 added to the local stack then decrement the
2603 if (options.useXstack && sym->stack)
2605 emitcode ("mov", "a,sp");
2606 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2607 emitcode ("mov", "sp,a");
2611 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2613 if (options.useXstack)
2615 emitcode ("mov", "r0,%s", spname);
2616 emitcode ("movx", "a,@r0");
2617 emitcode ("mov", "_bp,a");
2618 emitcode ("dec", "%s", spname);
2622 emitcode ("pop", "_bp");
2626 /* restore the register bank */
2627 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2629 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2630 || !options.useXstack)
2632 /* Special case of ISR using non-zero bank with useXstack
2635 emitcode ("pop", "psw");
2639 if (IFFUNC_ISISR (sym->type))
2642 /* now we need to restore the registers */
2643 /* if this isr has no bank i.e. is going to
2644 run with bank 0 , then we need to save more
2646 if (!FUNC_REGBANK (sym->type))
2648 /* if this function does not call any other
2649 function then we can be economical and
2650 save only those registers that are used */
2651 if (!IFFUNC_HASFCALL(sym->type))
2655 /* if any registers used */
2658 /* save the registers used */
2659 for (i = sym->regsUsed->size; i >= 0; i--)
2661 if (bitVectBitValue (sym->regsUsed, i) ||
2662 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2663 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2670 if (options.parms_in_bank1) {
2672 for (i = 7 ; i >= 0 ; i-- ) {
2673 emitcode ("pop","%s",rb1regs[i]);
2676 /* this function has a function call cannot
2677 determines register usage so we will have to pop the
2679 unsaveRBank (0, ic, FALSE);
2684 /* This ISR uses a non-zero bank.
2686 * Restore any register banks saved by genFunction
2689 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2692 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2694 if (savedBanks & (1 << ix))
2696 unsaveRBank(ix, NULL, FALSE);
2700 if (options.useXstack)
2702 /* Restore bank AFTER calling unsaveRBank,
2703 * since it can trash r0.
2705 emitcode ("pop", "psw");
2709 if (!inExcludeList ("dph"))
2710 emitcode ("pop", "dph");
2711 if (!inExcludeList ("dpl"))
2712 emitcode ("pop", "dpl");
2713 if (!inExcludeList ("b"))
2714 emitcode ("pop", "b");
2715 if (!inExcludeList ("acc"))
2716 emitcode ("pop", "acc");
2718 if (IFFUNC_ISCRITICAL (sym->type))
2720 emitcode ("pop", "psw"); /* restore ea via c in psw */
2721 emitcode ("mov", "ea,c");
2724 /* if debug then send end of function */
2725 if (options.debug && currFunc)
2728 emitcode ("", "C$%s$%d$%d$%d ==.",
2729 FileBaseName (ic->filename), currFunc->lastLine,
2730 ic->level, ic->block);
2731 if (IS_STATIC (currFunc->etype))
2732 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2734 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2738 emitcode ("reti", "");
2742 if (IFFUNC_ISCRITICAL (sym->type))
2744 emitcode ("pop", "psw"); /* restore ea via c in psw */
2745 emitcode ("mov", "ea,c");
2748 if (IFFUNC_CALLEESAVES(sym->type))
2752 /* if any registers used */
2755 /* save the registers used */
2756 for (i = sym->regsUsed->size; i >= 0; i--)
2758 if (bitVectBitValue (sym->regsUsed, i) ||
2759 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2760 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2766 /* if debug then send end of function */
2767 if (options.debug && currFunc)
2770 emitcode ("", "C$%s$%d$%d$%d ==.",
2771 FileBaseName (ic->filename), currFunc->lastLine,
2772 ic->level, ic->block);
2773 if (IS_STATIC (currFunc->etype))
2774 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2776 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2780 emitcode ("ret", "");
2785 /*-----------------------------------------------------------------*/
2786 /* genRet - generate code for return statement */
2787 /*-----------------------------------------------------------------*/
2791 int size, offset = 0, pushed = 0;
2793 D(emitcode ("; genRet",""));
2795 /* if we have no return value then
2796 just generate the "ret" */
2800 /* we have something to return then
2801 move the return value into place */
2802 aopOp (IC_LEFT (ic), ic, FALSE);
2803 size = AOP_SIZE (IC_LEFT (ic));
2808 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2811 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2813 emitcode ("push", "%s", l);
2818 l = aopGet (AOP (IC_LEFT (ic)), offset,
2820 if (strcmp (fReturn[offset], l))
2821 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2830 if (strcmp (fReturn[pushed], "a"))
2831 emitcode ("pop", fReturn[pushed]);
2833 emitcode ("pop", "acc");
2836 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2839 /* generate a jump to the return label
2840 if the next is not the return statement */
2841 if (!(ic->next && ic->next->op == LABEL &&
2842 IC_LABEL (ic->next) == returnLabel))
2844 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2848 /*-----------------------------------------------------------------*/
2849 /* genLabel - generates a label */
2850 /*-----------------------------------------------------------------*/
2852 genLabel (iCode * ic)
2854 /* special case never generate */
2855 if (IC_LABEL (ic) == entryLabel)
2858 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2861 /*-----------------------------------------------------------------*/
2862 /* genGoto - generates a ljmp */
2863 /*-----------------------------------------------------------------*/
2865 genGoto (iCode * ic)
2867 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2870 /*-----------------------------------------------------------------*/
2871 /* findLabelBackwards: walks back through the iCode chain looking */
2872 /* for the given label. Returns number of iCode instructions */
2873 /* between that label and given ic. */
2874 /* Returns zero if label not found. */
2875 /*-----------------------------------------------------------------*/
2877 findLabelBackwards (iCode * ic, int key)
2886 /* If we have any pushes or pops, we cannot predict the distance.
2887 I don't like this at all, this should be dealt with in the
2889 if (ic->op == IPUSH || ic->op == IPOP) {
2893 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2902 /*-----------------------------------------------------------------*/
2903 /* genPlusIncr :- does addition with increment if possible */
2904 /*-----------------------------------------------------------------*/
2906 genPlusIncr (iCode * ic)
2908 unsigned int icount;
2909 unsigned int size = getDataSize (IC_RESULT (ic));
2911 /* will try to generate an increment */
2912 /* if the right side is not a literal
2914 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2917 /* if the literal value of the right hand side
2918 is greater than 4 then it is not worth it */
2919 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2922 D(emitcode ("; genPlusIncr",""));
2924 /* if increment >=16 bits in register or direct space */
2925 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2926 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2934 /* If the next instruction is a goto and the goto target
2935 * is < 10 instructions previous to this, we can generate
2936 * jumps straight to that target.
2938 if (ic->next && ic->next->op == GOTO
2939 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2940 && labelRange <= 10)
2942 emitcode (";", "tail increment optimized");
2943 tlbl = IC_LABEL (ic->next);
2948 tlbl = newiTempLabel (NULL);
2951 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2952 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2953 IS_AOP_PREG (IC_RESULT (ic)))
2954 emitcode ("cjne", "%s,#0x00,%05d$",
2955 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2959 emitcode ("clr", "a");
2960 emitcode ("cjne", "a,%s,%05d$",
2961 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2965 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2969 IS_AOP_PREG (IC_RESULT (ic)))
2970 emitcode ("cjne", "%s,#0x00,%05d$",
2971 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2974 emitcode ("cjne", "a,%s,%05d$",
2975 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2978 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2982 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2983 IS_AOP_PREG (IC_RESULT (ic)))
2984 emitcode ("cjne", "%s,#0x00,%05d$",
2985 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2989 emitcode ("cjne", "a,%s,%05d$",
2990 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2993 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2998 emitcode ("", "%05d$:", tlbl->key + 100);
3003 /* if the sizes are greater than 1 then we cannot */
3004 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3005 AOP_SIZE (IC_LEFT (ic)) > 1)
3008 /* we can if the aops of the left & result match or
3009 if they are in registers and the registers are the
3011 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3016 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3017 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3018 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3024 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3033 /*-----------------------------------------------------------------*/
3034 /* outBitAcc - output a bit in acc */
3035 /*-----------------------------------------------------------------*/
3037 outBitAcc (operand * result)
3039 symbol *tlbl = newiTempLabel (NULL);
3040 /* if the result is a bit */
3041 if (AOP_TYPE (result) == AOP_CRY)
3043 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3047 emitcode ("jz", "%05d$", tlbl->key + 100);
3048 emitcode ("mov", "a,%s", one);
3049 emitcode ("", "%05d$:", tlbl->key + 100);
3054 /*-----------------------------------------------------------------*/
3055 /* genPlusBits - generates code for addition of two bits */
3056 /*-----------------------------------------------------------------*/
3058 genPlusBits (iCode * ic)
3060 D(emitcode ("; genPlusBits",""));
3062 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3064 symbol *lbl = newiTempLabel (NULL);
3065 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3066 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3067 emitcode ("cpl", "c");
3068 emitcode ("", "%05d$:", (lbl->key + 100));
3069 outBitC (IC_RESULT (ic));
3073 emitcode ("clr", "a");
3074 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3075 emitcode ("rlc", "a");
3076 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3077 emitcode ("addc", "a,#0x00");
3078 outAcc (IC_RESULT (ic));
3083 /* This is the original version of this code.
3085 * This is being kept around for reference,
3086 * because I am not entirely sure I got it right...
3089 adjustArithmeticResult (iCode * ic)
3091 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3092 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3093 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3094 aopPut (AOP (IC_RESULT (ic)),
3095 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3097 isOperandVolatile (IC_RESULT (ic), FALSE));
3099 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3100 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3101 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3102 aopPut (AOP (IC_RESULT (ic)),
3103 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3105 isOperandVolatile (IC_RESULT (ic), FALSE));
3107 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3108 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3109 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3110 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3111 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3114 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3115 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3119 /* This is the pure and virtuous version of this code.
3120 * I'm pretty certain it's right, but not enough to toss the old
3124 adjustArithmeticResult (iCode * ic)
3126 if (opIsGptr (IC_RESULT (ic)) &&
3127 opIsGptr (IC_LEFT (ic)) &&
3128 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3130 aopPut (AOP (IC_RESULT (ic)),
3131 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3133 isOperandVolatile (IC_RESULT (ic), FALSE));
3136 if (opIsGptr (IC_RESULT (ic)) &&
3137 opIsGptr (IC_RIGHT (ic)) &&
3138 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3140 aopPut (AOP (IC_RESULT (ic)),
3141 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3143 isOperandVolatile (IC_RESULT (ic), FALSE));
3146 if (opIsGptr (IC_RESULT (ic)) &&
3147 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3148 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3149 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3150 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3153 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3154 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3159 /*-----------------------------------------------------------------*/
3160 /* genPlus - generates code for addition */
3161 /*-----------------------------------------------------------------*/
3163 genPlus (iCode * ic)
3165 int size, offset = 0;
3167 asmop *leftOp, *rightOp;
3169 /* special cases :- */
3171 D(emitcode ("; genPlus",""));
3173 aopOp (IC_LEFT (ic), ic, FALSE);
3174 aopOp (IC_RIGHT (ic), ic, FALSE);
3175 aopOp (IC_RESULT (ic), ic, TRUE);
3177 /* if literal, literal on the right or
3178 if left requires ACC or right is already
3180 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3181 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3182 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3184 operand *t = IC_RIGHT (ic);
3185 IC_RIGHT (ic) = IC_LEFT (ic);
3189 /* if both left & right are in bit
3191 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3192 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3198 /* if left in bit space & right literal */
3199 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3200 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3202 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3203 /* if result in bit space */
3204 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3206 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3207 emitcode ("cpl", "c");
3208 outBitC (IC_RESULT (ic));
3212 size = getDataSize (IC_RESULT (ic));
3215 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3216 emitcode ("addc", "a,#00");
3217 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3223 /* if I can do an increment instead
3224 of add then GOOD for ME */
3225 if (genPlusIncr (ic) == TRUE)
3228 size = getDataSize (IC_RESULT (ic));
3230 leftOp = AOP(IC_LEFT(ic));
3231 rightOp = AOP(IC_RIGHT(ic));
3236 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3238 emitcode("mov", "b,a");
3239 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3240 emitcode("xch", "a,b");
3241 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3242 emitcode (add, "a,b");
3244 else if (aopGetUsesAcc (leftOp, offset))
3246 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3247 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3251 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3252 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3254 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3255 add = "addc"; /* further adds must propagate carry */
3258 adjustArithmeticResult (ic);
3261 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3262 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3263 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3266 /*-----------------------------------------------------------------*/
3267 /* genMinusDec :- does subtraction with deccrement if possible */
3268 /*-----------------------------------------------------------------*/
3270 genMinusDec (iCode * ic)
3272 unsigned int icount;
3273 unsigned int size = getDataSize (IC_RESULT (ic));
3275 /* will try to generate an increment */
3276 /* if the right side is not a literal
3278 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3281 /* if the literal value of the right hand side
3282 is greater than 4 then it is not worth it */
3283 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3286 D(emitcode ("; genMinusDec",""));
3288 /* if decrement >=16 bits in register or direct space */
3289 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3290 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3298 /* If the next instruction is a goto and the goto target
3299 * is <= 10 instructions previous to this, we can generate
3300 * jumps straight to that target.
3302 if (ic->next && ic->next->op == GOTO
3303 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3304 && labelRange <= 10)
3306 emitcode (";", "tail decrement optimized");
3307 tlbl = IC_LABEL (ic->next);
3312 tlbl = newiTempLabel (NULL);
3316 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3317 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3318 IS_AOP_PREG (IC_RESULT (ic)))
3319 emitcode ("cjne", "%s,#0xff,%05d$"
3320 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3324 emitcode ("mov", "a,#0xff");
3325 emitcode ("cjne", "a,%s,%05d$"
3326 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3329 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3332 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3333 IS_AOP_PREG (IC_RESULT (ic)))
3334 emitcode ("cjne", "%s,#0xff,%05d$"
3335 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3339 emitcode ("cjne", "a,%s,%05d$"
3340 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3343 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3347 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3348 IS_AOP_PREG (IC_RESULT (ic)))
3349 emitcode ("cjne", "%s,#0xff,%05d$"
3350 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3354 emitcode ("cjne", "a,%s,%05d$"
3355 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3358 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3362 emitcode ("", "%05d$:", tlbl->key + 100);
3367 /* if the sizes are greater than 1 then we cannot */
3368 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3369 AOP_SIZE (IC_LEFT (ic)) > 1)
3372 /* we can if the aops of the left & result match or
3373 if they are in registers and the registers are the
3375 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3379 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3387 /*-----------------------------------------------------------------*/
3388 /* addSign - complete with sign */
3389 /*-----------------------------------------------------------------*/
3391 addSign (operand * result, int offset, int sign)
3393 int size = (getDataSize (result) - offset);
3398 emitcode ("rlc", "a");
3399 emitcode ("subb", "a,acc");
3401 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3405 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3409 /*-----------------------------------------------------------------*/
3410 /* genMinusBits - generates code for subtraction of two bits */
3411 /*-----------------------------------------------------------------*/
3413 genMinusBits (iCode * ic)
3415 symbol *lbl = newiTempLabel (NULL);
3417 D(emitcode ("; genMinusBits",""));
3419 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3421 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3422 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3423 emitcode ("cpl", "c");
3424 emitcode ("", "%05d$:", (lbl->key + 100));
3425 outBitC (IC_RESULT (ic));
3429 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3430 emitcode ("subb", "a,acc");
3431 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3432 emitcode ("inc", "a");
3433 emitcode ("", "%05d$:", (lbl->key + 100));
3434 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3435 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3439 /*-----------------------------------------------------------------*/
3440 /* genMinus - generates code for subtraction */
3441 /*-----------------------------------------------------------------*/
3443 genMinus (iCode * ic)
3445 int size, offset = 0;
3447 D(emitcode ("; genMinus",""));
3449 aopOp (IC_LEFT (ic), ic, FALSE);
3450 aopOp (IC_RIGHT (ic), ic, FALSE);
3451 aopOp (IC_RESULT (ic), ic, TRUE);
3453 /* special cases :- */
3454 /* if both left & right are in bit space */
3455 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3456 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3462 /* if I can do an decrement instead
3463 of subtract then GOOD for ME */
3464 if (genMinusDec (ic) == TRUE)
3467 size = getDataSize (IC_RESULT (ic));
3469 /* if literal, add a,#-lit, else normal subb */
3470 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3472 unsigned long lit = 0L;
3474 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3479 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3480 /* first add without previous c */
3482 if (!size && lit== (unsigned long) -1) {
3483 emitcode ("dec", "a");
3485 emitcode ("add", "a,#0x%02x",
3486 (unsigned int) (lit & 0x0FFL));
3489 emitcode ("addc", "a,#0x%02x",
3490 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3492 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3497 asmop *leftOp, *rightOp;
3499 leftOp = AOP(IC_LEFT(ic));
3500 rightOp = AOP(IC_RIGHT(ic));
3504 if (aopGetUsesAcc(rightOp, offset)) {
3505 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3506 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3508 emitcode( "setb", "c");
3510 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3511 emitcode("cpl", "a");
3513 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3516 emitcode ("subb", "a,%s",
3517 aopGet(rightOp, offset, FALSE, TRUE));
3520 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3525 adjustArithmeticResult (ic);
3528 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3529 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3530 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3534 /*-----------------------------------------------------------------*/
3535 /* genMultbits :- multiplication of bits */
3536 /*-----------------------------------------------------------------*/
3538 genMultbits (operand * left,
3542 D(emitcode ("; genMultbits",""));
3544 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3545 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3550 /*-----------------------------------------------------------------*/
3551 /* genMultOneByte : 8*8=8/16 bit multiplication */
3552 /*-----------------------------------------------------------------*/
3554 genMultOneByte (operand * left,
3558 sym_link *opetype = operandType (result);
3560 int size=AOP_SIZE(result);
3562 D(emitcode ("; genMultOneByte",""));
3564 if (size<1 || size>2) {
3565 // this should never happen
3566 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3567 AOP_SIZE(result), __FILE__, lineno);
3571 /* (if two literals: the value is computed before) */
3572 /* if one literal, literal on the right */
3573 if (AOP_TYPE (left) == AOP_LIT)
3578 //emitcode (";", "swapped left and right");
3581 if (SPEC_USIGN(opetype)
3582 // ignore the sign of left and right, what else can we do?
3583 || (SPEC_USIGN(operandType(left)) &&
3584 SPEC_USIGN(operandType(right)))) {
3585 // just an unsigned 8*8=8/16 multiply
3586 //emitcode (";","unsigned");
3587 // TODO: check for accumulator clash between left & right aops?
3588 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3589 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3590 emitcode ("mul", "ab");
3591 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3593 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3598 // we have to do a signed multiply
3600 //emitcode (";", "signed");
3601 emitcode ("clr", "F0"); // reset sign flag
3602 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3604 lbl=newiTempLabel(NULL);
3605 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3606 // left side is negative, 8-bit two's complement, this fails for -128
3607 emitcode ("setb", "F0"); // set sign flag
3608 emitcode ("cpl", "a");
3609 emitcode ("inc", "a");
3611 emitcode ("", "%05d$:", lbl->key+100);
3614 if (AOP_TYPE(right)==AOP_LIT) {
3615 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3616 /* AND literal negative */
3618 emitcode ("cpl", "F0"); // complement sign flag
3619 emitcode ("mov", "b,#0x%02x", -val);
3621 emitcode ("mov", "b,#0x%02x", val);
3624 lbl=newiTempLabel(NULL);
3625 emitcode ("mov", "b,a");
3626 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3627 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3628 // right side is negative, 8-bit two's complement
3629 emitcode ("cpl", "F0"); // complement sign flag
3630 emitcode ("cpl", "a");
3631 emitcode ("inc", "a");
3632 emitcode ("", "%05d$:", lbl->key+100);
3634 emitcode ("mul", "ab");
3636 lbl=newiTempLabel(NULL);
3637 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3638 // only ONE op was negative, we have to do a 8/16-bit two's complement
3639 emitcode ("cpl", "a"); // lsb
3641 emitcode ("inc", "a");
3643 emitcode ("add", "a,#1");
3644 emitcode ("xch", "a,b");
3645 emitcode ("cpl", "a"); // msb
3646 emitcode ("addc", "a,#0");
3647 emitcode ("xch", "a,b");
3650 emitcode ("", "%05d$:", lbl->key+100);
3651 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3653 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3657 /*-----------------------------------------------------------------*/
3658 /* genMult - generates code for multiplication */
3659 /*-----------------------------------------------------------------*/
3661 genMult (iCode * ic)
3663 operand *left = IC_LEFT (ic);
3664 operand *right = IC_RIGHT (ic);
3665 operand *result = IC_RESULT (ic);
3667 D(emitcode ("; genMult",""));
3669 /* assign the amsops */
3670 aopOp (left, ic, FALSE);
3671 aopOp (right, ic, FALSE);
3672 aopOp (result, ic, TRUE);
3674 /* special cases first */
3676 if (AOP_TYPE (left) == AOP_CRY &&
3677 AOP_TYPE (right) == AOP_CRY)
3679 genMultbits (left, right, result);
3683 /* if both are of size == 1 */
3684 #if 0 // one of them can be a sloc shared with the result
3685 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3687 if (getSize(operandType(left)) == 1 &&
3688 getSize(operandType(right)) == 1)
3691 genMultOneByte (left, right, result);
3695 /* should have been converted to function call */
3696 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3697 getSize(OP_SYMBOL(right)->type));
3701 freeAsmop (result, NULL, ic, TRUE);
3702 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3703 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3706 /*-----------------------------------------------------------------*/
3707 /* genDivbits :- division of bits */
3708 /*-----------------------------------------------------------------*/
3710 genDivbits (operand * left,
3717 D(emitcode ("; genDivbits",""));
3719 /* the result must be bit */
3720 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3721 l = aopGet (AOP (left), 0, FALSE, FALSE);
3725 emitcode ("div", "ab");
3726 emitcode ("rrc", "a");
3727 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3730 /*-----------------------------------------------------------------*/
3731 /* genDivOneByte : 8 bit division */
3732 /*-----------------------------------------------------------------*/
3734 genDivOneByte (operand * left,
3738 sym_link *opetype = operandType (result);
3743 D(emitcode ("; genDivOneByte",""));
3745 size = AOP_SIZE (result) - 1;
3747 /* signed or unsigned */
3748 if (SPEC_USIGN (opetype))
3750 /* unsigned is easy */
3751 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3752 l = aopGet (AOP (left), 0, FALSE, FALSE);
3754 emitcode ("div", "ab");
3755 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3757 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3761 /* signed is a little bit more difficult */
3763 /* save the signs of the operands */
3764 l = aopGet (AOP (left), 0, FALSE, FALSE);
3766 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3767 emitcode ("push", "acc"); /* save it on the stack */
3769 /* now sign adjust for both left & right */
3770 l = aopGet (AOP (right), 0, FALSE, FALSE);
3772 lbl = newiTempLabel (NULL);
3773 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3774 emitcode ("cpl", "a");
3775 emitcode ("inc", "a");
3776 emitcode ("", "%05d$:", (lbl->key + 100));
3777 emitcode ("mov", "b,a");
3779 /* sign adjust left side */
3780 l = aopGet (AOP (left), 0, FALSE, FALSE);
3783 lbl = newiTempLabel (NULL);
3784 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3785 emitcode ("cpl", "a");
3786 emitcode ("inc", "a");
3787 emitcode ("", "%05d$:", (lbl->key + 100));
3789 /* now the division */
3790 emitcode ("div", "ab");
3791 /* we are interested in the lower order
3793 emitcode ("mov", "b,a");
3794 lbl = newiTempLabel (NULL);
3795 emitcode ("pop", "acc");
3796 /* if there was an over flow we don't
3797 adjust the sign of the result */
3798 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3799 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3801 emitcode ("clr", "a");
3802 emitcode ("subb", "a,b");
3803 emitcode ("mov", "b,a");
3804 emitcode ("", "%05d$:", (lbl->key + 100));
3806 /* now we are done */
3807 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3810 emitcode ("mov", "c,b.7");
3811 emitcode ("subb", "a,acc");
3814 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3818 /*-----------------------------------------------------------------*/
3819 /* genDiv - generates code for division */
3820 /*-----------------------------------------------------------------*/
3824 operand *left = IC_LEFT (ic);
3825 operand *right = IC_RIGHT (ic);
3826 operand *result = IC_RESULT (ic);
3828 D(emitcode ("; genDiv",""));
3830 /* assign the amsops */
3831 aopOp (left, ic, FALSE);
3832 aopOp (right, ic, FALSE);
3833 aopOp (result, ic, TRUE);
3835 /* special cases first */
3837 if (AOP_TYPE (left) == AOP_CRY &&
3838 AOP_TYPE (right) == AOP_CRY)
3840 genDivbits (left, right, result);
3844 /* if both are of size == 1 */
3845 if (AOP_SIZE (left) == 1 &&
3846 AOP_SIZE (right) == 1)
3848 genDivOneByte (left, right, result);
3852 /* should have been converted to function call */
3855 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3856 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3857 freeAsmop (result, NULL, ic, TRUE);
3860 /*-----------------------------------------------------------------*/
3861 /* genModbits :- modulus of bits */
3862 /*-----------------------------------------------------------------*/
3864 genModbits (operand * left,
3871 D(emitcode ("; genModbits",""));
3873 /* the result must be bit */
3874 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3875 l = aopGet (AOP (left), 0, FALSE, FALSE);
3879 emitcode ("div", "ab");
3880 emitcode ("mov", "a,b");
3881 emitcode ("rrc", "a");
3882 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3885 /*-----------------------------------------------------------------*/
3886 /* genModOneByte : 8 bit modulus */
3887 /*-----------------------------------------------------------------*/
3889 genModOneByte (operand * left,
3893 sym_link *opetype = operandType (result);
3897 D(emitcode ("; genModOneByte",""));
3899 /* signed or unsigned */
3900 if (SPEC_USIGN (opetype))
3902 /* unsigned is easy */
3903 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3904 l = aopGet (AOP (left), 0, FALSE, FALSE);
3906 emitcode ("div", "ab");
3907 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3911 /* signed is a little bit more difficult */
3913 /* save the signs of the operands */
3914 l = aopGet (AOP (left), 0, FALSE, FALSE);
3917 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3918 emitcode ("push", "acc"); /* save it on the stack */
3920 /* now sign adjust for both left & right */
3921 l = aopGet (AOP (right), 0, FALSE, FALSE);
3924 lbl = newiTempLabel (NULL);
3925 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3926 emitcode ("cpl", "a");
3927 emitcode ("inc", "a");
3928 emitcode ("", "%05d$:", (lbl->key + 100));
3929 emitcode ("mov", "b,a");
3931 /* sign adjust left side */
3932 l = aopGet (AOP (left), 0, FALSE, FALSE);
3935 lbl = newiTempLabel (NULL);
3936 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3937 emitcode ("cpl", "a");
3938 emitcode ("inc", "a");
3939 emitcode ("", "%05d$:", (lbl->key + 100));
3941 /* now the multiplication */
3942 emitcode ("div", "ab");
3943 /* we are interested in the lower order
3945 lbl = newiTempLabel (NULL);
3946 emitcode ("pop", "acc");
3947 /* if there was an over flow we don't
3948 adjust the sign of the result */
3949 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3950 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3952 emitcode ("clr", "a");
3953 emitcode ("subb", "a,b");
3954 emitcode ("mov", "b,a");
3955 emitcode ("", "%05d$:", (lbl->key + 100));
3957 /* now we are done */
3958 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3962 /*-----------------------------------------------------------------*/
3963 /* genMod - generates code for division */
3964 /*-----------------------------------------------------------------*/
3968 operand *left = IC_LEFT (ic);
3969 operand *right = IC_RIGHT (ic);
3970 operand *result = IC_RESULT (ic);
3972 D(emitcode ("; genMod",""));
3974 /* assign the amsops */
3975 aopOp (left, ic, FALSE);
3976 aopOp (right, ic, FALSE);
3977 aopOp (result, ic, TRUE);
3979 /* special cases first */
3981 if (AOP_TYPE (left) == AOP_CRY &&
3982 AOP_TYPE (right) == AOP_CRY)
3984 genModbits (left, right, result);
3988 /* if both are of size == 1 */
3989 if (AOP_SIZE (left) == 1 &&
3990 AOP_SIZE (right) == 1)
3992 genModOneByte (left, right, result);
3996 /* should have been converted to function call */
4000 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4001 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4002 freeAsmop (result, NULL, ic, TRUE);
4005 /*-----------------------------------------------------------------*/
4006 /* genIfxJump :- will create a jump depending on the ifx */
4007 /*-----------------------------------------------------------------*/
4009 genIfxJump (iCode * ic, char *jval)
4012 symbol *tlbl = newiTempLabel (NULL);
4015 D(emitcode ("; genIfxJump",""));
4017 /* if true label then we jump if condition
4021 jlbl = IC_TRUE (ic);
4022 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4023 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4027 /* false label is present */
4028 jlbl = IC_FALSE (ic);
4029 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4030 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4032 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4033 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4035 emitcode (inst, "%05d$", tlbl->key + 100);
4036 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4037 emitcode ("", "%05d$:", tlbl->key + 100);
4039 /* mark the icode as generated */
4043 /*-----------------------------------------------------------------*/
4044 /* genCmp :- greater or less than comparison */
4045 /*-----------------------------------------------------------------*/
4047 genCmp (operand * left, operand * right,
4048 operand * result, iCode * ifx, int sign, iCode *ic)
4050 int size, offset = 0;
4051 unsigned long lit = 0L;
4054 D(emitcode ("; genCmp",""));
4056 /* if left & right are bit variables */
4057 if (AOP_TYPE (left) == AOP_CRY &&
4058 AOP_TYPE (right) == AOP_CRY)
4060 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4061 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4065 /* subtract right from left if at the
4066 end the carry flag is set then we know that
4067 left is greater than right */
4068 size = max (AOP_SIZE (left), AOP_SIZE (right));
4070 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4071 if ((size == 1) && !sign &&
4072 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4074 symbol *lbl = newiTempLabel (NULL);
4075 emitcode ("cjne", "%s,%s,%05d$",
4076 aopGet (AOP (left), offset, FALSE, FALSE),
4077 aopGet (AOP (right), offset, FALSE, FALSE),
4079 emitcode ("", "%05d$:", lbl->key + 100);
4083 if (AOP_TYPE (right) == AOP_LIT)
4085 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4086 /* optimize if(x < 0) or if(x >= 0) */
4095 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4096 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4098 genIfxJump (ifx, "acc.7");
4102 emitcode ("rlc", "a");
4110 rightInB = aopGetUsesAcc(AOP (right), offset);
4112 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4113 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4114 if (sign && size == 0)
4116 emitcode ("xrl", "a,#0x80");
4117 if (AOP_TYPE (right) == AOP_LIT)
4119 unsigned long lit = (unsigned long)
4120 floatFromVal (AOP (right)->aopu.aop_lit);
4121 emitcode ("subb", "a,#0x%02x",
4122 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4127 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4128 emitcode ("xrl", "b,#0x80");
4129 emitcode ("subb", "a,b");
4135 emitcode ("subb", "a,b");
4137 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4145 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4146 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4147 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4153 /* if the result is used in the next
4154 ifx conditional branch then generate
4155 code a little differently */
4157 genIfxJump (ifx, "c");
4160 /* leave the result in acc */
4164 /*-----------------------------------------------------------------*/
4165 /* genCmpGt :- greater than comparison */
4166 /*-----------------------------------------------------------------*/
4168 genCmpGt (iCode * ic, iCode * ifx)
4170 operand *left, *right, *result;
4171 sym_link *letype, *retype;
4174 D(emitcode ("; genCmpGt",""));
4176 left = IC_LEFT (ic);
4177 right = IC_RIGHT (ic);
4178 result = IC_RESULT (ic);
4180 letype = getSpec (operandType (left));
4181 retype = getSpec (operandType (right));
4182 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4183 /* assign the amsops */
4184 aopOp (left, ic, FALSE);
4185 aopOp (right, ic, FALSE);
4186 aopOp (result, ic, TRUE);
4188 genCmp (right, left, result, ifx, sign,ic);
4190 freeAsmop (result, NULL, ic, TRUE);
4193 /*-----------------------------------------------------------------*/
4194 /* genCmpLt - less than comparisons */
4195 /*-----------------------------------------------------------------*/
4197 genCmpLt (iCode * ic, iCode * ifx)
4199 operand *left, *right, *result;
4200 sym_link *letype, *retype;
4203 D(emitcode ("; genCmpLt",""));
4205 left = IC_LEFT (ic);
4206 right = IC_RIGHT (ic);
4207 result = IC_RESULT (ic);
4209 letype = getSpec (operandType (left));
4210 retype = getSpec (operandType (right));
4211 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4213 /* assign the amsops */
4214 aopOp (left, ic, FALSE);
4215 aopOp (right, ic, FALSE);
4216 aopOp (result, ic, TRUE);
4218 genCmp (left, right, result, ifx, sign,ic);
4220 freeAsmop (result, NULL, ic, TRUE);
4223 /*-----------------------------------------------------------------*/
4224 /* gencjneshort - compare and jump if not equal */
4225 /*-----------------------------------------------------------------*/
4227 gencjneshort (operand * left, operand * right, symbol * lbl)
4229 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4231 unsigned long lit = 0L;
4233 /* if the left side is a literal or
4234 if the right is in a pointer register and left
4236 if ((AOP_TYPE (left) == AOP_LIT) ||
4237 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4243 if (AOP_TYPE (right) == AOP_LIT)
4244 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4246 /* if the right side is a literal then anything goes */
4247 if (AOP_TYPE (right) == AOP_LIT &&
4248 AOP_TYPE (left) != AOP_DIR &&
4249 AOP_TYPE (left) != AOP_IMMD)
4253 emitcode ("cjne", "%s,%s,%05d$",
4254 aopGet (AOP (left), offset, FALSE, FALSE),
4255 aopGet (AOP (right), offset, FALSE, FALSE),
4261 /* if the right side is in a register or in direct space or
4262 if the left is a pointer register & right is not */
4263 else if (AOP_TYPE (right) == AOP_REG ||
4264 AOP_TYPE (right) == AOP_DIR ||
4265 AOP_TYPE (right) == AOP_LIT ||
4266 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4267 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4271 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4272 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4273 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4274 emitcode ("jnz", "%05d$", lbl->key + 100);
4276 emitcode ("cjne", "a,%s,%05d$",
4277 aopGet (AOP (right), offset, FALSE, TRUE),
4284 /* right is a pointer reg need both a & b */
4287 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4288 if (strcmp (l, "b"))
4289 emitcode ("mov", "b,%s", l);
4290 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4291 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4297 /*-----------------------------------------------------------------*/
4298 /* gencjne - compare and jump if not equal */
4299 /*-----------------------------------------------------------------*/
4301 gencjne (operand * left, operand * right, symbol * lbl)
4303 symbol *tlbl = newiTempLabel (NULL);
4305 gencjneshort (left, right, lbl);
4307 emitcode ("mov", "a,%s", one);
4308 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4309 emitcode ("", "%05d$:", lbl->key + 100);
4310 emitcode ("clr", "a");
4311 emitcode ("", "%05d$:", tlbl->key + 100);
4314 /*-----------------------------------------------------------------*/
4315 /* genCmpEq - generates code for equal to */
4316 /*-----------------------------------------------------------------*/
4318 genCmpEq (iCode * ic, iCode * ifx)
4320 operand *left, *right, *result;
4322 D(emitcode ("; genCmpEq",""));
4324 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4325 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4326 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4328 /* if literal, literal on the right or
4329 if the right is in a pointer register and left
4331 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4332 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4334 operand *t = IC_RIGHT (ic);
4335 IC_RIGHT (ic) = IC_LEFT (ic);
4339 if (ifx && !AOP_SIZE (result))
4342 /* if they are both bit variables */
4343 if (AOP_TYPE (left) == AOP_CRY &&
4344 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4346 if (AOP_TYPE (right) == AOP_LIT)
4348 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4351 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4352 emitcode ("cpl", "c");
4356 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4360 emitcode ("clr", "c");
4362 /* AOP_TYPE(right) == AOP_CRY */
4366 symbol *lbl = newiTempLabel (NULL);
4367 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4368 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4369 emitcode ("cpl", "c");
4370 emitcode ("", "%05d$:", (lbl->key + 100));
4372 /* if true label then we jump if condition
4374 tlbl = newiTempLabel (NULL);
4377 emitcode ("jnc", "%05d$", tlbl->key + 100);
4378 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4382 emitcode ("jc", "%05d$", tlbl->key + 100);
4383 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4385 emitcode ("", "%05d$:", tlbl->key + 100);
4389 tlbl = newiTempLabel (NULL);
4390 gencjneshort (left, right, tlbl);
4393 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4394 emitcode ("", "%05d$:", tlbl->key + 100);
4398 symbol *lbl = newiTempLabel (NULL);
4399 emitcode ("sjmp", "%05d$", lbl->key + 100);
4400 emitcode ("", "%05d$:", tlbl->key + 100);
4401 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4402 emitcode ("", "%05d$:", lbl->key + 100);
4405 /* mark the icode as generated */
4410 /* if they are both bit variables */
4411 if (AOP_TYPE (left) == AOP_CRY &&
4412 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4414 if (AOP_TYPE (right) == AOP_LIT)
4416 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4419 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4420 emitcode ("cpl", "c");
4424 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4428 emitcode ("clr", "c");
4430 /* AOP_TYPE(right) == AOP_CRY */
4434 symbol *lbl = newiTempLabel (NULL);
4435 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4436 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4437 emitcode ("cpl", "c");
4438 emitcode ("", "%05d$:", (lbl->key + 100));
4441 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4448 genIfxJump (ifx, "c");
4451 /* if the result is used in an arithmetic operation
4452 then put the result in place */
4457 gencjne (left, right, newiTempLabel (NULL));
4458 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4460 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4465 genIfxJump (ifx, "a");
4468 /* if the result is used in an arithmetic operation
4469 then put the result in place */
4470 if (AOP_TYPE (result) != AOP_CRY)
4472 /* leave the result in acc */
4476 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4477 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4478 freeAsmop (result, NULL, ic, TRUE);
4481 /*-----------------------------------------------------------------*/
4482 /* ifxForOp - returns the icode containing the ifx for operand */
4483 /*-----------------------------------------------------------------*/
4485 ifxForOp (operand * op, iCode * ic)
4487 /* if true symbol then needs to be assigned */
4488 if (IS_TRUE_SYMOP (op))
4491 /* if this has register type condition and
4492 the next instruction is ifx with the same operand
4493 and live to of the operand is upto the ifx only then */
4495 ic->next->op == IFX &&
4496 IC_COND (ic->next)->key == op->key &&
4497 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4503 /*-----------------------------------------------------------------*/
4504 /* hasInc - operand is incremented before any other use */
4505 /*-----------------------------------------------------------------*/
4507 hasInc (operand *op, iCode *ic,int osize)
4509 sym_link *type = operandType(op);
4510 sym_link *retype = getSpec (type);
4511 iCode *lic = ic->next;
4514 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4515 if (!IS_SYMOP(op)) return NULL;
4517 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4518 if (IS_AGGREGATE(type->next)) return NULL;
4519 if (osize != (isize = getSize(type->next))) return NULL;
4522 /* if operand of the form op = op + <sizeof *op> */
4523 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4524 isOperandEqual(IC_RESULT(lic),op) &&
4525 isOperandLiteral(IC_RIGHT(lic)) &&
4526 operandLitValue(IC_RIGHT(lic)) == isize) {
4529 /* if the operand used or deffed */
4530 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4533 /* if GOTO or IFX */
4534 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4540 /*-----------------------------------------------------------------*/
4541 /* genAndOp - for && operation */
4542 /*-----------------------------------------------------------------*/
4544 genAndOp (iCode * ic)
4546 operand *left, *right, *result;
4549 D(emitcode ("; genAndOp",""));
4551 /* note here that && operations that are in an
4552 if statement are taken away by backPatchLabels
4553 only those used in arthmetic operations remain */
4554 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4555 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4556 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4558 /* if both are bit variables */
4559 if (AOP_TYPE (left) == AOP_CRY &&
4560 AOP_TYPE (right) == AOP_CRY)
4562 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4563 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4568 tlbl = newiTempLabel (NULL);
4570 emitcode ("jz", "%05d$", tlbl->key + 100);
4572 emitcode ("", "%05d$:", tlbl->key + 100);
4576 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4577 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 freeAsmop (result, NULL, ic, TRUE);
4582 /*-----------------------------------------------------------------*/
4583 /* genOrOp - for || operation */
4584 /*-----------------------------------------------------------------*/
4586 genOrOp (iCode * ic)
4588 operand *left, *right, *result;
4591 D(emitcode ("; genOrOp",""));
4593 /* note here that || operations that are in an
4594 if statement are taken away by backPatchLabels
4595 only those used in arthmetic operations remain */
4596 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4597 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4598 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4600 /* if both are bit variables */
4601 if (AOP_TYPE (left) == AOP_CRY &&
4602 AOP_TYPE (right) == AOP_CRY)
4604 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4605 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4610 tlbl = newiTempLabel (NULL);
4612 emitcode ("jnz", "%05d$", tlbl->key + 100);
4614 emitcode ("", "%05d$:", tlbl->key + 100);
4618 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4619 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620 freeAsmop (result, NULL, ic, TRUE);
4623 /*-----------------------------------------------------------------*/
4624 /* isLiteralBit - test if lit == 2^n */
4625 /*-----------------------------------------------------------------*/
4627 isLiteralBit (unsigned long lit)
4629 unsigned long pw[32] =
4630 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4631 0x100L, 0x200L, 0x400L, 0x800L,
4632 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4633 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4634 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4635 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4636 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4639 for (idx = 0; idx < 32; idx++)
4645 /*-----------------------------------------------------------------*/
4646 /* continueIfTrue - */
4647 /*-----------------------------------------------------------------*/
4649 continueIfTrue (iCode * ic)
4652 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4656 /*-----------------------------------------------------------------*/
4658 /*-----------------------------------------------------------------*/
4660 jumpIfTrue (iCode * ic)
4663 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4667 /*-----------------------------------------------------------------*/
4668 /* jmpTrueOrFalse - */
4669 /*-----------------------------------------------------------------*/
4671 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4673 // ugly but optimized by peephole
4676 symbol *nlbl = newiTempLabel (NULL);
4677 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4678 emitcode ("", "%05d$:", tlbl->key + 100);
4679 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4680 emitcode ("", "%05d$:", nlbl->key + 100);
4684 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4685 emitcode ("", "%05d$:", tlbl->key + 100);
4690 /*-----------------------------------------------------------------*/
4691 /* genAnd - code for and */
4692 /*-----------------------------------------------------------------*/
4694 genAnd (iCode * ic, iCode * ifx)
4696 operand *left, *right, *result;
4697 int size, offset = 0;
4698 unsigned long lit = 0L;
4702 D(emitcode ("; genAnd",""));
4704 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4705 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4706 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4709 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4711 AOP_TYPE (left), AOP_TYPE (right));
4712 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4714 AOP_SIZE (left), AOP_SIZE (right));
4717 /* if left is a literal & right is not then exchange them */
4718 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4719 AOP_NEEDSACC (left))
4721 operand *tmp = right;
4726 /* if result = right then exchange them */
4727 if (sameRegs (AOP (result), AOP (right)))
4729 operand *tmp = right;
4734 /* if right is bit then exchange them */
4735 if (AOP_TYPE (right) == AOP_CRY &&
4736 AOP_TYPE (left) != AOP_CRY)
4738 operand *tmp = right;
4742 if (AOP_TYPE (right) == AOP_LIT)
4743 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4745 size = AOP_SIZE (result);
4748 // result = bit & yy;
4749 if (AOP_TYPE (left) == AOP_CRY)
4751 // c = bit & literal;
4752 if (AOP_TYPE (right) == AOP_LIT)
4756 if (size && sameRegs (AOP (result), AOP (left)))
4759 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4764 if (size && (AOP_TYPE (result) == AOP_CRY))
4766 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4769 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4774 emitcode ("clr", "c");
4779 if (AOP_TYPE (right) == AOP_CRY)
4782 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4783 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4788 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4790 emitcode ("rrc", "a");
4791 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4799 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4800 genIfxJump (ifx, "c");
4804 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4805 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4806 if ((AOP_TYPE (right) == AOP_LIT) &&
4807 (AOP_TYPE (result) == AOP_CRY) &&
4808 (AOP_TYPE (left) != AOP_CRY))
4810 int posbit = isLiteralBit (lit);
4815 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4818 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4824 sprintf (buffer, "acc.%d", posbit & 0x07);
4825 genIfxJump (ifx, buffer);
4832 symbol *tlbl = newiTempLabel (NULL);
4833 int sizel = AOP_SIZE (left);
4835 emitcode ("setb", "c");
4838 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4840 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4842 if ((posbit = isLiteralBit (bytelit)) != 0)
4843 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4846 if (bytelit != 0x0FFL)
4847 emitcode ("anl", "a,%s",
4848 aopGet (AOP (right), offset, FALSE, TRUE));
4849 emitcode ("jnz", "%05d$", tlbl->key + 100);
4854 // bit = left & literal
4857 emitcode ("clr", "c");
4858 emitcode ("", "%05d$:", tlbl->key + 100);
4860 // if(left & literal)
4864 jmpTrueOrFalse (ifx, tlbl);
4872 /* if left is same as result */
4873 if (sameRegs (AOP (result), AOP (left)))
4875 for (; size--; offset++)
4877 if (AOP_TYPE (right) == AOP_LIT)
4879 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4881 else if (bytelit == 0)
4883 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4885 else if (IS_AOP_PREG (result))
4887 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4888 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4889 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4892 emitcode ("anl", "%s,%s",
4893 aopGet (AOP (left), offset, FALSE, TRUE),
4894 aopGet (AOP (right), offset, FALSE, FALSE));
4898 if (AOP_TYPE (left) == AOP_ACC)
4899 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4902 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4903 if (IS_AOP_PREG (result))
4905 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4906 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4910 emitcode ("anl", "%s,a",
4911 aopGet (AOP (left), offset, FALSE, TRUE));
4918 // left & result in different registers
4919 if (AOP_TYPE (result) == AOP_CRY)
4922 // if(size), result in bit
4923 // if(!size && ifx), conditional oper: if(left & right)
4924 symbol *tlbl = newiTempLabel (NULL);
4925 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4927 emitcode ("setb", "c");
4930 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4931 emitcode ("anl", "a,%s",
4932 aopGet (AOP (right), offset, FALSE, FALSE));
4934 if (AOP_TYPE(left)==AOP_ACC) {
4935 emitcode("mov", "b,a");
4936 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4937 emitcode("anl", "a,b");
4939 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4940 emitcode ("anl", "a,%s",
4941 aopGet (AOP (left), offset, FALSE, FALSE));
4944 emitcode ("jnz", "%05d$", tlbl->key + 100);
4950 emitcode ("", "%05d$:", tlbl->key + 100);
4954 jmpTrueOrFalse (ifx, tlbl);
4958 for (; (size--); offset++)
4961 // result = left & right
4962 if (AOP_TYPE (right) == AOP_LIT)
4964 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4966 aopPut (AOP (result),
4967 aopGet (AOP (left), offset, FALSE, FALSE),
4969 isOperandVolatile (result, FALSE));
4972 else if (bytelit == 0)
4974 /* dummy read of volatile operand */
4975 if (isOperandVolatile (left, FALSE))
4976 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4977 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4981 // faster than result <- left, anl result,right
4982 // and better if result is SFR
4983 if (AOP_TYPE (left) == AOP_ACC)
4984 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4987 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4988 emitcode ("anl", "a,%s",
4989 aopGet (AOP (left), offset, FALSE, FALSE));
4991 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4998 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4999 freeAsmop (result, NULL, ic, TRUE);
5002 /*-----------------------------------------------------------------*/
5003 /* genOr - code for or */
5004 /*-----------------------------------------------------------------*/
5006 genOr (iCode * ic, iCode * ifx)
5008 operand *left, *right, *result;
5009 int size, offset = 0;
5010 unsigned long lit = 0L;
5012 D(emitcode ("; genOr",""));
5014 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5015 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5016 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5019 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5021 AOP_TYPE (left), AOP_TYPE (right));
5022 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5024 AOP_SIZE (left), AOP_SIZE (right));
5027 /* if left is a literal & right is not then exchange them */
5028 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5029 AOP_NEEDSACC (left))
5031 operand *tmp = right;
5036 /* if result = right then exchange them */
5037 if (sameRegs (AOP (result), AOP (right)))
5039 operand *tmp = right;
5044 /* if right is bit then exchange them */
5045 if (AOP_TYPE (right) == AOP_CRY &&
5046 AOP_TYPE (left) != AOP_CRY)
5048 operand *tmp = right;
5052 if (AOP_TYPE (right) == AOP_LIT)
5053 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5055 size = AOP_SIZE (result);
5059 if (AOP_TYPE (left) == AOP_CRY)
5061 if (AOP_TYPE (right) == AOP_LIT)
5063 // c = bit | literal;
5066 // lit != 0 => result = 1
5067 if (AOP_TYPE (result) == AOP_CRY)
5070 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5072 continueIfTrue (ifx);
5075 emitcode ("setb", "c");
5079 // lit == 0 => result = left
5080 if (size && sameRegs (AOP (result), AOP (left)))
5082 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5087 if (AOP_TYPE (right) == AOP_CRY)
5090 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5091 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5096 symbol *tlbl = newiTempLabel (NULL);
5097 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5098 emitcode ("setb", "c");
5099 emitcode ("jb", "%s,%05d$",
5100 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5102 emitcode ("jnz", "%05d$", tlbl->key + 100);
5103 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5105 jmpTrueOrFalse (ifx, tlbl);
5111 emitcode ("", "%05d$:", tlbl->key + 100);
5120 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5121 genIfxJump (ifx, "c");
5125 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5126 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5127 if ((AOP_TYPE (right) == AOP_LIT) &&
5128 (AOP_TYPE (result) == AOP_CRY) &&
5129 (AOP_TYPE (left) != AOP_CRY))
5135 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5137 continueIfTrue (ifx);
5142 // lit = 0, result = boolean(left)
5144 emitcode ("setb", "c");
5148 symbol *tlbl = newiTempLabel (NULL);
5149 emitcode ("jnz", "%05d$", tlbl->key + 100);
5151 emitcode ("", "%05d$:", tlbl->key + 100);
5155 genIfxJump (ifx, "a");
5163 /* if left is same as result */
5164 if (sameRegs (AOP (result), AOP (left)))
5166 for (; size--; offset++)
5168 if (AOP_TYPE (right) == AOP_LIT)
5170 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5172 /* dummy read of volatile operand */
5173 if (isOperandVolatile (left, FALSE))
5174 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5178 else if (IS_AOP_PREG (left))
5180 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5181 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5182 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5185 emitcode ("orl", "%s,%s",
5186 aopGet (AOP (left), offset, FALSE, TRUE),
5187 aopGet (AOP (right), offset, FALSE, FALSE));
5191 if (AOP_TYPE (left) == AOP_ACC)
5192 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5195 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5196 if (IS_AOP_PREG (left))
5198 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5199 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5202 emitcode ("orl", "%s,a",
5203 aopGet (AOP (left), offset, FALSE, TRUE));
5210 // left & result in different registers
5211 if (AOP_TYPE (result) == AOP_CRY)
5214 // if(size), result in bit
5215 // if(!size && ifx), conditional oper: if(left | right)
5216 symbol *tlbl = newiTempLabel (NULL);
5217 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5219 emitcode ("setb", "c");
5222 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5223 emitcode ("orl", "a,%s",
5224 aopGet (AOP (right), offset, FALSE, FALSE));
5226 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5227 emitcode ("orl", "a,%s",
5228 aopGet (AOP (left), offset, FALSE, FALSE));
5230 emitcode ("jnz", "%05d$", tlbl->key + 100);
5236 emitcode ("", "%05d$:", tlbl->key + 100);
5240 jmpTrueOrFalse (ifx, tlbl);
5243 for (; (size--); offset++)
5246 // result = left & right
5247 if (AOP_TYPE (right) == AOP_LIT)
5249 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5251 aopPut (AOP (result),
5252 aopGet (AOP (left), offset, FALSE, FALSE),
5254 isOperandVolatile (result, FALSE));
5258 // faster than result <- left, anl result,right
5259 // and better if result is SFR
5260 if (AOP_TYPE (left) == AOP_ACC)
5261 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5264 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5265 emitcode ("orl", "a,%s",
5266 aopGet (AOP (left), offset, FALSE, FALSE));
5268 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5273 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5274 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5275 freeAsmop (result, NULL, ic, TRUE);
5278 /*-----------------------------------------------------------------*/
5279 /* genXor - code for xclusive or */
5280 /*-----------------------------------------------------------------*/
5282 genXor (iCode * ic, iCode * ifx)
5284 operand *left, *right, *result;
5285 int size, offset = 0;
5286 unsigned long lit = 0L;
5288 D(emitcode ("; genXor",""));
5290 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5291 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5292 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5295 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5297 AOP_TYPE (left), AOP_TYPE (right));
5298 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5300 AOP_SIZE (left), AOP_SIZE (right));
5303 /* if left is a literal & right is not ||
5304 if left needs acc & right does not */
5305 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5306 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5308 operand *tmp = right;
5313 /* if result = right then exchange them */
5314 if (sameRegs (AOP (result), AOP (right)))
5316 operand *tmp = right;
5321 /* if right is bit then exchange them */
5322 if (AOP_TYPE (right) == AOP_CRY &&
5323 AOP_TYPE (left) != AOP_CRY)
5325 operand *tmp = right;
5329 if (AOP_TYPE (right) == AOP_LIT)
5330 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5332 size = AOP_SIZE (result);
5336 if (AOP_TYPE (left) == AOP_CRY)
5338 if (AOP_TYPE (right) == AOP_LIT)
5340 // c = bit & literal;
5343 // lit>>1 != 0 => result = 1
5344 if (AOP_TYPE (result) == AOP_CRY)
5347 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5349 continueIfTrue (ifx);
5352 emitcode ("setb", "c");
5359 // lit == 0, result = left
5360 if (size && sameRegs (AOP (result), AOP (left)))
5362 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5366 // lit == 1, result = not(left)
5367 if (size && sameRegs (AOP (result), AOP (left)))
5369 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5374 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5375 emitcode ("cpl", "c");
5384 symbol *tlbl = newiTempLabel (NULL);
5385 if (AOP_TYPE (right) == AOP_CRY)
5388 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5392 int sizer = AOP_SIZE (right);
5394 // if val>>1 != 0, result = 1
5395 emitcode ("setb", "c");
5398 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5400 // test the msb of the lsb
5401 emitcode ("anl", "a,#0xfe");
5402 emitcode ("jnz", "%05d$", tlbl->key + 100);
5406 emitcode ("rrc", "a");
5408 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5409 emitcode ("cpl", "c");
5410 emitcode ("", "%05d$:", (tlbl->key + 100));
5417 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5418 genIfxJump (ifx, "c");
5422 if (sameRegs (AOP (result), AOP (left)))
5424 /* if left is same as result */
5425 for (; size--; offset++)
5427 if (AOP_TYPE (right) == AOP_LIT)
5429 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5431 else if (IS_AOP_PREG (left))
5433 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5434 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5435 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5438 emitcode ("xrl", "%s,%s",
5439 aopGet (AOP (left), offset, FALSE, TRUE),
5440 aopGet (AOP (right), offset, FALSE, FALSE));
5444 if (AOP_TYPE (left) == AOP_ACC)
5445 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5448 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5449 if (IS_AOP_PREG (left))
5451 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5452 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5455 emitcode ("xrl", "%s,a",
5456 aopGet (AOP (left), offset, FALSE, TRUE));
5463 // left & result in different registers
5464 if (AOP_TYPE (result) == AOP_CRY)
5467 // if(size), result in bit
5468 // if(!size && ifx), conditional oper: if(left ^ right)
5469 symbol *tlbl = newiTempLabel (NULL);
5470 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5472 emitcode ("setb", "c");
5475 if ((AOP_TYPE (right) == AOP_LIT) &&
5476 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5478 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5482 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5483 emitcode ("xrl", "a,%s",
5484 aopGet (AOP (right), offset, FALSE, FALSE));
5486 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5487 emitcode ("xrl", "a,%s",
5488 aopGet (AOP (left), offset, FALSE, FALSE));
5491 emitcode ("jnz", "%05d$", tlbl->key + 100);
5497 emitcode ("", "%05d$:", tlbl->key + 100);
5501 jmpTrueOrFalse (ifx, tlbl);
5504 for (; (size--); offset++)
5507 // result = left & right
5508 if (AOP_TYPE (right) == AOP_LIT)
5510 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5512 aopPut (AOP (result),
5513 aopGet (AOP (left), offset, FALSE, FALSE),
5515 isOperandVolatile (result, FALSE));
5519 // faster than result <- left, anl result,right
5520 // and better if result is SFR
5521 if (AOP_TYPE (left) == AOP_ACC)
5522 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5525 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5526 emitcode ("xrl", "a,%s",
5527 aopGet (AOP (left), offset, FALSE, TRUE));
5529 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5534 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5536 freeAsmop (result, NULL, ic, TRUE);
5539 /*-----------------------------------------------------------------*/
5540 /* genInline - write the inline code out */
5541 /*-----------------------------------------------------------------*/
5543 genInline (iCode * ic)
5545 char *buffer, *bp, *bp1;
5547 D(emitcode ("; genInline",""));
5549 _G.inLine += (!options.asmpeep);
5551 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5552 strcpy (buffer, IC_INLINE (ic));
5554 /* emit each line as a code */
5579 /* emitcode("",buffer); */
5580 _G.inLine -= (!options.asmpeep);
5583 /*-----------------------------------------------------------------*/
5584 /* genRRC - rotate right with carry */
5585 /*-----------------------------------------------------------------*/
5589 operand *left, *result;
5590 int size, offset = 0;
5593 D(emitcode ("; genRRC",""));
5595 /* rotate right with carry */
5596 left = IC_LEFT (ic);
5597 result = IC_RESULT (ic);
5598 aopOp (left, ic, FALSE);
5599 aopOp (result, ic, FALSE);
5601 /* move it to the result */
5602 size = AOP_SIZE (result);
5604 if (size == 1) { /* special case for 1 byte */
5605 l = aopGet (AOP (left), offset, FALSE, FALSE);
5607 emitcode ("rr", "a");
5613 l = aopGet (AOP (left), offset, FALSE, FALSE);
5615 emitcode ("rrc", "a");
5616 if (AOP_SIZE (result) > 1)
5617 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5619 /* now we need to put the carry into the
5620 highest order byte of the result */
5621 if (AOP_SIZE (result) > 1)
5623 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5626 emitcode ("mov", "acc.7,c");
5628 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5629 freeAsmop (left, NULL, ic, TRUE);
5630 freeAsmop (result, NULL, ic, TRUE);
5633 /*-----------------------------------------------------------------*/
5634 /* genRLC - generate code for rotate left with carry */
5635 /*-----------------------------------------------------------------*/
5639 operand *left, *result;
5640 int size, offset = 0;
5643 D(emitcode ("; genRLC",""));
5645 /* rotate right with carry */
5646 left = IC_LEFT (ic);
5647 result = IC_RESULT (ic);
5648 aopOp (left, ic, FALSE);
5649 aopOp (result, ic, FALSE);
5651 /* move it to the result */
5652 size = AOP_SIZE (result);
5656 l = aopGet (AOP (left), offset, FALSE, FALSE);
5658 if (size == 0) { /* special case for 1 byte */
5662 emitcode ("add", "a,acc");
5663 if (AOP_SIZE (result) > 1)
5664 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5667 l = aopGet (AOP (left), offset, FALSE, FALSE);
5669 emitcode ("rlc", "a");
5670 if (AOP_SIZE (result) > 1)
5671 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5674 /* now we need to put the carry into the
5675 highest order byte of the result */
5676 if (AOP_SIZE (result) > 1)
5678 l = aopGet (AOP (result), 0, FALSE, FALSE);
5681 emitcode ("mov", "acc.0,c");
5683 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5684 freeAsmop (left, NULL, ic, TRUE);
5685 freeAsmop (result, NULL, ic, TRUE);
5688 /*-----------------------------------------------------------------*/
5689 /* genGetHbit - generates code get highest order bit */
5690 /*-----------------------------------------------------------------*/
5692 genGetHbit (iCode * ic)
5694 operand *left, *result;
5696 D(emitcode ("; genGetHbit",""));
5698 left = IC_LEFT (ic);
5699 result = IC_RESULT (ic);
5700 aopOp (left, ic, FALSE);
5701 aopOp (result, ic, FALSE);
5703 /* get the highest order byte into a */
5704 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5705 if (AOP_TYPE (result) == AOP_CRY)
5707 emitcode ("rlc", "a");
5712 emitcode ("rl", "a");
5713 emitcode ("anl", "a,#0x01");
5718 freeAsmop (left, NULL, ic, TRUE);
5719 freeAsmop (result, NULL, ic, TRUE);
5722 /*-----------------------------------------------------------------*/
5723 /* AccRol - rotate left accumulator by known count */
5724 /*-----------------------------------------------------------------*/
5726 AccRol (int shCount)
5728 shCount &= 0x0007; // shCount : 0..7
5735 emitcode ("rl", "a");
5738 emitcode ("rl", "a");
5739 emitcode ("rl", "a");
5742 emitcode ("swap", "a");
5743 emitcode ("rr", "a");
5746 emitcode ("swap", "a");
5749 emitcode ("swap", "a");
5750 emitcode ("rl", "a");
5753 emitcode ("rr", "a");
5754 emitcode ("rr", "a");
5757 emitcode ("rr", "a");
5762 /*-----------------------------------------------------------------*/
5763 /* AccLsh - left shift accumulator by known count */
5764 /*-----------------------------------------------------------------*/
5766 AccLsh (int shCount)
5771 emitcode ("add", "a,acc");
5772 else if (shCount == 2)
5774 emitcode ("add", "a,acc");
5775 emitcode ("add", "a,acc");
5779 /* rotate left accumulator */
5781 /* and kill the lower order bits */
5782 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5787 /*-----------------------------------------------------------------*/
5788 /* AccRsh - right shift accumulator by known count */
5789 /*-----------------------------------------------------------------*/
5791 AccRsh (int shCount)
5798 emitcode ("rrc", "a");
5802 /* rotate right accumulator */
5803 AccRol (8 - shCount);
5804 /* and kill the higher order bits */
5805 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5810 /*-----------------------------------------------------------------*/
5811 /* AccSRsh - signed right shift accumulator by known count */
5812 /*-----------------------------------------------------------------*/
5814 AccSRsh (int shCount)
5821 emitcode ("mov", "c,acc.7");
5822 emitcode ("rrc", "a");
5824 else if (shCount == 2)
5826 emitcode ("mov", "c,acc.7");
5827 emitcode ("rrc", "a");
5828 emitcode ("mov", "c,acc.7");
5829 emitcode ("rrc", "a");
5833 tlbl = newiTempLabel (NULL);
5834 /* rotate right accumulator */
5835 AccRol (8 - shCount);
5836 /* and kill the higher order bits */
5837 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5838 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5839 emitcode ("orl", "a,#0x%02x",
5840 (unsigned char) ~SRMask[shCount]);
5841 emitcode ("", "%05d$:", tlbl->key + 100);
5846 /*-----------------------------------------------------------------*/
5847 /* shiftR1Left2Result - shift right one byte from left to result */
5848 /*-----------------------------------------------------------------*/
5850 shiftR1Left2Result (operand * left, int offl,
5851 operand * result, int offr,
5852 int shCount, int sign)
5854 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5855 /* shift right accumulator */
5860 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5863 /*-----------------------------------------------------------------*/
5864 /* shiftL1Left2Result - shift left one byte from left to result */
5865 /*-----------------------------------------------------------------*/
5867 shiftL1Left2Result (operand * left, int offl,
5868 operand * result, int offr, int shCount)
5871 l = aopGet (AOP (left), offl, FALSE, FALSE);
5873 /* shift left accumulator */
5875 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5878 /*-----------------------------------------------------------------*/
5879 /* movLeft2Result - move byte from left to result */
5880 /*-----------------------------------------------------------------*/
5882 movLeft2Result (operand * left, int offl,
5883 operand * result, int offr, int sign)
5886 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5888 l = aopGet (AOP (left), offl, FALSE, FALSE);
5890 if (*l == '@' && (IS_AOP_PREG (result)))
5892 emitcode ("mov", "a,%s", l);
5893 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5898 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5901 /* MSB sign in acc.7 ! */
5902 if (getDataSize (left) == offl + 1)
5904 emitcode ("mov", "a,%s", l);
5905 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5912 /*-----------------------------------------------------------------*/
5913 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5914 /*-----------------------------------------------------------------*/
5918 emitcode ("rrc", "a");
5919 emitcode ("xch", "a,%s", x);
5920 emitcode ("rrc", "a");
5921 emitcode ("xch", "a,%s", x);
5924 /*-----------------------------------------------------------------*/
5925 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5926 /*-----------------------------------------------------------------*/
5930 emitcode ("xch", "a,%s", x);
5931 emitcode ("rlc", "a");
5932 emitcode ("xch", "a,%s", x);
5933 emitcode ("rlc", "a");
5936 /*-----------------------------------------------------------------*/
5937 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5938 /*-----------------------------------------------------------------*/
5942 emitcode ("xch", "a,%s", x);
5943 emitcode ("add", "a,acc");
5944 emitcode ("xch", "a,%s", x);
5945 emitcode ("rlc", "a");
5948 /*-----------------------------------------------------------------*/
5949 /* AccAXLsh - left shift a:x by known count (0..7) */
5950 /*-----------------------------------------------------------------*/
5952 AccAXLsh (char *x, int shCount)
5967 case 5: // AAAAABBB:CCCCCDDD
5969 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5971 emitcode ("anl", "a,#0x%02x",
5972 SLMask[shCount]); // BBB00000:CCCCCDDD
5974 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5976 AccRol (shCount); // DDDCCCCC:BBB00000
5978 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5980 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5982 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5984 emitcode ("anl", "a,#0x%02x",
5985 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5987 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5989 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5992 case 6: // AAAAAABB:CCCCCCDD
5993 emitcode ("anl", "a,#0x%02x",
5994 SRMask[shCount]); // 000000BB:CCCCCCDD
5995 emitcode ("mov", "c,acc.0"); // c = B
5996 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5998 AccAXRrl1 (x); // BCCCCCCD:D000000B
5999 AccAXRrl1 (x); // BBCCCCCC:DD000000
6001 emitcode("rrc","a");
6002 emitcode("xch","a,%s", x);
6003 emitcode("rrc","a");
6004 emitcode("mov","c,acc.0"); //<< get correct bit
6005 emitcode("xch","a,%s", x);
6007 emitcode("rrc","a");
6008 emitcode("xch","a,%s", x);
6009 emitcode("rrc","a");
6010 emitcode("xch","a,%s", x);
6013 case 7: // a:x <<= 7
6015 emitcode ("anl", "a,#0x%02x",
6016 SRMask[shCount]); // 0000000B:CCCCCCCD
6018 emitcode ("mov", "c,acc.0"); // c = B
6020 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6022 AccAXRrl1 (x); // BCCCCCCC:D0000000
6030 /*-----------------------------------------------------------------*/
6031 /* AccAXRsh - right shift a:x known count (0..7) */
6032 /*-----------------------------------------------------------------*/
6034 AccAXRsh (char *x, int shCount)
6042 AccAXRrl1 (x); // 0->a:x
6047 AccAXRrl1 (x); // 0->a:x
6050 AccAXRrl1 (x); // 0->a:x
6055 case 5: // AAAAABBB:CCCCCDDD = a:x
6057 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6059 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6061 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6063 emitcode ("anl", "a,#0x%02x",
6064 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6066 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6068 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6070 emitcode ("anl", "a,#0x%02x",
6071 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6073 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6075 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6077 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6080 case 6: // AABBBBBB:CCDDDDDD
6082 emitcode ("mov", "c,acc.7");
6083 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6085 emitcode ("mov", "c,acc.7");
6086 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6088 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6090 emitcode ("anl", "a,#0x%02x",
6091 SRMask[shCount]); // 000000AA:BBBBBBCC
6094 case 7: // ABBBBBBB:CDDDDDDD
6096 emitcode ("mov", "c,acc.7"); // c = A
6098 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6100 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6102 emitcode ("anl", "a,#0x%02x",
6103 SRMask[shCount]); // 0000000A:BBBBBBBC
6111 /*-----------------------------------------------------------------*/
6112 /* AccAXRshS - right shift signed a:x known count (0..7) */
6113 /*-----------------------------------------------------------------*/
6115 AccAXRshS (char *x, int shCount)
6123 emitcode ("mov", "c,acc.7");
6124 AccAXRrl1 (x); // s->a:x
6128 emitcode ("mov", "c,acc.7");
6129 AccAXRrl1 (x); // s->a:x
6131 emitcode ("mov", "c,acc.7");
6132 AccAXRrl1 (x); // s->a:x
6137 case 5: // AAAAABBB:CCCCCDDD = a:x
6139 tlbl = newiTempLabel (NULL);
6140 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6142 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6144 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6146 emitcode ("anl", "a,#0x%02x",
6147 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6149 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6151 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6153 emitcode ("anl", "a,#0x%02x",
6154 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6156 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6158 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6160 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6162 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6163 emitcode ("orl", "a,#0x%02x",
6164 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6166 emitcode ("", "%05d$:", tlbl->key + 100);
6167 break; // SSSSAAAA:BBBCCCCC
6169 case 6: // AABBBBBB:CCDDDDDD
6171 tlbl = newiTempLabel (NULL);
6172 emitcode ("mov", "c,acc.7");
6173 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6175 emitcode ("mov", "c,acc.7");
6176 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6178 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6180 emitcode ("anl", "a,#0x%02x",
6181 SRMask[shCount]); // 000000AA:BBBBBBCC
6183 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6184 emitcode ("orl", "a,#0x%02x",
6185 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6187 emitcode ("", "%05d$:", tlbl->key + 100);
6189 case 7: // ABBBBBBB:CDDDDDDD
6191 tlbl = newiTempLabel (NULL);
6192 emitcode ("mov", "c,acc.7"); // c = A
6194 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6196 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6198 emitcode ("anl", "a,#0x%02x",
6199 SRMask[shCount]); // 0000000A:BBBBBBBC
6201 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6202 emitcode ("orl", "a,#0x%02x",
6203 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6205 emitcode ("", "%05d$:", tlbl->key + 100);
6212 /*-----------------------------------------------------------------*/
6213 /* shiftL2Left2Result - shift left two bytes from left to result */
6214 /*-----------------------------------------------------------------*/
6216 shiftL2Left2Result (operand * left, int offl,
6217 operand * result, int offr, int shCount)
6219 if (sameRegs (AOP (result), AOP (left)) &&
6220 ((offl + MSB16) == offr))
6222 /* don't crash result[offr] */
6223 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6224 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6228 movLeft2Result (left, offl, result, offr, 0);
6229 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6231 /* ax << shCount (x = lsb(result)) */
6232 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6233 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6237 /*-----------------------------------------------------------------*/
6238 /* shiftR2Left2Result - shift right two bytes from left to result */
6239 /*-----------------------------------------------------------------*/
6241 shiftR2Left2Result (operand * left, int offl,
6242 operand * result, int offr,
6243 int shCount, int sign)
6245 if (sameRegs (AOP (result), AOP (left)) &&
6246 ((offl + MSB16) == offr))
6248 /* don't crash result[offr] */
6249 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6250 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6254 movLeft2Result (left, offl, result, offr, 0);
6255 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6257 /* a:x >> shCount (x = lsb(result)) */
6259 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6261 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6262 if (getDataSize (result) > 1)
6263 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6266 /*-----------------------------------------------------------------*/
6267 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6268 /*-----------------------------------------------------------------*/
6270 shiftLLeftOrResult (operand * left, int offl,
6271 operand * result, int offr, int shCount)
6273 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6274 /* shift left accumulator */
6276 /* or with result */
6277 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6278 /* back to result */
6279 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6282 /*-----------------------------------------------------------------*/
6283 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6284 /*-----------------------------------------------------------------*/
6286 shiftRLeftOrResult (operand * left, int offl,
6287 operand * result, int offr, int shCount)
6289 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6290 /* shift right accumulator */
6292 /* or with result */
6293 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6294 /* back to result */
6295 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6298 /*-----------------------------------------------------------------*/
6299 /* genlshOne - left shift a one byte quantity by known count */
6300 /*-----------------------------------------------------------------*/
6302 genlshOne (operand * result, operand * left, int shCount)
6304 D(emitcode ("; genlshOne",""));
6306 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6309 /*-----------------------------------------------------------------*/
6310 /* genlshTwo - left shift two bytes by known amount != 0 */
6311 /*-----------------------------------------------------------------*/
6313 genlshTwo (operand * result, operand * left, int shCount)
6317 D(emitcode ("; genlshTwo",""));
6319 size = getDataSize (result);
6321 /* if shCount >= 8 */
6329 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6331 movLeft2Result (left, LSB, result, MSB16, 0);
6333 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6336 /* 1 <= shCount <= 7 */
6340 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6342 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6346 /*-----------------------------------------------------------------*/
6347 /* shiftLLong - shift left one long from left to result */
6348 /* offl = LSB or MSB16 */
6349 /*-----------------------------------------------------------------*/
6351 shiftLLong (operand * left, operand * result, int offr)
6354 int size = AOP_SIZE (result);
6356 if (size >= LSB + offr)
6358 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6360 emitcode ("add", "a,acc");
6361 if (sameRegs (AOP (left), AOP (result)) &&
6362 size >= MSB16 + offr && offr != LSB)
6363 emitcode ("xch", "a,%s",
6364 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6366 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6369 if (size >= MSB16 + offr)
6371 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6373 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6376 emitcode ("rlc", "a");
6377 if (sameRegs (AOP (left), AOP (result)) &&
6378 size >= MSB24 + offr && offr != LSB)
6379 emitcode ("xch", "a,%s",
6380 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6382 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6385 if (size >= MSB24 + offr)
6387 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6389 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6392 emitcode ("rlc", "a");
6393 if (sameRegs (AOP (left), AOP (result)) &&
6394 size >= MSB32 + offr && offr != LSB)
6395 emitcode ("xch", "a,%s",
6396 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6398 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6401 if (size > MSB32 + offr)
6403 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6405 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6408 emitcode ("rlc", "a");
6409 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6412 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6415 /*-----------------------------------------------------------------*/
6416 /* genlshFour - shift four byte by a known amount != 0 */
6417 /*-----------------------------------------------------------------*/
6419 genlshFour (operand * result, operand * left, int shCount)
6423 D(emitcode ("; genlshFour",""));
6425 size = AOP_SIZE (result);
6427 /* if shifting more that 3 bytes */
6432 /* lowest order of left goes to the highest
6433 order of the destination */
6434 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6436 movLeft2Result (left, LSB, result, MSB32, 0);
6437 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6438 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6439 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6443 /* more than two bytes */
6444 else if (shCount >= 16)
6446 /* lower order two bytes goes to higher order two bytes */
6448 /* if some more remaining */
6450 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6453 movLeft2Result (left, MSB16, result, MSB32, 0);
6454 movLeft2Result (left, LSB, result, MSB24, 0);
6456 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6457 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6461 /* if more than 1 byte */
6462 else if (shCount >= 8)
6464 /* lower order three bytes goes to higher order three bytes */
6469 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6471 movLeft2Result (left, LSB, result, MSB16, 0);
6477 movLeft2Result (left, MSB24, result, MSB32, 0);
6478 movLeft2Result (left, MSB16, result, MSB24, 0);
6479 movLeft2Result (left, LSB, result, MSB16, 0);
6480 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6482 else if (shCount == 1)
6483 shiftLLong (left, result, MSB16);
6486 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6487 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6488 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6489 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6494 /* 1 <= shCount <= 7 */
6495 else if (shCount <= 2)
6497 shiftLLong (left, result, LSB);
6499 shiftLLong (result, result, LSB);
6501 /* 3 <= shCount <= 7, optimize */
6504 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6505 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6506 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6510 /*-----------------------------------------------------------------*/
6511 /* genLeftShiftLiteral - left shifting by known count */
6512 /*-----------------------------------------------------------------*/
6514 genLeftShiftLiteral (operand * left,
6519 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6522 D(emitcode ("; genLeftShiftLiteral",""));
6524 freeAsmop (right, NULL, ic, TRUE);
6526 aopOp (left, ic, FALSE);
6527 aopOp (result, ic, FALSE);
6529 size = getSize (operandType (result));
6532 emitcode ("; shift left ", "result %d, left %d", size,
6536 /* I suppose that the left size >= result size */
6541 movLeft2Result (left, size, result, size, 0);
6545 else if (shCount >= (size * 8))
6547 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6553 genlshOne (result, left, shCount);
6557 genlshTwo (result, left, shCount);
6561 genlshFour (result, left, shCount);
6564 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6565 "*** ack! mystery literal shift!\n");
6569 freeAsmop (left, NULL, ic, TRUE);
6570 freeAsmop (result, NULL, ic, TRUE);
6573 /*-----------------------------------------------------------------*/
6574 /* genLeftShift - generates code for left shifting */
6575 /*-----------------------------------------------------------------*/
6577 genLeftShift (iCode * ic)
6579 operand *left, *right, *result;
6582 symbol *tlbl, *tlbl1;
6584 D(emitcode ("; genLeftShift",""));
6586 right = IC_RIGHT (ic);
6587 left = IC_LEFT (ic);
6588 result = IC_RESULT (ic);
6590 aopOp (right, ic, FALSE);
6592 /* if the shift count is known then do it
6593 as efficiently as possible */
6594 if (AOP_TYPE (right) == AOP_LIT)
6596 genLeftShiftLiteral (left, right, result, ic);
6600 /* shift count is unknown then we have to form
6601 a loop get the loop count in B : Note: we take
6602 only the lower order byte since shifting
6603 more that 32 bits make no sense anyway, ( the
6604 largest size of an object can be only 32 bits ) */
6606 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6607 emitcode ("inc", "b");
6608 freeAsmop (right, NULL, ic, TRUE);
6609 aopOp (left, ic, FALSE);
6610 aopOp (result, ic, FALSE);
6612 /* now move the left to the result if they are not the
6614 if (!sameRegs (AOP (left), AOP (result)) &&
6615 AOP_SIZE (result) > 1)
6618 size = AOP_SIZE (result);
6622 l = aopGet (AOP (left), offset, FALSE, TRUE);
6623 if (*l == '@' && (IS_AOP_PREG (result)))
6626 emitcode ("mov", "a,%s", l);
6627 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6630 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6635 tlbl = newiTempLabel (NULL);
6636 size = AOP_SIZE (result);
6638 tlbl1 = newiTempLabel (NULL);
6640 /* if it is only one byte then */
6643 symbol *tlbl1 = newiTempLabel (NULL);
6645 l = aopGet (AOP (left), 0, FALSE, FALSE);
6647 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6648 emitcode ("", "%05d$:", tlbl->key + 100);
6649 emitcode ("add", "a,acc");
6650 emitcode ("", "%05d$:", tlbl1->key + 100);
6651 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6652 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6656 reAdjustPreg (AOP (result));
6658 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6659 emitcode ("", "%05d$:", tlbl->key + 100);
6660 l = aopGet (AOP (result), offset, FALSE, FALSE);
6662 emitcode ("add", "a,acc");
6663 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6666 l = aopGet (AOP (result), offset, FALSE, FALSE);
6668 emitcode ("rlc", "a");
6669 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6671 reAdjustPreg (AOP (result));
6673 emitcode ("", "%05d$:", tlbl1->key + 100);
6674 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6676 freeAsmop (left, NULL, ic, TRUE);
6677 freeAsmop (result, NULL, ic, TRUE);
6680 /*-----------------------------------------------------------------*/
6681 /* genrshOne - right shift a one byte quantity by known count */
6682 /*-----------------------------------------------------------------*/
6684 genrshOne (operand * result, operand * left,
6685 int shCount, int sign)
6687 D(emitcode ("; genrshOne",""));
6689 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6692 /*-----------------------------------------------------------------*/
6693 /* genrshTwo - right shift two bytes by known amount != 0 */
6694 /*-----------------------------------------------------------------*/
6696 genrshTwo (operand * result, operand * left,
6697 int shCount, int sign)
6699 D(emitcode ("; genrshTwo",""));
6701 /* if shCount >= 8 */
6706 shiftR1Left2Result (left, MSB16, result, LSB,
6709 movLeft2Result (left, MSB16, result, LSB, sign);
6710 addSign (result, MSB16, sign);
6713 /* 1 <= shCount <= 7 */
6715 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6718 /*-----------------------------------------------------------------*/
6719 /* shiftRLong - shift right one long from left to result */
6720 /* offl = LSB or MSB16 */
6721 /*-----------------------------------------------------------------*/
6723 shiftRLong (operand * left, int offl,
6724 operand * result, int sign)
6726 int isSameRegs=sameRegs(AOP(left),AOP(result));
6728 if (isSameRegs && offl>1) {
6729 // we are in big trouble, but this shouldn't happen
6730 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6733 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6738 emitcode ("rlc", "a");
6739 emitcode ("subb", "a,acc");
6741 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6743 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6744 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6747 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6752 emitcode ("clr", "c");
6754 emitcode ("mov", "c,acc.7");
6757 emitcode ("rrc", "a");
6759 if (isSameRegs && offl==MSB16) {
6760 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6762 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6763 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6766 emitcode ("rrc", "a");
6767 if (isSameRegs && offl==1) {
6768 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6770 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6771 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6773 emitcode ("rrc", "a");
6774 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6778 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6779 emitcode ("rrc", "a");
6780 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6784 /*-----------------------------------------------------------------*/
6785 /* genrshFour - shift four byte by a known amount != 0 */
6786 /*-----------------------------------------------------------------*/
6788 genrshFour (operand * result, operand * left,
6789 int shCount, int sign)
6791 D(emitcode ("; genrshFour",""));
6793 /* if shifting more that 3 bytes */
6798 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6800 movLeft2Result (left, MSB32, result, LSB, sign);
6801 addSign (result, MSB16, sign);
6803 else if (shCount >= 16)
6807 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6810 movLeft2Result (left, MSB24, result, LSB, 0);
6811 movLeft2Result (left, MSB32, result, MSB16, sign);
6813 addSign (result, MSB24, sign);
6815 else if (shCount >= 8)
6819 shiftRLong (left, MSB16, result, sign);
6820 else if (shCount == 0)
6822 movLeft2Result (left, MSB16, result, LSB, 0);
6823 movLeft2Result (left, MSB24, result, MSB16, 0);
6824 movLeft2Result (left, MSB32, result, MSB24, sign);
6825 addSign (result, MSB32, sign);
6829 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6830 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6831 /* the last shift is signed */
6832 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6833 addSign (result, MSB32, sign);
6837 { /* 1 <= shCount <= 7 */
6840 shiftRLong (left, LSB, result, sign);
6842 shiftRLong (result, LSB, result, sign);
6846 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6847 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6848 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6853 /*-----------------------------------------------------------------*/
6854 /* genRightShiftLiteral - right shifting by known count */
6855 /*-----------------------------------------------------------------*/
6857 genRightShiftLiteral (operand * left,
6863 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6866 D(emitcode ("; genRightShiftLiteral",""));
6868 freeAsmop (right, NULL, ic, TRUE);
6870 aopOp (left, ic, FALSE);
6871 aopOp (result, ic, FALSE);
6874 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6878 size = getDataSize (left);
6879 /* test the LEFT size !!! */
6881 /* I suppose that the left size >= result size */
6884 size = getDataSize (result);
6886 movLeft2Result (left, size, result, size, 0);
6889 else if (shCount >= (size * 8))
6892 /* get sign in acc.7 */
6893 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6895 addSign (result, LSB, sign);
6902 genrshOne (result, left, shCount, sign);
6906 genrshTwo (result, left, shCount, sign);
6910 genrshFour (result, left, shCount, sign);
6916 freeAsmop (left, NULL, ic, TRUE);
6917 freeAsmop (result, NULL, ic, TRUE);
6920 /*-----------------------------------------------------------------*/
6921 /* genSignedRightShift - right shift of signed number */
6922 /*-----------------------------------------------------------------*/
6924 genSignedRightShift (iCode * ic)
6926 operand *right, *left, *result;
6929 symbol *tlbl, *tlbl1;
6931 D(emitcode ("; genSignedRightShift",""));
6933 /* we do it the hard way put the shift count in b
6934 and loop thru preserving the sign */
6936 right = IC_RIGHT (ic);
6937 left = IC_LEFT (ic);
6938 result = IC_RESULT (ic);
6940 aopOp (right, ic, FALSE);
6943 if (AOP_TYPE (right) == AOP_LIT)
6945 genRightShiftLiteral (left, right, result, ic, 1);
6948 /* shift count is unknown then we have to form
6949 a loop get the loop count in B : Note: we take
6950 only the lower order byte since shifting
6951 more that 32 bits make no sense anyway, ( the
6952 largest size of an object can be only 32 bits ) */
6954 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6955 emitcode ("inc", "b");
6956 freeAsmop (right, NULL, ic, TRUE);
6957 aopOp (left, ic, FALSE);
6958 aopOp (result, ic, FALSE);
6960 /* now move the left to the result if they are not the
6962 if (!sameRegs (AOP (left), AOP (result)) &&
6963 AOP_SIZE (result) > 1)
6966 size = AOP_SIZE (result);
6970 l = aopGet (AOP (left), offset, FALSE, TRUE);
6971 if (*l == '@' && IS_AOP_PREG (result))
6974 emitcode ("mov", "a,%s", l);
6975 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6978 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6983 /* mov the highest order bit to OVR */
6984 tlbl = newiTempLabel (NULL);
6985 tlbl1 = newiTempLabel (NULL);
6987 size = AOP_SIZE (result);
6989 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6990 emitcode ("rlc", "a");
6991 emitcode ("mov", "ov,c");
6992 /* if it is only one byte then */
6995 l = aopGet (AOP (left), 0, FALSE, FALSE);
6997 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6998 emitcode ("", "%05d$:", tlbl->key + 100);
6999 emitcode ("mov", "c,ov");
7000 emitcode ("rrc", "a");
7001 emitcode ("", "%05d$:", tlbl1->key + 100);
7002 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7003 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7007 reAdjustPreg (AOP (result));
7008 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7009 emitcode ("", "%05d$:", tlbl->key + 100);
7010 emitcode ("mov", "c,ov");
7013 l = aopGet (AOP (result), offset, FALSE, FALSE);
7015 emitcode ("rrc", "a");
7016 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7018 reAdjustPreg (AOP (result));
7019 emitcode ("", "%05d$:", tlbl1->key + 100);
7020 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7023 freeAsmop (left, NULL, ic, TRUE);
7024 freeAsmop (result, NULL, ic, TRUE);
7027 /*-----------------------------------------------------------------*/
7028 /* genRightShift - generate code for right shifting */
7029 /*-----------------------------------------------------------------*/
7031 genRightShift (iCode * ic)
7033 operand *right, *left, *result;
7037 symbol *tlbl, *tlbl1;
7039 D(emitcode ("; genRightShift",""));
7041 /* if signed then we do it the hard way preserve the
7042 sign bit moving it inwards */
7043 retype = getSpec (operandType (IC_RESULT (ic)));
7045 if (!SPEC_USIGN (retype))
7047 genSignedRightShift (ic);
7051 /* signed & unsigned types are treated the same : i.e. the
7052 signed is NOT propagated inwards : quoting from the
7053 ANSI - standard : "for E1 >> E2, is equivalent to division
7054 by 2**E2 if unsigned or if it has a non-negative value,
7055 otherwise the result is implementation defined ", MY definition
7056 is that the sign does not get propagated */
7058 right = IC_RIGHT (ic);
7059 left = IC_LEFT (ic);
7060 result = IC_RESULT (ic);
7062 aopOp (right, ic, FALSE);
7064 /* if the shift count is known then do it
7065 as efficiently as possible */
7066 if (AOP_TYPE (right) == AOP_LIT)
7068 genRightShiftLiteral (left, right, result, ic, 0);
7072 /* shift count is unknown then we have to form
7073 a loop get the loop count in B : Note: we take
7074 only the lower order byte since shifting
7075 more that 32 bits make no sense anyway, ( the
7076 largest size of an object can be only 32 bits ) */
7078 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7079 emitcode ("inc", "b");
7080 freeAsmop (right, NULL, ic, TRUE);
7081 aopOp (left, ic, FALSE);
7082 aopOp (result, ic, FALSE);
7084 /* now move the left to the result if they are not the
7086 if (!sameRegs (AOP (left), AOP (result)) &&
7087 AOP_SIZE (result) > 1)
7090 size = AOP_SIZE (result);
7094 l = aopGet (AOP (left), offset, FALSE, TRUE);
7095 if (*l == '@' && IS_AOP_PREG (result))
7098 emitcode ("mov", "a,%s", l);
7099 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7102 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7107 tlbl = newiTempLabel (NULL);
7108 tlbl1 = newiTempLabel (NULL);
7109 size = AOP_SIZE (result);
7112 /* if it is only one byte then */
7115 l = aopGet (AOP (left), 0, FALSE, FALSE);
7117 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7118 emitcode ("", "%05d$:", tlbl->key + 100);
7120 emitcode ("rrc", "a");
7121 emitcode ("", "%05d$:", tlbl1->key + 100);
7122 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7123 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7127 reAdjustPreg (AOP (result));
7128 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7129 emitcode ("", "%05d$:", tlbl->key + 100);
7133 l = aopGet (AOP (result), offset, FALSE, FALSE);
7135 emitcode ("rrc", "a");
7136 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7138 reAdjustPreg (AOP (result));
7140 emitcode ("", "%05d$:", tlbl1->key + 100);
7141 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7144 freeAsmop (left, NULL, ic, TRUE);
7145 freeAsmop (result, NULL, ic, TRUE);
7148 /*-----------------------------------------------------------------*/
7149 /* emitPtrByteGet - emits code to get a byte into A through a */
7150 /* pointer register (R0, R1, or DPTR). The */
7151 /* original value of A can be preserved in B. */
7152 /*-----------------------------------------------------------------*/
7154 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7161 emitcode ("mov", "b,a");
7162 emitcode ("mov", "a,@%s", rname);
7167 emitcode ("mov", "b,a");
7168 emitcode ("movx", "a,@%s", rname);
7173 emitcode ("mov", "b,a");
7174 emitcode ("movx", "a,@dptr");
7179 emitcode ("mov", "b,a");
7180 emitcode ("clr", "a");
7181 emitcode ("movc", "a,@a+dptr");
7187 emitcode ("push", "b");
7188 emitcode ("push", "acc");
7190 emitcode ("lcall", "__gptrget");
7192 emitcode ("pop", "b");
7197 /*-----------------------------------------------------------------*/
7198 /* emitPtrByteSet - emits code to set a byte from src through a */
7199 /* pointer register (R0, R1, or DPTR). */
7200 /*-----------------------------------------------------------------*/
7202 emitPtrByteSet (char *rname, int p_type, char *src)
7211 emitcode ("mov", "@%s,a", rname);
7214 emitcode ("mov", "@%s,%s", rname, src);
7219 emitcode ("movx", "@%s,a", rname);
7224 emitcode ("movx", "@dptr,a");
7229 emitcode ("lcall", "__gptrput");
7234 /*-----------------------------------------------------------------*/
7235 /* genUnpackBits - generates code for unpacking bits */
7236 /*-----------------------------------------------------------------*/
7238 genUnpackBits (operand * result, char *rname, int ptype)
7240 int offset = 0; /* result byte offset */
7241 int rsize; /* result size */
7242 int rlen = 0; /* remaining bitfield length */
7243 sym_link *etype; /* bitfield type information */
7244 int blen; /* bitfield length */
7245 int bstr; /* bitfield starting bit within byte */
7247 D(emitcode ("; genUnpackBits",""));
7249 etype = getSpec (operandType (result));
7250 rsize = getSize (operandType (result));
7251 blen = SPEC_BLEN (etype);
7252 bstr = SPEC_BSTR (etype);
7254 /* If the bitfield length is less than a byte */
7257 emitPtrByteGet (rname, ptype, FALSE);
7259 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7260 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7264 /* Bit field did not fit in a byte. Copy all
7265 but the partial byte at the end. */
7266 for (rlen=blen;rlen>=8;rlen-=8)
7268 emitPtrByteGet (rname, ptype, FALSE);
7269 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7271 emitcode ("inc", "%s", rname);
7274 /* Handle the partial byte at the end */
7277 emitPtrByteGet (rname, ptype, FALSE);
7278 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7279 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7287 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7292 /*-----------------------------------------------------------------*/
7293 /* genDataPointerGet - generates code when ptr offset is known */
7294 /*-----------------------------------------------------------------*/
7296 genDataPointerGet (operand * left,
7302 int size, offset = 0;
7304 D(emitcode ("; genDataPointerGet",""));
7306 aopOp (result, ic, TRUE);
7308 /* get the string representation of the name */
7309 l = aopGet (AOP (left), 0, FALSE, TRUE);
7310 size = AOP_SIZE (result);
7314 sprintf (buffer, "(%s + %d)", l + 1, offset);
7316 sprintf (buffer, "%s", l + 1);
7317 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7320 freeAsmop (left, NULL, ic, TRUE);
7321 freeAsmop (result, NULL, ic, TRUE);
7324 /*-----------------------------------------------------------------*/
7325 /* genNearPointerGet - emitcode for near pointer fetch */
7326 /*-----------------------------------------------------------------*/
7328 genNearPointerGet (operand * left,
7336 sym_link *rtype, *retype;
7337 sym_link *ltype = operandType (left);
7340 D(emitcode ("; genNearPointerGet",""));
7342 rtype = operandType (result);
7343 retype = getSpec (rtype);
7345 aopOp (left, ic, FALSE);
7347 /* if left is rematerialisable and
7348 result is not bit variable type and
7349 the left is pointer to data space i.e
7350 lower 128 bytes of space */
7351 if (AOP_TYPE (left) == AOP_IMMD &&
7352 !IS_BITVAR (retype) &&
7353 DCL_TYPE (ltype) == POINTER)
7355 genDataPointerGet (left, result, ic);
7359 /* if the value is already in a pointer register
7360 then don't need anything more */
7361 if (!AOP_INPREG (AOP (left)))
7363 if (IS_AOP_PREG (left))
7365 // Aha, it is a pointer, just in disguise.
7366 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7369 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7370 __FILE__, __LINE__);
7375 emitcode ("mov", "a%s,%s", rname + 1, rname);
7376 rname++; // skip the '@'.
7381 /* otherwise get a free pointer register */
7383 preg = getFreePtr (ic, &aop, FALSE);
7384 emitcode ("mov", "%s,%s",
7386 aopGet (AOP (left), 0, FALSE, TRUE));
7391 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7393 //aopOp (result, ic, FALSE);
7394 aopOp (result, ic, result?TRUE:FALSE);
7396 /* if bitfield then unpack the bits */
7397 if (IS_BITVAR (retype))
7398 genUnpackBits (result, rname, POINTER);
7401 /* we have can just get the values */
7402 int size = AOP_SIZE (result);
7407 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7410 emitcode ("mov", "a,@%s", rname);
7411 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7415 sprintf (buffer, "@%s", rname);
7416 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7420 emitcode ("inc", "%s", rname);
7424 /* now some housekeeping stuff */
7425 if (aop) /* we had to allocate for this iCode */
7427 if (pi) { /* post increment present */
7428 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7430 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7434 /* we did not allocate which means left
7435 already in a pointer register, then
7436 if size > 0 && this could be used again
7437 we have to point it back to where it
7439 if ((AOP_SIZE (result) > 1 &&
7440 !OP_SYMBOL (left)->remat &&
7441 (OP_SYMBOL (left)->liveTo > ic->seq ||
7445 int size = AOP_SIZE (result) - 1;
7447 emitcode ("dec", "%s", rname);
7452 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7453 freeAsmop (left, NULL, ic, TRUE);
7454 if (pi) pi->generated = 1;
7457 /*-----------------------------------------------------------------*/
7458 /* genPagedPointerGet - emitcode for paged pointer fetch */
7459 /*-----------------------------------------------------------------*/
7461 genPagedPointerGet (operand * left,
7469 sym_link *rtype, *retype;
7471 D(emitcode ("; genPagedPointerGet",""));
7473 rtype = operandType (result);
7474 retype = getSpec (rtype);
7476 aopOp (left, ic, FALSE);
7478 /* if the value is already in a pointer register
7479 then don't need anything more */
7480 if (!AOP_INPREG (AOP (left)))
7482 /* otherwise get a free pointer register */
7484 preg = getFreePtr (ic, &aop, FALSE);
7485 emitcode ("mov", "%s,%s",
7487 aopGet (AOP (left), 0, FALSE, TRUE));
7491 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7493 aopOp (result, ic, FALSE);
7495 /* if bitfield then unpack the bits */
7496 if (IS_BITVAR (retype))
7497 genUnpackBits (result, rname, PPOINTER);
7500 /* we have can just get the values */
7501 int size = AOP_SIZE (result);
7507 emitcode ("movx", "a,@%s", rname);
7508 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7513 emitcode ("inc", "%s", rname);
7517 /* now some housekeeping stuff */
7518 if (aop) /* we had to allocate for this iCode */
7520 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7521 freeAsmop (NULL, aop, ic, TRUE);
7525 /* we did not allocate which means left
7526 already in a pointer register, then
7527 if size > 0 && this could be used again
7528 we have to point it back to where it
7530 if ((AOP_SIZE (result) > 1 &&
7531 !OP_SYMBOL (left)->remat &&
7532 (OP_SYMBOL (left)->liveTo > ic->seq ||
7536 int size = AOP_SIZE (result) - 1;
7538 emitcode ("dec", "%s", rname);
7543 freeAsmop (left, NULL, ic, TRUE);
7544 freeAsmop (result, NULL, ic, TRUE);
7545 if (pi) pi->generated = 1;
7549 /*-----------------------------------------------------------------*/
7550 /* genFarPointerGet - gget value from far space */
7551 /*-----------------------------------------------------------------*/
7553 genFarPointerGet (operand * left,
7554 operand * result, iCode * ic, iCode * pi)
7557 sym_link *retype = getSpec (operandType (result));
7559 D(emitcode ("; genFarPointerGet",""));
7561 aopOp (left, ic, FALSE);
7563 /* if the operand is already in dptr
7564 then we do nothing else we move the value to dptr */
7565 if (AOP_TYPE (left) != AOP_STR)
7567 /* if this is remateriazable */
7568 if (AOP_TYPE (left) == AOP_IMMD)
7569 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7571 { /* we need to get it byte by byte */
7572 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7573 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7576 /* so dptr know contains the address */
7577 aopOp (result, ic, FALSE);
7579 /* if bit then unpack */
7580 if (IS_BITVAR (retype))
7581 genUnpackBits (result, "dptr", FPOINTER);
7584 size = AOP_SIZE (result);
7589 emitcode ("movx", "a,@dptr");
7590 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7592 emitcode ("inc", "dptr");
7596 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7597 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7598 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7601 freeAsmop (left, NULL, ic, TRUE);
7602 freeAsmop (result, NULL, ic, TRUE);
7605 /*-----------------------------------------------------------------*/
7606 /* genCodePointerGet - gget value from code space */
7607 /*-----------------------------------------------------------------*/
7609 genCodePointerGet (operand * left,
7610 operand * result, iCode * ic, iCode *pi)
7613 sym_link *retype = getSpec (operandType (result));
7615 D(emitcode ("; genCodePointerGet",""));
7617 aopOp (left, ic, FALSE);
7619 /* if the operand is already in dptr
7620 then we do nothing else we move the value to dptr */
7621 if (AOP_TYPE (left) != AOP_STR)
7623 /* if this is remateriazable */
7624 if (AOP_TYPE (left) == AOP_IMMD)
7625 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7627 { /* we need to get it byte by byte */
7628 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7629 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7632 /* so dptr know contains the address */
7633 aopOp (result, ic, FALSE);
7635 /* if bit then unpack */
7636 if (IS_BITVAR (retype))
7637 genUnpackBits (result, "dptr", CPOINTER);
7640 size = AOP_SIZE (result);
7647 emitcode ("clr", "a");
7648 emitcode ("movc", "a,@a+dptr");
7649 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7650 emitcode ("inc", "dptr");
7654 emitcode ("mov", "a,#0x%02x", offset);
7655 emitcode ("movc", "a,@a+dptr");
7656 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7661 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7662 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7663 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7666 freeAsmop (left, NULL, ic, TRUE);
7667 freeAsmop (result, NULL, ic, TRUE);
7670 /*-----------------------------------------------------------------*/
7671 /* genGenPointerGet - gget value from generic pointer space */
7672 /*-----------------------------------------------------------------*/
7674 genGenPointerGet (operand * left,
7675 operand * result, iCode * ic, iCode *pi)
7678 sym_link *retype = getSpec (operandType (result));
7680 D(emitcode ("; genGenPointerGet",""));
7682 aopOp (left, ic, FALSE);
7684 /* if the operand is already in dptr
7685 then we do nothing else we move the value to dptr */
7686 if (AOP_TYPE (left) != AOP_STR)
7688 /* if this is remateriazable */
7689 if (AOP_TYPE (left) == AOP_IMMD)
7691 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7692 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7693 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7695 emitcode ("mov", "b,#%d", pointerCode (retype));
7698 { /* we need to get it byte by byte */
7699 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7700 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7701 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7704 /* so dptr know contains the address */
7705 aopOp (result, ic, FALSE);
7707 /* if bit then unpack */
7708 if (IS_BITVAR (retype))
7709 genUnpackBits (result, "dptr", GPOINTER);
7712 size = AOP_SIZE (result);
7717 emitcode ("lcall", "__gptrget");
7718 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7720 emitcode ("inc", "dptr");
7724 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7725 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7726 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7729 freeAsmop (left, NULL, ic, TRUE);
7730 freeAsmop (result, NULL, ic, TRUE);
7733 /*-----------------------------------------------------------------*/
7734 /* genPointerGet - generate code for pointer get */
7735 /*-----------------------------------------------------------------*/
7737 genPointerGet (iCode * ic, iCode *pi)
7739 operand *left, *result;
7740 sym_link *type, *etype;
7743 D(emitcode ("; genPointerGet",""));
7745 left = IC_LEFT (ic);
7746 result = IC_RESULT (ic);
7748 /* depending on the type of pointer we need to
7749 move it to the correct pointer register */
7750 type = operandType (left);
7751 etype = getSpec (type);
7752 /* if left is of type of pointer then it is simple */
7753 if (IS_PTR (type) && !IS_FUNC (type->next))
7754 p_type = DCL_TYPE (type);
7757 /* we have to go by the storage class */
7758 p_type = PTR_TYPE (SPEC_OCLS (etype));
7761 /* special case when cast remat */
7762 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7763 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7764 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7765 type = operandType (left);
7766 p_type = DCL_TYPE (type);
7768 /* now that we have the pointer type we assign
7769 the pointer values */
7775 genNearPointerGet (left, result, ic, pi);
7779 genPagedPointerGet (left, result, ic, pi);
7783 genFarPointerGet (left, result, ic, pi);
7787 genCodePointerGet (left, result, ic, pi);
7791 genGenPointerGet (left, result, ic, pi);
7799 /*-----------------------------------------------------------------*/
7800 /* genPackBits - generates code for packed bit storage */
7801 /*-----------------------------------------------------------------*/
7803 genPackBits (sym_link * etype,
7805 char *rname, int p_type)
7807 int offset = 0; /* source byte offset */
7808 int rlen = 0; /* remaining bitfield length */
7809 int blen; /* bitfield length */
7810 int bstr; /* bitfield starting bit within byte */
7811 int litval; /* source literal value (if AOP_LIT) */
7812 unsigned char mask; /* bitmask within current byte */
7814 D(emitcode ("; genPackBits",""));
7816 blen = SPEC_BLEN (etype);
7817 bstr = SPEC_BSTR (etype);
7819 /* If the bitfield length is less than a byte */
7822 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7823 (unsigned char) (0xFF >> (8 - bstr)));
7825 if (AOP_TYPE (right) == AOP_LIT)
7827 /* Case with a bitfield length <8 and literal source
7829 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7831 litval &= (~mask) & 0xff;
7832 emitPtrByteGet (rname, p_type, FALSE);
7833 if ((mask|litval)!=0xff)
7834 emitcode ("anl","a,#0x%02x", mask);
7836 emitcode ("orl","a,#0x%02x", litval);
7840 if ((blen==1) && (p_type!=GPOINTER))
7842 /* Case with a bitfield length == 1 and no generic pointer
7844 if (AOP_TYPE (right) == AOP_CRY)
7845 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7848 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7849 emitcode ("rrc","a");
7851 emitPtrByteGet (rname, p_type, FALSE);
7852 emitcode ("mov","acc.%d,c",bstr);
7856 /* Case with a bitfield length < 8 and arbitrary source
7858 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7859 /* shift and mask source value */
7861 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7863 /* transfer A to B and get next byte */
7864 emitPtrByteGet (rname, p_type, TRUE);
7866 emitcode ("anl", "a,#0x%02x", mask);
7867 emitcode ("orl", "a,b");
7868 if (p_type == GPOINTER)
7869 emitcode ("pop", "b");
7873 emitPtrByteSet (rname, p_type, "a");
7877 /* Bit length is greater than 7 bits. In this case, copy */
7878 /* all except the partial byte at the end */
7879 for (rlen=blen;rlen>=8;rlen-=8)
7881 emitPtrByteSet (rname, p_type,
7882 aopGet (AOP (right), offset++, FALSE, TRUE) );
7884 emitcode ("inc", "%s", rname);
7887 /* If there was a partial byte at the end */
7890 mask = (((unsigned char) -1 << rlen) & 0xff);
7892 if (AOP_TYPE (right) == AOP_LIT)
7894 /* Case with partial byte and literal source
7896 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7897 litval >>= (blen-rlen);
7898 litval &= (~mask) & 0xff;
7899 emitPtrByteGet (rname, p_type, FALSE);
7900 if ((mask|litval)!=0xff)
7901 emitcode ("anl","a,#0x%02x", mask);
7903 emitcode ("orl","a,#0x%02x", litval);
7907 /* Case with partial byte and arbitrary source
7909 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7910 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7912 /* transfer A to B and get next byte */
7913 emitPtrByteGet (rname, p_type, TRUE);
7915 emitcode ("anl", "a,#0x%02x", mask);
7916 emitcode ("orl", "a,b");
7917 if (p_type == GPOINTER)
7918 emitcode ("pop", "b");
7920 emitPtrByteSet (rname, p_type, "a");
7926 /*-----------------------------------------------------------------*/
7927 /* genDataPointerSet - remat pointer to data space */
7928 /*-----------------------------------------------------------------*/
7930 genDataPointerSet (operand * right,
7934 int size, offset = 0;
7935 char *l, buffer[256];
7937 D(emitcode ("; genDataPointerSet",""));
7939 aopOp (right, ic, FALSE);
7941 l = aopGet (AOP (result), 0, FALSE, TRUE);
7942 size = AOP_SIZE (right);
7946 sprintf (buffer, "(%s + %d)", l + 1, offset);
7948 sprintf (buffer, "%s", l + 1);
7949 emitcode ("mov", "%s,%s", buffer,
7950 aopGet (AOP (right), offset++, FALSE, FALSE));
7953 freeAsmop (right, NULL, ic, TRUE);
7954 freeAsmop (result, NULL, ic, TRUE);
7957 /*-----------------------------------------------------------------*/
7958 /* genNearPointerSet - emitcode for near pointer put */
7959 /*-----------------------------------------------------------------*/
7961 genNearPointerSet (operand * right,
7969 sym_link *retype, *letype;
7970 sym_link *ptype = operandType (result);
7972 D(emitcode ("; genNearPointerSet",""));
7974 retype = getSpec (operandType (right));
7975 letype = getSpec (ptype);
7976 aopOp (result, ic, FALSE);
7978 /* if the result is rematerializable &
7979 in data space & not a bit variable */
7980 if (AOP_TYPE (result) == AOP_IMMD &&
7981 DCL_TYPE (ptype) == POINTER &&
7982 !IS_BITVAR (retype) &&
7983 !IS_BITVAR (letype))
7985 genDataPointerSet (right, result, ic);
7989 /* if the value is already in a pointer register
7990 then don't need anything more */
7991 if (!AOP_INPREG (AOP (result)))
7994 //AOP_TYPE (result) == AOP_STK
7998 // Aha, it is a pointer, just in disguise.
7999 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8002 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8003 __FILE__, __LINE__);
8008 emitcode ("mov", "a%s,%s", rname + 1, rname);
8009 rname++; // skip the '@'.
8014 /* otherwise get a free pointer register */
8016 preg = getFreePtr (ic, &aop, FALSE);
8017 emitcode ("mov", "%s,%s",
8019 aopGet (AOP (result), 0, FALSE, TRUE));
8025 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8028 aopOp (right, ic, FALSE);
8030 /* if bitfield then unpack the bits */
8031 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8032 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8035 /* we have can just get the values */
8036 int size = AOP_SIZE (right);
8041 l = aopGet (AOP (right), offset, FALSE, TRUE);
8045 emitcode ("mov", "@%s,a", rname);
8048 emitcode ("mov", "@%s,%s", rname, l);
8050 emitcode ("inc", "%s", rname);
8055 /* now some housekeeping stuff */
8056 if (aop) /* we had to allocate for this iCode */
8059 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8060 freeAsmop (NULL, aop, ic, TRUE);
8064 /* we did not allocate which means left
8065 already in a pointer register, then
8066 if size > 0 && this could be used again
8067 we have to point it back to where it
8069 if ((AOP_SIZE (right) > 1 &&
8070 !OP_SYMBOL (result)->remat &&
8071 (OP_SYMBOL (result)->liveTo > ic->seq ||
8075 int size = AOP_SIZE (right) - 1;
8077 emitcode ("dec", "%s", rname);
8082 if (pi) pi->generated = 1;
8083 freeAsmop (result, NULL, ic, TRUE);
8084 freeAsmop (right, NULL, ic, TRUE);
8087 /*-----------------------------------------------------------------*/
8088 /* genPagedPointerSet - emitcode for Paged pointer put */
8089 /*-----------------------------------------------------------------*/
8091 genPagedPointerSet (operand * right,
8099 sym_link *retype, *letype;
8101 D(emitcode ("; genPagedPointerSet",""));
8103 retype = getSpec (operandType (right));
8104 letype = getSpec (operandType (result));
8106 aopOp (result, ic, FALSE);
8108 /* if the value is already in a pointer register
8109 then don't need anything more */
8110 if (!AOP_INPREG (AOP (result)))
8112 /* otherwise get a free pointer register */
8114 preg = getFreePtr (ic, &aop, FALSE);
8115 emitcode ("mov", "%s,%s",
8117 aopGet (AOP (result), 0, FALSE, TRUE));
8121 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8123 aopOp (right, ic, FALSE);
8125 /* if bitfield then unpack the bits */
8126 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8127 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8130 /* we have can just get the values */
8131 int size = AOP_SIZE (right);
8136 l = aopGet (AOP (right), offset, FALSE, TRUE);
8139 emitcode ("movx", "@%s,a", rname);
8142 emitcode ("inc", "%s", rname);
8148 /* now some housekeeping stuff */
8149 if (aop) /* we had to allocate for this iCode */
8152 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8153 freeAsmop (NULL, aop, ic, TRUE);
8157 /* we did not allocate which means left
8158 already in a pointer register, then
8159 if size > 0 && this could be used again
8160 we have to point it back to where it
8162 if (AOP_SIZE (right) > 1 &&
8163 !OP_SYMBOL (result)->remat &&
8164 (OP_SYMBOL (result)->liveTo > ic->seq ||
8167 int size = AOP_SIZE (right) - 1;
8169 emitcode ("dec", "%s", rname);
8174 if (pi) pi->generated = 1;
8175 freeAsmop (result, NULL, ic, TRUE);
8176 freeAsmop (right, NULL, ic, TRUE);
8181 /*-----------------------------------------------------------------*/
8182 /* genFarPointerSet - set value from far space */
8183 /*-----------------------------------------------------------------*/
8185 genFarPointerSet (operand * right,
8186 operand * result, iCode * ic, iCode * pi)
8189 sym_link *retype = getSpec (operandType (right));
8190 sym_link *letype = getSpec (operandType (result));
8192 D(emitcode ("; genFarPointerSet",""));
8194 aopOp (result, ic, FALSE);
8196 /* if the operand is already in dptr
8197 then we do nothing else we move the value to dptr */
8198 if (AOP_TYPE (result) != AOP_STR)
8200 /* if this is remateriazable */
8201 if (AOP_TYPE (result) == AOP_IMMD)
8202 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8204 { /* we need to get it byte by byte */
8205 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8206 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8209 /* so dptr know contains the address */
8210 aopOp (right, ic, FALSE);
8212 /* if bit then unpack */
8213 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8214 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8217 size = AOP_SIZE (right);
8222 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8224 emitcode ("movx", "@dptr,a");
8226 emitcode ("inc", "dptr");
8229 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8230 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8231 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8234 freeAsmop (result, NULL, ic, TRUE);
8235 freeAsmop (right, NULL, ic, TRUE);
8238 /*-----------------------------------------------------------------*/
8239 /* genGenPointerSet - set value from generic pointer space */
8240 /*-----------------------------------------------------------------*/
8242 genGenPointerSet (operand * right,
8243 operand * result, iCode * ic, iCode * pi)
8246 sym_link *retype = getSpec (operandType (right));
8247 sym_link *letype = getSpec (operandType (result));
8249 D(emitcode ("; genGenPointerSet",""));
8251 aopOp (result, ic, FALSE);
8253 /* if the operand is already in dptr
8254 then we do nothing else we move the value to dptr */
8255 if (AOP_TYPE (result) != AOP_STR)
8257 /* if this is remateriazable */
8258 if (AOP_TYPE (result) == AOP_IMMD)
8260 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8261 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8262 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8264 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8267 { /* we need to get it byte by byte */
8268 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8269 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8270 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8273 /* so dptr know contains the address */
8274 aopOp (right, ic, FALSE);
8276 /* if bit then unpack */
8277 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8278 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8281 size = AOP_SIZE (right);
8286 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8288 emitcode ("lcall", "__gptrput");
8290 emitcode ("inc", "dptr");
8294 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8295 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8296 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8299 freeAsmop (result, NULL, ic, TRUE);
8300 freeAsmop (right, NULL, ic, TRUE);
8303 /*-----------------------------------------------------------------*/
8304 /* genPointerSet - stores the value into a pointer location */
8305 /*-----------------------------------------------------------------*/
8307 genPointerSet (iCode * ic, iCode *pi)
8309 operand *right, *result;
8310 sym_link *type, *etype;
8313 D(emitcode ("; genPointerSet",""));
8315 right = IC_RIGHT (ic);
8316 result = IC_RESULT (ic);
8318 /* depending on the type of pointer we need to
8319 move it to the correct pointer register */
8320 type = operandType (result);
8321 etype = getSpec (type);
8322 /* if left is of type of pointer then it is simple */
8323 if (IS_PTR (type) && !IS_FUNC (type->next))
8325 p_type = DCL_TYPE (type);
8329 /* we have to go by the storage class */
8330 p_type = PTR_TYPE (SPEC_OCLS (etype));
8333 /* special case when cast remat */
8334 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8335 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8336 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8337 type = operandType (result);
8338 p_type = DCL_TYPE (type);
8340 /* now that we have the pointer type we assign
8341 the pointer values */
8347 genNearPointerSet (right, result, ic, pi);
8351 genPagedPointerSet (right, result, ic, pi);
8355 genFarPointerSet (right, result, ic, pi);
8359 genGenPointerSet (right, result, ic, pi);
8363 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8364 "genPointerSet: illegal pointer type");
8369 /*-----------------------------------------------------------------*/
8370 /* genIfx - generate code for Ifx statement */
8371 /*-----------------------------------------------------------------*/
8373 genIfx (iCode * ic, iCode * popIc)
8375 operand *cond = IC_COND (ic);
8378 D(emitcode ("; genIfx",""));
8380 aopOp (cond, ic, FALSE);
8382 /* get the value into acc */
8383 if (AOP_TYPE (cond) != AOP_CRY)
8387 /* the result is now in the accumulator */
8388 freeAsmop (cond, NULL, ic, TRUE);
8390 /* if there was something to be popped then do it */
8394 /* if the condition is a bit variable */
8395 if (isbit && IS_ITEMP (cond) &&
8397 genIfxJump (ic, SPIL_LOC (cond)->rname);
8398 else if (isbit && !IS_ITEMP (cond))
8399 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8401 genIfxJump (ic, "a");
8406 /*-----------------------------------------------------------------*/
8407 /* genAddrOf - generates code for address of */
8408 /*-----------------------------------------------------------------*/
8410 genAddrOf (iCode * ic)
8412 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8415 D(emitcode ("; genAddrOf",""));
8417 aopOp (IC_RESULT (ic), ic, FALSE);
8419 /* if the operand is on the stack then we
8420 need to get the stack offset of this
8424 /* if it has an offset then we need to compute
8428 emitcode ("mov", "a,_bp");
8429 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8430 ((char) (sym->stack - _G.nRegsSaved)) :
8431 ((char) sym->stack)) & 0xff);
8432 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8436 /* we can just move _bp */
8437 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8439 /* fill the result with zero */
8440 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8445 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8451 /* object not on stack then we need the name */
8452 size = AOP_SIZE (IC_RESULT (ic));
8457 char s[SDCC_NAME_MAX];
8459 sprintf (s, "#(%s >> %d)",
8463 sprintf (s, "#%s", sym->rname);
8464 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8468 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8472 /*-----------------------------------------------------------------*/
8473 /* genFarFarAssign - assignment when both are in far space */
8474 /*-----------------------------------------------------------------*/
8476 genFarFarAssign (operand * result, operand * right, iCode * ic)
8478 int size = AOP_SIZE (right);
8482 D(emitcode ("; genFarFarAssign",""));
8484 /* first push the right side on to the stack */
8487 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8489 emitcode ("push", "acc");
8492 freeAsmop (right, NULL, ic, FALSE);
8493 /* now assign DPTR to result */
8494 aopOp (result, ic, FALSE);
8495 size = AOP_SIZE (result);
8498 emitcode ("pop", "acc");
8499 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8501 freeAsmop (result, NULL, ic, FALSE);
8505 /*-----------------------------------------------------------------*/
8506 /* genAssign - generate code for assignment */
8507 /*-----------------------------------------------------------------*/
8509 genAssign (iCode * ic)
8511 operand *result, *right;
8513 unsigned long lit = 0L;
8515 D(emitcode("; genAssign",""));
8517 result = IC_RESULT (ic);
8518 right = IC_RIGHT (ic);
8520 /* if they are the same */
8521 if (operandsEqu (result, right) &&
8522 !isOperandVolatile (result, FALSE) &&
8523 !isOperandVolatile (right, FALSE))
8526 aopOp (right, ic, FALSE);
8528 /* special case both in far space */
8529 if (AOP_TYPE (right) == AOP_DPTR &&
8530 IS_TRUE_SYMOP (result) &&
8531 isOperandInFarSpace (result))
8534 genFarFarAssign (result, right, ic);
8538 aopOp (result, ic, TRUE);
8540 /* if they are the same registers */
8541 if (sameRegs (AOP (right), AOP (result)) &&
8542 !isOperandVolatile (result, FALSE) &&
8543 !isOperandVolatile (right, FALSE))
8546 /* if the result is a bit */
8547 if (AOP_TYPE (result) == AOP_CRY)
8550 /* if the right size is a literal then
8551 we know what the value is */
8552 if (AOP_TYPE (right) == AOP_LIT)
8554 if (((int) operandLitValue (right)))
8555 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8557 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8561 /* the right is also a bit variable */
8562 if (AOP_TYPE (right) == AOP_CRY)
8564 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8565 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8571 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8575 /* bit variables done */
8577 size = AOP_SIZE (result);
8579 if (AOP_TYPE (right) == AOP_LIT)
8580 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8582 (AOP_TYPE (result) != AOP_REG) &&
8583 (AOP_TYPE (right) == AOP_LIT) &&
8584 !IS_FLOAT (operandType (right)) &&
8587 emitcode ("clr", "a");
8590 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8591 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8593 aopPut (AOP (result),
8594 aopGet (AOP (right), size, FALSE, FALSE),
8596 isOperandVolatile (result, FALSE));
8603 aopPut (AOP (result),
8604 aopGet (AOP (right), offset, FALSE, FALSE),
8606 isOperandVolatile (result, FALSE));
8612 freeAsmop (right, NULL, ic, TRUE);
8613 freeAsmop (result, NULL, ic, TRUE);
8616 /*-----------------------------------------------------------------*/
8617 /* genJumpTab - genrates code for jump table */
8618 /*-----------------------------------------------------------------*/
8620 genJumpTab (iCode * ic)
8625 D(emitcode ("; genJumpTab",""));
8627 aopOp (IC_JTCOND (ic), ic, FALSE);
8628 /* get the condition into accumulator */
8629 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8631 /* multiply by three */
8632 emitcode ("add", "a,acc");
8633 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8634 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8636 jtab = newiTempLabel (NULL);
8637 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8638 emitcode ("jmp", "@a+dptr");
8639 emitcode ("", "%05d$:", jtab->key + 100);
8640 /* now generate the jump labels */
8641 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8642 jtab = setNextItem (IC_JTLABELS (ic)))
8643 emitcode ("ljmp", "%05d$", jtab->key + 100);
8647 /*-----------------------------------------------------------------*/
8648 /* genCast - gen code for casting */
8649 /*-----------------------------------------------------------------*/
8651 genCast (iCode * ic)
8653 operand *result = IC_RESULT (ic);
8654 sym_link *ctype = operandType (IC_LEFT (ic));
8655 sym_link *rtype = operandType (IC_RIGHT (ic));
8656 operand *right = IC_RIGHT (ic);
8659 D(emitcode("; genCast",""));
8661 /* if they are equivalent then do nothing */
8662 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8665 aopOp (right, ic, FALSE);
8666 aopOp (result, ic, FALSE);
8668 /* if the result is a bit (and not a bitfield) */
8669 // if (AOP_TYPE (result) == AOP_CRY)
8670 if (IS_BITVAR (OP_SYMBOL (result)->type)
8671 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8673 /* if the right size is a literal then
8674 we know what the value is */
8675 if (AOP_TYPE (right) == AOP_LIT)
8677 if (((int) operandLitValue (right)))
8678 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8680 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8685 /* the right is also a bit variable */
8686 if (AOP_TYPE (right) == AOP_CRY)
8688 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8689 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8695 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8700 /* if they are the same size : or less */
8701 if (AOP_SIZE (result) <= AOP_SIZE (right))
8704 /* if they are in the same place */
8705 if (sameRegs (AOP (right), AOP (result)))
8708 /* if they in different places then copy */
8709 size = AOP_SIZE (result);
8713 aopPut (AOP (result),
8714 aopGet (AOP (right), offset, FALSE, FALSE),
8716 isOperandVolatile (result, FALSE));
8723 /* if the result is of type pointer */
8728 sym_link *type = operandType (right);
8729 sym_link *etype = getSpec (type);
8731 /* pointer to generic pointer */
8732 if (IS_GENPTR (ctype))
8735 p_type = DCL_TYPE (type);
8738 if (SPEC_SCLS(etype)==S_REGISTER) {
8739 // let's assume it is a generic pointer
8742 /* we have to go by the storage class */
8743 p_type = PTR_TYPE (SPEC_OCLS (etype));
8747 /* the first two bytes are known */
8748 size = GPTRSIZE - 1;
8752 aopPut (AOP (result),
8753 aopGet (AOP (right), offset, FALSE, FALSE),
8755 isOperandVolatile (result, FALSE));
8758 /* the last byte depending on type */
8760 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8765 // pointerTypeToGPByte will have bitched.
8769 sprintf(gpValStr, "#0x%d", gpVal);
8770 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8775 /* just copy the pointers */
8776 size = AOP_SIZE (result);
8780 aopPut (AOP (result),
8781 aopGet (AOP (right), offset, FALSE, FALSE),
8783 isOperandVolatile (result, FALSE));
8789 /* so we now know that the size of destination is greater
8790 than the size of the source */
8791 /* we move to result for the size of source */
8792 size = AOP_SIZE (right);
8796 aopPut (AOP (result),
8797 aopGet (AOP (right), offset, FALSE, FALSE),
8799 isOperandVolatile (result, FALSE));
8803 /* now depending on the sign of the source && destination */
8804 size = AOP_SIZE (result) - AOP_SIZE (right);
8805 /* if unsigned or not an integral type */
8806 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8809 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8813 /* we need to extend the sign :{ */
8814 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8817 emitcode ("rlc", "a");
8818 emitcode ("subb", "a,acc");
8820 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8823 /* we are done hurray !!!! */
8826 freeAsmop (right, NULL, ic, TRUE);
8827 freeAsmop (result, NULL, ic, TRUE);
8831 /*-----------------------------------------------------------------*/
8832 /* genDjnz - generate decrement & jump if not zero instrucion */
8833 /*-----------------------------------------------------------------*/
8835 genDjnz (iCode * ic, iCode * ifx)
8841 D(emitcode ("; genDjnz",""));
8843 /* if the if condition has a false label
8844 then we cannot save */
8848 /* if the minus is not of the form
8850 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8851 !IS_OP_LITERAL (IC_RIGHT (ic)))
8854 if (operandLitValue (IC_RIGHT (ic)) != 1)
8857 /* if the size of this greater than one then no
8859 if (getSize (operandType (IC_RESULT (ic))) > 1)
8862 /* otherwise we can save BIG */
8863 lbl = newiTempLabel (NULL);
8864 lbl1 = newiTempLabel (NULL);
8866 aopOp (IC_RESULT (ic), ic, FALSE);
8868 if (AOP_NEEDSACC(IC_RESULT(ic)))
8870 /* If the result is accessed indirectly via
8871 * the accumulator, we must explicitly write
8872 * it back after the decrement.
8874 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8876 if (strcmp(rByte, "a"))
8878 /* Something is hopelessly wrong */
8879 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8880 __FILE__, __LINE__);
8881 /* We can just give up; the generated code will be inefficient,
8884 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8887 emitcode ("dec", "%s", rByte);
8888 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8889 emitcode ("jnz", "%05d$", lbl->key + 100);
8891 else if (IS_AOP_PREG (IC_RESULT (ic)))
8893 emitcode ("dec", "%s",
8894 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8895 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8896 emitcode ("jnz", "%05d$", lbl->key + 100);
8900 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8903 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8904 emitcode ("", "%05d$:", lbl->key + 100);
8905 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8906 emitcode ("", "%05d$:", lbl1->key + 100);
8908 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8913 /*-----------------------------------------------------------------*/
8914 /* genReceive - generate code for a receive iCode */
8915 /*-----------------------------------------------------------------*/
8917 genReceive (iCode * ic)
8919 int size = getSize (operandType (IC_RESULT (ic)));
8921 D(emitcode ("; genReceive",""));
8923 if (ic->argreg == 1) { /* first parameter */
8924 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8925 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8926 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8928 offset = fReturnSizeMCS51 - size;
8930 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8931 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8934 aopOp (IC_RESULT (ic), ic, FALSE);
8935 size = AOP_SIZE (IC_RESULT (ic));
8938 emitcode ("pop", "acc");
8939 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8944 aopOp (IC_RESULT (ic), ic, FALSE);
8946 assignResultValue (IC_RESULT (ic));
8948 } else { /* second receive onwards */
8950 aopOp (IC_RESULT (ic), ic, FALSE);
8951 rb1off = ic->argreg;
8953 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8956 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8959 /*-----------------------------------------------------------------*/
8960 /* genDummyRead - generate code for dummy read of volatiles */
8961 /*-----------------------------------------------------------------*/
8963 genDummyRead (iCode * ic)
8968 D(emitcode("; genDummyRead",""));
8970 right = IC_RIGHT (ic);
8972 aopOp (right, ic, FALSE);
8974 /* if the result is a bit */
8975 if (AOP_TYPE (right) == AOP_CRY)
8977 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8981 /* bit variables done */
8983 size = AOP_SIZE (right);
8987 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8992 freeAsmop (right, NULL, ic, TRUE);
8995 /*-----------------------------------------------------------------*/
8996 /* gen51Code - generate code for 8051 based controllers */
8997 /*-----------------------------------------------------------------*/
8999 gen51Code (iCode * lic)
9004 lineHead = lineCurr = NULL;
9006 /* print the allocation information */
9007 if (allocInfo && currFunc)
9008 printAllocInfo (currFunc, codeOutFile);
9009 /* if debug information required */
9010 if (options.debug && currFunc)
9012 debugFile->writeFunction(currFunc);
9014 if (IS_STATIC (currFunc->etype))
9015 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9017 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9020 /* stack pointer name */
9021 if (options.useXstack)
9027 for (ic = lic; ic; ic = ic->next)
9029 _G.current_iCode = ic;
9031 if (ic->lineno && cln != ic->lineno)
9036 emitcode ("", "C$%s$%d$%d$%d ==.",
9037 FileBaseName (ic->filename), ic->lineno,
9038 ic->level, ic->block);
9041 if (!options.noCcodeInAsm) {
9042 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9043 printCLine(ic->filename, ic->lineno));
9047 if (options.iCodeInAsm) {
9051 for (i=0; i<8; i++) {
9052 sprintf (®sInUse[i],
9053 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9056 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9058 /* if the result is marked as
9059 spilt and rematerializable or code for
9060 this has already been generated then
9062 if (resultRemat (ic) || ic->generated)
9065 /* depending on the operation */
9085 /* IPOP happens only when trying to restore a
9086 spilt live range, if there is an ifx statement
9087 following this pop then the if statement might
9088 be using some of the registers being popped which
9089 would destory the contents of the register so
9090 we need to check for this condition and handle it */
9092 ic->next->op == IFX &&
9093 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9094 genIfx (ic->next, ic);
9112 genEndFunction (ic);
9132 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9149 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9153 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9160 /* note these two are xlated by algebraic equivalence
9161 during parsing SDCC.y */
9162 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9163 "got '>=' or '<=' shouldn't have come here");
9167 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9179 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9183 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9187 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9214 case GET_VALUE_AT_ADDRESS:
9215 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9219 if (POINTER_SET (ic))
9220 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9246 addSet (&_G.sendSet, ic);
9249 case DUMMY_READ_VOLATILE:
9258 _G.current_iCode = NULL;
9260 /* now we are ready to call the
9261 peep hole optimizer */
9262 if (!options.nopeep)
9263 peepHole (&lineHead);
9265 /* now do the actual printing */
9266 printLine (lineHead, codeOutFile);