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
1553 if (IS_SYMOP(IC_LEFT(ic)) &&
1554 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1555 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1558 /* safe the registers in use at this time but skip the
1559 ones for the result */
1560 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1561 mcs51_rUmaskForOp (IC_RESULT(ic)));
1564 if (options.useXstack)
1566 if (bitVectBitValue (rsave, R0_IDX))
1567 emitcode ("mov", "b,r0");
1568 emitcode ("mov", "r0,%s", spname);
1569 for (i = 0; i < mcs51_nRegs; i++)
1571 if (bitVectBitValue (rsave, i))
1574 emitcode ("mov", "a,b");
1576 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1577 emitcode ("movx", "@r0,a");
1578 emitcode ("inc", "r0");
1581 emitcode ("mov", "%s,r0", spname);
1582 if (bitVectBitValue (rsave, R0_IDX))
1583 emitcode ("mov", "r0,b");
1586 for (i = 0; i < mcs51_nRegs; i++)
1588 if (bitVectBitValue (rsave, i))
1589 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1593 /*-----------------------------------------------------------------*/
1594 /* unsaveRegisters - pop the pushed registers */
1595 /*-----------------------------------------------------------------*/
1597 unsaveRegisters (iCode * ic)
1602 /* restore the registers in use at this time but skip the
1603 ones for the result */
1604 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1605 mcs51_rUmaskForOp (IC_RESULT(ic)));
1607 if (options.useXstack)
1609 emitcode ("mov", "r0,%s", spname);
1610 for (i = mcs51_nRegs; i >= 0; i--)
1612 if (bitVectBitValue (rsave, i))
1614 emitcode ("dec", "r0");
1615 emitcode ("movx", "a,@r0");
1617 emitcode ("mov", "b,a");
1619 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1623 emitcode ("mov", "%s,r0", spname);
1624 if (bitVectBitValue (rsave, R0_IDX))
1625 emitcode ("mov", "r0,b");
1628 for (i = mcs51_nRegs; i >= 0; i--)
1630 if (bitVectBitValue (rsave, i))
1631 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1637 /*-----------------------------------------------------------------*/
1639 /*-----------------------------------------------------------------*/
1641 pushSide (operand * oper, int size)
1646 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1647 if (AOP_TYPE (oper) != AOP_REG &&
1648 AOP_TYPE (oper) != AOP_DIR &&
1651 emitcode ("mov", "a,%s", l);
1652 emitcode ("push", "acc");
1655 emitcode ("push", "%s", l);
1659 /*-----------------------------------------------------------------*/
1660 /* assignResultValue - */
1661 /*-----------------------------------------------------------------*/
1663 assignResultValue (operand * oper)
1666 int size = AOP_SIZE (oper);
1669 aopPut (AOP (oper), fReturn[offset], offset);
1675 /*-----------------------------------------------------------------*/
1676 /* genXpush - pushes onto the external stack */
1677 /*-----------------------------------------------------------------*/
1679 genXpush (iCode * ic)
1681 asmop *aop = newAsmop (0);
1683 int size, offset = 0;
1685 D(emitcode ("; genXpush",""));
1687 aopOp (IC_LEFT (ic), ic, FALSE);
1688 r = getFreePtr (ic, &aop, FALSE);
1691 emitcode ("mov", "%s,_spx", r->name);
1693 size = AOP_SIZE (IC_LEFT (ic));
1697 char *l = aopGet (AOP (IC_LEFT (ic)),
1698 offset++, FALSE, FALSE);
1700 emitcode ("movx", "@%s,a", r->name);
1701 emitcode ("inc", "%s", r->name);
1706 emitcode ("mov", "_spx,%s", r->name);
1708 freeAsmop (NULL, aop, ic, TRUE);
1709 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1712 /*-----------------------------------------------------------------*/
1713 /* genIpush - genrate code for pushing this gets a little complex */
1714 /*-----------------------------------------------------------------*/
1716 genIpush (iCode * ic)
1718 int size, offset = 0;
1721 D(emitcode ("; genIpush",""));
1723 /* if this is not a parm push : ie. it is spill push
1724 and spill push is always done on the local stack */
1728 /* and the item is spilt then do nothing */
1729 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1732 aopOp (IC_LEFT (ic), ic, FALSE);
1733 size = AOP_SIZE (IC_LEFT (ic));
1734 /* push it on the stack */
1737 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1743 emitcode ("push", "%s", l);
1748 /* this is a paramter push: in this case we call
1749 the routine to find the call and save those
1750 registers that need to be saved */
1753 /* if use external stack then call the external
1754 stack pushing routine */
1755 if (options.useXstack)
1761 /* then do the push */
1762 aopOp (IC_LEFT (ic), ic, FALSE);
1765 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1766 size = AOP_SIZE (IC_LEFT (ic));
1770 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1771 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1772 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1775 emitcode ("mov", "a,%s", l);
1776 emitcode ("push", "acc");
1779 emitcode ("push", "%s", l);
1782 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1785 /*-----------------------------------------------------------------*/
1786 /* genIpop - recover the registers: can happen only for spilling */
1787 /*-----------------------------------------------------------------*/
1789 genIpop (iCode * ic)
1793 D(emitcode ("; genIpop",""));
1795 /* if the temp was not pushed then */
1796 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1799 aopOp (IC_LEFT (ic), ic, FALSE);
1800 size = AOP_SIZE (IC_LEFT (ic));
1801 offset = (size - 1);
1803 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1806 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1809 /*-----------------------------------------------------------------*/
1810 /* unsaveRBank - restores the resgister bank from stack */
1811 /*-----------------------------------------------------------------*/
1813 unsaveRBank (int bank, iCode * ic, bool popPsw)
1819 if (options.useXstack)
1823 /* Assume r0 is available for use. */
1824 r = mcs51_regWithIdx (R0_IDX);;
1829 r = getFreePtr (ic, &aop, FALSE);
1831 emitcode ("mov", "%s,_spx", r->name);
1836 if (options.useXstack)
1838 emitcode ("movx", "a,@%s", r->name);
1839 emitcode ("mov", "psw,a");
1840 emitcode ("dec", "%s", r->name);
1844 emitcode ("pop", "psw");
1848 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1850 if (options.useXstack)
1852 emitcode ("movx", "a,@%s", r->name);
1853 emitcode ("mov", "(%s+%d),a",
1854 regs8051[i].base, 8 * bank + regs8051[i].offset);
1855 emitcode ("dec", "%s", r->name);
1859 emitcode ("pop", "(%s+%d)",
1860 regs8051[i].base, 8 * bank + regs8051[i].offset);
1863 if (options.useXstack)
1865 emitcode ("mov", "_spx,%s", r->name);
1870 freeAsmop (NULL, aop, ic, TRUE);
1874 /*-----------------------------------------------------------------*/
1875 /* saveRBank - saves an entire register bank on the stack */
1876 /*-----------------------------------------------------------------*/
1878 saveRBank (int bank, iCode * ic, bool pushPsw)
1884 if (options.useXstack)
1888 /* Assume r0 is available for use. */
1889 r = mcs51_regWithIdx (R0_IDX);;
1894 r = getFreePtr (ic, &aop, FALSE);
1896 emitcode ("mov", "%s,_spx", r->name);
1899 for (i = 0; i < mcs51_nRegs; i++)
1901 if (options.useXstack)
1903 emitcode ("inc", "%s", r->name);
1904 emitcode ("mov", "a,(%s+%d)",
1905 regs8051[i].base, 8 * bank + regs8051[i].offset);
1906 emitcode ("movx", "@%s,a", r->name);
1909 emitcode ("push", "(%s+%d)",
1910 regs8051[i].base, 8 * bank + regs8051[i].offset);
1915 if (options.useXstack)
1917 emitcode ("mov", "a,psw");
1918 emitcode ("movx", "@%s,a", r->name);
1919 emitcode ("inc", "%s", r->name);
1920 emitcode ("mov", "_spx,%s", r->name);
1925 emitcode ("push", "psw");
1928 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1933 freeAsmop (NULL, aop, ic, TRUE);
1942 /*-----------------------------------------------------------------*/
1943 /* genSend - gen code for SEND */
1944 /*-----------------------------------------------------------------*/
1945 static void genSend(set *sendSet)
1950 for (sic = setFirstItem (_G.sendSet); sic;
1951 sic = setNextItem (_G.sendSet)) {
1952 int size, offset = 0;
1953 aopOp (IC_LEFT (sic), sic, FALSE);
1954 size = AOP_SIZE (IC_LEFT (sic));
1956 if (sic->argreg == 1) {
1958 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1960 if (strcmp (l, fReturn[offset]))
1961 emitcode ("mov", "%s,%s", fReturn[offset], l);
1967 emitcode ("mov","b1_%d,%s",rb1_count++,
1968 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1971 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1975 /*-----------------------------------------------------------------*/
1976 /* genCall - generates a call statement */
1977 /*-----------------------------------------------------------------*/
1979 genCall (iCode * ic)
1982 // bool restoreBank = FALSE;
1983 bool swapBanks = FALSE;
1985 D(emitcode("; genCall",""));
1987 dtype = operandType (IC_LEFT (ic));
1988 /* if send set is not empty the assign */
1991 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1992 genSend(reverseSet(_G.sendSet));
1994 genSend(_G.sendSet);
2000 /* if we are calling a not _naked function that is not using
2001 the same register bank then we need to save the
2002 destination registers on the stack */
2003 dtype = operandType (IC_LEFT (ic));
2004 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2005 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2006 !IFFUNC_ISISR (dtype))
2011 /* if caller saves & we have not saved then */
2017 emitcode ("mov", "psw,#0x%02x",
2018 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2022 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2023 OP_SYMBOL (IC_LEFT (ic))->rname :
2024 OP_SYMBOL (IC_LEFT (ic))->name));
2028 emitcode ("mov", "psw,#0x%02x",
2029 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2032 /* if we need assign a result value */
2033 if ((IS_ITEMP (IC_RESULT (ic)) &&
2034 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2035 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2036 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2037 IS_TRUE_SYMOP (IC_RESULT (ic)))
2041 aopOp (IC_RESULT (ic), ic, FALSE);
2044 assignResultValue (IC_RESULT (ic));
2046 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2049 /* adjust the stack for parameters if
2054 if (ic->parmBytes > 3)
2056 emitcode ("mov", "a,%s", spname);
2057 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2058 emitcode ("mov", "%s,a", spname);
2061 for (i = 0; i < ic->parmBytes; i++)
2062 emitcode ("dec", "%s", spname);
2065 /* if we hade saved some registers then unsave them */
2066 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2067 unsaveRegisters (ic);
2069 // /* if register bank was saved then pop them */
2071 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2074 /*-----------------------------------------------------------------*/
2075 /* -10l - generates a call by pointer statement */
2076 /*-----------------------------------------------------------------*/
2078 genPcall (iCode * ic)
2081 symbol *rlbl = newiTempLabel (NULL);
2082 // bool restoreBank=FALSE;
2083 bool swapBanks = FALSE;
2085 D(emitcode("; genPCall",""));
2087 /* if caller saves & we have not saved then */
2091 /* if we are calling a not _naked function that is not using
2092 the same register bank then we need to save the
2093 destination registers on the stack */
2094 dtype = operandType (IC_LEFT (ic))->next;
2095 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2096 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2097 !IFFUNC_ISISR (dtype))
2099 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2100 // restoreBank=TRUE;
2102 // need caution message to user here
2105 /* push the return address on to the stack */
2106 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2107 emitcode ("push", "acc");
2108 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2109 emitcode ("push", "acc");
2111 /* now push the calling address */
2112 aopOp (IC_LEFT (ic), ic, FALSE);
2114 pushSide (IC_LEFT (ic), FPTRSIZE);
2116 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2118 /* if send set is not empty the assign */
2121 genSend(reverseSet(_G.sendSet));
2127 emitcode ("mov", "psw,#0x%02x",
2128 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2132 emitcode ("ret", "");
2133 emitcode ("", "%05d$:", (rlbl->key + 100));
2138 emitcode ("mov", "psw,#0x%02x",
2139 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2142 /* if we need assign a result value */
2143 if ((IS_ITEMP (IC_RESULT (ic)) &&
2144 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2145 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2146 IS_TRUE_SYMOP (IC_RESULT (ic)))
2150 aopOp (IC_RESULT (ic), ic, FALSE);
2153 assignResultValue (IC_RESULT (ic));
2155 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2158 /* adjust the stack for parameters if
2163 if (ic->parmBytes > 3)
2165 emitcode ("mov", "a,%s", spname);
2166 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2167 emitcode ("mov", "%s,a", spname);
2170 for (i = 0; i < ic->parmBytes; i++)
2171 emitcode ("dec", "%s", spname);
2175 // /* if register bank was saved then unsave them */
2177 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2179 /* if we hade saved some registers then
2181 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2182 unsaveRegisters (ic);
2185 /*-----------------------------------------------------------------*/
2186 /* resultRemat - result is rematerializable */
2187 /*-----------------------------------------------------------------*/
2189 resultRemat (iCode * ic)
2191 if (SKIP_IC (ic) || ic->op == IFX)
2194 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2196 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2197 if (sym->remat && !POINTER_SET (ic))
2204 #if defined(__BORLANDC__) || defined(_MSC_VER)
2205 #define STRCASECMP stricmp
2207 #define STRCASECMP strcasecmp
2210 /*-----------------------------------------------------------------*/
2211 /* inExcludeList - return 1 if the string is in exclude Reg list */
2212 /*-----------------------------------------------------------------*/
2214 inExcludeList (char *s)
2218 if (options.excludeRegs[i] &&
2219 STRCASECMP (options.excludeRegs[i], "none") == 0)
2222 for (i = 0; options.excludeRegs[i]; i++)
2224 if (options.excludeRegs[i] &&
2225 STRCASECMP (s, options.excludeRegs[i]) == 0)
2231 /*-----------------------------------------------------------------*/
2232 /* genFunction - generated code for function entry */
2233 /*-----------------------------------------------------------------*/
2235 genFunction (iCode * ic)
2239 bool switchedPSW = FALSE;
2240 int calleesaves_saved_register = -1;
2243 /* create the function header */
2244 emitcode (";", "-----------------------------------------");
2245 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2246 emitcode (";", "-----------------------------------------");
2248 emitcode ("", "%s:", sym->rname);
2249 ftype = operandType (IC_LEFT (ic));
2251 if (IFFUNC_ISNAKED(ftype))
2253 emitcode(";", "naked function: no prologue.");
2257 /* if critical function then turn interrupts off */
2258 if (IFFUNC_ISCRITICAL (ftype))
2259 emitcode ("clr", "ea");
2261 /* here we need to generate the equates for the
2262 register bank if required */
2263 if (FUNC_REGBANK (ftype) != rbank)
2267 rbank = FUNC_REGBANK (ftype);
2268 for (i = 0; i < mcs51_nRegs; i++)
2270 if (strcmp (regs8051[i].base, "0") == 0)
2271 emitcode ("", "%s = 0x%02x",
2273 8 * rbank + regs8051[i].offset);
2275 emitcode ("", "%s = %s + 0x%02x",
2278 8 * rbank + regs8051[i].offset);
2282 /* if this is an interrupt service routine then
2283 save acc, b, dpl, dph */
2284 if (IFFUNC_ISISR (sym->type))
2287 if (!inExcludeList ("acc"))
2288 emitcode ("push", "acc");
2289 if (!inExcludeList ("b"))
2290 emitcode ("push", "b");
2291 if (!inExcludeList ("dpl"))
2292 emitcode ("push", "dpl");
2293 if (!inExcludeList ("dph"))
2294 emitcode ("push", "dph");
2295 /* if this isr has no bank i.e. is going to
2296 run with bank 0 , then we need to save more
2298 if (!FUNC_REGBANK (sym->type))
2301 /* if this function does not call any other
2302 function then we can be economical and
2303 save only those registers that are used */
2304 if (!IFFUNC_HASFCALL(sym->type))
2308 /* if any registers used */
2311 /* save the registers used */
2312 for (i = 0; i < sym->regsUsed->size; i++)
2314 if (bitVectBitValue (sym->regsUsed, i) ||
2315 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2316 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2324 /* this function has a function call cannot
2325 determines register usage so we will have to push the
2327 saveRBank (0, ic, FALSE);
2328 if (options.parms_in_bank1) {
2330 for (i=0; i < 8 ; i++ ) {
2331 emitcode ("push","%s",rb1regs[i]);
2338 /* This ISR uses a non-zero bank.
2340 * We assume that the bank is available for our
2343 * However, if this ISR calls a function which uses some
2344 * other bank, we must save that bank entirely.
2346 unsigned long banksToSave = 0;
2348 if (IFFUNC_HASFCALL(sym->type))
2351 #define MAX_REGISTER_BANKS 4
2356 for (i = ic; i; i = i->next)
2358 if (i->op == ENDFUNCTION)
2360 /* we got to the end OK. */
2368 dtype = operandType (IC_LEFT(i));
2370 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2372 /* Mark this bank for saving. */
2373 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2375 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2379 banksToSave |= (1 << FUNC_REGBANK(dtype));
2382 /* And note that we don't need to do it in
2390 /* This is a mess; we have no idea what
2391 * register bank the called function might
2394 * The only thing I can think of to do is
2395 * throw a warning and hope.
2397 werror(W_FUNCPTR_IN_USING_ISR);
2401 if (banksToSave && options.useXstack)
2403 /* Since we aren't passing it an ic,
2404 * saveRBank will assume r0 is available to abuse.
2406 * So switch to our (trashable) bank now, so
2407 * the caller's R0 isn't trashed.
2409 emitcode ("push", "psw");
2410 emitcode ("mov", "psw,#0x%02x",
2411 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2415 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2417 if (banksToSave & (1 << ix))
2419 saveRBank(ix, NULL, FALSE);
2423 // TODO: this needs a closer look
2424 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2429 /* if callee-save to be used for this function
2430 then save the registers being used in this function */
2431 if (IFFUNC_CALLEESAVES(sym->type))
2435 /* if any registers used */
2438 /* save the registers used */
2439 for (i = 0; i < sym->regsUsed->size; i++)
2441 if (bitVectBitValue (sym->regsUsed, i) ||
2442 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2444 /* remember one saved register for later usage */
2445 if (calleesaves_saved_register < 0)
2446 calleesaves_saved_register = i;
2447 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2455 /* set the register bank to the desired value */
2456 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2459 emitcode ("push", "psw");
2460 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2463 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2466 if (options.useXstack)
2468 emitcode ("mov", "r0,%s", spname);
2469 emitcode ("mov", "a,_bp");
2470 emitcode ("movx", "@r0,a");
2471 emitcode ("inc", "%s", spname);
2475 /* set up the stack */
2476 emitcode ("push", "_bp"); /* save the callers stack */
2478 emitcode ("mov", "_bp,%s", spname);
2481 /* adjust the stack for the function */
2487 werror (W_STACK_OVERFLOW, sym->name);
2489 if (i > 3 && sym->recvSize < 4)
2492 emitcode ("mov", "a,sp");
2493 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2494 emitcode ("mov", "sp,a");
2499 if (IFFUNC_CALLEESAVES(sym->type))
2501 /* if it's a callee-saves function we need a saved register */
2502 if (calleesaves_saved_register >= 0)
2504 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2505 emitcode ("mov", "a,sp");
2506 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2507 emitcode ("mov", "sp,a");
2508 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2511 /* do it the hard way */
2513 emitcode ("inc", "sp");
2517 /* not callee-saves, we can clobber r0 */
2518 emitcode ("mov", "r0,a");
2519 emitcode ("mov", "a,sp");
2520 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2521 emitcode ("mov", "sp,a");
2522 emitcode ("mov", "a,r0");
2527 emitcode ("inc", "sp");
2533 emitcode ("mov", "a,_spx");
2534 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2535 emitcode ("mov", "_spx,a");
2540 /*-----------------------------------------------------------------*/
2541 /* genEndFunction - generates epilogue for functions */
2542 /*-----------------------------------------------------------------*/
2544 genEndFunction (iCode * ic)
2546 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2548 if (IFFUNC_ISNAKED(sym->type))
2550 emitcode(";", "naked function: no epilogue.");
2554 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2556 emitcode ("mov", "%s,_bp", spname);
2559 /* if use external stack but some variables were
2560 added to the local stack then decrement the
2562 if (options.useXstack && sym->stack)
2564 emitcode ("mov", "a,sp");
2565 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2566 emitcode ("mov", "sp,a");
2570 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2572 if (options.useXstack)
2574 emitcode ("mov", "r0,%s", spname);
2575 emitcode ("movx", "a,@r0");
2576 emitcode ("mov", "_bp,a");
2577 emitcode ("dec", "%s", spname);
2581 emitcode ("pop", "_bp");
2585 /* restore the register bank */
2586 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2588 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2589 || !options.useXstack)
2591 /* Special case of ISR using non-zero bank with useXstack
2594 emitcode ("pop", "psw");
2598 if (IFFUNC_ISISR (sym->type))
2601 /* now we need to restore the registers */
2602 /* if this isr has no bank i.e. is going to
2603 run with bank 0 , then we need to save more
2605 if (!FUNC_REGBANK (sym->type))
2607 /* if this function does not call any other
2608 function then we can be economical and
2609 save only those registers that are used */
2610 if (!IFFUNC_HASFCALL(sym->type))
2614 /* if any registers used */
2617 /* save the registers used */
2618 for (i = sym->regsUsed->size; i >= 0; i--)
2620 if (bitVectBitValue (sym->regsUsed, i) ||
2621 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2622 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2629 if (options.parms_in_bank1) {
2631 for (i = 7 ; i >= 0 ; i-- ) {
2632 emitcode ("pop","%s",rb1regs[i]);
2635 /* this function has a function call cannot
2636 determines register usage so we will have to pop the
2638 unsaveRBank (0, ic, FALSE);
2643 /* This ISR uses a non-zero bank.
2645 * Restore any register banks saved by genFunction
2648 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2651 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2653 if (savedBanks & (1 << ix))
2655 unsaveRBank(ix, NULL, FALSE);
2659 if (options.useXstack)
2661 /* Restore bank AFTER calling unsaveRBank,
2662 * since it can trash r0.
2664 emitcode ("pop", "psw");
2668 if (!inExcludeList ("dph"))
2669 emitcode ("pop", "dph");
2670 if (!inExcludeList ("dpl"))
2671 emitcode ("pop", "dpl");
2672 if (!inExcludeList ("b"))
2673 emitcode ("pop", "b");
2674 if (!inExcludeList ("acc"))
2675 emitcode ("pop", "acc");
2677 if (IFFUNC_ISCRITICAL (sym->type))
2678 emitcode ("setb", "ea");
2680 /* if debug then send end of function */
2681 if (options.debug && currFunc)
2684 emitcode ("", "C$%s$%d$%d$%d ==.",
2685 FileBaseName (ic->filename), currFunc->lastLine,
2686 ic->level, ic->block);
2687 if (IS_STATIC (currFunc->etype))
2688 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2690 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2694 emitcode ("reti", "");
2698 if (IFFUNC_ISCRITICAL (sym->type))
2699 emitcode ("setb", "ea");
2701 if (IFFUNC_CALLEESAVES(sym->type))
2705 /* if any registers used */
2708 /* save the registers used */
2709 for (i = sym->regsUsed->size; i >= 0; i--)
2711 if (bitVectBitValue (sym->regsUsed, i) ||
2712 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2713 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2719 /* if debug then send end of function */
2720 if (options.debug && currFunc)
2723 emitcode ("", "C$%s$%d$%d$%d ==.",
2724 FileBaseName (ic->filename), currFunc->lastLine,
2725 ic->level, ic->block);
2726 if (IS_STATIC (currFunc->etype))
2727 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2729 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2733 emitcode ("ret", "");
2738 /*-----------------------------------------------------------------*/
2739 /* genRet - generate code for return statement */
2740 /*-----------------------------------------------------------------*/
2744 int size, offset = 0, pushed = 0;
2746 D(emitcode ("; genRet",""));
2748 /* if we have no return value then
2749 just generate the "ret" */
2753 /* we have something to return then
2754 move the return value into place */
2755 aopOp (IC_LEFT (ic), ic, FALSE);
2756 size = AOP_SIZE (IC_LEFT (ic));
2761 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2764 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2766 emitcode ("push", "%s", l);
2771 l = aopGet (AOP (IC_LEFT (ic)), offset,
2773 if (strcmp (fReturn[offset], l))
2774 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2783 if (strcmp (fReturn[pushed], "a"))
2784 emitcode ("pop", fReturn[pushed]);
2786 emitcode ("pop", "acc");
2789 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2792 /* generate a jump to the return label
2793 if the next is not the return statement */
2794 if (!(ic->next && ic->next->op == LABEL &&
2795 IC_LABEL (ic->next) == returnLabel))
2797 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2801 /*-----------------------------------------------------------------*/
2802 /* genLabel - generates a label */
2803 /*-----------------------------------------------------------------*/
2805 genLabel (iCode * ic)
2807 /* special case never generate */
2808 if (IC_LABEL (ic) == entryLabel)
2811 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2814 /*-----------------------------------------------------------------*/
2815 /* genGoto - generates a ljmp */
2816 /*-----------------------------------------------------------------*/
2818 genGoto (iCode * ic)
2820 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2823 /*-----------------------------------------------------------------*/
2824 /* findLabelBackwards: walks back through the iCode chain looking */
2825 /* for the given label. Returns number of iCode instructions */
2826 /* between that label and given ic. */
2827 /* Returns zero if label not found. */
2828 /*-----------------------------------------------------------------*/
2830 findLabelBackwards (iCode * ic, int key)
2839 /* If we have any pushes or pops, we cannot predict the distance.
2840 I don't like this at all, this should be dealt with in the
2842 if (ic->op == IPUSH || ic->op == IPOP) {
2846 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2855 /*-----------------------------------------------------------------*/
2856 /* genPlusIncr :- does addition with increment if possible */
2857 /*-----------------------------------------------------------------*/
2859 genPlusIncr (iCode * ic)
2861 unsigned int icount;
2862 unsigned int size = getDataSize (IC_RESULT (ic));
2864 /* will try to generate an increment */
2865 /* if the right side is not a literal
2867 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2870 /* if the literal value of the right hand side
2871 is greater than 4 then it is not worth it */
2872 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2875 D(emitcode ("; genPlusIncr",""));
2877 /* if increment >=16 bits in register or direct space */
2878 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2879 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2887 /* If the next instruction is a goto and the goto target
2888 * is < 10 instructions previous to this, we can generate
2889 * jumps straight to that target.
2891 if (ic->next && ic->next->op == GOTO
2892 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2893 && labelRange <= 10)
2895 emitcode (";", "tail increment optimized");
2896 tlbl = IC_LABEL (ic->next);
2901 tlbl = newiTempLabel (NULL);
2904 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2905 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2906 IS_AOP_PREG (IC_RESULT (ic)))
2907 emitcode ("cjne", "%s,#0x00,%05d$",
2908 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2912 emitcode ("clr", "a");
2913 emitcode ("cjne", "a,%s,%05d$",
2914 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2918 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2921 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2922 IS_AOP_PREG (IC_RESULT (ic)))
2923 emitcode ("cjne", "%s,#0x00,%05d$",
2924 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2927 emitcode ("cjne", "a,%s,%05d$",
2928 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2931 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2935 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2936 IS_AOP_PREG (IC_RESULT (ic)))
2937 emitcode ("cjne", "%s,#0x00,%05d$",
2938 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2942 emitcode ("cjne", "a,%s,%05d$",
2943 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2946 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2951 emitcode ("", "%05d$:", tlbl->key + 100);
2956 /* if the sizes are greater than 1 then we cannot */
2957 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2958 AOP_SIZE (IC_LEFT (ic)) > 1)
2961 /* we can if the aops of the left & result match or
2962 if they are in registers and the registers are the
2964 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2969 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2970 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2971 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2977 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2986 /*-----------------------------------------------------------------*/
2987 /* outBitAcc - output a bit in acc */
2988 /*-----------------------------------------------------------------*/
2990 outBitAcc (operand * result)
2992 symbol *tlbl = newiTempLabel (NULL);
2993 /* if the result is a bit */
2994 if (AOP_TYPE (result) == AOP_CRY)
2996 aopPut (AOP (result), "a", 0);
3000 emitcode ("jz", "%05d$", tlbl->key + 100);
3001 emitcode ("mov", "a,%s", one);
3002 emitcode ("", "%05d$:", tlbl->key + 100);
3007 /*-----------------------------------------------------------------*/
3008 /* genPlusBits - generates code for addition of two bits */
3009 /*-----------------------------------------------------------------*/
3011 genPlusBits (iCode * ic)
3013 D(emitcode ("; genPlusBits",""));
3015 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3017 symbol *lbl = newiTempLabel (NULL);
3018 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3019 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3020 emitcode ("cpl", "c");
3021 emitcode ("", "%05d$:", (lbl->key + 100));
3022 outBitC (IC_RESULT (ic));
3026 emitcode ("clr", "a");
3027 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3028 emitcode ("rlc", "a");
3029 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3030 emitcode ("addc", "a,#0x00");
3031 outAcc (IC_RESULT (ic));
3036 /* This is the original version of this code.
3038 * This is being kept around for reference,
3039 * because I am not entirely sure I got it right...
3042 adjustArithmeticResult (iCode * ic)
3044 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3045 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3046 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3047 aopPut (AOP (IC_RESULT (ic)),
3048 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3051 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3052 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3053 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3054 aopPut (AOP (IC_RESULT (ic)),
3055 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3058 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3059 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3060 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3061 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3062 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3065 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3066 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3070 /* This is the pure and virtuous version of this code.
3071 * I'm pretty certain it's right, but not enough to toss the old
3075 adjustArithmeticResult (iCode * ic)
3077 if (opIsGptr (IC_RESULT (ic)) &&
3078 opIsGptr (IC_LEFT (ic)) &&
3079 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3081 aopPut (AOP (IC_RESULT (ic)),
3082 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3086 if (opIsGptr (IC_RESULT (ic)) &&
3087 opIsGptr (IC_RIGHT (ic)) &&
3088 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3090 aopPut (AOP (IC_RESULT (ic)),
3091 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3095 if (opIsGptr (IC_RESULT (ic)) &&
3096 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3097 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3098 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3099 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3102 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3103 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3108 /*-----------------------------------------------------------------*/
3109 /* genPlus - generates code for addition */
3110 /*-----------------------------------------------------------------*/
3112 genPlus (iCode * ic)
3114 int size, offset = 0;
3116 asmop *leftOp, *rightOp;
3118 /* special cases :- */
3120 D(emitcode ("; genPlus",""));
3122 aopOp (IC_LEFT (ic), ic, FALSE);
3123 aopOp (IC_RIGHT (ic), ic, FALSE);
3124 aopOp (IC_RESULT (ic), ic, TRUE);
3126 /* if literal, literal on the right or
3127 if left requires ACC or right is already
3129 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3130 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3131 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3133 operand *t = IC_RIGHT (ic);
3134 IC_RIGHT (ic) = IC_LEFT (ic);
3138 /* if both left & right are in bit
3140 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3141 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3147 /* if left in bit space & right literal */
3148 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3149 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3151 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3152 /* if result in bit space */
3153 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3155 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3156 emitcode ("cpl", "c");
3157 outBitC (IC_RESULT (ic));
3161 size = getDataSize (IC_RESULT (ic));
3164 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3165 emitcode ("addc", "a,#00");
3166 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3172 /* if I can do an increment instead
3173 of add then GOOD for ME */
3174 if (genPlusIncr (ic) == TRUE)
3177 size = getDataSize (IC_RESULT (ic));
3179 leftOp = AOP(IC_LEFT(ic));
3180 rightOp = AOP(IC_RIGHT(ic));
3185 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3187 emitcode("mov", "b,a");
3188 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3189 emitcode("xch", "a,b");
3190 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3191 emitcode (add, "a,b");
3193 else if (aopGetUsesAcc (leftOp, offset))
3195 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3196 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3200 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3201 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3203 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3204 add = "addc"; /* further adds must propagate carry */
3207 adjustArithmeticResult (ic);
3210 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3211 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3212 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3215 /*-----------------------------------------------------------------*/
3216 /* genMinusDec :- does subtraction with deccrement if possible */
3217 /*-----------------------------------------------------------------*/
3219 genMinusDec (iCode * ic)
3221 unsigned int icount;
3222 unsigned int size = getDataSize (IC_RESULT (ic));
3224 /* will try to generate an increment */
3225 /* if the right side is not a literal
3227 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3230 /* if the literal value of the right hand side
3231 is greater than 4 then it is not worth it */
3232 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3235 D(emitcode ("; genMinusDec",""));
3237 /* if decrement >=16 bits in register or direct space */
3238 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3239 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3247 /* If the next instruction is a goto and the goto target
3248 * is <= 10 instructions previous to this, we can generate
3249 * jumps straight to that target.
3251 if (ic->next && ic->next->op == GOTO
3252 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3253 && labelRange <= 10)
3255 emitcode (";", "tail decrement optimized");
3256 tlbl = IC_LABEL (ic->next);
3261 tlbl = newiTempLabel (NULL);
3265 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3266 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3267 IS_AOP_PREG (IC_RESULT (ic)))
3268 emitcode ("cjne", "%s,#0xff,%05d$"
3269 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3273 emitcode ("mov", "a,#0xff");
3274 emitcode ("cjne", "a,%s,%05d$"
3275 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3278 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3281 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3282 IS_AOP_PREG (IC_RESULT (ic)))
3283 emitcode ("cjne", "%s,#0xff,%05d$"
3284 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3288 emitcode ("cjne", "a,%s,%05d$"
3289 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3292 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3296 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3297 IS_AOP_PREG (IC_RESULT (ic)))
3298 emitcode ("cjne", "%s,#0xff,%05d$"
3299 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3303 emitcode ("cjne", "a,%s,%05d$"
3304 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3307 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3311 emitcode ("", "%05d$:", tlbl->key + 100);
3316 /* if the sizes are greater than 1 then we cannot */
3317 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3318 AOP_SIZE (IC_LEFT (ic)) > 1)
3321 /* we can if the aops of the left & result match or
3322 if they are in registers and the registers are the
3324 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3328 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3336 /*-----------------------------------------------------------------*/
3337 /* addSign - complete with sign */
3338 /*-----------------------------------------------------------------*/
3340 addSign (operand * result, int offset, int sign)
3342 int size = (getDataSize (result) - offset);
3347 emitcode ("rlc", "a");
3348 emitcode ("subb", "a,acc");
3350 aopPut (AOP (result), "a", offset++);
3354 aopPut (AOP (result), zero, offset++);
3358 /*-----------------------------------------------------------------*/
3359 /* genMinusBits - generates code for subtraction of two bits */
3360 /*-----------------------------------------------------------------*/
3362 genMinusBits (iCode * ic)
3364 symbol *lbl = newiTempLabel (NULL);
3366 D(emitcode ("; genMinusBits",""));
3368 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3370 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3371 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3372 emitcode ("cpl", "c");
3373 emitcode ("", "%05d$:", (lbl->key + 100));
3374 outBitC (IC_RESULT (ic));
3378 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3379 emitcode ("subb", "a,acc");
3380 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3381 emitcode ("inc", "a");
3382 emitcode ("", "%05d$:", (lbl->key + 100));
3383 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3384 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3388 /*-----------------------------------------------------------------*/
3389 /* genMinus - generates code for subtraction */
3390 /*-----------------------------------------------------------------*/
3392 genMinus (iCode * ic)
3394 int size, offset = 0;
3396 D(emitcode ("; genMinus",""));
3398 aopOp (IC_LEFT (ic), ic, FALSE);
3399 aopOp (IC_RIGHT (ic), ic, FALSE);
3400 aopOp (IC_RESULT (ic), ic, TRUE);
3402 /* special cases :- */
3403 /* if both left & right are in bit space */
3404 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3405 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3411 /* if I can do an decrement instead
3412 of subtract then GOOD for ME */
3413 if (genMinusDec (ic) == TRUE)
3416 size = getDataSize (IC_RESULT (ic));
3418 /* if literal, add a,#-lit, else normal subb */
3419 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3421 unsigned long lit = 0L;
3423 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3428 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3429 /* first add without previous c */
3431 if (!size && lit==-1) {
3432 emitcode ("dec", "a");
3434 emitcode ("add", "a,#0x%02x",
3435 (unsigned int) (lit & 0x0FFL));
3438 emitcode ("addc", "a,#0x%02x",
3439 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3441 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3446 asmop *leftOp, *rightOp;
3448 leftOp = AOP(IC_LEFT(ic));
3449 rightOp = AOP(IC_RIGHT(ic));
3453 if (aopGetUsesAcc(rightOp, offset)) {
3454 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3455 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3457 emitcode( "setb", "c");
3459 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3460 emitcode("cpl", "a");
3462 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3465 emitcode ("subb", "a,%s",
3466 aopGet(rightOp, offset, FALSE, TRUE));
3469 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3474 adjustArithmeticResult (ic);
3477 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3478 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3479 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3483 /*-----------------------------------------------------------------*/
3484 /* genMultbits :- multiplication of bits */
3485 /*-----------------------------------------------------------------*/
3487 genMultbits (operand * left,
3491 D(emitcode ("; genMultbits",""));
3493 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3494 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3499 /*-----------------------------------------------------------------*/
3500 /* genMultOneByte : 8*8=8/16 bit multiplication */
3501 /*-----------------------------------------------------------------*/
3503 genMultOneByte (operand * left,
3507 sym_link *opetype = operandType (result);
3509 int size=AOP_SIZE(result);
3511 D(emitcode ("; genMultOneByte",""));
3513 if (size<1 || size>2) {
3514 // this should never happen
3515 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3516 AOP_SIZE(result), __FILE__, lineno);
3520 /* (if two literals: the value is computed before) */
3521 /* if one literal, literal on the right */
3522 if (AOP_TYPE (left) == AOP_LIT)
3527 //emitcode (";", "swapped left and right");
3530 if (SPEC_USIGN(opetype)
3531 // ignore the sign of left and right, what else can we do?
3532 || (SPEC_USIGN(operandType(left)) &&
3533 SPEC_USIGN(operandType(right)))) {
3534 // just an unsigned 8*8=8/16 multiply
3535 //emitcode (";","unsigned");
3536 // TODO: check for accumulator clash between left & right aops?
3537 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3538 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3539 emitcode ("mul", "ab");
3540 aopPut (AOP (result), "a", 0);
3542 aopPut (AOP (result), "b", 1);
3547 // we have to do a signed multiply
3549 //emitcode (";", "signed");
3550 emitcode ("clr", "F0"); // reset sign flag
3551 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3553 lbl=newiTempLabel(NULL);
3554 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3555 // left side is negative, 8-bit two's complement, this fails for -128
3556 emitcode ("setb", "F0"); // set sign flag
3557 emitcode ("cpl", "a");
3558 emitcode ("inc", "a");
3560 emitcode ("", "%05d$:", lbl->key+100);
3563 if (AOP_TYPE(right)==AOP_LIT) {
3564 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3565 /* AND literal negative */
3567 emitcode ("cpl", "F0"); // complement sign flag
3568 emitcode ("mov", "b,#0x%02x", -val);
3570 emitcode ("mov", "b,#0x%02x", val);
3573 lbl=newiTempLabel(NULL);
3574 emitcode ("mov", "b,a");
3575 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3576 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3577 // right side is negative, 8-bit two's complement
3578 emitcode ("cpl", "F0"); // complement sign flag
3579 emitcode ("cpl", "a");
3580 emitcode ("inc", "a");
3581 emitcode ("", "%05d$:", lbl->key+100);
3583 emitcode ("mul", "ab");
3585 lbl=newiTempLabel(NULL);
3586 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3587 // only ONE op was negative, we have to do a 8/16-bit two's complement
3588 emitcode ("cpl", "a"); // lsb
3590 emitcode ("inc", "a");
3592 emitcode ("add", "a,#1");
3593 emitcode ("xch", "a,b");
3594 emitcode ("cpl", "a"); // msb
3595 emitcode ("addc", "a,#0");
3596 emitcode ("xch", "a,b");
3599 emitcode ("", "%05d$:", lbl->key+100);
3600 aopPut (AOP (result), "a", 0);
3602 aopPut (AOP (result), "b", 1);
3606 /*-----------------------------------------------------------------*/
3607 /* genMult - generates code for multiplication */
3608 /*-----------------------------------------------------------------*/
3610 genMult (iCode * ic)
3612 operand *left = IC_LEFT (ic);
3613 operand *right = IC_RIGHT (ic);
3614 operand *result = IC_RESULT (ic);
3616 D(emitcode ("; genMult",""));
3618 /* assign the amsops */
3619 aopOp (left, ic, FALSE);
3620 aopOp (right, ic, FALSE);
3621 aopOp (result, ic, TRUE);
3623 /* special cases first */
3625 if (AOP_TYPE (left) == AOP_CRY &&
3626 AOP_TYPE (right) == AOP_CRY)
3628 genMultbits (left, right, result);
3632 /* if both are of size == 1 */
3633 #if 0 // one of them can be a sloc shared with the result
3634 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3636 if (getSize(operandType(left)) == 1 &&
3637 getSize(operandType(right)) == 1)
3640 genMultOneByte (left, right, result);
3644 /* should have been converted to function call */
3645 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3646 getSize(OP_SYMBOL(right)->type));
3650 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3651 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3652 freeAsmop (result, NULL, ic, TRUE);
3655 /*-----------------------------------------------------------------*/
3656 /* genDivbits :- division of bits */
3657 /*-----------------------------------------------------------------*/
3659 genDivbits (operand * left,
3666 D(emitcode ("; genDivbits",""));
3668 /* the result must be bit */
3669 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3670 l = aopGet (AOP (left), 0, FALSE, FALSE);
3674 emitcode ("div", "ab");
3675 emitcode ("rrc", "a");
3676 aopPut (AOP (result), "c", 0);
3679 /*-----------------------------------------------------------------*/
3680 /* genDivOneByte : 8 bit division */
3681 /*-----------------------------------------------------------------*/
3683 genDivOneByte (operand * left,
3687 sym_link *opetype = operandType (result);
3692 D(emitcode ("; genDivOneByte",""));
3694 size = AOP_SIZE (result) - 1;
3696 /* signed or unsigned */
3697 if (SPEC_USIGN (opetype))
3699 /* unsigned is easy */
3700 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3701 l = aopGet (AOP (left), 0, FALSE, FALSE);
3703 emitcode ("div", "ab");
3704 aopPut (AOP (result), "a", 0);
3706 aopPut (AOP (result), zero, offset++);
3710 /* signed is a little bit more difficult */
3712 /* save the signs of the operands */
3713 l = aopGet (AOP (left), 0, FALSE, FALSE);
3715 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3716 emitcode ("push", "acc"); /* save it on the stack */
3718 /* now sign adjust for both left & right */
3719 l = aopGet (AOP (right), 0, FALSE, FALSE);
3721 lbl = newiTempLabel (NULL);
3722 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3723 emitcode ("cpl", "a");
3724 emitcode ("inc", "a");
3725 emitcode ("", "%05d$:", (lbl->key + 100));
3726 emitcode ("mov", "b,a");
3728 /* sign adjust left side */
3729 l = aopGet (AOP (left), 0, FALSE, FALSE);
3732 lbl = newiTempLabel (NULL);
3733 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3734 emitcode ("cpl", "a");
3735 emitcode ("inc", "a");
3736 emitcode ("", "%05d$:", (lbl->key + 100));
3738 /* now the division */
3739 emitcode ("div", "ab");
3740 /* we are interested in the lower order
3742 emitcode ("mov", "b,a");
3743 lbl = newiTempLabel (NULL);
3744 emitcode ("pop", "acc");
3745 /* if there was an over flow we don't
3746 adjust the sign of the result */
3747 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3748 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3750 emitcode ("clr", "a");
3751 emitcode ("subb", "a,b");
3752 emitcode ("mov", "b,a");
3753 emitcode ("", "%05d$:", (lbl->key + 100));
3755 /* now we are done */
3756 aopPut (AOP (result), "b", 0);
3759 emitcode ("mov", "c,b.7");
3760 emitcode ("subb", "a,acc");
3763 aopPut (AOP (result), "a", offset++);
3767 /*-----------------------------------------------------------------*/
3768 /* genDiv - generates code for division */
3769 /*-----------------------------------------------------------------*/
3773 operand *left = IC_LEFT (ic);
3774 operand *right = IC_RIGHT (ic);
3775 operand *result = IC_RESULT (ic);
3777 D(emitcode ("; genDiv",""));
3779 /* assign the amsops */
3780 aopOp (left, ic, FALSE);
3781 aopOp (right, ic, FALSE);
3782 aopOp (result, ic, TRUE);
3784 /* special cases first */
3786 if (AOP_TYPE (left) == AOP_CRY &&
3787 AOP_TYPE (right) == AOP_CRY)
3789 genDivbits (left, right, result);
3793 /* if both are of size == 1 */
3794 if (AOP_SIZE (left) == 1 &&
3795 AOP_SIZE (right) == 1)
3797 genDivOneByte (left, right, result);
3801 /* should have been converted to function call */
3804 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3805 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3806 freeAsmop (result, NULL, ic, TRUE);
3809 /*-----------------------------------------------------------------*/
3810 /* genModbits :- modulus of bits */
3811 /*-----------------------------------------------------------------*/
3813 genModbits (operand * left,
3820 D(emitcode ("; genModbits",""));
3822 /* the result must be bit */
3823 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3824 l = aopGet (AOP (left), 0, FALSE, FALSE);
3828 emitcode ("div", "ab");
3829 emitcode ("mov", "a,b");
3830 emitcode ("rrc", "a");
3831 aopPut (AOP (result), "c", 0);
3834 /*-----------------------------------------------------------------*/
3835 /* genModOneByte : 8 bit modulus */
3836 /*-----------------------------------------------------------------*/
3838 genModOneByte (operand * left,
3842 sym_link *opetype = operandType (result);
3846 D(emitcode ("; genModOneByte",""));
3848 /* signed or unsigned */
3849 if (SPEC_USIGN (opetype))
3851 /* unsigned is easy */
3852 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3853 l = aopGet (AOP (left), 0, FALSE, FALSE);
3855 emitcode ("div", "ab");
3856 aopPut (AOP (result), "b", 0);
3860 /* signed is a little bit more difficult */
3862 /* save the signs of the operands */
3863 l = aopGet (AOP (left), 0, FALSE, FALSE);
3866 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3867 emitcode ("push", "acc"); /* save it on the stack */
3869 /* now sign adjust for both left & right */
3870 l = aopGet (AOP (right), 0, FALSE, FALSE);
3873 lbl = newiTempLabel (NULL);
3874 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3875 emitcode ("cpl", "a");
3876 emitcode ("inc", "a");
3877 emitcode ("", "%05d$:", (lbl->key + 100));
3878 emitcode ("mov", "b,a");
3880 /* sign adjust left side */
3881 l = aopGet (AOP (left), 0, FALSE, FALSE);
3884 lbl = newiTempLabel (NULL);
3885 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3886 emitcode ("cpl", "a");
3887 emitcode ("inc", "a");
3888 emitcode ("", "%05d$:", (lbl->key + 100));
3890 /* now the multiplication */
3891 emitcode ("div", "ab");
3892 /* we are interested in the lower order
3894 lbl = newiTempLabel (NULL);
3895 emitcode ("pop", "acc");
3896 /* if there was an over flow we don't
3897 adjust the sign of the result */
3898 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3899 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3901 emitcode ("clr", "a");
3902 emitcode ("subb", "a,b");
3903 emitcode ("mov", "b,a");
3904 emitcode ("", "%05d$:", (lbl->key + 100));
3906 /* now we are done */
3907 aopPut (AOP (result), "b", 0);
3911 /*-----------------------------------------------------------------*/
3912 /* genMod - generates code for division */
3913 /*-----------------------------------------------------------------*/
3917 operand *left = IC_LEFT (ic);
3918 operand *right = IC_RIGHT (ic);
3919 operand *result = IC_RESULT (ic);
3921 D(emitcode ("; genMod",""));
3923 /* assign the amsops */
3924 aopOp (left, ic, FALSE);
3925 aopOp (right, ic, FALSE);
3926 aopOp (result, ic, TRUE);
3928 /* special cases first */
3930 if (AOP_TYPE (left) == AOP_CRY &&
3931 AOP_TYPE (right) == AOP_CRY)
3933 genModbits (left, right, result);
3937 /* if both are of size == 1 */
3938 if (AOP_SIZE (left) == 1 &&
3939 AOP_SIZE (right) == 1)
3941 genModOneByte (left, right, result);
3945 /* should have been converted to function call */
3949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3951 freeAsmop (result, NULL, ic, TRUE);
3954 /*-----------------------------------------------------------------*/
3955 /* genIfxJump :- will create a jump depending on the ifx */
3956 /*-----------------------------------------------------------------*/
3958 genIfxJump (iCode * ic, char *jval)
3961 symbol *tlbl = newiTempLabel (NULL);
3964 D(emitcode ("; genIfxJump",""));
3966 /* if true label then we jump if condition
3970 jlbl = IC_TRUE (ic);
3971 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3972 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3976 /* false label is present */
3977 jlbl = IC_FALSE (ic);
3978 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3979 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3981 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3982 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3984 emitcode (inst, "%05d$", tlbl->key + 100);
3985 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3986 emitcode ("", "%05d$:", tlbl->key + 100);
3988 /* mark the icode as generated */
3992 /*-----------------------------------------------------------------*/
3993 /* genCmp :- greater or less than comparison */
3994 /*-----------------------------------------------------------------*/
3996 genCmp (operand * left, operand * right,
3997 operand * result, iCode * ifx, int sign, iCode *ic)
3999 int size, offset = 0;
4000 unsigned long lit = 0L;
4002 D(emitcode ("; genCmp",""));
4004 /* if left & right are bit variables */
4005 if (AOP_TYPE (left) == AOP_CRY &&
4006 AOP_TYPE (right) == AOP_CRY)
4008 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4009 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4013 /* subtract right from left if at the
4014 end the carry flag is set then we know that
4015 left is greater than right */
4016 size = max (AOP_SIZE (left), AOP_SIZE (right));
4018 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4019 if ((size == 1) && !sign &&
4020 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4022 symbol *lbl = newiTempLabel (NULL);
4023 emitcode ("cjne", "%s,%s,%05d$",
4024 aopGet (AOP (left), offset, FALSE, FALSE),
4025 aopGet (AOP (right), offset, FALSE, FALSE),
4027 emitcode ("", "%05d$:", lbl->key + 100);
4031 if (AOP_TYPE (right) == AOP_LIT)
4033 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4034 /* optimize if(x < 0) or if(x >= 0) */
4043 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4044 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4046 genIfxJump (ifx, "acc.7");
4050 emitcode ("rlc", "a");
4058 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4059 if (sign && size == 0)
4061 emitcode ("xrl", "a,#0x80");
4062 if (AOP_TYPE (right) == AOP_LIT)
4064 unsigned long lit = (unsigned long)
4065 floatFromVal (AOP (right)->aopu.aop_lit);
4066 emitcode ("subb", "a,#0x%02x",
4067 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4071 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4072 emitcode ("xrl", "b,#0x80");
4073 emitcode ("subb", "a,b");
4077 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4083 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4084 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4085 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4091 /* if the result is used in the next
4092 ifx conditional branch then generate
4093 code a little differently */
4095 genIfxJump (ifx, "c");
4098 /* leave the result in acc */
4102 /*-----------------------------------------------------------------*/
4103 /* genCmpGt :- greater than comparison */
4104 /*-----------------------------------------------------------------*/
4106 genCmpGt (iCode * ic, iCode * ifx)
4108 operand *left, *right, *result;
4109 sym_link *letype, *retype;
4112 D(emitcode ("; genCmpGt",""));
4114 left = IC_LEFT (ic);
4115 right = IC_RIGHT (ic);
4116 result = IC_RESULT (ic);
4118 letype = getSpec (operandType (left));
4119 retype = getSpec (operandType (right));
4120 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4121 /* assign the amsops */
4122 aopOp (left, ic, FALSE);
4123 aopOp (right, ic, FALSE);
4124 aopOp (result, ic, TRUE);
4126 genCmp (right, left, result, ifx, sign,ic);
4128 freeAsmop (result, NULL, ic, TRUE);
4131 /*-----------------------------------------------------------------*/
4132 /* genCmpLt - less than comparisons */
4133 /*-----------------------------------------------------------------*/
4135 genCmpLt (iCode * ic, iCode * ifx)
4137 operand *left, *right, *result;
4138 sym_link *letype, *retype;
4141 D(emitcode ("; genCmpLt",""));
4143 left = IC_LEFT (ic);
4144 right = IC_RIGHT (ic);
4145 result = IC_RESULT (ic);
4147 letype = getSpec (operandType (left));
4148 retype = getSpec (operandType (right));
4149 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4151 /* assign the amsops */
4152 aopOp (left, ic, FALSE);
4153 aopOp (right, ic, FALSE);
4154 aopOp (result, ic, TRUE);
4156 genCmp (left, right, result, ifx, sign,ic);
4158 freeAsmop (result, NULL, ic, TRUE);
4161 /*-----------------------------------------------------------------*/
4162 /* gencjneshort - compare and jump if not equal */
4163 /*-----------------------------------------------------------------*/
4165 gencjneshort (operand * left, operand * right, symbol * lbl)
4167 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4169 unsigned long lit = 0L;
4171 /* if the left side is a literal or
4172 if the right is in a pointer register and left
4174 if ((AOP_TYPE (left) == AOP_LIT) ||
4175 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4181 if (AOP_TYPE (right) == AOP_LIT)
4182 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4184 /* if the right side is a literal then anything goes */
4185 if (AOP_TYPE (right) == AOP_LIT &&
4186 AOP_TYPE (left) != AOP_DIR)
4190 emitcode ("cjne", "%s,%s,%05d$",
4191 aopGet (AOP (left), offset, FALSE, FALSE),
4192 aopGet (AOP (right), offset, FALSE, FALSE),
4198 /* if the right side is in a register or in direct space or
4199 if the left is a pointer register & right is not */
4200 else if (AOP_TYPE (right) == AOP_REG ||
4201 AOP_TYPE (right) == AOP_DIR ||
4202 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4203 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4207 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4208 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4209 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4210 emitcode ("jnz", "%05d$", lbl->key + 100);
4212 emitcode ("cjne", "a,%s,%05d$",
4213 aopGet (AOP (right), offset, FALSE, TRUE),
4220 /* right is a pointer reg need both a & b */
4223 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4224 if (strcmp (l, "b"))
4225 emitcode ("mov", "b,%s", l);
4226 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4227 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4233 /*-----------------------------------------------------------------*/
4234 /* gencjne - compare and jump if not equal */
4235 /*-----------------------------------------------------------------*/
4237 gencjne (operand * left, operand * right, symbol * lbl)
4239 symbol *tlbl = newiTempLabel (NULL);
4241 gencjneshort (left, right, lbl);
4243 emitcode ("mov", "a,%s", one);
4244 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4245 emitcode ("", "%05d$:", lbl->key + 100);
4246 emitcode ("clr", "a");
4247 emitcode ("", "%05d$:", tlbl->key + 100);
4250 /*-----------------------------------------------------------------*/
4251 /* genCmpEq - generates code for equal to */
4252 /*-----------------------------------------------------------------*/
4254 genCmpEq (iCode * ic, iCode * ifx)
4256 operand *left, *right, *result;
4258 D(emitcode ("; genCmpEq",""));
4260 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4261 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4262 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4264 /* if literal, literal on the right or
4265 if the right is in a pointer register and left
4267 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4268 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4270 operand *t = IC_RIGHT (ic);
4271 IC_RIGHT (ic) = IC_LEFT (ic);
4275 if (ifx && !AOP_SIZE (result))
4278 /* if they are both bit variables */
4279 if (AOP_TYPE (left) == AOP_CRY &&
4280 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4282 if (AOP_TYPE (right) == AOP_LIT)
4284 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4287 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4288 emitcode ("cpl", "c");
4292 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4296 emitcode ("clr", "c");
4298 /* AOP_TYPE(right) == AOP_CRY */
4302 symbol *lbl = newiTempLabel (NULL);
4303 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4304 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4305 emitcode ("cpl", "c");
4306 emitcode ("", "%05d$:", (lbl->key + 100));
4308 /* if true label then we jump if condition
4310 tlbl = newiTempLabel (NULL);
4313 emitcode ("jnc", "%05d$", tlbl->key + 100);
4314 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4318 emitcode ("jc", "%05d$", tlbl->key + 100);
4319 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4321 emitcode ("", "%05d$:", tlbl->key + 100);
4325 tlbl = newiTempLabel (NULL);
4326 gencjneshort (left, right, tlbl);
4329 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4330 emitcode ("", "%05d$:", tlbl->key + 100);
4334 symbol *lbl = newiTempLabel (NULL);
4335 emitcode ("sjmp", "%05d$", lbl->key + 100);
4336 emitcode ("", "%05d$:", tlbl->key + 100);
4337 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4338 emitcode ("", "%05d$:", lbl->key + 100);
4341 /* mark the icode as generated */
4346 /* if they are both bit variables */
4347 if (AOP_TYPE (left) == AOP_CRY &&
4348 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4350 if (AOP_TYPE (right) == AOP_LIT)
4352 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4355 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4356 emitcode ("cpl", "c");
4360 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4364 emitcode ("clr", "c");
4366 /* AOP_TYPE(right) == AOP_CRY */
4370 symbol *lbl = newiTempLabel (NULL);
4371 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4372 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4373 emitcode ("cpl", "c");
4374 emitcode ("", "%05d$:", (lbl->key + 100));
4377 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4384 genIfxJump (ifx, "c");
4387 /* if the result is used in an arithmetic operation
4388 then put the result in place */
4393 gencjne (left, right, newiTempLabel (NULL));
4394 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4396 aopPut (AOP (result), "a", 0);
4401 genIfxJump (ifx, "a");
4404 /* if the result is used in an arithmetic operation
4405 then put the result in place */
4406 if (AOP_TYPE (result) != AOP_CRY)
4408 /* leave the result in acc */
4412 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4413 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4414 freeAsmop (result, NULL, ic, TRUE);
4417 /*-----------------------------------------------------------------*/
4418 /* ifxForOp - returns the icode containing the ifx for operand */
4419 /*-----------------------------------------------------------------*/
4421 ifxForOp (operand * op, iCode * ic)
4423 /* if true symbol then needs to be assigned */
4424 if (IS_TRUE_SYMOP (op))
4427 /* if this has register type condition and
4428 the next instruction is ifx with the same operand
4429 and live to of the operand is upto the ifx only then */
4431 ic->next->op == IFX &&
4432 IC_COND (ic->next)->key == op->key &&
4433 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4439 /*-----------------------------------------------------------------*/
4440 /* hasInc - operand is incremented before any other use */
4441 /*-----------------------------------------------------------------*/
4443 hasInc (operand *op, iCode *ic,int osize)
4445 sym_link *type = operandType(op);
4446 sym_link *retype = getSpec (type);
4447 iCode *lic = ic->next;
4450 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4451 if (!IS_SYMOP(op)) return NULL;
4453 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4454 if (IS_AGGREGATE(type->next)) return NULL;
4455 if (osize != (isize = getSize(type->next))) return NULL;
4458 /* if operand of the form op = op + <sizeof *op> */
4459 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4460 isOperandEqual(IC_RESULT(lic),op) &&
4461 isOperandLiteral(IC_RIGHT(lic)) &&
4462 operandLitValue(IC_RIGHT(lic)) == isize) {
4465 /* if the operand used or deffed */
4466 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4469 /* if GOTO or IFX */
4470 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4476 /*-----------------------------------------------------------------*/
4477 /* genAndOp - for && operation */
4478 /*-----------------------------------------------------------------*/
4480 genAndOp (iCode * ic)
4482 operand *left, *right, *result;
4485 D(emitcode ("; genAndOp",""));
4487 /* note here that && operations that are in an
4488 if statement are taken away by backPatchLabels
4489 only those used in arthmetic operations remain */
4490 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4491 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4492 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4494 /* if both are bit variables */
4495 if (AOP_TYPE (left) == AOP_CRY &&
4496 AOP_TYPE (right) == AOP_CRY)
4498 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4499 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4504 tlbl = newiTempLabel (NULL);
4506 emitcode ("jz", "%05d$", tlbl->key + 100);
4508 emitcode ("", "%05d$:", tlbl->key + 100);
4512 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4513 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4514 freeAsmop (result, NULL, ic, TRUE);
4518 /*-----------------------------------------------------------------*/
4519 /* genOrOp - for || operation */
4520 /*-----------------------------------------------------------------*/
4522 genOrOp (iCode * ic)
4524 operand *left, *right, *result;
4527 D(emitcode ("; genOrOp",""));
4529 /* note here that || operations that are in an
4530 if statement are taken away by backPatchLabels
4531 only those used in arthmetic operations remain */
4532 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4533 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4534 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4536 /* if both are bit variables */
4537 if (AOP_TYPE (left) == AOP_CRY &&
4538 AOP_TYPE (right) == AOP_CRY)
4540 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4541 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4546 tlbl = newiTempLabel (NULL);
4548 emitcode ("jnz", "%05d$", tlbl->key + 100);
4550 emitcode ("", "%05d$:", tlbl->key + 100);
4554 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4555 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4556 freeAsmop (result, NULL, ic, TRUE);
4559 /*-----------------------------------------------------------------*/
4560 /* isLiteralBit - test if lit == 2^n */
4561 /*-----------------------------------------------------------------*/
4563 isLiteralBit (unsigned long lit)
4565 unsigned long pw[32] =
4566 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4567 0x100L, 0x200L, 0x400L, 0x800L,
4568 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4569 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4570 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4571 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4572 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4575 for (idx = 0; idx < 32; idx++)
4581 /*-----------------------------------------------------------------*/
4582 /* continueIfTrue - */
4583 /*-----------------------------------------------------------------*/
4585 continueIfTrue (iCode * ic)
4588 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4592 /*-----------------------------------------------------------------*/
4594 /*-----------------------------------------------------------------*/
4596 jumpIfTrue (iCode * ic)
4599 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4603 /*-----------------------------------------------------------------*/
4604 /* jmpTrueOrFalse - */
4605 /*-----------------------------------------------------------------*/
4607 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4609 // ugly but optimized by peephole
4612 symbol *nlbl = newiTempLabel (NULL);
4613 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4614 emitcode ("", "%05d$:", tlbl->key + 100);
4615 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4616 emitcode ("", "%05d$:", nlbl->key + 100);
4620 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4621 emitcode ("", "%05d$:", tlbl->key + 100);
4626 /*-----------------------------------------------------------------*/
4627 /* genAnd - code for and */
4628 /*-----------------------------------------------------------------*/
4630 genAnd (iCode * ic, iCode * ifx)
4632 operand *left, *right, *result;
4633 int size, offset = 0;
4634 unsigned long lit = 0L;
4638 D(emitcode ("; genAnd",""));
4640 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4641 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4642 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4645 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4647 AOP_TYPE (left), AOP_TYPE (right));
4648 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4650 AOP_SIZE (left), AOP_SIZE (right));
4653 /* if left is a literal & right is not then exchange them */
4654 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4655 AOP_NEEDSACC (left))
4657 operand *tmp = right;
4662 /* if result = right then exchange them */
4663 if (sameRegs (AOP (result), AOP (right)))
4665 operand *tmp = right;
4670 /* if right is bit then exchange them */
4671 if (AOP_TYPE (right) == AOP_CRY &&
4672 AOP_TYPE (left) != AOP_CRY)
4674 operand *tmp = right;
4678 if (AOP_TYPE (right) == AOP_LIT)
4679 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4681 size = AOP_SIZE (result);
4684 // result = bit & yy;
4685 if (AOP_TYPE (left) == AOP_CRY)
4687 // c = bit & literal;
4688 if (AOP_TYPE (right) == AOP_LIT)
4692 if (size && sameRegs (AOP (result), AOP (left)))
4695 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4700 if (size && (AOP_TYPE (result) == AOP_CRY))
4702 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4705 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4710 emitcode ("clr", "c");
4715 if (AOP_TYPE (right) == AOP_CRY)
4718 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4719 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4724 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4726 emitcode ("rrc", "a");
4727 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4735 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4736 genIfxJump (ifx, "c");
4740 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4741 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4742 if ((AOP_TYPE (right) == AOP_LIT) &&
4743 (AOP_TYPE (result) == AOP_CRY) &&
4744 (AOP_TYPE (left) != AOP_CRY))
4746 int posbit = isLiteralBit (lit);
4751 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4754 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4760 sprintf (buffer, "acc.%d", posbit & 0x07);
4761 genIfxJump (ifx, buffer);
4768 symbol *tlbl = newiTempLabel (NULL);
4769 int sizel = AOP_SIZE (left);
4771 emitcode ("setb", "c");
4774 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4776 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4778 if ((posbit = isLiteralBit (bytelit)) != 0)
4779 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4782 if (bytelit != 0x0FFL)
4783 emitcode ("anl", "a,%s",
4784 aopGet (AOP (right), offset, FALSE, TRUE));
4785 emitcode ("jnz", "%05d$", tlbl->key + 100);
4790 // bit = left & literal
4793 emitcode ("clr", "c");
4794 emitcode ("", "%05d$:", tlbl->key + 100);
4796 // if(left & literal)
4800 jmpTrueOrFalse (ifx, tlbl);
4808 /* if left is same as result */
4809 if (sameRegs (AOP (result), AOP (left)))
4811 for (; size--; offset++)
4813 if (AOP_TYPE (right) == AOP_LIT)
4815 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4817 else if (bytelit == 0)
4818 aopPut (AOP (result), zero, offset);
4819 else if (IS_AOP_PREG (result))
4821 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4822 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4823 aopPut (AOP (result), "a", offset);
4826 emitcode ("anl", "%s,%s",
4827 aopGet (AOP (left), offset, FALSE, TRUE),
4828 aopGet (AOP (right), offset, FALSE, FALSE));
4832 if (AOP_TYPE (left) == AOP_ACC)
4833 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4836 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4837 if (IS_AOP_PREG (result))
4839 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4840 aopPut (AOP (result), "a", offset);
4844 emitcode ("anl", "%s,a",
4845 aopGet (AOP (left), offset, FALSE, TRUE));
4852 // left & result in different registers
4853 if (AOP_TYPE (result) == AOP_CRY)
4856 // if(size), result in bit
4857 // if(!size && ifx), conditional oper: if(left & right)
4858 symbol *tlbl = newiTempLabel (NULL);
4859 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4861 emitcode ("setb", "c");
4864 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4865 emitcode ("anl", "a,%s",
4866 aopGet (AOP (right), offset, FALSE, FALSE));
4868 if (AOP_TYPE(left)==AOP_ACC) {
4869 emitcode("mov", "b,a");
4870 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4871 emitcode("anl", "a,b");
4873 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4874 emitcode ("anl", "a,%s",
4875 aopGet (AOP (left), offset, FALSE, FALSE));
4878 emitcode ("jnz", "%05d$", tlbl->key + 100);
4884 emitcode ("", "%05d$:", tlbl->key + 100);
4888 jmpTrueOrFalse (ifx, tlbl);
4892 for (; (size--); offset++)
4895 // result = left & right
4896 if (AOP_TYPE (right) == AOP_LIT)
4898 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4900 aopPut (AOP (result),
4901 aopGet (AOP (left), offset, FALSE, FALSE),
4905 else if (bytelit == 0)
4907 aopPut (AOP (result), zero, offset);
4911 // faster than result <- left, anl result,right
4912 // and better if result is SFR
4913 if (AOP_TYPE (left) == AOP_ACC)
4914 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4917 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4918 emitcode ("anl", "a,%s",
4919 aopGet (AOP (left), offset, FALSE, FALSE));
4921 aopPut (AOP (result), "a", offset);
4927 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4928 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4929 freeAsmop (result, NULL, ic, TRUE);
4932 /*-----------------------------------------------------------------*/
4933 /* genOr - code for or */
4934 /*-----------------------------------------------------------------*/
4936 genOr (iCode * ic, iCode * ifx)
4938 operand *left, *right, *result;
4939 int size, offset = 0;
4940 unsigned long lit = 0L;
4942 D(emitcode ("; genOr",""));
4944 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4945 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4946 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4949 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4951 AOP_TYPE (left), AOP_TYPE (right));
4952 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4954 AOP_SIZE (left), AOP_SIZE (right));
4957 /* if left is a literal & right is not then exchange them */
4958 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4959 AOP_NEEDSACC (left))
4961 operand *tmp = right;
4966 /* if result = right then exchange them */
4967 if (sameRegs (AOP (result), AOP (right)))
4969 operand *tmp = right;
4974 /* if right is bit then exchange them */
4975 if (AOP_TYPE (right) == AOP_CRY &&
4976 AOP_TYPE (left) != AOP_CRY)
4978 operand *tmp = right;
4982 if (AOP_TYPE (right) == AOP_LIT)
4983 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4985 size = AOP_SIZE (result);
4989 if (AOP_TYPE (left) == AOP_CRY)
4991 if (AOP_TYPE (right) == AOP_LIT)
4993 // c = bit | literal;
4996 // lit != 0 => result = 1
4997 if (AOP_TYPE (result) == AOP_CRY)
5000 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5002 continueIfTrue (ifx);
5005 emitcode ("setb", "c");
5009 // lit == 0 => result = left
5010 if (size && sameRegs (AOP (result), AOP (left)))
5012 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5017 if (AOP_TYPE (right) == AOP_CRY)
5020 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5021 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5026 symbol *tlbl = newiTempLabel (NULL);
5027 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5028 emitcode ("setb", "c");
5029 emitcode ("jb", "%s,%05d$",
5030 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5032 emitcode ("jnz", "%05d$", tlbl->key + 100);
5033 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5035 jmpTrueOrFalse (ifx, tlbl);
5041 emitcode ("", "%05d$:", tlbl->key + 100);
5050 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5051 genIfxJump (ifx, "c");
5055 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5056 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5057 if ((AOP_TYPE (right) == AOP_LIT) &&
5058 (AOP_TYPE (result) == AOP_CRY) &&
5059 (AOP_TYPE (left) != AOP_CRY))
5065 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5067 continueIfTrue (ifx);
5072 // lit = 0, result = boolean(left)
5074 emitcode ("setb", "c");
5078 symbol *tlbl = newiTempLabel (NULL);
5079 emitcode ("jnz", "%05d$", tlbl->key + 100);
5081 emitcode ("", "%05d$:", tlbl->key + 100);
5085 genIfxJump (ifx, "a");
5093 /* if left is same as result */
5094 if (sameRegs (AOP (result), AOP (left)))
5096 for (; size--; offset++)
5098 if (AOP_TYPE (right) == AOP_LIT)
5100 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5102 else if (IS_AOP_PREG (left))
5104 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5105 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5106 aopPut (AOP (result), "a", offset);
5109 emitcode ("orl", "%s,%s",
5110 aopGet (AOP (left), offset, FALSE, TRUE),
5111 aopGet (AOP (right), offset, FALSE, FALSE));
5115 if (AOP_TYPE (left) == AOP_ACC)
5116 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5119 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5120 if (IS_AOP_PREG (left))
5122 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5123 aopPut (AOP (result), "a", offset);
5126 emitcode ("orl", "%s,a",
5127 aopGet (AOP (left), offset, FALSE, TRUE));
5134 // left & result in different registers
5135 if (AOP_TYPE (result) == AOP_CRY)
5138 // if(size), result in bit
5139 // if(!size && ifx), conditional oper: if(left | right)
5140 symbol *tlbl = newiTempLabel (NULL);
5141 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5143 emitcode ("setb", "c");
5146 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5147 emitcode ("orl", "a,%s",
5148 aopGet (AOP (right), offset, FALSE, FALSE));
5150 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5151 emitcode ("orl", "a,%s",
5152 aopGet (AOP (left), offset, FALSE, FALSE));
5154 emitcode ("jnz", "%05d$", tlbl->key + 100);
5160 emitcode ("", "%05d$:", tlbl->key + 100);
5164 jmpTrueOrFalse (ifx, tlbl);
5167 for (; (size--); offset++)
5170 // result = left & right
5171 if (AOP_TYPE (right) == AOP_LIT)
5173 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5175 aopPut (AOP (result),
5176 aopGet (AOP (left), offset, FALSE, FALSE),
5181 // faster than result <- left, anl result,right
5182 // and better if result is SFR
5183 if (AOP_TYPE (left) == AOP_ACC)
5184 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5187 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5188 emitcode ("orl", "a,%s",
5189 aopGet (AOP (left), offset, FALSE, FALSE));
5191 aopPut (AOP (result), "a", offset);
5196 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5197 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5198 freeAsmop (result, NULL, ic, TRUE);
5201 /*-----------------------------------------------------------------*/
5202 /* genXor - code for xclusive or */
5203 /*-----------------------------------------------------------------*/
5205 genXor (iCode * ic, iCode * ifx)
5207 operand *left, *right, *result;
5208 int size, offset = 0;
5209 unsigned long lit = 0L;
5211 D(emitcode ("; genXor",""));
5213 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5214 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5215 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5218 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5220 AOP_TYPE (left), AOP_TYPE (right));
5221 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5223 AOP_SIZE (left), AOP_SIZE (right));
5226 /* if left is a literal & right is not ||
5227 if left needs acc & right does not */
5228 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5229 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5231 operand *tmp = right;
5236 /* if result = right then exchange them */
5237 if (sameRegs (AOP (result), AOP (right)))
5239 operand *tmp = right;
5244 /* if right is bit then exchange them */
5245 if (AOP_TYPE (right) == AOP_CRY &&
5246 AOP_TYPE (left) != AOP_CRY)
5248 operand *tmp = right;
5252 if (AOP_TYPE (right) == AOP_LIT)
5253 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5255 size = AOP_SIZE (result);
5259 if (AOP_TYPE (left) == AOP_CRY)
5261 if (AOP_TYPE (right) == AOP_LIT)
5263 // c = bit & literal;
5266 // lit>>1 != 0 => result = 1
5267 if (AOP_TYPE (result) == AOP_CRY)
5270 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5272 continueIfTrue (ifx);
5275 emitcode ("setb", "c");
5282 // lit == 0, result = left
5283 if (size && sameRegs (AOP (result), AOP (left)))
5285 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5289 // lit == 1, result = not(left)
5290 if (size && sameRegs (AOP (result), AOP (left)))
5292 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5297 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5298 emitcode ("cpl", "c");
5307 symbol *tlbl = newiTempLabel (NULL);
5308 if (AOP_TYPE (right) == AOP_CRY)
5311 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5315 int sizer = AOP_SIZE (right);
5317 // if val>>1 != 0, result = 1
5318 emitcode ("setb", "c");
5321 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5323 // test the msb of the lsb
5324 emitcode ("anl", "a,#0xfe");
5325 emitcode ("jnz", "%05d$", tlbl->key + 100);
5329 emitcode ("rrc", "a");
5331 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5332 emitcode ("cpl", "c");
5333 emitcode ("", "%05d$:", (tlbl->key + 100));
5340 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5341 genIfxJump (ifx, "c");
5345 if (sameRegs (AOP (result), AOP (left)))
5347 /* if left is same as result */
5348 for (; size--; offset++)
5350 if (AOP_TYPE (right) == AOP_LIT)
5352 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5354 else if (IS_AOP_PREG (left))
5356 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5357 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5358 aopPut (AOP (result), "a", offset);
5361 emitcode ("xrl", "%s,%s",
5362 aopGet (AOP (left), offset, FALSE, TRUE),
5363 aopGet (AOP (right), offset, FALSE, FALSE));
5367 if (AOP_TYPE (left) == AOP_ACC)
5368 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5371 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5372 if (IS_AOP_PREG (left))
5374 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5375 aopPut (AOP (result), "a", offset);
5378 emitcode ("xrl", "%s,a",
5379 aopGet (AOP (left), offset, FALSE, TRUE));
5386 // left & result in different registers
5387 if (AOP_TYPE (result) == AOP_CRY)
5390 // if(size), result in bit
5391 // if(!size && ifx), conditional oper: if(left ^ right)
5392 symbol *tlbl = newiTempLabel (NULL);
5393 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5395 emitcode ("setb", "c");
5398 if ((AOP_TYPE (right) == AOP_LIT) &&
5399 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5401 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5405 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5406 emitcode ("xrl", "a,%s",
5407 aopGet (AOP (right), offset, FALSE, FALSE));
5409 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5410 emitcode ("xrl", "a,%s",
5411 aopGet (AOP (left), offset, FALSE, FALSE));
5414 emitcode ("jnz", "%05d$", tlbl->key + 100);
5420 emitcode ("", "%05d$:", tlbl->key + 100);
5424 jmpTrueOrFalse (ifx, tlbl);
5427 for (; (size--); offset++)
5430 // result = left & right
5431 if (AOP_TYPE (right) == AOP_LIT)
5433 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5435 aopPut (AOP (result),
5436 aopGet (AOP (left), offset, FALSE, FALSE),
5441 // faster than result <- left, anl result,right
5442 // and better if result is SFR
5443 if (AOP_TYPE (left) == AOP_ACC)
5444 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5447 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5448 emitcode ("xrl", "a,%s",
5449 aopGet (AOP (left), offset, FALSE, TRUE));
5451 aopPut (AOP (result), "a", offset);
5456 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5457 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5458 freeAsmop (result, NULL, ic, TRUE);
5461 /*-----------------------------------------------------------------*/
5462 /* genInline - write the inline code out */
5463 /*-----------------------------------------------------------------*/
5465 genInline (iCode * ic)
5467 char *buffer, *bp, *bp1;
5469 D(emitcode ("; genInline",""));
5471 _G.inLine += (!options.asmpeep);
5473 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5474 strcpy (buffer, IC_INLINE (ic));
5476 /* emit each line as a code */
5501 /* emitcode("",buffer); */
5502 _G.inLine -= (!options.asmpeep);
5505 /*-----------------------------------------------------------------*/
5506 /* genRRC - rotate right with carry */
5507 /*-----------------------------------------------------------------*/
5511 operand *left, *result;
5512 int size, offset = 0;
5515 D(emitcode ("; genRRC",""));
5517 /* rotate right with carry */
5518 left = IC_LEFT (ic);
5519 result = IC_RESULT (ic);
5520 aopOp (left, ic, FALSE);
5521 aopOp (result, ic, FALSE);
5523 /* move it to the result */
5524 size = AOP_SIZE (result);
5526 if (size == 1) { /* special case for 1 byte */
5527 l = aopGet (AOP (left), offset, FALSE, FALSE);
5529 emitcode ("rr", "a");
5535 l = aopGet (AOP (left), offset, FALSE, FALSE);
5537 emitcode ("rrc", "a");
5538 if (AOP_SIZE (result) > 1)
5539 aopPut (AOP (result), "a", offset--);
5541 /* now we need to put the carry into the
5542 highest order byte of the result */
5543 if (AOP_SIZE (result) > 1)
5545 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5548 emitcode ("mov", "acc.7,c");
5550 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5551 freeAsmop (left, NULL, ic, TRUE);
5552 freeAsmop (result, NULL, ic, TRUE);
5555 /*-----------------------------------------------------------------*/
5556 /* genRLC - generate code for rotate left with carry */
5557 /*-----------------------------------------------------------------*/
5561 operand *left, *result;
5562 int size, offset = 0;
5565 D(emitcode ("; genRLC",""));
5567 /* rotate right with carry */
5568 left = IC_LEFT (ic);
5569 result = IC_RESULT (ic);
5570 aopOp (left, ic, FALSE);
5571 aopOp (result, ic, FALSE);
5573 /* move it to the result */
5574 size = AOP_SIZE (result);
5578 l = aopGet (AOP (left), offset, FALSE, FALSE);
5580 if (size == 0) { /* special case for 1 byte */
5584 emitcode ("add", "a,acc");
5585 if (AOP_SIZE (result) > 1)
5586 aopPut (AOP (result), "a", offset++);
5589 l = aopGet (AOP (left), offset, FALSE, FALSE);
5591 emitcode ("rlc", "a");
5592 if (AOP_SIZE (result) > 1)
5593 aopPut (AOP (result), "a", offset++);
5596 /* now we need to put the carry into the
5597 highest order byte of the result */
5598 if (AOP_SIZE (result) > 1)
5600 l = aopGet (AOP (result), 0, FALSE, FALSE);
5603 emitcode ("mov", "acc.0,c");
5605 aopPut (AOP (result), "a", 0);
5606 freeAsmop (left, NULL, ic, TRUE);
5607 freeAsmop (result, NULL, ic, TRUE);
5610 /*-----------------------------------------------------------------*/
5611 /* genGetHbit - generates code get highest order bit */
5612 /*-----------------------------------------------------------------*/
5614 genGetHbit (iCode * ic)
5616 operand *left, *result;
5618 D(emitcode ("; genGetHbit",""));
5620 left = IC_LEFT (ic);
5621 result = IC_RESULT (ic);
5622 aopOp (left, ic, FALSE);
5623 aopOp (result, ic, FALSE);
5625 /* get the highest order byte into a */
5626 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5627 if (AOP_TYPE (result) == AOP_CRY)
5629 emitcode ("rlc", "a");
5634 emitcode ("rl", "a");
5635 emitcode ("anl", "a,#0x01");
5640 freeAsmop (left, NULL, ic, TRUE);
5641 freeAsmop (result, NULL, ic, TRUE);
5644 /*-----------------------------------------------------------------*/
5645 /* AccRol - rotate left accumulator by known count */
5646 /*-----------------------------------------------------------------*/
5648 AccRol (int shCount)
5650 shCount &= 0x0007; // shCount : 0..7
5657 emitcode ("rl", "a");
5660 emitcode ("rl", "a");
5661 emitcode ("rl", "a");
5664 emitcode ("swap", "a");
5665 emitcode ("rr", "a");
5668 emitcode ("swap", "a");
5671 emitcode ("swap", "a");
5672 emitcode ("rl", "a");
5675 emitcode ("rr", "a");
5676 emitcode ("rr", "a");
5679 emitcode ("rr", "a");
5684 /*-----------------------------------------------------------------*/
5685 /* AccLsh - left shift accumulator by known count */
5686 /*-----------------------------------------------------------------*/
5688 AccLsh (int shCount)
5693 emitcode ("add", "a,acc");
5694 else if (shCount == 2)
5696 emitcode ("add", "a,acc");
5697 emitcode ("add", "a,acc");
5701 /* rotate left accumulator */
5703 /* and kill the lower order bits */
5704 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5709 /*-----------------------------------------------------------------*/
5710 /* AccRsh - right shift accumulator by known count */
5711 /*-----------------------------------------------------------------*/
5713 AccRsh (int shCount)
5720 emitcode ("rrc", "a");
5724 /* rotate right accumulator */
5725 AccRol (8 - shCount);
5726 /* and kill the higher order bits */
5727 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5732 /*-----------------------------------------------------------------*/
5733 /* AccSRsh - signed right shift accumulator by known count */
5734 /*-----------------------------------------------------------------*/
5736 AccSRsh (int shCount)
5743 emitcode ("mov", "c,acc.7");
5744 emitcode ("rrc", "a");
5746 else if (shCount == 2)
5748 emitcode ("mov", "c,acc.7");
5749 emitcode ("rrc", "a");
5750 emitcode ("mov", "c,acc.7");
5751 emitcode ("rrc", "a");
5755 tlbl = newiTempLabel (NULL);
5756 /* rotate right accumulator */
5757 AccRol (8 - shCount);
5758 /* and kill the higher order bits */
5759 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5760 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5761 emitcode ("orl", "a,#0x%02x",
5762 (unsigned char) ~SRMask[shCount]);
5763 emitcode ("", "%05d$:", tlbl->key + 100);
5768 /*-----------------------------------------------------------------*/
5769 /* shiftR1Left2Result - shift right one byte from left to result */
5770 /*-----------------------------------------------------------------*/
5772 shiftR1Left2Result (operand * left, int offl,
5773 operand * result, int offr,
5774 int shCount, int sign)
5776 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5777 /* shift right accumulator */
5782 aopPut (AOP (result), "a", offr);
5785 /*-----------------------------------------------------------------*/
5786 /* shiftL1Left2Result - shift left one byte from left to result */
5787 /*-----------------------------------------------------------------*/
5789 shiftL1Left2Result (operand * left, int offl,
5790 operand * result, int offr, int shCount)
5793 l = aopGet (AOP (left), offl, FALSE, FALSE);
5795 /* shift left accumulator */
5797 aopPut (AOP (result), "a", offr);
5800 /*-----------------------------------------------------------------*/
5801 /* movLeft2Result - move byte from left to result */
5802 /*-----------------------------------------------------------------*/
5804 movLeft2Result (operand * left, int offl,
5805 operand * result, int offr, int sign)
5808 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5810 l = aopGet (AOP (left), offl, FALSE, FALSE);
5812 if (*l == '@' && (IS_AOP_PREG (result)))
5814 emitcode ("mov", "a,%s", l);
5815 aopPut (AOP (result), "a", offr);
5820 aopPut (AOP (result), l, offr);
5823 /* MSB sign in acc.7 ! */
5824 if (getDataSize (left) == offl + 1)
5826 emitcode ("mov", "a,%s", l);
5827 aopPut (AOP (result), "a", offr);
5834 /*-----------------------------------------------------------------*/
5835 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5836 /*-----------------------------------------------------------------*/
5840 emitcode ("rrc", "a");
5841 emitcode ("xch", "a,%s", x);
5842 emitcode ("rrc", "a");
5843 emitcode ("xch", "a,%s", x);
5846 /*-----------------------------------------------------------------*/
5847 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5848 /*-----------------------------------------------------------------*/
5852 emitcode ("xch", "a,%s", x);
5853 emitcode ("rlc", "a");
5854 emitcode ("xch", "a,%s", x);
5855 emitcode ("rlc", "a");
5858 /*-----------------------------------------------------------------*/
5859 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5860 /*-----------------------------------------------------------------*/
5864 emitcode ("xch", "a,%s", x);
5865 emitcode ("add", "a,acc");
5866 emitcode ("xch", "a,%s", x);
5867 emitcode ("rlc", "a");
5870 /*-----------------------------------------------------------------*/
5871 /* AccAXLsh - left shift a:x by known count (0..7) */
5872 /*-----------------------------------------------------------------*/
5874 AccAXLsh (char *x, int shCount)
5889 case 5: // AAAAABBB:CCCCCDDD
5891 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5893 emitcode ("anl", "a,#0x%02x",
5894 SLMask[shCount]); // BBB00000:CCCCCDDD
5896 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5898 AccRol (shCount); // DDDCCCCC:BBB00000
5900 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5902 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5904 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5906 emitcode ("anl", "a,#0x%02x",
5907 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5909 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5911 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5914 case 6: // AAAAAABB:CCCCCCDD
5915 emitcode ("anl", "a,#0x%02x",
5916 SRMask[shCount]); // 000000BB:CCCCCCDD
5917 emitcode ("mov", "c,acc.0"); // c = B
5918 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5920 AccAXRrl1 (x); // BCCCCCCD:D000000B
5921 AccAXRrl1 (x); // BBCCCCCC:DD000000
5923 emitcode("rrc","a");
5924 emitcode("xch","a,%s", x);
5925 emitcode("rrc","a");
5926 emitcode("mov","c,acc.0"); //<< get correct bit
5927 emitcode("xch","a,%s", x);
5929 emitcode("rrc","a");
5930 emitcode("xch","a,%s", x);
5931 emitcode("rrc","a");
5932 emitcode("xch","a,%s", x);
5935 case 7: // a:x <<= 7
5937 emitcode ("anl", "a,#0x%02x",
5938 SRMask[shCount]); // 0000000B:CCCCCCCD
5940 emitcode ("mov", "c,acc.0"); // c = B
5942 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5944 AccAXRrl1 (x); // BCCCCCCC:D0000000
5952 /*-----------------------------------------------------------------*/
5953 /* AccAXRsh - right shift a:x known count (0..7) */
5954 /*-----------------------------------------------------------------*/
5956 AccAXRsh (char *x, int shCount)
5964 AccAXRrl1 (x); // 0->a:x
5969 AccAXRrl1 (x); // 0->a:x
5972 AccAXRrl1 (x); // 0->a:x
5977 case 5: // AAAAABBB:CCCCCDDD = a:x
5979 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5981 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5983 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5985 emitcode ("anl", "a,#0x%02x",
5986 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5988 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5990 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5992 emitcode ("anl", "a,#0x%02x",
5993 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5995 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5997 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5999 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6002 case 6: // AABBBBBB:CCDDDDDD
6004 emitcode ("mov", "c,acc.7");
6005 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6007 emitcode ("mov", "c,acc.7");
6008 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6010 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6012 emitcode ("anl", "a,#0x%02x",
6013 SRMask[shCount]); // 000000AA:BBBBBBCC
6016 case 7: // ABBBBBBB:CDDDDDDD
6018 emitcode ("mov", "c,acc.7"); // c = A
6020 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6022 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6024 emitcode ("anl", "a,#0x%02x",
6025 SRMask[shCount]); // 0000000A:BBBBBBBC
6033 /*-----------------------------------------------------------------*/
6034 /* AccAXRshS - right shift signed a:x known count (0..7) */
6035 /*-----------------------------------------------------------------*/
6037 AccAXRshS (char *x, int shCount)
6045 emitcode ("mov", "c,acc.7");
6046 AccAXRrl1 (x); // s->a:x
6050 emitcode ("mov", "c,acc.7");
6051 AccAXRrl1 (x); // s->a:x
6053 emitcode ("mov", "c,acc.7");
6054 AccAXRrl1 (x); // s->a:x
6059 case 5: // AAAAABBB:CCCCCDDD = a:x
6061 tlbl = newiTempLabel (NULL);
6062 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6064 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6066 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6068 emitcode ("anl", "a,#0x%02x",
6069 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6071 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6073 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6075 emitcode ("anl", "a,#0x%02x",
6076 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6078 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6080 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6082 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6084 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6085 emitcode ("orl", "a,#0x%02x",
6086 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6088 emitcode ("", "%05d$:", tlbl->key + 100);
6089 break; // SSSSAAAA:BBBCCCCC
6091 case 6: // AABBBBBB:CCDDDDDD
6093 tlbl = newiTempLabel (NULL);
6094 emitcode ("mov", "c,acc.7");
6095 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6097 emitcode ("mov", "c,acc.7");
6098 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6100 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6102 emitcode ("anl", "a,#0x%02x",
6103 SRMask[shCount]); // 000000AA:BBBBBBCC
6105 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6106 emitcode ("orl", "a,#0x%02x",
6107 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6109 emitcode ("", "%05d$:", tlbl->key + 100);
6111 case 7: // ABBBBBBB:CDDDDDDD
6113 tlbl = newiTempLabel (NULL);
6114 emitcode ("mov", "c,acc.7"); // c = A
6116 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6118 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6120 emitcode ("anl", "a,#0x%02x",
6121 SRMask[shCount]); // 0000000A:BBBBBBBC
6123 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6124 emitcode ("orl", "a,#0x%02x",
6125 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6127 emitcode ("", "%05d$:", tlbl->key + 100);
6134 /*-----------------------------------------------------------------*/
6135 /* shiftL2Left2Result - shift left two bytes from left to result */
6136 /*-----------------------------------------------------------------*/
6138 shiftL2Left2Result (operand * left, int offl,
6139 operand * result, int offr, int shCount)
6141 if (sameRegs (AOP (result), AOP (left)) &&
6142 ((offl + MSB16) == offr))
6144 /* don't crash result[offr] */
6145 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6146 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6150 movLeft2Result (left, offl, result, offr, 0);
6151 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6153 /* ax << shCount (x = lsb(result)) */
6154 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6155 aopPut (AOP (result), "a", offr + MSB16);
6159 /*-----------------------------------------------------------------*/
6160 /* shiftR2Left2Result - shift right two bytes from left to result */
6161 /*-----------------------------------------------------------------*/
6163 shiftR2Left2Result (operand * left, int offl,
6164 operand * result, int offr,
6165 int shCount, int sign)
6167 if (sameRegs (AOP (result), AOP (left)) &&
6168 ((offl + MSB16) == offr))
6170 /* don't crash result[offr] */
6171 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6172 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6176 movLeft2Result (left, offl, result, offr, 0);
6177 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6179 /* a:x >> shCount (x = lsb(result)) */
6181 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6183 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6184 if (getDataSize (result) > 1)
6185 aopPut (AOP (result), "a", offr + MSB16);
6188 /*-----------------------------------------------------------------*/
6189 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6190 /*-----------------------------------------------------------------*/
6192 shiftLLeftOrResult (operand * left, int offl,
6193 operand * result, int offr, int shCount)
6195 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6196 /* shift left accumulator */
6198 /* or with result */
6199 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6200 /* back to result */
6201 aopPut (AOP (result), "a", offr);
6204 /*-----------------------------------------------------------------*/
6205 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6206 /*-----------------------------------------------------------------*/
6208 shiftRLeftOrResult (operand * left, int offl,
6209 operand * result, int offr, int shCount)
6211 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6212 /* shift right accumulator */
6214 /* or with result */
6215 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6216 /* back to result */
6217 aopPut (AOP (result), "a", offr);
6220 /*-----------------------------------------------------------------*/
6221 /* genlshOne - left shift a one byte quantity by known count */
6222 /*-----------------------------------------------------------------*/
6224 genlshOne (operand * result, operand * left, int shCount)
6226 D(emitcode ("; genlshOne",""));
6228 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6231 /*-----------------------------------------------------------------*/
6232 /* genlshTwo - left shift two bytes by known amount != 0 */
6233 /*-----------------------------------------------------------------*/
6235 genlshTwo (operand * result, operand * left, int shCount)
6239 D(emitcode ("; genlshTwo",""));
6241 size = getDataSize (result);
6243 /* if shCount >= 8 */
6251 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6253 movLeft2Result (left, LSB, result, MSB16, 0);
6255 aopPut (AOP (result), zero, LSB);
6258 /* 1 <= shCount <= 7 */
6262 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6264 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6268 /*-----------------------------------------------------------------*/
6269 /* shiftLLong - shift left one long from left to result */
6270 /* offl = LSB or MSB16 */
6271 /*-----------------------------------------------------------------*/
6273 shiftLLong (operand * left, operand * result, int offr)
6276 int size = AOP_SIZE (result);
6278 if (size >= LSB + offr)
6280 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6282 emitcode ("add", "a,acc");
6283 if (sameRegs (AOP (left), AOP (result)) &&
6284 size >= MSB16 + offr && offr != LSB)
6285 emitcode ("xch", "a,%s",
6286 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6288 aopPut (AOP (result), "a", LSB + offr);
6291 if (size >= MSB16 + offr)
6293 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6295 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6298 emitcode ("rlc", "a");
6299 if (sameRegs (AOP (left), AOP (result)) &&
6300 size >= MSB24 + offr && offr != LSB)
6301 emitcode ("xch", "a,%s",
6302 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6304 aopPut (AOP (result), "a", MSB16 + offr);
6307 if (size >= MSB24 + offr)
6309 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6311 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6314 emitcode ("rlc", "a");
6315 if (sameRegs (AOP (left), AOP (result)) &&
6316 size >= MSB32 + offr && offr != LSB)
6317 emitcode ("xch", "a,%s",
6318 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6320 aopPut (AOP (result), "a", MSB24 + offr);
6323 if (size > MSB32 + offr)
6325 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6327 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6330 emitcode ("rlc", "a");
6331 aopPut (AOP (result), "a", MSB32 + offr);
6334 aopPut (AOP (result), zero, LSB);
6337 /*-----------------------------------------------------------------*/
6338 /* genlshFour - shift four byte by a known amount != 0 */
6339 /*-----------------------------------------------------------------*/
6341 genlshFour (operand * result, operand * left, int shCount)
6345 D(emitcode ("; genlshFour",""));
6347 size = AOP_SIZE (result);
6349 /* if shifting more that 3 bytes */
6354 /* lowest order of left goes to the highest
6355 order of the destination */
6356 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6358 movLeft2Result (left, LSB, result, MSB32, 0);
6359 aopPut (AOP (result), zero, LSB);
6360 aopPut (AOP (result), zero, MSB16);
6361 aopPut (AOP (result), zero, MSB24);
6365 /* more than two bytes */
6366 else if (shCount >= 16)
6368 /* lower order two bytes goes to higher order two bytes */
6370 /* if some more remaining */
6372 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6375 movLeft2Result (left, MSB16, result, MSB32, 0);
6376 movLeft2Result (left, LSB, result, MSB24, 0);
6378 aopPut (AOP (result), zero, MSB16);
6379 aopPut (AOP (result), zero, LSB);
6383 /* if more than 1 byte */
6384 else if (shCount >= 8)
6386 /* lower order three bytes goes to higher order three bytes */
6391 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6393 movLeft2Result (left, LSB, result, MSB16, 0);
6399 movLeft2Result (left, MSB24, result, MSB32, 0);
6400 movLeft2Result (left, MSB16, result, MSB24, 0);
6401 movLeft2Result (left, LSB, result, MSB16, 0);
6402 aopPut (AOP (result), zero, LSB);
6404 else if (shCount == 1)
6405 shiftLLong (left, result, MSB16);
6408 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6409 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6410 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6411 aopPut (AOP (result), zero, LSB);
6416 /* 1 <= shCount <= 7 */
6417 else if (shCount <= 2)
6419 shiftLLong (left, result, LSB);
6421 shiftLLong (result, result, LSB);
6423 /* 3 <= shCount <= 7, optimize */
6426 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6427 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6428 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6432 /*-----------------------------------------------------------------*/
6433 /* genLeftShiftLiteral - left shifting by known count */
6434 /*-----------------------------------------------------------------*/
6436 genLeftShiftLiteral (operand * left,
6441 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6444 D(emitcode ("; genLeftShiftLiteral",""));
6446 freeAsmop (right, NULL, ic, TRUE);
6448 aopOp (left, ic, FALSE);
6449 aopOp (result, ic, FALSE);
6451 size = getSize (operandType (result));
6454 emitcode ("; shift left ", "result %d, left %d", size,
6458 /* I suppose that the left size >= result size */
6463 movLeft2Result (left, size, result, size, 0);
6467 else if (shCount >= (size * 8))
6469 aopPut (AOP (result), zero, size);
6475 genlshOne (result, left, shCount);
6479 genlshTwo (result, left, shCount);
6483 genlshFour (result, left, shCount);
6486 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6487 "*** ack! mystery literal shift!\n");
6491 freeAsmop (left, NULL, ic, TRUE);
6492 freeAsmop (result, NULL, ic, TRUE);
6495 /*-----------------------------------------------------------------*/
6496 /* genLeftShift - generates code for left shifting */
6497 /*-----------------------------------------------------------------*/
6499 genLeftShift (iCode * ic)
6501 operand *left, *right, *result;
6504 symbol *tlbl, *tlbl1;
6506 D(emitcode ("; genLeftShift",""));
6508 right = IC_RIGHT (ic);
6509 left = IC_LEFT (ic);
6510 result = IC_RESULT (ic);
6512 aopOp (right, ic, FALSE);
6514 /* if the shift count is known then do it
6515 as efficiently as possible */
6516 if (AOP_TYPE (right) == AOP_LIT)
6518 genLeftShiftLiteral (left, right, result, ic);
6522 /* shift count is unknown then we have to form
6523 a loop get the loop count in B : Note: we take
6524 only the lower order byte since shifting
6525 more that 32 bits make no sense anyway, ( the
6526 largest size of an object can be only 32 bits ) */
6528 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6529 emitcode ("inc", "b");
6530 freeAsmop (right, NULL, ic, TRUE);
6531 aopOp (left, ic, FALSE);
6532 aopOp (result, ic, FALSE);
6534 /* now move the left to the result if they are not the
6536 if (!sameRegs (AOP (left), AOP (result)) &&
6537 AOP_SIZE (result) > 1)
6540 size = AOP_SIZE (result);
6544 l = aopGet (AOP (left), offset, FALSE, TRUE);
6545 if (*l == '@' && (IS_AOP_PREG (result)))
6548 emitcode ("mov", "a,%s", l);
6549 aopPut (AOP (result), "a", offset);
6552 aopPut (AOP (result), l, offset);
6557 tlbl = newiTempLabel (NULL);
6558 size = AOP_SIZE (result);
6560 tlbl1 = newiTempLabel (NULL);
6562 /* if it is only one byte then */
6565 symbol *tlbl1 = newiTempLabel (NULL);
6567 l = aopGet (AOP (left), 0, FALSE, FALSE);
6569 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6570 emitcode ("", "%05d$:", tlbl->key + 100);
6571 emitcode ("add", "a,acc");
6572 emitcode ("", "%05d$:", tlbl1->key + 100);
6573 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6574 aopPut (AOP (result), "a", 0);
6578 reAdjustPreg (AOP (result));
6580 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6581 emitcode ("", "%05d$:", tlbl->key + 100);
6582 l = aopGet (AOP (result), offset, FALSE, FALSE);
6584 emitcode ("add", "a,acc");
6585 aopPut (AOP (result), "a", offset++);
6588 l = aopGet (AOP (result), offset, FALSE, FALSE);
6590 emitcode ("rlc", "a");
6591 aopPut (AOP (result), "a", offset++);
6593 reAdjustPreg (AOP (result));
6595 emitcode ("", "%05d$:", tlbl1->key + 100);
6596 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6598 freeAsmop (left, NULL, ic, TRUE);
6599 freeAsmop (result, NULL, ic, TRUE);
6602 /*-----------------------------------------------------------------*/
6603 /* genrshOne - right shift a one byte quantity by known count */
6604 /*-----------------------------------------------------------------*/
6606 genrshOne (operand * result, operand * left,
6607 int shCount, int sign)
6609 D(emitcode ("; genrshOne",""));
6611 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6614 /*-----------------------------------------------------------------*/
6615 /* genrshTwo - right shift two bytes by known amount != 0 */
6616 /*-----------------------------------------------------------------*/
6618 genrshTwo (operand * result, operand * left,
6619 int shCount, int sign)
6621 D(emitcode ("; genrshTwo",""));
6623 /* if shCount >= 8 */
6628 shiftR1Left2Result (left, MSB16, result, LSB,
6631 movLeft2Result (left, MSB16, result, LSB, sign);
6632 addSign (result, MSB16, sign);
6635 /* 1 <= shCount <= 7 */
6637 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6640 /*-----------------------------------------------------------------*/
6641 /* shiftRLong - shift right one long from left to result */
6642 /* offl = LSB or MSB16 */
6643 /*-----------------------------------------------------------------*/
6645 shiftRLong (operand * left, int offl,
6646 operand * result, int sign)
6648 int isSameRegs=sameRegs(AOP(left),AOP(result));
6650 if (isSameRegs && offl>1) {
6651 // we are in big trouble, but this shouldn't happen
6652 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6655 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6660 emitcode ("rlc", "a");
6661 emitcode ("subb", "a,acc");
6663 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6665 aopPut (AOP (result), "a", MSB32);
6666 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6669 aopPut (AOP(result), zero, MSB32);
6674 emitcode ("clr", "c");
6676 emitcode ("mov", "c,acc.7");
6679 emitcode ("rrc", "a");
6681 if (isSameRegs && offl==MSB16) {
6682 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6684 aopPut (AOP (result), "a", MSB32-offl);
6685 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6688 emitcode ("rrc", "a");
6689 if (isSameRegs && offl==1) {
6690 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6692 aopPut (AOP (result), "a", MSB24-offl);
6693 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6695 emitcode ("rrc", "a");
6696 aopPut (AOP (result), "a", MSB16 - offl);
6700 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6701 emitcode ("rrc", "a");
6702 aopPut (AOP (result), "a", LSB);
6706 /*-----------------------------------------------------------------*/
6707 /* genrshFour - shift four byte by a known amount != 0 */
6708 /*-----------------------------------------------------------------*/
6710 genrshFour (operand * result, operand * left,
6711 int shCount, int sign)
6713 D(emitcode ("; genrshFour",""));
6715 /* if shifting more that 3 bytes */
6720 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6722 movLeft2Result (left, MSB32, result, LSB, sign);
6723 addSign (result, MSB16, sign);
6725 else if (shCount >= 16)
6729 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6732 movLeft2Result (left, MSB24, result, LSB, 0);
6733 movLeft2Result (left, MSB32, result, MSB16, sign);
6735 addSign (result, MSB24, sign);
6737 else if (shCount >= 8)
6741 shiftRLong (left, MSB16, result, sign);
6742 else if (shCount == 0)
6744 movLeft2Result (left, MSB16, result, LSB, 0);
6745 movLeft2Result (left, MSB24, result, MSB16, 0);
6746 movLeft2Result (left, MSB32, result, MSB24, sign);
6747 addSign (result, MSB32, sign);
6751 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6752 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6753 /* the last shift is signed */
6754 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6755 addSign (result, MSB32, sign);
6759 { /* 1 <= shCount <= 7 */
6762 shiftRLong (left, LSB, result, sign);
6764 shiftRLong (result, LSB, result, sign);
6768 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6769 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6770 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6775 /*-----------------------------------------------------------------*/
6776 /* genRightShiftLiteral - right shifting by known count */
6777 /*-----------------------------------------------------------------*/
6779 genRightShiftLiteral (operand * left,
6785 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6788 D(emitcode ("; genRightShiftLiteral",""));
6790 freeAsmop (right, NULL, ic, TRUE);
6792 aopOp (left, ic, FALSE);
6793 aopOp (result, ic, FALSE);
6796 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6800 size = getDataSize (left);
6801 /* test the LEFT size !!! */
6803 /* I suppose that the left size >= result size */
6806 size = getDataSize (result);
6808 movLeft2Result (left, size, result, size, 0);
6811 else if (shCount >= (size * 8))
6814 /* get sign in acc.7 */
6815 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6817 addSign (result, LSB, sign);
6824 genrshOne (result, left, shCount, sign);
6828 genrshTwo (result, left, shCount, sign);
6832 genrshFour (result, left, shCount, sign);
6838 freeAsmop (left, NULL, ic, TRUE);
6839 freeAsmop (result, NULL, ic, TRUE);
6842 /*-----------------------------------------------------------------*/
6843 /* genSignedRightShift - right shift of signed number */
6844 /*-----------------------------------------------------------------*/
6846 genSignedRightShift (iCode * ic)
6848 operand *right, *left, *result;
6851 symbol *tlbl, *tlbl1;
6853 D(emitcode ("; genSignedRightShift",""));
6855 /* we do it the hard way put the shift count in b
6856 and loop thru preserving the sign */
6858 right = IC_RIGHT (ic);
6859 left = IC_LEFT (ic);
6860 result = IC_RESULT (ic);
6862 aopOp (right, ic, FALSE);
6865 if (AOP_TYPE (right) == AOP_LIT)
6867 genRightShiftLiteral (left, right, result, ic, 1);
6870 /* shift count is unknown then we have to form
6871 a loop get the loop count in B : Note: we take
6872 only the lower order byte since shifting
6873 more that 32 bits make no sense anyway, ( the
6874 largest size of an object can be only 32 bits ) */
6876 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6877 emitcode ("inc", "b");
6878 freeAsmop (right, NULL, ic, TRUE);
6879 aopOp (left, ic, FALSE);
6880 aopOp (result, ic, FALSE);
6882 /* now move the left to the result if they are not the
6884 if (!sameRegs (AOP (left), AOP (result)) &&
6885 AOP_SIZE (result) > 1)
6888 size = AOP_SIZE (result);
6892 l = aopGet (AOP (left), offset, FALSE, TRUE);
6893 if (*l == '@' && IS_AOP_PREG (result))
6896 emitcode ("mov", "a,%s", l);
6897 aopPut (AOP (result), "a", offset);
6900 aopPut (AOP (result), l, offset);
6905 /* mov the highest order bit to OVR */
6906 tlbl = newiTempLabel (NULL);
6907 tlbl1 = newiTempLabel (NULL);
6909 size = AOP_SIZE (result);
6911 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6912 emitcode ("rlc", "a");
6913 emitcode ("mov", "ov,c");
6914 /* if it is only one byte then */
6917 l = aopGet (AOP (left), 0, FALSE, FALSE);
6919 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6920 emitcode ("", "%05d$:", tlbl->key + 100);
6921 emitcode ("mov", "c,ov");
6922 emitcode ("rrc", "a");
6923 emitcode ("", "%05d$:", tlbl1->key + 100);
6924 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6925 aopPut (AOP (result), "a", 0);
6929 reAdjustPreg (AOP (result));
6930 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6931 emitcode ("", "%05d$:", tlbl->key + 100);
6932 emitcode ("mov", "c,ov");
6935 l = aopGet (AOP (result), offset, FALSE, FALSE);
6937 emitcode ("rrc", "a");
6938 aopPut (AOP (result), "a", offset--);
6940 reAdjustPreg (AOP (result));
6941 emitcode ("", "%05d$:", tlbl1->key + 100);
6942 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6945 freeAsmop (left, NULL, ic, TRUE);
6946 freeAsmop (result, NULL, ic, TRUE);
6949 /*-----------------------------------------------------------------*/
6950 /* genRightShift - generate code for right shifting */
6951 /*-----------------------------------------------------------------*/
6953 genRightShift (iCode * ic)
6955 operand *right, *left, *result;
6959 symbol *tlbl, *tlbl1;
6961 D(emitcode ("; genRightShift",""));
6963 /* if signed then we do it the hard way preserve the
6964 sign bit moving it inwards */
6965 retype = getSpec (operandType (IC_RESULT (ic)));
6967 if (!SPEC_USIGN (retype))
6969 genSignedRightShift (ic);
6973 /* signed & unsigned types are treated the same : i.e. the
6974 signed is NOT propagated inwards : quoting from the
6975 ANSI - standard : "for E1 >> E2, is equivalent to division
6976 by 2**E2 if unsigned or if it has a non-negative value,
6977 otherwise the result is implementation defined ", MY definition
6978 is that the sign does not get propagated */
6980 right = IC_RIGHT (ic);
6981 left = IC_LEFT (ic);
6982 result = IC_RESULT (ic);
6984 aopOp (right, ic, FALSE);
6986 /* if the shift count is known then do it
6987 as efficiently as possible */
6988 if (AOP_TYPE (right) == AOP_LIT)
6990 genRightShiftLiteral (left, right, result, ic, 0);
6994 /* shift count is unknown then we have to form
6995 a loop get the loop count in B : Note: we take
6996 only the lower order byte since shifting
6997 more that 32 bits make no sense anyway, ( the
6998 largest size of an object can be only 32 bits ) */
7000 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7001 emitcode ("inc", "b");
7002 freeAsmop (right, NULL, ic, TRUE);
7003 aopOp (left, ic, FALSE);
7004 aopOp (result, ic, FALSE);
7006 /* now move the left to the result if they are not the
7008 if (!sameRegs (AOP (left), AOP (result)) &&
7009 AOP_SIZE (result) > 1)
7012 size = AOP_SIZE (result);
7016 l = aopGet (AOP (left), offset, FALSE, TRUE);
7017 if (*l == '@' && IS_AOP_PREG (result))
7020 emitcode ("mov", "a,%s", l);
7021 aopPut (AOP (result), "a", offset);
7024 aopPut (AOP (result), l, offset);
7029 tlbl = newiTempLabel (NULL);
7030 tlbl1 = newiTempLabel (NULL);
7031 size = AOP_SIZE (result);
7034 /* if it is only one byte then */
7037 l = aopGet (AOP (left), 0, FALSE, FALSE);
7039 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7040 emitcode ("", "%05d$:", tlbl->key + 100);
7042 emitcode ("rrc", "a");
7043 emitcode ("", "%05d$:", tlbl1->key + 100);
7044 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7045 aopPut (AOP (result), "a", 0);
7049 reAdjustPreg (AOP (result));
7050 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7051 emitcode ("", "%05d$:", tlbl->key + 100);
7055 l = aopGet (AOP (result), offset, FALSE, FALSE);
7057 emitcode ("rrc", "a");
7058 aopPut (AOP (result), "a", offset--);
7060 reAdjustPreg (AOP (result));
7062 emitcode ("", "%05d$:", tlbl1->key + 100);
7063 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7066 freeAsmop (left, NULL, ic, TRUE);
7067 freeAsmop (result, NULL, ic, TRUE);
7070 /*-----------------------------------------------------------------*/
7071 /* genUnpackBits - generates code for unpacking bits */
7072 /*-----------------------------------------------------------------*/
7074 genUnpackBits (operand * result, char *rname, int ptype)
7082 D(emitcode ("; genUnpackBits",""));
7084 etype = getSpec (operandType (result));
7085 rsize = getSize (operandType (result));
7086 /* read the first byte */
7092 emitcode ("mov", "a,@%s", rname);
7096 emitcode ("movx", "a,@%s", rname);
7100 emitcode ("movx", "a,@dptr");
7104 emitcode ("clr", "a");
7105 emitcode ("movc", "a,@a+dptr");
7109 emitcode ("lcall", "__gptrget");
7113 rlen = SPEC_BLEN (etype);
7115 /* if we have bitdisplacement then it fits */
7116 /* into this byte completely or if length is */
7117 /* less than a byte */
7118 if ((shCnt = SPEC_BSTR (etype)) ||
7119 (SPEC_BLEN (etype) <= 8))
7122 /* shift right acc */
7125 emitcode ("anl", "a,#0x%02x",
7126 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7127 aopPut (AOP (result), "a", offset++);
7131 /* bit field did not fit in a byte */
7132 aopPut (AOP (result), "a", offset++);
7141 emitcode ("inc", "%s", rname);
7142 emitcode ("mov", "a,@%s", rname);
7146 emitcode ("inc", "%s", rname);
7147 emitcode ("movx", "a,@%s", rname);
7151 emitcode ("inc", "dptr");
7152 emitcode ("movx", "a,@dptr");
7156 emitcode ("clr", "a");
7157 emitcode ("inc", "dptr");
7158 emitcode ("movc", "a,@a+dptr");
7162 emitcode ("inc", "dptr");
7163 emitcode ("lcall", "__gptrget");
7168 /* if we are done */
7172 aopPut (AOP (result), "a", offset++);
7178 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7180 aopPut (AOP (result), "a", offset++);
7188 aopPut (AOP (result), zero, offset++);
7194 /*-----------------------------------------------------------------*/
7195 /* genDataPointerGet - generates code when ptr offset is known */
7196 /*-----------------------------------------------------------------*/
7198 genDataPointerGet (operand * left,
7204 int size, offset = 0;
7206 D(emitcode ("; genDataPointerGet",""));
7208 aopOp (result, ic, TRUE);
7210 /* get the string representation of the name */
7211 l = aopGet (AOP (left), 0, FALSE, TRUE);
7212 size = AOP_SIZE (result);
7216 sprintf (buffer, "(%s + %d)", l + 1, offset);
7218 sprintf (buffer, "%s", l + 1);
7219 aopPut (AOP (result), buffer, offset++);
7222 freeAsmop (left, NULL, ic, TRUE);
7223 freeAsmop (result, NULL, ic, TRUE);
7226 /*-----------------------------------------------------------------*/
7227 /* genNearPointerGet - emitcode for near pointer fetch */
7228 /*-----------------------------------------------------------------*/
7230 genNearPointerGet (operand * left,
7238 sym_link *rtype, *retype;
7239 sym_link *ltype = operandType (left);
7242 D(emitcode ("; genNearPointerGet",""));
7244 rtype = operandType (result);
7245 retype = getSpec (rtype);
7247 aopOp (left, ic, FALSE);
7249 /* if left is rematerialisable and
7250 result is not bit variable type and
7251 the left is pointer to data space i.e
7252 lower 128 bytes of space */
7253 if (AOP_TYPE (left) == AOP_IMMD &&
7254 !IS_BITVAR (retype) &&
7255 DCL_TYPE (ltype) == POINTER)
7257 genDataPointerGet (left, result, ic);
7261 /* if the value is already in a pointer register
7262 then don't need anything more */
7263 if (!AOP_INPREG (AOP (left)))
7265 /* otherwise get a free pointer register */
7267 preg = getFreePtr (ic, &aop, FALSE);
7268 emitcode ("mov", "%s,%s",
7270 aopGet (AOP (left), 0, FALSE, TRUE));
7274 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7276 //aopOp (result, ic, FALSE);
7277 aopOp (result, ic, result?TRUE:FALSE);
7279 /* if bitfield then unpack the bits */
7280 if (IS_BITVAR (retype))
7281 genUnpackBits (result, rname, POINTER);
7284 /* we have can just get the values */
7285 int size = AOP_SIZE (result);
7290 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7293 emitcode ("mov", "a,@%s", rname);
7294 aopPut (AOP (result), "a", offset);
7298 sprintf (buffer, "@%s", rname);
7299 aopPut (AOP (result), buffer, offset);
7303 emitcode ("inc", "%s", rname);
7307 /* now some housekeeping stuff */
7308 if (aop) /* we had to allocate for this iCode */
7310 if (pi) { /* post increment present */
7311 aopPut(AOP ( left ),rname,0);
7313 freeAsmop (NULL, aop, ic, TRUE);
7317 /* we did not allocate which means left
7318 already in a pointer register, then
7319 if size > 0 && this could be used again
7320 we have to point it back to where it
7322 if ((AOP_SIZE (result) > 1 &&
7323 !OP_SYMBOL (left)->remat &&
7324 (OP_SYMBOL (left)->liveTo > ic->seq ||
7328 int size = AOP_SIZE (result) - 1;
7330 emitcode ("dec", "%s", rname);
7335 freeAsmop (left, NULL, ic, TRUE);
7336 freeAsmop (result, NULL, ic, TRUE);
7337 if (pi) pi->generated = 1;
7340 /*-----------------------------------------------------------------*/
7341 /* genPagedPointerGet - emitcode for paged pointer fetch */
7342 /*-----------------------------------------------------------------*/
7344 genPagedPointerGet (operand * left,
7352 sym_link *rtype, *retype;
7354 D(emitcode ("; genPagedPointerGet",""));
7356 rtype = operandType (result);
7357 retype = getSpec (rtype);
7359 aopOp (left, ic, FALSE);
7361 /* if the value is already in a pointer register
7362 then don't need anything more */
7363 if (!AOP_INPREG (AOP (left)))
7365 /* otherwise get a free pointer register */
7367 preg = getFreePtr (ic, &aop, FALSE);
7368 emitcode ("mov", "%s,%s",
7370 aopGet (AOP (left), 0, FALSE, TRUE));
7374 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7376 aopOp (result, ic, FALSE);
7378 /* if bitfield then unpack the bits */
7379 if (IS_BITVAR (retype))
7380 genUnpackBits (result, rname, PPOINTER);
7383 /* we have can just get the values */
7384 int size = AOP_SIZE (result);
7390 emitcode ("movx", "a,@%s", rname);
7391 aopPut (AOP (result), "a", offset);
7396 emitcode ("inc", "%s", rname);
7400 /* now some housekeeping stuff */
7401 if (aop) /* we had to allocate for this iCode */
7403 if (pi) aopPut ( AOP (left), rname, 0);
7404 freeAsmop (NULL, aop, ic, TRUE);
7408 /* we did not allocate which means left
7409 already in a pointer register, then
7410 if size > 0 && this could be used again
7411 we have to point it back to where it
7413 if ((AOP_SIZE (result) > 1 &&
7414 !OP_SYMBOL (left)->remat &&
7415 (OP_SYMBOL (left)->liveTo > ic->seq ||
7419 int size = AOP_SIZE (result) - 1;
7421 emitcode ("dec", "%s", rname);
7426 freeAsmop (left, NULL, ic, TRUE);
7427 freeAsmop (result, NULL, ic, TRUE);
7428 if (pi) pi->generated = 1;
7432 /*-----------------------------------------------------------------*/
7433 /* genFarPointerGet - gget value from far space */
7434 /*-----------------------------------------------------------------*/
7436 genFarPointerGet (operand * left,
7437 operand * result, iCode * ic, iCode * pi)
7440 sym_link *retype = getSpec (operandType (result));
7442 D(emitcode ("; genFarPointerGet",""));
7444 aopOp (left, ic, FALSE);
7446 /* if the operand is already in dptr
7447 then we do nothing else we move the value to dptr */
7448 if (AOP_TYPE (left) != AOP_STR)
7450 /* if this is remateriazable */
7451 if (AOP_TYPE (left) == AOP_IMMD)
7452 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7454 { /* we need to get it byte by byte */
7455 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7456 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7459 /* so dptr know contains the address */
7460 aopOp (result, ic, FALSE);
7462 /* if bit then unpack */
7463 if (IS_BITVAR (retype))
7464 genUnpackBits (result, "dptr", FPOINTER);
7467 size = AOP_SIZE (result);
7472 emitcode ("movx", "a,@dptr");
7473 aopPut (AOP (result), "a", offset++);
7475 emitcode ("inc", "dptr");
7479 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7480 aopPut ( AOP (left), "dpl", 0);
7481 aopPut ( AOP (left), "dph", 1);
7484 freeAsmop (left, NULL, ic, TRUE);
7485 freeAsmop (result, NULL, ic, TRUE);
7488 /*-----------------------------------------------------------------*/
7489 /* genCodePointerGet - gget value from code space */
7490 /*-----------------------------------------------------------------*/
7492 genCodePointerGet (operand * left,
7493 operand * result, iCode * ic, iCode *pi)
7496 sym_link *retype = getSpec (operandType (result));
7498 D(emitcode ("; genCodePointerGet",""));
7500 aopOp (left, ic, FALSE);
7502 /* if the operand is already in dptr
7503 then we do nothing else we move the value to dptr */
7504 if (AOP_TYPE (left) != AOP_STR)
7506 /* if this is remateriazable */
7507 if (AOP_TYPE (left) == AOP_IMMD)
7508 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7510 { /* we need to get it byte by byte */
7511 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7512 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7515 /* so dptr know contains the address */
7516 aopOp (result, ic, FALSE);
7518 /* if bit then unpack */
7519 if (IS_BITVAR (retype))
7520 genUnpackBits (result, "dptr", CPOINTER);
7523 size = AOP_SIZE (result);
7530 emitcode ("clr", "a");
7531 emitcode ("movc", "a,@a+dptr");
7532 aopPut (AOP (result), "a", offset++);
7533 emitcode ("inc", "dptr");
7537 emitcode ("mov", "a,#0x%02x", offset);
7538 emitcode ("movc", "a,@a+dptr");
7539 aopPut (AOP (result), "a", offset++);
7544 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7545 aopPut ( AOP (left), "dpl", 0);
7546 aopPut ( AOP (left), "dph", 1);
7549 freeAsmop (left, NULL, ic, TRUE);
7550 freeAsmop (result, NULL, ic, TRUE);
7553 /*-----------------------------------------------------------------*/
7554 /* genGenPointerGet - gget value from generic pointer space */
7555 /*-----------------------------------------------------------------*/
7557 genGenPointerGet (operand * left,
7558 operand * result, iCode * ic, iCode *pi)
7561 sym_link *retype = getSpec (operandType (result));
7563 D(emitcode ("; genGenPointerGet",""));
7565 aopOp (left, ic, FALSE);
7567 /* if the operand is already in dptr
7568 then we do nothing else we move the value to dptr */
7569 if (AOP_TYPE (left) != AOP_STR)
7571 /* if this is remateriazable */
7572 if (AOP_TYPE (left) == AOP_IMMD)
7574 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7575 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7576 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7578 emitcode ("mov", "b,#%d", pointerCode (retype));
7581 { /* we need to get it byte by byte */
7582 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7583 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7584 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7587 /* so dptr know contains the address */
7588 aopOp (result, ic, FALSE);
7590 /* if bit then unpack */
7591 if (IS_BITVAR (retype))
7592 genUnpackBits (result, "dptr", GPOINTER);
7595 size = AOP_SIZE (result);
7600 emitcode ("lcall", "__gptrget");
7601 aopPut (AOP (result), "a", offset++);
7603 emitcode ("inc", "dptr");
7607 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7608 aopPut ( AOP (left), "dpl", 0);
7609 aopPut ( AOP (left), "dph", 1);
7610 aopPut ( AOP (left), "b", 2);
7613 freeAsmop (left, NULL, ic, TRUE);
7614 freeAsmop (result, NULL, ic, TRUE);
7617 /*-----------------------------------------------------------------*/
7618 /* genPointerGet - generate code for pointer get */
7619 /*-----------------------------------------------------------------*/
7621 genPointerGet (iCode * ic, iCode *pi)
7623 operand *left, *result;
7624 sym_link *type, *etype;
7627 D(emitcode ("; genPointerGet",""));
7629 left = IC_LEFT (ic);
7630 result = IC_RESULT (ic);
7632 /* depending on the type of pointer we need to
7633 move it to the correct pointer register */
7634 type = operandType (left);
7635 etype = getSpec (type);
7636 /* if left is of type of pointer then it is simple */
7637 if (IS_PTR (type) && !IS_FUNC (type->next))
7638 p_type = DCL_TYPE (type);
7641 /* we have to go by the storage class */
7642 p_type = PTR_TYPE (SPEC_OCLS (etype));
7645 /* special case when cast remat */
7646 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7647 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7648 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7649 type = operandType (left);
7650 p_type = DCL_TYPE (type);
7652 /* now that we have the pointer type we assign
7653 the pointer values */
7659 genNearPointerGet (left, result, ic, pi);
7663 genPagedPointerGet (left, result, ic, pi);
7667 genFarPointerGet (left, result, ic, pi);
7671 genCodePointerGet (left, result, ic, pi);
7675 genGenPointerGet (left, result, ic, pi);
7681 /*-----------------------------------------------------------------*/
7682 /* genPackBits - generates code for packed bit storage */
7683 /*-----------------------------------------------------------------*/
7685 genPackBits (sym_link * etype,
7687 char *rname, int p_type)
7695 D(emitcode ("; genPackBits",""));
7697 blen = SPEC_BLEN (etype);
7698 bstr = SPEC_BSTR (etype);
7700 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7703 /* if the bit lenth is less than or */
7704 /* it exactly fits a byte then */
7705 if (SPEC_BLEN (etype) <= 8)
7707 shCount = SPEC_BSTR (etype);
7709 /* shift left acc */
7712 if (SPEC_BLEN (etype) < 8)
7713 { /* if smaller than a byte */
7719 emitcode ("mov", "b,a");
7720 emitcode ("mov", "a,@%s", rname);
7724 emitcode ("mov", "b,a");
7725 emitcode ("movx", "a,@dptr");
7729 emitcode ("push", "b");
7730 emitcode ("push", "acc");
7731 emitcode ("lcall", "__gptrget");
7732 emitcode ("pop", "b");
7736 emitcode ("anl", "a,#0x%02x", (unsigned char)
7737 ((unsigned char) (0xFF << (blen + bstr)) |
7738 (unsigned char) (0xFF >> (8 - bstr))));
7739 emitcode ("orl", "a,b");
7740 if (p_type == GPOINTER)
7741 emitcode ("pop", "b");
7748 emitcode ("mov", "@%s,a", rname);
7752 emitcode ("movx", "@dptr,a");
7756 emitcode ("lcall", "__gptrput");
7761 if (SPEC_BLEN (etype) <= 8)
7764 emitcode ("inc", "%s", rname);
7765 rLen = SPEC_BLEN (etype);
7767 /* now generate for lengths greater than one byte */
7771 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7783 emitcode ("mov", "@%s,a", rname);
7786 emitcode ("mov", "@%s,%s", rname, l);
7791 emitcode ("movx", "@dptr,a");
7796 emitcode ("lcall", "__gptrput");
7799 emitcode ("inc", "%s", rname);
7804 /* last last was not complete */
7807 /* save the byte & read byte */
7811 emitcode ("mov", "b,a");
7812 emitcode ("mov", "a,@%s", rname);
7816 emitcode ("mov", "b,a");
7817 emitcode ("movx", "a,@dptr");
7821 emitcode ("push", "b");
7822 emitcode ("push", "acc");
7823 emitcode ("lcall", "__gptrget");
7824 emitcode ("pop", "b");
7828 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7829 emitcode ("orl", "a,b");
7832 if (p_type == GPOINTER)
7833 emitcode ("pop", "b");
7839 emitcode ("mov", "@%s,a", rname);
7843 emitcode ("movx", "@dptr,a");
7847 emitcode ("lcall", "__gptrput");
7851 /*-----------------------------------------------------------------*/
7852 /* genDataPointerSet - remat pointer to data space */
7853 /*-----------------------------------------------------------------*/
7855 genDataPointerSet (operand * right,
7859 int size, offset = 0;
7860 char *l, buffer[256];
7862 D(emitcode ("; genDataPointerSet",""));
7864 aopOp (right, ic, FALSE);
7866 l = aopGet (AOP (result), 0, FALSE, TRUE);
7867 size = AOP_SIZE (right);
7871 sprintf (buffer, "(%s + %d)", l + 1, offset);
7873 sprintf (buffer, "%s", l + 1);
7874 emitcode ("mov", "%s,%s", buffer,
7875 aopGet (AOP (right), offset++, FALSE, FALSE));
7878 freeAsmop (right, NULL, ic, TRUE);
7879 freeAsmop (result, NULL, ic, TRUE);
7882 /*-----------------------------------------------------------------*/
7883 /* genNearPointerSet - emitcode for near pointer put */
7884 /*-----------------------------------------------------------------*/
7886 genNearPointerSet (operand * right,
7894 sym_link *retype, *letype;
7895 sym_link *ptype = operandType (result);
7897 D(emitcode ("; genNearPointerSet",""));
7899 retype = getSpec (operandType (right));
7900 letype = getSpec (ptype);
7901 aopOp (result, ic, FALSE);
7903 /* if the result is rematerializable &
7904 in data space & not a bit variable */
7905 if (AOP_TYPE (result) == AOP_IMMD &&
7906 DCL_TYPE (ptype) == POINTER &&
7907 !IS_BITVAR (retype) &&
7908 !IS_BITVAR (letype))
7910 genDataPointerSet (right, result, ic);
7914 /* if the value is already in a pointer register
7915 then don't need anything more */
7916 if (!AOP_INPREG (AOP (result)))
7919 //AOP_TYPE (result) == AOP_STK
7923 // Aha, it is a pointer, just in disguise.
7924 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7927 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7928 __FILE__, __LINE__);
7933 rname++; // skip the '@'.
7938 /* otherwise get a free pointer register */
7940 preg = getFreePtr (ic, &aop, FALSE);
7941 emitcode ("mov", "%s,%s",
7943 aopGet (AOP (result), 0, FALSE, TRUE));
7949 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7952 aopOp (right, ic, FALSE);
7954 /* if bitfield then unpack the bits */
7955 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7956 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7959 /* we have can just get the values */
7960 int size = AOP_SIZE (right);
7965 l = aopGet (AOP (right), offset, FALSE, TRUE);
7969 emitcode ("mov", "@%s,a", rname);
7972 emitcode ("mov", "@%s,%s", rname, l);
7974 emitcode ("inc", "%s", rname);
7979 /* now some housekeeping stuff */
7980 if (aop) /* we had to allocate for this iCode */
7982 if (pi) aopPut (AOP (result),rname,0);
7983 freeAsmop (NULL, aop, ic, TRUE);
7987 /* we did not allocate which means left
7988 already in a pointer register, then
7989 if size > 0 && this could be used again
7990 we have to point it back to where it
7992 if ((AOP_SIZE (right) > 1 &&
7993 !OP_SYMBOL (result)->remat &&
7994 (OP_SYMBOL (result)->liveTo > ic->seq ||
7998 int size = AOP_SIZE (right) - 1;
8000 emitcode ("dec", "%s", rname);
8005 if (pi) pi->generated = 1;
8006 freeAsmop (result, NULL, ic, TRUE);
8007 freeAsmop (right, NULL, ic, TRUE);
8010 /*-----------------------------------------------------------------*/
8011 /* genPagedPointerSet - emitcode for Paged pointer put */
8012 /*-----------------------------------------------------------------*/
8014 genPagedPointerSet (operand * right,
8022 sym_link *retype, *letype;
8024 D(emitcode ("; genPagedPointerSet",""));
8026 retype = getSpec (operandType (right));
8027 letype = getSpec (operandType (result));
8029 aopOp (result, ic, FALSE);
8031 /* if the value is already in a pointer register
8032 then don't need anything more */
8033 if (!AOP_INPREG (AOP (result)))
8035 /* otherwise get a free pointer register */
8037 preg = getFreePtr (ic, &aop, FALSE);
8038 emitcode ("mov", "%s,%s",
8040 aopGet (AOP (result), 0, FALSE, TRUE));
8044 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8046 aopOp (right, ic, FALSE);
8048 /* if bitfield then unpack the bits */
8049 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8050 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8053 /* we have can just get the values */
8054 int size = AOP_SIZE (right);
8059 l = aopGet (AOP (right), offset, FALSE, TRUE);
8062 emitcode ("movx", "@%s,a", rname);
8065 emitcode ("inc", "%s", rname);
8071 /* now some housekeeping stuff */
8072 if (aop) /* we had to allocate for this iCode */
8074 if (pi) aopPut (AOP (result),rname,0);
8075 freeAsmop (NULL, aop, ic, TRUE);
8079 /* we did not allocate which means left
8080 already in a pointer register, then
8081 if size > 0 && this could be used again
8082 we have to point it back to where it
8084 if (AOP_SIZE (right) > 1 &&
8085 !OP_SYMBOL (result)->remat &&
8086 (OP_SYMBOL (result)->liveTo > ic->seq ||
8089 int size = AOP_SIZE (right) - 1;
8091 emitcode ("dec", "%s", rname);
8096 if (pi) pi->generated = 1;
8097 freeAsmop (result, NULL, ic, TRUE);
8098 freeAsmop (right, NULL, ic, TRUE);
8103 /*-----------------------------------------------------------------*/
8104 /* genFarPointerSet - set value from far space */
8105 /*-----------------------------------------------------------------*/
8107 genFarPointerSet (operand * right,
8108 operand * result, iCode * ic, iCode * pi)
8111 sym_link *retype = getSpec (operandType (right));
8112 sym_link *letype = getSpec (operandType (result));
8114 D(emitcode ("; genFarPointerSet",""));
8116 aopOp (result, ic, FALSE);
8118 /* if the operand is already in dptr
8119 then we do nothing else we move the value to dptr */
8120 if (AOP_TYPE (result) != AOP_STR)
8122 /* if this is remateriazable */
8123 if (AOP_TYPE (result) == AOP_IMMD)
8124 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8126 { /* we need to get it byte by byte */
8127 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8128 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8131 /* so dptr know contains the address */
8132 aopOp (right, ic, FALSE);
8134 /* if bit then unpack */
8135 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8136 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8139 size = AOP_SIZE (right);
8144 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8146 emitcode ("movx", "@dptr,a");
8148 emitcode ("inc", "dptr");
8151 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8152 aopPut (AOP(result),"dpl",0);
8153 aopPut (AOP(result),"dph",1);
8156 freeAsmop (result, NULL, ic, TRUE);
8157 freeAsmop (right, NULL, ic, TRUE);
8160 /*-----------------------------------------------------------------*/
8161 /* genGenPointerSet - set value from generic pointer space */
8162 /*-----------------------------------------------------------------*/
8164 genGenPointerSet (operand * right,
8165 operand * result, iCode * ic, iCode * pi)
8168 sym_link *retype = getSpec (operandType (right));
8169 sym_link *letype = getSpec (operandType (result));
8171 D(emitcode ("; genGenPointerSet",""));
8173 aopOp (result, ic, FALSE);
8175 /* if the operand is already in dptr
8176 then we do nothing else we move the value to dptr */
8177 if (AOP_TYPE (result) != AOP_STR)
8179 /* if this is remateriazable */
8180 if (AOP_TYPE (result) == AOP_IMMD)
8182 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8183 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8184 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8186 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8189 { /* we need to get it byte by byte */
8190 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8191 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8192 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8195 /* so dptr know contains the address */
8196 aopOp (right, ic, FALSE);
8198 /* if bit then unpack */
8199 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8200 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8203 size = AOP_SIZE (right);
8208 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8210 emitcode ("lcall", "__gptrput");
8212 emitcode ("inc", "dptr");
8216 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8217 aopPut (AOP(result),"dpl",0);
8218 aopPut (AOP(result),"dph",1);
8219 aopPut (AOP(result),"b",2);
8222 freeAsmop (result, NULL, ic, TRUE);
8223 freeAsmop (right, NULL, ic, TRUE);
8226 /*-----------------------------------------------------------------*/
8227 /* genPointerSet - stores the value into a pointer location */
8228 /*-----------------------------------------------------------------*/
8230 genPointerSet (iCode * ic, iCode *pi)
8232 operand *right, *result;
8233 sym_link *type, *etype;
8236 D(emitcode ("; genPointerSet",""));
8238 right = IC_RIGHT (ic);
8239 result = IC_RESULT (ic);
8241 /* depending on the type of pointer we need to
8242 move it to the correct pointer register */
8243 type = operandType (result);
8244 etype = getSpec (type);
8245 /* if left is of type of pointer then it is simple */
8246 if (IS_PTR (type) && !IS_FUNC (type->next))
8248 p_type = DCL_TYPE (type);
8252 /* we have to go by the storage class */
8253 p_type = PTR_TYPE (SPEC_OCLS (etype));
8256 /* special case when cast remat */
8257 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8258 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8259 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8260 type = operandType (result);
8261 p_type = DCL_TYPE (type);
8263 /* now that we have the pointer type we assign
8264 the pointer values */
8270 genNearPointerSet (right, result, ic, pi);
8274 genPagedPointerSet (right, result, ic, pi);
8278 genFarPointerSet (right, result, ic, pi);
8282 genGenPointerSet (right, result, ic, pi);
8286 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8287 "genPointerSet: illegal pointer type");
8292 /*-----------------------------------------------------------------*/
8293 /* genIfx - generate code for Ifx statement */
8294 /*-----------------------------------------------------------------*/
8296 genIfx (iCode * ic, iCode * popIc)
8298 operand *cond = IC_COND (ic);
8301 D(emitcode ("; genIfx",""));
8303 aopOp (cond, ic, FALSE);
8305 /* get the value into acc */
8306 if (AOP_TYPE (cond) != AOP_CRY)
8310 /* the result is now in the accumulator */
8311 freeAsmop (cond, NULL, ic, TRUE);
8313 /* if there was something to be popped then do it */
8317 /* if the condition is a bit variable */
8318 if (isbit && IS_ITEMP (cond) &&
8320 genIfxJump (ic, SPIL_LOC (cond)->rname);
8321 else if (isbit && !IS_ITEMP (cond))
8322 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8324 genIfxJump (ic, "a");
8329 /*-----------------------------------------------------------------*/
8330 /* genAddrOf - generates code for address of */
8331 /*-----------------------------------------------------------------*/
8333 genAddrOf (iCode * ic)
8335 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8338 D(emitcode ("; genAddrOf",""));
8340 aopOp (IC_RESULT (ic), ic, FALSE);
8342 /* if the operand is on the stack then we
8343 need to get the stack offset of this
8347 /* if it has an offset then we need to compute
8351 emitcode ("mov", "a,_bp");
8352 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8353 ((char) (sym->stack - _G.nRegsSaved)) :
8354 ((char) sym->stack)) & 0xff);
8355 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8359 /* we can just move _bp */
8360 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8362 /* fill the result with zero */
8363 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8368 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8374 /* object not on stack then we need the name */
8375 size = AOP_SIZE (IC_RESULT (ic));
8380 char s[SDCC_NAME_MAX];
8382 sprintf (s, "#(%s >> %d)",
8386 sprintf (s, "#%s", sym->rname);
8387 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8391 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8395 /*-----------------------------------------------------------------*/
8396 /* genFarFarAssign - assignment when both are in far space */
8397 /*-----------------------------------------------------------------*/
8399 genFarFarAssign (operand * result, operand * right, iCode * ic)
8401 int size = AOP_SIZE (right);
8405 D(emitcode ("; genFarFarAssign",""));
8407 /* first push the right side on to the stack */
8410 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8412 emitcode ("push", "acc");
8415 freeAsmop (right, NULL, ic, FALSE);
8416 /* now assign DPTR to result */
8417 aopOp (result, ic, FALSE);
8418 size = AOP_SIZE (result);
8421 emitcode ("pop", "acc");
8422 aopPut (AOP (result), "a", --offset);
8424 freeAsmop (result, NULL, ic, FALSE);
8428 /*-----------------------------------------------------------------*/
8429 /* genAssign - generate code for assignment */
8430 /*-----------------------------------------------------------------*/
8432 genAssign (iCode * ic)
8434 operand *result, *right;
8436 unsigned long lit = 0L;
8438 D(emitcode("; genAssign",""));
8440 result = IC_RESULT (ic);
8441 right = IC_RIGHT (ic);
8443 /* if they are the same */
8444 if (operandsEqu (result, right)) {
8448 aopOp (right, ic, FALSE);
8450 /* special case both in far space */
8451 if (AOP_TYPE (right) == AOP_DPTR &&
8452 IS_TRUE_SYMOP (result) &&
8453 isOperandInFarSpace (result))
8456 genFarFarAssign (result, right, ic);
8460 aopOp (result, ic, TRUE);
8462 /* if they are the same registers */
8463 if (sameRegs (AOP (right), AOP (result)))
8466 /* if the result is a bit */
8467 if (AOP_TYPE (result) == AOP_CRY)
8470 /* if the right size is a literal then
8471 we know what the value is */
8472 if (AOP_TYPE (right) == AOP_LIT)
8474 if (((int) operandLitValue (right)))
8475 aopPut (AOP (result), one, 0);
8477 aopPut (AOP (result), zero, 0);
8481 /* the right is also a bit variable */
8482 if (AOP_TYPE (right) == AOP_CRY)
8484 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8485 aopPut (AOP (result), "c", 0);
8491 aopPut (AOP (result), "a", 0);
8495 /* bit variables done */
8497 size = AOP_SIZE (result);
8499 if (AOP_TYPE (right) == AOP_LIT)
8500 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8502 (AOP_TYPE (result) != AOP_REG) &&
8503 (AOP_TYPE (right) == AOP_LIT) &&
8504 !IS_FLOAT (operandType (right)) &&
8507 emitcode ("clr", "a");
8510 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8511 aopPut (AOP (result), "a", size);
8513 aopPut (AOP (result),
8514 aopGet (AOP (right), size, FALSE, FALSE),
8522 aopPut (AOP (result),
8523 aopGet (AOP (right), offset, FALSE, FALSE),
8530 freeAsmop (right, NULL, ic, TRUE);
8531 freeAsmop (result, NULL, ic, TRUE);
8534 /*-----------------------------------------------------------------*/
8535 /* genJumpTab - genrates code for jump table */
8536 /*-----------------------------------------------------------------*/
8538 genJumpTab (iCode * ic)
8543 D(emitcode ("; genJumpTab",""));
8545 aopOp (IC_JTCOND (ic), ic, FALSE);
8546 /* get the condition into accumulator */
8547 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8549 /* multiply by three */
8550 emitcode ("add", "a,acc");
8551 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8552 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8554 jtab = newiTempLabel (NULL);
8555 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8556 emitcode ("jmp", "@a+dptr");
8557 emitcode ("", "%05d$:", jtab->key + 100);
8558 /* now generate the jump labels */
8559 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8560 jtab = setNextItem (IC_JTLABELS (ic)))
8561 emitcode ("ljmp", "%05d$", jtab->key + 100);
8565 /*-----------------------------------------------------------------*/
8566 /* genCast - gen code for casting */
8567 /*-----------------------------------------------------------------*/
8569 genCast (iCode * ic)
8571 operand *result = IC_RESULT (ic);
8572 sym_link *ctype = operandType (IC_LEFT (ic));
8573 sym_link *rtype = operandType (IC_RIGHT (ic));
8574 operand *right = IC_RIGHT (ic);
8577 D(emitcode("; genCast",""));
8579 /* if they are equivalent then do nothing */
8580 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8583 aopOp (right, ic, FALSE);
8584 aopOp (result, ic, FALSE);
8586 /* if the result is a bit */
8587 if (IS_BITVAR(OP_SYMBOL(result)->type))
8589 /* if the right size is a literal then
8590 we know what the value is */
8591 if (AOP_TYPE (right) == AOP_LIT)
8593 if (((int) operandLitValue (right)))
8594 aopPut (AOP (result), one, 0);
8596 aopPut (AOP (result), zero, 0);
8601 /* the right is also a bit variable */
8602 if (AOP_TYPE (right) == AOP_CRY)
8604 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8605 aopPut (AOP (result), "c", 0);
8611 aopPut (AOP (result), "a", 0);
8615 /* if they are the same size : or less */
8616 if (AOP_SIZE (result) <= AOP_SIZE (right))
8619 /* if they are in the same place */
8620 if (sameRegs (AOP (right), AOP (result)))
8623 /* if they in different places then copy */
8624 size = AOP_SIZE (result);
8628 aopPut (AOP (result),
8629 aopGet (AOP (right), offset, FALSE, FALSE),
8637 /* if the result is of type pointer */
8642 sym_link *type = operandType (right);
8643 sym_link *etype = getSpec (type);
8645 /* pointer to generic pointer */
8646 if (IS_GENPTR (ctype))
8649 p_type = DCL_TYPE (type);
8652 if (SPEC_SCLS(etype)==S_REGISTER) {
8653 // let's assume it is a generic pointer
8656 /* we have to go by the storage class */
8657 p_type = PTR_TYPE (SPEC_OCLS (etype));
8661 /* the first two bytes are known */
8662 size = GPTRSIZE - 1;
8666 aopPut (AOP (result),
8667 aopGet (AOP (right), offset, FALSE, FALSE),
8671 /* the last byte depending on type */
8673 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8678 // pointerTypeToGPByte will have bitched.
8682 sprintf(gpValStr, "#0x%d", gpVal);
8683 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8688 /* just copy the pointers */
8689 size = AOP_SIZE (result);
8693 aopPut (AOP (result),
8694 aopGet (AOP (right), offset, FALSE, FALSE),
8701 /* so we now know that the size of destination is greater
8702 than the size of the source */
8703 /* we move to result for the size of source */
8704 size = AOP_SIZE (right);
8708 aopPut (AOP (result),
8709 aopGet (AOP (right), offset, FALSE, FALSE),
8714 /* now depending on the sign of the source && destination */
8715 size = AOP_SIZE (result) - AOP_SIZE (right);
8716 /* if unsigned or not an integral type */
8717 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8720 aopPut (AOP (result), zero, offset++);
8724 /* we need to extend the sign :{ */
8725 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8728 emitcode ("rlc", "a");
8729 emitcode ("subb", "a,acc");
8731 aopPut (AOP (result), "a", offset++);
8734 /* we are done hurray !!!! */
8737 freeAsmop (right, NULL, ic, TRUE);
8738 freeAsmop (result, NULL, ic, TRUE);
8742 /*-----------------------------------------------------------------*/
8743 /* genDjnz - generate decrement & jump if not zero instrucion */
8744 /*-----------------------------------------------------------------*/
8746 genDjnz (iCode * ic, iCode * ifx)
8752 D(emitcode ("; genDjnz",""));
8754 /* if the if condition has a false label
8755 then we cannot save */
8759 /* if the minus is not of the form
8761 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8762 !IS_OP_LITERAL (IC_RIGHT (ic)))
8765 if (operandLitValue (IC_RIGHT (ic)) != 1)
8768 /* if the size of this greater than one then no
8770 if (getSize (operandType (IC_RESULT (ic))) > 1)
8773 /* otherwise we can save BIG */
8774 lbl = newiTempLabel (NULL);
8775 lbl1 = newiTempLabel (NULL);
8777 aopOp (IC_RESULT (ic), ic, FALSE);
8779 if (AOP_NEEDSACC(IC_RESULT(ic)))
8781 /* If the result is accessed indirectly via
8782 * the accumulator, we must explicitly write
8783 * it back after the decrement.
8785 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8787 if (strcmp(rByte, "a"))
8789 /* Something is hopelessly wrong */
8790 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8791 __FILE__, __LINE__);
8792 /* We can just give up; the generated code will be inefficient,
8795 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8798 emitcode ("dec", "%s", rByte);
8799 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8800 emitcode ("jnz", "%05d$", lbl->key + 100);
8802 else if (IS_AOP_PREG (IC_RESULT (ic)))
8804 emitcode ("dec", "%s",
8805 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8806 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8807 emitcode ("jnz", "%05d$", lbl->key + 100);
8811 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8814 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8815 emitcode ("", "%05d$:", lbl->key + 100);
8816 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8817 emitcode ("", "%05d$:", lbl1->key + 100);
8819 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8824 /*-----------------------------------------------------------------*/
8825 /* genReceive - generate code for a receive iCode */
8826 /*-----------------------------------------------------------------*/
8828 genReceive (iCode * ic)
8830 int size = getSize (operandType (IC_RESULT (ic)));
8832 D(emitcode ("; genReceive",""));
8834 if (ic->argreg == 1) { /* first parameter */
8835 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8836 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8837 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8839 offset = fReturnSizeMCS51 - size;
8841 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8842 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8845 aopOp (IC_RESULT (ic), ic, FALSE);
8846 size = AOP_SIZE (IC_RESULT (ic));
8849 emitcode ("pop", "acc");
8850 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8855 aopOp (IC_RESULT (ic), ic, FALSE);
8857 assignResultValue (IC_RESULT (ic));
8859 } else { /* second receive onwards */
8861 aopOp (IC_RESULT (ic), ic, FALSE);
8862 rb1off = ic->argreg;
8864 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8867 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8870 /*-----------------------------------------------------------------*/
8871 /* gen51Code - generate code for 8051 based controllers */
8872 /*-----------------------------------------------------------------*/
8874 gen51Code (iCode * lic)
8879 lineHead = lineCurr = NULL;
8881 /* print the allocation information */
8883 printAllocInfo (currFunc, codeOutFile);
8884 /* if debug information required */
8885 if (options.debug && currFunc)
8887 debugFile->writeFunction(currFunc);
8889 if (IS_STATIC (currFunc->etype))
8890 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8892 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8895 /* stack pointer name */
8896 if (options.useXstack)
8902 for (ic = lic; ic; ic = ic->next)
8905 if (ic->lineno && cln != ic->lineno)
8910 emitcode ("", "C$%s$%d$%d$%d ==.",
8911 FileBaseName (ic->filename), ic->lineno,
8912 ic->level, ic->block);
8915 if (!options.noCcodeInAsm) {
8916 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8917 printCLine(ic->filename, ic->lineno));
8921 if (options.iCodeInAsm) {
8925 for (i=0; i<8; i++) {
8926 sprintf (®sInUse[i],
8927 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8930 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8932 /* if the result is marked as
8933 spilt and rematerializable or code for
8934 this has already been generated then
8936 if (resultRemat (ic) || ic->generated)
8939 /* depending on the operation */
8959 /* IPOP happens only when trying to restore a
8960 spilt live range, if there is an ifx statement
8961 following this pop then the if statement might
8962 be using some of the registers being popped which
8963 would destory the contents of the register so
8964 we need to check for this condition and handle it */
8966 ic->next->op == IFX &&
8967 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8968 genIfx (ic->next, ic);
8986 genEndFunction (ic);
9006 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9023 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9027 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9034 /* note these two are xlated by algebraic equivalence
9035 during parsing SDCC.y */
9036 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9037 "got '>=' or '<=' shouldn't have come here");
9041 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9053 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9057 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9061 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9088 case GET_VALUE_AT_ADDRESS:
9089 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9093 if (POINTER_SET (ic))
9094 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9120 addSet (&_G.sendSet, ic);
9129 /* now we are ready to call the
9130 peep hole optimizer */
9131 if (!options.nopeep)
9132 peepHole (&lineHead);
9134 /* now do the actual printing */
9135 printLine (lineHead, codeOutFile);