1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static short rbank = -1;
79 static char *rb1regs[] = {
80 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
83 extern int mcs51_ptrRegReq;
84 extern int mcs51_nRegs;
85 extern FILE *codeOutFile;
86 static void saveRBank (int, iCode *, bool);
87 #define RESULTONSTACK(x) \
88 (IC_RESULT(x) && IC_RESULT(x)->aop && \
89 IC_RESULT(x)->aop->type == AOP_STK )
91 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
92 #define CLRC emitcode("clr","c")
93 #define SETC emitcode("setb","c")
95 static lineNode *lineHead = NULL;
96 static lineNode *lineCurr = NULL;
98 static unsigned char SLMask[] =
99 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
100 0xE0, 0xC0, 0x80, 0x00};
101 static unsigned char SRMask[] =
102 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00};
110 /*-----------------------------------------------------------------*/
111 /* emitcode - writes the code into a file : for now it is simple */
112 /*-----------------------------------------------------------------*/
114 emitcode (char *inst, char *fmt,...)
117 char lb[INITIAL_INLINEASM];
125 sprintf (lb, "%s\t", inst);
127 sprintf (lb, "%s", inst);
128 vsprintf (lb + (strlen (lb)), fmt, ap);
131 vsprintf (lb, fmt, ap);
133 while (isspace (*lbp))
137 lineCurr = (lineCurr ?
138 connectLine (lineCurr, newLineNode (lb)) :
139 (lineHead = newLineNode (lb)));
140 lineCurr->isInline = _G.inLine;
141 lineCurr->isDebug = _G.debugLine;
145 /*-----------------------------------------------------------------*/
146 /* mova - moves specified value into accumulator */
147 /*-----------------------------------------------------------------*/
151 /* do some early peephole optimization */
152 if (!strcmp(x, "a") || !strcmp(x, "acc"))
155 emitcode("mov","a,%s", x);
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
386 val += (int) operandLitValue (IC_RIGHT (ic));
387 else if (ic->op == '-')
388 val -= (int) operandLitValue (IC_RIGHT (ic));
389 else if (IS_CAST_ICODE(ic)) {
390 sym_link *from_type = operandType(IC_RIGHT(ic));
391 aop->aopu.aop_immd.from_cast_remat = 1;
392 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
393 ptr_type = DCL_TYPE(from_type);
394 if (ptr_type == IPOINTER) {
401 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
405 sprintf (buffer, "(%s %c 0x%04x)",
406 OP_SYMBOL (IC_LEFT (ic))->rname,
407 val >= 0 ? '+' : '-',
410 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
413 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
414 /* set immd2 field if required */
415 if (aop->aopu.aop_immd.from_cast_remat) {
416 sprintf(buffer,"#0x%02x",ptr_type);
417 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
418 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
424 /*-----------------------------------------------------------------*/
425 /* regsInCommon - two operands have some registers in common */
426 /*-----------------------------------------------------------------*/
428 regsInCommon (operand * op1, operand * op2)
433 /* if they have registers in common */
434 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
437 sym1 = OP_SYMBOL (op1);
438 sym2 = OP_SYMBOL (op2);
440 if (sym1->nRegs == 0 || sym2->nRegs == 0)
443 for (i = 0; i < sym1->nRegs; i++)
449 for (j = 0; j < sym2->nRegs; j++)
454 if (sym2->regs[j] == sym1->regs[i])
462 /*-----------------------------------------------------------------*/
463 /* operandsEqu - equivalent */
464 /*-----------------------------------------------------------------*/
466 operandsEqu (operand * op1, operand * op2)
470 /* if they not symbols */
471 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
474 sym1 = OP_SYMBOL (op1);
475 sym2 = OP_SYMBOL (op2);
477 /* if both are itemps & one is spilt
478 and the other is not then false */
479 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
480 sym1->isspilt != sym2->isspilt)
483 /* if they are the same */
487 if (strcmp (sym1->rname, sym2->rname) == 0)
491 /* if left is a tmp & right is not */
492 if (IS_ITEMP (op1) &&
495 (sym1->usl.spillLoc == sym2))
498 if (IS_ITEMP (op2) &&
502 (sym2->usl.spillLoc == sym1))
508 /*-----------------------------------------------------------------*/
509 /* sameRegs - two asmops have the same registers */
510 /*-----------------------------------------------------------------*/
512 sameRegs (asmop * aop1, asmop * aop2)
519 if (aop1->type != AOP_REG ||
520 aop2->type != AOP_REG)
523 if (aop1->size != aop2->size)
526 for (i = 0; i < aop1->size; i++)
527 if (aop1->aopu.aop_reg[i] !=
528 aop2->aopu.aop_reg[i])
534 /*-----------------------------------------------------------------*/
535 /* aopOp - allocates an asmop for an operand : */
536 /*-----------------------------------------------------------------*/
538 aopOp (operand * op, iCode * ic, bool result)
547 /* if this a literal */
548 if (IS_OP_LITERAL (op))
550 op->aop = aop = newAsmop (AOP_LIT);
551 aop->aopu.aop_lit = op->operand.valOperand;
552 aop->size = getSize (operandType (op));
556 /* if already has a asmop then continue */
560 /* if the underlying symbol has a aop */
561 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
563 op->aop = OP_SYMBOL (op)->aop;
567 /* if this is a true symbol */
568 if (IS_TRUE_SYMOP (op))
570 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
574 /* this is a temporary : this has
580 e) can be a return use only */
582 sym = OP_SYMBOL (op);
584 /* if the type is a conditional */
585 if (sym->regType == REG_CND)
587 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
592 /* if it is spilt then two situations
594 b) has a spill location */
595 if (sym->isspilt || sym->nRegs == 0)
598 /* rematerialize it NOW */
601 sym->aop = op->aop = aop =
603 aop->size = getSize (sym->type);
610 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
611 aop->size = getSize (sym->type);
612 for (i = 0; i < 2; i++)
613 aop->aopu.aop_str[i] = accUse[i];
621 aop = op->aop = sym->aop = newAsmop (AOP_STR);
622 aop->size = getSize (sym->type);
623 for (i = 0; i < fReturnSizeMCS51; i++)
624 aop->aopu.aop_str[i] = fReturn[i];
628 /* else spill location */
629 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
630 /* force a new aop if sizes differ */
631 sym->usl.spillLoc->aop = NULL;
633 sym->aop = op->aop = aop =
634 aopForSym (ic, sym->usl.spillLoc, result);
635 aop->size = getSize (sym->type);
639 /* must be in a register */
640 sym->aop = op->aop = aop = newAsmop (AOP_REG);
641 aop->size = sym->nRegs;
642 for (i = 0; i < sym->nRegs; i++)
643 aop->aopu.aop_reg[i] = sym->regs[i];
646 /*-----------------------------------------------------------------*/
647 /* freeAsmop - free up the asmop given to an operand */
648 /*----------------------------------------------------------------*/
650 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
667 /* depending on the asmop type only three cases need work AOP_RO
668 , AOP_R1 && AOP_STK */
676 emitcode ("pop", "ar0");
680 bitVectUnSetBit (ic->rUsed, R0_IDX);
688 emitcode ("pop", "ar1");
692 bitVectUnSetBit (ic->rUsed, R1_IDX);
698 int stk = aop->aopu.aop_stk + aop->size;
699 bitVectUnSetBit (ic->rUsed, R0_IDX);
700 bitVectUnSetBit (ic->rUsed, R1_IDX);
702 getFreePtr (ic, &aop, FALSE);
706 emitcode ("mov", "a,_bp");
707 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
708 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
712 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
717 emitcode ("pop", "acc");
718 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
721 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
724 freeAsmop (op, NULL, ic, TRUE);
727 emitcode ("pop", "ar0");
733 emitcode ("pop", "ar1");
740 /* all other cases just dealloc */
746 OP_SYMBOL (op)->aop = NULL;
747 /* if the symbol has a spill */
749 SPIL_LOC (op)->aop = NULL;
754 /*-----------------------------------------------------------------*/
755 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
756 /* clobber the accumulator */
757 /*-----------------------------------------------------------------*/
759 aopGetUsesAcc (asmop *aop, int offset)
761 if (offset > (aop->size - 1))
779 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
788 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
792 /* Error case --- will have been caught already */
799 /*-----------------------------------------------------------------*/
800 /* aopGet - for fetching value of the aop */
801 /*-----------------------------------------------------------------*/
803 aopGet (asmop * aop, int offset, bool bit16, bool dname)
808 /* offset is greater than
810 if (offset > (aop->size - 1) &&
811 aop->type != AOP_LIT)
814 /* depending on type */
820 /* if we need to increment it */
821 while (offset > aop->coff)
823 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
827 while (offset < aop->coff)
829 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
836 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
837 return (dname ? "acc" : "a");
839 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
840 rs = Safe_calloc (1, strlen (s) + 1);
845 if (aop->code && aop->coff==0 && offset>=1) {
846 emitcode ("mov", "a,#0x%02x", offset);
847 emitcode ("movc", "a,@a+dptr");
848 return (dname ? "acc" : "a");
851 while (offset > aop->coff)
853 emitcode ("inc", "dptr");
857 while (offset < aop->coff)
859 emitcode ("lcall", "__decdptr");
866 emitcode ("clr", "a");
867 emitcode ("movc", "a,@a+dptr");
871 emitcode ("movx", "a,@dptr");
873 return (dname ? "acc" : "a");
877 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
878 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
880 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
882 sprintf (s, "#(%s >> %d)",
883 aop->aopu.aop_immd.aop_immd1,
887 aop->aopu.aop_immd.aop_immd1);
888 rs = Safe_calloc (1, strlen (s) + 1);
894 sprintf (s, "(%s + %d)",
898 sprintf (s, "%s", aop->aopu.aop_dir);
899 rs = Safe_calloc (1, strlen (s) + 1);
905 return aop->aopu.aop_reg[offset]->dname;
907 return aop->aopu.aop_reg[offset]->name;
910 emitcode ("clr", "a");
911 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
912 emitcode ("rlc", "a");
913 return (dname ? "acc" : "a");
916 if (!offset && dname)
918 return aop->aopu.aop_str[offset];
921 return aopLiteral (aop->aopu.aop_lit, offset);
925 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
929 return aop->aopu.aop_str[offset];
933 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
934 "aopget got unsupported aop->type");
937 /*-----------------------------------------------------------------*/
938 /* aopPut - puts a string for a aop */
939 /*-----------------------------------------------------------------*/
941 aopPut (asmop * aop, char *s, int offset)
945 if (aop->size && offset > (aop->size - 1))
947 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
948 "aopPut got offset > aop->size");
952 /* will assign value to value */
953 /* depending on where it is ofcourse */
958 sprintf (d, "(%s + %d)",
959 aop->aopu.aop_dir, offset);
961 sprintf (d, "%s", aop->aopu.aop_dir);
964 emitcode ("mov", "%s,%s", d, s);
969 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
970 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
973 strcmp (s, "r0") == 0 ||
974 strcmp (s, "r1") == 0 ||
975 strcmp (s, "r2") == 0 ||
976 strcmp (s, "r3") == 0 ||
977 strcmp (s, "r4") == 0 ||
978 strcmp (s, "r5") == 0 ||
979 strcmp (s, "r6") == 0 ||
980 strcmp (s, "r7") == 0)
981 emitcode ("mov", "%s,%s",
982 aop->aopu.aop_reg[offset]->dname, s);
984 emitcode ("mov", "%s,%s",
985 aop->aopu.aop_reg[offset]->name, s);
992 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
993 "aopPut writting to code space");
997 while (offset > aop->coff)
1000 emitcode ("inc", "dptr");
1003 while (offset < aop->coff)
1006 emitcode ("lcall", "__decdptr");
1011 /* if not in accumulater */
1014 emitcode ("movx", "@dptr,a");
1019 while (offset > aop->coff)
1022 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1024 while (offset < aop->coff)
1027 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1034 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1040 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1042 else if (strcmp (s, "r0") == 0 ||
1043 strcmp (s, "r1") == 0 ||
1044 strcmp (s, "r2") == 0 ||
1045 strcmp (s, "r3") == 0 ||
1046 strcmp (s, "r4") == 0 ||
1047 strcmp (s, "r5") == 0 ||
1048 strcmp (s, "r6") == 0 ||
1049 strcmp (s, "r7") == 0)
1052 sprintf (buffer, "a%s", s);
1053 emitcode ("mov", "@%s,%s",
1054 aop->aopu.aop_ptr->name, buffer);
1057 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1062 if (strcmp (s, "a") == 0)
1063 emitcode ("push", "acc");
1067 emitcode ("push", "acc");
1069 emitcode ("push", s);
1075 /* if bit variable */
1076 if (!aop->aopu.aop_dir)
1078 emitcode ("clr", "a");
1079 emitcode ("rlc", "a");
1084 emitcode ("clr", "%s", aop->aopu.aop_dir);
1086 emitcode ("setb", "%s", aop->aopu.aop_dir);
1087 else if (!strcmp (s, "c"))
1088 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1091 if (strcmp (s, "a"))
1096 /* set C, if a >= 1 */
1097 emitcode ("add", "a,#0xff");
1098 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1106 if (strcmp (aop->aopu.aop_str[offset], s))
1107 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1112 if (!offset && (strcmp (s, "acc") == 0))
1115 if (strcmp (aop->aopu.aop_str[offset], s))
1116 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1120 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1121 "aopPut got unsupported aop->type");
1129 /*-----------------------------------------------------------------*/
1130 /* pointToEnd :- points to the last byte of the operand */
1131 /*-----------------------------------------------------------------*/
1133 pointToEnd (asmop * aop)
1139 aop->coff = count = (aop->size - 1);
1145 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1149 emitcode ("inc", "dptr");
1156 /*-----------------------------------------------------------------*/
1157 /* reAdjustPreg - points a register back to where it should */
1158 /*-----------------------------------------------------------------*/
1160 reAdjustPreg (asmop * aop)
1162 if ((aop->coff==0) || aop->size <= 1)
1170 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1175 emitcode ("lcall", "__decdptr");
1182 #define AOP(op) op->aop
1183 #define AOP_TYPE(op) AOP(op)->type
1184 #define AOP_SIZE(op) AOP(op)->size
1185 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1186 AOP_TYPE(x) == AOP_R0))
1188 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1189 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1191 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1192 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1193 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1195 /*-----------------------------------------------------------------*/
1196 /* genNotFloat - generates not for float operations */
1197 /*-----------------------------------------------------------------*/
1199 genNotFloat (operand * op, operand * res)
1205 D(emitcode ("; genNotFloat",""));
1207 /* we will put 127 in the first byte of
1209 aopPut (AOP (res), "#127", 0);
1210 size = AOP_SIZE (op) - 1;
1213 l = aopGet (op->aop, offset++, FALSE, FALSE);
1218 emitcode ("orl", "a,%s",
1220 offset++, FALSE, FALSE));
1223 tlbl = newiTempLabel (NULL);
1224 aopPut (res->aop, one, 1);
1225 emitcode ("jz", "%05d$", (tlbl->key + 100));
1226 aopPut (res->aop, zero, 1);
1227 emitcode ("", "%05d$:", (tlbl->key + 100));
1229 size = res->aop->size - 2;
1231 /* put zeros in the rest */
1233 aopPut (res->aop, zero, offset++);
1236 /*-----------------------------------------------------------------*/
1237 /* opIsGptr: returns non-zero if the passed operand is */
1238 /* a generic pointer type. */
1239 /*-----------------------------------------------------------------*/
1241 opIsGptr (operand * op)
1243 sym_link *type = operandType (op);
1245 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1252 /*-----------------------------------------------------------------*/
1253 /* getDataSize - get the operand data size */
1254 /*-----------------------------------------------------------------*/
1256 getDataSize (operand * op)
1259 size = AOP_SIZE (op);
1260 if (size == GPTRSIZE)
1262 sym_link *type = operandType (op);
1263 if (IS_GENPTR (type))
1265 /* generic pointer; arithmetic operations
1266 * should ignore the high byte (pointer type).
1274 /*-----------------------------------------------------------------*/
1275 /* outAcc - output Acc */
1276 /*-----------------------------------------------------------------*/
1278 outAcc (operand * result)
1281 size = getDataSize (result);
1284 aopPut (AOP (result), "a", 0);
1287 /* unsigned or positive */
1290 aopPut (AOP (result), zero, offset++);
1295 /*-----------------------------------------------------------------*/
1296 /* outBitC - output a bit C */
1297 /*-----------------------------------------------------------------*/
1299 outBitC (operand * result)
1301 /* if the result is bit */
1302 if (AOP_TYPE (result) == AOP_CRY)
1303 aopPut (AOP (result), "c", 0);
1306 emitcode ("clr", "a");
1307 emitcode ("rlc", "a");
1312 /*-----------------------------------------------------------------*/
1313 /* toBoolean - emit code for orl a,operator(sizeop) */
1314 /*-----------------------------------------------------------------*/
1316 toBoolean (operand * oper)
1318 int size = AOP_SIZE (oper) - 1;
1320 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1322 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1326 /*-----------------------------------------------------------------*/
1327 /* genNot - generate code for ! operation */
1328 /*-----------------------------------------------------------------*/
1333 sym_link *optype = operandType (IC_LEFT (ic));
1335 D(emitcode ("; genNot",""));
1337 /* assign asmOps to operand & result */
1338 aopOp (IC_LEFT (ic), ic, FALSE);
1339 aopOp (IC_RESULT (ic), ic, TRUE);
1341 /* if in bit space then a special case */
1342 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1344 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1345 emitcode ("cpl", "c");
1346 outBitC (IC_RESULT (ic));
1350 /* if type float then do float */
1351 if (IS_FLOAT (optype))
1353 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1357 toBoolean (IC_LEFT (ic));
1359 tlbl = newiTempLabel (NULL);
1360 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1361 emitcode ("", "%05d$:", tlbl->key + 100);
1362 outBitC (IC_RESULT (ic));
1365 /* release the aops */
1366 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1367 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1371 /*-----------------------------------------------------------------*/
1372 /* genCpl - generate code for complement */
1373 /*-----------------------------------------------------------------*/
1381 D(emitcode ("; genCpl",""));
1383 /* assign asmOps to operand & result */
1384 aopOp (IC_LEFT (ic), ic, FALSE);
1385 aopOp (IC_RESULT (ic), ic, TRUE);
1387 /* special case if in bit space */
1388 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1389 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1390 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1391 emitcode ("cpl", "c");
1392 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1395 tlbl=newiTempLabel(NULL);
1396 emitcode ("cjne", "%s,#0x01,%05d$",
1397 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1398 emitcode ("", "%05d$:", tlbl->key+100);
1399 outBitC (IC_RESULT(ic));
1403 size = AOP_SIZE (IC_RESULT (ic));
1406 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1408 emitcode ("cpl", "a");
1409 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1414 /* release the aops */
1415 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1416 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1419 /*-----------------------------------------------------------------*/
1420 /* genUminusFloat - unary minus for floating points */
1421 /*-----------------------------------------------------------------*/
1423 genUminusFloat (operand * op, operand * result)
1425 int size, offset = 0;
1428 D(emitcode ("; genUminusFloat",""));
1430 /* for this we just copy and then flip the bit */
1432 size = AOP_SIZE (op) - 1;
1436 aopPut (AOP (result),
1437 aopGet (AOP (op), offset, FALSE, FALSE),
1442 l = aopGet (AOP (op), offset, FALSE, FALSE);
1446 emitcode ("cpl", "acc.7");
1447 aopPut (AOP (result), "a", offset);
1450 /*-----------------------------------------------------------------*/
1451 /* genUminus - unary minus code generation */
1452 /*-----------------------------------------------------------------*/
1454 genUminus (iCode * ic)
1457 sym_link *optype, *rtype;
1460 D(emitcode ("; genUminus",""));
1463 aopOp (IC_LEFT (ic), ic, FALSE);
1464 aopOp (IC_RESULT (ic), ic, TRUE);
1466 /* if both in bit space then special
1468 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1469 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1472 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1473 emitcode ("cpl", "c");
1474 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1478 optype = operandType (IC_LEFT (ic));
1479 rtype = operandType (IC_RESULT (ic));
1481 /* if float then do float stuff */
1482 if (IS_FLOAT (optype))
1484 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1488 /* otherwise subtract from zero */
1489 size = AOP_SIZE (IC_LEFT (ic));
1494 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1495 if (!strcmp (l, "a"))
1499 emitcode ("cpl", "a");
1500 emitcode ("addc", "a,#0");
1506 emitcode ("clr", "a");
1507 emitcode ("subb", "a,%s", l);
1509 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1512 /* if any remaining bytes in the result */
1513 /* we just need to propagate the sign */
1514 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1516 emitcode ("rlc", "a");
1517 emitcode ("subb", "a,acc");
1519 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1523 /* release the aops */
1524 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1525 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1528 /*-----------------------------------------------------------------*/
1529 /* saveRegisters - will look for a call and save the registers */
1530 /*-----------------------------------------------------------------*/
1532 saveRegisters (iCode * lic)
1539 for (ic = lic; ic; ic = ic->next)
1540 if (ic->op == CALL || ic->op == PCALL)
1545 fprintf (stderr, "found parameter push with no function call\n");
1549 /* if the registers have been saved already or don't need to be then
1551 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1552 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1555 /* safe the registers in use at this time but skip the
1556 ones for the result */
1557 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1558 mcs51_rUmaskForOp (IC_RESULT(ic)));
1561 if (options.useXstack)
1563 if (bitVectBitValue (rsave, R0_IDX))
1564 emitcode ("mov", "b,r0");
1565 emitcode ("mov", "r0,%s", spname);
1566 for (i = 0; i < mcs51_nRegs; i++)
1568 if (bitVectBitValue (rsave, i))
1571 emitcode ("mov", "a,b");
1573 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1574 emitcode ("movx", "@r0,a");
1575 emitcode ("inc", "r0");
1578 emitcode ("mov", "%s,r0", spname);
1579 if (bitVectBitValue (rsave, R0_IDX))
1580 emitcode ("mov", "r0,b");
1583 for (i = 0; i < mcs51_nRegs; i++)
1585 if (bitVectBitValue (rsave, i))
1586 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1590 /*-----------------------------------------------------------------*/
1591 /* unsaveRegisters - pop the pushed registers */
1592 /*-----------------------------------------------------------------*/
1594 unsaveRegisters (iCode * ic)
1599 /* restore the registers in use at this time but skip the
1600 ones for the result */
1601 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1602 mcs51_rUmaskForOp (IC_RESULT(ic)));
1604 if (options.useXstack)
1606 emitcode ("mov", "r0,%s", spname);
1607 for (i = mcs51_nRegs; i >= 0; i--)
1609 if (bitVectBitValue (rsave, i))
1611 emitcode ("dec", "r0");
1612 emitcode ("movx", "a,@r0");
1614 emitcode ("mov", "b,a");
1616 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1620 emitcode ("mov", "%s,r0", spname);
1621 if (bitVectBitValue (rsave, R0_IDX))
1622 emitcode ("mov", "r0,b");
1625 for (i = mcs51_nRegs; i >= 0; i--)
1627 if (bitVectBitValue (rsave, i))
1628 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1634 /*-----------------------------------------------------------------*/
1636 /*-----------------------------------------------------------------*/
1638 pushSide (operand * oper, int size)
1643 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1644 if (AOP_TYPE (oper) != AOP_REG &&
1645 AOP_TYPE (oper) != AOP_DIR &&
1648 emitcode ("mov", "a,%s", l);
1649 emitcode ("push", "acc");
1652 emitcode ("push", "%s", l);
1656 /*-----------------------------------------------------------------*/
1657 /* assignResultValue - */
1658 /*-----------------------------------------------------------------*/
1660 assignResultValue (operand * oper)
1663 int size = AOP_SIZE (oper);
1666 aopPut (AOP (oper), fReturn[offset], offset);
1672 /*-----------------------------------------------------------------*/
1673 /* genXpush - pushes onto the external stack */
1674 /*-----------------------------------------------------------------*/
1676 genXpush (iCode * ic)
1678 asmop *aop = newAsmop (0);
1680 int size, offset = 0;
1682 D(emitcode ("; genXpush",""));
1684 aopOp (IC_LEFT (ic), ic, FALSE);
1685 r = getFreePtr (ic, &aop, FALSE);
1688 emitcode ("mov", "%s,_spx", r->name);
1690 size = AOP_SIZE (IC_LEFT (ic));
1694 char *l = aopGet (AOP (IC_LEFT (ic)),
1695 offset++, FALSE, FALSE);
1697 emitcode ("movx", "@%s,a", r->name);
1698 emitcode ("inc", "%s", r->name);
1703 emitcode ("mov", "_spx,%s", r->name);
1705 freeAsmop (NULL, aop, ic, TRUE);
1706 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1709 /*-----------------------------------------------------------------*/
1710 /* genIpush - genrate code for pushing this gets a little complex */
1711 /*-----------------------------------------------------------------*/
1713 genIpush (iCode * ic)
1715 int size, offset = 0;
1718 D(emitcode ("; genIpush",""));
1720 /* if this is not a parm push : ie. it is spill push
1721 and spill push is always done on the local stack */
1725 /* and the item is spilt then do nothing */
1726 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1729 aopOp (IC_LEFT (ic), ic, FALSE);
1730 size = AOP_SIZE (IC_LEFT (ic));
1731 /* push it on the stack */
1734 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1740 emitcode ("push", "%s", l);
1745 /* this is a paramter push: in this case we call
1746 the routine to find the call and save those
1747 registers that need to be saved */
1750 /* if use external stack then call the external
1751 stack pushing routine */
1752 if (options.useXstack)
1758 /* then do the push */
1759 aopOp (IC_LEFT (ic), ic, FALSE);
1762 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1763 size = AOP_SIZE (IC_LEFT (ic));
1767 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1768 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1769 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1772 emitcode ("mov", "a,%s", l);
1773 emitcode ("push", "acc");
1776 emitcode ("push", "%s", l);
1779 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1782 /*-----------------------------------------------------------------*/
1783 /* genIpop - recover the registers: can happen only for spilling */
1784 /*-----------------------------------------------------------------*/
1786 genIpop (iCode * ic)
1790 D(emitcode ("; genIpop",""));
1792 /* if the temp was not pushed then */
1793 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1796 aopOp (IC_LEFT (ic), ic, FALSE);
1797 size = AOP_SIZE (IC_LEFT (ic));
1798 offset = (size - 1);
1800 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1803 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1806 /*-----------------------------------------------------------------*/
1807 /* unsaveRBank - restores the resgister bank from stack */
1808 /*-----------------------------------------------------------------*/
1810 unsaveRBank (int bank, iCode * ic, bool popPsw)
1816 if (options.useXstack)
1820 /* Assume r0 is available for use. */
1821 r = mcs51_regWithIdx (R0_IDX);;
1826 r = getFreePtr (ic, &aop, FALSE);
1828 emitcode ("mov", "%s,_spx", r->name);
1833 if (options.useXstack)
1835 emitcode ("movx", "a,@%s", r->name);
1836 emitcode ("mov", "psw,a");
1837 emitcode ("dec", "%s", r->name);
1841 emitcode ("pop", "psw");
1845 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1847 if (options.useXstack)
1849 emitcode ("movx", "a,@%s", r->name);
1850 emitcode ("mov", "(%s+%d),a",
1851 regs8051[i].base, 8 * bank + regs8051[i].offset);
1852 emitcode ("dec", "%s", r->name);
1856 emitcode ("pop", "(%s+%d)",
1857 regs8051[i].base, 8 * bank + regs8051[i].offset);
1860 if (options.useXstack)
1862 emitcode ("mov", "_spx,%s", r->name);
1867 freeAsmop (NULL, aop, ic, TRUE);
1871 /*-----------------------------------------------------------------*/
1872 /* saveRBank - saves an entire register bank on the stack */
1873 /*-----------------------------------------------------------------*/
1875 saveRBank (int bank, iCode * ic, bool pushPsw)
1881 if (options.useXstack)
1885 /* Assume r0 is available for use. */
1886 r = mcs51_regWithIdx (R0_IDX);;
1891 r = getFreePtr (ic, &aop, FALSE);
1893 emitcode ("mov", "%s,_spx", r->name);
1896 for (i = 0; i < mcs51_nRegs; i++)
1898 if (options.useXstack)
1900 emitcode ("inc", "%s", r->name);
1901 emitcode ("mov", "a,(%s+%d)",
1902 regs8051[i].base, 8 * bank + regs8051[i].offset);
1903 emitcode ("movx", "@%s,a", r->name);
1906 emitcode ("push", "(%s+%d)",
1907 regs8051[i].base, 8 * bank + regs8051[i].offset);
1912 if (options.useXstack)
1914 emitcode ("mov", "a,psw");
1915 emitcode ("movx", "@%s,a", r->name);
1916 emitcode ("inc", "%s", r->name);
1917 emitcode ("mov", "_spx,%s", r->name);
1922 emitcode ("push", "psw");
1925 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1930 freeAsmop (NULL, aop, ic, TRUE);
1939 /*-----------------------------------------------------------------*/
1940 /* genSend - gen code for SEND */
1941 /*-----------------------------------------------------------------*/
1942 static void genSend(set *sendSet)
1947 for (sic = setFirstItem (_G.sendSet); sic;
1948 sic = setNextItem (_G.sendSet)) {
1949 int size, offset = 0;
1950 aopOp (IC_LEFT (sic), sic, FALSE);
1951 size = AOP_SIZE (IC_LEFT (sic));
1953 if (sic->argreg == 1) {
1955 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1957 if (strcmp (l, fReturn[offset]))
1958 emitcode ("mov", "%s,%s", fReturn[offset], l);
1964 emitcode ("mov","b1_%d,%s",rb1_count++,
1965 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1968 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1972 /*-----------------------------------------------------------------*/
1973 /* genCall - generates a call statement */
1974 /*-----------------------------------------------------------------*/
1976 genCall (iCode * ic)
1979 // bool restoreBank = FALSE;
1980 bool swapBanks = FALSE;
1982 D(emitcode("; genCall",""));
1984 dtype = operandType (IC_LEFT (ic));
1985 /* if send set is not empty the assign */
1988 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1989 genSend(reverseSet(_G.sendSet));
1991 genSend(_G.sendSet);
1997 /* if we are calling a not _naked function that is not using
1998 the same register bank then we need to save the
1999 destination registers on the stack */
2000 dtype = operandType (IC_LEFT (ic));
2001 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2002 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2003 !IFFUNC_ISISR (dtype))
2008 /* if caller saves & we have not saved then */
2014 emitcode ("mov", "psw,#0x%02x",
2015 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2019 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2020 OP_SYMBOL (IC_LEFT (ic))->rname :
2021 OP_SYMBOL (IC_LEFT (ic))->name));
2025 emitcode ("mov", "psw,#0x%02x",
2026 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2029 /* if we need assign a result value */
2030 if ((IS_ITEMP (IC_RESULT (ic)) &&
2031 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2032 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2033 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2034 IS_TRUE_SYMOP (IC_RESULT (ic)))
2038 aopOp (IC_RESULT (ic), ic, FALSE);
2041 assignResultValue (IC_RESULT (ic));
2043 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2046 /* adjust the stack for parameters if
2051 if (ic->parmBytes > 3)
2053 emitcode ("mov", "a,%s", spname);
2054 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2055 emitcode ("mov", "%s,a", spname);
2058 for (i = 0; i < ic->parmBytes; i++)
2059 emitcode ("dec", "%s", spname);
2062 /* if we hade saved some registers then unsave them */
2063 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2064 unsaveRegisters (ic);
2066 // /* if register bank was saved then pop them */
2068 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2071 /*-----------------------------------------------------------------*/
2072 /* -10l - generates a call by pointer statement */
2073 /*-----------------------------------------------------------------*/
2075 genPcall (iCode * ic)
2078 symbol *rlbl = newiTempLabel (NULL);
2079 // bool restoreBank=FALSE;
2080 bool swapBanks = FALSE;
2082 D(emitcode("; genPCall",""));
2084 /* if caller saves & we have not saved then */
2088 /* if we are calling a not _naked function that is not using
2089 the same register bank then we need to save the
2090 destination registers on the stack */
2091 dtype = operandType (IC_LEFT (ic))->next;
2092 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2093 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2094 !IFFUNC_ISISR (dtype))
2096 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2097 // restoreBank=TRUE;
2099 // need caution message to user here
2102 /* push the return address on to the stack */
2103 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2104 emitcode ("push", "acc");
2105 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2106 emitcode ("push", "acc");
2108 /* now push the calling address */
2109 aopOp (IC_LEFT (ic), ic, FALSE);
2111 pushSide (IC_LEFT (ic), FPTRSIZE);
2113 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2115 /* if send set is not empty the assign */
2118 genSend(reverseSet(_G.sendSet));
2124 emitcode ("mov", "psw,#0x%02x",
2125 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2129 emitcode ("ret", "");
2130 emitcode ("", "%05d$:", (rlbl->key + 100));
2135 emitcode ("mov", "psw,#0x%02x",
2136 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2139 /* if we need assign a result value */
2140 if ((IS_ITEMP (IC_RESULT (ic)) &&
2141 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2142 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2143 IS_TRUE_SYMOP (IC_RESULT (ic)))
2147 aopOp (IC_RESULT (ic), ic, FALSE);
2150 assignResultValue (IC_RESULT (ic));
2152 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2155 /* adjust the stack for parameters if
2160 if (ic->parmBytes > 3)
2162 emitcode ("mov", "a,%s", spname);
2163 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2164 emitcode ("mov", "%s,a", spname);
2167 for (i = 0; i < ic->parmBytes; i++)
2168 emitcode ("dec", "%s", spname);
2172 // /* if register bank was saved then unsave them */
2174 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2176 /* if we hade saved some registers then
2178 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2179 unsaveRegisters (ic);
2182 /*-----------------------------------------------------------------*/
2183 /* resultRemat - result is rematerializable */
2184 /*-----------------------------------------------------------------*/
2186 resultRemat (iCode * ic)
2188 if (SKIP_IC (ic) || ic->op == IFX)
2191 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2193 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2194 if (sym->remat && !POINTER_SET (ic))
2201 #if defined(__BORLANDC__) || defined(_MSC_VER)
2202 #define STRCASECMP stricmp
2204 #define STRCASECMP strcasecmp
2207 /*-----------------------------------------------------------------*/
2208 /* inExcludeList - return 1 if the string is in exclude Reg list */
2209 /*-----------------------------------------------------------------*/
2211 inExcludeList (char *s)
2215 if (options.excludeRegs[i] &&
2216 STRCASECMP (options.excludeRegs[i], "none") == 0)
2219 for (i = 0; options.excludeRegs[i]; i++)
2221 if (options.excludeRegs[i] &&
2222 STRCASECMP (s, options.excludeRegs[i]) == 0)
2228 /*-----------------------------------------------------------------*/
2229 /* genFunction - generated code for function entry */
2230 /*-----------------------------------------------------------------*/
2232 genFunction (iCode * ic)
2236 bool switchedPSW = FALSE;
2237 int calleesaves_saved_register = -1;
2240 /* create the function header */
2241 emitcode (";", "-----------------------------------------");
2242 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2243 emitcode (";", "-----------------------------------------");
2245 emitcode ("", "%s:", sym->rname);
2246 ftype = operandType (IC_LEFT (ic));
2248 if (IFFUNC_ISNAKED(ftype))
2250 emitcode(";", "naked function: no prologue.");
2254 /* if critical function then turn interrupts off */
2255 if (IFFUNC_ISCRITICAL (ftype))
2256 emitcode ("clr", "ea");
2258 /* here we need to generate the equates for the
2259 register bank if required */
2260 if (FUNC_REGBANK (ftype) != rbank)
2264 rbank = FUNC_REGBANK (ftype);
2265 for (i = 0; i < mcs51_nRegs; i++)
2267 if (strcmp (regs8051[i].base, "0") == 0)
2268 emitcode ("", "%s = 0x%02x",
2270 8 * rbank + regs8051[i].offset);
2272 emitcode ("", "%s = %s + 0x%02x",
2275 8 * rbank + regs8051[i].offset);
2279 /* if this is an interrupt service routine then
2280 save acc, b, dpl, dph */
2281 if (IFFUNC_ISISR (sym->type))
2284 if (!inExcludeList ("acc"))
2285 emitcode ("push", "acc");
2286 if (!inExcludeList ("b"))
2287 emitcode ("push", "b");
2288 if (!inExcludeList ("dpl"))
2289 emitcode ("push", "dpl");
2290 if (!inExcludeList ("dph"))
2291 emitcode ("push", "dph");
2292 /* if this isr has no bank i.e. is going to
2293 run with bank 0 , then we need to save more
2295 if (!FUNC_REGBANK (sym->type))
2298 /* if this function does not call any other
2299 function then we can be economical and
2300 save only those registers that are used */
2301 if (!IFFUNC_HASFCALL(sym->type))
2305 /* if any registers used */
2308 /* save the registers used */
2309 for (i = 0; i < sym->regsUsed->size; i++)
2311 if (bitVectBitValue (sym->regsUsed, i) ||
2312 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2313 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2321 /* this function has a function call cannot
2322 determines register usage so we will have to push the
2324 saveRBank (0, ic, FALSE);
2325 if (options.parms_in_bank1) {
2327 for (i=0; i < 8 ; i++ ) {
2328 emitcode ("push","%s",rb1regs[i]);
2335 /* This ISR uses a non-zero bank.
2337 * We assume that the bank is available for our
2340 * However, if this ISR calls a function which uses some
2341 * other bank, we must save that bank entirely.
2343 unsigned long banksToSave = 0;
2345 if (IFFUNC_HASFCALL(sym->type))
2348 #define MAX_REGISTER_BANKS 4
2353 for (i = ic; i; i = i->next)
2355 if (i->op == ENDFUNCTION)
2357 /* we got to the end OK. */
2365 dtype = operandType (IC_LEFT(i));
2367 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2369 /* Mark this bank for saving. */
2370 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2372 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2376 banksToSave |= (1 << FUNC_REGBANK(dtype));
2379 /* And note that we don't need to do it in
2387 /* This is a mess; we have no idea what
2388 * register bank the called function might
2391 * The only thing I can think of to do is
2392 * throw a warning and hope.
2394 werror(W_FUNCPTR_IN_USING_ISR);
2398 if (banksToSave && options.useXstack)
2400 /* Since we aren't passing it an ic,
2401 * saveRBank will assume r0 is available to abuse.
2403 * So switch to our (trashable) bank now, so
2404 * the caller's R0 isn't trashed.
2406 emitcode ("push", "psw");
2407 emitcode ("mov", "psw,#0x%02x",
2408 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2412 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2414 if (banksToSave & (1 << ix))
2416 saveRBank(ix, NULL, FALSE);
2420 // jwk: this needs a closer look
2421 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2426 /* if callee-save to be used for this function
2427 then save the registers being used in this function */
2428 if (IFFUNC_CALLEESAVES(sym->type))
2432 /* if any registers used */
2435 /* save the registers used */
2436 for (i = 0; i < sym->regsUsed->size; i++)
2438 if (bitVectBitValue (sym->regsUsed, i) ||
2439 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2441 /* remember one saved register for later usage */
2442 if (calleesaves_saved_register < 0)
2443 calleesaves_saved_register = i;
2444 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2452 /* set the register bank to the desired value */
2453 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2456 emitcode ("push", "psw");
2457 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2460 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2463 if (options.useXstack)
2465 emitcode ("mov", "r0,%s", spname);
2466 emitcode ("mov", "a,_bp");
2467 emitcode ("movx", "@r0,a");
2468 emitcode ("inc", "%s", spname);
2472 /* set up the stack */
2473 emitcode ("push", "_bp"); /* save the callers stack */
2475 emitcode ("mov", "_bp,%s", spname);
2478 /* adjust the stack for the function */
2484 werror (W_STACK_OVERFLOW, sym->name);
2486 if (i > 3 && sym->recvSize < 4)
2489 emitcode ("mov", "a,sp");
2490 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2491 emitcode ("mov", "sp,a");
2496 if (IFFUNC_CALLEESAVES(sym->type))
2498 /* if it's a callee-saves function we need a saved register */
2499 if (calleesaves_saved_register >= 0)
2501 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2502 emitcode ("mov", "a,sp");
2503 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2504 emitcode ("mov", "sp,a");
2505 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2508 /* do it the hard way */
2510 emitcode ("inc", "sp");
2514 /* not callee-saves, we can clobber r0 */
2515 emitcode ("mov", "r0,a");
2516 emitcode ("mov", "a,sp");
2517 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2518 emitcode ("mov", "sp,a");
2519 emitcode ("mov", "a,r0");
2524 emitcode ("inc", "sp");
2530 emitcode ("mov", "a,_spx");
2531 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2532 emitcode ("mov", "_spx,a");
2537 /*-----------------------------------------------------------------*/
2538 /* genEndFunction - generates epilogue for functions */
2539 /*-----------------------------------------------------------------*/
2541 genEndFunction (iCode * ic)
2543 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2545 if (IFFUNC_ISNAKED(sym->type))
2547 emitcode(";", "naked function: no epilogue.");
2551 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2553 emitcode ("mov", "%s,_bp", spname);
2556 /* if use external stack but some variables were
2557 added to the local stack then decrement the
2559 if (options.useXstack && sym->stack)
2561 emitcode ("mov", "a,sp");
2562 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2563 emitcode ("mov", "sp,a");
2567 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2569 if (options.useXstack)
2571 emitcode ("mov", "r0,%s", spname);
2572 emitcode ("movx", "a,@r0");
2573 emitcode ("mov", "_bp,a");
2574 emitcode ("dec", "%s", spname);
2578 emitcode ("pop", "_bp");
2582 /* restore the register bank */
2583 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2585 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2586 || !options.useXstack)
2588 /* Special case of ISR using non-zero bank with useXstack
2591 emitcode ("pop", "psw");
2595 if (IFFUNC_ISISR (sym->type))
2598 /* now we need to restore the registers */
2599 /* if this isr has no bank i.e. is going to
2600 run with bank 0 , then we need to save more
2602 if (!FUNC_REGBANK (sym->type))
2604 /* if this function does not call any other
2605 function then we can be economical and
2606 save only those registers that are used */
2607 if (!IFFUNC_HASFCALL(sym->type))
2611 /* if any registers used */
2614 /* save the registers used */
2615 for (i = sym->regsUsed->size; i >= 0; i--)
2617 if (bitVectBitValue (sym->regsUsed, i) ||
2618 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2619 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2626 if (options.parms_in_bank1) {
2628 for (i = 7 ; i >= 0 ; i-- ) {
2629 emitcode ("pop","%s",rb1regs[i]);
2632 /* this function has a function call cannot
2633 determines register usage so we will have to pop the
2635 unsaveRBank (0, ic, FALSE);
2640 /* This ISR uses a non-zero bank.
2642 * Restore any register banks saved by genFunction
2645 // jwk: this needs a closer look
2646 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2649 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2651 if (savedBanks & (1 << ix))
2653 unsaveRBank(ix, NULL, FALSE);
2657 if (options.useXstack)
2659 /* Restore bank AFTER calling unsaveRBank,
2660 * since it can trash r0.
2662 emitcode ("pop", "psw");
2666 if (!inExcludeList ("dph"))
2667 emitcode ("pop", "dph");
2668 if (!inExcludeList ("dpl"))
2669 emitcode ("pop", "dpl");
2670 if (!inExcludeList ("b"))
2671 emitcode ("pop", "b");
2672 if (!inExcludeList ("acc"))
2673 emitcode ("pop", "acc");
2675 if (IFFUNC_ISCRITICAL (sym->type))
2676 emitcode ("setb", "ea");
2678 /* if debug then send end of function */
2679 if (options.debug && currFunc)
2682 emitcode ("", "C$%s$%d$%d$%d ==.",
2683 FileBaseName (ic->filename), currFunc->lastLine,
2684 ic->level, ic->block);
2685 if (IS_STATIC (currFunc->etype))
2686 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2688 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2692 emitcode ("reti", "");
2696 if (IFFUNC_ISCRITICAL (sym->type))
2697 emitcode ("setb", "ea");
2699 if (IFFUNC_CALLEESAVES(sym->type))
2703 /* if any registers used */
2706 /* save the registers used */
2707 for (i = sym->regsUsed->size; i >= 0; i--)
2709 if (bitVectBitValue (sym->regsUsed, i) ||
2710 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2711 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2717 /* if debug then send end of function */
2718 if (options.debug && currFunc)
2721 emitcode ("", "C$%s$%d$%d$%d ==.",
2722 FileBaseName (ic->filename), currFunc->lastLine,
2723 ic->level, ic->block);
2724 if (IS_STATIC (currFunc->etype))
2725 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2727 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2731 emitcode ("ret", "");
2736 /*-----------------------------------------------------------------*/
2737 /* genRet - generate code for return statement */
2738 /*-----------------------------------------------------------------*/
2742 int size, offset = 0, pushed = 0;
2744 D(emitcode ("; genRet",""));
2746 /* if we have no return value then
2747 just generate the "ret" */
2751 /* we have something to return then
2752 move the return value into place */
2753 aopOp (IC_LEFT (ic), ic, FALSE);
2754 size = AOP_SIZE (IC_LEFT (ic));
2759 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2762 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2764 emitcode ("push", "%s", l);
2769 l = aopGet (AOP (IC_LEFT (ic)), offset,
2771 if (strcmp (fReturn[offset], l))
2772 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2781 if (strcmp (fReturn[pushed], "a"))
2782 emitcode ("pop", fReturn[pushed]);
2784 emitcode ("pop", "acc");
2787 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2790 /* generate a jump to the return label
2791 if the next is not the return statement */
2792 if (!(ic->next && ic->next->op == LABEL &&
2793 IC_LABEL (ic->next) == returnLabel))
2795 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2799 /*-----------------------------------------------------------------*/
2800 /* genLabel - generates a label */
2801 /*-----------------------------------------------------------------*/
2803 genLabel (iCode * ic)
2805 /* special case never generate */
2806 if (IC_LABEL (ic) == entryLabel)
2809 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2812 /*-----------------------------------------------------------------*/
2813 /* genGoto - generates a ljmp */
2814 /*-----------------------------------------------------------------*/
2816 genGoto (iCode * ic)
2818 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2821 /*-----------------------------------------------------------------*/
2822 /* findLabelBackwards: walks back through the iCode chain looking */
2823 /* for the given label. Returns number of iCode instructions */
2824 /* between that label and given ic. */
2825 /* Returns zero if label not found. */
2826 /*-----------------------------------------------------------------*/
2828 findLabelBackwards (iCode * ic, int key)
2837 /* If we have any pushes or pops, we cannot predict the distance.
2838 I don't like this at all, this should be dealt with in the
2840 if (ic->op == IPUSH || ic->op == IPOP) {
2844 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2853 /*-----------------------------------------------------------------*/
2854 /* genPlusIncr :- does addition with increment if possible */
2855 /*-----------------------------------------------------------------*/
2857 genPlusIncr (iCode * ic)
2859 unsigned int icount;
2860 unsigned int size = getDataSize (IC_RESULT (ic));
2862 /* will try to generate an increment */
2863 /* if the right side is not a literal
2865 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2868 /* if the literal value of the right hand side
2869 is greater than 4 then it is not worth it */
2870 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2873 D(emitcode ("; genPlusIncr",""));
2875 /* if increment 16 bits in register */
2876 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2877 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2885 /* If the next instruction is a goto and the goto target
2886 * is < 10 instructions previous to this, we can generate
2887 * jumps straight to that target.
2889 if (ic->next && ic->next->op == GOTO
2890 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2891 && labelRange <= 10)
2893 emitcode (";", "tail increment optimized");
2894 tlbl = IC_LABEL (ic->next);
2899 tlbl = newiTempLabel (NULL);
2902 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2903 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2904 IS_AOP_PREG (IC_RESULT (ic)))
2905 emitcode ("cjne", "%s,#0x00,%05d$",
2906 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2910 emitcode ("clr", "a");
2911 emitcode ("cjne", "a,%s,%05d$",
2912 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2916 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2919 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2920 IS_AOP_PREG (IC_RESULT (ic)))
2921 emitcode ("cjne", "%s,#0x00,%05d$",
2922 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2925 emitcode ("cjne", "a,%s,%05d$",
2926 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2929 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2933 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2934 IS_AOP_PREG (IC_RESULT (ic)))
2935 emitcode ("cjne", "%s,#0x00,%05d$",
2936 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2940 emitcode ("cjne", "a,%s,%05d$",
2941 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2944 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2949 emitcode ("", "%05d$:", tlbl->key + 100);
2954 /* if the sizes are greater than 1 then we cannot */
2955 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2956 AOP_SIZE (IC_LEFT (ic)) > 1)
2959 /* we can if the aops of the left & result match or
2960 if they are in registers and the registers are the
2962 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2967 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2968 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2969 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2975 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2984 /*-----------------------------------------------------------------*/
2985 /* outBitAcc - output a bit in acc */
2986 /*-----------------------------------------------------------------*/
2988 outBitAcc (operand * result)
2990 symbol *tlbl = newiTempLabel (NULL);
2991 /* if the result is a bit */
2992 if (AOP_TYPE (result) == AOP_CRY)
2994 aopPut (AOP (result), "a", 0);
2998 emitcode ("jz", "%05d$", tlbl->key + 100);
2999 emitcode ("mov", "a,%s", one);
3000 emitcode ("", "%05d$:", tlbl->key + 100);
3005 /*-----------------------------------------------------------------*/
3006 /* genPlusBits - generates code for addition of two bits */
3007 /*-----------------------------------------------------------------*/
3009 genPlusBits (iCode * ic)
3011 D(emitcode ("; genPlusBits",""));
3013 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3015 symbol *lbl = newiTempLabel (NULL);
3016 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3017 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3018 emitcode ("cpl", "c");
3019 emitcode ("", "%05d$:", (lbl->key + 100));
3020 outBitC (IC_RESULT (ic));
3024 emitcode ("clr", "a");
3025 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3026 emitcode ("rlc", "a");
3027 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3028 emitcode ("addc", "a,#0x00");
3029 outAcc (IC_RESULT (ic));
3034 /* This is the original version of this code.
3036 * This is being kept around for reference,
3037 * because I am not entirely sure I got it right...
3040 adjustArithmeticResult (iCode * ic)
3042 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3043 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3044 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3045 aopPut (AOP (IC_RESULT (ic)),
3046 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3049 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3050 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3051 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3052 aopPut (AOP (IC_RESULT (ic)),
3053 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3056 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3057 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3058 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3059 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3060 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3063 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3064 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3068 /* This is the pure and virtuous version of this code.
3069 * I'm pretty certain it's right, but not enough to toss the old
3073 adjustArithmeticResult (iCode * ic)
3075 if (opIsGptr (IC_RESULT (ic)) &&
3076 opIsGptr (IC_LEFT (ic)) &&
3077 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3079 aopPut (AOP (IC_RESULT (ic)),
3080 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3084 if (opIsGptr (IC_RESULT (ic)) &&
3085 opIsGptr (IC_RIGHT (ic)) &&
3086 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3088 aopPut (AOP (IC_RESULT (ic)),
3089 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3093 if (opIsGptr (IC_RESULT (ic)) &&
3094 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3095 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3096 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3097 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3100 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3101 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3106 /*-----------------------------------------------------------------*/
3107 /* genPlus - generates code for addition */
3108 /*-----------------------------------------------------------------*/
3110 genPlus (iCode * ic)
3112 int size, offset = 0;
3114 asmop *leftOp, *rightOp;
3116 /* special cases :- */
3118 D(emitcode ("; genPlus",""));
3120 aopOp (IC_LEFT (ic), ic, FALSE);
3121 aopOp (IC_RIGHT (ic), ic, FALSE);
3122 aopOp (IC_RESULT (ic), ic, TRUE);
3124 /* if literal, literal on the right or
3125 if left requires ACC or right is already
3127 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3128 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3129 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3131 operand *t = IC_RIGHT (ic);
3132 IC_RIGHT (ic) = IC_LEFT (ic);
3136 /* if both left & right are in bit
3138 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3139 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3145 /* if left in bit space & right literal */
3146 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3147 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3149 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3150 /* if result in bit space */
3151 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3153 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3154 emitcode ("cpl", "c");
3155 outBitC (IC_RESULT (ic));
3159 size = getDataSize (IC_RESULT (ic));
3162 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3163 emitcode ("addc", "a,#00");
3164 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3170 /* if I can do an increment instead
3171 of add then GOOD for ME */
3172 if (genPlusIncr (ic) == TRUE)
3175 size = getDataSize (IC_RESULT (ic));
3177 leftOp = AOP(IC_LEFT(ic));
3178 rightOp = AOP(IC_RIGHT(ic));
3183 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3185 emitcode("mov", "b,a");
3186 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3187 emitcode("xch", "a,b");
3188 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3189 emitcode (add, "a,b");
3191 else if (aopGetUsesAcc (leftOp, offset))
3193 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3194 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3198 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3199 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3201 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3202 add = "addc"; /* further adds must propagate carry */
3205 adjustArithmeticResult (ic);
3208 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3209 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3213 /*-----------------------------------------------------------------*/
3214 /* genMinusDec :- does subtraction with deccrement if possible */
3215 /*-----------------------------------------------------------------*/
3217 genMinusDec (iCode * ic)
3219 unsigned int icount;
3220 unsigned int size = getDataSize (IC_RESULT (ic));
3222 /* will try to generate an increment */
3223 /* if the right side is not a literal
3225 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3228 /* if the literal value of the right hand side
3229 is greater than 4 then it is not worth it */
3230 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3233 D(emitcode ("; genMinusDec",""));
3235 /* if decrement 16 bits in register */
3236 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3237 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3245 /* If the next instruction is a goto and the goto target
3246 * is <= 10 instructions previous to this, we can generate
3247 * jumps straight to that target.
3249 if (ic->next && ic->next->op == GOTO
3250 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3251 && labelRange <= 10)
3253 emitcode (";", "tail decrement optimized");
3254 tlbl = IC_LABEL (ic->next);
3259 tlbl = newiTempLabel (NULL);
3263 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3264 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3265 IS_AOP_PREG (IC_RESULT (ic)))
3266 emitcode ("cjne", "%s,#0xff,%05d$"
3267 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3271 emitcode ("mov", "a,#0xff");
3272 emitcode ("cjne", "a,%s,%05d$"
3273 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3276 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3279 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3280 IS_AOP_PREG (IC_RESULT (ic)))
3281 emitcode ("cjne", "%s,#0xff,%05d$"
3282 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3286 emitcode ("cjne", "a,%s,%05d$"
3287 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3290 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3294 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3295 IS_AOP_PREG (IC_RESULT (ic)))
3296 emitcode ("cjne", "%s,#0xff,%05d$"
3297 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3301 emitcode ("cjne", "a,%s,%05d$"
3302 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3305 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3309 emitcode ("", "%05d$:", tlbl->key + 100);
3314 /* if the sizes are greater than 1 then we cannot */
3315 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3316 AOP_SIZE (IC_LEFT (ic)) > 1)
3319 /* we can if the aops of the left & result match or
3320 if they are in registers and the registers are the
3322 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3326 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3334 /*-----------------------------------------------------------------*/
3335 /* addSign - complete with sign */
3336 /*-----------------------------------------------------------------*/
3338 addSign (operand * result, int offset, int sign)
3340 int size = (getDataSize (result) - offset);
3345 emitcode ("rlc", "a");
3346 emitcode ("subb", "a,acc");
3348 aopPut (AOP (result), "a", offset++);
3352 aopPut (AOP (result), zero, offset++);
3356 /*-----------------------------------------------------------------*/
3357 /* genMinusBits - generates code for subtraction of two bits */
3358 /*-----------------------------------------------------------------*/
3360 genMinusBits (iCode * ic)
3362 symbol *lbl = newiTempLabel (NULL);
3364 D(emitcode ("; genMinusBits",""));
3366 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3368 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3369 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3370 emitcode ("cpl", "c");
3371 emitcode ("", "%05d$:", (lbl->key + 100));
3372 outBitC (IC_RESULT (ic));
3376 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3377 emitcode ("subb", "a,acc");
3378 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3379 emitcode ("inc", "a");
3380 emitcode ("", "%05d$:", (lbl->key + 100));
3381 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3382 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3386 /*-----------------------------------------------------------------*/
3387 /* genMinus - generates code for subtraction */
3388 /*-----------------------------------------------------------------*/
3390 genMinus (iCode * ic)
3392 int size, offset = 0;
3394 D(emitcode ("; genMinus",""));
3396 aopOp (IC_LEFT (ic), ic, FALSE);
3397 aopOp (IC_RIGHT (ic), ic, FALSE);
3398 aopOp (IC_RESULT (ic), ic, TRUE);
3400 /* special cases :- */
3401 /* if both left & right are in bit space */
3402 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3403 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3409 /* if I can do an decrement instead
3410 of subtract then GOOD for ME */
3411 if (genMinusDec (ic) == TRUE)
3414 size = getDataSize (IC_RESULT (ic));
3416 /* if literal, add a,#-lit, else normal subb */
3417 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3419 unsigned long lit = 0L;
3421 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3426 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3427 /* first add without previous c */
3429 if (!size && lit==-1) {
3430 emitcode ("dec", "a");
3432 emitcode ("add", "a,#0x%02x",
3433 (unsigned int) (lit & 0x0FFL));
3436 emitcode ("addc", "a,#0x%02x",
3437 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3439 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3444 asmop *leftOp, *rightOp;
3446 leftOp = AOP(IC_LEFT(ic));
3447 rightOp = AOP(IC_RIGHT(ic));
3451 if (aopGetUsesAcc(rightOp, offset)) {
3452 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3453 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3455 emitcode( "setb", "c");
3457 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3458 emitcode("cpl", "a");
3460 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3463 emitcode ("subb", "a,%s",
3464 aopGet(rightOp, offset, FALSE, TRUE));
3467 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3472 adjustArithmeticResult (ic);
3475 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3476 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3477 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3481 /*-----------------------------------------------------------------*/
3482 /* genMultbits :- multiplication of bits */
3483 /*-----------------------------------------------------------------*/
3485 genMultbits (operand * left,
3489 D(emitcode ("; genMultbits",""));
3491 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3492 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3497 /*-----------------------------------------------------------------*/
3498 /* genMultOneByte : 8*8=8/16 bit multiplication */
3499 /*-----------------------------------------------------------------*/
3501 genMultOneByte (operand * left,
3505 sym_link *opetype = operandType (result);
3507 int size=AOP_SIZE(result);
3509 D(emitcode ("; genMultOneByte",""));
3511 if (size<1 || size>2) {
3512 // this should never happen
3513 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3514 AOP_SIZE(result), __FILE__, lineno);
3518 /* (if two literals: the value is computed before) */
3519 /* if one literal, literal on the right */
3520 if (AOP_TYPE (left) == AOP_LIT)
3525 //emitcode (";", "swapped left and right");
3528 if (SPEC_USIGN(opetype)
3529 // ignore the sign of left and right, what else can we do?
3530 || (SPEC_USIGN(operandType(left)) &&
3531 SPEC_USIGN(operandType(right)))) {
3532 // just an unsigned 8*8=8/16 multiply
3533 //emitcode (";","unsigned");
3534 // TODO: check for accumulator clash between left & right aops?
3535 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3536 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3537 emitcode ("mul", "ab");
3538 aopPut (AOP (result), "a", 0);
3540 aopPut (AOP (result), "b", 1);
3545 // we have to do a signed multiply
3547 //emitcode (";", "signed");
3548 emitcode ("clr", "F0"); // reset sign flag
3549 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3551 lbl=newiTempLabel(NULL);
3552 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3553 // left side is negative, 8-bit two's complement, this fails for -128
3554 emitcode ("setb", "F0"); // set sign flag
3555 emitcode ("cpl", "a");
3556 emitcode ("inc", "a");
3558 emitcode ("", "%05d$:", lbl->key+100);
3561 if (AOP_TYPE(right)==AOP_LIT) {
3562 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3563 /* AND literal negative */
3565 emitcode ("cpl", "F0"); // complement sign flag
3566 emitcode ("mov", "b,#0x%02x", -val);
3568 emitcode ("mov", "b,#0x%02x", val);
3571 lbl=newiTempLabel(NULL);
3572 emitcode ("mov", "b,a");
3573 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3574 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3575 // right side is negative, 8-bit two's complement
3576 emitcode ("cpl", "F0"); // complement sign flag
3577 emitcode ("cpl", "a");
3578 emitcode ("inc", "a");
3579 emitcode ("", "%05d$:", lbl->key+100);
3581 emitcode ("mul", "ab");
3583 lbl=newiTempLabel(NULL);
3584 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3585 // only ONE op was negative, we have to do a 8/16-bit two's complement
3586 emitcode ("cpl", "a"); // lsb
3588 emitcode ("inc", "a");
3590 emitcode ("add", "a,#1");
3591 emitcode ("xch", "a,b");
3592 emitcode ("cpl", "a"); // msb
3593 emitcode ("addc", "a,#0");
3594 emitcode ("xch", "a,b");
3597 emitcode ("", "%05d$:", lbl->key+100);
3598 aopPut (AOP (result), "a", 0);
3600 aopPut (AOP (result), "b", 1);
3604 /*-----------------------------------------------------------------*/
3605 /* genMult - generates code for multiplication */
3606 /*-----------------------------------------------------------------*/
3608 genMult (iCode * ic)
3610 operand *left = IC_LEFT (ic);
3611 operand *right = IC_RIGHT (ic);
3612 operand *result = IC_RESULT (ic);
3614 D(emitcode ("; genMult",""));
3616 /* assign the amsops */
3617 aopOp (left, ic, FALSE);
3618 aopOp (right, ic, FALSE);
3619 aopOp (result, ic, TRUE);
3621 /* special cases first */
3623 if (AOP_TYPE (left) == AOP_CRY &&
3624 AOP_TYPE (right) == AOP_CRY)
3626 genMultbits (left, right, result);
3630 /* if both are of size == 1 */
3631 #if 0 // one of them can be a sloc shared with the result
3632 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3634 if (getSize(operandType(left)) == 1 &&
3635 getSize(operandType(right)) == 1)
3638 genMultOneByte (left, right, result);
3642 /* should have been converted to function call */
3643 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3644 getSize(OP_SYMBOL(right)->type));
3648 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3649 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3650 freeAsmop (result, NULL, ic, TRUE);
3653 /*-----------------------------------------------------------------*/
3654 /* genDivbits :- division of bits */
3655 /*-----------------------------------------------------------------*/
3657 genDivbits (operand * left,
3664 D(emitcode ("; genDivbits",""));
3666 /* the result must be bit */
3667 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3668 l = aopGet (AOP (left), 0, FALSE, FALSE);
3672 emitcode ("div", "ab");
3673 emitcode ("rrc", "a");
3674 aopPut (AOP (result), "c", 0);
3677 /*-----------------------------------------------------------------*/
3678 /* genDivOneByte : 8 bit division */
3679 /*-----------------------------------------------------------------*/
3681 genDivOneByte (operand * left,
3685 sym_link *opetype = operandType (result);
3690 D(emitcode ("; genDivOneByte",""));
3692 size = AOP_SIZE (result) - 1;
3694 /* signed or unsigned */
3695 if (SPEC_USIGN (opetype))
3697 /* unsigned is easy */
3698 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3699 l = aopGet (AOP (left), 0, FALSE, FALSE);
3701 emitcode ("div", "ab");
3702 aopPut (AOP (result), "a", 0);
3704 aopPut (AOP (result), zero, offset++);
3708 /* signed is a little bit more difficult */
3710 /* save the signs of the operands */
3711 l = aopGet (AOP (left), 0, FALSE, FALSE);
3713 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3714 emitcode ("push", "acc"); /* save it on the stack */
3716 /* now sign adjust for both left & right */
3717 l = aopGet (AOP (right), 0, FALSE, FALSE);
3719 lbl = newiTempLabel (NULL);
3720 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3721 emitcode ("cpl", "a");
3722 emitcode ("inc", "a");
3723 emitcode ("", "%05d$:", (lbl->key + 100));
3724 emitcode ("mov", "b,a");
3726 /* sign adjust left side */
3727 l = aopGet (AOP (left), 0, FALSE, FALSE);
3730 lbl = newiTempLabel (NULL);
3731 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3732 emitcode ("cpl", "a");
3733 emitcode ("inc", "a");
3734 emitcode ("", "%05d$:", (lbl->key + 100));
3736 /* now the division */
3737 emitcode ("div", "ab");
3738 /* we are interested in the lower order
3740 emitcode ("mov", "b,a");
3741 lbl = newiTempLabel (NULL);
3742 emitcode ("pop", "acc");
3743 /* if there was an over flow we don't
3744 adjust the sign of the result */
3745 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3746 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3748 emitcode ("clr", "a");
3749 emitcode ("subb", "a,b");
3750 emitcode ("mov", "b,a");
3751 emitcode ("", "%05d$:", (lbl->key + 100));
3753 /* now we are done */
3754 aopPut (AOP (result), "b", 0);
3757 emitcode ("mov", "c,b.7");
3758 emitcode ("subb", "a,acc");
3761 aopPut (AOP (result), "a", offset++);
3765 /*-----------------------------------------------------------------*/
3766 /* genDiv - generates code for division */
3767 /*-----------------------------------------------------------------*/
3771 operand *left = IC_LEFT (ic);
3772 operand *right = IC_RIGHT (ic);
3773 operand *result = IC_RESULT (ic);
3775 D(emitcode ("; genDiv",""));
3777 /* assign the amsops */
3778 aopOp (left, ic, FALSE);
3779 aopOp (right, ic, FALSE);
3780 aopOp (result, ic, TRUE);
3782 /* special cases first */
3784 if (AOP_TYPE (left) == AOP_CRY &&
3785 AOP_TYPE (right) == AOP_CRY)
3787 genDivbits (left, right, result);
3791 /* if both are of size == 1 */
3792 if (AOP_SIZE (left) == 1 &&
3793 AOP_SIZE (right) == 1)
3795 genDivOneByte (left, right, result);
3799 /* should have been converted to function call */
3802 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3803 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3804 freeAsmop (result, NULL, ic, TRUE);
3807 /*-----------------------------------------------------------------*/
3808 /* genModbits :- modulus of bits */
3809 /*-----------------------------------------------------------------*/
3811 genModbits (operand * left,
3818 D(emitcode ("; genModbits",""));
3820 /* the result must be bit */
3821 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3822 l = aopGet (AOP (left), 0, FALSE, FALSE);
3826 emitcode ("div", "ab");
3827 emitcode ("mov", "a,b");
3828 emitcode ("rrc", "a");
3829 aopPut (AOP (result), "c", 0);
3832 /*-----------------------------------------------------------------*/
3833 /* genModOneByte : 8 bit modulus */
3834 /*-----------------------------------------------------------------*/
3836 genModOneByte (operand * left,
3840 sym_link *opetype = operandType (result);
3844 D(emitcode ("; genModOneByte",""));
3846 /* signed or unsigned */
3847 if (SPEC_USIGN (opetype))
3849 /* unsigned is easy */
3850 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3851 l = aopGet (AOP (left), 0, FALSE, FALSE);
3853 emitcode ("div", "ab");
3854 aopPut (AOP (result), "b", 0);
3858 /* signed is a little bit more difficult */
3860 /* save the signs of the operands */
3861 l = aopGet (AOP (left), 0, FALSE, FALSE);
3864 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3865 emitcode ("push", "acc"); /* save it on the stack */
3867 /* now sign adjust for both left & right */
3868 l = aopGet (AOP (right), 0, FALSE, FALSE);
3871 lbl = newiTempLabel (NULL);
3872 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3873 emitcode ("cpl", "a");
3874 emitcode ("inc", "a");
3875 emitcode ("", "%05d$:", (lbl->key + 100));
3876 emitcode ("mov", "b,a");
3878 /* sign adjust left side */
3879 l = aopGet (AOP (left), 0, FALSE, FALSE);
3882 lbl = newiTempLabel (NULL);
3883 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3884 emitcode ("cpl", "a");
3885 emitcode ("inc", "a");
3886 emitcode ("", "%05d$:", (lbl->key + 100));
3888 /* now the multiplication */
3889 emitcode ("div", "ab");
3890 /* we are interested in the lower order
3892 lbl = newiTempLabel (NULL);
3893 emitcode ("pop", "acc");
3894 /* if there was an over flow we don't
3895 adjust the sign of the result */
3896 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3897 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3899 emitcode ("clr", "a");
3900 emitcode ("subb", "a,b");
3901 emitcode ("mov", "b,a");
3902 emitcode ("", "%05d$:", (lbl->key + 100));
3904 /* now we are done */
3905 aopPut (AOP (result), "b", 0);
3909 /*-----------------------------------------------------------------*/
3910 /* genMod - generates code for division */
3911 /*-----------------------------------------------------------------*/
3915 operand *left = IC_LEFT (ic);
3916 operand *right = IC_RIGHT (ic);
3917 operand *result = IC_RESULT (ic);
3919 D(emitcode ("; genMod",""));
3921 /* assign the amsops */
3922 aopOp (left, ic, FALSE);
3923 aopOp (right, ic, FALSE);
3924 aopOp (result, ic, TRUE);
3926 /* special cases first */
3928 if (AOP_TYPE (left) == AOP_CRY &&
3929 AOP_TYPE (right) == AOP_CRY)
3931 genModbits (left, right, result);
3935 /* if both are of size == 1 */
3936 if (AOP_SIZE (left) == 1 &&
3937 AOP_SIZE (right) == 1)
3939 genModOneByte (left, right, result);
3943 /* should have been converted to function call */
3947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3949 freeAsmop (result, NULL, ic, TRUE);
3952 /*-----------------------------------------------------------------*/
3953 /* genIfxJump :- will create a jump depending on the ifx */
3954 /*-----------------------------------------------------------------*/
3956 genIfxJump (iCode * ic, char *jval)
3959 symbol *tlbl = newiTempLabel (NULL);
3962 D(emitcode ("; genIfxJump",""));
3964 /* if true label then we jump if condition
3968 jlbl = IC_TRUE (ic);
3969 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3970 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3974 /* false label is present */
3975 jlbl = IC_FALSE (ic);
3976 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3977 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3979 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3980 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3982 emitcode (inst, "%05d$", tlbl->key + 100);
3983 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3984 emitcode ("", "%05d$:", tlbl->key + 100);
3986 /* mark the icode as generated */
3990 /*-----------------------------------------------------------------*/
3991 /* genCmp :- greater or less than comparison */
3992 /*-----------------------------------------------------------------*/
3994 genCmp (operand * left, operand * right,
3995 operand * result, iCode * ifx, int sign, iCode *ic)
3997 int size, offset = 0;
3998 unsigned long lit = 0L;
4000 D(emitcode ("; genCmp",""));
4002 /* if left & right are bit variables */
4003 if (AOP_TYPE (left) == AOP_CRY &&
4004 AOP_TYPE (right) == AOP_CRY)
4006 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4007 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4011 /* subtract right from left if at the
4012 end the carry flag is set then we know that
4013 left is greater than right */
4014 size = max (AOP_SIZE (left), AOP_SIZE (right));
4016 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4017 if ((size == 1) && !sign &&
4018 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4020 symbol *lbl = newiTempLabel (NULL);
4021 emitcode ("cjne", "%s,%s,%05d$",
4022 aopGet (AOP (left), offset, FALSE, FALSE),
4023 aopGet (AOP (right), offset, FALSE, FALSE),
4025 emitcode ("", "%05d$:", lbl->key + 100);
4029 if (AOP_TYPE (right) == AOP_LIT)
4031 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4032 /* optimize if(x < 0) or if(x >= 0) */
4041 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4042 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4044 genIfxJump (ifx, "acc.7");
4048 emitcode ("rlc", "a");
4056 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4057 if (sign && size == 0)
4059 emitcode ("xrl", "a,#0x80");
4060 if (AOP_TYPE (right) == AOP_LIT)
4062 unsigned long lit = (unsigned long)
4063 floatFromVal (AOP (right)->aopu.aop_lit);
4064 emitcode ("subb", "a,#0x%02x",
4065 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4069 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4070 emitcode ("xrl", "b,#0x80");
4071 emitcode ("subb", "a,b");
4075 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4081 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4082 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4083 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4089 /* if the result is used in the next
4090 ifx conditional branch then generate
4091 code a little differently */
4093 genIfxJump (ifx, "c");
4096 /* leave the result in acc */
4100 /*-----------------------------------------------------------------*/
4101 /* genCmpGt :- greater than comparison */
4102 /*-----------------------------------------------------------------*/
4104 genCmpGt (iCode * ic, iCode * ifx)
4106 operand *left, *right, *result;
4107 sym_link *letype, *retype;
4110 D(emitcode ("; genCmpGt",""));
4112 left = IC_LEFT (ic);
4113 right = IC_RIGHT (ic);
4114 result = IC_RESULT (ic);
4116 letype = getSpec (operandType (left));
4117 retype = getSpec (operandType (right));
4118 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4119 /* assign the amsops */
4120 aopOp (left, ic, FALSE);
4121 aopOp (right, ic, FALSE);
4122 aopOp (result, ic, TRUE);
4124 genCmp (right, left, result, ifx, sign,ic);
4126 freeAsmop (result, NULL, ic, TRUE);
4129 /*-----------------------------------------------------------------*/
4130 /* genCmpLt - less than comparisons */
4131 /*-----------------------------------------------------------------*/
4133 genCmpLt (iCode * ic, iCode * ifx)
4135 operand *left, *right, *result;
4136 sym_link *letype, *retype;
4139 D(emitcode ("; genCmpLt",""));
4141 left = IC_LEFT (ic);
4142 right = IC_RIGHT (ic);
4143 result = IC_RESULT (ic);
4145 letype = getSpec (operandType (left));
4146 retype = getSpec (operandType (right));
4147 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4149 /* assign the amsops */
4150 aopOp (left, ic, FALSE);
4151 aopOp (right, ic, FALSE);
4152 aopOp (result, ic, TRUE);
4154 genCmp (left, right, result, ifx, sign,ic);
4156 freeAsmop (result, NULL, ic, TRUE);
4159 /*-----------------------------------------------------------------*/
4160 /* gencjneshort - compare and jump if not equal */
4161 /*-----------------------------------------------------------------*/
4163 gencjneshort (operand * left, operand * right, symbol * lbl)
4165 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4167 unsigned long lit = 0L;
4169 /* if the left side is a literal or
4170 if the right is in a pointer register and left
4172 if ((AOP_TYPE (left) == AOP_LIT) ||
4173 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4179 if (AOP_TYPE (right) == AOP_LIT)
4180 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4182 /* if the right side is a literal then anything goes */
4183 if (AOP_TYPE (right) == AOP_LIT &&
4184 AOP_TYPE (left) != AOP_DIR)
4188 emitcode ("cjne", "%s,%s,%05d$",
4189 aopGet (AOP (left), offset, FALSE, FALSE),
4190 aopGet (AOP (right), offset, FALSE, FALSE),
4196 /* if the right side is in a register or in direct space or
4197 if the left is a pointer register & right is not */
4198 else if (AOP_TYPE (right) == AOP_REG ||
4199 AOP_TYPE (right) == AOP_DIR ||
4200 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4201 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4205 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4206 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4207 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4208 emitcode ("jnz", "%05d$", lbl->key + 100);
4210 emitcode ("cjne", "a,%s,%05d$",
4211 aopGet (AOP (right), offset, FALSE, TRUE),
4218 /* right is a pointer reg need both a & b */
4221 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4222 if (strcmp (l, "b"))
4223 emitcode ("mov", "b,%s", l);
4224 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4225 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4231 /*-----------------------------------------------------------------*/
4232 /* gencjne - compare and jump if not equal */
4233 /*-----------------------------------------------------------------*/
4235 gencjne (operand * left, operand * right, symbol * lbl)
4237 symbol *tlbl = newiTempLabel (NULL);
4239 gencjneshort (left, right, lbl);
4241 emitcode ("mov", "a,%s", one);
4242 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4243 emitcode ("", "%05d$:", lbl->key + 100);
4244 emitcode ("clr", "a");
4245 emitcode ("", "%05d$:", tlbl->key + 100);
4248 /*-----------------------------------------------------------------*/
4249 /* genCmpEq - generates code for equal to */
4250 /*-----------------------------------------------------------------*/
4252 genCmpEq (iCode * ic, iCode * ifx)
4254 operand *left, *right, *result;
4256 D(emitcode ("; genCmpEq",""));
4258 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4259 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4260 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4262 /* if literal, literal on the right or
4263 if the right is in a pointer register and left
4265 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4266 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4268 operand *t = IC_RIGHT (ic);
4269 IC_RIGHT (ic) = IC_LEFT (ic);
4273 if (ifx && !AOP_SIZE (result))
4276 /* if they are both bit variables */
4277 if (AOP_TYPE (left) == AOP_CRY &&
4278 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4280 if (AOP_TYPE (right) == AOP_LIT)
4282 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4285 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4286 emitcode ("cpl", "c");
4290 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4294 emitcode ("clr", "c");
4296 /* AOP_TYPE(right) == AOP_CRY */
4300 symbol *lbl = newiTempLabel (NULL);
4301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4302 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4303 emitcode ("cpl", "c");
4304 emitcode ("", "%05d$:", (lbl->key + 100));
4306 /* if true label then we jump if condition
4308 tlbl = newiTempLabel (NULL);
4311 emitcode ("jnc", "%05d$", tlbl->key + 100);
4312 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4316 emitcode ("jc", "%05d$", tlbl->key + 100);
4317 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4319 emitcode ("", "%05d$:", tlbl->key + 100);
4323 tlbl = newiTempLabel (NULL);
4324 gencjneshort (left, right, tlbl);
4327 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4328 emitcode ("", "%05d$:", tlbl->key + 100);
4332 symbol *lbl = newiTempLabel (NULL);
4333 emitcode ("sjmp", "%05d$", lbl->key + 100);
4334 emitcode ("", "%05d$:", tlbl->key + 100);
4335 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4336 emitcode ("", "%05d$:", lbl->key + 100);
4339 /* mark the icode as generated */
4344 /* if they are both bit variables */
4345 if (AOP_TYPE (left) == AOP_CRY &&
4346 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4348 if (AOP_TYPE (right) == AOP_LIT)
4350 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4353 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4354 emitcode ("cpl", "c");
4358 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4362 emitcode ("clr", "c");
4364 /* AOP_TYPE(right) == AOP_CRY */
4368 symbol *lbl = newiTempLabel (NULL);
4369 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4370 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4371 emitcode ("cpl", "c");
4372 emitcode ("", "%05d$:", (lbl->key + 100));
4375 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4382 genIfxJump (ifx, "c");
4385 /* if the result is used in an arithmetic operation
4386 then put the result in place */
4391 gencjne (left, right, newiTempLabel (NULL));
4392 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4394 aopPut (AOP (result), "a", 0);
4399 genIfxJump (ifx, "a");
4402 /* if the result is used in an arithmetic operation
4403 then put the result in place */
4404 if (AOP_TYPE (result) != AOP_CRY)
4406 /* leave the result in acc */
4410 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4411 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4412 freeAsmop (result, NULL, ic, TRUE);
4415 /*-----------------------------------------------------------------*/
4416 /* ifxForOp - returns the icode containing the ifx for operand */
4417 /*-----------------------------------------------------------------*/
4419 ifxForOp (operand * op, iCode * ic)
4421 /* if true symbol then needs to be assigned */
4422 if (IS_TRUE_SYMOP (op))
4425 /* if this has register type condition and
4426 the next instruction is ifx with the same operand
4427 and live to of the operand is upto the ifx only then */
4429 ic->next->op == IFX &&
4430 IC_COND (ic->next)->key == op->key &&
4431 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4437 /*-----------------------------------------------------------------*/
4438 /* hasInc - operand is incremented before any other use */
4439 /*-----------------------------------------------------------------*/
4441 hasInc (operand *op, iCode *ic,int osize)
4443 sym_link *type = operandType(op);
4444 sym_link *retype = getSpec (type);
4445 iCode *lic = ic->next;
4448 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4449 if (!IS_SYMOP(op)) return NULL;
4451 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4452 if (IS_AGGREGATE(type->next)) return NULL;
4453 if (osize != (isize = getSize(type->next))) return NULL;
4456 /* if operand of the form op = op + <sizeof *op> */
4457 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4458 isOperandEqual(IC_RESULT(lic),op) &&
4459 isOperandLiteral(IC_RIGHT(lic)) &&
4460 operandLitValue(IC_RIGHT(lic)) == isize) {
4463 /* if the operand used or deffed */
4464 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4467 /* if GOTO or IFX */
4468 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4474 /*-----------------------------------------------------------------*/
4475 /* genAndOp - for && operation */
4476 /*-----------------------------------------------------------------*/
4478 genAndOp (iCode * ic)
4480 operand *left, *right, *result;
4483 D(emitcode ("; genAndOp",""));
4485 /* note here that && operations that are in an
4486 if statement are taken away by backPatchLabels
4487 only those used in arthmetic operations remain */
4488 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4489 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4490 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4492 /* if both are bit variables */
4493 if (AOP_TYPE (left) == AOP_CRY &&
4494 AOP_TYPE (right) == AOP_CRY)
4496 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4497 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4502 tlbl = newiTempLabel (NULL);
4504 emitcode ("jz", "%05d$", tlbl->key + 100);
4506 emitcode ("", "%05d$:", tlbl->key + 100);
4510 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4511 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4512 freeAsmop (result, NULL, ic, TRUE);
4516 /*-----------------------------------------------------------------*/
4517 /* genOrOp - for || operation */
4518 /*-----------------------------------------------------------------*/
4520 genOrOp (iCode * ic)
4522 operand *left, *right, *result;
4525 D(emitcode ("; genOrOp",""));
4527 /* note here that || operations that are in an
4528 if statement are taken away by backPatchLabels
4529 only those used in arthmetic operations remain */
4530 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4531 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4532 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4534 /* if both are bit variables */
4535 if (AOP_TYPE (left) == AOP_CRY &&
4536 AOP_TYPE (right) == AOP_CRY)
4538 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4539 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4544 tlbl = newiTempLabel (NULL);
4546 emitcode ("jnz", "%05d$", tlbl->key + 100);
4548 emitcode ("", "%05d$:", tlbl->key + 100);
4552 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4553 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4554 freeAsmop (result, NULL, ic, TRUE);
4557 /*-----------------------------------------------------------------*/
4558 /* isLiteralBit - test if lit == 2^n */
4559 /*-----------------------------------------------------------------*/
4561 isLiteralBit (unsigned long lit)
4563 unsigned long pw[32] =
4564 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4565 0x100L, 0x200L, 0x400L, 0x800L,
4566 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4567 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4568 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4569 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4570 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4573 for (idx = 0; idx < 32; idx++)
4579 /*-----------------------------------------------------------------*/
4580 /* continueIfTrue - */
4581 /*-----------------------------------------------------------------*/
4583 continueIfTrue (iCode * ic)
4586 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4590 /*-----------------------------------------------------------------*/
4592 /*-----------------------------------------------------------------*/
4594 jumpIfTrue (iCode * ic)
4597 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4601 /*-----------------------------------------------------------------*/
4602 /* jmpTrueOrFalse - */
4603 /*-----------------------------------------------------------------*/
4605 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4607 // ugly but optimized by peephole
4610 symbol *nlbl = newiTempLabel (NULL);
4611 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4612 emitcode ("", "%05d$:", tlbl->key + 100);
4613 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4614 emitcode ("", "%05d$:", nlbl->key + 100);
4618 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4619 emitcode ("", "%05d$:", tlbl->key + 100);
4624 /*-----------------------------------------------------------------*/
4625 /* genAnd - code for and */
4626 /*-----------------------------------------------------------------*/
4628 genAnd (iCode * ic, iCode * ifx)
4630 operand *left, *right, *result;
4631 int size, offset = 0;
4632 unsigned long lit = 0L;
4636 D(emitcode ("; genAnd",""));
4638 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4639 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4640 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4643 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4645 AOP_TYPE (left), AOP_TYPE (right));
4646 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4648 AOP_SIZE (left), AOP_SIZE (right));
4651 /* if left is a literal & right is not then exchange them */
4652 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4653 AOP_NEEDSACC (left))
4655 operand *tmp = right;
4660 /* if result = right then exchange them */
4661 if (sameRegs (AOP (result), AOP (right)))
4663 operand *tmp = right;
4668 /* if right is bit then exchange them */
4669 if (AOP_TYPE (right) == AOP_CRY &&
4670 AOP_TYPE (left) != AOP_CRY)
4672 operand *tmp = right;
4676 if (AOP_TYPE (right) == AOP_LIT)
4677 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4679 size = AOP_SIZE (result);
4682 // result = bit & yy;
4683 if (AOP_TYPE (left) == AOP_CRY)
4685 // c = bit & literal;
4686 if (AOP_TYPE (right) == AOP_LIT)
4690 if (size && sameRegs (AOP (result), AOP (left)))
4693 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4698 if (size && (AOP_TYPE (result) == AOP_CRY))
4700 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4703 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4708 emitcode ("clr", "c");
4713 if (AOP_TYPE (right) == AOP_CRY)
4716 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4717 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4722 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4724 emitcode ("rrc", "a");
4725 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4733 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4734 genIfxJump (ifx, "c");
4738 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4739 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4740 if ((AOP_TYPE (right) == AOP_LIT) &&
4741 (AOP_TYPE (result) == AOP_CRY) &&
4742 (AOP_TYPE (left) != AOP_CRY))
4744 int posbit = isLiteralBit (lit);
4749 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4752 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4758 sprintf (buffer, "acc.%d", posbit & 0x07);
4759 genIfxJump (ifx, buffer);
4766 symbol *tlbl = newiTempLabel (NULL);
4767 int sizel = AOP_SIZE (left);
4769 emitcode ("setb", "c");
4772 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4774 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4776 if ((posbit = isLiteralBit (bytelit)) != 0)
4777 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4780 if (bytelit != 0x0FFL)
4781 emitcode ("anl", "a,%s",
4782 aopGet (AOP (right), offset, FALSE, TRUE));
4783 emitcode ("jnz", "%05d$", tlbl->key + 100);
4788 // bit = left & literal
4791 emitcode ("clr", "c");
4792 emitcode ("", "%05d$:", tlbl->key + 100);
4794 // if(left & literal)
4798 jmpTrueOrFalse (ifx, tlbl);
4806 /* if left is same as result */
4807 if (sameRegs (AOP (result), AOP (left)))
4809 for (; size--; offset++)
4811 if (AOP_TYPE (right) == AOP_LIT)
4813 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4815 else if (bytelit == 0)
4816 aopPut (AOP (result), zero, offset);
4817 else if (IS_AOP_PREG (result))
4819 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4820 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4821 aopPut (AOP (result), "a", offset);
4824 emitcode ("anl", "%s,%s",
4825 aopGet (AOP (left), offset, FALSE, TRUE),
4826 aopGet (AOP (right), offset, FALSE, FALSE));
4830 if (AOP_TYPE (left) == AOP_ACC)
4831 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4834 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4835 if (IS_AOP_PREG (result))
4837 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4838 aopPut (AOP (result), "a", offset);
4842 emitcode ("anl", "%s,a",
4843 aopGet (AOP (left), offset, FALSE, TRUE));
4850 // left & result in different registers
4851 if (AOP_TYPE (result) == AOP_CRY)
4854 // if(size), result in bit
4855 // if(!size && ifx), conditional oper: if(left & right)
4856 symbol *tlbl = newiTempLabel (NULL);
4857 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4859 emitcode ("setb", "c");
4862 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4863 emitcode ("anl", "a,%s",
4864 aopGet (AOP (right), offset, FALSE, FALSE));
4866 if (AOP_TYPE(left)==AOP_ACC) {
4867 emitcode("mov", "b,a");
4868 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4869 emitcode("anl", "a,b");
4871 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4872 emitcode ("anl", "a,%s",
4873 aopGet (AOP (left), offset, FALSE, FALSE));
4876 emitcode ("jnz", "%05d$", tlbl->key + 100);
4882 emitcode ("", "%05d$:", tlbl->key + 100);
4886 jmpTrueOrFalse (ifx, tlbl);
4890 for (; (size--); offset++)
4893 // result = left & right
4894 if (AOP_TYPE (right) == AOP_LIT)
4896 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4898 aopPut (AOP (result),
4899 aopGet (AOP (left), offset, FALSE, FALSE),
4903 else if (bytelit == 0)
4905 aopPut (AOP (result), zero, offset);
4909 // faster than result <- left, anl result,right
4910 // and better if result is SFR
4911 if (AOP_TYPE (left) == AOP_ACC)
4912 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4915 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4916 emitcode ("anl", "a,%s",
4917 aopGet (AOP (left), offset, FALSE, FALSE));
4919 aopPut (AOP (result), "a", offset);
4925 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4926 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4927 freeAsmop (result, NULL, ic, TRUE);
4930 /*-----------------------------------------------------------------*/
4931 /* genOr - code for or */
4932 /*-----------------------------------------------------------------*/
4934 genOr (iCode * ic, iCode * ifx)
4936 operand *left, *right, *result;
4937 int size, offset = 0;
4938 unsigned long lit = 0L;
4940 D(emitcode ("; genOr",""));
4942 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4943 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4944 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4947 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4949 AOP_TYPE (left), AOP_TYPE (right));
4950 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4952 AOP_SIZE (left), AOP_SIZE (right));
4955 /* if left is a literal & right is not then exchange them */
4956 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4957 AOP_NEEDSACC (left))
4959 operand *tmp = right;
4964 /* if result = right then exchange them */
4965 if (sameRegs (AOP (result), AOP (right)))
4967 operand *tmp = right;
4972 /* if right is bit then exchange them */
4973 if (AOP_TYPE (right) == AOP_CRY &&
4974 AOP_TYPE (left) != AOP_CRY)
4976 operand *tmp = right;
4980 if (AOP_TYPE (right) == AOP_LIT)
4981 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4983 size = AOP_SIZE (result);
4987 if (AOP_TYPE (left) == AOP_CRY)
4989 if (AOP_TYPE (right) == AOP_LIT)
4991 // c = bit | literal;
4994 // lit != 0 => result = 1
4995 if (AOP_TYPE (result) == AOP_CRY)
4998 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5000 continueIfTrue (ifx);
5003 emitcode ("setb", "c");
5007 // lit == 0 => result = left
5008 if (size && sameRegs (AOP (result), AOP (left)))
5010 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5015 if (AOP_TYPE (right) == AOP_CRY)
5018 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5019 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5024 symbol *tlbl = newiTempLabel (NULL);
5025 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5026 emitcode ("setb", "c");
5027 emitcode ("jb", "%s,%05d$",
5028 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5030 emitcode ("jnz", "%05d$", tlbl->key + 100);
5031 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5033 jmpTrueOrFalse (ifx, tlbl);
5039 emitcode ("", "%05d$:", tlbl->key + 100);
5048 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5049 genIfxJump (ifx, "c");
5053 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5054 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5055 if ((AOP_TYPE (right) == AOP_LIT) &&
5056 (AOP_TYPE (result) == AOP_CRY) &&
5057 (AOP_TYPE (left) != AOP_CRY))
5063 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5065 continueIfTrue (ifx);
5070 // lit = 0, result = boolean(left)
5072 emitcode ("setb", "c");
5076 symbol *tlbl = newiTempLabel (NULL);
5077 emitcode ("jnz", "%05d$", tlbl->key + 100);
5079 emitcode ("", "%05d$:", tlbl->key + 100);
5083 genIfxJump (ifx, "a");
5091 /* if left is same as result */
5092 if (sameRegs (AOP (result), AOP (left)))
5094 for (; size--; offset++)
5096 if (AOP_TYPE (right) == AOP_LIT)
5098 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5100 else if (IS_AOP_PREG (left))
5102 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5103 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5104 aopPut (AOP (result), "a", offset);
5107 emitcode ("orl", "%s,%s",
5108 aopGet (AOP (left), offset, FALSE, TRUE),
5109 aopGet (AOP (right), offset, FALSE, FALSE));
5113 if (AOP_TYPE (left) == AOP_ACC)
5114 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5117 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5118 if (IS_AOP_PREG (left))
5120 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5121 aopPut (AOP (result), "a", offset);
5124 emitcode ("orl", "%s,a",
5125 aopGet (AOP (left), offset, FALSE, TRUE));
5132 // left & result in different registers
5133 if (AOP_TYPE (result) == AOP_CRY)
5136 // if(size), result in bit
5137 // if(!size && ifx), conditional oper: if(left | right)
5138 symbol *tlbl = newiTempLabel (NULL);
5139 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5141 emitcode ("setb", "c");
5144 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5145 emitcode ("orl", "a,%s",
5146 aopGet (AOP (right), offset, FALSE, FALSE));
5148 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5149 emitcode ("orl", "a,%s",
5150 aopGet (AOP (left), offset, FALSE, FALSE));
5152 emitcode ("jnz", "%05d$", tlbl->key + 100);
5158 emitcode ("", "%05d$:", tlbl->key + 100);
5162 jmpTrueOrFalse (ifx, tlbl);
5165 for (; (size--); offset++)
5168 // result = left & right
5169 if (AOP_TYPE (right) == AOP_LIT)
5171 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5173 aopPut (AOP (result),
5174 aopGet (AOP (left), offset, FALSE, FALSE),
5179 // faster than result <- left, anl result,right
5180 // and better if result is SFR
5181 if (AOP_TYPE (left) == AOP_ACC)
5182 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5185 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5186 emitcode ("orl", "a,%s",
5187 aopGet (AOP (left), offset, FALSE, FALSE));
5189 aopPut (AOP (result), "a", offset);
5194 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5195 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5196 freeAsmop (result, NULL, ic, TRUE);
5199 /*-----------------------------------------------------------------*/
5200 /* genXor - code for xclusive or */
5201 /*-----------------------------------------------------------------*/
5203 genXor (iCode * ic, iCode * ifx)
5205 operand *left, *right, *result;
5206 int size, offset = 0;
5207 unsigned long lit = 0L;
5209 D(emitcode ("; genXor",""));
5211 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5212 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5213 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5216 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5218 AOP_TYPE (left), AOP_TYPE (right));
5219 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5221 AOP_SIZE (left), AOP_SIZE (right));
5224 /* if left is a literal & right is not ||
5225 if left needs acc & right does not */
5226 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5227 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5229 operand *tmp = right;
5234 /* if result = right then exchange them */
5235 if (sameRegs (AOP (result), AOP (right)))
5237 operand *tmp = right;
5242 /* if right is bit then exchange them */
5243 if (AOP_TYPE (right) == AOP_CRY &&
5244 AOP_TYPE (left) != AOP_CRY)
5246 operand *tmp = right;
5250 if (AOP_TYPE (right) == AOP_LIT)
5251 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5253 size = AOP_SIZE (result);
5257 if (AOP_TYPE (left) == AOP_CRY)
5259 if (AOP_TYPE (right) == AOP_LIT)
5261 // c = bit & literal;
5264 // lit>>1 != 0 => result = 1
5265 if (AOP_TYPE (result) == AOP_CRY)
5268 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5270 continueIfTrue (ifx);
5273 emitcode ("setb", "c");
5280 // lit == 0, result = left
5281 if (size && sameRegs (AOP (result), AOP (left)))
5283 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5287 // lit == 1, result = not(left)
5288 if (size && sameRegs (AOP (result), AOP (left)))
5290 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5296 emitcode ("cpl", "c");
5305 symbol *tlbl = newiTempLabel (NULL);
5306 if (AOP_TYPE (right) == AOP_CRY)
5309 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5313 int sizer = AOP_SIZE (right);
5315 // if val>>1 != 0, result = 1
5316 emitcode ("setb", "c");
5319 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5321 // test the msb of the lsb
5322 emitcode ("anl", "a,#0xfe");
5323 emitcode ("jnz", "%05d$", tlbl->key + 100);
5327 emitcode ("rrc", "a");
5329 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5330 emitcode ("cpl", "c");
5331 emitcode ("", "%05d$:", (tlbl->key + 100));
5338 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5339 genIfxJump (ifx, "c");
5343 if (sameRegs (AOP (result), AOP (left)))
5345 /* if left is same as result */
5346 for (; size--; offset++)
5348 if (AOP_TYPE (right) == AOP_LIT)
5350 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5352 else if (IS_AOP_PREG (left))
5354 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5355 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5356 aopPut (AOP (result), "a", offset);
5359 emitcode ("xrl", "%s,%s",
5360 aopGet (AOP (left), offset, FALSE, TRUE),
5361 aopGet (AOP (right), offset, FALSE, FALSE));
5365 if (AOP_TYPE (left) == AOP_ACC)
5366 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5369 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5370 if (IS_AOP_PREG (left))
5372 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5373 aopPut (AOP (result), "a", offset);
5376 emitcode ("xrl", "%s,a",
5377 aopGet (AOP (left), offset, FALSE, TRUE));
5384 // left & result in different registers
5385 if (AOP_TYPE (result) == AOP_CRY)
5388 // if(size), result in bit
5389 // if(!size && ifx), conditional oper: if(left ^ right)
5390 symbol *tlbl = newiTempLabel (NULL);
5391 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5393 emitcode ("setb", "c");
5396 if ((AOP_TYPE (right) == AOP_LIT) &&
5397 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5399 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5403 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5404 emitcode ("xrl", "a,%s",
5405 aopGet (AOP (right), offset, FALSE, FALSE));
5407 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5408 emitcode ("xrl", "a,%s",
5409 aopGet (AOP (left), offset, FALSE, FALSE));
5412 emitcode ("jnz", "%05d$", tlbl->key + 100);
5418 emitcode ("", "%05d$:", tlbl->key + 100);
5422 jmpTrueOrFalse (ifx, tlbl);
5425 for (; (size--); offset++)
5428 // result = left & right
5429 if (AOP_TYPE (right) == AOP_LIT)
5431 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5433 aopPut (AOP (result),
5434 aopGet (AOP (left), offset, FALSE, FALSE),
5439 // faster than result <- left, anl result,right
5440 // and better if result is SFR
5441 if (AOP_TYPE (left) == AOP_ACC)
5442 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5445 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5446 emitcode ("xrl", "a,%s",
5447 aopGet (AOP (left), offset, FALSE, TRUE));
5449 aopPut (AOP (result), "a", offset);
5454 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5455 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5456 freeAsmop (result, NULL, ic, TRUE);
5459 /*-----------------------------------------------------------------*/
5460 /* genInline - write the inline code out */
5461 /*-----------------------------------------------------------------*/
5463 genInline (iCode * ic)
5465 char *buffer, *bp, *bp1;
5467 D(emitcode ("; genInline",""));
5469 _G.inLine += (!options.asmpeep);
5471 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5472 strcpy (buffer, IC_INLINE (ic));
5474 /* emit each line as a code */
5499 /* emitcode("",buffer); */
5500 _G.inLine -= (!options.asmpeep);
5503 /*-----------------------------------------------------------------*/
5504 /* genRRC - rotate right with carry */
5505 /*-----------------------------------------------------------------*/
5509 operand *left, *result;
5510 int size, offset = 0;
5513 D(emitcode ("; genRRC",""));
5515 /* rotate right with carry */
5516 left = IC_LEFT (ic);
5517 result = IC_RESULT (ic);
5518 aopOp (left, ic, FALSE);
5519 aopOp (result, ic, FALSE);
5521 /* move it to the result */
5522 size = AOP_SIZE (result);
5524 if (size == 1) { /* special case for 1 byte */
5525 l = aopGet (AOP (left), offset, FALSE, FALSE);
5527 emitcode ("rr", "a");
5533 l = aopGet (AOP (left), offset, FALSE, FALSE);
5535 emitcode ("rrc", "a");
5536 if (AOP_SIZE (result) > 1)
5537 aopPut (AOP (result), "a", offset--);
5539 /* now we need to put the carry into the
5540 highest order byte of the result */
5541 if (AOP_SIZE (result) > 1)
5543 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5546 emitcode ("mov", "acc.7,c");
5548 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5549 freeAsmop (left, NULL, ic, TRUE);
5550 freeAsmop (result, NULL, ic, TRUE);
5553 /*-----------------------------------------------------------------*/
5554 /* genRLC - generate code for rotate left with carry */
5555 /*-----------------------------------------------------------------*/
5559 operand *left, *result;
5560 int size, offset = 0;
5563 D(emitcode ("; genRLC",""));
5565 /* rotate right with carry */
5566 left = IC_LEFT (ic);
5567 result = IC_RESULT (ic);
5568 aopOp (left, ic, FALSE);
5569 aopOp (result, ic, FALSE);
5571 /* move it to the result */
5572 size = AOP_SIZE (result);
5576 l = aopGet (AOP (left), offset, FALSE, FALSE);
5578 if (size == 0) { /* special case for 1 byte */
5582 emitcode ("add", "a,acc");
5583 if (AOP_SIZE (result) > 1)
5584 aopPut (AOP (result), "a", offset++);
5587 l = aopGet (AOP (left), offset, FALSE, FALSE);
5589 emitcode ("rlc", "a");
5590 if (AOP_SIZE (result) > 1)
5591 aopPut (AOP (result), "a", offset++);
5594 /* now we need to put the carry into the
5595 highest order byte of the result */
5596 if (AOP_SIZE (result) > 1)
5598 l = aopGet (AOP (result), 0, FALSE, FALSE);
5601 emitcode ("mov", "acc.0,c");
5603 aopPut (AOP (result), "a", 0);
5604 freeAsmop (left, NULL, ic, TRUE);
5605 freeAsmop (result, NULL, ic, TRUE);
5608 /*-----------------------------------------------------------------*/
5609 /* genGetHbit - generates code get highest order bit */
5610 /*-----------------------------------------------------------------*/
5612 genGetHbit (iCode * ic)
5614 operand *left, *result;
5616 D(emitcode ("; genGetHbit",""));
5618 left = IC_LEFT (ic);
5619 result = IC_RESULT (ic);
5620 aopOp (left, ic, FALSE);
5621 aopOp (result, ic, FALSE);
5623 /* get the highest order byte into a */
5624 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5625 if (AOP_TYPE (result) == AOP_CRY)
5627 emitcode ("rlc", "a");
5632 emitcode ("rl", "a");
5633 emitcode ("anl", "a,#0x01");
5638 freeAsmop (left, NULL, ic, TRUE);
5639 freeAsmop (result, NULL, ic, TRUE);
5642 /*-----------------------------------------------------------------*/
5643 /* AccRol - rotate left accumulator by known count */
5644 /*-----------------------------------------------------------------*/
5646 AccRol (int shCount)
5648 shCount &= 0x0007; // shCount : 0..7
5655 emitcode ("rl", "a");
5658 emitcode ("rl", "a");
5659 emitcode ("rl", "a");
5662 emitcode ("swap", "a");
5663 emitcode ("rr", "a");
5666 emitcode ("swap", "a");
5669 emitcode ("swap", "a");
5670 emitcode ("rl", "a");
5673 emitcode ("rr", "a");
5674 emitcode ("rr", "a");
5677 emitcode ("rr", "a");
5682 /*-----------------------------------------------------------------*/
5683 /* AccLsh - left shift accumulator by known count */
5684 /*-----------------------------------------------------------------*/
5686 AccLsh (int shCount)
5691 emitcode ("add", "a,acc");
5692 else if (shCount == 2)
5694 emitcode ("add", "a,acc");
5695 emitcode ("add", "a,acc");
5699 /* rotate left accumulator */
5701 /* and kill the lower order bits */
5702 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5707 /*-----------------------------------------------------------------*/
5708 /* AccRsh - right shift accumulator by known count */
5709 /*-----------------------------------------------------------------*/
5711 AccRsh (int shCount)
5718 emitcode ("rrc", "a");
5722 /* rotate right accumulator */
5723 AccRol (8 - shCount);
5724 /* and kill the higher order bits */
5725 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5730 /*-----------------------------------------------------------------*/
5731 /* AccSRsh - signed right shift accumulator by known count */
5732 /*-----------------------------------------------------------------*/
5734 AccSRsh (int shCount)
5741 emitcode ("mov", "c,acc.7");
5742 emitcode ("rrc", "a");
5744 else if (shCount == 2)
5746 emitcode ("mov", "c,acc.7");
5747 emitcode ("rrc", "a");
5748 emitcode ("mov", "c,acc.7");
5749 emitcode ("rrc", "a");
5753 tlbl = newiTempLabel (NULL);
5754 /* rotate right accumulator */
5755 AccRol (8 - shCount);
5756 /* and kill the higher order bits */
5757 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5758 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5759 emitcode ("orl", "a,#0x%02x",
5760 (unsigned char) ~SRMask[shCount]);
5761 emitcode ("", "%05d$:", tlbl->key + 100);
5766 /*-----------------------------------------------------------------*/
5767 /* shiftR1Left2Result - shift right one byte from left to result */
5768 /*-----------------------------------------------------------------*/
5770 shiftR1Left2Result (operand * left, int offl,
5771 operand * result, int offr,
5772 int shCount, int sign)
5774 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5775 /* shift right accumulator */
5780 aopPut (AOP (result), "a", offr);
5783 /*-----------------------------------------------------------------*/
5784 /* shiftL1Left2Result - shift left one byte from left to result */
5785 /*-----------------------------------------------------------------*/
5787 shiftL1Left2Result (operand * left, int offl,
5788 operand * result, int offr, int shCount)
5791 l = aopGet (AOP (left), offl, FALSE, FALSE);
5793 /* shift left accumulator */
5795 aopPut (AOP (result), "a", offr);
5798 /*-----------------------------------------------------------------*/
5799 /* movLeft2Result - move byte from left to result */
5800 /*-----------------------------------------------------------------*/
5802 movLeft2Result (operand * left, int offl,
5803 operand * result, int offr, int sign)
5806 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5808 l = aopGet (AOP (left), offl, FALSE, FALSE);
5810 if (*l == '@' && (IS_AOP_PREG (result)))
5812 emitcode ("mov", "a,%s", l);
5813 aopPut (AOP (result), "a", offr);
5818 aopPut (AOP (result), l, offr);
5821 /* MSB sign in acc.7 ! */
5822 if (getDataSize (left) == offl + 1)
5824 emitcode ("mov", "a,%s", l);
5825 aopPut (AOP (result), "a", offr);
5832 /*-----------------------------------------------------------------*/
5833 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5834 /*-----------------------------------------------------------------*/
5838 emitcode ("rrc", "a");
5839 emitcode ("xch", "a,%s", x);
5840 emitcode ("rrc", "a");
5841 emitcode ("xch", "a,%s", x);
5844 /*-----------------------------------------------------------------*/
5845 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5846 /*-----------------------------------------------------------------*/
5850 emitcode ("xch", "a,%s", x);
5851 emitcode ("rlc", "a");
5852 emitcode ("xch", "a,%s", x);
5853 emitcode ("rlc", "a");
5856 /*-----------------------------------------------------------------*/
5857 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5858 /*-----------------------------------------------------------------*/
5862 emitcode ("xch", "a,%s", x);
5863 emitcode ("add", "a,acc");
5864 emitcode ("xch", "a,%s", x);
5865 emitcode ("rlc", "a");
5868 /*-----------------------------------------------------------------*/
5869 /* AccAXLsh - left shift a:x by known count (0..7) */
5870 /*-----------------------------------------------------------------*/
5872 AccAXLsh (char *x, int shCount)
5887 case 5: // AAAAABBB:CCCCCDDD
5889 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5891 emitcode ("anl", "a,#0x%02x",
5892 SLMask[shCount]); // BBB00000:CCCCCDDD
5894 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5896 AccRol (shCount); // DDDCCCCC:BBB00000
5898 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5900 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5902 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5904 emitcode ("anl", "a,#0x%02x",
5905 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5907 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5909 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5912 case 6: // AAAAAABB:CCCCCCDD
5913 emitcode ("anl", "a,#0x%02x",
5914 SRMask[shCount]); // 000000BB:CCCCCCDD
5915 emitcode ("mov", "c,acc.0"); // c = B
5916 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5918 AccAXRrl1 (x); // BCCCCCCD:D000000B
5919 AccAXRrl1 (x); // BBCCCCCC:DD000000
5921 emitcode("rrc","a");
5922 emitcode("xch","a,%s", x);
5923 emitcode("rrc","a");
5924 emitcode("mov","c,acc.0"); //<< get correct bit
5925 emitcode("xch","a,%s", x);
5927 emitcode("rrc","a");
5928 emitcode("xch","a,%s", x);
5929 emitcode("rrc","a");
5930 emitcode("xch","a,%s", x);
5933 case 7: // a:x <<= 7
5935 emitcode ("anl", "a,#0x%02x",
5936 SRMask[shCount]); // 0000000B:CCCCCCCD
5938 emitcode ("mov", "c,acc.0"); // c = B
5940 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5942 AccAXRrl1 (x); // BCCCCCCC:D0000000
5950 /*-----------------------------------------------------------------*/
5951 /* AccAXRsh - right shift a:x known count (0..7) */
5952 /*-----------------------------------------------------------------*/
5954 AccAXRsh (char *x, int shCount)
5962 AccAXRrl1 (x); // 0->a:x
5967 AccAXRrl1 (x); // 0->a:x
5970 AccAXRrl1 (x); // 0->a:x
5975 case 5: // AAAAABBB:CCCCCDDD = a:x
5977 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5979 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5981 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5983 emitcode ("anl", "a,#0x%02x",
5984 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5986 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5988 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5990 emitcode ("anl", "a,#0x%02x",
5991 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5993 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5995 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5997 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6000 case 6: // AABBBBBB:CCDDDDDD
6002 emitcode ("mov", "c,acc.7");
6003 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6005 emitcode ("mov", "c,acc.7");
6006 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6008 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6010 emitcode ("anl", "a,#0x%02x",
6011 SRMask[shCount]); // 000000AA:BBBBBBCC
6014 case 7: // ABBBBBBB:CDDDDDDD
6016 emitcode ("mov", "c,acc.7"); // c = A
6018 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6020 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6022 emitcode ("anl", "a,#0x%02x",
6023 SRMask[shCount]); // 0000000A:BBBBBBBC
6031 /*-----------------------------------------------------------------*/
6032 /* AccAXRshS - right shift signed a:x known count (0..7) */
6033 /*-----------------------------------------------------------------*/
6035 AccAXRshS (char *x, int shCount)
6043 emitcode ("mov", "c,acc.7");
6044 AccAXRrl1 (x); // s->a:x
6048 emitcode ("mov", "c,acc.7");
6049 AccAXRrl1 (x); // s->a:x
6051 emitcode ("mov", "c,acc.7");
6052 AccAXRrl1 (x); // s->a:x
6057 case 5: // AAAAABBB:CCCCCDDD = a:x
6059 tlbl = newiTempLabel (NULL);
6060 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6062 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6064 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6066 emitcode ("anl", "a,#0x%02x",
6067 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6069 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6071 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6073 emitcode ("anl", "a,#0x%02x",
6074 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6076 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6078 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6080 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6082 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6083 emitcode ("orl", "a,#0x%02x",
6084 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6086 emitcode ("", "%05d$:", tlbl->key + 100);
6087 break; // SSSSAAAA:BBBCCCCC
6089 case 6: // AABBBBBB:CCDDDDDD
6091 tlbl = newiTempLabel (NULL);
6092 emitcode ("mov", "c,acc.7");
6093 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6095 emitcode ("mov", "c,acc.7");
6096 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6098 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6100 emitcode ("anl", "a,#0x%02x",
6101 SRMask[shCount]); // 000000AA:BBBBBBCC
6103 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6104 emitcode ("orl", "a,#0x%02x",
6105 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6107 emitcode ("", "%05d$:", tlbl->key + 100);
6109 case 7: // ABBBBBBB:CDDDDDDD
6111 tlbl = newiTempLabel (NULL);
6112 emitcode ("mov", "c,acc.7"); // c = A
6114 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6116 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6118 emitcode ("anl", "a,#0x%02x",
6119 SRMask[shCount]); // 0000000A:BBBBBBBC
6121 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6122 emitcode ("orl", "a,#0x%02x",
6123 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6125 emitcode ("", "%05d$:", tlbl->key + 100);
6132 /*-----------------------------------------------------------------*/
6133 /* shiftL2Left2Result - shift left two bytes from left to result */
6134 /*-----------------------------------------------------------------*/
6136 shiftL2Left2Result (operand * left, int offl,
6137 operand * result, int offr, int shCount)
6139 if (sameRegs (AOP (result), AOP (left)) &&
6140 ((offl + MSB16) == offr))
6142 /* don't crash result[offr] */
6143 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6144 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6148 movLeft2Result (left, offl, result, offr, 0);
6149 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6151 /* ax << shCount (x = lsb(result)) */
6152 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6153 aopPut (AOP (result), "a", offr + MSB16);
6157 /*-----------------------------------------------------------------*/
6158 /* shiftR2Left2Result - shift right two bytes from left to result */
6159 /*-----------------------------------------------------------------*/
6161 shiftR2Left2Result (operand * left, int offl,
6162 operand * result, int offr,
6163 int shCount, int sign)
6165 if (sameRegs (AOP (result), AOP (left)) &&
6166 ((offl + MSB16) == offr))
6168 /* don't crash result[offr] */
6169 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6170 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6174 movLeft2Result (left, offl, result, offr, 0);
6175 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6177 /* a:x >> shCount (x = lsb(result)) */
6179 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6181 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6182 if (getDataSize (result) > 1)
6183 aopPut (AOP (result), "a", offr + MSB16);
6186 /*-----------------------------------------------------------------*/
6187 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6188 /*-----------------------------------------------------------------*/
6190 shiftLLeftOrResult (operand * left, int offl,
6191 operand * result, int offr, int shCount)
6193 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6194 /* shift left accumulator */
6196 /* or with result */
6197 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6198 /* back to result */
6199 aopPut (AOP (result), "a", offr);
6202 /*-----------------------------------------------------------------*/
6203 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6204 /*-----------------------------------------------------------------*/
6206 shiftRLeftOrResult (operand * left, int offl,
6207 operand * result, int offr, int shCount)
6209 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6210 /* shift right accumulator */
6212 /* or with result */
6213 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6214 /* back to result */
6215 aopPut (AOP (result), "a", offr);
6218 /*-----------------------------------------------------------------*/
6219 /* genlshOne - left shift a one byte quantity by known count */
6220 /*-----------------------------------------------------------------*/
6222 genlshOne (operand * result, operand * left, int shCount)
6224 D(emitcode ("; genlshOne",""));
6226 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6229 /*-----------------------------------------------------------------*/
6230 /* genlshTwo - left shift two bytes by known amount != 0 */
6231 /*-----------------------------------------------------------------*/
6233 genlshTwo (operand * result, operand * left, int shCount)
6237 D(emitcode ("; genlshTwo",""));
6239 size = getDataSize (result);
6241 /* if shCount >= 8 */
6249 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6251 movLeft2Result (left, LSB, result, MSB16, 0);
6253 aopPut (AOP (result), zero, LSB);
6256 /* 1 <= shCount <= 7 */
6260 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6262 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6266 /*-----------------------------------------------------------------*/
6267 /* shiftLLong - shift left one long from left to result */
6268 /* offl = LSB or MSB16 */
6269 /*-----------------------------------------------------------------*/
6271 shiftLLong (operand * left, operand * result, int offr)
6274 int size = AOP_SIZE (result);
6276 if (size >= LSB + offr)
6278 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6280 emitcode ("add", "a,acc");
6281 if (sameRegs (AOP (left), AOP (result)) &&
6282 size >= MSB16 + offr && offr != LSB)
6283 emitcode ("xch", "a,%s",
6284 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6286 aopPut (AOP (result), "a", LSB + offr);
6289 if (size >= MSB16 + offr)
6291 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6293 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6296 emitcode ("rlc", "a");
6297 if (sameRegs (AOP (left), AOP (result)) &&
6298 size >= MSB24 + offr && offr != LSB)
6299 emitcode ("xch", "a,%s",
6300 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6302 aopPut (AOP (result), "a", MSB16 + offr);
6305 if (size >= MSB24 + offr)
6307 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6309 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6312 emitcode ("rlc", "a");
6313 if (sameRegs (AOP (left), AOP (result)) &&
6314 size >= MSB32 + offr && offr != LSB)
6315 emitcode ("xch", "a,%s",
6316 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6318 aopPut (AOP (result), "a", MSB24 + offr);
6321 if (size > MSB32 + offr)
6323 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6325 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6328 emitcode ("rlc", "a");
6329 aopPut (AOP (result), "a", MSB32 + offr);
6332 aopPut (AOP (result), zero, LSB);
6335 /*-----------------------------------------------------------------*/
6336 /* genlshFour - shift four byte by a known amount != 0 */
6337 /*-----------------------------------------------------------------*/
6339 genlshFour (operand * result, operand * left, int shCount)
6343 D(emitcode ("; genlshFour",""));
6345 size = AOP_SIZE (result);
6347 /* if shifting more that 3 bytes */
6352 /* lowest order of left goes to the highest
6353 order of the destination */
6354 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6356 movLeft2Result (left, LSB, result, MSB32, 0);
6357 aopPut (AOP (result), zero, LSB);
6358 aopPut (AOP (result), zero, MSB16);
6359 aopPut (AOP (result), zero, MSB24);
6363 /* more than two bytes */
6364 else if (shCount >= 16)
6366 /* lower order two bytes goes to higher order two bytes */
6368 /* if some more remaining */
6370 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6373 movLeft2Result (left, MSB16, result, MSB32, 0);
6374 movLeft2Result (left, LSB, result, MSB24, 0);
6376 aopPut (AOP (result), zero, MSB16);
6377 aopPut (AOP (result), zero, LSB);
6381 /* if more than 1 byte */
6382 else if (shCount >= 8)
6384 /* lower order three bytes goes to higher order three bytes */
6389 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6391 movLeft2Result (left, LSB, result, MSB16, 0);
6397 movLeft2Result (left, MSB24, result, MSB32, 0);
6398 movLeft2Result (left, MSB16, result, MSB24, 0);
6399 movLeft2Result (left, LSB, result, MSB16, 0);
6400 aopPut (AOP (result), zero, LSB);
6402 else if (shCount == 1)
6403 shiftLLong (left, result, MSB16);
6406 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6407 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6408 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6409 aopPut (AOP (result), zero, LSB);
6414 /* 1 <= shCount <= 7 */
6415 else if (shCount <= 2)
6417 shiftLLong (left, result, LSB);
6419 shiftLLong (result, result, LSB);
6421 /* 3 <= shCount <= 7, optimize */
6424 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6425 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6426 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6430 /*-----------------------------------------------------------------*/
6431 /* genLeftShiftLiteral - left shifting by known count */
6432 /*-----------------------------------------------------------------*/
6434 genLeftShiftLiteral (operand * left,
6439 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6442 D(emitcode ("; genLeftShiftLiteral",""));
6444 freeAsmop (right, NULL, ic, TRUE);
6446 aopOp (left, ic, FALSE);
6447 aopOp (result, ic, FALSE);
6449 size = getSize (operandType (result));
6452 emitcode ("; shift left ", "result %d, left %d", size,
6456 /* I suppose that the left size >= result size */
6461 movLeft2Result (left, size, result, size, 0);
6465 else if (shCount >= (size * 8))
6467 aopPut (AOP (result), zero, size);
6473 genlshOne (result, left, shCount);
6477 genlshTwo (result, left, shCount);
6481 genlshFour (result, left, shCount);
6484 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6485 "*** ack! mystery literal shift!\n");
6489 freeAsmop (left, NULL, ic, TRUE);
6490 freeAsmop (result, NULL, ic, TRUE);
6493 /*-----------------------------------------------------------------*/
6494 /* genLeftShift - generates code for left shifting */
6495 /*-----------------------------------------------------------------*/
6497 genLeftShift (iCode * ic)
6499 operand *left, *right, *result;
6502 symbol *tlbl, *tlbl1;
6504 D(emitcode ("; genLeftShift",""));
6506 right = IC_RIGHT (ic);
6507 left = IC_LEFT (ic);
6508 result = IC_RESULT (ic);
6510 aopOp (right, ic, FALSE);
6512 /* if the shift count is known then do it
6513 as efficiently as possible */
6514 if (AOP_TYPE (right) == AOP_LIT)
6516 genLeftShiftLiteral (left, right, result, ic);
6520 /* shift count is unknown then we have to form
6521 a loop get the loop count in B : Note: we take
6522 only the lower order byte since shifting
6523 more that 32 bits make no sense anyway, ( the
6524 largest size of an object can be only 32 bits ) */
6526 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6527 emitcode ("inc", "b");
6528 freeAsmop (right, NULL, ic, TRUE);
6529 aopOp (left, ic, FALSE);
6530 aopOp (result, ic, FALSE);
6532 /* now move the left to the result if they are not the
6534 if (!sameRegs (AOP (left), AOP (result)) &&
6535 AOP_SIZE (result) > 1)
6538 size = AOP_SIZE (result);
6542 l = aopGet (AOP (left), offset, FALSE, TRUE);
6543 if (*l == '@' && (IS_AOP_PREG (result)))
6546 emitcode ("mov", "a,%s", l);
6547 aopPut (AOP (result), "a", offset);
6550 aopPut (AOP (result), l, offset);
6555 tlbl = newiTempLabel (NULL);
6556 size = AOP_SIZE (result);
6558 tlbl1 = newiTempLabel (NULL);
6560 /* if it is only one byte then */
6563 symbol *tlbl1 = newiTempLabel (NULL);
6565 l = aopGet (AOP (left), 0, FALSE, FALSE);
6567 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6568 emitcode ("", "%05d$:", tlbl->key + 100);
6569 emitcode ("add", "a,acc");
6570 emitcode ("", "%05d$:", tlbl1->key + 100);
6571 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6572 aopPut (AOP (result), "a", 0);
6576 reAdjustPreg (AOP (result));
6578 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6579 emitcode ("", "%05d$:", tlbl->key + 100);
6580 l = aopGet (AOP (result), offset, FALSE, FALSE);
6582 emitcode ("add", "a,acc");
6583 aopPut (AOP (result), "a", offset++);
6586 l = aopGet (AOP (result), offset, FALSE, FALSE);
6588 emitcode ("rlc", "a");
6589 aopPut (AOP (result), "a", offset++);
6591 reAdjustPreg (AOP (result));
6593 emitcode ("", "%05d$:", tlbl1->key + 100);
6594 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6596 freeAsmop (left, NULL, ic, TRUE);
6597 freeAsmop (result, NULL, ic, TRUE);
6600 /*-----------------------------------------------------------------*/
6601 /* genrshOne - right shift a one byte quantity by known count */
6602 /*-----------------------------------------------------------------*/
6604 genrshOne (operand * result, operand * left,
6605 int shCount, int sign)
6607 D(emitcode ("; genrshOne",""));
6609 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6612 /*-----------------------------------------------------------------*/
6613 /* genrshTwo - right shift two bytes by known amount != 0 */
6614 /*-----------------------------------------------------------------*/
6616 genrshTwo (operand * result, operand * left,
6617 int shCount, int sign)
6619 D(emitcode ("; genrshTwo",""));
6621 /* if shCount >= 8 */
6626 shiftR1Left2Result (left, MSB16, result, LSB,
6629 movLeft2Result (left, MSB16, result, LSB, sign);
6630 addSign (result, MSB16, sign);
6633 /* 1 <= shCount <= 7 */
6635 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6638 /*-----------------------------------------------------------------*/
6639 /* shiftRLong - shift right one long from left to result */
6640 /* offl = LSB or MSB16 */
6641 /*-----------------------------------------------------------------*/
6643 shiftRLong (operand * left, int offl,
6644 operand * result, int sign)
6646 int isSameRegs=sameRegs(AOP(left),AOP(result));
6648 if (isSameRegs && offl>1) {
6649 // we are in big trouble, but this shouldn't happen
6650 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6653 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6658 emitcode ("rlc", "a");
6659 emitcode ("subb", "a,acc");
6661 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6663 aopPut (AOP (result), "a", MSB32);
6664 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6667 aopPut (AOP(result), zero, MSB32);
6672 emitcode ("clr", "c");
6674 emitcode ("mov", "c,acc.7");
6677 emitcode ("rrc", "a");
6679 if (isSameRegs && offl==MSB16) {
6680 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6682 aopPut (AOP (result), "a", MSB32-offl);
6683 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6686 emitcode ("rrc", "a");
6687 if (isSameRegs && offl==1) {
6688 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6690 aopPut (AOP (result), "a", MSB24-offl);
6691 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6693 emitcode ("rrc", "a");
6694 aopPut (AOP (result), "a", MSB16 - offl);
6698 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6699 emitcode ("rrc", "a");
6700 aopPut (AOP (result), "a", LSB);
6704 /*-----------------------------------------------------------------*/
6705 /* genrshFour - shift four byte by a known amount != 0 */
6706 /*-----------------------------------------------------------------*/
6708 genrshFour (operand * result, operand * left,
6709 int shCount, int sign)
6711 D(emitcode ("; genrshFour",""));
6713 /* if shifting more that 3 bytes */
6718 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6720 movLeft2Result (left, MSB32, result, LSB, sign);
6721 addSign (result, MSB16, sign);
6723 else if (shCount >= 16)
6727 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6730 movLeft2Result (left, MSB24, result, LSB, 0);
6731 movLeft2Result (left, MSB32, result, MSB16, sign);
6733 addSign (result, MSB24, sign);
6735 else if (shCount >= 8)
6739 shiftRLong (left, MSB16, result, sign);
6740 else if (shCount == 0)
6742 movLeft2Result (left, MSB16, result, LSB, 0);
6743 movLeft2Result (left, MSB24, result, MSB16, 0);
6744 movLeft2Result (left, MSB32, result, MSB24, sign);
6745 addSign (result, MSB32, sign);
6749 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6750 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6751 /* the last shift is signed */
6752 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6753 addSign (result, MSB32, sign);
6757 { /* 1 <= shCount <= 7 */
6760 shiftRLong (left, LSB, result, sign);
6762 shiftRLong (result, LSB, result, sign);
6766 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6767 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6768 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6773 /*-----------------------------------------------------------------*/
6774 /* genRightShiftLiteral - right shifting by known count */
6775 /*-----------------------------------------------------------------*/
6777 genRightShiftLiteral (operand * left,
6783 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6786 D(emitcode ("; genRightShiftLiteral",""));
6788 freeAsmop (right, NULL, ic, TRUE);
6790 aopOp (left, ic, FALSE);
6791 aopOp (result, ic, FALSE);
6794 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6798 size = getDataSize (left);
6799 /* test the LEFT size !!! */
6801 /* I suppose that the left size >= result size */
6804 size = getDataSize (result);
6806 movLeft2Result (left, size, result, size, 0);
6809 else if (shCount >= (size * 8))
6812 /* get sign in acc.7 */
6813 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6815 addSign (result, LSB, sign);
6822 genrshOne (result, left, shCount, sign);
6826 genrshTwo (result, left, shCount, sign);
6830 genrshFour (result, left, shCount, sign);
6836 freeAsmop (left, NULL, ic, TRUE);
6837 freeAsmop (result, NULL, ic, TRUE);
6840 /*-----------------------------------------------------------------*/
6841 /* genSignedRightShift - right shift of signed number */
6842 /*-----------------------------------------------------------------*/
6844 genSignedRightShift (iCode * ic)
6846 operand *right, *left, *result;
6849 symbol *tlbl, *tlbl1;
6851 D(emitcode ("; genSignedRightShift",""));
6853 /* we do it the hard way put the shift count in b
6854 and loop thru preserving the sign */
6856 right = IC_RIGHT (ic);
6857 left = IC_LEFT (ic);
6858 result = IC_RESULT (ic);
6860 aopOp (right, ic, FALSE);
6863 if (AOP_TYPE (right) == AOP_LIT)
6865 genRightShiftLiteral (left, right, result, ic, 1);
6868 /* shift count is unknown then we have to form
6869 a loop get the loop count in B : Note: we take
6870 only the lower order byte since shifting
6871 more that 32 bits make no sense anyway, ( the
6872 largest size of an object can be only 32 bits ) */
6874 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6875 emitcode ("inc", "b");
6876 freeAsmop (right, NULL, ic, TRUE);
6877 aopOp (left, ic, FALSE);
6878 aopOp (result, ic, FALSE);
6880 /* now move the left to the result if they are not the
6882 if (!sameRegs (AOP (left), AOP (result)) &&
6883 AOP_SIZE (result) > 1)
6886 size = AOP_SIZE (result);
6890 l = aopGet (AOP (left), offset, FALSE, TRUE);
6891 if (*l == '@' && IS_AOP_PREG (result))
6894 emitcode ("mov", "a,%s", l);
6895 aopPut (AOP (result), "a", offset);
6898 aopPut (AOP (result), l, offset);
6903 /* mov the highest order bit to OVR */
6904 tlbl = newiTempLabel (NULL);
6905 tlbl1 = newiTempLabel (NULL);
6907 size = AOP_SIZE (result);
6909 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6910 emitcode ("rlc", "a");
6911 emitcode ("mov", "ov,c");
6912 /* if it is only one byte then */
6915 l = aopGet (AOP (left), 0, FALSE, FALSE);
6917 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6918 emitcode ("", "%05d$:", tlbl->key + 100);
6919 emitcode ("mov", "c,ov");
6920 emitcode ("rrc", "a");
6921 emitcode ("", "%05d$:", tlbl1->key + 100);
6922 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6923 aopPut (AOP (result), "a", 0);
6927 reAdjustPreg (AOP (result));
6928 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6929 emitcode ("", "%05d$:", tlbl->key + 100);
6930 emitcode ("mov", "c,ov");
6933 l = aopGet (AOP (result), offset, FALSE, FALSE);
6935 emitcode ("rrc", "a");
6936 aopPut (AOP (result), "a", offset--);
6938 reAdjustPreg (AOP (result));
6939 emitcode ("", "%05d$:", tlbl1->key + 100);
6940 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6943 freeAsmop (left, NULL, ic, TRUE);
6944 freeAsmop (result, NULL, ic, TRUE);
6947 /*-----------------------------------------------------------------*/
6948 /* genRightShift - generate code for right shifting */
6949 /*-----------------------------------------------------------------*/
6951 genRightShift (iCode * ic)
6953 operand *right, *left, *result;
6957 symbol *tlbl, *tlbl1;
6959 D(emitcode ("; genRightShift",""));
6961 /* if signed then we do it the hard way preserve the
6962 sign bit moving it inwards */
6963 retype = getSpec (operandType (IC_RESULT (ic)));
6965 if (!SPEC_USIGN (retype))
6967 genSignedRightShift (ic);
6971 /* signed & unsigned types are treated the same : i.e. the
6972 signed is NOT propagated inwards : quoting from the
6973 ANSI - standard : "for E1 >> E2, is equivalent to division
6974 by 2**E2 if unsigned or if it has a non-negative value,
6975 otherwise the result is implementation defined ", MY definition
6976 is that the sign does not get propagated */
6978 right = IC_RIGHT (ic);
6979 left = IC_LEFT (ic);
6980 result = IC_RESULT (ic);
6982 aopOp (right, ic, FALSE);
6984 /* if the shift count is known then do it
6985 as efficiently as possible */
6986 if (AOP_TYPE (right) == AOP_LIT)
6988 genRightShiftLiteral (left, right, result, ic, 0);
6992 /* shift count is unknown then we have to form
6993 a loop get the loop count in B : Note: we take
6994 only the lower order byte since shifting
6995 more that 32 bits make no sense anyway, ( the
6996 largest size of an object can be only 32 bits ) */
6998 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6999 emitcode ("inc", "b");
7000 freeAsmop (right, NULL, ic, TRUE);
7001 aopOp (left, ic, FALSE);
7002 aopOp (result, ic, FALSE);
7004 /* now move the left to the result if they are not the
7006 if (!sameRegs (AOP (left), AOP (result)) &&
7007 AOP_SIZE (result) > 1)
7010 size = AOP_SIZE (result);
7014 l = aopGet (AOP (left), offset, FALSE, TRUE);
7015 if (*l == '@' && IS_AOP_PREG (result))
7018 emitcode ("mov", "a,%s", l);
7019 aopPut (AOP (result), "a", offset);
7022 aopPut (AOP (result), l, offset);
7027 tlbl = newiTempLabel (NULL);
7028 tlbl1 = newiTempLabel (NULL);
7029 size = AOP_SIZE (result);
7032 /* if it is only one byte then */
7035 l = aopGet (AOP (left), 0, FALSE, FALSE);
7037 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7038 emitcode ("", "%05d$:", tlbl->key + 100);
7040 emitcode ("rrc", "a");
7041 emitcode ("", "%05d$:", tlbl1->key + 100);
7042 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7043 aopPut (AOP (result), "a", 0);
7047 reAdjustPreg (AOP (result));
7048 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7049 emitcode ("", "%05d$:", tlbl->key + 100);
7053 l = aopGet (AOP (result), offset, FALSE, FALSE);
7055 emitcode ("rrc", "a");
7056 aopPut (AOP (result), "a", offset--);
7058 reAdjustPreg (AOP (result));
7060 emitcode ("", "%05d$:", tlbl1->key + 100);
7061 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7064 freeAsmop (left, NULL, ic, TRUE);
7065 freeAsmop (result, NULL, ic, TRUE);
7068 /*-----------------------------------------------------------------*/
7069 /* genUnpackBits - generates code for unpacking bits */
7070 /*-----------------------------------------------------------------*/
7072 genUnpackBits (operand * result, char *rname, int ptype)
7080 D(emitcode ("; genUnpackBits",""));
7082 etype = getSpec (operandType (result));
7083 rsize = getSize (operandType (result));
7084 /* read the first byte */
7090 emitcode ("mov", "a,@%s", rname);
7094 emitcode ("movx", "a,@%s", rname);
7098 emitcode ("movx", "a,@dptr");
7102 emitcode ("clr", "a");
7103 emitcode ("movc", "a,@a+dptr");
7107 emitcode ("lcall", "__gptrget");
7111 rlen = SPEC_BLEN (etype);
7113 /* if we have bitdisplacement then it fits */
7114 /* into this byte completely or if length is */
7115 /* less than a byte */
7116 if ((shCnt = SPEC_BSTR (etype)) ||
7117 (SPEC_BLEN (etype) <= 8))
7120 /* shift right acc */
7123 emitcode ("anl", "a,#0x%02x",
7124 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7125 aopPut (AOP (result), "a", offset++);
7129 /* bit field did not fit in a byte */
7130 aopPut (AOP (result), "a", offset++);
7139 emitcode ("inc", "%s", rname);
7140 emitcode ("mov", "a,@%s", rname);
7144 emitcode ("inc", "%s", rname);
7145 emitcode ("movx", "a,@%s", rname);
7149 emitcode ("inc", "dptr");
7150 emitcode ("movx", "a,@dptr");
7154 emitcode ("clr", "a");
7155 emitcode ("inc", "dptr");
7156 emitcode ("movc", "a,@a+dptr");
7160 emitcode ("inc", "dptr");
7161 emitcode ("lcall", "__gptrget");
7166 /* if we are done */
7170 aopPut (AOP (result), "a", offset++);
7176 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7178 aopPut (AOP (result), "a", offset++);
7186 aopPut (AOP (result), zero, offset++);
7192 /*-----------------------------------------------------------------*/
7193 /* genDataPointerGet - generates code when ptr offset is known */
7194 /*-----------------------------------------------------------------*/
7196 genDataPointerGet (operand * left,
7202 int size, offset = 0;
7204 D(emitcode ("; genDataPointerGet",""));
7206 aopOp (result, ic, TRUE);
7208 /* get the string representation of the name */
7209 l = aopGet (AOP (left), 0, FALSE, TRUE);
7210 size = AOP_SIZE (result);
7214 sprintf (buffer, "(%s + %d)", l + 1, offset);
7216 sprintf (buffer, "%s", l + 1);
7217 aopPut (AOP (result), buffer, offset++);
7220 freeAsmop (left, NULL, ic, TRUE);
7221 freeAsmop (result, NULL, ic, TRUE);
7224 /*-----------------------------------------------------------------*/
7225 /* genNearPointerGet - emitcode for near pointer fetch */
7226 /*-----------------------------------------------------------------*/
7228 genNearPointerGet (operand * left,
7236 sym_link *rtype, *retype;
7237 sym_link *ltype = operandType (left);
7240 D(emitcode ("; genNearPointerGet",""));
7242 rtype = operandType (result);
7243 retype = getSpec (rtype);
7245 aopOp (left, ic, FALSE);
7247 /* if left is rematerialisable and
7248 result is not bit variable type and
7249 the left is pointer to data space i.e
7250 lower 128 bytes of space */
7251 if (AOP_TYPE (left) == AOP_IMMD &&
7252 !IS_BITVAR (retype) &&
7253 DCL_TYPE (ltype) == POINTER)
7255 genDataPointerGet (left, result, ic);
7259 /* if the value is already in a pointer register
7260 then don't need anything more */
7261 if (!AOP_INPREG (AOP (left)))
7263 /* otherwise get a free pointer register */
7265 preg = getFreePtr (ic, &aop, FALSE);
7266 emitcode ("mov", "%s,%s",
7268 aopGet (AOP (left), 0, FALSE, TRUE));
7272 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7274 //aopOp (result, ic, FALSE);
7275 aopOp (result, ic, result?TRUE:FALSE);
7277 /* if bitfield then unpack the bits */
7278 if (IS_BITVAR (retype))
7279 genUnpackBits (result, rname, POINTER);
7282 /* we have can just get the values */
7283 int size = AOP_SIZE (result);
7288 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7291 emitcode ("mov", "a,@%s", rname);
7292 aopPut (AOP (result), "a", offset);
7296 sprintf (buffer, "@%s", rname);
7297 aopPut (AOP (result), buffer, offset);
7301 emitcode ("inc", "%s", rname);
7305 /* now some housekeeping stuff */
7306 if (aop) /* we had to allocate for this iCode */
7308 if (pi) { /* post increment present */
7309 aopPut(AOP ( left ),rname,0);
7311 freeAsmop (NULL, aop, ic, TRUE);
7315 /* we did not allocate which means left
7316 already in a pointer register, then
7317 if size > 0 && this could be used again
7318 we have to point it back to where it
7320 if ((AOP_SIZE (result) > 1 &&
7321 !OP_SYMBOL (left)->remat &&
7322 (OP_SYMBOL (left)->liveTo > ic->seq ||
7326 int size = AOP_SIZE (result) - 1;
7328 emitcode ("dec", "%s", rname);
7333 freeAsmop (left, NULL, ic, TRUE);
7334 freeAsmop (result, NULL, ic, TRUE);
7335 if (pi) pi->generated = 1;
7338 /*-----------------------------------------------------------------*/
7339 /* genPagedPointerGet - emitcode for paged pointer fetch */
7340 /*-----------------------------------------------------------------*/
7342 genPagedPointerGet (operand * left,
7350 sym_link *rtype, *retype;
7352 D(emitcode ("; genPagedPointerGet",""));
7354 rtype = operandType (result);
7355 retype = getSpec (rtype);
7357 aopOp (left, ic, FALSE);
7359 /* if the value is already in a pointer register
7360 then don't need anything more */
7361 if (!AOP_INPREG (AOP (left)))
7363 /* otherwise get a free pointer register */
7365 preg = getFreePtr (ic, &aop, FALSE);
7366 emitcode ("mov", "%s,%s",
7368 aopGet (AOP (left), 0, FALSE, TRUE));
7372 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7374 aopOp (result, ic, FALSE);
7376 /* if bitfield then unpack the bits */
7377 if (IS_BITVAR (retype))
7378 genUnpackBits (result, rname, PPOINTER);
7381 /* we have can just get the values */
7382 int size = AOP_SIZE (result);
7388 emitcode ("movx", "a,@%s", rname);
7389 aopPut (AOP (result), "a", offset);
7394 emitcode ("inc", "%s", rname);
7398 /* now some housekeeping stuff */
7399 if (aop) /* we had to allocate for this iCode */
7401 if (pi) aopPut ( AOP (left), rname, 0);
7402 freeAsmop (NULL, aop, ic, TRUE);
7406 /* we did not allocate which means left
7407 already in a pointer register, then
7408 if size > 0 && this could be used again
7409 we have to point it back to where it
7411 if ((AOP_SIZE (result) > 1 &&
7412 !OP_SYMBOL (left)->remat &&
7413 (OP_SYMBOL (left)->liveTo > ic->seq ||
7417 int size = AOP_SIZE (result) - 1;
7419 emitcode ("dec", "%s", rname);
7424 freeAsmop (left, NULL, ic, TRUE);
7425 freeAsmop (result, NULL, ic, TRUE);
7426 if (pi) pi->generated = 1;
7430 /*-----------------------------------------------------------------*/
7431 /* genFarPointerGet - gget value from far space */
7432 /*-----------------------------------------------------------------*/
7434 genFarPointerGet (operand * left,
7435 operand * result, iCode * ic, iCode * pi)
7438 sym_link *retype = getSpec (operandType (result));
7440 D(emitcode ("; genFarPointerGet",""));
7442 aopOp (left, ic, FALSE);
7444 /* if the operand is already in dptr
7445 then we do nothing else we move the value to dptr */
7446 if (AOP_TYPE (left) != AOP_STR)
7448 /* if this is remateriazable */
7449 if (AOP_TYPE (left) == AOP_IMMD)
7450 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7452 { /* we need to get it byte by byte */
7453 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7454 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7457 /* so dptr know contains the address */
7458 aopOp (result, ic, FALSE);
7460 /* if bit then unpack */
7461 if (IS_BITVAR (retype))
7462 genUnpackBits (result, "dptr", FPOINTER);
7465 size = AOP_SIZE (result);
7470 emitcode ("movx", "a,@dptr");
7471 aopPut (AOP (result), "a", offset++);
7473 emitcode ("inc", "dptr");
7477 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7478 aopPut ( AOP (left), "dpl", 0);
7479 aopPut ( AOP (left), "dph", 1);
7482 freeAsmop (left, NULL, ic, TRUE);
7483 freeAsmop (result, NULL, ic, TRUE);
7486 /*-----------------------------------------------------------------*/
7487 /* genCodePointerGet - gget value from code space */
7488 /*-----------------------------------------------------------------*/
7490 genCodePointerGet (operand * left,
7491 operand * result, iCode * ic, iCode *pi)
7494 sym_link *retype = getSpec (operandType (result));
7496 D(emitcode ("; genCodePointerGet",""));
7498 aopOp (left, ic, FALSE);
7500 /* if the operand is already in dptr
7501 then we do nothing else we move the value to dptr */
7502 if (AOP_TYPE (left) != AOP_STR)
7504 /* if this is remateriazable */
7505 if (AOP_TYPE (left) == AOP_IMMD)
7506 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7508 { /* we need to get it byte by byte */
7509 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7510 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7513 /* so dptr know contains the address */
7514 aopOp (result, ic, FALSE);
7516 /* if bit then unpack */
7517 if (IS_BITVAR (retype))
7518 genUnpackBits (result, "dptr", CPOINTER);
7521 size = AOP_SIZE (result);
7526 emitcode ("clr", "a");
7527 emitcode ("movc", "a,@a+dptr");
7528 aopPut (AOP (result), "a", offset++);
7530 emitcode ("inc", "dptr");
7534 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7535 aopPut ( AOP (left), "dpl", 0);
7536 aopPut ( AOP (left), "dph", 1);
7539 freeAsmop (left, NULL, ic, TRUE);
7540 freeAsmop (result, NULL, ic, TRUE);
7543 /*-----------------------------------------------------------------*/
7544 /* genGenPointerGet - gget value from generic pointer space */
7545 /*-----------------------------------------------------------------*/
7547 genGenPointerGet (operand * left,
7548 operand * result, iCode * ic, iCode *pi)
7551 sym_link *retype = getSpec (operandType (result));
7553 D(emitcode ("; genGenPointerGet",""));
7555 aopOp (left, ic, FALSE);
7557 /* if the operand is already in dptr
7558 then we do nothing else we move the value to dptr */
7559 if (AOP_TYPE (left) != AOP_STR)
7561 /* if this is remateriazable */
7562 if (AOP_TYPE (left) == AOP_IMMD)
7564 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7565 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7566 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7568 emitcode ("mov", "b,#%d", pointerCode (retype));
7571 { /* we need to get it byte by byte */
7572 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7573 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7574 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7577 /* so dptr know contains the address */
7578 aopOp (result, ic, FALSE);
7580 /* if bit then unpack */
7581 if (IS_BITVAR (retype))
7582 genUnpackBits (result, "dptr", GPOINTER);
7585 size = AOP_SIZE (result);
7590 emitcode ("lcall", "__gptrget");
7591 aopPut (AOP (result), "a", offset++);
7593 emitcode ("inc", "dptr");
7597 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7598 aopPut ( AOP (left), "dpl", 0);
7599 aopPut ( AOP (left), "dph", 1);
7600 aopPut ( AOP (left), "b", 2);
7603 freeAsmop (left, NULL, ic, TRUE);
7604 freeAsmop (result, NULL, ic, TRUE);
7607 /*-----------------------------------------------------------------*/
7608 /* genPointerGet - generate code for pointer get */
7609 /*-----------------------------------------------------------------*/
7611 genPointerGet (iCode * ic, iCode *pi)
7613 operand *left, *result;
7614 sym_link *type, *etype;
7617 D(emitcode ("; genPointerGet",""));
7619 left = IC_LEFT (ic);
7620 result = IC_RESULT (ic);
7622 /* depending on the type of pointer we need to
7623 move it to the correct pointer register */
7624 type = operandType (left);
7625 etype = getSpec (type);
7626 /* if left is of type of pointer then it is simple */
7627 if (IS_PTR (type) && !IS_FUNC (type->next))
7628 p_type = DCL_TYPE (type);
7631 /* we have to go by the storage class */
7632 p_type = PTR_TYPE (SPEC_OCLS (etype));
7635 /* special case when cast remat */
7636 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7637 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7638 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7639 type = operandType (left);
7640 p_type = DCL_TYPE (type);
7642 /* now that we have the pointer type we assign
7643 the pointer values */
7649 genNearPointerGet (left, result, ic, pi);
7653 genPagedPointerGet (left, result, ic, pi);
7657 genFarPointerGet (left, result, ic, pi);
7661 genCodePointerGet (left, result, ic, pi);
7665 genGenPointerGet (left, result, ic, pi);
7671 /*-----------------------------------------------------------------*/
7672 /* genPackBits - generates code for packed bit storage */
7673 /*-----------------------------------------------------------------*/
7675 genPackBits (sym_link * etype,
7677 char *rname, int p_type)
7685 D(emitcode ("; genPackBits",""));
7687 blen = SPEC_BLEN (etype);
7688 bstr = SPEC_BSTR (etype);
7690 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7693 /* if the bit lenth is less than or */
7694 /* it exactly fits a byte then */
7695 if (SPEC_BLEN (etype) <= 8)
7697 shCount = SPEC_BSTR (etype);
7699 /* shift left acc */
7702 if (SPEC_BLEN (etype) < 8)
7703 { /* if smaller than a byte */
7709 emitcode ("mov", "b,a");
7710 emitcode ("mov", "a,@%s", rname);
7714 emitcode ("mov", "b,a");
7715 emitcode ("movx", "a,@dptr");
7719 emitcode ("push", "b");
7720 emitcode ("push", "acc");
7721 emitcode ("lcall", "__gptrget");
7722 emitcode ("pop", "b");
7726 emitcode ("anl", "a,#0x%02x", (unsigned char)
7727 ((unsigned char) (0xFF << (blen + bstr)) |
7728 (unsigned char) (0xFF >> (8 - bstr))));
7729 emitcode ("orl", "a,b");
7730 if (p_type == GPOINTER)
7731 emitcode ("pop", "b");
7738 emitcode ("mov", "@%s,a", rname);
7742 emitcode ("movx", "@dptr,a");
7746 emitcode ("lcall", "__gptrput");
7751 if (SPEC_BLEN (etype) <= 8)
7754 emitcode ("inc", "%s", rname);
7755 rLen = SPEC_BLEN (etype);
7757 /* now generate for lengths greater than one byte */
7761 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7773 emitcode ("mov", "@%s,a", rname);
7776 emitcode ("mov", "@%s,%s", rname, l);
7781 emitcode ("movx", "@dptr,a");
7786 emitcode ("lcall", "__gptrput");
7789 emitcode ("inc", "%s", rname);
7794 /* last last was not complete */
7797 /* save the byte & read byte */
7801 emitcode ("mov", "b,a");
7802 emitcode ("mov", "a,@%s", rname);
7806 emitcode ("mov", "b,a");
7807 emitcode ("movx", "a,@dptr");
7811 emitcode ("push", "b");
7812 emitcode ("push", "acc");
7813 emitcode ("lcall", "__gptrget");
7814 emitcode ("pop", "b");
7818 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7819 emitcode ("orl", "a,b");
7822 if (p_type == GPOINTER)
7823 emitcode ("pop", "b");
7829 emitcode ("mov", "@%s,a", rname);
7833 emitcode ("movx", "@dptr,a");
7837 emitcode ("lcall", "__gptrput");
7841 /*-----------------------------------------------------------------*/
7842 /* genDataPointerSet - remat pointer to data space */
7843 /*-----------------------------------------------------------------*/
7845 genDataPointerSet (operand * right,
7849 int size, offset = 0;
7850 char *l, buffer[256];
7852 D(emitcode ("; genDataPointerSet",""));
7854 aopOp (right, ic, FALSE);
7856 l = aopGet (AOP (result), 0, FALSE, TRUE);
7857 size = AOP_SIZE (right);
7861 sprintf (buffer, "(%s + %d)", l + 1, offset);
7863 sprintf (buffer, "%s", l + 1);
7864 emitcode ("mov", "%s,%s", buffer,
7865 aopGet (AOP (right), offset++, FALSE, FALSE));
7868 freeAsmop (right, NULL, ic, TRUE);
7869 freeAsmop (result, NULL, ic, TRUE);
7872 /*-----------------------------------------------------------------*/
7873 /* genNearPointerSet - emitcode for near pointer put */
7874 /*-----------------------------------------------------------------*/
7876 genNearPointerSet (operand * right,
7884 sym_link *retype, *letype;
7885 sym_link *ptype = operandType (result);
7887 D(emitcode ("; genNearPointerSet",""));
7889 retype = getSpec (operandType (right));
7890 letype = getSpec (ptype);
7891 aopOp (result, ic, FALSE);
7893 /* if the result is rematerializable &
7894 in data space & not a bit variable */
7895 if (AOP_TYPE (result) == AOP_IMMD &&
7896 DCL_TYPE (ptype) == POINTER &&
7897 !IS_BITVAR (retype) &&
7898 !IS_BITVAR (letype))
7900 genDataPointerSet (right, result, ic);
7904 /* if the value is already in a pointer register
7905 then don't need anything more */
7906 if (!AOP_INPREG (AOP (result)))
7909 //AOP_TYPE (result) == AOP_STK
7913 // Aha, it is a pointer, just in disguise.
7914 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7917 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7918 __FILE__, __LINE__);
7923 rname++; // skip the '@'.
7928 /* otherwise get a free pointer register */
7930 preg = getFreePtr (ic, &aop, FALSE);
7931 emitcode ("mov", "%s,%s",
7933 aopGet (AOP (result), 0, FALSE, TRUE));
7939 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7942 aopOp (right, ic, FALSE);
7944 /* if bitfield then unpack the bits */
7945 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7946 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7949 /* we have can just get the values */
7950 int size = AOP_SIZE (right);
7955 l = aopGet (AOP (right), offset, FALSE, TRUE);
7959 emitcode ("mov", "@%s,a", rname);
7962 emitcode ("mov", "@%s,%s", rname, l);
7964 emitcode ("inc", "%s", rname);
7969 /* now some housekeeping stuff */
7970 if (aop) /* we had to allocate for this iCode */
7972 if (pi) aopPut (AOP (result),rname,0);
7973 freeAsmop (NULL, aop, ic, TRUE);
7977 /* we did not allocate which means left
7978 already in a pointer register, then
7979 if size > 0 && this could be used again
7980 we have to point it back to where it
7982 if ((AOP_SIZE (right) > 1 &&
7983 !OP_SYMBOL (result)->remat &&
7984 (OP_SYMBOL (result)->liveTo > ic->seq ||
7988 int size = AOP_SIZE (right) - 1;
7990 emitcode ("dec", "%s", rname);
7995 if (pi) pi->generated = 1;
7996 freeAsmop (result, NULL, ic, TRUE);
7997 freeAsmop (right, NULL, ic, TRUE);
8000 /*-----------------------------------------------------------------*/
8001 /* genPagedPointerSet - emitcode for Paged pointer put */
8002 /*-----------------------------------------------------------------*/
8004 genPagedPointerSet (operand * right,
8012 sym_link *retype, *letype;
8014 D(emitcode ("; genPagedPointerSet",""));
8016 retype = getSpec (operandType (right));
8017 letype = getSpec (operandType (result));
8019 aopOp (result, ic, FALSE);
8021 /* if the value is already in a pointer register
8022 then don't need anything more */
8023 if (!AOP_INPREG (AOP (result)))
8025 /* otherwise get a free pointer register */
8027 preg = getFreePtr (ic, &aop, FALSE);
8028 emitcode ("mov", "%s,%s",
8030 aopGet (AOP (result), 0, FALSE, TRUE));
8034 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8036 aopOp (right, ic, FALSE);
8038 /* if bitfield then unpack the bits */
8039 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8040 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8043 /* we have can just get the values */
8044 int size = AOP_SIZE (right);
8049 l = aopGet (AOP (right), offset, FALSE, TRUE);
8052 emitcode ("movx", "@%s,a", rname);
8055 emitcode ("inc", "%s", rname);
8061 /* now some housekeeping stuff */
8062 if (aop) /* we had to allocate for this iCode */
8064 if (pi) aopPut (AOP (result),rname,0);
8065 freeAsmop (NULL, aop, ic, TRUE);
8069 /* we did not allocate which means left
8070 already in a pointer register, then
8071 if size > 0 && this could be used again
8072 we have to point it back to where it
8074 if (AOP_SIZE (right) > 1 &&
8075 !OP_SYMBOL (result)->remat &&
8076 (OP_SYMBOL (result)->liveTo > ic->seq ||
8079 int size = AOP_SIZE (right) - 1;
8081 emitcode ("dec", "%s", rname);
8086 if (pi) pi->generated = 1;
8087 freeAsmop (result, NULL, ic, TRUE);
8088 freeAsmop (right, NULL, ic, TRUE);
8093 /*-----------------------------------------------------------------*/
8094 /* genFarPointerSet - set value from far space */
8095 /*-----------------------------------------------------------------*/
8097 genFarPointerSet (operand * right,
8098 operand * result, iCode * ic, iCode * pi)
8101 sym_link *retype = getSpec (operandType (right));
8102 sym_link *letype = getSpec (operandType (result));
8104 D(emitcode ("; genFarPointerSet",""));
8106 aopOp (result, ic, FALSE);
8108 /* if the operand is already in dptr
8109 then we do nothing else we move the value to dptr */
8110 if (AOP_TYPE (result) != AOP_STR)
8112 /* if this is remateriazable */
8113 if (AOP_TYPE (result) == AOP_IMMD)
8114 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8116 { /* we need to get it byte by byte */
8117 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8118 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8121 /* so dptr know contains the address */
8122 aopOp (right, ic, FALSE);
8124 /* if bit then unpack */
8125 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8126 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8129 size = AOP_SIZE (right);
8134 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8136 emitcode ("movx", "@dptr,a");
8138 emitcode ("inc", "dptr");
8141 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8142 aopPut (AOP(result),"dpl",0);
8143 aopPut (AOP(result),"dph",1);
8146 freeAsmop (result, NULL, ic, TRUE);
8147 freeAsmop (right, NULL, ic, TRUE);
8150 /*-----------------------------------------------------------------*/
8151 /* genGenPointerSet - set value from generic pointer space */
8152 /*-----------------------------------------------------------------*/
8154 genGenPointerSet (operand * right,
8155 operand * result, iCode * ic, iCode * pi)
8158 sym_link *retype = getSpec (operandType (right));
8159 sym_link *letype = getSpec (operandType (result));
8161 D(emitcode ("; genGenPointerSet",""));
8163 aopOp (result, ic, FALSE);
8165 /* if the operand is already in dptr
8166 then we do nothing else we move the value to dptr */
8167 if (AOP_TYPE (result) != AOP_STR)
8169 /* if this is remateriazable */
8170 if (AOP_TYPE (result) == AOP_IMMD)
8172 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8173 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8174 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8176 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8179 { /* we need to get it byte by byte */
8180 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8181 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8182 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8185 /* so dptr know contains the address */
8186 aopOp (right, ic, FALSE);
8188 /* if bit then unpack */
8189 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8190 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8193 size = AOP_SIZE (right);
8198 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8200 emitcode ("lcall", "__gptrput");
8202 emitcode ("inc", "dptr");
8206 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8207 aopPut (AOP(result),"dpl",0);
8208 aopPut (AOP(result),"dph",1);
8209 aopPut (AOP(result),"b",2);
8212 freeAsmop (result, NULL, ic, TRUE);
8213 freeAsmop (right, NULL, ic, TRUE);
8216 /*-----------------------------------------------------------------*/
8217 /* genPointerSet - stores the value into a pointer location */
8218 /*-----------------------------------------------------------------*/
8220 genPointerSet (iCode * ic, iCode *pi)
8222 operand *right, *result;
8223 sym_link *type, *etype;
8226 D(emitcode ("; genPointerSet",""));
8228 right = IC_RIGHT (ic);
8229 result = IC_RESULT (ic);
8231 /* depending on the type of pointer we need to
8232 move it to the correct pointer register */
8233 type = operandType (result);
8234 etype = getSpec (type);
8235 /* if left is of type of pointer then it is simple */
8236 if (IS_PTR (type) && !IS_FUNC (type->next))
8238 p_type = DCL_TYPE (type);
8242 /* we have to go by the storage class */
8243 p_type = PTR_TYPE (SPEC_OCLS (etype));
8246 /* special case when cast remat */
8247 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8248 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8249 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8250 type = operandType (result);
8251 p_type = DCL_TYPE (type);
8253 /* now that we have the pointer type we assign
8254 the pointer values */
8260 genNearPointerSet (right, result, ic, pi);
8264 genPagedPointerSet (right, result, ic, pi);
8268 genFarPointerSet (right, result, ic, pi);
8272 genGenPointerSet (right, result, ic, pi);
8276 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8277 "genPointerSet: illegal pointer type");
8282 /*-----------------------------------------------------------------*/
8283 /* genIfx - generate code for Ifx statement */
8284 /*-----------------------------------------------------------------*/
8286 genIfx (iCode * ic, iCode * popIc)
8288 operand *cond = IC_COND (ic);
8291 D(emitcode ("; genIfx",""));
8293 aopOp (cond, ic, FALSE);
8295 /* get the value into acc */
8296 if (AOP_TYPE (cond) != AOP_CRY)
8300 /* the result is now in the accumulator */
8301 freeAsmop (cond, NULL, ic, TRUE);
8303 /* if there was something to be popped then do it */
8307 /* if the condition is a bit variable */
8308 if (isbit && IS_ITEMP (cond) &&
8310 genIfxJump (ic, SPIL_LOC (cond)->rname);
8311 else if (isbit && !IS_ITEMP (cond))
8312 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8314 genIfxJump (ic, "a");
8319 /*-----------------------------------------------------------------*/
8320 /* genAddrOf - generates code for address of */
8321 /*-----------------------------------------------------------------*/
8323 genAddrOf (iCode * ic)
8325 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8328 D(emitcode ("; genAddrOf",""));
8330 aopOp (IC_RESULT (ic), ic, FALSE);
8332 /* if the operand is on the stack then we
8333 need to get the stack offset of this
8337 /* if it has an offset then we need to compute
8341 emitcode ("mov", "a,_bp");
8342 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8343 ((char) (sym->stack - _G.nRegsSaved)) :
8344 ((char) sym->stack)) & 0xff);
8345 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8349 /* we can just move _bp */
8350 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8352 /* fill the result with zero */
8353 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8358 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8364 /* object not on stack then we need the name */
8365 size = AOP_SIZE (IC_RESULT (ic));
8370 char s[SDCC_NAME_MAX];
8372 sprintf (s, "#(%s >> %d)",
8376 sprintf (s, "#%s", sym->rname);
8377 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8381 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8385 /*-----------------------------------------------------------------*/
8386 /* genFarFarAssign - assignment when both are in far space */
8387 /*-----------------------------------------------------------------*/
8389 genFarFarAssign (operand * result, operand * right, iCode * ic)
8391 int size = AOP_SIZE (right);
8395 D(emitcode ("; genFarFarAssign",""));
8397 /* first push the right side on to the stack */
8400 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8402 emitcode ("push", "acc");
8405 freeAsmop (right, NULL, ic, FALSE);
8406 /* now assign DPTR to result */
8407 aopOp (result, ic, FALSE);
8408 size = AOP_SIZE (result);
8411 emitcode ("pop", "acc");
8412 aopPut (AOP (result), "a", --offset);
8414 freeAsmop (result, NULL, ic, FALSE);
8418 /*-----------------------------------------------------------------*/
8419 /* genAssign - generate code for assignment */
8420 /*-----------------------------------------------------------------*/
8422 genAssign (iCode * ic)
8424 operand *result, *right;
8426 unsigned long lit = 0L;
8428 D(emitcode("; genAssign",""));
8430 result = IC_RESULT (ic);
8431 right = IC_RIGHT (ic);
8433 /* if they are the same */
8434 if (operandsEqu (result, right)) {
8438 aopOp (right, ic, FALSE);
8440 /* special case both in far space */
8441 if (AOP_TYPE (right) == AOP_DPTR &&
8442 IS_TRUE_SYMOP (result) &&
8443 isOperandInFarSpace (result))
8446 genFarFarAssign (result, right, ic);
8450 aopOp (result, ic, TRUE);
8452 /* if they are the same registers */
8453 if (sameRegs (AOP (right), AOP (result)))
8456 /* if the result is a bit */
8457 if (AOP_TYPE (result) == AOP_CRY)
8460 /* if the right size is a literal then
8461 we know what the value is */
8462 if (AOP_TYPE (right) == AOP_LIT)
8464 if (((int) operandLitValue (right)))
8465 aopPut (AOP (result), one, 0);
8467 aopPut (AOP (result), zero, 0);
8471 /* the right is also a bit variable */
8472 if (AOP_TYPE (right) == AOP_CRY)
8474 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8475 aopPut (AOP (result), "c", 0);
8481 aopPut (AOP (result), "a", 0);
8485 /* bit variables done */
8487 size = AOP_SIZE (result);
8489 if (AOP_TYPE (right) == AOP_LIT)
8490 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8492 (AOP_TYPE (result) != AOP_REG) &&
8493 (AOP_TYPE (right) == AOP_LIT) &&
8494 !IS_FLOAT (operandType (right)) &&
8497 emitcode ("clr", "a");
8500 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8501 aopPut (AOP (result), "a", size);
8503 aopPut (AOP (result),
8504 aopGet (AOP (right), size, FALSE, FALSE),
8512 aopPut (AOP (result),
8513 aopGet (AOP (right), offset, FALSE, FALSE),
8520 freeAsmop (right, NULL, ic, TRUE);
8521 freeAsmop (result, NULL, ic, TRUE);
8524 /*-----------------------------------------------------------------*/
8525 /* genJumpTab - genrates code for jump table */
8526 /*-----------------------------------------------------------------*/
8528 genJumpTab (iCode * ic)
8533 D(emitcode ("; genJumpTab",""));
8535 aopOp (IC_JTCOND (ic), ic, FALSE);
8536 /* get the condition into accumulator */
8537 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8539 /* multiply by three */
8540 emitcode ("add", "a,acc");
8541 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8542 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8544 jtab = newiTempLabel (NULL);
8545 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8546 emitcode ("jmp", "@a+dptr");
8547 emitcode ("", "%05d$:", jtab->key + 100);
8548 /* now generate the jump labels */
8549 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8550 jtab = setNextItem (IC_JTLABELS (ic)))
8551 emitcode ("ljmp", "%05d$", jtab->key + 100);
8555 /*-----------------------------------------------------------------*/
8556 /* genCast - gen code for casting */
8557 /*-----------------------------------------------------------------*/
8559 genCast (iCode * ic)
8561 operand *result = IC_RESULT (ic);
8562 sym_link *ctype = operandType (IC_LEFT (ic));
8563 sym_link *rtype = operandType (IC_RIGHT (ic));
8564 operand *right = IC_RIGHT (ic);
8567 D(emitcode("; genCast",""));
8569 /* if they are equivalent then do nothing */
8570 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8573 aopOp (right, ic, FALSE);
8574 aopOp (result, ic, FALSE);
8576 /* if the result is a bit */
8577 if (IS_BITVAR(OP_SYMBOL(result)->type))
8579 /* if the right size is a literal then
8580 we know what the value is */
8581 if (AOP_TYPE (right) == AOP_LIT)
8583 if (((int) operandLitValue (right)))
8584 aopPut (AOP (result), one, 0);
8586 aopPut (AOP (result), zero, 0);
8591 /* the right is also a bit variable */
8592 if (AOP_TYPE (right) == AOP_CRY)
8594 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8595 aopPut (AOP (result), "c", 0);
8601 aopPut (AOP (result), "a", 0);
8605 /* if they are the same size : or less */
8606 if (AOP_SIZE (result) <= AOP_SIZE (right))
8609 /* if they are in the same place */
8610 if (sameRegs (AOP (right), AOP (result)))
8613 /* if they in different places then copy */
8614 size = AOP_SIZE (result);
8618 aopPut (AOP (result),
8619 aopGet (AOP (right), offset, FALSE, FALSE),
8627 /* if the result is of type pointer */
8632 sym_link *type = operandType (right);
8633 sym_link *etype = getSpec (type);
8635 /* pointer to generic pointer */
8636 if (IS_GENPTR (ctype))
8639 p_type = DCL_TYPE (type);
8642 if (SPEC_SCLS(etype)==S_REGISTER) {
8643 // let's assume it is a generic pointer
8646 /* we have to go by the storage class */
8647 p_type = PTR_TYPE (SPEC_OCLS (etype));
8651 /* the first two bytes are known */
8652 size = GPTRSIZE - 1;
8656 aopPut (AOP (result),
8657 aopGet (AOP (right), offset, FALSE, FALSE),
8661 /* the last byte depending on type */
8663 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8668 // pointerTypeToGPByte will have bitched.
8672 sprintf(gpValStr, "#0x%d", gpVal);
8673 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8678 /* just copy the pointers */
8679 size = AOP_SIZE (result);
8683 aopPut (AOP (result),
8684 aopGet (AOP (right), offset, FALSE, FALSE),
8691 /* so we now know that the size of destination is greater
8692 than the size of the source */
8693 /* we move to result for the size of source */
8694 size = AOP_SIZE (right);
8698 aopPut (AOP (result),
8699 aopGet (AOP (right), offset, FALSE, FALSE),
8704 /* now depending on the sign of the source && destination */
8705 size = AOP_SIZE (result) - AOP_SIZE (right);
8706 /* if unsigned or not an integral type */
8707 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8710 aopPut (AOP (result), zero, offset++);
8714 /* we need to extend the sign :{ */
8715 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8718 emitcode ("rlc", "a");
8719 emitcode ("subb", "a,acc");
8721 aopPut (AOP (result), "a", offset++);
8724 /* we are done hurray !!!! */
8727 freeAsmop (right, NULL, ic, TRUE);
8728 freeAsmop (result, NULL, ic, TRUE);
8732 /*-----------------------------------------------------------------*/
8733 /* genDjnz - generate decrement & jump if not zero instrucion */
8734 /*-----------------------------------------------------------------*/
8736 genDjnz (iCode * ic, iCode * ifx)
8742 D(emitcode ("; genDjnz",""));
8744 /* if the if condition has a false label
8745 then we cannot save */
8749 /* if the minus is not of the form
8751 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8752 !IS_OP_LITERAL (IC_RIGHT (ic)))
8755 if (operandLitValue (IC_RIGHT (ic)) != 1)
8758 /* if the size of this greater than one then no
8760 if (getSize (operandType (IC_RESULT (ic))) > 1)
8763 /* otherwise we can save BIG */
8764 lbl = newiTempLabel (NULL);
8765 lbl1 = newiTempLabel (NULL);
8767 aopOp (IC_RESULT (ic), ic, FALSE);
8769 if (AOP_NEEDSACC(IC_RESULT(ic)))
8771 /* If the result is accessed indirectly via
8772 * the accumulator, we must explicitly write
8773 * it back after the decrement.
8775 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8777 if (strcmp(rByte, "a"))
8779 /* Something is hopelessly wrong */
8780 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8781 __FILE__, __LINE__);
8782 /* We can just give up; the generated code will be inefficient,
8785 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8788 emitcode ("dec", "%s", rByte);
8789 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8790 emitcode ("jnz", "%05d$", lbl->key + 100);
8792 else if (IS_AOP_PREG (IC_RESULT (ic)))
8794 emitcode ("dec", "%s",
8795 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8796 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8797 emitcode ("jnz", "%05d$", lbl->key + 100);
8801 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8804 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8805 emitcode ("", "%05d$:", lbl->key + 100);
8806 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8807 emitcode ("", "%05d$:", lbl1->key + 100);
8809 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8814 /*-----------------------------------------------------------------*/
8815 /* genReceive - generate code for a receive iCode */
8816 /*-----------------------------------------------------------------*/
8818 genReceive (iCode * ic)
8820 int size = getSize (operandType (IC_RESULT (ic)));
8822 D(emitcode ("; genReceive",""));
8824 if (ic->argreg == 1) { /* first parameter */
8825 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8826 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8827 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8829 offset = fReturnSizeMCS51 - size;
8831 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8832 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8835 aopOp (IC_RESULT (ic), ic, FALSE);
8836 size = AOP_SIZE (IC_RESULT (ic));
8839 emitcode ("pop", "acc");
8840 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8845 aopOp (IC_RESULT (ic), ic, FALSE);
8847 assignResultValue (IC_RESULT (ic));
8849 } else { /* second receive onwards */
8851 aopOp (IC_RESULT (ic), ic, FALSE);
8852 rb1off = ic->argreg;
8854 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8857 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8860 /*-----------------------------------------------------------------*/
8861 /* gen51Code - generate code for 8051 based controllers */
8862 /*-----------------------------------------------------------------*/
8864 gen51Code (iCode * lic)
8869 lineHead = lineCurr = NULL;
8871 /* print the allocation information */
8873 printAllocInfo (currFunc, codeOutFile);
8874 /* if debug information required */
8875 if (options.debug && currFunc)
8877 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8879 if (IS_STATIC (currFunc->etype))
8880 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8882 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8885 /* stack pointer name */
8886 if (options.useXstack)
8892 for (ic = lic; ic; ic = ic->next)
8895 if (ic->lineno && cln != ic->lineno)
8900 emitcode ("", "C$%s$%d$%d$%d ==.",
8901 FileBaseName (ic->filename), ic->lineno,
8902 ic->level, ic->block);
8905 if (!options.noCcodeInAsm) {
8906 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8907 printCLine(ic->filename, ic->lineno));
8911 if (options.iCodeInAsm) {
8912 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
8914 /* if the result is marked as
8915 spilt and rematerializable or code for
8916 this has already been generated then
8918 if (resultRemat (ic) || ic->generated)
8921 /* depending on the operation */
8941 /* IPOP happens only when trying to restore a
8942 spilt live range, if there is an ifx statement
8943 following this pop then the if statement might
8944 be using some of the registers being popped which
8945 would destory the contents of the register so
8946 we need to check for this condition and handle it */
8948 ic->next->op == IFX &&
8949 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8950 genIfx (ic->next, ic);
8968 genEndFunction (ic);
8988 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9005 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9009 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9016 /* note these two are xlated by algebraic equivalence
9017 during parsing SDCC.y */
9018 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9019 "got '>=' or '<=' shouldn't have come here");
9023 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9035 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9039 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9043 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9070 case GET_VALUE_AT_ADDRESS:
9071 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9075 if (POINTER_SET (ic))
9076 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9102 addSet (&_G.sendSet, ic);
9111 /* now we are ready to call the
9112 peep hole optimizer */
9113 if (!options.nopeep)
9114 peepHole (&lineHead);
9116 /* now do the actual printing */
9117 printLine (lineHead, codeOutFile);