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 short rbank = -1;
79 static char *rb1regs[] = {
80 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
83 extern int mcs51_ptrRegReq;
84 extern int mcs51_nRegs;
85 extern FILE *codeOutFile;
86 static void saveRBank (int, iCode *, bool);
87 #define RESULTONSTACK(x) \
88 (IC_RESULT(x) && IC_RESULT(x)->aop && \
89 IC_RESULT(x)->aop->type == AOP_STK )
91 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
92 #define CLRC emitcode("clr","c")
93 #define SETC emitcode("setb","c")
95 static lineNode *lineHead = NULL;
96 static lineNode *lineCurr = NULL;
98 static unsigned char SLMask[] =
99 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
100 0xE0, 0xC0, 0x80, 0x00};
101 static unsigned char SRMask[] =
102 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00};
110 /*-----------------------------------------------------------------*/
111 /* emitcode - writes the code into a file : for now it is simple */
112 /*-----------------------------------------------------------------*/
114 emitcode (char *inst, char *fmt,...)
117 char lb[INITIAL_INLINEASM];
125 sprintf (lb, "%s\t", inst);
127 sprintf (lb, "%s", inst);
128 vsprintf (lb + (strlen (lb)), fmt, ap);
131 vsprintf (lb, fmt, ap);
133 while (isspace (*lbp))
137 lineCurr = (lineCurr ?
138 connectLine (lineCurr, newLineNode (lb)) :
139 (lineHead = newLineNode (lb)));
140 lineCurr->isInline = _G.inLine;
141 lineCurr->isDebug = _G.debugLine;
145 /*-----------------------------------------------------------------*/
146 /* mova - moves specified value into accumulator */
147 /*-----------------------------------------------------------------*/
151 /* do some early peephole optimization */
152 if (!strcmp(x, "a") || !strcmp(x, "acc"))
155 emitcode("mov","a,%s", x);
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
386 val += (int) operandLitValue (IC_RIGHT (ic));
387 else if (ic->op == '-')
388 val -= (int) operandLitValue (IC_RIGHT (ic));
389 else if (IS_CAST_ICODE(ic)) {
390 sym_link *from_type = operandType(IC_RIGHT(ic));
391 aop->aopu.aop_immd.from_cast_remat = 1;
392 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
393 ptr_type = DCL_TYPE(from_type);
394 if (ptr_type == IPOINTER) {
401 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
405 sprintf (buffer, "(%s %c 0x%04x)",
406 OP_SYMBOL (IC_LEFT (ic))->rname,
407 val >= 0 ? '+' : '-',
410 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
413 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
414 /* set immd2 field if required */
415 if (aop->aopu.aop_immd.from_cast_remat) {
416 sprintf(buffer,"#0x%02x",ptr_type);
417 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
418 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
424 /*-----------------------------------------------------------------*/
425 /* regsInCommon - two operands have some registers in common */
426 /*-----------------------------------------------------------------*/
428 regsInCommon (operand * op1, operand * op2)
433 /* if they have registers in common */
434 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
437 sym1 = OP_SYMBOL (op1);
438 sym2 = OP_SYMBOL (op2);
440 if (sym1->nRegs == 0 || sym2->nRegs == 0)
443 for (i = 0; i < sym1->nRegs; i++)
449 for (j = 0; j < sym2->nRegs; j++)
454 if (sym2->regs[j] == sym1->regs[i])
462 /*-----------------------------------------------------------------*/
463 /* operandsEqu - equivalent */
464 /*-----------------------------------------------------------------*/
466 operandsEqu (operand * op1, operand * op2)
470 /* if they not symbols */
471 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
474 sym1 = OP_SYMBOL (op1);
475 sym2 = OP_SYMBOL (op2);
477 /* if both are itemps & one is spilt
478 and the other is not then false */
479 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
480 sym1->isspilt != sym2->isspilt)
483 /* if they are the same */
487 if (strcmp (sym1->rname, sym2->rname) == 0)
491 /* if left is a tmp & right is not */
492 if (IS_ITEMP (op1) &&
495 (sym1->usl.spillLoc == sym2))
498 if (IS_ITEMP (op2) &&
502 (sym2->usl.spillLoc == sym1))
508 /*-----------------------------------------------------------------*/
509 /* sameRegs - two asmops have the same registers */
510 /*-----------------------------------------------------------------*/
512 sameRegs (asmop * aop1, asmop * aop2)
519 if (aop1->type != AOP_REG ||
520 aop2->type != AOP_REG)
523 if (aop1->size != aop2->size)
526 for (i = 0; i < aop1->size; i++)
527 if (aop1->aopu.aop_reg[i] !=
528 aop2->aopu.aop_reg[i])
534 /*-----------------------------------------------------------------*/
535 /* aopOp - allocates an asmop for an operand : */
536 /*-----------------------------------------------------------------*/
538 aopOp (operand * op, iCode * ic, bool result)
547 /* if this a literal */
548 if (IS_OP_LITERAL (op))
550 op->aop = aop = newAsmop (AOP_LIT);
551 aop->aopu.aop_lit = op->operand.valOperand;
552 aop->size = getSize (operandType (op));
556 /* if already has a asmop then continue */
560 /* if the underlying symbol has a aop */
561 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
563 op->aop = OP_SYMBOL (op)->aop;
567 /* if this is a true symbol */
568 if (IS_TRUE_SYMOP (op))
570 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
574 /* this is a temporary : this has
580 e) can be a return use only */
582 sym = OP_SYMBOL (op);
584 /* if the type is a conditional */
585 if (sym->regType == REG_CND)
587 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
592 /* if it is spilt then two situations
594 b) has a spill location */
595 if (sym->isspilt || sym->nRegs == 0)
598 /* rematerialize it NOW */
601 sym->aop = op->aop = aop =
603 aop->size = getSize (sym->type);
610 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
611 aop->size = getSize (sym->type);
612 for (i = 0; i < 2; i++)
613 aop->aopu.aop_str[i] = accUse[i];
621 aop = op->aop = sym->aop = newAsmop (AOP_STR);
622 aop->size = getSize (sym->type);
623 for (i = 0; i < fReturnSizeMCS51; i++)
624 aop->aopu.aop_str[i] = fReturn[i];
628 /* else spill location */
629 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
630 /* force a new aop if sizes differ */
631 sym->usl.spillLoc->aop = NULL;
633 sym->aop = op->aop = aop =
634 aopForSym (ic, sym->usl.spillLoc, result);
635 aop->size = getSize (sym->type);
639 /* must be in a register */
640 sym->aop = op->aop = aop = newAsmop (AOP_REG);
641 aop->size = sym->nRegs;
642 for (i = 0; i < sym->nRegs; i++)
643 aop->aopu.aop_reg[i] = sym->regs[i];
646 /*-----------------------------------------------------------------*/
647 /* freeAsmop - free up the asmop given to an operand */
648 /*----------------------------------------------------------------*/
650 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
667 /* depending on the asmop type only three cases need work AOP_RO
668 , AOP_R1 && AOP_STK */
676 emitcode ("pop", "ar0");
680 bitVectUnSetBit (ic->rUsed, R0_IDX);
688 emitcode ("pop", "ar1");
692 bitVectUnSetBit (ic->rUsed, R1_IDX);
698 int stk = aop->aopu.aop_stk + aop->size;
699 bitVectUnSetBit (ic->rUsed, R0_IDX);
700 bitVectUnSetBit (ic->rUsed, R1_IDX);
702 getFreePtr (ic, &aop, FALSE);
706 emitcode ("mov", "a,_bp");
707 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
708 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
712 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
717 emitcode ("pop", "acc");
718 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
721 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
724 freeAsmop (op, NULL, ic, TRUE);
727 emitcode ("pop", "ar0");
733 emitcode ("pop", "ar1");
740 /* all other cases just dealloc */
746 OP_SYMBOL (op)->aop = NULL;
747 /* if the symbol has a spill */
749 SPIL_LOC (op)->aop = NULL;
754 /*-----------------------------------------------------------------*/
755 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
756 /* clobber the accumulator */
757 /*-----------------------------------------------------------------*/
759 aopGetUsesAcc (asmop *aop, int offset)
761 if (offset > (aop->size - 1))
779 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
788 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
792 /* Error case --- will have been caught already */
799 /*-----------------------------------------------------------------*/
800 /* aopGet - for fetching value of the aop */
801 /*-----------------------------------------------------------------*/
803 aopGet (asmop * aop, int offset, bool bit16, bool dname)
808 /* offset is greater than
810 if (offset > (aop->size - 1) &&
811 aop->type != AOP_LIT)
814 /* depending on type */
820 /* if we need to increment it */
821 while (offset > aop->coff)
823 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
827 while (offset < aop->coff)
829 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
836 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
837 return (dname ? "acc" : "a");
839 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
840 rs = Safe_calloc (1, strlen (s) + 1);
845 if (aop->code && aop->coff==0 && offset>=1) {
846 emitcode ("mov", "a,#0x%02x", offset);
847 emitcode ("movc", "a,@a+dptr");
848 return (dname ? "acc" : "a");
851 while (offset > aop->coff)
853 emitcode ("inc", "dptr");
857 while (offset < aop->coff)
859 emitcode ("lcall", "__decdptr");
866 emitcode ("clr", "a");
867 emitcode ("movc", "a,@a+dptr");
871 emitcode ("movx", "a,@dptr");
873 return (dname ? "acc" : "a");
877 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
878 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
880 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
882 sprintf (s, "#(%s >> %d)",
883 aop->aopu.aop_immd.aop_immd1,
887 aop->aopu.aop_immd.aop_immd1);
888 rs = Safe_calloc (1, strlen (s) + 1);
894 sprintf (s, "(%s + %d)",
898 sprintf (s, "%s", aop->aopu.aop_dir);
899 rs = Safe_calloc (1, strlen (s) + 1);
905 return aop->aopu.aop_reg[offset]->dname;
907 return aop->aopu.aop_reg[offset]->name;
910 emitcode ("clr", "a");
911 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
912 emitcode ("rlc", "a");
913 return (dname ? "acc" : "a");
916 if (!offset && dname)
918 return aop->aopu.aop_str[offset];
921 return aopLiteral (aop->aopu.aop_lit, offset);
925 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
929 return aop->aopu.aop_str[offset];
933 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
934 "aopget got unsupported aop->type");
937 /*-----------------------------------------------------------------*/
938 /* aopPut - puts a string for a aop */
939 /*-----------------------------------------------------------------*/
941 aopPut (asmop * aop, char *s, int offset)
945 if (aop->size && offset > (aop->size - 1))
947 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
948 "aopPut got offset > aop->size");
952 /* will assign value to value */
953 /* depending on where it is ofcourse */
958 sprintf (d, "(%s + %d)",
959 aop->aopu.aop_dir, offset);
961 sprintf (d, "%s", aop->aopu.aop_dir);
964 emitcode ("mov", "%s,%s", d, s);
969 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
970 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
973 strcmp (s, "r0") == 0 ||
974 strcmp (s, "r1") == 0 ||
975 strcmp (s, "r2") == 0 ||
976 strcmp (s, "r3") == 0 ||
977 strcmp (s, "r4") == 0 ||
978 strcmp (s, "r5") == 0 ||
979 strcmp (s, "r6") == 0 ||
980 strcmp (s, "r7") == 0)
981 emitcode ("mov", "%s,%s",
982 aop->aopu.aop_reg[offset]->dname, s);
984 emitcode ("mov", "%s,%s",
985 aop->aopu.aop_reg[offset]->name, s);
992 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
993 "aopPut writting to code space");
997 while (offset > aop->coff)
1000 emitcode ("inc", "dptr");
1003 while (offset < aop->coff)
1006 emitcode ("lcall", "__decdptr");
1011 /* if not in accumulater */
1014 emitcode ("movx", "@dptr,a");
1019 while (offset > aop->coff)
1022 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1024 while (offset < aop->coff)
1027 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1034 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1040 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1042 else if (strcmp (s, "r0") == 0 ||
1043 strcmp (s, "r1") == 0 ||
1044 strcmp (s, "r2") == 0 ||
1045 strcmp (s, "r3") == 0 ||
1046 strcmp (s, "r4") == 0 ||
1047 strcmp (s, "r5") == 0 ||
1048 strcmp (s, "r6") == 0 ||
1049 strcmp (s, "r7") == 0)
1052 sprintf (buffer, "a%s", s);
1053 emitcode ("mov", "@%s,%s",
1054 aop->aopu.aop_ptr->name, buffer);
1057 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1062 if (strcmp (s, "a") == 0)
1063 emitcode ("push", "acc");
1067 emitcode ("push", "acc");
1069 emitcode ("push", s);
1075 /* if bit variable */
1076 if (!aop->aopu.aop_dir)
1078 emitcode ("clr", "a");
1079 emitcode ("rlc", "a");
1084 emitcode ("clr", "%s", aop->aopu.aop_dir);
1086 emitcode ("setb", "%s", aop->aopu.aop_dir);
1087 else if (!strcmp (s, "c"))
1088 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1091 if (strcmp (s, "a"))
1096 /* set C, if a >= 1 */
1097 emitcode ("add", "a,#0xff");
1098 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1106 if (strcmp (aop->aopu.aop_str[offset], s))
1107 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1112 if (!offset && (strcmp (s, "acc") == 0))
1115 if (strcmp (aop->aopu.aop_str[offset], s))
1116 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1120 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1121 "aopPut got unsupported aop->type");
1129 /*-----------------------------------------------------------------*/
1130 /* pointToEnd :- points to the last byte of the operand */
1131 /*-----------------------------------------------------------------*/
1133 pointToEnd (asmop * aop)
1139 aop->coff = count = (aop->size - 1);
1145 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1149 emitcode ("inc", "dptr");
1156 /*-----------------------------------------------------------------*/
1157 /* reAdjustPreg - points a register back to where it should */
1158 /*-----------------------------------------------------------------*/
1160 reAdjustPreg (asmop * aop)
1162 if ((aop->coff==0) || aop->size <= 1)
1170 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1175 emitcode ("lcall", "__decdptr");
1182 #define AOP(op) op->aop
1183 #define AOP_TYPE(op) AOP(op)->type
1184 #define AOP_SIZE(op) AOP(op)->size
1185 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1186 AOP_TYPE(x) == AOP_R0))
1188 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1189 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1191 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1192 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1193 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1195 /*-----------------------------------------------------------------*/
1196 /* genNotFloat - generates not for float operations */
1197 /*-----------------------------------------------------------------*/
1199 genNotFloat (operand * op, operand * res)
1205 D(emitcode ("; genNotFloat",""));
1207 /* we will put 127 in the first byte of
1209 aopPut (AOP (res), "#127", 0);
1210 size = AOP_SIZE (op) - 1;
1213 l = aopGet (op->aop, offset++, FALSE, FALSE);
1218 emitcode ("orl", "a,%s",
1220 offset++, FALSE, FALSE));
1223 tlbl = newiTempLabel (NULL);
1224 aopPut (res->aop, one, 1);
1225 emitcode ("jz", "%05d$", (tlbl->key + 100));
1226 aopPut (res->aop, zero, 1);
1227 emitcode ("", "%05d$:", (tlbl->key + 100));
1229 size = res->aop->size - 2;
1231 /* put zeros in the rest */
1233 aopPut (res->aop, zero, offset++);
1236 /*-----------------------------------------------------------------*/
1237 /* opIsGptr: returns non-zero if the passed operand is */
1238 /* a generic pointer type. */
1239 /*-----------------------------------------------------------------*/
1241 opIsGptr (operand * op)
1243 sym_link *type = operandType (op);
1245 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1252 /*-----------------------------------------------------------------*/
1253 /* getDataSize - get the operand data size */
1254 /*-----------------------------------------------------------------*/
1256 getDataSize (operand * op)
1259 size = AOP_SIZE (op);
1260 if (size == GPTRSIZE)
1262 sym_link *type = operandType (op);
1263 if (IS_GENPTR (type))
1265 /* generic pointer; arithmetic operations
1266 * should ignore the high byte (pointer type).
1274 /*-----------------------------------------------------------------*/
1275 /* outAcc - output Acc */
1276 /*-----------------------------------------------------------------*/
1278 outAcc (operand * result)
1281 size = getDataSize (result);
1284 aopPut (AOP (result), "a", 0);
1287 /* unsigned or positive */
1290 aopPut (AOP (result), zero, offset++);
1295 /*-----------------------------------------------------------------*/
1296 /* outBitC - output a bit C */
1297 /*-----------------------------------------------------------------*/
1299 outBitC (operand * result)
1301 /* if the result is bit */
1302 if (AOP_TYPE (result) == AOP_CRY)
1303 aopPut (AOP (result), "c", 0);
1306 emitcode ("clr", "a");
1307 emitcode ("rlc", "a");
1312 /*-----------------------------------------------------------------*/
1313 /* toBoolean - emit code for orl a,operator(sizeop) */
1314 /*-----------------------------------------------------------------*/
1316 toBoolean (operand * oper)
1318 int size = AOP_SIZE (oper) - 1;
1320 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1322 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1326 /*-----------------------------------------------------------------*/
1327 /* genNot - generate code for ! operation */
1328 /*-----------------------------------------------------------------*/
1333 sym_link *optype = operandType (IC_LEFT (ic));
1335 D(emitcode ("; genNot",""));
1337 /* assign asmOps to operand & result */
1338 aopOp (IC_LEFT (ic), ic, FALSE);
1339 aopOp (IC_RESULT (ic), ic, TRUE);
1341 /* if in bit space then a special case */
1342 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1344 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1345 emitcode ("cpl", "c");
1346 outBitC (IC_RESULT (ic));
1350 /* if type float then do float */
1351 if (IS_FLOAT (optype))
1353 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1357 toBoolean (IC_LEFT (ic));
1359 tlbl = newiTempLabel (NULL);
1360 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1361 emitcode ("", "%05d$:", tlbl->key + 100);
1362 outBitC (IC_RESULT (ic));
1365 /* release the aops */
1366 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1367 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1371 /*-----------------------------------------------------------------*/
1372 /* genCpl - generate code for complement */
1373 /*-----------------------------------------------------------------*/
1381 D(emitcode ("; genCpl",""));
1383 /* assign asmOps to operand & result */
1384 aopOp (IC_LEFT (ic), ic, FALSE);
1385 aopOp (IC_RESULT (ic), ic, TRUE);
1387 /* special case if in bit space */
1388 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1389 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1390 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1391 emitcode ("cpl", "c");
1392 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1395 tlbl=newiTempLabel(NULL);
1396 emitcode ("cjne", "%s,#0x01,%05d$",
1397 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1398 emitcode ("", "%05d$:", tlbl->key+100);
1399 outBitC (IC_RESULT(ic));
1403 size = AOP_SIZE (IC_RESULT (ic));
1406 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1408 emitcode ("cpl", "a");
1409 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1414 /* release the aops */
1415 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1416 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1419 /*-----------------------------------------------------------------*/
1420 /* genUminusFloat - unary minus for floating points */
1421 /*-----------------------------------------------------------------*/
1423 genUminusFloat (operand * op, operand * result)
1425 int size, offset = 0;
1428 D(emitcode ("; genUminusFloat",""));
1430 /* for this we just copy and then flip the bit */
1432 size = AOP_SIZE (op) - 1;
1436 aopPut (AOP (result),
1437 aopGet (AOP (op), offset, FALSE, FALSE),
1442 l = aopGet (AOP (op), offset, FALSE, FALSE);
1446 emitcode ("cpl", "acc.7");
1447 aopPut (AOP (result), "a", offset);
1450 /*-----------------------------------------------------------------*/
1451 /* genUminus - unary minus code generation */
1452 /*-----------------------------------------------------------------*/
1454 genUminus (iCode * ic)
1457 sym_link *optype, *rtype;
1460 D(emitcode ("; genUminus",""));
1463 aopOp (IC_LEFT (ic), ic, FALSE);
1464 aopOp (IC_RESULT (ic), ic, TRUE);
1466 /* if both in bit space then special
1468 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1469 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1472 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1473 emitcode ("cpl", "c");
1474 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1478 optype = operandType (IC_LEFT (ic));
1479 rtype = operandType (IC_RESULT (ic));
1481 /* if float then do float stuff */
1482 if (IS_FLOAT (optype))
1484 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1488 /* otherwise subtract from zero */
1489 size = AOP_SIZE (IC_LEFT (ic));
1494 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1495 if (!strcmp (l, "a"))
1499 emitcode ("cpl", "a");
1500 emitcode ("addc", "a,#0");
1506 emitcode ("clr", "a");
1507 emitcode ("subb", "a,%s", l);
1509 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1512 /* if any remaining bytes in the result */
1513 /* we just need to propagate the sign */
1514 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1516 emitcode ("rlc", "a");
1517 emitcode ("subb", "a,acc");
1519 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1523 /* release the aops */
1524 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1525 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1528 /*-----------------------------------------------------------------*/
1529 /* saveRegisters - will look for a call and save the registers */
1530 /*-----------------------------------------------------------------*/
1532 saveRegisters (iCode * lic)
1539 for (ic = lic; ic; ic = ic->next)
1540 if (ic->op == CALL || ic->op == PCALL)
1545 fprintf (stderr, "found parameter push with no function call\n");
1549 /* if the registers have been saved already or don't need to be then
1551 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1552 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1555 /* safe the registers in use at this time but skip the
1556 ones for the result */
1557 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1558 mcs51_rUmaskForOp (IC_RESULT(ic)));
1561 if (options.useXstack)
1563 if (bitVectBitValue (rsave, R0_IDX))
1564 emitcode ("mov", "b,r0");
1565 emitcode ("mov", "r0,%s", spname);
1566 for (i = 0; i < mcs51_nRegs; i++)
1568 if (bitVectBitValue (rsave, i))
1571 emitcode ("mov", "a,b");
1573 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1574 emitcode ("movx", "@r0,a");
1575 emitcode ("inc", "r0");
1578 emitcode ("mov", "%s,r0", spname);
1579 if (bitVectBitValue (rsave, R0_IDX))
1580 emitcode ("mov", "r0,b");
1583 for (i = 0; i < mcs51_nRegs; i++)
1585 if (bitVectBitValue (rsave, i))
1586 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1590 /*-----------------------------------------------------------------*/
1591 /* unsaveRegisters - pop the pushed registers */
1592 /*-----------------------------------------------------------------*/
1594 unsaveRegisters (iCode * ic)
1599 /* restore the registers in use at this time but skip the
1600 ones for the result */
1601 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1602 mcs51_rUmaskForOp (IC_RESULT(ic)));
1604 if (options.useXstack)
1606 emitcode ("mov", "r0,%s", spname);
1607 for (i = mcs51_nRegs; i >= 0; i--)
1609 if (bitVectBitValue (rsave, i))
1611 emitcode ("dec", "r0");
1612 emitcode ("movx", "a,@r0");
1614 emitcode ("mov", "b,a");
1616 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1620 emitcode ("mov", "%s,r0", spname);
1621 if (bitVectBitValue (rsave, R0_IDX))
1622 emitcode ("mov", "r0,b");
1625 for (i = mcs51_nRegs; i >= 0; i--)
1627 if (bitVectBitValue (rsave, i))
1628 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1634 /*-----------------------------------------------------------------*/
1636 /*-----------------------------------------------------------------*/
1638 pushSide (operand * oper, int size)
1643 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1644 if (AOP_TYPE (oper) != AOP_REG &&
1645 AOP_TYPE (oper) != AOP_DIR &&
1648 emitcode ("mov", "a,%s", l);
1649 emitcode ("push", "acc");
1652 emitcode ("push", "%s", l);
1656 /*-----------------------------------------------------------------*/
1657 /* assignResultValue - */
1658 /*-----------------------------------------------------------------*/
1660 assignResultValue (operand * oper)
1663 int size = AOP_SIZE (oper);
1666 aopPut (AOP (oper), fReturn[offset], offset);
1672 /*-----------------------------------------------------------------*/
1673 /* genXpush - pushes onto the external stack */
1674 /*-----------------------------------------------------------------*/
1676 genXpush (iCode * ic)
1678 asmop *aop = newAsmop (0);
1680 int size, offset = 0;
1682 D(emitcode ("; genXpush",""));
1684 aopOp (IC_LEFT (ic), ic, FALSE);
1685 r = getFreePtr (ic, &aop, FALSE);
1688 emitcode ("mov", "%s,_spx", r->name);
1690 size = AOP_SIZE (IC_LEFT (ic));
1694 char *l = aopGet (AOP (IC_LEFT (ic)),
1695 offset++, FALSE, FALSE);
1697 emitcode ("movx", "@%s,a", r->name);
1698 emitcode ("inc", "%s", r->name);
1703 emitcode ("mov", "_spx,%s", r->name);
1705 freeAsmop (NULL, aop, ic, TRUE);
1706 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1709 /*-----------------------------------------------------------------*/
1710 /* genIpush - genrate code for pushing this gets a little complex */
1711 /*-----------------------------------------------------------------*/
1713 genIpush (iCode * ic)
1715 int size, offset = 0;
1718 D(emitcode ("; genIpush",""));
1720 /* if this is not a parm push : ie. it is spill push
1721 and spill push is always done on the local stack */
1725 /* and the item is spilt then do nothing */
1726 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1729 aopOp (IC_LEFT (ic), ic, FALSE);
1730 size = AOP_SIZE (IC_LEFT (ic));
1731 /* push it on the stack */
1734 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1740 emitcode ("push", "%s", l);
1745 /* this is a paramter push: in this case we call
1746 the routine to find the call and save those
1747 registers that need to be saved */
1750 /* if use external stack then call the external
1751 stack pushing routine */
1752 if (options.useXstack)
1758 /* then do the push */
1759 aopOp (IC_LEFT (ic), ic, FALSE);
1762 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1763 size = AOP_SIZE (IC_LEFT (ic));
1767 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1768 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1769 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1772 emitcode ("mov", "a,%s", l);
1773 emitcode ("push", "acc");
1776 emitcode ("push", "%s", l);
1779 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1782 /*-----------------------------------------------------------------*/
1783 /* genIpop - recover the registers: can happen only for spilling */
1784 /*-----------------------------------------------------------------*/
1786 genIpop (iCode * ic)
1790 D(emitcode ("; genIpop",""));
1792 /* if the temp was not pushed then */
1793 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1796 aopOp (IC_LEFT (ic), ic, FALSE);
1797 size = AOP_SIZE (IC_LEFT (ic));
1798 offset = (size - 1);
1800 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1803 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1806 /*-----------------------------------------------------------------*/
1807 /* unsaveRBank - restores the resgister bank from stack */
1808 /*-----------------------------------------------------------------*/
1810 unsaveRBank (int bank, iCode * ic, bool popPsw)
1816 if (options.useXstack)
1820 /* Assume r0 is available for use. */
1821 r = mcs51_regWithIdx (R0_IDX);;
1826 r = getFreePtr (ic, &aop, FALSE);
1828 emitcode ("mov", "%s,_spx", r->name);
1833 if (options.useXstack)
1835 emitcode ("movx", "a,@%s", r->name);
1836 emitcode ("mov", "psw,a");
1837 emitcode ("dec", "%s", r->name);
1841 emitcode ("pop", "psw");
1845 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1847 if (options.useXstack)
1849 emitcode ("movx", "a,@%s", r->name);
1850 emitcode ("mov", "(%s+%d),a",
1851 regs8051[i].base, 8 * bank + regs8051[i].offset);
1852 emitcode ("dec", "%s", r->name);
1856 emitcode ("pop", "(%s+%d)",
1857 regs8051[i].base, 8 * bank + regs8051[i].offset);
1860 if (options.useXstack)
1862 emitcode ("mov", "_spx,%s", r->name);
1867 freeAsmop (NULL, aop, ic, TRUE);
1871 /*-----------------------------------------------------------------*/
1872 /* saveRBank - saves an entire register bank on the stack */
1873 /*-----------------------------------------------------------------*/
1875 saveRBank (int bank, iCode * ic, bool pushPsw)
1881 if (options.useXstack)
1885 /* Assume r0 is available for use. */
1886 r = mcs51_regWithIdx (R0_IDX);;
1891 r = getFreePtr (ic, &aop, FALSE);
1893 emitcode ("mov", "%s,_spx", r->name);
1896 for (i = 0; i < mcs51_nRegs; i++)
1898 if (options.useXstack)
1900 emitcode ("inc", "%s", r->name);
1901 emitcode ("mov", "a,(%s+%d)",
1902 regs8051[i].base, 8 * bank + regs8051[i].offset);
1903 emitcode ("movx", "@%s,a", r->name);
1906 emitcode ("push", "(%s+%d)",
1907 regs8051[i].base, 8 * bank + regs8051[i].offset);
1912 if (options.useXstack)
1914 emitcode ("mov", "a,psw");
1915 emitcode ("movx", "@%s,a", r->name);
1916 emitcode ("inc", "%s", r->name);
1917 emitcode ("mov", "_spx,%s", r->name);
1922 emitcode ("push", "psw");
1925 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1930 freeAsmop (NULL, aop, ic, TRUE);
1939 /*-----------------------------------------------------------------*/
1940 /* genSend - gen code for SEND */
1941 /*-----------------------------------------------------------------*/
1942 static void genSend(set *sendSet)
1947 for (sic = setFirstItem (_G.sendSet); sic;
1948 sic = setNextItem (_G.sendSet)) {
1949 int size, offset = 0;
1950 aopOp (IC_LEFT (sic), sic, FALSE);
1951 size = AOP_SIZE (IC_LEFT (sic));
1953 if (sic->argreg == 1) {
1955 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1957 if (strcmp (l, fReturn[offset]))
1958 emitcode ("mov", "%s,%s", fReturn[offset], l);
1964 emitcode ("mov","b1_%d,%s",rb1_count++,
1965 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1968 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1972 /*-----------------------------------------------------------------*/
1973 /* genCall - generates a call statement */
1974 /*-----------------------------------------------------------------*/
1976 genCall (iCode * ic)
1979 // bool restoreBank = FALSE;
1980 bool swapBanks = FALSE;
1982 D(emitcode("; genCall",""));
1984 dtype = operandType (IC_LEFT (ic));
1985 /* if send set is not empty the assign */
1988 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1989 genSend(reverseSet(_G.sendSet));
1991 genSend(_G.sendSet);
1997 /* if we are calling a not _naked function that is not using
1998 the same register bank then we need to save the
1999 destination registers on the stack */
2000 dtype = operandType (IC_LEFT (ic));
2001 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2002 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2003 !IFFUNC_ISISR (dtype))
2008 /* if caller saves & we have not saved then */
2014 emitcode ("mov", "psw,#0x%02x",
2015 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2019 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2020 OP_SYMBOL (IC_LEFT (ic))->rname :
2021 OP_SYMBOL (IC_LEFT (ic))->name));
2025 emitcode ("mov", "psw,#0x%02x",
2026 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2029 /* if we need assign a result value */
2030 if ((IS_ITEMP (IC_RESULT (ic)) &&
2031 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2032 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2033 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2034 IS_TRUE_SYMOP (IC_RESULT (ic)))
2038 aopOp (IC_RESULT (ic), ic, FALSE);
2041 assignResultValue (IC_RESULT (ic));
2043 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2046 /* adjust the stack for parameters if
2051 if (ic->parmBytes > 3)
2053 emitcode ("mov", "a,%s", spname);
2054 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2055 emitcode ("mov", "%s,a", spname);
2058 for (i = 0; i < ic->parmBytes; i++)
2059 emitcode ("dec", "%s", spname);
2062 /* if we hade saved some registers then unsave them */
2063 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2064 unsaveRegisters (ic);
2066 // /* if register bank was saved then pop them */
2068 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2071 /*-----------------------------------------------------------------*/
2072 /* -10l - generates a call by pointer statement */
2073 /*-----------------------------------------------------------------*/
2075 genPcall (iCode * ic)
2078 symbol *rlbl = newiTempLabel (NULL);
2079 // bool restoreBank=FALSE;
2080 bool swapBanks = FALSE;
2082 D(emitcode("; genPCall",""));
2084 /* if caller saves & we have not saved then */
2088 /* if we are calling a not _naked function that is not using
2089 the same register bank then we need to save the
2090 destination registers on the stack */
2091 dtype = operandType (IC_LEFT (ic))->next;
2092 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2093 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2094 !IFFUNC_ISISR (dtype))
2096 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2097 // restoreBank=TRUE;
2099 // need caution message to user here
2102 /* push the return address on to the stack */
2103 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2104 emitcode ("push", "acc");
2105 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2106 emitcode ("push", "acc");
2108 /* now push the calling address */
2109 aopOp (IC_LEFT (ic), ic, FALSE);
2111 pushSide (IC_LEFT (ic), FPTRSIZE);
2113 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2115 /* if send set is not empty the assign */
2118 genSend(reverseSet(_G.sendSet));
2124 emitcode ("mov", "psw,#0x%02x",
2125 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2129 emitcode ("ret", "");
2130 emitcode ("", "%05d$:", (rlbl->key + 100));
2135 emitcode ("mov", "psw,#0x%02x",
2136 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2139 /* if we need assign a result value */
2140 if ((IS_ITEMP (IC_RESULT (ic)) &&
2141 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2142 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2143 IS_TRUE_SYMOP (IC_RESULT (ic)))
2147 aopOp (IC_RESULT (ic), ic, FALSE);
2150 assignResultValue (IC_RESULT (ic));
2152 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2155 /* adjust the stack for parameters if
2160 if (ic->parmBytes > 3)
2162 emitcode ("mov", "a,%s", spname);
2163 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2164 emitcode ("mov", "%s,a", spname);
2167 for (i = 0; i < ic->parmBytes; i++)
2168 emitcode ("dec", "%s", spname);
2172 // /* if register bank was saved then unsave them */
2174 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2176 /* if we hade saved some registers then
2178 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2179 unsaveRegisters (ic);
2182 /*-----------------------------------------------------------------*/
2183 /* resultRemat - result is rematerializable */
2184 /*-----------------------------------------------------------------*/
2186 resultRemat (iCode * ic)
2188 if (SKIP_IC (ic) || ic->op == IFX)
2191 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2193 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2194 if (sym->remat && !POINTER_SET (ic))
2201 #if defined(__BORLANDC__) || defined(_MSC_VER)
2202 #define STRCASECMP stricmp
2204 #define STRCASECMP strcasecmp
2207 /*-----------------------------------------------------------------*/
2208 /* inExcludeList - return 1 if the string is in exclude Reg list */
2209 /*-----------------------------------------------------------------*/
2211 inExcludeList (char *s)
2215 if (options.excludeRegs[i] &&
2216 STRCASECMP (options.excludeRegs[i], "none") == 0)
2219 for (i = 0; options.excludeRegs[i]; i++)
2221 if (options.excludeRegs[i] &&
2222 STRCASECMP (s, options.excludeRegs[i]) == 0)
2228 /*-----------------------------------------------------------------*/
2229 /* genFunction - generated code for function entry */
2230 /*-----------------------------------------------------------------*/
2232 genFunction (iCode * ic)
2236 bool switchedPSW = FALSE;
2237 int calleesaves_saved_register = -1;
2240 /* create the function header */
2241 emitcode (";", "-----------------------------------------");
2242 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2243 emitcode (";", "-----------------------------------------");
2245 emitcode ("", "%s:", sym->rname);
2246 ftype = operandType (IC_LEFT (ic));
2248 if (IFFUNC_ISNAKED(ftype))
2250 emitcode(";", "naked function: no prologue.");
2254 /* if critical function then turn interrupts off */
2255 if (IFFUNC_ISCRITICAL (ftype))
2256 emitcode ("clr", "ea");
2258 /* here we need to generate the equates for the
2259 register bank if required */
2260 if (FUNC_REGBANK (ftype) != rbank)
2264 rbank = FUNC_REGBANK (ftype);
2265 for (i = 0; i < mcs51_nRegs; i++)
2267 if (strcmp (regs8051[i].base, "0") == 0)
2268 emitcode ("", "%s = 0x%02x",
2270 8 * rbank + regs8051[i].offset);
2272 emitcode ("", "%s = %s + 0x%02x",
2275 8 * rbank + regs8051[i].offset);
2279 /* if this is an interrupt service routine then
2280 save acc, b, dpl, dph */
2281 if (IFFUNC_ISISR (sym->type))
2284 if (!inExcludeList ("acc"))
2285 emitcode ("push", "acc");
2286 if (!inExcludeList ("b"))
2287 emitcode ("push", "b");
2288 if (!inExcludeList ("dpl"))
2289 emitcode ("push", "dpl");
2290 if (!inExcludeList ("dph"))
2291 emitcode ("push", "dph");
2292 /* if this isr has no bank i.e. is going to
2293 run with bank 0 , then we need to save more
2295 if (!FUNC_REGBANK (sym->type))
2298 /* if this function does not call any other
2299 function then we can be economical and
2300 save only those registers that are used */
2301 if (!IFFUNC_HASFCALL(sym->type))
2305 /* if any registers used */
2308 /* save the registers used */
2309 for (i = 0; i < sym->regsUsed->size; i++)
2311 if (bitVectBitValue (sym->regsUsed, i) ||
2312 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2313 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2321 /* this function has a function call cannot
2322 determines register usage so we will have to push the
2324 saveRBank (0, ic, FALSE);
2325 if (options.parms_in_bank1) {
2327 for (i=0; i < 8 ; i++ ) {
2328 emitcode ("push","%s",rb1regs[i]);
2335 /* This ISR uses a non-zero bank.
2337 * We assume that the bank is available for our
2340 * However, if this ISR calls a function which uses some
2341 * other bank, we must save that bank entirely.
2343 unsigned long banksToSave = 0;
2345 if (IFFUNC_HASFCALL(sym->type))
2348 #define MAX_REGISTER_BANKS 4
2353 for (i = ic; i; i = i->next)
2355 if (i->op == ENDFUNCTION)
2357 /* we got to the end OK. */
2365 dtype = operandType (IC_LEFT(i));
2367 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2369 /* Mark this bank for saving. */
2370 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2372 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2376 banksToSave |= (1 << FUNC_REGBANK(dtype));
2379 /* And note that we don't need to do it in
2387 /* This is a mess; we have no idea what
2388 * register bank the called function might
2391 * The only thing I can think of to do is
2392 * throw a warning and hope.
2394 werror(W_FUNCPTR_IN_USING_ISR);
2398 if (banksToSave && options.useXstack)
2400 /* Since we aren't passing it an ic,
2401 * saveRBank will assume r0 is available to abuse.
2403 * So switch to our (trashable) bank now, so
2404 * the caller's R0 isn't trashed.
2406 emitcode ("push", "psw");
2407 emitcode ("mov", "psw,#0x%02x",
2408 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2412 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2414 if (banksToSave & (1 << ix))
2416 saveRBank(ix, NULL, FALSE);
2420 // TODO: this needs a closer look
2421 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2426 /* if callee-save to be used for this function
2427 then save the registers being used in this function */
2428 if (IFFUNC_CALLEESAVES(sym->type))
2432 /* if any registers used */
2435 /* save the registers used */
2436 for (i = 0; i < sym->regsUsed->size; i++)
2438 if (bitVectBitValue (sym->regsUsed, i) ||
2439 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2441 /* remember one saved register for later usage */
2442 if (calleesaves_saved_register < 0)
2443 calleesaves_saved_register = i;
2444 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2452 /* set the register bank to the desired value */
2453 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2456 emitcode ("push", "psw");
2457 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2460 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2463 if (options.useXstack)
2465 emitcode ("mov", "r0,%s", spname);
2466 emitcode ("mov", "a,_bp");
2467 emitcode ("movx", "@r0,a");
2468 emitcode ("inc", "%s", spname);
2472 /* set up the stack */
2473 emitcode ("push", "_bp"); /* save the callers stack */
2475 emitcode ("mov", "_bp,%s", spname);
2478 /* adjust the stack for the function */
2484 werror (W_STACK_OVERFLOW, sym->name);
2486 if (i > 3 && sym->recvSize < 4)
2489 emitcode ("mov", "a,sp");
2490 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2491 emitcode ("mov", "sp,a");
2496 if (IFFUNC_CALLEESAVES(sym->type))
2498 /* if it's a callee-saves function we need a saved register */
2499 if (calleesaves_saved_register >= 0)
2501 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2502 emitcode ("mov", "a,sp");
2503 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2504 emitcode ("mov", "sp,a");
2505 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2508 /* do it the hard way */
2510 emitcode ("inc", "sp");
2514 /* not callee-saves, we can clobber r0 */
2515 emitcode ("mov", "r0,a");
2516 emitcode ("mov", "a,sp");
2517 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2518 emitcode ("mov", "sp,a");
2519 emitcode ("mov", "a,r0");
2524 emitcode ("inc", "sp");
2530 emitcode ("mov", "a,_spx");
2531 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2532 emitcode ("mov", "_spx,a");
2537 /*-----------------------------------------------------------------*/
2538 /* genEndFunction - generates epilogue for functions */
2539 /*-----------------------------------------------------------------*/
2541 genEndFunction (iCode * ic)
2543 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2545 if (IFFUNC_ISNAKED(sym->type))
2547 emitcode(";", "naked function: no epilogue.");
2551 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2553 emitcode ("mov", "%s,_bp", spname);
2556 /* if use external stack but some variables were
2557 added to the local stack then decrement the
2559 if (options.useXstack && sym->stack)
2561 emitcode ("mov", "a,sp");
2562 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2563 emitcode ("mov", "sp,a");
2567 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2569 if (options.useXstack)
2571 emitcode ("mov", "r0,%s", spname);
2572 emitcode ("movx", "a,@r0");
2573 emitcode ("mov", "_bp,a");
2574 emitcode ("dec", "%s", spname);
2578 emitcode ("pop", "_bp");
2582 /* restore the register bank */
2583 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2585 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2586 || !options.useXstack)
2588 /* Special case of ISR using non-zero bank with useXstack
2591 emitcode ("pop", "psw");
2595 if (IFFUNC_ISISR (sym->type))
2598 /* now we need to restore the registers */
2599 /* if this isr has no bank i.e. is going to
2600 run with bank 0 , then we need to save more
2602 if (!FUNC_REGBANK (sym->type))
2604 /* if this function does not call any other
2605 function then we can be economical and
2606 save only those registers that are used */
2607 if (!IFFUNC_HASFCALL(sym->type))
2611 /* if any registers used */
2614 /* save the registers used */
2615 for (i = sym->regsUsed->size; i >= 0; i--)
2617 if (bitVectBitValue (sym->regsUsed, i) ||
2618 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2619 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2626 if (options.parms_in_bank1) {
2628 for (i = 7 ; i >= 0 ; i-- ) {
2629 emitcode ("pop","%s",rb1regs[i]);
2632 /* this function has a function call cannot
2633 determines register usage so we will have to pop the
2635 unsaveRBank (0, ic, FALSE);
2640 /* This ISR uses a non-zero bank.
2642 * Restore any register banks saved by genFunction
2645 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2648 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2650 if (savedBanks & (1 << ix))
2652 unsaveRBank(ix, NULL, FALSE);
2656 if (options.useXstack)
2658 /* Restore bank AFTER calling unsaveRBank,
2659 * since it can trash r0.
2661 emitcode ("pop", "psw");
2665 if (!inExcludeList ("dph"))
2666 emitcode ("pop", "dph");
2667 if (!inExcludeList ("dpl"))
2668 emitcode ("pop", "dpl");
2669 if (!inExcludeList ("b"))
2670 emitcode ("pop", "b");
2671 if (!inExcludeList ("acc"))
2672 emitcode ("pop", "acc");
2674 if (IFFUNC_ISCRITICAL (sym->type))
2675 emitcode ("setb", "ea");
2677 /* if debug then send end of function */
2678 if (options.debug && currFunc)
2681 emitcode ("", "C$%s$%d$%d$%d ==.",
2682 FileBaseName (ic->filename), currFunc->lastLine,
2683 ic->level, ic->block);
2684 if (IS_STATIC (currFunc->etype))
2685 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2687 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2691 emitcode ("reti", "");
2695 if (IFFUNC_ISCRITICAL (sym->type))
2696 emitcode ("setb", "ea");
2698 if (IFFUNC_CALLEESAVES(sym->type))
2702 /* if any registers used */
2705 /* save the registers used */
2706 for (i = sym->regsUsed->size; i >= 0; i--)
2708 if (bitVectBitValue (sym->regsUsed, i) ||
2709 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2710 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2716 /* if debug then send end of function */
2717 if (options.debug && currFunc)
2720 emitcode ("", "C$%s$%d$%d$%d ==.",
2721 FileBaseName (ic->filename), currFunc->lastLine,
2722 ic->level, ic->block);
2723 if (IS_STATIC (currFunc->etype))
2724 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2726 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2730 emitcode ("ret", "");
2735 /*-----------------------------------------------------------------*/
2736 /* genRet - generate code for return statement */
2737 /*-----------------------------------------------------------------*/
2741 int size, offset = 0, pushed = 0;
2743 D(emitcode ("; genRet",""));
2745 /* if we have no return value then
2746 just generate the "ret" */
2750 /* we have something to return then
2751 move the return value into place */
2752 aopOp (IC_LEFT (ic), ic, FALSE);
2753 size = AOP_SIZE (IC_LEFT (ic));
2758 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2761 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2763 emitcode ("push", "%s", l);
2768 l = aopGet (AOP (IC_LEFT (ic)), offset,
2770 if (strcmp (fReturn[offset], l))
2771 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2780 if (strcmp (fReturn[pushed], "a"))
2781 emitcode ("pop", fReturn[pushed]);
2783 emitcode ("pop", "acc");
2786 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2789 /* generate a jump to the return label
2790 if the next is not the return statement */
2791 if (!(ic->next && ic->next->op == LABEL &&
2792 IC_LABEL (ic->next) == returnLabel))
2794 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2798 /*-----------------------------------------------------------------*/
2799 /* genLabel - generates a label */
2800 /*-----------------------------------------------------------------*/
2802 genLabel (iCode * ic)
2804 /* special case never generate */
2805 if (IC_LABEL (ic) == entryLabel)
2808 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2811 /*-----------------------------------------------------------------*/
2812 /* genGoto - generates a ljmp */
2813 /*-----------------------------------------------------------------*/
2815 genGoto (iCode * ic)
2817 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2820 /*-----------------------------------------------------------------*/
2821 /* findLabelBackwards: walks back through the iCode chain looking */
2822 /* for the given label. Returns number of iCode instructions */
2823 /* between that label and given ic. */
2824 /* Returns zero if label not found. */
2825 /*-----------------------------------------------------------------*/
2827 findLabelBackwards (iCode * ic, int key)
2836 /* If we have any pushes or pops, we cannot predict the distance.
2837 I don't like this at all, this should be dealt with in the
2839 if (ic->op == IPUSH || ic->op == IPOP) {
2843 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2852 /*-----------------------------------------------------------------*/
2853 /* genPlusIncr :- does addition with increment if possible */
2854 /*-----------------------------------------------------------------*/
2856 genPlusIncr (iCode * ic)
2858 unsigned int icount;
2859 unsigned int size = getDataSize (IC_RESULT (ic));
2861 /* will try to generate an increment */
2862 /* if the right side is not a literal
2864 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2867 /* if the literal value of the right hand side
2868 is greater than 4 then it is not worth it */
2869 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2872 D(emitcode ("; genPlusIncr",""));
2874 /* if increment >=16 bits in register or direct space */
2875 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2876 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2884 /* If the next instruction is a goto and the goto target
2885 * is < 10 instructions previous to this, we can generate
2886 * jumps straight to that target.
2888 if (ic->next && ic->next->op == GOTO
2889 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2890 && labelRange <= 10)
2892 emitcode (";", "tail increment optimized");
2893 tlbl = IC_LABEL (ic->next);
2898 tlbl = newiTempLabel (NULL);
2901 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2902 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2903 IS_AOP_PREG (IC_RESULT (ic)))
2904 emitcode ("cjne", "%s,#0x00,%05d$",
2905 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2909 emitcode ("clr", "a");
2910 emitcode ("cjne", "a,%s,%05d$",
2911 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2915 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2918 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2919 IS_AOP_PREG (IC_RESULT (ic)))
2920 emitcode ("cjne", "%s,#0x00,%05d$",
2921 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2924 emitcode ("cjne", "a,%s,%05d$",
2925 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2928 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2932 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2933 IS_AOP_PREG (IC_RESULT (ic)))
2934 emitcode ("cjne", "%s,#0x00,%05d$",
2935 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2939 emitcode ("cjne", "a,%s,%05d$",
2940 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2943 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2948 emitcode ("", "%05d$:", tlbl->key + 100);
2953 /* if the sizes are greater than 1 then we cannot */
2954 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2955 AOP_SIZE (IC_LEFT (ic)) > 1)
2958 /* we can if the aops of the left & result match or
2959 if they are in registers and the registers are the
2961 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2966 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2967 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2968 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2974 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2983 /*-----------------------------------------------------------------*/
2984 /* outBitAcc - output a bit in acc */
2985 /*-----------------------------------------------------------------*/
2987 outBitAcc (operand * result)
2989 symbol *tlbl = newiTempLabel (NULL);
2990 /* if the result is a bit */
2991 if (AOP_TYPE (result) == AOP_CRY)
2993 aopPut (AOP (result), "a", 0);
2997 emitcode ("jz", "%05d$", tlbl->key + 100);
2998 emitcode ("mov", "a,%s", one);
2999 emitcode ("", "%05d$:", tlbl->key + 100);
3004 /*-----------------------------------------------------------------*/
3005 /* genPlusBits - generates code for addition of two bits */
3006 /*-----------------------------------------------------------------*/
3008 genPlusBits (iCode * ic)
3010 D(emitcode ("; genPlusBits",""));
3012 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3014 symbol *lbl = newiTempLabel (NULL);
3015 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3016 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3017 emitcode ("cpl", "c");
3018 emitcode ("", "%05d$:", (lbl->key + 100));
3019 outBitC (IC_RESULT (ic));
3023 emitcode ("clr", "a");
3024 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3025 emitcode ("rlc", "a");
3026 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3027 emitcode ("addc", "a,#0x00");
3028 outAcc (IC_RESULT (ic));
3033 /* This is the original version of this code.
3035 * This is being kept around for reference,
3036 * because I am not entirely sure I got it right...
3039 adjustArithmeticResult (iCode * ic)
3041 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3042 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3043 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3044 aopPut (AOP (IC_RESULT (ic)),
3045 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3048 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3049 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3050 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3051 aopPut (AOP (IC_RESULT (ic)),
3052 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3055 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3056 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3057 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3058 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3059 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3062 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3063 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3067 /* This is the pure and virtuous version of this code.
3068 * I'm pretty certain it's right, but not enough to toss the old
3072 adjustArithmeticResult (iCode * ic)
3074 if (opIsGptr (IC_RESULT (ic)) &&
3075 opIsGptr (IC_LEFT (ic)) &&
3076 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3078 aopPut (AOP (IC_RESULT (ic)),
3079 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3083 if (opIsGptr (IC_RESULT (ic)) &&
3084 opIsGptr (IC_RIGHT (ic)) &&
3085 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3087 aopPut (AOP (IC_RESULT (ic)),
3088 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3092 if (opIsGptr (IC_RESULT (ic)) &&
3093 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3094 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3095 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3096 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3099 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3100 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3105 /*-----------------------------------------------------------------*/
3106 /* genPlus - generates code for addition */
3107 /*-----------------------------------------------------------------*/
3109 genPlus (iCode * ic)
3111 int size, offset = 0;
3113 asmop *leftOp, *rightOp;
3115 /* special cases :- */
3117 D(emitcode ("; genPlus",""));
3119 aopOp (IC_LEFT (ic), ic, FALSE);
3120 aopOp (IC_RIGHT (ic), ic, FALSE);
3121 aopOp (IC_RESULT (ic), ic, TRUE);
3123 /* if literal, literal on the right or
3124 if left requires ACC or right is already
3126 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3127 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3128 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3130 operand *t = IC_RIGHT (ic);
3131 IC_RIGHT (ic) = IC_LEFT (ic);
3135 /* if both left & right are in bit
3137 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3138 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3144 /* if left in bit space & right literal */
3145 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3146 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3148 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3149 /* if result in bit space */
3150 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3152 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3153 emitcode ("cpl", "c");
3154 outBitC (IC_RESULT (ic));
3158 size = getDataSize (IC_RESULT (ic));
3161 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3162 emitcode ("addc", "a,#00");
3163 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3169 /* if I can do an increment instead
3170 of add then GOOD for ME */
3171 if (genPlusIncr (ic) == TRUE)
3174 size = getDataSize (IC_RESULT (ic));
3176 leftOp = AOP(IC_LEFT(ic));
3177 rightOp = AOP(IC_RIGHT(ic));
3182 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3184 emitcode("mov", "b,a");
3185 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3186 emitcode("xch", "a,b");
3187 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3188 emitcode (add, "a,b");
3190 else if (aopGetUsesAcc (leftOp, offset))
3192 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3193 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3197 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3198 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3200 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3201 add = "addc"; /* further adds must propagate carry */
3204 adjustArithmeticResult (ic);
3207 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3208 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3209 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3212 /*-----------------------------------------------------------------*/
3213 /* genMinusDec :- does subtraction with deccrement if possible */
3214 /*-----------------------------------------------------------------*/
3216 genMinusDec (iCode * ic)
3218 unsigned int icount;
3219 unsigned int size = getDataSize (IC_RESULT (ic));
3221 /* will try to generate an increment */
3222 /* if the right side is not a literal
3224 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3227 /* if the literal value of the right hand side
3228 is greater than 4 then it is not worth it */
3229 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3232 D(emitcode ("; genMinusDec",""));
3234 /* if decrement >=16 bits in register or direct space */
3235 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3236 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3244 /* If the next instruction is a goto and the goto target
3245 * is <= 10 instructions previous to this, we can generate
3246 * jumps straight to that target.
3248 if (ic->next && ic->next->op == GOTO
3249 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3250 && labelRange <= 10)
3252 emitcode (";", "tail decrement optimized");
3253 tlbl = IC_LABEL (ic->next);
3258 tlbl = newiTempLabel (NULL);
3262 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3263 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3264 IS_AOP_PREG (IC_RESULT (ic)))
3265 emitcode ("cjne", "%s,#0xff,%05d$"
3266 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3270 emitcode ("mov", "a,#0xff");
3271 emitcode ("cjne", "a,%s,%05d$"
3272 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3275 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3278 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3279 IS_AOP_PREG (IC_RESULT (ic)))
3280 emitcode ("cjne", "%s,#0xff,%05d$"
3281 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3285 emitcode ("cjne", "a,%s,%05d$"
3286 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3289 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3293 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3294 IS_AOP_PREG (IC_RESULT (ic)))
3295 emitcode ("cjne", "%s,#0xff,%05d$"
3296 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3300 emitcode ("cjne", "a,%s,%05d$"
3301 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3304 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3308 emitcode ("", "%05d$:", tlbl->key + 100);
3313 /* if the sizes are greater than 1 then we cannot */
3314 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3315 AOP_SIZE (IC_LEFT (ic)) > 1)
3318 /* we can if the aops of the left & result match or
3319 if they are in registers and the registers are the
3321 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3325 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3333 /*-----------------------------------------------------------------*/
3334 /* addSign - complete with sign */
3335 /*-----------------------------------------------------------------*/
3337 addSign (operand * result, int offset, int sign)
3339 int size = (getDataSize (result) - offset);
3344 emitcode ("rlc", "a");
3345 emitcode ("subb", "a,acc");
3347 aopPut (AOP (result), "a", offset++);
3351 aopPut (AOP (result), zero, offset++);
3355 /*-----------------------------------------------------------------*/
3356 /* genMinusBits - generates code for subtraction of two bits */
3357 /*-----------------------------------------------------------------*/
3359 genMinusBits (iCode * ic)
3361 symbol *lbl = newiTempLabel (NULL);
3363 D(emitcode ("; genMinusBits",""));
3365 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3367 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3368 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3369 emitcode ("cpl", "c");
3370 emitcode ("", "%05d$:", (lbl->key + 100));
3371 outBitC (IC_RESULT (ic));
3375 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3376 emitcode ("subb", "a,acc");
3377 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3378 emitcode ("inc", "a");
3379 emitcode ("", "%05d$:", (lbl->key + 100));
3380 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3381 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3385 /*-----------------------------------------------------------------*/
3386 /* genMinus - generates code for subtraction */
3387 /*-----------------------------------------------------------------*/
3389 genMinus (iCode * ic)
3391 int size, offset = 0;
3393 D(emitcode ("; genMinus",""));
3395 aopOp (IC_LEFT (ic), ic, FALSE);
3396 aopOp (IC_RIGHT (ic), ic, FALSE);
3397 aopOp (IC_RESULT (ic), ic, TRUE);
3399 /* special cases :- */
3400 /* if both left & right are in bit space */
3401 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3402 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3408 /* if I can do an decrement instead
3409 of subtract then GOOD for ME */
3410 if (genMinusDec (ic) == TRUE)
3413 size = getDataSize (IC_RESULT (ic));
3415 /* if literal, add a,#-lit, else normal subb */
3416 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3418 unsigned long lit = 0L;
3420 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3425 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3426 /* first add without previous c */
3428 if (!size && lit==-1) {
3429 emitcode ("dec", "a");
3431 emitcode ("add", "a,#0x%02x",
3432 (unsigned int) (lit & 0x0FFL));
3435 emitcode ("addc", "a,#0x%02x",
3436 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3438 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3443 asmop *leftOp, *rightOp;
3445 leftOp = AOP(IC_LEFT(ic));
3446 rightOp = AOP(IC_RIGHT(ic));
3450 if (aopGetUsesAcc(rightOp, offset)) {
3451 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3452 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3454 emitcode( "setb", "c");
3456 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3457 emitcode("cpl", "a");
3459 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3462 emitcode ("subb", "a,%s",
3463 aopGet(rightOp, offset, FALSE, TRUE));
3466 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3471 adjustArithmeticResult (ic);
3474 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3475 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3480 /*-----------------------------------------------------------------*/
3481 /* genMultbits :- multiplication of bits */
3482 /*-----------------------------------------------------------------*/
3484 genMultbits (operand * left,
3488 D(emitcode ("; genMultbits",""));
3490 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3491 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3496 /*-----------------------------------------------------------------*/
3497 /* genMultOneByte : 8*8=8/16 bit multiplication */
3498 /*-----------------------------------------------------------------*/
3500 genMultOneByte (operand * left,
3504 sym_link *opetype = operandType (result);
3506 int size=AOP_SIZE(result);
3508 D(emitcode ("; genMultOneByte",""));
3510 if (size<1 || size>2) {
3511 // this should never happen
3512 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3513 AOP_SIZE(result), __FILE__, lineno);
3517 /* (if two literals: the value is computed before) */
3518 /* if one literal, literal on the right */
3519 if (AOP_TYPE (left) == AOP_LIT)
3524 //emitcode (";", "swapped left and right");
3527 if (SPEC_USIGN(opetype)
3528 // ignore the sign of left and right, what else can we do?
3529 || (SPEC_USIGN(operandType(left)) &&
3530 SPEC_USIGN(operandType(right)))) {
3531 // just an unsigned 8*8=8/16 multiply
3532 //emitcode (";","unsigned");
3533 // TODO: check for accumulator clash between left & right aops?
3534 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3535 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3536 emitcode ("mul", "ab");
3537 aopPut (AOP (result), "a", 0);
3539 aopPut (AOP (result), "b", 1);
3544 // we have to do a signed multiply
3546 //emitcode (";", "signed");
3547 emitcode ("clr", "F0"); // reset sign flag
3548 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3550 lbl=newiTempLabel(NULL);
3551 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3552 // left side is negative, 8-bit two's complement, this fails for -128
3553 emitcode ("setb", "F0"); // set sign flag
3554 emitcode ("cpl", "a");
3555 emitcode ("inc", "a");
3557 emitcode ("", "%05d$:", lbl->key+100);
3560 if (AOP_TYPE(right)==AOP_LIT) {
3561 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3562 /* AND literal negative */
3564 emitcode ("cpl", "F0"); // complement sign flag
3565 emitcode ("mov", "b,#0x%02x", -val);
3567 emitcode ("mov", "b,#0x%02x", val);
3570 lbl=newiTempLabel(NULL);
3571 emitcode ("mov", "b,a");
3572 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3573 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3574 // right side is negative, 8-bit two's complement
3575 emitcode ("cpl", "F0"); // complement sign flag
3576 emitcode ("cpl", "a");
3577 emitcode ("inc", "a");
3578 emitcode ("", "%05d$:", lbl->key+100);
3580 emitcode ("mul", "ab");
3582 lbl=newiTempLabel(NULL);
3583 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3584 // only ONE op was negative, we have to do a 8/16-bit two's complement
3585 emitcode ("cpl", "a"); // lsb
3587 emitcode ("inc", "a");
3589 emitcode ("add", "a,#1");
3590 emitcode ("xch", "a,b");
3591 emitcode ("cpl", "a"); // msb
3592 emitcode ("addc", "a,#0");
3593 emitcode ("xch", "a,b");
3596 emitcode ("", "%05d$:", lbl->key+100);
3597 aopPut (AOP (result), "a", 0);
3599 aopPut (AOP (result), "b", 1);
3603 /*-----------------------------------------------------------------*/
3604 /* genMult - generates code for multiplication */
3605 /*-----------------------------------------------------------------*/
3607 genMult (iCode * ic)
3609 operand *left = IC_LEFT (ic);
3610 operand *right = IC_RIGHT (ic);
3611 operand *result = IC_RESULT (ic);
3613 D(emitcode ("; genMult",""));
3615 /* assign the amsops */
3616 aopOp (left, ic, FALSE);
3617 aopOp (right, ic, FALSE);
3618 aopOp (result, ic, TRUE);
3620 /* special cases first */
3622 if (AOP_TYPE (left) == AOP_CRY &&
3623 AOP_TYPE (right) == AOP_CRY)
3625 genMultbits (left, right, result);
3629 /* if both are of size == 1 */
3630 #if 0 // one of them can be a sloc shared with the result
3631 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3633 if (getSize(operandType(left)) == 1 &&
3634 getSize(operandType(right)) == 1)
3637 genMultOneByte (left, right, result);
3641 /* should have been converted to function call */
3642 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3643 getSize(OP_SYMBOL(right)->type));
3647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3648 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3649 freeAsmop (result, NULL, ic, TRUE);
3652 /*-----------------------------------------------------------------*/
3653 /* genDivbits :- division of bits */
3654 /*-----------------------------------------------------------------*/
3656 genDivbits (operand * left,
3663 D(emitcode ("; genDivbits",""));
3665 /* the result must be bit */
3666 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3667 l = aopGet (AOP (left), 0, FALSE, FALSE);
3671 emitcode ("div", "ab");
3672 emitcode ("rrc", "a");
3673 aopPut (AOP (result), "c", 0);
3676 /*-----------------------------------------------------------------*/
3677 /* genDivOneByte : 8 bit division */
3678 /*-----------------------------------------------------------------*/
3680 genDivOneByte (operand * left,
3684 sym_link *opetype = operandType (result);
3689 D(emitcode ("; genDivOneByte",""));
3691 size = AOP_SIZE (result) - 1;
3693 /* signed or unsigned */
3694 if (SPEC_USIGN (opetype))
3696 /* unsigned is easy */
3697 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3698 l = aopGet (AOP (left), 0, FALSE, FALSE);
3700 emitcode ("div", "ab");
3701 aopPut (AOP (result), "a", 0);
3703 aopPut (AOP (result), zero, offset++);
3707 /* signed is a little bit more difficult */
3709 /* save the signs of the operands */
3710 l = aopGet (AOP (left), 0, FALSE, FALSE);
3712 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3713 emitcode ("push", "acc"); /* save it on the stack */
3715 /* now sign adjust for both left & right */
3716 l = aopGet (AOP (right), 0, FALSE, FALSE);
3718 lbl = newiTempLabel (NULL);
3719 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3720 emitcode ("cpl", "a");
3721 emitcode ("inc", "a");
3722 emitcode ("", "%05d$:", (lbl->key + 100));
3723 emitcode ("mov", "b,a");
3725 /* sign adjust left side */
3726 l = aopGet (AOP (left), 0, FALSE, FALSE);
3729 lbl = newiTempLabel (NULL);
3730 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3731 emitcode ("cpl", "a");
3732 emitcode ("inc", "a");
3733 emitcode ("", "%05d$:", (lbl->key + 100));
3735 /* now the division */
3736 emitcode ("div", "ab");
3737 /* we are interested in the lower order
3739 emitcode ("mov", "b,a");
3740 lbl = newiTempLabel (NULL);
3741 emitcode ("pop", "acc");
3742 /* if there was an over flow we don't
3743 adjust the sign of the result */
3744 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3745 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3747 emitcode ("clr", "a");
3748 emitcode ("subb", "a,b");
3749 emitcode ("mov", "b,a");
3750 emitcode ("", "%05d$:", (lbl->key + 100));
3752 /* now we are done */
3753 aopPut (AOP (result), "b", 0);
3756 emitcode ("mov", "c,b.7");
3757 emitcode ("subb", "a,acc");
3760 aopPut (AOP (result), "a", offset++);
3764 /*-----------------------------------------------------------------*/
3765 /* genDiv - generates code for division */
3766 /*-----------------------------------------------------------------*/
3770 operand *left = IC_LEFT (ic);
3771 operand *right = IC_RIGHT (ic);
3772 operand *result = IC_RESULT (ic);
3774 D(emitcode ("; genDiv",""));
3776 /* assign the amsops */
3777 aopOp (left, ic, FALSE);
3778 aopOp (right, ic, FALSE);
3779 aopOp (result, ic, TRUE);
3781 /* special cases first */
3783 if (AOP_TYPE (left) == AOP_CRY &&
3784 AOP_TYPE (right) == AOP_CRY)
3786 genDivbits (left, right, result);
3790 /* if both are of size == 1 */
3791 if (AOP_SIZE (left) == 1 &&
3792 AOP_SIZE (right) == 1)
3794 genDivOneByte (left, right, result);
3798 /* should have been converted to function call */
3801 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3802 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3803 freeAsmop (result, NULL, ic, TRUE);
3806 /*-----------------------------------------------------------------*/
3807 /* genModbits :- modulus of bits */
3808 /*-----------------------------------------------------------------*/
3810 genModbits (operand * left,
3817 D(emitcode ("; genModbits",""));
3819 /* the result must be bit */
3820 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3821 l = aopGet (AOP (left), 0, FALSE, FALSE);
3825 emitcode ("div", "ab");
3826 emitcode ("mov", "a,b");
3827 emitcode ("rrc", "a");
3828 aopPut (AOP (result), "c", 0);
3831 /*-----------------------------------------------------------------*/
3832 /* genModOneByte : 8 bit modulus */
3833 /*-----------------------------------------------------------------*/
3835 genModOneByte (operand * left,
3839 sym_link *opetype = operandType (result);
3843 D(emitcode ("; genModOneByte",""));
3845 /* signed or unsigned */
3846 if (SPEC_USIGN (opetype))
3848 /* unsigned is easy */
3849 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3850 l = aopGet (AOP (left), 0, FALSE, FALSE);
3852 emitcode ("div", "ab");
3853 aopPut (AOP (result), "b", 0);
3857 /* signed is a little bit more difficult */
3859 /* save the signs of the operands */
3860 l = aopGet (AOP (left), 0, FALSE, FALSE);
3863 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3864 emitcode ("push", "acc"); /* save it on the stack */
3866 /* now sign adjust for both left & right */
3867 l = aopGet (AOP (right), 0, FALSE, FALSE);
3870 lbl = newiTempLabel (NULL);
3871 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3872 emitcode ("cpl", "a");
3873 emitcode ("inc", "a");
3874 emitcode ("", "%05d$:", (lbl->key + 100));
3875 emitcode ("mov", "b,a");
3877 /* sign adjust left side */
3878 l = aopGet (AOP (left), 0, FALSE, FALSE);
3881 lbl = newiTempLabel (NULL);
3882 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3883 emitcode ("cpl", "a");
3884 emitcode ("inc", "a");
3885 emitcode ("", "%05d$:", (lbl->key + 100));
3887 /* now the multiplication */
3888 emitcode ("div", "ab");
3889 /* we are interested in the lower order
3891 lbl = newiTempLabel (NULL);
3892 emitcode ("pop", "acc");
3893 /* if there was an over flow we don't
3894 adjust the sign of the result */
3895 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3896 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3898 emitcode ("clr", "a");
3899 emitcode ("subb", "a,b");
3900 emitcode ("mov", "b,a");
3901 emitcode ("", "%05d$:", (lbl->key + 100));
3903 /* now we are done */
3904 aopPut (AOP (result), "b", 0);
3908 /*-----------------------------------------------------------------*/
3909 /* genMod - generates code for division */
3910 /*-----------------------------------------------------------------*/
3914 operand *left = IC_LEFT (ic);
3915 operand *right = IC_RIGHT (ic);
3916 operand *result = IC_RESULT (ic);
3918 D(emitcode ("; genMod",""));
3920 /* assign the amsops */
3921 aopOp (left, ic, FALSE);
3922 aopOp (right, ic, FALSE);
3923 aopOp (result, ic, TRUE);
3925 /* special cases first */
3927 if (AOP_TYPE (left) == AOP_CRY &&
3928 AOP_TYPE (right) == AOP_CRY)
3930 genModbits (left, right, result);
3934 /* if both are of size == 1 */
3935 if (AOP_SIZE (left) == 1 &&
3936 AOP_SIZE (right) == 1)
3938 genModOneByte (left, right, result);
3942 /* should have been converted to function call */
3946 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3947 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3948 freeAsmop (result, NULL, ic, TRUE);
3951 /*-----------------------------------------------------------------*/
3952 /* genIfxJump :- will create a jump depending on the ifx */
3953 /*-----------------------------------------------------------------*/
3955 genIfxJump (iCode * ic, char *jval)
3958 symbol *tlbl = newiTempLabel (NULL);
3961 D(emitcode ("; genIfxJump",""));
3963 /* if true label then we jump if condition
3967 jlbl = IC_TRUE (ic);
3968 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3969 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3973 /* false label is present */
3974 jlbl = IC_FALSE (ic);
3975 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3976 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3978 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3979 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3981 emitcode (inst, "%05d$", tlbl->key + 100);
3982 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3983 emitcode ("", "%05d$:", tlbl->key + 100);
3985 /* mark the icode as generated */
3989 /*-----------------------------------------------------------------*/
3990 /* genCmp :- greater or less than comparison */
3991 /*-----------------------------------------------------------------*/
3993 genCmp (operand * left, operand * right,
3994 operand * result, iCode * ifx, int sign, iCode *ic)
3996 int size, offset = 0;
3997 unsigned long lit = 0L;
3999 D(emitcode ("; genCmp",""));
4001 /* if left & right are bit variables */
4002 if (AOP_TYPE (left) == AOP_CRY &&
4003 AOP_TYPE (right) == AOP_CRY)
4005 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4006 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4010 /* subtract right from left if at the
4011 end the carry flag is set then we know that
4012 left is greater than right */
4013 size = max (AOP_SIZE (left), AOP_SIZE (right));
4015 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4016 if ((size == 1) && !sign &&
4017 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4019 symbol *lbl = newiTempLabel (NULL);
4020 emitcode ("cjne", "%s,%s,%05d$",
4021 aopGet (AOP (left), offset, FALSE, FALSE),
4022 aopGet (AOP (right), offset, FALSE, FALSE),
4024 emitcode ("", "%05d$:", lbl->key + 100);
4028 if (AOP_TYPE (right) == AOP_LIT)
4030 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4031 /* optimize if(x < 0) or if(x >= 0) */
4040 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4041 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4043 genIfxJump (ifx, "acc.7");
4047 emitcode ("rlc", "a");
4055 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4056 if (sign && size == 0)
4058 emitcode ("xrl", "a,#0x80");
4059 if (AOP_TYPE (right) == AOP_LIT)
4061 unsigned long lit = (unsigned long)
4062 floatFromVal (AOP (right)->aopu.aop_lit);
4063 emitcode ("subb", "a,#0x%02x",
4064 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4068 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4069 emitcode ("xrl", "b,#0x80");
4070 emitcode ("subb", "a,b");
4074 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4080 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4081 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4082 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4088 /* if the result is used in the next
4089 ifx conditional branch then generate
4090 code a little differently */
4092 genIfxJump (ifx, "c");
4095 /* leave the result in acc */
4099 /*-----------------------------------------------------------------*/
4100 /* genCmpGt :- greater than comparison */
4101 /*-----------------------------------------------------------------*/
4103 genCmpGt (iCode * ic, iCode * ifx)
4105 operand *left, *right, *result;
4106 sym_link *letype, *retype;
4109 D(emitcode ("; genCmpGt",""));
4111 left = IC_LEFT (ic);
4112 right = IC_RIGHT (ic);
4113 result = IC_RESULT (ic);
4115 letype = getSpec (operandType (left));
4116 retype = getSpec (operandType (right));
4117 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4118 /* assign the amsops */
4119 aopOp (left, ic, FALSE);
4120 aopOp (right, ic, FALSE);
4121 aopOp (result, ic, TRUE);
4123 genCmp (right, left, result, ifx, sign,ic);
4125 freeAsmop (result, NULL, ic, TRUE);
4128 /*-----------------------------------------------------------------*/
4129 /* genCmpLt - less than comparisons */
4130 /*-----------------------------------------------------------------*/
4132 genCmpLt (iCode * ic, iCode * ifx)
4134 operand *left, *right, *result;
4135 sym_link *letype, *retype;
4138 D(emitcode ("; genCmpLt",""));
4140 left = IC_LEFT (ic);
4141 right = IC_RIGHT (ic);
4142 result = IC_RESULT (ic);
4144 letype = getSpec (operandType (left));
4145 retype = getSpec (operandType (right));
4146 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4148 /* assign the amsops */
4149 aopOp (left, ic, FALSE);
4150 aopOp (right, ic, FALSE);
4151 aopOp (result, ic, TRUE);
4153 genCmp (left, right, result, ifx, sign,ic);
4155 freeAsmop (result, NULL, ic, TRUE);
4158 /*-----------------------------------------------------------------*/
4159 /* gencjneshort - compare and jump if not equal */
4160 /*-----------------------------------------------------------------*/
4162 gencjneshort (operand * left, operand * right, symbol * lbl)
4164 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4166 unsigned long lit = 0L;
4168 /* if the left side is a literal or
4169 if the right is in a pointer register and left
4171 if ((AOP_TYPE (left) == AOP_LIT) ||
4172 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4178 if (AOP_TYPE (right) == AOP_LIT)
4179 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4181 /* if the right side is a literal then anything goes */
4182 if (AOP_TYPE (right) == AOP_LIT &&
4183 AOP_TYPE (left) != AOP_DIR)
4187 emitcode ("cjne", "%s,%s,%05d$",
4188 aopGet (AOP (left), offset, FALSE, FALSE),
4189 aopGet (AOP (right), offset, FALSE, FALSE),
4195 /* if the right side is in a register or in direct space or
4196 if the left is a pointer register & right is not */
4197 else if (AOP_TYPE (right) == AOP_REG ||
4198 AOP_TYPE (right) == AOP_DIR ||
4199 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4200 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4204 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4205 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4206 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4207 emitcode ("jnz", "%05d$", lbl->key + 100);
4209 emitcode ("cjne", "a,%s,%05d$",
4210 aopGet (AOP (right), offset, FALSE, TRUE),
4217 /* right is a pointer reg need both a & b */
4220 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4221 if (strcmp (l, "b"))
4222 emitcode ("mov", "b,%s", l);
4223 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4224 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4230 /*-----------------------------------------------------------------*/
4231 /* gencjne - compare and jump if not equal */
4232 /*-----------------------------------------------------------------*/
4234 gencjne (operand * left, operand * right, symbol * lbl)
4236 symbol *tlbl = newiTempLabel (NULL);
4238 gencjneshort (left, right, lbl);
4240 emitcode ("mov", "a,%s", one);
4241 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4242 emitcode ("", "%05d$:", lbl->key + 100);
4243 emitcode ("clr", "a");
4244 emitcode ("", "%05d$:", tlbl->key + 100);
4247 /*-----------------------------------------------------------------*/
4248 /* genCmpEq - generates code for equal to */
4249 /*-----------------------------------------------------------------*/
4251 genCmpEq (iCode * ic, iCode * ifx)
4253 operand *left, *right, *result;
4255 D(emitcode ("; genCmpEq",""));
4257 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4258 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4259 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4261 /* if literal, literal on the right or
4262 if the right is in a pointer register and left
4264 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4265 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4267 operand *t = IC_RIGHT (ic);
4268 IC_RIGHT (ic) = IC_LEFT (ic);
4272 if (ifx && !AOP_SIZE (result))
4275 /* if they are both bit variables */
4276 if (AOP_TYPE (left) == AOP_CRY &&
4277 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4279 if (AOP_TYPE (right) == AOP_LIT)
4281 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4284 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4285 emitcode ("cpl", "c");
4289 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4293 emitcode ("clr", "c");
4295 /* AOP_TYPE(right) == AOP_CRY */
4299 symbol *lbl = newiTempLabel (NULL);
4300 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4301 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4302 emitcode ("cpl", "c");
4303 emitcode ("", "%05d$:", (lbl->key + 100));
4305 /* if true label then we jump if condition
4307 tlbl = newiTempLabel (NULL);
4310 emitcode ("jnc", "%05d$", tlbl->key + 100);
4311 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4315 emitcode ("jc", "%05d$", tlbl->key + 100);
4316 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4318 emitcode ("", "%05d$:", tlbl->key + 100);
4322 tlbl = newiTempLabel (NULL);
4323 gencjneshort (left, right, tlbl);
4326 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4327 emitcode ("", "%05d$:", tlbl->key + 100);
4331 symbol *lbl = newiTempLabel (NULL);
4332 emitcode ("sjmp", "%05d$", lbl->key + 100);
4333 emitcode ("", "%05d$:", tlbl->key + 100);
4334 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4335 emitcode ("", "%05d$:", lbl->key + 100);
4338 /* mark the icode as generated */
4343 /* if they are both bit variables */
4344 if (AOP_TYPE (left) == AOP_CRY &&
4345 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4347 if (AOP_TYPE (right) == AOP_LIT)
4349 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4352 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4353 emitcode ("cpl", "c");
4357 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4361 emitcode ("clr", "c");
4363 /* AOP_TYPE(right) == AOP_CRY */
4367 symbol *lbl = newiTempLabel (NULL);
4368 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4369 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4370 emitcode ("cpl", "c");
4371 emitcode ("", "%05d$:", (lbl->key + 100));
4374 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4381 genIfxJump (ifx, "c");
4384 /* if the result is used in an arithmetic operation
4385 then put the result in place */
4390 gencjne (left, right, newiTempLabel (NULL));
4391 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4393 aopPut (AOP (result), "a", 0);
4398 genIfxJump (ifx, "a");
4401 /* if the result is used in an arithmetic operation
4402 then put the result in place */
4403 if (AOP_TYPE (result) != AOP_CRY)
4405 /* leave the result in acc */
4409 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4410 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4411 freeAsmop (result, NULL, ic, TRUE);
4414 /*-----------------------------------------------------------------*/
4415 /* ifxForOp - returns the icode containing the ifx for operand */
4416 /*-----------------------------------------------------------------*/
4418 ifxForOp (operand * op, iCode * ic)
4420 /* if true symbol then needs to be assigned */
4421 if (IS_TRUE_SYMOP (op))
4424 /* if this has register type condition and
4425 the next instruction is ifx with the same operand
4426 and live to of the operand is upto the ifx only then */
4428 ic->next->op == IFX &&
4429 IC_COND (ic->next)->key == op->key &&
4430 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4436 /*-----------------------------------------------------------------*/
4437 /* hasInc - operand is incremented before any other use */
4438 /*-----------------------------------------------------------------*/
4440 hasInc (operand *op, iCode *ic,int osize)
4442 sym_link *type = operandType(op);
4443 sym_link *retype = getSpec (type);
4444 iCode *lic = ic->next;
4447 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4448 if (!IS_SYMOP(op)) return NULL;
4450 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4451 if (IS_AGGREGATE(type->next)) return NULL;
4452 if (osize != (isize = getSize(type->next))) return NULL;
4455 /* if operand of the form op = op + <sizeof *op> */
4456 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4457 isOperandEqual(IC_RESULT(lic),op) &&
4458 isOperandLiteral(IC_RIGHT(lic)) &&
4459 operandLitValue(IC_RIGHT(lic)) == isize) {
4462 /* if the operand used or deffed */
4463 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4466 /* if GOTO or IFX */
4467 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4473 /*-----------------------------------------------------------------*/
4474 /* genAndOp - for && operation */
4475 /*-----------------------------------------------------------------*/
4477 genAndOp (iCode * ic)
4479 operand *left, *right, *result;
4482 D(emitcode ("; genAndOp",""));
4484 /* note here that && operations that are in an
4485 if statement are taken away by backPatchLabels
4486 only those used in arthmetic operations remain */
4487 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4488 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4489 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4491 /* if both are bit variables */
4492 if (AOP_TYPE (left) == AOP_CRY &&
4493 AOP_TYPE (right) == AOP_CRY)
4495 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4496 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4501 tlbl = newiTempLabel (NULL);
4503 emitcode ("jz", "%05d$", tlbl->key + 100);
4505 emitcode ("", "%05d$:", tlbl->key + 100);
4509 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4510 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4511 freeAsmop (result, NULL, ic, TRUE);
4515 /*-----------------------------------------------------------------*/
4516 /* genOrOp - for || operation */
4517 /*-----------------------------------------------------------------*/
4519 genOrOp (iCode * ic)
4521 operand *left, *right, *result;
4524 D(emitcode ("; genOrOp",""));
4526 /* note here that || operations that are in an
4527 if statement are taken away by backPatchLabels
4528 only those used in arthmetic operations remain */
4529 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4530 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4531 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4533 /* if both are bit variables */
4534 if (AOP_TYPE (left) == AOP_CRY &&
4535 AOP_TYPE (right) == AOP_CRY)
4537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4538 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4543 tlbl = newiTempLabel (NULL);
4545 emitcode ("jnz", "%05d$", tlbl->key + 100);
4547 emitcode ("", "%05d$:", tlbl->key + 100);
4551 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4552 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4553 freeAsmop (result, NULL, ic, TRUE);
4556 /*-----------------------------------------------------------------*/
4557 /* isLiteralBit - test if lit == 2^n */
4558 /*-----------------------------------------------------------------*/
4560 isLiteralBit (unsigned long lit)
4562 unsigned long pw[32] =
4563 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4564 0x100L, 0x200L, 0x400L, 0x800L,
4565 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4566 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4567 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4568 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4569 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4572 for (idx = 0; idx < 32; idx++)
4578 /*-----------------------------------------------------------------*/
4579 /* continueIfTrue - */
4580 /*-----------------------------------------------------------------*/
4582 continueIfTrue (iCode * ic)
4585 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4589 /*-----------------------------------------------------------------*/
4591 /*-----------------------------------------------------------------*/
4593 jumpIfTrue (iCode * ic)
4596 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4600 /*-----------------------------------------------------------------*/
4601 /* jmpTrueOrFalse - */
4602 /*-----------------------------------------------------------------*/
4604 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4606 // ugly but optimized by peephole
4609 symbol *nlbl = newiTempLabel (NULL);
4610 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4611 emitcode ("", "%05d$:", tlbl->key + 100);
4612 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4613 emitcode ("", "%05d$:", nlbl->key + 100);
4617 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4618 emitcode ("", "%05d$:", tlbl->key + 100);
4623 /*-----------------------------------------------------------------*/
4624 /* genAnd - code for and */
4625 /*-----------------------------------------------------------------*/
4627 genAnd (iCode * ic, iCode * ifx)
4629 operand *left, *right, *result;
4630 int size, offset = 0;
4631 unsigned long lit = 0L;
4635 D(emitcode ("; genAnd",""));
4637 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4638 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4639 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4642 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4644 AOP_TYPE (left), AOP_TYPE (right));
4645 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4647 AOP_SIZE (left), AOP_SIZE (right));
4650 /* if left is a literal & right is not then exchange them */
4651 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4652 AOP_NEEDSACC (left))
4654 operand *tmp = right;
4659 /* if result = right then exchange them */
4660 if (sameRegs (AOP (result), AOP (right)))
4662 operand *tmp = right;
4667 /* if right is bit then exchange them */
4668 if (AOP_TYPE (right) == AOP_CRY &&
4669 AOP_TYPE (left) != AOP_CRY)
4671 operand *tmp = right;
4675 if (AOP_TYPE (right) == AOP_LIT)
4676 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4678 size = AOP_SIZE (result);
4681 // result = bit & yy;
4682 if (AOP_TYPE (left) == AOP_CRY)
4684 // c = bit & literal;
4685 if (AOP_TYPE (right) == AOP_LIT)
4689 if (size && sameRegs (AOP (result), AOP (left)))
4692 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4697 if (size && (AOP_TYPE (result) == AOP_CRY))
4699 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4702 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4707 emitcode ("clr", "c");
4712 if (AOP_TYPE (right) == AOP_CRY)
4715 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4716 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4721 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4723 emitcode ("rrc", "a");
4724 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4732 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4733 genIfxJump (ifx, "c");
4737 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4738 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4739 if ((AOP_TYPE (right) == AOP_LIT) &&
4740 (AOP_TYPE (result) == AOP_CRY) &&
4741 (AOP_TYPE (left) != AOP_CRY))
4743 int posbit = isLiteralBit (lit);
4748 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4751 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4757 sprintf (buffer, "acc.%d", posbit & 0x07);
4758 genIfxJump (ifx, buffer);
4765 symbol *tlbl = newiTempLabel (NULL);
4766 int sizel = AOP_SIZE (left);
4768 emitcode ("setb", "c");
4771 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4773 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4775 if ((posbit = isLiteralBit (bytelit)) != 0)
4776 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4779 if (bytelit != 0x0FFL)
4780 emitcode ("anl", "a,%s",
4781 aopGet (AOP (right), offset, FALSE, TRUE));
4782 emitcode ("jnz", "%05d$", tlbl->key + 100);
4787 // bit = left & literal
4790 emitcode ("clr", "c");
4791 emitcode ("", "%05d$:", tlbl->key + 100);
4793 // if(left & literal)
4797 jmpTrueOrFalse (ifx, tlbl);
4805 /* if left is same as result */
4806 if (sameRegs (AOP (result), AOP (left)))
4808 for (; size--; offset++)
4810 if (AOP_TYPE (right) == AOP_LIT)
4812 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4814 else if (bytelit == 0)
4815 aopPut (AOP (result), zero, offset);
4816 else if (IS_AOP_PREG (result))
4818 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4819 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4820 aopPut (AOP (result), "a", offset);
4823 emitcode ("anl", "%s,%s",
4824 aopGet (AOP (left), offset, FALSE, TRUE),
4825 aopGet (AOP (right), offset, FALSE, FALSE));
4829 if (AOP_TYPE (left) == AOP_ACC)
4830 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4833 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4834 if (IS_AOP_PREG (result))
4836 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4837 aopPut (AOP (result), "a", offset);
4841 emitcode ("anl", "%s,a",
4842 aopGet (AOP (left), offset, FALSE, TRUE));
4849 // left & result in different registers
4850 if (AOP_TYPE (result) == AOP_CRY)
4853 // if(size), result in bit
4854 // if(!size && ifx), conditional oper: if(left & right)
4855 symbol *tlbl = newiTempLabel (NULL);
4856 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4858 emitcode ("setb", "c");
4861 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4862 emitcode ("anl", "a,%s",
4863 aopGet (AOP (right), offset, FALSE, FALSE));
4865 if (AOP_TYPE(left)==AOP_ACC) {
4866 emitcode("mov", "b,a");
4867 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4868 emitcode("anl", "a,b");
4870 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4871 emitcode ("anl", "a,%s",
4872 aopGet (AOP (left), offset, FALSE, FALSE));
4875 emitcode ("jnz", "%05d$", tlbl->key + 100);
4881 emitcode ("", "%05d$:", tlbl->key + 100);
4885 jmpTrueOrFalse (ifx, tlbl);
4889 for (; (size--); offset++)
4892 // result = left & right
4893 if (AOP_TYPE (right) == AOP_LIT)
4895 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4897 aopPut (AOP (result),
4898 aopGet (AOP (left), offset, FALSE, FALSE),
4902 else if (bytelit == 0)
4904 aopPut (AOP (result), zero, offset);
4908 // faster than result <- left, anl result,right
4909 // and better if result is SFR
4910 if (AOP_TYPE (left) == AOP_ACC)
4911 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4914 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4915 emitcode ("anl", "a,%s",
4916 aopGet (AOP (left), offset, FALSE, FALSE));
4918 aopPut (AOP (result), "a", offset);
4924 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4926 freeAsmop (result, NULL, ic, TRUE);
4929 /*-----------------------------------------------------------------*/
4930 /* genOr - code for or */
4931 /*-----------------------------------------------------------------*/
4933 genOr (iCode * ic, iCode * ifx)
4935 operand *left, *right, *result;
4936 int size, offset = 0;
4937 unsigned long lit = 0L;
4939 D(emitcode ("; genOr",""));
4941 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4942 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4943 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4946 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4948 AOP_TYPE (left), AOP_TYPE (right));
4949 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4951 AOP_SIZE (left), AOP_SIZE (right));
4954 /* if left is a literal & right is not then exchange them */
4955 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4956 AOP_NEEDSACC (left))
4958 operand *tmp = right;
4963 /* if result = right then exchange them */
4964 if (sameRegs (AOP (result), AOP (right)))
4966 operand *tmp = right;
4971 /* if right is bit then exchange them */
4972 if (AOP_TYPE (right) == AOP_CRY &&
4973 AOP_TYPE (left) != AOP_CRY)
4975 operand *tmp = right;
4979 if (AOP_TYPE (right) == AOP_LIT)
4980 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4982 size = AOP_SIZE (result);
4986 if (AOP_TYPE (left) == AOP_CRY)
4988 if (AOP_TYPE (right) == AOP_LIT)
4990 // c = bit | literal;
4993 // lit != 0 => result = 1
4994 if (AOP_TYPE (result) == AOP_CRY)
4997 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4999 continueIfTrue (ifx);
5002 emitcode ("setb", "c");
5006 // lit == 0 => result = left
5007 if (size && sameRegs (AOP (result), AOP (left)))
5009 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5014 if (AOP_TYPE (right) == AOP_CRY)
5017 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5018 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5023 symbol *tlbl = newiTempLabel (NULL);
5024 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5025 emitcode ("setb", "c");
5026 emitcode ("jb", "%s,%05d$",
5027 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5029 emitcode ("jnz", "%05d$", tlbl->key + 100);
5030 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5032 jmpTrueOrFalse (ifx, tlbl);
5038 emitcode ("", "%05d$:", tlbl->key + 100);
5047 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5048 genIfxJump (ifx, "c");
5052 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5053 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5054 if ((AOP_TYPE (right) == AOP_LIT) &&
5055 (AOP_TYPE (result) == AOP_CRY) &&
5056 (AOP_TYPE (left) != AOP_CRY))
5062 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5064 continueIfTrue (ifx);
5069 // lit = 0, result = boolean(left)
5071 emitcode ("setb", "c");
5075 symbol *tlbl = newiTempLabel (NULL);
5076 emitcode ("jnz", "%05d$", tlbl->key + 100);
5078 emitcode ("", "%05d$:", tlbl->key + 100);
5082 genIfxJump (ifx, "a");
5090 /* if left is same as result */
5091 if (sameRegs (AOP (result), AOP (left)))
5093 for (; size--; offset++)
5095 if (AOP_TYPE (right) == AOP_LIT)
5097 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5099 else if (IS_AOP_PREG (left))
5101 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5102 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5103 aopPut (AOP (result), "a", offset);
5106 emitcode ("orl", "%s,%s",
5107 aopGet (AOP (left), offset, FALSE, TRUE),
5108 aopGet (AOP (right), offset, FALSE, FALSE));
5112 if (AOP_TYPE (left) == AOP_ACC)
5113 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5116 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5117 if (IS_AOP_PREG (left))
5119 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5120 aopPut (AOP (result), "a", offset);
5123 emitcode ("orl", "%s,a",
5124 aopGet (AOP (left), offset, FALSE, TRUE));
5131 // left & result in different registers
5132 if (AOP_TYPE (result) == AOP_CRY)
5135 // if(size), result in bit
5136 // if(!size && ifx), conditional oper: if(left | right)
5137 symbol *tlbl = newiTempLabel (NULL);
5138 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5140 emitcode ("setb", "c");
5143 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5144 emitcode ("orl", "a,%s",
5145 aopGet (AOP (right), offset, FALSE, FALSE));
5147 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5148 emitcode ("orl", "a,%s",
5149 aopGet (AOP (left), offset, FALSE, FALSE));
5151 emitcode ("jnz", "%05d$", tlbl->key + 100);
5157 emitcode ("", "%05d$:", tlbl->key + 100);
5161 jmpTrueOrFalse (ifx, tlbl);
5164 for (; (size--); offset++)
5167 // result = left & right
5168 if (AOP_TYPE (right) == AOP_LIT)
5170 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5172 aopPut (AOP (result),
5173 aopGet (AOP (left), offset, FALSE, FALSE),
5178 // faster than result <- left, anl result,right
5179 // and better if result is SFR
5180 if (AOP_TYPE (left) == AOP_ACC)
5181 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5184 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5185 emitcode ("orl", "a,%s",
5186 aopGet (AOP (left), offset, FALSE, FALSE));
5188 aopPut (AOP (result), "a", offset);
5193 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5194 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5195 freeAsmop (result, NULL, ic, TRUE);
5198 /*-----------------------------------------------------------------*/
5199 /* genXor - code for xclusive or */
5200 /*-----------------------------------------------------------------*/
5202 genXor (iCode * ic, iCode * ifx)
5204 operand *left, *right, *result;
5205 int size, offset = 0;
5206 unsigned long lit = 0L;
5208 D(emitcode ("; genXor",""));
5210 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5211 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5212 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5215 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5217 AOP_TYPE (left), AOP_TYPE (right));
5218 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5220 AOP_SIZE (left), AOP_SIZE (right));
5223 /* if left is a literal & right is not ||
5224 if left needs acc & right does not */
5225 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5226 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5228 operand *tmp = right;
5233 /* if result = right then exchange them */
5234 if (sameRegs (AOP (result), AOP (right)))
5236 operand *tmp = right;
5241 /* if right is bit then exchange them */
5242 if (AOP_TYPE (right) == AOP_CRY &&
5243 AOP_TYPE (left) != AOP_CRY)
5245 operand *tmp = right;
5249 if (AOP_TYPE (right) == AOP_LIT)
5250 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5252 size = AOP_SIZE (result);
5256 if (AOP_TYPE (left) == AOP_CRY)
5258 if (AOP_TYPE (right) == AOP_LIT)
5260 // c = bit & literal;
5263 // lit>>1 != 0 => result = 1
5264 if (AOP_TYPE (result) == AOP_CRY)
5267 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5269 continueIfTrue (ifx);
5272 emitcode ("setb", "c");
5279 // lit == 0, result = left
5280 if (size && sameRegs (AOP (result), AOP (left)))
5282 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5286 // lit == 1, result = not(left)
5287 if (size && sameRegs (AOP (result), AOP (left)))
5289 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5295 emitcode ("cpl", "c");
5304 symbol *tlbl = newiTempLabel (NULL);
5305 if (AOP_TYPE (right) == AOP_CRY)
5308 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5312 int sizer = AOP_SIZE (right);
5314 // if val>>1 != 0, result = 1
5315 emitcode ("setb", "c");
5318 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5320 // test the msb of the lsb
5321 emitcode ("anl", "a,#0xfe");
5322 emitcode ("jnz", "%05d$", tlbl->key + 100);
5326 emitcode ("rrc", "a");
5328 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5329 emitcode ("cpl", "c");
5330 emitcode ("", "%05d$:", (tlbl->key + 100));
5337 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5338 genIfxJump (ifx, "c");
5342 if (sameRegs (AOP (result), AOP (left)))
5344 /* if left is same as result */
5345 for (; size--; offset++)
5347 if (AOP_TYPE (right) == AOP_LIT)
5349 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5351 else if (IS_AOP_PREG (left))
5353 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5354 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5355 aopPut (AOP (result), "a", offset);
5358 emitcode ("xrl", "%s,%s",
5359 aopGet (AOP (left), offset, FALSE, TRUE),
5360 aopGet (AOP (right), offset, FALSE, FALSE));
5364 if (AOP_TYPE (left) == AOP_ACC)
5365 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5368 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5369 if (IS_AOP_PREG (left))
5371 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5372 aopPut (AOP (result), "a", offset);
5375 emitcode ("xrl", "%s,a",
5376 aopGet (AOP (left), offset, FALSE, TRUE));
5383 // left & result in different registers
5384 if (AOP_TYPE (result) == AOP_CRY)
5387 // if(size), result in bit
5388 // if(!size && ifx), conditional oper: if(left ^ right)
5389 symbol *tlbl = newiTempLabel (NULL);
5390 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5392 emitcode ("setb", "c");
5395 if ((AOP_TYPE (right) == AOP_LIT) &&
5396 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5398 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5402 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5403 emitcode ("xrl", "a,%s",
5404 aopGet (AOP (right), offset, FALSE, FALSE));
5406 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5407 emitcode ("xrl", "a,%s",
5408 aopGet (AOP (left), offset, FALSE, FALSE));
5411 emitcode ("jnz", "%05d$", tlbl->key + 100);
5417 emitcode ("", "%05d$:", tlbl->key + 100);
5421 jmpTrueOrFalse (ifx, tlbl);
5424 for (; (size--); offset++)
5427 // result = left & right
5428 if (AOP_TYPE (right) == AOP_LIT)
5430 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5432 aopPut (AOP (result),
5433 aopGet (AOP (left), offset, FALSE, FALSE),
5438 // faster than result <- left, anl result,right
5439 // and better if result is SFR
5440 if (AOP_TYPE (left) == AOP_ACC)
5441 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5444 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5445 emitcode ("xrl", "a,%s",
5446 aopGet (AOP (left), offset, FALSE, TRUE));
5448 aopPut (AOP (result), "a", offset);
5453 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5454 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5455 freeAsmop (result, NULL, ic, TRUE);
5458 /*-----------------------------------------------------------------*/
5459 /* genInline - write the inline code out */
5460 /*-----------------------------------------------------------------*/
5462 genInline (iCode * ic)
5464 char *buffer, *bp, *bp1;
5466 D(emitcode ("; genInline",""));
5468 _G.inLine += (!options.asmpeep);
5470 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5471 strcpy (buffer, IC_INLINE (ic));
5473 /* emit each line as a code */
5498 /* emitcode("",buffer); */
5499 _G.inLine -= (!options.asmpeep);
5502 /*-----------------------------------------------------------------*/
5503 /* genRRC - rotate right with carry */
5504 /*-----------------------------------------------------------------*/
5508 operand *left, *result;
5509 int size, offset = 0;
5512 D(emitcode ("; genRRC",""));
5514 /* rotate right with carry */
5515 left = IC_LEFT (ic);
5516 result = IC_RESULT (ic);
5517 aopOp (left, ic, FALSE);
5518 aopOp (result, ic, FALSE);
5520 /* move it to the result */
5521 size = AOP_SIZE (result);
5523 if (size == 1) { /* special case for 1 byte */
5524 l = aopGet (AOP (left), offset, FALSE, FALSE);
5526 emitcode ("rr", "a");
5532 l = aopGet (AOP (left), offset, FALSE, FALSE);
5534 emitcode ("rrc", "a");
5535 if (AOP_SIZE (result) > 1)
5536 aopPut (AOP (result), "a", offset--);
5538 /* now we need to put the carry into the
5539 highest order byte of the result */
5540 if (AOP_SIZE (result) > 1)
5542 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5545 emitcode ("mov", "acc.7,c");
5547 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5548 freeAsmop (left, NULL, ic, TRUE);
5549 freeAsmop (result, NULL, ic, TRUE);
5552 /*-----------------------------------------------------------------*/
5553 /* genRLC - generate code for rotate left with carry */
5554 /*-----------------------------------------------------------------*/
5558 operand *left, *result;
5559 int size, offset = 0;
5562 D(emitcode ("; genRLC",""));
5564 /* rotate right with carry */
5565 left = IC_LEFT (ic);
5566 result = IC_RESULT (ic);
5567 aopOp (left, ic, FALSE);
5568 aopOp (result, ic, FALSE);
5570 /* move it to the result */
5571 size = AOP_SIZE (result);
5575 l = aopGet (AOP (left), offset, FALSE, FALSE);
5577 if (size == 0) { /* special case for 1 byte */
5581 emitcode ("add", "a,acc");
5582 if (AOP_SIZE (result) > 1)
5583 aopPut (AOP (result), "a", offset++);
5586 l = aopGet (AOP (left), offset, FALSE, FALSE);
5588 emitcode ("rlc", "a");
5589 if (AOP_SIZE (result) > 1)
5590 aopPut (AOP (result), "a", offset++);
5593 /* now we need to put the carry into the
5594 highest order byte of the result */
5595 if (AOP_SIZE (result) > 1)
5597 l = aopGet (AOP (result), 0, FALSE, FALSE);
5600 emitcode ("mov", "acc.0,c");
5602 aopPut (AOP (result), "a", 0);
5603 freeAsmop (left, NULL, ic, TRUE);
5604 freeAsmop (result, NULL, ic, TRUE);
5607 /*-----------------------------------------------------------------*/
5608 /* genGetHbit - generates code get highest order bit */
5609 /*-----------------------------------------------------------------*/
5611 genGetHbit (iCode * ic)
5613 operand *left, *result;
5615 D(emitcode ("; genGetHbit",""));
5617 left = IC_LEFT (ic);
5618 result = IC_RESULT (ic);
5619 aopOp (left, ic, FALSE);
5620 aopOp (result, ic, FALSE);
5622 /* get the highest order byte into a */
5623 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5624 if (AOP_TYPE (result) == AOP_CRY)
5626 emitcode ("rlc", "a");
5631 emitcode ("rl", "a");
5632 emitcode ("anl", "a,#0x01");
5637 freeAsmop (left, NULL, ic, TRUE);
5638 freeAsmop (result, NULL, ic, TRUE);
5641 /*-----------------------------------------------------------------*/
5642 /* AccRol - rotate left accumulator by known count */
5643 /*-----------------------------------------------------------------*/
5645 AccRol (int shCount)
5647 shCount &= 0x0007; // shCount : 0..7
5654 emitcode ("rl", "a");
5657 emitcode ("rl", "a");
5658 emitcode ("rl", "a");
5661 emitcode ("swap", "a");
5662 emitcode ("rr", "a");
5665 emitcode ("swap", "a");
5668 emitcode ("swap", "a");
5669 emitcode ("rl", "a");
5672 emitcode ("rr", "a");
5673 emitcode ("rr", "a");
5676 emitcode ("rr", "a");
5681 /*-----------------------------------------------------------------*/
5682 /* AccLsh - left shift accumulator by known count */
5683 /*-----------------------------------------------------------------*/
5685 AccLsh (int shCount)
5690 emitcode ("add", "a,acc");
5691 else if (shCount == 2)
5693 emitcode ("add", "a,acc");
5694 emitcode ("add", "a,acc");
5698 /* rotate left accumulator */
5700 /* and kill the lower order bits */
5701 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5706 /*-----------------------------------------------------------------*/
5707 /* AccRsh - right shift accumulator by known count */
5708 /*-----------------------------------------------------------------*/
5710 AccRsh (int shCount)
5717 emitcode ("rrc", "a");
5721 /* rotate right accumulator */
5722 AccRol (8 - shCount);
5723 /* and kill the higher order bits */
5724 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5729 /*-----------------------------------------------------------------*/
5730 /* AccSRsh - signed right shift accumulator by known count */
5731 /*-----------------------------------------------------------------*/
5733 AccSRsh (int shCount)
5740 emitcode ("mov", "c,acc.7");
5741 emitcode ("rrc", "a");
5743 else if (shCount == 2)
5745 emitcode ("mov", "c,acc.7");
5746 emitcode ("rrc", "a");
5747 emitcode ("mov", "c,acc.7");
5748 emitcode ("rrc", "a");
5752 tlbl = newiTempLabel (NULL);
5753 /* rotate right accumulator */
5754 AccRol (8 - shCount);
5755 /* and kill the higher order bits */
5756 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5757 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5758 emitcode ("orl", "a,#0x%02x",
5759 (unsigned char) ~SRMask[shCount]);
5760 emitcode ("", "%05d$:", tlbl->key + 100);
5765 /*-----------------------------------------------------------------*/
5766 /* shiftR1Left2Result - shift right one byte from left to result */
5767 /*-----------------------------------------------------------------*/
5769 shiftR1Left2Result (operand * left, int offl,
5770 operand * result, int offr,
5771 int shCount, int sign)
5773 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5774 /* shift right accumulator */
5779 aopPut (AOP (result), "a", offr);
5782 /*-----------------------------------------------------------------*/
5783 /* shiftL1Left2Result - shift left one byte from left to result */
5784 /*-----------------------------------------------------------------*/
5786 shiftL1Left2Result (operand * left, int offl,
5787 operand * result, int offr, int shCount)
5790 l = aopGet (AOP (left), offl, FALSE, FALSE);
5792 /* shift left accumulator */
5794 aopPut (AOP (result), "a", offr);
5797 /*-----------------------------------------------------------------*/
5798 /* movLeft2Result - move byte from left to result */
5799 /*-----------------------------------------------------------------*/
5801 movLeft2Result (operand * left, int offl,
5802 operand * result, int offr, int sign)
5805 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5807 l = aopGet (AOP (left), offl, FALSE, FALSE);
5809 if (*l == '@' && (IS_AOP_PREG (result)))
5811 emitcode ("mov", "a,%s", l);
5812 aopPut (AOP (result), "a", offr);
5817 aopPut (AOP (result), l, offr);
5820 /* MSB sign in acc.7 ! */
5821 if (getDataSize (left) == offl + 1)
5823 emitcode ("mov", "a,%s", l);
5824 aopPut (AOP (result), "a", offr);
5831 /*-----------------------------------------------------------------*/
5832 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5833 /*-----------------------------------------------------------------*/
5837 emitcode ("rrc", "a");
5838 emitcode ("xch", "a,%s", x);
5839 emitcode ("rrc", "a");
5840 emitcode ("xch", "a,%s", x);
5843 /*-----------------------------------------------------------------*/
5844 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5845 /*-----------------------------------------------------------------*/
5849 emitcode ("xch", "a,%s", x);
5850 emitcode ("rlc", "a");
5851 emitcode ("xch", "a,%s", x);
5852 emitcode ("rlc", "a");
5855 /*-----------------------------------------------------------------*/
5856 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5857 /*-----------------------------------------------------------------*/
5861 emitcode ("xch", "a,%s", x);
5862 emitcode ("add", "a,acc");
5863 emitcode ("xch", "a,%s", x);
5864 emitcode ("rlc", "a");
5867 /*-----------------------------------------------------------------*/
5868 /* AccAXLsh - left shift a:x by known count (0..7) */
5869 /*-----------------------------------------------------------------*/
5871 AccAXLsh (char *x, int shCount)
5886 case 5: // AAAAABBB:CCCCCDDD
5888 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5890 emitcode ("anl", "a,#0x%02x",
5891 SLMask[shCount]); // BBB00000:CCCCCDDD
5893 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5895 AccRol (shCount); // DDDCCCCC:BBB00000
5897 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5899 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5901 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5903 emitcode ("anl", "a,#0x%02x",
5904 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5906 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5908 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5911 case 6: // AAAAAABB:CCCCCCDD
5912 emitcode ("anl", "a,#0x%02x",
5913 SRMask[shCount]); // 000000BB:CCCCCCDD
5914 emitcode ("mov", "c,acc.0"); // c = B
5915 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5917 AccAXRrl1 (x); // BCCCCCCD:D000000B
5918 AccAXRrl1 (x); // BBCCCCCC:DD000000
5920 emitcode("rrc","a");
5921 emitcode("xch","a,%s", x);
5922 emitcode("rrc","a");
5923 emitcode("mov","c,acc.0"); //<< get correct bit
5924 emitcode("xch","a,%s", x);
5926 emitcode("rrc","a");
5927 emitcode("xch","a,%s", x);
5928 emitcode("rrc","a");
5929 emitcode("xch","a,%s", x);
5932 case 7: // a:x <<= 7
5934 emitcode ("anl", "a,#0x%02x",
5935 SRMask[shCount]); // 0000000B:CCCCCCCD
5937 emitcode ("mov", "c,acc.0"); // c = B
5939 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5941 AccAXRrl1 (x); // BCCCCCCC:D0000000
5949 /*-----------------------------------------------------------------*/
5950 /* AccAXRsh - right shift a:x known count (0..7) */
5951 /*-----------------------------------------------------------------*/
5953 AccAXRsh (char *x, int shCount)
5961 AccAXRrl1 (x); // 0->a:x
5966 AccAXRrl1 (x); // 0->a:x
5969 AccAXRrl1 (x); // 0->a:x
5974 case 5: // AAAAABBB:CCCCCDDD = a:x
5976 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5978 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5980 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5982 emitcode ("anl", "a,#0x%02x",
5983 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5985 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5987 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5989 emitcode ("anl", "a,#0x%02x",
5990 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5992 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5994 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5996 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5999 case 6: // AABBBBBB:CCDDDDDD
6001 emitcode ("mov", "c,acc.7");
6002 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6004 emitcode ("mov", "c,acc.7");
6005 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6007 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6009 emitcode ("anl", "a,#0x%02x",
6010 SRMask[shCount]); // 000000AA:BBBBBBCC
6013 case 7: // ABBBBBBB:CDDDDDDD
6015 emitcode ("mov", "c,acc.7"); // c = A
6017 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6019 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6021 emitcode ("anl", "a,#0x%02x",
6022 SRMask[shCount]); // 0000000A:BBBBBBBC
6030 /*-----------------------------------------------------------------*/
6031 /* AccAXRshS - right shift signed a:x known count (0..7) */
6032 /*-----------------------------------------------------------------*/
6034 AccAXRshS (char *x, int shCount)
6042 emitcode ("mov", "c,acc.7");
6043 AccAXRrl1 (x); // s->a:x
6047 emitcode ("mov", "c,acc.7");
6048 AccAXRrl1 (x); // s->a:x
6050 emitcode ("mov", "c,acc.7");
6051 AccAXRrl1 (x); // s->a:x
6056 case 5: // AAAAABBB:CCCCCDDD = a:x
6058 tlbl = newiTempLabel (NULL);
6059 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6061 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6063 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6065 emitcode ("anl", "a,#0x%02x",
6066 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6068 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6070 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6072 emitcode ("anl", "a,#0x%02x",
6073 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6075 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6077 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6079 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6081 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6082 emitcode ("orl", "a,#0x%02x",
6083 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6085 emitcode ("", "%05d$:", tlbl->key + 100);
6086 break; // SSSSAAAA:BBBCCCCC
6088 case 6: // AABBBBBB:CCDDDDDD
6090 tlbl = newiTempLabel (NULL);
6091 emitcode ("mov", "c,acc.7");
6092 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6094 emitcode ("mov", "c,acc.7");
6095 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6097 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6099 emitcode ("anl", "a,#0x%02x",
6100 SRMask[shCount]); // 000000AA:BBBBBBCC
6102 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6103 emitcode ("orl", "a,#0x%02x",
6104 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6106 emitcode ("", "%05d$:", tlbl->key + 100);
6108 case 7: // ABBBBBBB:CDDDDDDD
6110 tlbl = newiTempLabel (NULL);
6111 emitcode ("mov", "c,acc.7"); // c = A
6113 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6115 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6117 emitcode ("anl", "a,#0x%02x",
6118 SRMask[shCount]); // 0000000A:BBBBBBBC
6120 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6121 emitcode ("orl", "a,#0x%02x",
6122 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6124 emitcode ("", "%05d$:", tlbl->key + 100);
6131 /*-----------------------------------------------------------------*/
6132 /* shiftL2Left2Result - shift left two bytes from left to result */
6133 /*-----------------------------------------------------------------*/
6135 shiftL2Left2Result (operand * left, int offl,
6136 operand * result, int offr, int shCount)
6138 if (sameRegs (AOP (result), AOP (left)) &&
6139 ((offl + MSB16) == offr))
6141 /* don't crash result[offr] */
6142 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6143 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6147 movLeft2Result (left, offl, result, offr, 0);
6148 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6150 /* ax << shCount (x = lsb(result)) */
6151 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6152 aopPut (AOP (result), "a", offr + MSB16);
6156 /*-----------------------------------------------------------------*/
6157 /* shiftR2Left2Result - shift right two bytes from left to result */
6158 /*-----------------------------------------------------------------*/
6160 shiftR2Left2Result (operand * left, int offl,
6161 operand * result, int offr,
6162 int shCount, int sign)
6164 if (sameRegs (AOP (result), AOP (left)) &&
6165 ((offl + MSB16) == offr))
6167 /* don't crash result[offr] */
6168 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6169 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6173 movLeft2Result (left, offl, result, offr, 0);
6174 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6176 /* a:x >> shCount (x = lsb(result)) */
6178 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6180 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6181 if (getDataSize (result) > 1)
6182 aopPut (AOP (result), "a", offr + MSB16);
6185 /*-----------------------------------------------------------------*/
6186 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6187 /*-----------------------------------------------------------------*/
6189 shiftLLeftOrResult (operand * left, int offl,
6190 operand * result, int offr, int shCount)
6192 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6193 /* shift left accumulator */
6195 /* or with result */
6196 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6197 /* back to result */
6198 aopPut (AOP (result), "a", offr);
6201 /*-----------------------------------------------------------------*/
6202 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6203 /*-----------------------------------------------------------------*/
6205 shiftRLeftOrResult (operand * left, int offl,
6206 operand * result, int offr, int shCount)
6208 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6209 /* shift right accumulator */
6211 /* or with result */
6212 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6213 /* back to result */
6214 aopPut (AOP (result), "a", offr);
6217 /*-----------------------------------------------------------------*/
6218 /* genlshOne - left shift a one byte quantity by known count */
6219 /*-----------------------------------------------------------------*/
6221 genlshOne (operand * result, operand * left, int shCount)
6223 D(emitcode ("; genlshOne",""));
6225 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6228 /*-----------------------------------------------------------------*/
6229 /* genlshTwo - left shift two bytes by known amount != 0 */
6230 /*-----------------------------------------------------------------*/
6232 genlshTwo (operand * result, operand * left, int shCount)
6236 D(emitcode ("; genlshTwo",""));
6238 size = getDataSize (result);
6240 /* if shCount >= 8 */
6248 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6250 movLeft2Result (left, LSB, result, MSB16, 0);
6252 aopPut (AOP (result), zero, LSB);
6255 /* 1 <= shCount <= 7 */
6259 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6261 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6265 /*-----------------------------------------------------------------*/
6266 /* shiftLLong - shift left one long from left to result */
6267 /* offl = LSB or MSB16 */
6268 /*-----------------------------------------------------------------*/
6270 shiftLLong (operand * left, operand * result, int offr)
6273 int size = AOP_SIZE (result);
6275 if (size >= LSB + offr)
6277 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6279 emitcode ("add", "a,acc");
6280 if (sameRegs (AOP (left), AOP (result)) &&
6281 size >= MSB16 + offr && offr != LSB)
6282 emitcode ("xch", "a,%s",
6283 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6285 aopPut (AOP (result), "a", LSB + offr);
6288 if (size >= MSB16 + offr)
6290 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6292 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6295 emitcode ("rlc", "a");
6296 if (sameRegs (AOP (left), AOP (result)) &&
6297 size >= MSB24 + offr && offr != LSB)
6298 emitcode ("xch", "a,%s",
6299 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6301 aopPut (AOP (result), "a", MSB16 + offr);
6304 if (size >= MSB24 + offr)
6306 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6308 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6311 emitcode ("rlc", "a");
6312 if (sameRegs (AOP (left), AOP (result)) &&
6313 size >= MSB32 + offr && offr != LSB)
6314 emitcode ("xch", "a,%s",
6315 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6317 aopPut (AOP (result), "a", MSB24 + offr);
6320 if (size > MSB32 + offr)
6322 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6324 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6327 emitcode ("rlc", "a");
6328 aopPut (AOP (result), "a", MSB32 + offr);
6331 aopPut (AOP (result), zero, LSB);
6334 /*-----------------------------------------------------------------*/
6335 /* genlshFour - shift four byte by a known amount != 0 */
6336 /*-----------------------------------------------------------------*/
6338 genlshFour (operand * result, operand * left, int shCount)
6342 D(emitcode ("; genlshFour",""));
6344 size = AOP_SIZE (result);
6346 /* if shifting more that 3 bytes */
6351 /* lowest order of left goes to the highest
6352 order of the destination */
6353 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6355 movLeft2Result (left, LSB, result, MSB32, 0);
6356 aopPut (AOP (result), zero, LSB);
6357 aopPut (AOP (result), zero, MSB16);
6358 aopPut (AOP (result), zero, MSB24);
6362 /* more than two bytes */
6363 else if (shCount >= 16)
6365 /* lower order two bytes goes to higher order two bytes */
6367 /* if some more remaining */
6369 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6372 movLeft2Result (left, MSB16, result, MSB32, 0);
6373 movLeft2Result (left, LSB, result, MSB24, 0);
6375 aopPut (AOP (result), zero, MSB16);
6376 aopPut (AOP (result), zero, LSB);
6380 /* if more than 1 byte */
6381 else if (shCount >= 8)
6383 /* lower order three bytes goes to higher order three bytes */
6388 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6390 movLeft2Result (left, LSB, result, MSB16, 0);
6396 movLeft2Result (left, MSB24, result, MSB32, 0);
6397 movLeft2Result (left, MSB16, result, MSB24, 0);
6398 movLeft2Result (left, LSB, result, MSB16, 0);
6399 aopPut (AOP (result), zero, LSB);
6401 else if (shCount == 1)
6402 shiftLLong (left, result, MSB16);
6405 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6406 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6407 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6408 aopPut (AOP (result), zero, LSB);
6413 /* 1 <= shCount <= 7 */
6414 else if (shCount <= 2)
6416 shiftLLong (left, result, LSB);
6418 shiftLLong (result, result, LSB);
6420 /* 3 <= shCount <= 7, optimize */
6423 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6424 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6425 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6429 /*-----------------------------------------------------------------*/
6430 /* genLeftShiftLiteral - left shifting by known count */
6431 /*-----------------------------------------------------------------*/
6433 genLeftShiftLiteral (operand * left,
6438 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6441 D(emitcode ("; genLeftShiftLiteral",""));
6443 freeAsmop (right, NULL, ic, TRUE);
6445 aopOp (left, ic, FALSE);
6446 aopOp (result, ic, FALSE);
6448 size = getSize (operandType (result));
6451 emitcode ("; shift left ", "result %d, left %d", size,
6455 /* I suppose that the left size >= result size */
6460 movLeft2Result (left, size, result, size, 0);
6464 else if (shCount >= (size * 8))
6466 aopPut (AOP (result), zero, size);
6472 genlshOne (result, left, shCount);
6476 genlshTwo (result, left, shCount);
6480 genlshFour (result, left, shCount);
6483 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6484 "*** ack! mystery literal shift!\n");
6488 freeAsmop (left, NULL, ic, TRUE);
6489 freeAsmop (result, NULL, ic, TRUE);
6492 /*-----------------------------------------------------------------*/
6493 /* genLeftShift - generates code for left shifting */
6494 /*-----------------------------------------------------------------*/
6496 genLeftShift (iCode * ic)
6498 operand *left, *right, *result;
6501 symbol *tlbl, *tlbl1;
6503 D(emitcode ("; genLeftShift",""));
6505 right = IC_RIGHT (ic);
6506 left = IC_LEFT (ic);
6507 result = IC_RESULT (ic);
6509 aopOp (right, ic, FALSE);
6511 /* if the shift count is known then do it
6512 as efficiently as possible */
6513 if (AOP_TYPE (right) == AOP_LIT)
6515 genLeftShiftLiteral (left, right, result, ic);
6519 /* shift count is unknown then we have to form
6520 a loop get the loop count in B : Note: we take
6521 only the lower order byte since shifting
6522 more that 32 bits make no sense anyway, ( the
6523 largest size of an object can be only 32 bits ) */
6525 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6526 emitcode ("inc", "b");
6527 freeAsmop (right, NULL, ic, TRUE);
6528 aopOp (left, ic, FALSE);
6529 aopOp (result, ic, FALSE);
6531 /* now move the left to the result if they are not the
6533 if (!sameRegs (AOP (left), AOP (result)) &&
6534 AOP_SIZE (result) > 1)
6537 size = AOP_SIZE (result);
6541 l = aopGet (AOP (left), offset, FALSE, TRUE);
6542 if (*l == '@' && (IS_AOP_PREG (result)))
6545 emitcode ("mov", "a,%s", l);
6546 aopPut (AOP (result), "a", offset);
6549 aopPut (AOP (result), l, offset);
6554 tlbl = newiTempLabel (NULL);
6555 size = AOP_SIZE (result);
6557 tlbl1 = newiTempLabel (NULL);
6559 /* if it is only one byte then */
6562 symbol *tlbl1 = newiTempLabel (NULL);
6564 l = aopGet (AOP (left), 0, FALSE, FALSE);
6566 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6567 emitcode ("", "%05d$:", tlbl->key + 100);
6568 emitcode ("add", "a,acc");
6569 emitcode ("", "%05d$:", tlbl1->key + 100);
6570 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6571 aopPut (AOP (result), "a", 0);
6575 reAdjustPreg (AOP (result));
6577 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6578 emitcode ("", "%05d$:", tlbl->key + 100);
6579 l = aopGet (AOP (result), offset, FALSE, FALSE);
6581 emitcode ("add", "a,acc");
6582 aopPut (AOP (result), "a", offset++);
6585 l = aopGet (AOP (result), offset, FALSE, FALSE);
6587 emitcode ("rlc", "a");
6588 aopPut (AOP (result), "a", offset++);
6590 reAdjustPreg (AOP (result));
6592 emitcode ("", "%05d$:", tlbl1->key + 100);
6593 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6595 freeAsmop (left, NULL, ic, TRUE);
6596 freeAsmop (result, NULL, ic, TRUE);
6599 /*-----------------------------------------------------------------*/
6600 /* genrshOne - right shift a one byte quantity by known count */
6601 /*-----------------------------------------------------------------*/
6603 genrshOne (operand * result, operand * left,
6604 int shCount, int sign)
6606 D(emitcode ("; genrshOne",""));
6608 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6611 /*-----------------------------------------------------------------*/
6612 /* genrshTwo - right shift two bytes by known amount != 0 */
6613 /*-----------------------------------------------------------------*/
6615 genrshTwo (operand * result, operand * left,
6616 int shCount, int sign)
6618 D(emitcode ("; genrshTwo",""));
6620 /* if shCount >= 8 */
6625 shiftR1Left2Result (left, MSB16, result, LSB,
6628 movLeft2Result (left, MSB16, result, LSB, sign);
6629 addSign (result, MSB16, sign);
6632 /* 1 <= shCount <= 7 */
6634 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6637 /*-----------------------------------------------------------------*/
6638 /* shiftRLong - shift right one long from left to result */
6639 /* offl = LSB or MSB16 */
6640 /*-----------------------------------------------------------------*/
6642 shiftRLong (operand * left, int offl,
6643 operand * result, int sign)
6645 int isSameRegs=sameRegs(AOP(left),AOP(result));
6647 if (isSameRegs && offl>1) {
6648 // we are in big trouble, but this shouldn't happen
6649 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6652 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6657 emitcode ("rlc", "a");
6658 emitcode ("subb", "a,acc");
6660 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6662 aopPut (AOP (result), "a", MSB32);
6663 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6666 aopPut (AOP(result), zero, MSB32);
6671 emitcode ("clr", "c");
6673 emitcode ("mov", "c,acc.7");
6676 emitcode ("rrc", "a");
6678 if (isSameRegs && offl==MSB16) {
6679 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6681 aopPut (AOP (result), "a", MSB32-offl);
6682 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6685 emitcode ("rrc", "a");
6686 if (isSameRegs && offl==1) {
6687 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6689 aopPut (AOP (result), "a", MSB24-offl);
6690 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6692 emitcode ("rrc", "a");
6693 aopPut (AOP (result), "a", MSB16 - offl);
6697 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6698 emitcode ("rrc", "a");
6699 aopPut (AOP (result), "a", LSB);
6703 /*-----------------------------------------------------------------*/
6704 /* genrshFour - shift four byte by a known amount != 0 */
6705 /*-----------------------------------------------------------------*/
6707 genrshFour (operand * result, operand * left,
6708 int shCount, int sign)
6710 D(emitcode ("; genrshFour",""));
6712 /* if shifting more that 3 bytes */
6717 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6719 movLeft2Result (left, MSB32, result, LSB, sign);
6720 addSign (result, MSB16, sign);
6722 else if (shCount >= 16)
6726 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6729 movLeft2Result (left, MSB24, result, LSB, 0);
6730 movLeft2Result (left, MSB32, result, MSB16, sign);
6732 addSign (result, MSB24, sign);
6734 else if (shCount >= 8)
6738 shiftRLong (left, MSB16, result, sign);
6739 else if (shCount == 0)
6741 movLeft2Result (left, MSB16, result, LSB, 0);
6742 movLeft2Result (left, MSB24, result, MSB16, 0);
6743 movLeft2Result (left, MSB32, result, MSB24, sign);
6744 addSign (result, MSB32, sign);
6748 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6749 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6750 /* the last shift is signed */
6751 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6752 addSign (result, MSB32, sign);
6756 { /* 1 <= shCount <= 7 */
6759 shiftRLong (left, LSB, result, sign);
6761 shiftRLong (result, LSB, result, sign);
6765 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6766 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6767 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6772 /*-----------------------------------------------------------------*/
6773 /* genRightShiftLiteral - right shifting by known count */
6774 /*-----------------------------------------------------------------*/
6776 genRightShiftLiteral (operand * left,
6782 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6785 D(emitcode ("; genRightShiftLiteral",""));
6787 freeAsmop (right, NULL, ic, TRUE);
6789 aopOp (left, ic, FALSE);
6790 aopOp (result, ic, FALSE);
6793 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6797 size = getDataSize (left);
6798 /* test the LEFT size !!! */
6800 /* I suppose that the left size >= result size */
6803 size = getDataSize (result);
6805 movLeft2Result (left, size, result, size, 0);
6808 else if (shCount >= (size * 8))
6811 /* get sign in acc.7 */
6812 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6814 addSign (result, LSB, sign);
6821 genrshOne (result, left, shCount, sign);
6825 genrshTwo (result, left, shCount, sign);
6829 genrshFour (result, left, shCount, sign);
6835 freeAsmop (left, NULL, ic, TRUE);
6836 freeAsmop (result, NULL, ic, TRUE);
6839 /*-----------------------------------------------------------------*/
6840 /* genSignedRightShift - right shift of signed number */
6841 /*-----------------------------------------------------------------*/
6843 genSignedRightShift (iCode * ic)
6845 operand *right, *left, *result;
6848 symbol *tlbl, *tlbl1;
6850 D(emitcode ("; genSignedRightShift",""));
6852 /* we do it the hard way put the shift count in b
6853 and loop thru preserving the sign */
6855 right = IC_RIGHT (ic);
6856 left = IC_LEFT (ic);
6857 result = IC_RESULT (ic);
6859 aopOp (right, ic, FALSE);
6862 if (AOP_TYPE (right) == AOP_LIT)
6864 genRightShiftLiteral (left, right, result, ic, 1);
6867 /* shift count is unknown then we have to form
6868 a loop get the loop count in B : Note: we take
6869 only the lower order byte since shifting
6870 more that 32 bits make no sense anyway, ( the
6871 largest size of an object can be only 32 bits ) */
6873 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6874 emitcode ("inc", "b");
6875 freeAsmop (right, NULL, ic, TRUE);
6876 aopOp (left, ic, FALSE);
6877 aopOp (result, ic, FALSE);
6879 /* now move the left to the result if they are not the
6881 if (!sameRegs (AOP (left), AOP (result)) &&
6882 AOP_SIZE (result) > 1)
6885 size = AOP_SIZE (result);
6889 l = aopGet (AOP (left), offset, FALSE, TRUE);
6890 if (*l == '@' && IS_AOP_PREG (result))
6893 emitcode ("mov", "a,%s", l);
6894 aopPut (AOP (result), "a", offset);
6897 aopPut (AOP (result), l, offset);
6902 /* mov the highest order bit to OVR */
6903 tlbl = newiTempLabel (NULL);
6904 tlbl1 = newiTempLabel (NULL);
6906 size = AOP_SIZE (result);
6908 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6909 emitcode ("rlc", "a");
6910 emitcode ("mov", "ov,c");
6911 /* if it is only one byte then */
6914 l = aopGet (AOP (left), 0, FALSE, FALSE);
6916 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6917 emitcode ("", "%05d$:", tlbl->key + 100);
6918 emitcode ("mov", "c,ov");
6919 emitcode ("rrc", "a");
6920 emitcode ("", "%05d$:", tlbl1->key + 100);
6921 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6922 aopPut (AOP (result), "a", 0);
6926 reAdjustPreg (AOP (result));
6927 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6928 emitcode ("", "%05d$:", tlbl->key + 100);
6929 emitcode ("mov", "c,ov");
6932 l = aopGet (AOP (result), offset, FALSE, FALSE);
6934 emitcode ("rrc", "a");
6935 aopPut (AOP (result), "a", offset--);
6937 reAdjustPreg (AOP (result));
6938 emitcode ("", "%05d$:", tlbl1->key + 100);
6939 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6942 freeAsmop (left, NULL, ic, TRUE);
6943 freeAsmop (result, NULL, ic, TRUE);
6946 /*-----------------------------------------------------------------*/
6947 /* genRightShift - generate code for right shifting */
6948 /*-----------------------------------------------------------------*/
6950 genRightShift (iCode * ic)
6952 operand *right, *left, *result;
6956 symbol *tlbl, *tlbl1;
6958 D(emitcode ("; genRightShift",""));
6960 /* if signed then we do it the hard way preserve the
6961 sign bit moving it inwards */
6962 retype = getSpec (operandType (IC_RESULT (ic)));
6964 if (!SPEC_USIGN (retype))
6966 genSignedRightShift (ic);
6970 /* signed & unsigned types are treated the same : i.e. the
6971 signed is NOT propagated inwards : quoting from the
6972 ANSI - standard : "for E1 >> E2, is equivalent to division
6973 by 2**E2 if unsigned or if it has a non-negative value,
6974 otherwise the result is implementation defined ", MY definition
6975 is that the sign does not get propagated */
6977 right = IC_RIGHT (ic);
6978 left = IC_LEFT (ic);
6979 result = IC_RESULT (ic);
6981 aopOp (right, ic, FALSE);
6983 /* if the shift count is known then do it
6984 as efficiently as possible */
6985 if (AOP_TYPE (right) == AOP_LIT)
6987 genRightShiftLiteral (left, right, result, ic, 0);
6991 /* shift count is unknown then we have to form
6992 a loop get the loop count in B : Note: we take
6993 only the lower order byte since shifting
6994 more that 32 bits make no sense anyway, ( the
6995 largest size of an object can be only 32 bits ) */
6997 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6998 emitcode ("inc", "b");
6999 freeAsmop (right, NULL, ic, TRUE);
7000 aopOp (left, ic, FALSE);
7001 aopOp (result, ic, FALSE);
7003 /* now move the left to the result if they are not the
7005 if (!sameRegs (AOP (left), AOP (result)) &&
7006 AOP_SIZE (result) > 1)
7009 size = AOP_SIZE (result);
7013 l = aopGet (AOP (left), offset, FALSE, TRUE);
7014 if (*l == '@' && IS_AOP_PREG (result))
7017 emitcode ("mov", "a,%s", l);
7018 aopPut (AOP (result), "a", offset);
7021 aopPut (AOP (result), l, offset);
7026 tlbl = newiTempLabel (NULL);
7027 tlbl1 = newiTempLabel (NULL);
7028 size = AOP_SIZE (result);
7031 /* if it is only one byte then */
7034 l = aopGet (AOP (left), 0, FALSE, FALSE);
7036 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7037 emitcode ("", "%05d$:", tlbl->key + 100);
7039 emitcode ("rrc", "a");
7040 emitcode ("", "%05d$:", tlbl1->key + 100);
7041 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7042 aopPut (AOP (result), "a", 0);
7046 reAdjustPreg (AOP (result));
7047 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7048 emitcode ("", "%05d$:", tlbl->key + 100);
7052 l = aopGet (AOP (result), offset, FALSE, FALSE);
7054 emitcode ("rrc", "a");
7055 aopPut (AOP (result), "a", offset--);
7057 reAdjustPreg (AOP (result));
7059 emitcode ("", "%05d$:", tlbl1->key + 100);
7060 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7063 freeAsmop (left, NULL, ic, TRUE);
7064 freeAsmop (result, NULL, ic, TRUE);
7067 /*-----------------------------------------------------------------*/
7068 /* genUnpackBits - generates code for unpacking bits */
7069 /*-----------------------------------------------------------------*/
7071 genUnpackBits (operand * result, char *rname, int ptype)
7079 D(emitcode ("; genUnpackBits",""));
7081 etype = getSpec (operandType (result));
7082 rsize = getSize (operandType (result));
7083 /* read the first byte */
7089 emitcode ("mov", "a,@%s", rname);
7093 emitcode ("movx", "a,@%s", rname);
7097 emitcode ("movx", "a,@dptr");
7101 emitcode ("clr", "a");
7102 emitcode ("movc", "a,@a+dptr");
7106 emitcode ("lcall", "__gptrget");
7110 rlen = SPEC_BLEN (etype);
7112 /* if we have bitdisplacement then it fits */
7113 /* into this byte completely or if length is */
7114 /* less than a byte */
7115 if ((shCnt = SPEC_BSTR (etype)) ||
7116 (SPEC_BLEN (etype) <= 8))
7119 /* shift right acc */
7122 emitcode ("anl", "a,#0x%02x",
7123 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7124 aopPut (AOP (result), "a", offset++);
7128 /* bit field did not fit in a byte */
7129 aopPut (AOP (result), "a", offset++);
7138 emitcode ("inc", "%s", rname);
7139 emitcode ("mov", "a,@%s", rname);
7143 emitcode ("inc", "%s", rname);
7144 emitcode ("movx", "a,@%s", rname);
7148 emitcode ("inc", "dptr");
7149 emitcode ("movx", "a,@dptr");
7153 emitcode ("clr", "a");
7154 emitcode ("inc", "dptr");
7155 emitcode ("movc", "a,@a+dptr");
7159 emitcode ("inc", "dptr");
7160 emitcode ("lcall", "__gptrget");
7165 /* if we are done */
7169 aopPut (AOP (result), "a", offset++);
7175 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7177 aopPut (AOP (result), "a", offset++);
7185 aopPut (AOP (result), zero, offset++);
7191 /*-----------------------------------------------------------------*/
7192 /* genDataPointerGet - generates code when ptr offset is known */
7193 /*-----------------------------------------------------------------*/
7195 genDataPointerGet (operand * left,
7201 int size, offset = 0;
7203 D(emitcode ("; genDataPointerGet",""));
7205 aopOp (result, ic, TRUE);
7207 /* get the string representation of the name */
7208 l = aopGet (AOP (left), 0, FALSE, TRUE);
7209 size = AOP_SIZE (result);
7213 sprintf (buffer, "(%s + %d)", l + 1, offset);
7215 sprintf (buffer, "%s", l + 1);
7216 aopPut (AOP (result), buffer, offset++);
7219 freeAsmop (left, NULL, ic, TRUE);
7220 freeAsmop (result, NULL, ic, TRUE);
7223 /*-----------------------------------------------------------------*/
7224 /* genNearPointerGet - emitcode for near pointer fetch */
7225 /*-----------------------------------------------------------------*/
7227 genNearPointerGet (operand * left,
7235 sym_link *rtype, *retype;
7236 sym_link *ltype = operandType (left);
7239 D(emitcode ("; genNearPointerGet",""));
7241 rtype = operandType (result);
7242 retype = getSpec (rtype);
7244 aopOp (left, ic, FALSE);
7246 /* if left is rematerialisable and
7247 result is not bit variable type and
7248 the left is pointer to data space i.e
7249 lower 128 bytes of space */
7250 if (AOP_TYPE (left) == AOP_IMMD &&
7251 !IS_BITVAR (retype) &&
7252 DCL_TYPE (ltype) == POINTER)
7254 genDataPointerGet (left, result, ic);
7258 /* if the value is already in a pointer register
7259 then don't need anything more */
7260 if (!AOP_INPREG (AOP (left)))
7262 /* otherwise get a free pointer register */
7264 preg = getFreePtr (ic, &aop, FALSE);
7265 emitcode ("mov", "%s,%s",
7267 aopGet (AOP (left), 0, FALSE, TRUE));
7271 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7273 //aopOp (result, ic, FALSE);
7274 aopOp (result, ic, result?TRUE:FALSE);
7276 /* if bitfield then unpack the bits */
7277 if (IS_BITVAR (retype))
7278 genUnpackBits (result, rname, POINTER);
7281 /* we have can just get the values */
7282 int size = AOP_SIZE (result);
7287 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7290 emitcode ("mov", "a,@%s", rname);
7291 aopPut (AOP (result), "a", offset);
7295 sprintf (buffer, "@%s", rname);
7296 aopPut (AOP (result), buffer, offset);
7300 emitcode ("inc", "%s", rname);
7304 /* now some housekeeping stuff */
7305 if (aop) /* we had to allocate for this iCode */
7307 if (pi) { /* post increment present */
7308 aopPut(AOP ( left ),rname,0);
7310 freeAsmop (NULL, aop, ic, TRUE);
7314 /* we did not allocate which means left
7315 already in a pointer register, then
7316 if size > 0 && this could be used again
7317 we have to point it back to where it
7319 if ((AOP_SIZE (result) > 1 &&
7320 !OP_SYMBOL (left)->remat &&
7321 (OP_SYMBOL (left)->liveTo > ic->seq ||
7325 int size = AOP_SIZE (result) - 1;
7327 emitcode ("dec", "%s", rname);
7332 freeAsmop (left, NULL, ic, TRUE);
7333 freeAsmop (result, NULL, ic, TRUE);
7334 if (pi) pi->generated = 1;
7337 /*-----------------------------------------------------------------*/
7338 /* genPagedPointerGet - emitcode for paged pointer fetch */
7339 /*-----------------------------------------------------------------*/
7341 genPagedPointerGet (operand * left,
7349 sym_link *rtype, *retype;
7351 D(emitcode ("; genPagedPointerGet",""));
7353 rtype = operandType (result);
7354 retype = getSpec (rtype);
7356 aopOp (left, ic, FALSE);
7358 /* if the value is already in a pointer register
7359 then don't need anything more */
7360 if (!AOP_INPREG (AOP (left)))
7362 /* otherwise get a free pointer register */
7364 preg = getFreePtr (ic, &aop, FALSE);
7365 emitcode ("mov", "%s,%s",
7367 aopGet (AOP (left), 0, FALSE, TRUE));
7371 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7373 aopOp (result, ic, FALSE);
7375 /* if bitfield then unpack the bits */
7376 if (IS_BITVAR (retype))
7377 genUnpackBits (result, rname, PPOINTER);
7380 /* we have can just get the values */
7381 int size = AOP_SIZE (result);
7387 emitcode ("movx", "a,@%s", rname);
7388 aopPut (AOP (result), "a", offset);
7393 emitcode ("inc", "%s", rname);
7397 /* now some housekeeping stuff */
7398 if (aop) /* we had to allocate for this iCode */
7400 if (pi) aopPut ( AOP (left), rname, 0);
7401 freeAsmop (NULL, aop, ic, TRUE);
7405 /* we did not allocate which means left
7406 already in a pointer register, then
7407 if size > 0 && this could be used again
7408 we have to point it back to where it
7410 if ((AOP_SIZE (result) > 1 &&
7411 !OP_SYMBOL (left)->remat &&
7412 (OP_SYMBOL (left)->liveTo > ic->seq ||
7416 int size = AOP_SIZE (result) - 1;
7418 emitcode ("dec", "%s", rname);
7423 freeAsmop (left, NULL, ic, TRUE);
7424 freeAsmop (result, NULL, ic, TRUE);
7425 if (pi) pi->generated = 1;
7429 /*-----------------------------------------------------------------*/
7430 /* genFarPointerGet - gget value from far space */
7431 /*-----------------------------------------------------------------*/
7433 genFarPointerGet (operand * left,
7434 operand * result, iCode * ic, iCode * pi)
7437 sym_link *retype = getSpec (operandType (result));
7439 D(emitcode ("; genFarPointerGet",""));
7441 aopOp (left, ic, FALSE);
7443 /* if the operand is already in dptr
7444 then we do nothing else we move the value to dptr */
7445 if (AOP_TYPE (left) != AOP_STR)
7447 /* if this is remateriazable */
7448 if (AOP_TYPE (left) == AOP_IMMD)
7449 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7451 { /* we need to get it byte by byte */
7452 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7453 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7456 /* so dptr know contains the address */
7457 aopOp (result, ic, FALSE);
7459 /* if bit then unpack */
7460 if (IS_BITVAR (retype))
7461 genUnpackBits (result, "dptr", FPOINTER);
7464 size = AOP_SIZE (result);
7469 emitcode ("movx", "a,@dptr");
7470 aopPut (AOP (result), "a", offset++);
7472 emitcode ("inc", "dptr");
7476 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7477 aopPut ( AOP (left), "dpl", 0);
7478 aopPut ( AOP (left), "dph", 1);
7481 freeAsmop (left, NULL, ic, TRUE);
7482 freeAsmop (result, NULL, ic, TRUE);
7485 /*-----------------------------------------------------------------*/
7486 /* genCodePointerGet - gget value from code space */
7487 /*-----------------------------------------------------------------*/
7489 genCodePointerGet (operand * left,
7490 operand * result, iCode * ic, iCode *pi)
7493 sym_link *retype = getSpec (operandType (result));
7495 D(emitcode ("; genCodePointerGet",""));
7497 aopOp (left, ic, FALSE);
7499 /* if the operand is already in dptr
7500 then we do nothing else we move the value to dptr */
7501 if (AOP_TYPE (left) != AOP_STR)
7503 /* if this is remateriazable */
7504 if (AOP_TYPE (left) == AOP_IMMD)
7505 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7507 { /* we need to get it byte by byte */
7508 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7509 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7512 /* so dptr know contains the address */
7513 aopOp (result, ic, FALSE);
7515 /* if bit then unpack */
7516 if (IS_BITVAR (retype))
7517 genUnpackBits (result, "dptr", CPOINTER);
7520 size = AOP_SIZE (result);
7525 emitcode ("clr", "a");
7526 emitcode ("movc", "a,@a+dptr");
7527 aopPut (AOP (result), "a", offset++);
7529 emitcode ("inc", "dptr");
7533 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7534 aopPut ( AOP (left), "dpl", 0);
7535 aopPut ( AOP (left), "dph", 1);
7538 freeAsmop (left, NULL, ic, TRUE);
7539 freeAsmop (result, NULL, ic, TRUE);
7542 /*-----------------------------------------------------------------*/
7543 /* genGenPointerGet - gget value from generic pointer space */
7544 /*-----------------------------------------------------------------*/
7546 genGenPointerGet (operand * left,
7547 operand * result, iCode * ic, iCode *pi)
7550 sym_link *retype = getSpec (operandType (result));
7552 D(emitcode ("; genGenPointerGet",""));
7554 aopOp (left, ic, FALSE);
7556 /* if the operand is already in dptr
7557 then we do nothing else we move the value to dptr */
7558 if (AOP_TYPE (left) != AOP_STR)
7560 /* if this is remateriazable */
7561 if (AOP_TYPE (left) == AOP_IMMD)
7563 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7564 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7565 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7567 emitcode ("mov", "b,#%d", pointerCode (retype));
7570 { /* we need to get it byte by byte */
7571 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7572 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7573 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, 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", GPOINTER);
7584 size = AOP_SIZE (result);
7589 emitcode ("lcall", "__gptrget");
7590 aopPut (AOP (result), "a", offset++);
7592 emitcode ("inc", "dptr");
7596 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7597 aopPut ( AOP (left), "dpl", 0);
7598 aopPut ( AOP (left), "dph", 1);
7599 aopPut ( AOP (left), "b", 2);
7602 freeAsmop (left, NULL, ic, TRUE);
7603 freeAsmop (result, NULL, ic, TRUE);
7606 /*-----------------------------------------------------------------*/
7607 /* genPointerGet - generate code for pointer get */
7608 /*-----------------------------------------------------------------*/
7610 genPointerGet (iCode * ic, iCode *pi)
7612 operand *left, *result;
7613 sym_link *type, *etype;
7616 D(emitcode ("; genPointerGet",""));
7618 left = IC_LEFT (ic);
7619 result = IC_RESULT (ic);
7621 /* depending on the type of pointer we need to
7622 move it to the correct pointer register */
7623 type = operandType (left);
7624 etype = getSpec (type);
7625 /* if left is of type of pointer then it is simple */
7626 if (IS_PTR (type) && !IS_FUNC (type->next))
7627 p_type = DCL_TYPE (type);
7630 /* we have to go by the storage class */
7631 p_type = PTR_TYPE (SPEC_OCLS (etype));
7634 /* special case when cast remat */
7635 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7636 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7637 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7638 type = operandType (left);
7639 p_type = DCL_TYPE (type);
7641 /* now that we have the pointer type we assign
7642 the pointer values */
7648 genNearPointerGet (left, result, ic, pi);
7652 genPagedPointerGet (left, result, ic, pi);
7656 genFarPointerGet (left, result, ic, pi);
7660 genCodePointerGet (left, result, ic, pi);
7664 genGenPointerGet (left, result, ic, pi);
7670 /*-----------------------------------------------------------------*/
7671 /* genPackBits - generates code for packed bit storage */
7672 /*-----------------------------------------------------------------*/
7674 genPackBits (sym_link * etype,
7676 char *rname, int p_type)
7684 D(emitcode ("; genPackBits",""));
7686 blen = SPEC_BLEN (etype);
7687 bstr = SPEC_BSTR (etype);
7689 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7692 /* if the bit lenth is less than or */
7693 /* it exactly fits a byte then */
7694 if (SPEC_BLEN (etype) <= 8)
7696 shCount = SPEC_BSTR (etype);
7698 /* shift left acc */
7701 if (SPEC_BLEN (etype) < 8)
7702 { /* if smaller than a byte */
7708 emitcode ("mov", "b,a");
7709 emitcode ("mov", "a,@%s", rname);
7713 emitcode ("mov", "b,a");
7714 emitcode ("movx", "a,@dptr");
7718 emitcode ("push", "b");
7719 emitcode ("push", "acc");
7720 emitcode ("lcall", "__gptrget");
7721 emitcode ("pop", "b");
7725 emitcode ("anl", "a,#0x%02x", (unsigned char)
7726 ((unsigned char) (0xFF << (blen + bstr)) |
7727 (unsigned char) (0xFF >> (8 - bstr))));
7728 emitcode ("orl", "a,b");
7729 if (p_type == GPOINTER)
7730 emitcode ("pop", "b");
7737 emitcode ("mov", "@%s,a", rname);
7741 emitcode ("movx", "@dptr,a");
7745 emitcode ("lcall", "__gptrput");
7750 if (SPEC_BLEN (etype) <= 8)
7753 emitcode ("inc", "%s", rname);
7754 rLen = SPEC_BLEN (etype);
7756 /* now generate for lengths greater than one byte */
7760 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7772 emitcode ("mov", "@%s,a", rname);
7775 emitcode ("mov", "@%s,%s", rname, l);
7780 emitcode ("movx", "@dptr,a");
7785 emitcode ("lcall", "__gptrput");
7788 emitcode ("inc", "%s", rname);
7793 /* last last was not complete */
7796 /* save the byte & read byte */
7800 emitcode ("mov", "b,a");
7801 emitcode ("mov", "a,@%s", rname);
7805 emitcode ("mov", "b,a");
7806 emitcode ("movx", "a,@dptr");
7810 emitcode ("push", "b");
7811 emitcode ("push", "acc");
7812 emitcode ("lcall", "__gptrget");
7813 emitcode ("pop", "b");
7817 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7818 emitcode ("orl", "a,b");
7821 if (p_type == GPOINTER)
7822 emitcode ("pop", "b");
7828 emitcode ("mov", "@%s,a", rname);
7832 emitcode ("movx", "@dptr,a");
7836 emitcode ("lcall", "__gptrput");
7840 /*-----------------------------------------------------------------*/
7841 /* genDataPointerSet - remat pointer to data space */
7842 /*-----------------------------------------------------------------*/
7844 genDataPointerSet (operand * right,
7848 int size, offset = 0;
7849 char *l, buffer[256];
7851 D(emitcode ("; genDataPointerSet",""));
7853 aopOp (right, ic, FALSE);
7855 l = aopGet (AOP (result), 0, FALSE, TRUE);
7856 size = AOP_SIZE (right);
7860 sprintf (buffer, "(%s + %d)", l + 1, offset);
7862 sprintf (buffer, "%s", l + 1);
7863 emitcode ("mov", "%s,%s", buffer,
7864 aopGet (AOP (right), offset++, FALSE, FALSE));
7867 freeAsmop (right, NULL, ic, TRUE);
7868 freeAsmop (result, NULL, ic, TRUE);
7871 /*-----------------------------------------------------------------*/
7872 /* genNearPointerSet - emitcode for near pointer put */
7873 /*-----------------------------------------------------------------*/
7875 genNearPointerSet (operand * right,
7883 sym_link *retype, *letype;
7884 sym_link *ptype = operandType (result);
7886 D(emitcode ("; genNearPointerSet",""));
7888 retype = getSpec (operandType (right));
7889 letype = getSpec (ptype);
7890 aopOp (result, ic, FALSE);
7892 /* if the result is rematerializable &
7893 in data space & not a bit variable */
7894 if (AOP_TYPE (result) == AOP_IMMD &&
7895 DCL_TYPE (ptype) == POINTER &&
7896 !IS_BITVAR (retype) &&
7897 !IS_BITVAR (letype))
7899 genDataPointerSet (right, result, ic);
7903 /* if the value is already in a pointer register
7904 then don't need anything more */
7905 if (!AOP_INPREG (AOP (result)))
7908 //AOP_TYPE (result) == AOP_STK
7912 // Aha, it is a pointer, just in disguise.
7913 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7916 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7917 __FILE__, __LINE__);
7922 rname++; // skip the '@'.
7927 /* otherwise get a free pointer register */
7929 preg = getFreePtr (ic, &aop, FALSE);
7930 emitcode ("mov", "%s,%s",
7932 aopGet (AOP (result), 0, FALSE, TRUE));
7938 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7941 aopOp (right, ic, FALSE);
7943 /* if bitfield then unpack the bits */
7944 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7945 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7948 /* we have can just get the values */
7949 int size = AOP_SIZE (right);
7954 l = aopGet (AOP (right), offset, FALSE, TRUE);
7958 emitcode ("mov", "@%s,a", rname);
7961 emitcode ("mov", "@%s,%s", rname, l);
7963 emitcode ("inc", "%s", rname);
7968 /* now some housekeeping stuff */
7969 if (aop) /* we had to allocate for this iCode */
7971 if (pi) aopPut (AOP (result),rname,0);
7972 freeAsmop (NULL, aop, ic, TRUE);
7976 /* we did not allocate which means left
7977 already in a pointer register, then
7978 if size > 0 && this could be used again
7979 we have to point it back to where it
7981 if ((AOP_SIZE (right) > 1 &&
7982 !OP_SYMBOL (result)->remat &&
7983 (OP_SYMBOL (result)->liveTo > ic->seq ||
7987 int size = AOP_SIZE (right) - 1;
7989 emitcode ("dec", "%s", rname);
7994 if (pi) pi->generated = 1;
7995 freeAsmop (result, NULL, ic, TRUE);
7996 freeAsmop (right, NULL, ic, TRUE);
7999 /*-----------------------------------------------------------------*/
8000 /* genPagedPointerSet - emitcode for Paged pointer put */
8001 /*-----------------------------------------------------------------*/
8003 genPagedPointerSet (operand * right,
8011 sym_link *retype, *letype;
8013 D(emitcode ("; genPagedPointerSet",""));
8015 retype = getSpec (operandType (right));
8016 letype = getSpec (operandType (result));
8018 aopOp (result, ic, FALSE);
8020 /* if the value is already in a pointer register
8021 then don't need anything more */
8022 if (!AOP_INPREG (AOP (result)))
8024 /* otherwise get a free pointer register */
8026 preg = getFreePtr (ic, &aop, FALSE);
8027 emitcode ("mov", "%s,%s",
8029 aopGet (AOP (result), 0, FALSE, TRUE));
8033 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8035 aopOp (right, ic, FALSE);
8037 /* if bitfield then unpack the bits */
8038 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8039 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8042 /* we have can just get the values */
8043 int size = AOP_SIZE (right);
8048 l = aopGet (AOP (right), offset, FALSE, TRUE);
8051 emitcode ("movx", "@%s,a", rname);
8054 emitcode ("inc", "%s", rname);
8060 /* now some housekeeping stuff */
8061 if (aop) /* we had to allocate for this iCode */
8063 if (pi) aopPut (AOP (result),rname,0);
8064 freeAsmop (NULL, aop, ic, TRUE);
8068 /* we did not allocate which means left
8069 already in a pointer register, then
8070 if size > 0 && this could be used again
8071 we have to point it back to where it
8073 if (AOP_SIZE (right) > 1 &&
8074 !OP_SYMBOL (result)->remat &&
8075 (OP_SYMBOL (result)->liveTo > ic->seq ||
8078 int size = AOP_SIZE (right) - 1;
8080 emitcode ("dec", "%s", rname);
8085 if (pi) pi->generated = 1;
8086 freeAsmop (result, NULL, ic, TRUE);
8087 freeAsmop (right, NULL, ic, TRUE);
8092 /*-----------------------------------------------------------------*/
8093 /* genFarPointerSet - set value from far space */
8094 /*-----------------------------------------------------------------*/
8096 genFarPointerSet (operand * right,
8097 operand * result, iCode * ic, iCode * pi)
8100 sym_link *retype = getSpec (operandType (right));
8101 sym_link *letype = getSpec (operandType (result));
8103 D(emitcode ("; genFarPointerSet",""));
8105 aopOp (result, ic, FALSE);
8107 /* if the operand is already in dptr
8108 then we do nothing else we move the value to dptr */
8109 if (AOP_TYPE (result) != AOP_STR)
8111 /* if this is remateriazable */
8112 if (AOP_TYPE (result) == AOP_IMMD)
8113 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8115 { /* we need to get it byte by byte */
8116 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8117 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8120 /* so dptr know contains the address */
8121 aopOp (right, ic, FALSE);
8123 /* if bit then unpack */
8124 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8125 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8128 size = AOP_SIZE (right);
8133 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8135 emitcode ("movx", "@dptr,a");
8137 emitcode ("inc", "dptr");
8140 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8141 aopPut (AOP(result),"dpl",0);
8142 aopPut (AOP(result),"dph",1);
8145 freeAsmop (result, NULL, ic, TRUE);
8146 freeAsmop (right, NULL, ic, TRUE);
8149 /*-----------------------------------------------------------------*/
8150 /* genGenPointerSet - set value from generic pointer space */
8151 /*-----------------------------------------------------------------*/
8153 genGenPointerSet (operand * right,
8154 operand * result, iCode * ic, iCode * pi)
8157 sym_link *retype = getSpec (operandType (right));
8158 sym_link *letype = getSpec (operandType (result));
8160 D(emitcode ("; genGenPointerSet",""));
8162 aopOp (result, ic, FALSE);
8164 /* if the operand is already in dptr
8165 then we do nothing else we move the value to dptr */
8166 if (AOP_TYPE (result) != AOP_STR)
8168 /* if this is remateriazable */
8169 if (AOP_TYPE (result) == AOP_IMMD)
8171 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8172 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8173 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8175 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8178 { /* we need to get it byte by byte */
8179 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8180 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8181 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8184 /* so dptr know contains the address */
8185 aopOp (right, ic, FALSE);
8187 /* if bit then unpack */
8188 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8189 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8192 size = AOP_SIZE (right);
8197 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8199 emitcode ("lcall", "__gptrput");
8201 emitcode ("inc", "dptr");
8205 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8206 aopPut (AOP(result),"dpl",0);
8207 aopPut (AOP(result),"dph",1);
8208 aopPut (AOP(result),"b",2);
8211 freeAsmop (result, NULL, ic, TRUE);
8212 freeAsmop (right, NULL, ic, TRUE);
8215 /*-----------------------------------------------------------------*/
8216 /* genPointerSet - stores the value into a pointer location */
8217 /*-----------------------------------------------------------------*/
8219 genPointerSet (iCode * ic, iCode *pi)
8221 operand *right, *result;
8222 sym_link *type, *etype;
8225 D(emitcode ("; genPointerSet",""));
8227 right = IC_RIGHT (ic);
8228 result = IC_RESULT (ic);
8230 /* depending on the type of pointer we need to
8231 move it to the correct pointer register */
8232 type = operandType (result);
8233 etype = getSpec (type);
8234 /* if left is of type of pointer then it is simple */
8235 if (IS_PTR (type) && !IS_FUNC (type->next))
8237 p_type = DCL_TYPE (type);
8241 /* we have to go by the storage class */
8242 p_type = PTR_TYPE (SPEC_OCLS (etype));
8245 /* special case when cast remat */
8246 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8247 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8248 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8249 type = operandType (result);
8250 p_type = DCL_TYPE (type);
8252 /* now that we have the pointer type we assign
8253 the pointer values */
8259 genNearPointerSet (right, result, ic, pi);
8263 genPagedPointerSet (right, result, ic, pi);
8267 genFarPointerSet (right, result, ic, pi);
8271 genGenPointerSet (right, result, ic, pi);
8275 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8276 "genPointerSet: illegal pointer type");
8281 /*-----------------------------------------------------------------*/
8282 /* genIfx - generate code for Ifx statement */
8283 /*-----------------------------------------------------------------*/
8285 genIfx (iCode * ic, iCode * popIc)
8287 operand *cond = IC_COND (ic);
8290 D(emitcode ("; genIfx",""));
8292 aopOp (cond, ic, FALSE);
8294 /* get the value into acc */
8295 if (AOP_TYPE (cond) != AOP_CRY)
8299 /* the result is now in the accumulator */
8300 freeAsmop (cond, NULL, ic, TRUE);
8302 /* if there was something to be popped then do it */
8306 /* if the condition is a bit variable */
8307 if (isbit && IS_ITEMP (cond) &&
8309 genIfxJump (ic, SPIL_LOC (cond)->rname);
8310 else if (isbit && !IS_ITEMP (cond))
8311 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8313 genIfxJump (ic, "a");
8318 /*-----------------------------------------------------------------*/
8319 /* genAddrOf - generates code for address of */
8320 /*-----------------------------------------------------------------*/
8322 genAddrOf (iCode * ic)
8324 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8327 D(emitcode ("; genAddrOf",""));
8329 aopOp (IC_RESULT (ic), ic, FALSE);
8331 /* if the operand is on the stack then we
8332 need to get the stack offset of this
8336 /* if it has an offset then we need to compute
8340 emitcode ("mov", "a,_bp");
8341 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8342 ((char) (sym->stack - _G.nRegsSaved)) :
8343 ((char) sym->stack)) & 0xff);
8344 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8348 /* we can just move _bp */
8349 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8351 /* fill the result with zero */
8352 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8357 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8363 /* object not on stack then we need the name */
8364 size = AOP_SIZE (IC_RESULT (ic));
8369 char s[SDCC_NAME_MAX];
8371 sprintf (s, "#(%s >> %d)",
8375 sprintf (s, "#%s", sym->rname);
8376 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8380 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8384 /*-----------------------------------------------------------------*/
8385 /* genFarFarAssign - assignment when both are in far space */
8386 /*-----------------------------------------------------------------*/
8388 genFarFarAssign (operand * result, operand * right, iCode * ic)
8390 int size = AOP_SIZE (right);
8394 D(emitcode ("; genFarFarAssign",""));
8396 /* first push the right side on to the stack */
8399 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8401 emitcode ("push", "acc");
8404 freeAsmop (right, NULL, ic, FALSE);
8405 /* now assign DPTR to result */
8406 aopOp (result, ic, FALSE);
8407 size = AOP_SIZE (result);
8410 emitcode ("pop", "acc");
8411 aopPut (AOP (result), "a", --offset);
8413 freeAsmop (result, NULL, ic, FALSE);
8417 /*-----------------------------------------------------------------*/
8418 /* genAssign - generate code for assignment */
8419 /*-----------------------------------------------------------------*/
8421 genAssign (iCode * ic)
8423 operand *result, *right;
8425 unsigned long lit = 0L;
8427 D(emitcode("; genAssign",""));
8429 result = IC_RESULT (ic);
8430 right = IC_RIGHT (ic);
8432 /* if they are the same */
8433 if (operandsEqu (result, right)) {
8437 aopOp (right, ic, FALSE);
8439 /* special case both in far space */
8440 if (AOP_TYPE (right) == AOP_DPTR &&
8441 IS_TRUE_SYMOP (result) &&
8442 isOperandInFarSpace (result))
8445 genFarFarAssign (result, right, ic);
8449 aopOp (result, ic, TRUE);
8451 /* if they are the same registers */
8452 if (sameRegs (AOP (right), AOP (result)))
8455 /* if the result is a bit */
8456 if (AOP_TYPE (result) == AOP_CRY)
8459 /* if the right size is a literal then
8460 we know what the value is */
8461 if (AOP_TYPE (right) == AOP_LIT)
8463 if (((int) operandLitValue (right)))
8464 aopPut (AOP (result), one, 0);
8466 aopPut (AOP (result), zero, 0);
8470 /* the right is also a bit variable */
8471 if (AOP_TYPE (right) == AOP_CRY)
8473 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8474 aopPut (AOP (result), "c", 0);
8480 aopPut (AOP (result), "a", 0);
8484 /* bit variables done */
8486 size = AOP_SIZE (result);
8488 if (AOP_TYPE (right) == AOP_LIT)
8489 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8491 (AOP_TYPE (result) != AOP_REG) &&
8492 (AOP_TYPE (right) == AOP_LIT) &&
8493 !IS_FLOAT (operandType (right)) &&
8496 emitcode ("clr", "a");
8499 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8500 aopPut (AOP (result), "a", size);
8502 aopPut (AOP (result),
8503 aopGet (AOP (right), size, FALSE, FALSE),
8511 aopPut (AOP (result),
8512 aopGet (AOP (right), offset, FALSE, FALSE),
8519 freeAsmop (right, NULL, ic, TRUE);
8520 freeAsmop (result, NULL, ic, TRUE);
8523 /*-----------------------------------------------------------------*/
8524 /* genJumpTab - genrates code for jump table */
8525 /*-----------------------------------------------------------------*/
8527 genJumpTab (iCode * ic)
8532 D(emitcode ("; genJumpTab",""));
8534 aopOp (IC_JTCOND (ic), ic, FALSE);
8535 /* get the condition into accumulator */
8536 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8538 /* multiply by three */
8539 emitcode ("add", "a,acc");
8540 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8541 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8543 jtab = newiTempLabel (NULL);
8544 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8545 emitcode ("jmp", "@a+dptr");
8546 emitcode ("", "%05d$:", jtab->key + 100);
8547 /* now generate the jump labels */
8548 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8549 jtab = setNextItem (IC_JTLABELS (ic)))
8550 emitcode ("ljmp", "%05d$", jtab->key + 100);
8554 /*-----------------------------------------------------------------*/
8555 /* genCast - gen code for casting */
8556 /*-----------------------------------------------------------------*/
8558 genCast (iCode * ic)
8560 operand *result = IC_RESULT (ic);
8561 sym_link *ctype = operandType (IC_LEFT (ic));
8562 sym_link *rtype = operandType (IC_RIGHT (ic));
8563 operand *right = IC_RIGHT (ic);
8566 D(emitcode("; genCast",""));
8568 /* if they are equivalent then do nothing */
8569 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8572 aopOp (right, ic, FALSE);
8573 aopOp (result, ic, FALSE);
8575 /* if the result is a bit */
8576 if (IS_BITVAR(OP_SYMBOL(result)->type))
8578 /* if the right size is a literal then
8579 we know what the value is */
8580 if (AOP_TYPE (right) == AOP_LIT)
8582 if (((int) operandLitValue (right)))
8583 aopPut (AOP (result), one, 0);
8585 aopPut (AOP (result), zero, 0);
8590 /* the right is also a bit variable */
8591 if (AOP_TYPE (right) == AOP_CRY)
8593 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8594 aopPut (AOP (result), "c", 0);
8600 aopPut (AOP (result), "a", 0);
8604 /* if they are the same size : or less */
8605 if (AOP_SIZE (result) <= AOP_SIZE (right))
8608 /* if they are in the same place */
8609 if (sameRegs (AOP (right), AOP (result)))
8612 /* if they in different places then copy */
8613 size = AOP_SIZE (result);
8617 aopPut (AOP (result),
8618 aopGet (AOP (right), offset, FALSE, FALSE),
8626 /* if the result is of type pointer */
8631 sym_link *type = operandType (right);
8632 sym_link *etype = getSpec (type);
8634 /* pointer to generic pointer */
8635 if (IS_GENPTR (ctype))
8638 p_type = DCL_TYPE (type);
8641 if (SPEC_SCLS(etype)==S_REGISTER) {
8642 // let's assume it is a generic pointer
8645 /* we have to go by the storage class */
8646 p_type = PTR_TYPE (SPEC_OCLS (etype));
8650 /* the first two bytes are known */
8651 size = GPTRSIZE - 1;
8655 aopPut (AOP (result),
8656 aopGet (AOP (right), offset, FALSE, FALSE),
8660 /* the last byte depending on type */
8662 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8667 // pointerTypeToGPByte will have bitched.
8671 sprintf(gpValStr, "#0x%d", gpVal);
8672 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8677 /* just copy the pointers */
8678 size = AOP_SIZE (result);
8682 aopPut (AOP (result),
8683 aopGet (AOP (right), offset, FALSE, FALSE),
8690 /* so we now know that the size of destination is greater
8691 than the size of the source */
8692 /* we move to result for the size of source */
8693 size = AOP_SIZE (right);
8697 aopPut (AOP (result),
8698 aopGet (AOP (right), offset, FALSE, FALSE),
8703 /* now depending on the sign of the source && destination */
8704 size = AOP_SIZE (result) - AOP_SIZE (right);
8705 /* if unsigned or not an integral type */
8706 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8709 aopPut (AOP (result), zero, offset++);
8713 /* we need to extend the sign :{ */
8714 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8717 emitcode ("rlc", "a");
8718 emitcode ("subb", "a,acc");
8720 aopPut (AOP (result), "a", offset++);
8723 /* we are done hurray !!!! */
8726 freeAsmop (right, NULL, ic, TRUE);
8727 freeAsmop (result, NULL, ic, TRUE);
8731 /*-----------------------------------------------------------------*/
8732 /* genDjnz - generate decrement & jump if not zero instrucion */
8733 /*-----------------------------------------------------------------*/
8735 genDjnz (iCode * ic, iCode * ifx)
8741 D(emitcode ("; genDjnz",""));
8743 /* if the if condition has a false label
8744 then we cannot save */
8748 /* if the minus is not of the form
8750 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8751 !IS_OP_LITERAL (IC_RIGHT (ic)))
8754 if (operandLitValue (IC_RIGHT (ic)) != 1)
8757 /* if the size of this greater than one then no
8759 if (getSize (operandType (IC_RESULT (ic))) > 1)
8762 /* otherwise we can save BIG */
8763 lbl = newiTempLabel (NULL);
8764 lbl1 = newiTempLabel (NULL);
8766 aopOp (IC_RESULT (ic), ic, FALSE);
8768 if (AOP_NEEDSACC(IC_RESULT(ic)))
8770 /* If the result is accessed indirectly via
8771 * the accumulator, we must explicitly write
8772 * it back after the decrement.
8774 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8776 if (strcmp(rByte, "a"))
8778 /* Something is hopelessly wrong */
8779 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8780 __FILE__, __LINE__);
8781 /* We can just give up; the generated code will be inefficient,
8784 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8787 emitcode ("dec", "%s", rByte);
8788 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8789 emitcode ("jnz", "%05d$", lbl->key + 100);
8791 else if (IS_AOP_PREG (IC_RESULT (ic)))
8793 emitcode ("dec", "%s",
8794 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8795 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8796 emitcode ("jnz", "%05d$", lbl->key + 100);
8800 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8803 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8804 emitcode ("", "%05d$:", lbl->key + 100);
8805 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8806 emitcode ("", "%05d$:", lbl1->key + 100);
8808 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8813 /*-----------------------------------------------------------------*/
8814 /* genReceive - generate code for a receive iCode */
8815 /*-----------------------------------------------------------------*/
8817 genReceive (iCode * ic)
8819 int size = getSize (operandType (IC_RESULT (ic)));
8821 D(emitcode ("; genReceive",""));
8823 if (ic->argreg == 1) { /* first parameter */
8824 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8825 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8826 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8828 offset = fReturnSizeMCS51 - size;
8830 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8831 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8834 aopOp (IC_RESULT (ic), ic, FALSE);
8835 size = AOP_SIZE (IC_RESULT (ic));
8838 emitcode ("pop", "acc");
8839 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8844 aopOp (IC_RESULT (ic), ic, FALSE);
8846 assignResultValue (IC_RESULT (ic));
8848 } else { /* second receive onwards */
8850 aopOp (IC_RESULT (ic), ic, FALSE);
8851 rb1off = ic->argreg;
8853 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8856 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8859 /*-----------------------------------------------------------------*/
8860 /* gen51Code - generate code for 8051 based controllers */
8861 /*-----------------------------------------------------------------*/
8863 gen51Code (iCode * lic)
8868 lineHead = lineCurr = NULL;
8870 /* print the allocation information */
8872 printAllocInfo (currFunc, codeOutFile);
8873 /* if debug information required */
8874 if (options.debug && currFunc)
8876 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8878 if (IS_STATIC (currFunc->etype))
8879 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8881 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8884 /* stack pointer name */
8885 if (options.useXstack)
8891 for (ic = lic; ic; ic = ic->next)
8894 if (ic->lineno && cln != ic->lineno)
8899 emitcode ("", "C$%s$%d$%d$%d ==.",
8900 FileBaseName (ic->filename), ic->lineno,
8901 ic->level, ic->block);
8904 if (!options.noCcodeInAsm) {
8905 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8906 printCLine(ic->filename, ic->lineno));
8910 if (options.iCodeInAsm) {
8911 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
8913 /* if the result is marked as
8914 spilt and rematerializable or code for
8915 this has already been generated then
8917 if (resultRemat (ic) || ic->generated)
8920 /* depending on the operation */
8940 /* IPOP happens only when trying to restore a
8941 spilt live range, if there is an ifx statement
8942 following this pop then the if statement might
8943 be using some of the registers being popped which
8944 would destory the contents of the register so
8945 we need to check for this condition and handle it */
8947 ic->next->op == IFX &&
8948 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8949 genIfx (ic->next, ic);
8967 genEndFunction (ic);
8987 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9004 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9008 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9015 /* note these two are xlated by algebraic equivalence
9016 during parsing SDCC.y */
9017 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9018 "got '>=' or '<=' shouldn't have come here");
9022 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9034 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9038 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9042 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9069 case GET_VALUE_AT_ADDRESS:
9070 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9074 if (POINTER_SET (ic))
9075 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9101 addSet (&_G.sendSet, ic);
9110 /* now we are ready to call the
9111 peep hole optimizer */
9112 if (!options.nopeep)
9113 peepHole (&lineHead);
9115 /* now do the actual printing */
9116 printLine (lineHead, codeOutFile);