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);
234 /* I said end of world, but not quite end of world yet */
236 /* we can push it on the stack */
237 (*aopp)->type = AOP_STK;
240 /* in the case that result AND left AND right needs a pointer reg
241 we can safely use the result's */
242 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
243 (*aopp)->type = AOP_R0;
244 return mcs51_regWithIdx (R0_IDX);
246 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
247 (*aopp)->type = AOP_R1;
248 return mcs51_regWithIdx (R1_IDX);
252 /* now this is REALLY the end of the world */
253 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
254 "getFreePtr should never reach here");
258 /*-----------------------------------------------------------------*/
259 /* newAsmop - creates a new asmOp */
260 /*-----------------------------------------------------------------*/
262 newAsmop (short type)
266 aop = Safe_calloc (1, sizeof (asmop));
271 /*-----------------------------------------------------------------*/
272 /* pointerCode - returns the code for a pointer type */
273 /*-----------------------------------------------------------------*/
275 pointerCode (sym_link * etype)
278 return PTR_TYPE (SPEC_OCLS (etype));
282 /*-----------------------------------------------------------------*/
283 /* aopForSym - for a true symbol */
284 /*-----------------------------------------------------------------*/
286 aopForSym (iCode * ic, symbol * sym, bool result)
291 wassertl (ic != NULL, "Got a null iCode");
292 wassertl (sym != NULL, "Got a null symbol");
294 space = SPEC_OCLS (sym->etype);
296 /* if already has one */
300 /* assign depending on the storage class */
301 /* if it is on the stack or indirectly addressable */
302 /* space we need to assign either r0 or r1 to it */
303 if (sym->onStack || sym->iaccess)
305 sym->aop = aop = newAsmop (0);
306 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
307 aop->size = getSize (sym->type);
309 /* now assign the address of the variable to
310 the pointer register */
311 if (aop->type != AOP_STK)
317 emitcode ("push", "acc");
319 emitcode ("mov", "a,_bp");
320 emitcode ("add", "a,#0x%02x",
322 ((char) (sym->stack - _G.nRegsSaved)) :
323 ((char) sym->stack)) & 0xff);
324 emitcode ("mov", "%s,a",
325 aop->aopu.aop_ptr->name);
328 emitcode ("pop", "acc");
331 emitcode ("mov", "%s,#%s",
332 aop->aopu.aop_ptr->name,
334 aop->paged = space->paged;
337 aop->aopu.aop_stk = sym->stack;
341 /* if in bit space */
342 if (IN_BITSPACE (space))
344 sym->aop = aop = newAsmop (AOP_CRY);
345 aop->aopu.aop_dir = sym->rname;
346 aop->size = getSize (sym->type);
349 /* if it is in direct space */
350 if (IN_DIRSPACE (space))
352 sym->aop = aop = newAsmop (AOP_DIR);
353 aop->aopu.aop_dir = sym->rname;
354 aop->size = getSize (sym->type);
358 /* special case for a function */
359 if (IS_FUNC (sym->type))
361 sym->aop = aop = newAsmop (AOP_IMMD);
362 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
363 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
364 aop->size = FPTRSIZE;
368 /* only remaining is far space */
369 /* in which case DPTR gets the address */
370 sym->aop = aop = newAsmop (AOP_DPTR);
371 emitcode ("mov", "dptr,#%s", sym->rname);
372 aop->size = getSize (sym->type);
374 /* if it is in code space */
375 if (IN_CODESPACE (space))
381 /*-----------------------------------------------------------------*/
382 /* aopForRemat - rematerialzes an object */
383 /*-----------------------------------------------------------------*/
385 aopForRemat (symbol * sym)
387 iCode *ic = sym->rematiCode;
388 asmop *aop = newAsmop (AOP_IMMD);
395 val += (int) operandLitValue (IC_RIGHT (ic));
396 else if (ic->op == '-')
397 val -= (int) operandLitValue (IC_RIGHT (ic));
398 else if (IS_CAST_ICODE(ic)) {
399 sym_link *from_type = operandType(IC_RIGHT(ic));
400 aop->aopu.aop_immd.from_cast_remat = 1;
401 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
402 ptr_type = DCL_TYPE(from_type);
403 if (ptr_type == IPOINTER) {
410 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
414 sprintf (buffer, "(%s %c 0x%04x)",
415 OP_SYMBOL (IC_LEFT (ic))->rname,
416 val >= 0 ? '+' : '-',
419 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
421 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
422 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
423 /* set immd2 field if required */
424 if (aop->aopu.aop_immd.from_cast_remat) {
425 sprintf(buffer,"#0x%02x",ptr_type);
426 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
427 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
433 /*-----------------------------------------------------------------*/
434 /* regsInCommon - two operands have some registers in common */
435 /*-----------------------------------------------------------------*/
437 regsInCommon (operand * op1, operand * op2)
442 /* if they have registers in common */
443 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
446 sym1 = OP_SYMBOL (op1);
447 sym2 = OP_SYMBOL (op2);
449 if (sym1->nRegs == 0 || sym2->nRegs == 0)
452 for (i = 0; i < sym1->nRegs; i++)
458 for (j = 0; j < sym2->nRegs; j++)
463 if (sym2->regs[j] == sym1->regs[i])
471 /*-----------------------------------------------------------------*/
472 /* operandsEqu - equivalent */
473 /*-----------------------------------------------------------------*/
475 operandsEqu (operand * op1, operand * op2)
479 /* if they not symbols */
480 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
483 sym1 = OP_SYMBOL (op1);
484 sym2 = OP_SYMBOL (op2);
486 /* if both are itemps & one is spilt
487 and the other is not then false */
488 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
489 sym1->isspilt != sym2->isspilt)
492 /* if they are the same */
496 if (strcmp (sym1->rname, sym2->rname) == 0)
500 /* if left is a tmp & right is not */
501 if (IS_ITEMP (op1) &&
504 (sym1->usl.spillLoc == sym2))
507 if (IS_ITEMP (op2) &&
511 (sym2->usl.spillLoc == sym1))
517 /*-----------------------------------------------------------------*/
518 /* sameRegs - two asmops have the same registers */
519 /*-----------------------------------------------------------------*/
521 sameRegs (asmop * aop1, asmop * aop2)
528 if (aop1->type != AOP_REG ||
529 aop2->type != AOP_REG)
532 if (aop1->size != aop2->size)
535 for (i = 0; i < aop1->size; i++)
536 if (aop1->aopu.aop_reg[i] !=
537 aop2->aopu.aop_reg[i])
543 /*-----------------------------------------------------------------*/
544 /* aopOp - allocates an asmop for an operand : */
545 /*-----------------------------------------------------------------*/
547 aopOp (operand * op, iCode * ic, bool result)
556 /* if this a literal */
557 if (IS_OP_LITERAL (op))
559 op->aop = aop = newAsmop (AOP_LIT);
560 aop->aopu.aop_lit = op->operand.valOperand;
561 aop->size = getSize (operandType (op));
565 /* if already has a asmop then continue */
569 /* if the underlying symbol has a aop */
570 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
572 op->aop = OP_SYMBOL (op)->aop;
576 /* if this is a true symbol */
577 if (IS_TRUE_SYMOP (op))
579 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
583 /* this is a temporary : this has
589 e) can be a return use only */
591 sym = OP_SYMBOL (op);
593 /* if the type is a conditional */
594 if (sym->regType == REG_CND)
596 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
601 /* if it is spilt then two situations
603 b) has a spill location */
604 if (sym->isspilt || sym->nRegs == 0)
607 /* rematerialize it NOW */
610 sym->aop = op->aop = aop =
612 aop->size = getSize (sym->type);
619 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
620 aop->size = getSize (sym->type);
621 for (i = 0; i < 2; i++)
622 aop->aopu.aop_str[i] = accUse[i];
630 aop = op->aop = sym->aop = newAsmop (AOP_STR);
631 aop->size = getSize (sym->type);
632 for (i = 0; i < fReturnSizeMCS51; i++)
633 aop->aopu.aop_str[i] = fReturn[i];
637 /* else spill location */
638 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
639 /* force a new aop if sizes differ */
640 sym->usl.spillLoc->aop = NULL;
642 sym->aop = op->aop = aop =
643 aopForSym (ic, sym->usl.spillLoc, result);
644 aop->size = getSize (sym->type);
648 /* must be in a register */
649 sym->aop = op->aop = aop = newAsmop (AOP_REG);
650 aop->size = sym->nRegs;
651 for (i = 0; i < sym->nRegs; i++)
652 aop->aopu.aop_reg[i] = sym->regs[i];
655 /*-----------------------------------------------------------------*/
656 /* freeAsmop - free up the asmop given to an operand */
657 /*----------------------------------------------------------------*/
659 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
676 /* depending on the asmop type only three cases need work AOP_RO
677 , AOP_R1 && AOP_STK */
685 emitcode ("pop", "ar0");
689 bitVectUnSetBit (ic->rUsed, R0_IDX);
697 emitcode ("pop", "ar1");
701 bitVectUnSetBit (ic->rUsed, R1_IDX);
707 int stk = aop->aopu.aop_stk + aop->size;
708 bitVectUnSetBit (ic->rUsed, R0_IDX);
709 bitVectUnSetBit (ic->rUsed, R1_IDX);
711 getFreePtr (ic, &aop, FALSE);
715 emitcode ("mov", "a,_bp");
716 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
717 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
721 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
726 emitcode ("pop", "acc");
727 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
730 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
733 freeAsmop (op, NULL, ic, TRUE);
736 emitcode ("pop", "ar0");
742 emitcode ("pop", "ar1");
749 /* all other cases just dealloc */
755 OP_SYMBOL (op)->aop = NULL;
756 /* if the symbol has a spill */
758 SPIL_LOC (op)->aop = NULL;
763 /*-----------------------------------------------------------------*/
764 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
765 /* clobber the accumulator */
766 /*-----------------------------------------------------------------*/
768 aopGetUsesAcc (asmop *aop, int offset)
770 if (offset > (aop->size - 1))
788 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
797 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
801 /* Error case --- will have been caught already */
808 /*-----------------------------------------------------------------*/
809 /* aopGet - for fetching value of the aop */
810 /*-----------------------------------------------------------------*/
812 aopGet (asmop * aop, int offset, bool bit16, bool dname)
817 /* offset is greater than
819 if (offset > (aop->size - 1) &&
820 aop->type != AOP_LIT)
823 /* depending on type */
829 /* if we need to increment it */
830 while (offset > aop->coff)
832 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
836 while (offset < aop->coff)
838 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
845 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
846 return (dname ? "acc" : "a");
848 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
849 rs = Safe_calloc (1, strlen (s) + 1);
854 if (aop->code && aop->coff==0 && offset>=1) {
855 emitcode ("mov", "a,#0x%02x", offset);
856 emitcode ("movc", "a,@a+dptr");
857 return (dname ? "acc" : "a");
860 while (offset > aop->coff)
862 emitcode ("inc", "dptr");
866 while (offset < aop->coff)
868 emitcode ("lcall", "__decdptr");
875 emitcode ("clr", "a");
876 emitcode ("movc", "a,@a+dptr");
880 emitcode ("movx", "a,@dptr");
882 return (dname ? "acc" : "a");
886 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
887 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
889 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
891 sprintf (s, "#(%s >> %d)",
892 aop->aopu.aop_immd.aop_immd1,
896 aop->aopu.aop_immd.aop_immd1);
897 rs = Safe_calloc (1, strlen (s) + 1);
903 sprintf (s, "(%s + %d)",
907 sprintf (s, "%s", aop->aopu.aop_dir);
908 rs = Safe_calloc (1, strlen (s) + 1);
914 return aop->aopu.aop_reg[offset]->dname;
916 return aop->aopu.aop_reg[offset]->name;
919 emitcode ("clr", "a");
920 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
921 emitcode ("rlc", "a");
922 return (dname ? "acc" : "a");
925 if (!offset && dname)
927 return aop->aopu.aop_str[offset];
930 return aopLiteral (aop->aopu.aop_lit, offset);
934 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
938 return aop->aopu.aop_str[offset];
942 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
943 "aopget got unsupported aop->type");
946 /*-----------------------------------------------------------------*/
947 /* aopPut - puts a string for a aop */
948 /*-----------------------------------------------------------------*/
950 aopPut (asmop * aop, char *s, int offset)
954 if (aop->size && offset > (aop->size - 1))
956 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
957 "aopPut got offset > aop->size");
961 /* will assign value to value */
962 /* depending on where it is ofcourse */
967 sprintf (d, "(%s + %d)",
968 aop->aopu.aop_dir, offset);
970 sprintf (d, "%s", aop->aopu.aop_dir);
973 emitcode ("mov", "%s,%s", d, s);
978 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
979 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
982 strcmp (s, "r0") == 0 ||
983 strcmp (s, "r1") == 0 ||
984 strcmp (s, "r2") == 0 ||
985 strcmp (s, "r3") == 0 ||
986 strcmp (s, "r4") == 0 ||
987 strcmp (s, "r5") == 0 ||
988 strcmp (s, "r6") == 0 ||
989 strcmp (s, "r7") == 0)
990 emitcode ("mov", "%s,%s",
991 aop->aopu.aop_reg[offset]->dname, s);
993 emitcode ("mov", "%s,%s",
994 aop->aopu.aop_reg[offset]->name, s);
1001 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1002 "aopPut writting to code space");
1006 while (offset > aop->coff)
1009 emitcode ("inc", "dptr");
1012 while (offset < aop->coff)
1015 emitcode ("lcall", "__decdptr");
1020 /* if not in accumulater */
1023 emitcode ("movx", "@dptr,a");
1028 while (offset > aop->coff)
1031 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1033 while (offset < aop->coff)
1036 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1043 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1049 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1051 else if (strcmp (s, "r0") == 0 ||
1052 strcmp (s, "r1") == 0 ||
1053 strcmp (s, "r2") == 0 ||
1054 strcmp (s, "r3") == 0 ||
1055 strcmp (s, "r4") == 0 ||
1056 strcmp (s, "r5") == 0 ||
1057 strcmp (s, "r6") == 0 ||
1058 strcmp (s, "r7") == 0)
1061 sprintf (buffer, "a%s", s);
1062 emitcode ("mov", "@%s,%s",
1063 aop->aopu.aop_ptr->name, buffer);
1066 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1071 if (strcmp (s, "a") == 0)
1072 emitcode ("push", "acc");
1076 emitcode ("push", "acc");
1078 emitcode ("push", s);
1084 /* if bit variable */
1085 if (!aop->aopu.aop_dir)
1087 emitcode ("clr", "a");
1088 emitcode ("rlc", "a");
1093 emitcode ("clr", "%s", aop->aopu.aop_dir);
1095 emitcode ("setb", "%s", aop->aopu.aop_dir);
1096 else if (!strcmp (s, "c"))
1097 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1100 if (strcmp (s, "a"))
1105 /* set C, if a >= 1 */
1106 emitcode ("add", "a,#0xff");
1107 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1115 if (strcmp (aop->aopu.aop_str[offset], s))
1116 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1121 if (!offset && (strcmp (s, "acc") == 0))
1124 if (strcmp (aop->aopu.aop_str[offset], s))
1125 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1129 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1130 "aopPut got unsupported aop->type");
1138 /*-----------------------------------------------------------------*/
1139 /* pointToEnd :- points to the last byte of the operand */
1140 /*-----------------------------------------------------------------*/
1142 pointToEnd (asmop * aop)
1148 aop->coff = count = (aop->size - 1);
1154 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1158 emitcode ("inc", "dptr");
1165 /*-----------------------------------------------------------------*/
1166 /* reAdjustPreg - points a register back to where it should */
1167 /*-----------------------------------------------------------------*/
1169 reAdjustPreg (asmop * aop)
1171 if ((aop->coff==0) || aop->size <= 1)
1179 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1184 emitcode ("lcall", "__decdptr");
1191 #define AOP(op) op->aop
1192 #define AOP_TYPE(op) AOP(op)->type
1193 #define AOP_SIZE(op) AOP(op)->size
1194 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1195 AOP_TYPE(x) == AOP_R0))
1197 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1198 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1200 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1201 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1202 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1204 /*-----------------------------------------------------------------*/
1205 /* genNotFloat - generates not for float operations */
1206 /*-----------------------------------------------------------------*/
1208 genNotFloat (operand * op, operand * res)
1214 D(emitcode ("; genNotFloat",""));
1216 /* we will put 127 in the first byte of
1218 aopPut (AOP (res), "#127", 0);
1219 size = AOP_SIZE (op) - 1;
1222 l = aopGet (op->aop, offset++, FALSE, FALSE);
1227 emitcode ("orl", "a,%s",
1229 offset++, FALSE, FALSE));
1232 tlbl = newiTempLabel (NULL);
1233 aopPut (res->aop, one, 1);
1234 emitcode ("jz", "%05d$", (tlbl->key + 100));
1235 aopPut (res->aop, zero, 1);
1236 emitcode ("", "%05d$:", (tlbl->key + 100));
1238 size = res->aop->size - 2;
1240 /* put zeros in the rest */
1242 aopPut (res->aop, zero, offset++);
1245 /*-----------------------------------------------------------------*/
1246 /* opIsGptr: returns non-zero if the passed operand is */
1247 /* a generic pointer type. */
1248 /*-----------------------------------------------------------------*/
1250 opIsGptr (operand * op)
1252 sym_link *type = operandType (op);
1254 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1261 /*-----------------------------------------------------------------*/
1262 /* getDataSize - get the operand data size */
1263 /*-----------------------------------------------------------------*/
1265 getDataSize (operand * op)
1268 size = AOP_SIZE (op);
1269 if (size == GPTRSIZE)
1271 sym_link *type = operandType (op);
1272 if (IS_GENPTR (type))
1274 /* generic pointer; arithmetic operations
1275 * should ignore the high byte (pointer type).
1283 /*-----------------------------------------------------------------*/
1284 /* outAcc - output Acc */
1285 /*-----------------------------------------------------------------*/
1287 outAcc (operand * result)
1290 size = getDataSize (result);
1293 aopPut (AOP (result), "a", 0);
1296 /* unsigned or positive */
1299 aopPut (AOP (result), zero, offset++);
1304 /*-----------------------------------------------------------------*/
1305 /* outBitC - output a bit C */
1306 /*-----------------------------------------------------------------*/
1308 outBitC (operand * result)
1310 /* if the result is bit */
1311 if (AOP_TYPE (result) == AOP_CRY)
1312 aopPut (AOP (result), "c", 0);
1315 emitcode ("clr", "a");
1316 emitcode ("rlc", "a");
1321 /*-----------------------------------------------------------------*/
1322 /* toBoolean - emit code for orl a,operator(sizeop) */
1323 /*-----------------------------------------------------------------*/
1325 toBoolean (operand * oper)
1327 int size = AOP_SIZE (oper) - 1;
1329 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1331 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1335 /*-----------------------------------------------------------------*/
1336 /* genNot - generate code for ! operation */
1337 /*-----------------------------------------------------------------*/
1342 sym_link *optype = operandType (IC_LEFT (ic));
1344 D(emitcode ("; genNot",""));
1346 /* assign asmOps to operand & result */
1347 aopOp (IC_LEFT (ic), ic, FALSE);
1348 aopOp (IC_RESULT (ic), ic, TRUE);
1350 /* if in bit space then a special case */
1351 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1353 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1354 emitcode ("cpl", "c");
1355 outBitC (IC_RESULT (ic));
1359 /* if type float then do float */
1360 if (IS_FLOAT (optype))
1362 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1366 toBoolean (IC_LEFT (ic));
1368 tlbl = newiTempLabel (NULL);
1369 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1370 emitcode ("", "%05d$:", tlbl->key + 100);
1371 outBitC (IC_RESULT (ic));
1374 /* release the aops */
1375 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1376 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1380 /*-----------------------------------------------------------------*/
1381 /* genCpl - generate code for complement */
1382 /*-----------------------------------------------------------------*/
1390 D(emitcode ("; genCpl",""));
1392 /* assign asmOps to operand & result */
1393 aopOp (IC_LEFT (ic), ic, FALSE);
1394 aopOp (IC_RESULT (ic), ic, TRUE);
1396 /* special case if in bit space */
1397 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1398 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1399 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1400 emitcode ("cpl", "c");
1401 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1404 tlbl=newiTempLabel(NULL);
1405 emitcode ("cjne", "%s,#0x01,%05d$",
1406 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1407 emitcode ("", "%05d$:", tlbl->key+100);
1408 outBitC (IC_RESULT(ic));
1412 size = AOP_SIZE (IC_RESULT (ic));
1415 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1417 emitcode ("cpl", "a");
1418 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1423 /* release the aops */
1424 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1425 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1428 /*-----------------------------------------------------------------*/
1429 /* genUminusFloat - unary minus for floating points */
1430 /*-----------------------------------------------------------------*/
1432 genUminusFloat (operand * op, operand * result)
1434 int size, offset = 0;
1437 D(emitcode ("; genUminusFloat",""));
1439 /* for this we just copy and then flip the bit */
1441 size = AOP_SIZE (op) - 1;
1445 aopPut (AOP (result),
1446 aopGet (AOP (op), offset, FALSE, FALSE),
1451 l = aopGet (AOP (op), offset, FALSE, FALSE);
1455 emitcode ("cpl", "acc.7");
1456 aopPut (AOP (result), "a", offset);
1459 /*-----------------------------------------------------------------*/
1460 /* genUminus - unary minus code generation */
1461 /*-----------------------------------------------------------------*/
1463 genUminus (iCode * ic)
1466 sym_link *optype, *rtype;
1469 D(emitcode ("; genUminus",""));
1472 aopOp (IC_LEFT (ic), ic, FALSE);
1473 aopOp (IC_RESULT (ic), ic, TRUE);
1475 /* if both in bit space then special
1477 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1478 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1481 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1482 emitcode ("cpl", "c");
1483 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1487 optype = operandType (IC_LEFT (ic));
1488 rtype = operandType (IC_RESULT (ic));
1490 /* if float then do float stuff */
1491 if (IS_FLOAT (optype))
1493 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1497 /* otherwise subtract from zero */
1498 size = AOP_SIZE (IC_LEFT (ic));
1503 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1504 if (!strcmp (l, "a"))
1508 emitcode ("cpl", "a");
1509 emitcode ("addc", "a,#0");
1515 emitcode ("clr", "a");
1516 emitcode ("subb", "a,%s", l);
1518 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1521 /* if any remaining bytes in the result */
1522 /* we just need to propagate the sign */
1523 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1525 emitcode ("rlc", "a");
1526 emitcode ("subb", "a,acc");
1528 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1532 /* release the aops */
1533 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1534 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1537 /*-----------------------------------------------------------------*/
1538 /* saveRegisters - will look for a call and save the registers */
1539 /*-----------------------------------------------------------------*/
1541 saveRegisters (iCode * lic)
1548 for (ic = lic; ic; ic = ic->next)
1549 if (ic->op == CALL || ic->op == PCALL)
1554 fprintf (stderr, "found parameter push with no function call\n");
1558 /* if the registers have been saved already or don't need to be then
1562 if (IS_SYMOP(IC_LEFT(ic)) &&
1563 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1564 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1567 /* safe the registers in use at this time but skip the
1568 ones for the result */
1569 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1570 mcs51_rUmaskForOp (IC_RESULT(ic)));
1573 if (options.useXstack)
1575 if (bitVectBitValue (rsave, R0_IDX))
1576 emitcode ("mov", "b,r0");
1577 emitcode ("mov", "r0,%s", spname);
1578 for (i = 0; i < mcs51_nRegs; i++)
1580 if (bitVectBitValue (rsave, i))
1583 emitcode ("mov", "a,b");
1585 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1586 emitcode ("movx", "@r0,a");
1587 emitcode ("inc", "r0");
1590 emitcode ("mov", "%s,r0", spname);
1591 if (bitVectBitValue (rsave, R0_IDX))
1592 emitcode ("mov", "r0,b");
1595 for (i = 0; i < mcs51_nRegs; i++)
1597 if (bitVectBitValue (rsave, i))
1598 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1602 /*-----------------------------------------------------------------*/
1603 /* unsaveRegisters - pop the pushed registers */
1604 /*-----------------------------------------------------------------*/
1606 unsaveRegisters (iCode * ic)
1611 /* restore the registers in use at this time but skip the
1612 ones for the result */
1613 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1614 mcs51_rUmaskForOp (IC_RESULT(ic)));
1616 if (options.useXstack)
1618 emitcode ("mov", "r0,%s", spname);
1619 for (i = mcs51_nRegs; i >= 0; i--)
1621 if (bitVectBitValue (rsave, i))
1623 emitcode ("dec", "r0");
1624 emitcode ("movx", "a,@r0");
1626 emitcode ("mov", "b,a");
1628 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1632 emitcode ("mov", "%s,r0", spname);
1633 if (bitVectBitValue (rsave, R0_IDX))
1634 emitcode ("mov", "r0,b");
1637 for (i = mcs51_nRegs; i >= 0; i--)
1639 if (bitVectBitValue (rsave, i))
1640 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1646 /*-----------------------------------------------------------------*/
1648 /*-----------------------------------------------------------------*/
1650 pushSide (operand * oper, int size)
1655 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1656 if (AOP_TYPE (oper) != AOP_REG &&
1657 AOP_TYPE (oper) != AOP_DIR &&
1660 emitcode ("mov", "a,%s", l);
1661 emitcode ("push", "acc");
1664 emitcode ("push", "%s", l);
1668 /*-----------------------------------------------------------------*/
1669 /* assignResultValue - */
1670 /*-----------------------------------------------------------------*/
1672 assignResultValue (operand * oper)
1675 int size = AOP_SIZE (oper);
1678 aopPut (AOP (oper), fReturn[offset], offset);
1684 /*-----------------------------------------------------------------*/
1685 /* genXpush - pushes onto the external stack */
1686 /*-----------------------------------------------------------------*/
1688 genXpush (iCode * ic)
1690 asmop *aop = newAsmop (0);
1692 int size, offset = 0;
1694 D(emitcode ("; genXpush",""));
1696 aopOp (IC_LEFT (ic), ic, FALSE);
1697 r = getFreePtr (ic, &aop, FALSE);
1700 emitcode ("mov", "%s,_spx", r->name);
1702 size = AOP_SIZE (IC_LEFT (ic));
1706 char *l = aopGet (AOP (IC_LEFT (ic)),
1707 offset++, FALSE, FALSE);
1709 emitcode ("movx", "@%s,a", r->name);
1710 emitcode ("inc", "%s", r->name);
1715 emitcode ("mov", "_spx,%s", r->name);
1717 freeAsmop (NULL, aop, ic, TRUE);
1718 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1721 /*-----------------------------------------------------------------*/
1722 /* genIpush - genrate code for pushing this gets a little complex */
1723 /*-----------------------------------------------------------------*/
1725 genIpush (iCode * ic)
1727 int size, offset = 0;
1730 D(emitcode ("; genIpush",""));
1732 /* if this is not a parm push : ie. it is spill push
1733 and spill push is always done on the local stack */
1737 /* and the item is spilt then do nothing */
1738 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1741 aopOp (IC_LEFT (ic), ic, FALSE);
1742 size = AOP_SIZE (IC_LEFT (ic));
1743 /* push it on the stack */
1746 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1752 emitcode ("push", "%s", l);
1757 /* this is a paramter push: in this case we call
1758 the routine to find the call and save those
1759 registers that need to be saved */
1762 /* if use external stack then call the external
1763 stack pushing routine */
1764 if (options.useXstack)
1770 /* then do the push */
1771 aopOp (IC_LEFT (ic), ic, FALSE);
1774 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1775 size = AOP_SIZE (IC_LEFT (ic));
1779 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1780 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1781 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1784 emitcode ("mov", "a,%s", l);
1785 emitcode ("push", "acc");
1788 emitcode ("push", "%s", l);
1791 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1794 /*-----------------------------------------------------------------*/
1795 /* genIpop - recover the registers: can happen only for spilling */
1796 /*-----------------------------------------------------------------*/
1798 genIpop (iCode * ic)
1802 D(emitcode ("; genIpop",""));
1804 /* if the temp was not pushed then */
1805 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1808 aopOp (IC_LEFT (ic), ic, FALSE);
1809 size = AOP_SIZE (IC_LEFT (ic));
1810 offset = (size - 1);
1812 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1815 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1818 /*-----------------------------------------------------------------*/
1819 /* unsaveRBank - restores the resgister bank from stack */
1820 /*-----------------------------------------------------------------*/
1822 unsaveRBank (int bank, iCode * ic, bool popPsw)
1828 if (options.useXstack)
1832 /* Assume r0 is available for use. */
1833 r = mcs51_regWithIdx (R0_IDX);;
1838 r = getFreePtr (ic, &aop, FALSE);
1840 emitcode ("mov", "%s,_spx", r->name);
1845 if (options.useXstack)
1847 emitcode ("movx", "a,@%s", r->name);
1848 emitcode ("mov", "psw,a");
1849 emitcode ("dec", "%s", r->name);
1853 emitcode ("pop", "psw");
1857 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1859 if (options.useXstack)
1861 emitcode ("movx", "a,@%s", r->name);
1862 emitcode ("mov", "(%s+%d),a",
1863 regs8051[i].base, 8 * bank + regs8051[i].offset);
1864 emitcode ("dec", "%s", r->name);
1868 emitcode ("pop", "(%s+%d)",
1869 regs8051[i].base, 8 * bank + regs8051[i].offset);
1872 if (options.useXstack)
1874 emitcode ("mov", "_spx,%s", r->name);
1879 freeAsmop (NULL, aop, ic, TRUE);
1883 /*-----------------------------------------------------------------*/
1884 /* saveRBank - saves an entire register bank on the stack */
1885 /*-----------------------------------------------------------------*/
1887 saveRBank (int bank, iCode * ic, bool pushPsw)
1893 if (options.useXstack)
1897 /* Assume r0 is available for use. */
1898 r = mcs51_regWithIdx (R0_IDX);;
1903 r = getFreePtr (ic, &aop, FALSE);
1905 emitcode ("mov", "%s,_spx", r->name);
1908 for (i = 0; i < mcs51_nRegs; i++)
1910 if (options.useXstack)
1912 emitcode ("inc", "%s", r->name);
1913 emitcode ("mov", "a,(%s+%d)",
1914 regs8051[i].base, 8 * bank + regs8051[i].offset);
1915 emitcode ("movx", "@%s,a", r->name);
1918 emitcode ("push", "(%s+%d)",
1919 regs8051[i].base, 8 * bank + regs8051[i].offset);
1924 if (options.useXstack)
1926 emitcode ("mov", "a,psw");
1927 emitcode ("movx", "@%s,a", r->name);
1928 emitcode ("inc", "%s", r->name);
1929 emitcode ("mov", "_spx,%s", r->name);
1934 emitcode ("push", "psw");
1937 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1942 freeAsmop (NULL, aop, ic, TRUE);
1951 /*-----------------------------------------------------------------*/
1952 /* genSend - gen code for SEND */
1953 /*-----------------------------------------------------------------*/
1954 static void genSend(set *sendSet)
1959 for (sic = setFirstItem (_G.sendSet); sic;
1960 sic = setNextItem (_G.sendSet)) {
1961 int size, offset = 0;
1962 aopOp (IC_LEFT (sic), sic, FALSE);
1963 size = AOP_SIZE (IC_LEFT (sic));
1965 if (sic->argreg == 1) {
1967 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1969 if (strcmp (l, fReturn[offset]))
1970 emitcode ("mov", "%s,%s", fReturn[offset], l);
1976 emitcode ("mov","b1_%d,%s",rb1_count++,
1977 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1980 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1984 /*-----------------------------------------------------------------*/
1985 /* genCall - generates a call statement */
1986 /*-----------------------------------------------------------------*/
1988 genCall (iCode * ic)
1991 // bool restoreBank = FALSE;
1992 bool swapBanks = FALSE;
1994 D(emitcode("; genCall",""));
1996 dtype = operandType (IC_LEFT (ic));
1997 /* if send set is not empty the assign */
2000 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2001 genSend(reverseSet(_G.sendSet));
2003 genSend(_G.sendSet);
2009 /* if we are calling a not _naked function that is not using
2010 the same register bank then we need to save the
2011 destination registers on the stack */
2012 dtype = operandType (IC_LEFT (ic));
2013 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2014 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2015 !IFFUNC_ISISR (dtype))
2020 /* if caller saves & we have not saved then */
2026 emitcode ("mov", "psw,#0x%02x",
2027 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2031 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2032 OP_SYMBOL (IC_LEFT (ic))->rname :
2033 OP_SYMBOL (IC_LEFT (ic))->name));
2037 emitcode ("mov", "psw,#0x%02x",
2038 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2041 /* if we need assign a result value */
2042 if ((IS_ITEMP (IC_RESULT (ic)) &&
2043 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2044 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2045 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2046 IS_TRUE_SYMOP (IC_RESULT (ic)))
2050 aopOp (IC_RESULT (ic), ic, FALSE);
2053 assignResultValue (IC_RESULT (ic));
2055 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2058 /* adjust the stack for parameters if
2063 if (ic->parmBytes > 3)
2065 emitcode ("mov", "a,%s", spname);
2066 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2067 emitcode ("mov", "%s,a", spname);
2070 for (i = 0; i < ic->parmBytes; i++)
2071 emitcode ("dec", "%s", spname);
2074 /* if we hade saved some registers then unsave them */
2075 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2076 unsaveRegisters (ic);
2078 // /* if register bank was saved then pop them */
2080 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2083 /*-----------------------------------------------------------------*/
2084 /* -10l - generates a call by pointer statement */
2085 /*-----------------------------------------------------------------*/
2087 genPcall (iCode * ic)
2090 symbol *rlbl = newiTempLabel (NULL);
2091 // bool restoreBank=FALSE;
2092 bool swapBanks = FALSE;
2094 D(emitcode("; genPCall",""));
2096 /* if caller saves & we have not saved then */
2100 /* if we are calling a not _naked function that is not using
2101 the same register bank then we need to save the
2102 destination registers on the stack */
2103 dtype = operandType (IC_LEFT (ic))->next;
2104 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2105 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2106 !IFFUNC_ISISR (dtype))
2108 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2109 // restoreBank=TRUE;
2111 // need caution message to user here
2114 /* push the return address on to the stack */
2115 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2116 emitcode ("push", "acc");
2117 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2118 emitcode ("push", "acc");
2120 /* now push the calling address */
2121 aopOp (IC_LEFT (ic), ic, FALSE);
2123 pushSide (IC_LEFT (ic), FPTRSIZE);
2125 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2127 /* if send set is not empty the assign */
2130 genSend(reverseSet(_G.sendSet));
2136 emitcode ("mov", "psw,#0x%02x",
2137 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2141 emitcode ("ret", "");
2142 emitcode ("", "%05d$:", (rlbl->key + 100));
2147 emitcode ("mov", "psw,#0x%02x",
2148 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2151 /* if we need assign a result value */
2152 if ((IS_ITEMP (IC_RESULT (ic)) &&
2153 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2154 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2155 IS_TRUE_SYMOP (IC_RESULT (ic)))
2159 aopOp (IC_RESULT (ic), ic, FALSE);
2162 assignResultValue (IC_RESULT (ic));
2164 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2167 /* adjust the stack for parameters if
2172 if (ic->parmBytes > 3)
2174 emitcode ("mov", "a,%s", spname);
2175 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2176 emitcode ("mov", "%s,a", spname);
2179 for (i = 0; i < ic->parmBytes; i++)
2180 emitcode ("dec", "%s", spname);
2184 // /* if register bank was saved then unsave them */
2186 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2188 /* if we hade saved some registers then
2190 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2191 unsaveRegisters (ic);
2194 /*-----------------------------------------------------------------*/
2195 /* resultRemat - result is rematerializable */
2196 /*-----------------------------------------------------------------*/
2198 resultRemat (iCode * ic)
2200 if (SKIP_IC (ic) || ic->op == IFX)
2203 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2205 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2206 if (sym->remat && !POINTER_SET (ic))
2213 #if defined(__BORLANDC__) || defined(_MSC_VER)
2214 #define STRCASECMP stricmp
2216 #define STRCASECMP strcasecmp
2219 /*-----------------------------------------------------------------*/
2220 /* inExcludeList - return 1 if the string is in exclude Reg list */
2221 /*-----------------------------------------------------------------*/
2223 inExcludeList (char *s)
2227 if (options.excludeRegs[i] &&
2228 STRCASECMP (options.excludeRegs[i], "none") == 0)
2231 for (i = 0; options.excludeRegs[i]; i++)
2233 if (options.excludeRegs[i] &&
2234 STRCASECMP (s, options.excludeRegs[i]) == 0)
2240 /*-----------------------------------------------------------------*/
2241 /* genFunction - generated code for function entry */
2242 /*-----------------------------------------------------------------*/
2244 genFunction (iCode * ic)
2248 bool switchedPSW = FALSE;
2249 int calleesaves_saved_register = -1;
2252 /* create the function header */
2253 emitcode (";", "-----------------------------------------");
2254 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2255 emitcode (";", "-----------------------------------------");
2257 emitcode ("", "%s:", sym->rname);
2258 ftype = operandType (IC_LEFT (ic));
2260 if (IFFUNC_ISNAKED(ftype))
2262 emitcode(";", "naked function: no prologue.");
2266 /* if critical function then turn interrupts off */
2267 if (IFFUNC_ISCRITICAL (ftype))
2268 emitcode ("clr", "ea");
2270 /* here we need to generate the equates for the
2271 register bank if required */
2272 if (FUNC_REGBANK (ftype) != rbank)
2276 rbank = FUNC_REGBANK (ftype);
2277 for (i = 0; i < mcs51_nRegs; i++)
2279 if (strcmp (regs8051[i].base, "0") == 0)
2280 emitcode ("", "%s = 0x%02x",
2282 8 * rbank + regs8051[i].offset);
2284 emitcode ("", "%s = %s + 0x%02x",
2287 8 * rbank + regs8051[i].offset);
2291 /* if this is an interrupt service routine then
2292 save acc, b, dpl, dph */
2293 if (IFFUNC_ISISR (sym->type))
2296 if (!inExcludeList ("acc"))
2297 emitcode ("push", "acc");
2298 if (!inExcludeList ("b"))
2299 emitcode ("push", "b");
2300 if (!inExcludeList ("dpl"))
2301 emitcode ("push", "dpl");
2302 if (!inExcludeList ("dph"))
2303 emitcode ("push", "dph");
2304 /* if this isr has no bank i.e. is going to
2305 run with bank 0 , then we need to save more
2307 if (!FUNC_REGBANK (sym->type))
2310 /* if this function does not call any other
2311 function then we can be economical and
2312 save only those registers that are used */
2313 if (!IFFUNC_HASFCALL(sym->type))
2317 /* if any registers used */
2320 /* save the registers used */
2321 for (i = 0; i < sym->regsUsed->size; i++)
2323 if (bitVectBitValue (sym->regsUsed, i) ||
2324 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2325 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2333 /* this function has a function call cannot
2334 determines register usage so we will have to push the
2336 saveRBank (0, ic, FALSE);
2337 if (options.parms_in_bank1) {
2339 for (i=0; i < 8 ; i++ ) {
2340 emitcode ("push","%s",rb1regs[i]);
2347 /* This ISR uses a non-zero bank.
2349 * We assume that the bank is available for our
2352 * However, if this ISR calls a function which uses some
2353 * other bank, we must save that bank entirely.
2355 unsigned long banksToSave = 0;
2357 if (IFFUNC_HASFCALL(sym->type))
2360 #define MAX_REGISTER_BANKS 4
2365 for (i = ic; i; i = i->next)
2367 if (i->op == ENDFUNCTION)
2369 /* we got to the end OK. */
2377 dtype = operandType (IC_LEFT(i));
2379 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2381 /* Mark this bank for saving. */
2382 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2384 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2388 banksToSave |= (1 << FUNC_REGBANK(dtype));
2391 /* And note that we don't need to do it in
2399 /* This is a mess; we have no idea what
2400 * register bank the called function might
2403 * The only thing I can think of to do is
2404 * throw a warning and hope.
2406 werror(W_FUNCPTR_IN_USING_ISR);
2410 if (banksToSave && options.useXstack)
2412 /* Since we aren't passing it an ic,
2413 * saveRBank will assume r0 is available to abuse.
2415 * So switch to our (trashable) bank now, so
2416 * the caller's R0 isn't trashed.
2418 emitcode ("push", "psw");
2419 emitcode ("mov", "psw,#0x%02x",
2420 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2424 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2426 if (banksToSave & (1 << ix))
2428 saveRBank(ix, NULL, FALSE);
2432 // TODO: this needs a closer look
2433 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2438 /* if callee-save to be used for this function
2439 then save the registers being used in this function */
2440 if (IFFUNC_CALLEESAVES(sym->type))
2444 /* if any registers used */
2447 /* save the registers used */
2448 for (i = 0; i < sym->regsUsed->size; i++)
2450 if (bitVectBitValue (sym->regsUsed, i) ||
2451 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2453 /* remember one saved register for later usage */
2454 if (calleesaves_saved_register < 0)
2455 calleesaves_saved_register = i;
2456 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2464 /* set the register bank to the desired value */
2465 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2468 emitcode ("push", "psw");
2469 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2472 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2475 if (options.useXstack)
2477 emitcode ("mov", "r0,%s", spname);
2478 emitcode ("mov", "a,_bp");
2479 emitcode ("movx", "@r0,a");
2480 emitcode ("inc", "%s", spname);
2484 /* set up the stack */
2485 emitcode ("push", "_bp"); /* save the callers stack */
2487 emitcode ("mov", "_bp,%s", spname);
2490 /* adjust the stack for the function */
2496 werror (W_STACK_OVERFLOW, sym->name);
2498 if (i > 3 && sym->recvSize < 4)
2501 emitcode ("mov", "a,sp");
2502 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2503 emitcode ("mov", "sp,a");
2508 if (IFFUNC_CALLEESAVES(sym->type))
2510 /* if it's a callee-saves function we need a saved register */
2511 if (calleesaves_saved_register >= 0)
2513 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2514 emitcode ("mov", "a,sp");
2515 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2516 emitcode ("mov", "sp,a");
2517 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2520 /* do it the hard way */
2522 emitcode ("inc", "sp");
2526 /* not callee-saves, we can clobber r0 */
2527 emitcode ("mov", "r0,a");
2528 emitcode ("mov", "a,sp");
2529 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2530 emitcode ("mov", "sp,a");
2531 emitcode ("mov", "a,r0");
2536 emitcode ("inc", "sp");
2542 emitcode ("mov", "a,_spx");
2543 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2544 emitcode ("mov", "_spx,a");
2549 /*-----------------------------------------------------------------*/
2550 /* genEndFunction - generates epilogue for functions */
2551 /*-----------------------------------------------------------------*/
2553 genEndFunction (iCode * ic)
2555 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2557 if (IFFUNC_ISNAKED(sym->type))
2559 emitcode(";", "naked function: no epilogue.");
2563 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2565 emitcode ("mov", "%s,_bp", spname);
2568 /* if use external stack but some variables were
2569 added to the local stack then decrement the
2571 if (options.useXstack && sym->stack)
2573 emitcode ("mov", "a,sp");
2574 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2575 emitcode ("mov", "sp,a");
2579 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2581 if (options.useXstack)
2583 emitcode ("mov", "r0,%s", spname);
2584 emitcode ("movx", "a,@r0");
2585 emitcode ("mov", "_bp,a");
2586 emitcode ("dec", "%s", spname);
2590 emitcode ("pop", "_bp");
2594 /* restore the register bank */
2595 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2597 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2598 || !options.useXstack)
2600 /* Special case of ISR using non-zero bank with useXstack
2603 emitcode ("pop", "psw");
2607 if (IFFUNC_ISISR (sym->type))
2610 /* now we need to restore the registers */
2611 /* if this isr has no bank i.e. is going to
2612 run with bank 0 , then we need to save more
2614 if (!FUNC_REGBANK (sym->type))
2616 /* if this function does not call any other
2617 function then we can be economical and
2618 save only those registers that are used */
2619 if (!IFFUNC_HASFCALL(sym->type))
2623 /* if any registers used */
2626 /* save the registers used */
2627 for (i = sym->regsUsed->size; i >= 0; i--)
2629 if (bitVectBitValue (sym->regsUsed, i) ||
2630 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2631 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2638 if (options.parms_in_bank1) {
2640 for (i = 7 ; i >= 0 ; i-- ) {
2641 emitcode ("pop","%s",rb1regs[i]);
2644 /* this function has a function call cannot
2645 determines register usage so we will have to pop the
2647 unsaveRBank (0, ic, FALSE);
2652 /* This ISR uses a non-zero bank.
2654 * Restore any register banks saved by genFunction
2657 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2660 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2662 if (savedBanks & (1 << ix))
2664 unsaveRBank(ix, NULL, FALSE);
2668 if (options.useXstack)
2670 /* Restore bank AFTER calling unsaveRBank,
2671 * since it can trash r0.
2673 emitcode ("pop", "psw");
2677 if (!inExcludeList ("dph"))
2678 emitcode ("pop", "dph");
2679 if (!inExcludeList ("dpl"))
2680 emitcode ("pop", "dpl");
2681 if (!inExcludeList ("b"))
2682 emitcode ("pop", "b");
2683 if (!inExcludeList ("acc"))
2684 emitcode ("pop", "acc");
2686 if (IFFUNC_ISCRITICAL (sym->type))
2687 emitcode ("setb", "ea");
2689 /* if debug then send end of function */
2690 if (options.debug && currFunc)
2693 emitcode ("", "C$%s$%d$%d$%d ==.",
2694 FileBaseName (ic->filename), currFunc->lastLine,
2695 ic->level, ic->block);
2696 if (IS_STATIC (currFunc->etype))
2697 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2699 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2703 emitcode ("reti", "");
2707 if (IFFUNC_ISCRITICAL (sym->type))
2708 emitcode ("setb", "ea");
2710 if (IFFUNC_CALLEESAVES(sym->type))
2714 /* if any registers used */
2717 /* save the registers used */
2718 for (i = sym->regsUsed->size; i >= 0; i--)
2720 if (bitVectBitValue (sym->regsUsed, i) ||
2721 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2722 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2728 /* if debug then send end of function */
2729 if (options.debug && currFunc)
2732 emitcode ("", "C$%s$%d$%d$%d ==.",
2733 FileBaseName (ic->filename), currFunc->lastLine,
2734 ic->level, ic->block);
2735 if (IS_STATIC (currFunc->etype))
2736 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2738 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2742 emitcode ("ret", "");
2747 /*-----------------------------------------------------------------*/
2748 /* genRet - generate code for return statement */
2749 /*-----------------------------------------------------------------*/
2753 int size, offset = 0, pushed = 0;
2755 D(emitcode ("; genRet",""));
2757 /* if we have no return value then
2758 just generate the "ret" */
2762 /* we have something to return then
2763 move the return value into place */
2764 aopOp (IC_LEFT (ic), ic, FALSE);
2765 size = AOP_SIZE (IC_LEFT (ic));
2770 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2773 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2775 emitcode ("push", "%s", l);
2780 l = aopGet (AOP (IC_LEFT (ic)), offset,
2782 if (strcmp (fReturn[offset], l))
2783 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2792 if (strcmp (fReturn[pushed], "a"))
2793 emitcode ("pop", fReturn[pushed]);
2795 emitcode ("pop", "acc");
2798 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2801 /* generate a jump to the return label
2802 if the next is not the return statement */
2803 if (!(ic->next && ic->next->op == LABEL &&
2804 IC_LABEL (ic->next) == returnLabel))
2806 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2810 /*-----------------------------------------------------------------*/
2811 /* genLabel - generates a label */
2812 /*-----------------------------------------------------------------*/
2814 genLabel (iCode * ic)
2816 /* special case never generate */
2817 if (IC_LABEL (ic) == entryLabel)
2820 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2823 /*-----------------------------------------------------------------*/
2824 /* genGoto - generates a ljmp */
2825 /*-----------------------------------------------------------------*/
2827 genGoto (iCode * ic)
2829 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2832 /*-----------------------------------------------------------------*/
2833 /* findLabelBackwards: walks back through the iCode chain looking */
2834 /* for the given label. Returns number of iCode instructions */
2835 /* between that label and given ic. */
2836 /* Returns zero if label not found. */
2837 /*-----------------------------------------------------------------*/
2839 findLabelBackwards (iCode * ic, int key)
2848 /* If we have any pushes or pops, we cannot predict the distance.
2849 I don't like this at all, this should be dealt with in the
2851 if (ic->op == IPUSH || ic->op == IPOP) {
2855 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2864 /*-----------------------------------------------------------------*/
2865 /* genPlusIncr :- does addition with increment if possible */
2866 /*-----------------------------------------------------------------*/
2868 genPlusIncr (iCode * ic)
2870 unsigned int icount;
2871 unsigned int size = getDataSize (IC_RESULT (ic));
2873 /* will try to generate an increment */
2874 /* if the right side is not a literal
2876 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2879 /* if the literal value of the right hand side
2880 is greater than 4 then it is not worth it */
2881 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2884 D(emitcode ("; genPlusIncr",""));
2886 /* if increment >=16 bits in register or direct space */
2887 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2888 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2896 /* If the next instruction is a goto and the goto target
2897 * is < 10 instructions previous to this, we can generate
2898 * jumps straight to that target.
2900 if (ic->next && ic->next->op == GOTO
2901 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2902 && labelRange <= 10)
2904 emitcode (";", "tail increment optimized");
2905 tlbl = IC_LABEL (ic->next);
2910 tlbl = newiTempLabel (NULL);
2913 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2914 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2915 IS_AOP_PREG (IC_RESULT (ic)))
2916 emitcode ("cjne", "%s,#0x00,%05d$",
2917 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2921 emitcode ("clr", "a");
2922 emitcode ("cjne", "a,%s,%05d$",
2923 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2927 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2930 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2931 IS_AOP_PREG (IC_RESULT (ic)))
2932 emitcode ("cjne", "%s,#0x00,%05d$",
2933 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2936 emitcode ("cjne", "a,%s,%05d$",
2937 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2940 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2944 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2945 IS_AOP_PREG (IC_RESULT (ic)))
2946 emitcode ("cjne", "%s,#0x00,%05d$",
2947 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2951 emitcode ("cjne", "a,%s,%05d$",
2952 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2955 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2960 emitcode ("", "%05d$:", tlbl->key + 100);
2965 /* if the sizes are greater than 1 then we cannot */
2966 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2967 AOP_SIZE (IC_LEFT (ic)) > 1)
2970 /* we can if the aops of the left & result match or
2971 if they are in registers and the registers are the
2973 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2978 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2979 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2980 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2986 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2995 /*-----------------------------------------------------------------*/
2996 /* outBitAcc - output a bit in acc */
2997 /*-----------------------------------------------------------------*/
2999 outBitAcc (operand * result)
3001 symbol *tlbl = newiTempLabel (NULL);
3002 /* if the result is a bit */
3003 if (AOP_TYPE (result) == AOP_CRY)
3005 aopPut (AOP (result), "a", 0);
3009 emitcode ("jz", "%05d$", tlbl->key + 100);
3010 emitcode ("mov", "a,%s", one);
3011 emitcode ("", "%05d$:", tlbl->key + 100);
3016 /*-----------------------------------------------------------------*/
3017 /* genPlusBits - generates code for addition of two bits */
3018 /*-----------------------------------------------------------------*/
3020 genPlusBits (iCode * ic)
3022 D(emitcode ("; genPlusBits",""));
3024 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3026 symbol *lbl = newiTempLabel (NULL);
3027 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3028 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3029 emitcode ("cpl", "c");
3030 emitcode ("", "%05d$:", (lbl->key + 100));
3031 outBitC (IC_RESULT (ic));
3035 emitcode ("clr", "a");
3036 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3037 emitcode ("rlc", "a");
3038 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3039 emitcode ("addc", "a,#0x00");
3040 outAcc (IC_RESULT (ic));
3045 /* This is the original version of this code.
3047 * This is being kept around for reference,
3048 * because I am not entirely sure I got it right...
3051 adjustArithmeticResult (iCode * ic)
3053 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3054 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3055 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3056 aopPut (AOP (IC_RESULT (ic)),
3057 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3060 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3061 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3062 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3063 aopPut (AOP (IC_RESULT (ic)),
3064 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3067 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3068 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3069 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3070 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3071 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3074 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3075 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3079 /* This is the pure and virtuous version of this code.
3080 * I'm pretty certain it's right, but not enough to toss the old
3084 adjustArithmeticResult (iCode * ic)
3086 if (opIsGptr (IC_RESULT (ic)) &&
3087 opIsGptr (IC_LEFT (ic)) &&
3088 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3090 aopPut (AOP (IC_RESULT (ic)),
3091 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3095 if (opIsGptr (IC_RESULT (ic)) &&
3096 opIsGptr (IC_RIGHT (ic)) &&
3097 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3099 aopPut (AOP (IC_RESULT (ic)),
3100 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3104 if (opIsGptr (IC_RESULT (ic)) &&
3105 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3106 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3107 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3108 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3111 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3112 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3117 /*-----------------------------------------------------------------*/
3118 /* genPlus - generates code for addition */
3119 /*-----------------------------------------------------------------*/
3121 genPlus (iCode * ic)
3123 int size, offset = 0;
3125 asmop *leftOp, *rightOp;
3127 /* special cases :- */
3129 D(emitcode ("; genPlus",""));
3131 aopOp (IC_LEFT (ic), ic, FALSE);
3132 aopOp (IC_RIGHT (ic), ic, FALSE);
3133 aopOp (IC_RESULT (ic), ic, TRUE);
3135 /* if literal, literal on the right or
3136 if left requires ACC or right is already
3138 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3139 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3140 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3142 operand *t = IC_RIGHT (ic);
3143 IC_RIGHT (ic) = IC_LEFT (ic);
3147 /* if both left & right are in bit
3149 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3150 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3156 /* if left in bit space & right literal */
3157 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3158 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3160 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3161 /* if result in bit space */
3162 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3164 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3165 emitcode ("cpl", "c");
3166 outBitC (IC_RESULT (ic));
3170 size = getDataSize (IC_RESULT (ic));
3173 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3174 emitcode ("addc", "a,#00");
3175 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3181 /* if I can do an increment instead
3182 of add then GOOD for ME */
3183 if (genPlusIncr (ic) == TRUE)
3186 size = getDataSize (IC_RESULT (ic));
3188 leftOp = AOP(IC_LEFT(ic));
3189 rightOp = AOP(IC_RIGHT(ic));
3194 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3196 emitcode("mov", "b,a");
3197 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3198 emitcode("xch", "a,b");
3199 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3200 emitcode (add, "a,b");
3202 else if (aopGetUsesAcc (leftOp, offset))
3204 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3205 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3209 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3210 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3212 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3213 add = "addc"; /* further adds must propagate carry */
3216 adjustArithmeticResult (ic);
3219 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3220 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3221 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3224 /*-----------------------------------------------------------------*/
3225 /* genMinusDec :- does subtraction with deccrement if possible */
3226 /*-----------------------------------------------------------------*/
3228 genMinusDec (iCode * ic)
3230 unsigned int icount;
3231 unsigned int size = getDataSize (IC_RESULT (ic));
3233 /* will try to generate an increment */
3234 /* if the right side is not a literal
3236 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3239 /* if the literal value of the right hand side
3240 is greater than 4 then it is not worth it */
3241 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3244 D(emitcode ("; genMinusDec",""));
3246 /* if decrement >=16 bits in register or direct space */
3247 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3248 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3256 /* If the next instruction is a goto and the goto target
3257 * is <= 10 instructions previous to this, we can generate
3258 * jumps straight to that target.
3260 if (ic->next && ic->next->op == GOTO
3261 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3262 && labelRange <= 10)
3264 emitcode (";", "tail decrement optimized");
3265 tlbl = IC_LABEL (ic->next);
3270 tlbl = newiTempLabel (NULL);
3274 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3275 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3276 IS_AOP_PREG (IC_RESULT (ic)))
3277 emitcode ("cjne", "%s,#0xff,%05d$"
3278 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3282 emitcode ("mov", "a,#0xff");
3283 emitcode ("cjne", "a,%s,%05d$"
3284 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3287 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3290 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3291 IS_AOP_PREG (IC_RESULT (ic)))
3292 emitcode ("cjne", "%s,#0xff,%05d$"
3293 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3297 emitcode ("cjne", "a,%s,%05d$"
3298 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3301 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3305 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3306 IS_AOP_PREG (IC_RESULT (ic)))
3307 emitcode ("cjne", "%s,#0xff,%05d$"
3308 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3312 emitcode ("cjne", "a,%s,%05d$"
3313 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3316 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3320 emitcode ("", "%05d$:", tlbl->key + 100);
3325 /* if the sizes are greater than 1 then we cannot */
3326 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3327 AOP_SIZE (IC_LEFT (ic)) > 1)
3330 /* we can if the aops of the left & result match or
3331 if they are in registers and the registers are the
3333 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3337 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3345 /*-----------------------------------------------------------------*/
3346 /* addSign - complete with sign */
3347 /*-----------------------------------------------------------------*/
3349 addSign (operand * result, int offset, int sign)
3351 int size = (getDataSize (result) - offset);
3356 emitcode ("rlc", "a");
3357 emitcode ("subb", "a,acc");
3359 aopPut (AOP (result), "a", offset++);
3363 aopPut (AOP (result), zero, offset++);
3367 /*-----------------------------------------------------------------*/
3368 /* genMinusBits - generates code for subtraction of two bits */
3369 /*-----------------------------------------------------------------*/
3371 genMinusBits (iCode * ic)
3373 symbol *lbl = newiTempLabel (NULL);
3375 D(emitcode ("; genMinusBits",""));
3377 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3379 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3380 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3381 emitcode ("cpl", "c");
3382 emitcode ("", "%05d$:", (lbl->key + 100));
3383 outBitC (IC_RESULT (ic));
3387 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3388 emitcode ("subb", "a,acc");
3389 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3390 emitcode ("inc", "a");
3391 emitcode ("", "%05d$:", (lbl->key + 100));
3392 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3393 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3397 /*-----------------------------------------------------------------*/
3398 /* genMinus - generates code for subtraction */
3399 /*-----------------------------------------------------------------*/
3401 genMinus (iCode * ic)
3403 int size, offset = 0;
3405 D(emitcode ("; genMinus",""));
3407 aopOp (IC_LEFT (ic), ic, FALSE);
3408 aopOp (IC_RIGHT (ic), ic, FALSE);
3409 aopOp (IC_RESULT (ic), ic, TRUE);
3411 /* special cases :- */
3412 /* if both left & right are in bit space */
3413 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3414 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3420 /* if I can do an decrement instead
3421 of subtract then GOOD for ME */
3422 if (genMinusDec (ic) == TRUE)
3425 size = getDataSize (IC_RESULT (ic));
3427 /* if literal, add a,#-lit, else normal subb */
3428 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3430 unsigned long lit = 0L;
3432 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3437 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3438 /* first add without previous c */
3440 if (!size && lit==-1) {
3441 emitcode ("dec", "a");
3443 emitcode ("add", "a,#0x%02x",
3444 (unsigned int) (lit & 0x0FFL));
3447 emitcode ("addc", "a,#0x%02x",
3448 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3450 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3455 asmop *leftOp, *rightOp;
3457 leftOp = AOP(IC_LEFT(ic));
3458 rightOp = AOP(IC_RIGHT(ic));
3462 if (aopGetUsesAcc(rightOp, offset)) {
3463 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3464 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3466 emitcode( "setb", "c");
3468 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3469 emitcode("cpl", "a");
3471 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3474 emitcode ("subb", "a,%s",
3475 aopGet(rightOp, offset, FALSE, TRUE));
3478 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3483 adjustArithmeticResult (ic);
3486 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3487 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3488 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3492 /*-----------------------------------------------------------------*/
3493 /* genMultbits :- multiplication of bits */
3494 /*-----------------------------------------------------------------*/
3496 genMultbits (operand * left,
3500 D(emitcode ("; genMultbits",""));
3502 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3503 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3508 /*-----------------------------------------------------------------*/
3509 /* genMultOneByte : 8*8=8/16 bit multiplication */
3510 /*-----------------------------------------------------------------*/
3512 genMultOneByte (operand * left,
3516 sym_link *opetype = operandType (result);
3518 int size=AOP_SIZE(result);
3520 D(emitcode ("; genMultOneByte",""));
3522 if (size<1 || size>2) {
3523 // this should never happen
3524 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3525 AOP_SIZE(result), __FILE__, lineno);
3529 /* (if two literals: the value is computed before) */
3530 /* if one literal, literal on the right */
3531 if (AOP_TYPE (left) == AOP_LIT)
3536 //emitcode (";", "swapped left and right");
3539 if (SPEC_USIGN(opetype)
3540 // ignore the sign of left and right, what else can we do?
3541 || (SPEC_USIGN(operandType(left)) &&
3542 SPEC_USIGN(operandType(right)))) {
3543 // just an unsigned 8*8=8/16 multiply
3544 //emitcode (";","unsigned");
3545 // TODO: check for accumulator clash between left & right aops?
3546 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3547 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3548 emitcode ("mul", "ab");
3549 aopPut (AOP (result), "a", 0);
3551 aopPut (AOP (result), "b", 1);
3556 // we have to do a signed multiply
3558 //emitcode (";", "signed");
3559 emitcode ("clr", "F0"); // reset sign flag
3560 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3562 lbl=newiTempLabel(NULL);
3563 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3564 // left side is negative, 8-bit two's complement, this fails for -128
3565 emitcode ("setb", "F0"); // set sign flag
3566 emitcode ("cpl", "a");
3567 emitcode ("inc", "a");
3569 emitcode ("", "%05d$:", lbl->key+100);
3572 if (AOP_TYPE(right)==AOP_LIT) {
3573 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3574 /* AND literal negative */
3576 emitcode ("cpl", "F0"); // complement sign flag
3577 emitcode ("mov", "b,#0x%02x", -val);
3579 emitcode ("mov", "b,#0x%02x", val);
3582 lbl=newiTempLabel(NULL);
3583 emitcode ("mov", "b,a");
3584 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3585 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3586 // right side is negative, 8-bit two's complement
3587 emitcode ("cpl", "F0"); // complement sign flag
3588 emitcode ("cpl", "a");
3589 emitcode ("inc", "a");
3590 emitcode ("", "%05d$:", lbl->key+100);
3592 emitcode ("mul", "ab");
3594 lbl=newiTempLabel(NULL);
3595 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3596 // only ONE op was negative, we have to do a 8/16-bit two's complement
3597 emitcode ("cpl", "a"); // lsb
3599 emitcode ("inc", "a");
3601 emitcode ("add", "a,#1");
3602 emitcode ("xch", "a,b");
3603 emitcode ("cpl", "a"); // msb
3604 emitcode ("addc", "a,#0");
3605 emitcode ("xch", "a,b");
3608 emitcode ("", "%05d$:", lbl->key+100);
3609 aopPut (AOP (result), "a", 0);
3611 aopPut (AOP (result), "b", 1);
3615 /*-----------------------------------------------------------------*/
3616 /* genMult - generates code for multiplication */
3617 /*-----------------------------------------------------------------*/
3619 genMult (iCode * ic)
3621 operand *left = IC_LEFT (ic);
3622 operand *right = IC_RIGHT (ic);
3623 operand *result = IC_RESULT (ic);
3625 D(emitcode ("; genMult",""));
3627 /* assign the amsops */
3628 aopOp (left, ic, FALSE);
3629 aopOp (right, ic, FALSE);
3630 aopOp (result, ic, TRUE);
3632 /* special cases first */
3634 if (AOP_TYPE (left) == AOP_CRY &&
3635 AOP_TYPE (right) == AOP_CRY)
3637 genMultbits (left, right, result);
3641 /* if both are of size == 1 */
3642 #if 0 // one of them can be a sloc shared with the result
3643 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3645 if (getSize(operandType(left)) == 1 &&
3646 getSize(operandType(right)) == 1)
3649 genMultOneByte (left, right, result);
3653 /* should have been converted to function call */
3654 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3655 getSize(OP_SYMBOL(right)->type));
3659 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3660 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3661 freeAsmop (result, NULL, ic, TRUE);
3664 /*-----------------------------------------------------------------*/
3665 /* genDivbits :- division of bits */
3666 /*-----------------------------------------------------------------*/
3668 genDivbits (operand * left,
3675 D(emitcode ("; genDivbits",""));
3677 /* the result must be bit */
3678 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3679 l = aopGet (AOP (left), 0, FALSE, FALSE);
3683 emitcode ("div", "ab");
3684 emitcode ("rrc", "a");
3685 aopPut (AOP (result), "c", 0);
3688 /*-----------------------------------------------------------------*/
3689 /* genDivOneByte : 8 bit division */
3690 /*-----------------------------------------------------------------*/
3692 genDivOneByte (operand * left,
3696 sym_link *opetype = operandType (result);
3701 D(emitcode ("; genDivOneByte",""));
3703 size = AOP_SIZE (result) - 1;
3705 /* signed or unsigned */
3706 if (SPEC_USIGN (opetype))
3708 /* unsigned is easy */
3709 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3710 l = aopGet (AOP (left), 0, FALSE, FALSE);
3712 emitcode ("div", "ab");
3713 aopPut (AOP (result), "a", 0);
3715 aopPut (AOP (result), zero, offset++);
3719 /* signed is a little bit more difficult */
3721 /* save the signs of the operands */
3722 l = aopGet (AOP (left), 0, FALSE, FALSE);
3724 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3725 emitcode ("push", "acc"); /* save it on the stack */
3727 /* now sign adjust for both left & right */
3728 l = aopGet (AOP (right), 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));
3735 emitcode ("mov", "b,a");
3737 /* sign adjust left side */
3738 l = aopGet (AOP (left), 0, FALSE, FALSE);
3741 lbl = newiTempLabel (NULL);
3742 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3743 emitcode ("cpl", "a");
3744 emitcode ("inc", "a");
3745 emitcode ("", "%05d$:", (lbl->key + 100));
3747 /* now the division */
3748 emitcode ("div", "ab");
3749 /* we are interested in the lower order
3751 emitcode ("mov", "b,a");
3752 lbl = newiTempLabel (NULL);
3753 emitcode ("pop", "acc");
3754 /* if there was an over flow we don't
3755 adjust the sign of the result */
3756 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3757 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3759 emitcode ("clr", "a");
3760 emitcode ("subb", "a,b");
3761 emitcode ("mov", "b,a");
3762 emitcode ("", "%05d$:", (lbl->key + 100));
3764 /* now we are done */
3765 aopPut (AOP (result), "b", 0);
3768 emitcode ("mov", "c,b.7");
3769 emitcode ("subb", "a,acc");
3772 aopPut (AOP (result), "a", offset++);
3776 /*-----------------------------------------------------------------*/
3777 /* genDiv - generates code for division */
3778 /*-----------------------------------------------------------------*/
3782 operand *left = IC_LEFT (ic);
3783 operand *right = IC_RIGHT (ic);
3784 operand *result = IC_RESULT (ic);
3786 D(emitcode ("; genDiv",""));
3788 /* assign the amsops */
3789 aopOp (left, ic, FALSE);
3790 aopOp (right, ic, FALSE);
3791 aopOp (result, ic, TRUE);
3793 /* special cases first */
3795 if (AOP_TYPE (left) == AOP_CRY &&
3796 AOP_TYPE (right) == AOP_CRY)
3798 genDivbits (left, right, result);
3802 /* if both are of size == 1 */
3803 if (AOP_SIZE (left) == 1 &&
3804 AOP_SIZE (right) == 1)
3806 genDivOneByte (left, right, result);
3810 /* should have been converted to function call */
3813 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3814 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3815 freeAsmop (result, NULL, ic, TRUE);
3818 /*-----------------------------------------------------------------*/
3819 /* genModbits :- modulus of bits */
3820 /*-----------------------------------------------------------------*/
3822 genModbits (operand * left,
3829 D(emitcode ("; genModbits",""));
3831 /* the result must be bit */
3832 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3833 l = aopGet (AOP (left), 0, FALSE, FALSE);
3837 emitcode ("div", "ab");
3838 emitcode ("mov", "a,b");
3839 emitcode ("rrc", "a");
3840 aopPut (AOP (result), "c", 0);
3843 /*-----------------------------------------------------------------*/
3844 /* genModOneByte : 8 bit modulus */
3845 /*-----------------------------------------------------------------*/
3847 genModOneByte (operand * left,
3851 sym_link *opetype = operandType (result);
3855 D(emitcode ("; genModOneByte",""));
3857 /* signed or unsigned */
3858 if (SPEC_USIGN (opetype))
3860 /* unsigned is easy */
3861 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3862 l = aopGet (AOP (left), 0, FALSE, FALSE);
3864 emitcode ("div", "ab");
3865 aopPut (AOP (result), "b", 0);
3869 /* signed is a little bit more difficult */
3871 /* save the signs of the operands */
3872 l = aopGet (AOP (left), 0, FALSE, FALSE);
3875 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3876 emitcode ("push", "acc"); /* save it on the stack */
3878 /* now sign adjust for both left & right */
3879 l = aopGet (AOP (right), 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));
3887 emitcode ("mov", "b,a");
3889 /* sign adjust left side */
3890 l = aopGet (AOP (left), 0, FALSE, FALSE);
3893 lbl = newiTempLabel (NULL);
3894 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3895 emitcode ("cpl", "a");
3896 emitcode ("inc", "a");
3897 emitcode ("", "%05d$:", (lbl->key + 100));
3899 /* now the multiplication */
3900 emitcode ("div", "ab");
3901 /* we are interested in the lower order
3903 lbl = newiTempLabel (NULL);
3904 emitcode ("pop", "acc");
3905 /* if there was an over flow we don't
3906 adjust the sign of the result */
3907 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3908 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3910 emitcode ("clr", "a");
3911 emitcode ("subb", "a,b");
3912 emitcode ("mov", "b,a");
3913 emitcode ("", "%05d$:", (lbl->key + 100));
3915 /* now we are done */
3916 aopPut (AOP (result), "b", 0);
3920 /*-----------------------------------------------------------------*/
3921 /* genMod - generates code for division */
3922 /*-----------------------------------------------------------------*/
3926 operand *left = IC_LEFT (ic);
3927 operand *right = IC_RIGHT (ic);
3928 operand *result = IC_RESULT (ic);
3930 D(emitcode ("; genMod",""));
3932 /* assign the amsops */
3933 aopOp (left, ic, FALSE);
3934 aopOp (right, ic, FALSE);
3935 aopOp (result, ic, TRUE);
3937 /* special cases first */
3939 if (AOP_TYPE (left) == AOP_CRY &&
3940 AOP_TYPE (right) == AOP_CRY)
3942 genModbits (left, right, result);
3946 /* if both are of size == 1 */
3947 if (AOP_SIZE (left) == 1 &&
3948 AOP_SIZE (right) == 1)
3950 genModOneByte (left, right, result);
3954 /* should have been converted to function call */
3958 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3959 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3960 freeAsmop (result, NULL, ic, TRUE);
3963 /*-----------------------------------------------------------------*/
3964 /* genIfxJump :- will create a jump depending on the ifx */
3965 /*-----------------------------------------------------------------*/
3967 genIfxJump (iCode * ic, char *jval)
3970 symbol *tlbl = newiTempLabel (NULL);
3973 D(emitcode ("; genIfxJump",""));
3975 /* if true label then we jump if condition
3979 jlbl = IC_TRUE (ic);
3980 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3981 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3985 /* false label is present */
3986 jlbl = IC_FALSE (ic);
3987 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3988 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3990 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3991 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3993 emitcode (inst, "%05d$", tlbl->key + 100);
3994 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3995 emitcode ("", "%05d$:", tlbl->key + 100);
3997 /* mark the icode as generated */
4001 /*-----------------------------------------------------------------*/
4002 /* genCmp :- greater or less than comparison */
4003 /*-----------------------------------------------------------------*/
4005 genCmp (operand * left, operand * right,
4006 operand * result, iCode * ifx, int sign, iCode *ic)
4008 int size, offset = 0;
4009 unsigned long lit = 0L;
4011 D(emitcode ("; genCmp",""));
4013 /* if left & right are bit variables */
4014 if (AOP_TYPE (left) == AOP_CRY &&
4015 AOP_TYPE (right) == AOP_CRY)
4017 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4018 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4022 /* subtract right from left if at the
4023 end the carry flag is set then we know that
4024 left is greater than right */
4025 size = max (AOP_SIZE (left), AOP_SIZE (right));
4027 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4028 if ((size == 1) && !sign &&
4029 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4031 symbol *lbl = newiTempLabel (NULL);
4032 emitcode ("cjne", "%s,%s,%05d$",
4033 aopGet (AOP (left), offset, FALSE, FALSE),
4034 aopGet (AOP (right), offset, FALSE, FALSE),
4036 emitcode ("", "%05d$:", lbl->key + 100);
4040 if (AOP_TYPE (right) == AOP_LIT)
4042 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4043 /* optimize if(x < 0) or if(x >= 0) */
4052 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4053 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4055 genIfxJump (ifx, "acc.7");
4059 emitcode ("rlc", "a");
4067 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4068 if (sign && size == 0)
4070 emitcode ("xrl", "a,#0x80");
4071 if (AOP_TYPE (right) == AOP_LIT)
4073 unsigned long lit = (unsigned long)
4074 floatFromVal (AOP (right)->aopu.aop_lit);
4075 emitcode ("subb", "a,#0x%02x",
4076 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4080 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4081 emitcode ("xrl", "b,#0x80");
4082 emitcode ("subb", "a,b");
4086 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4092 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4093 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4094 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4100 /* if the result is used in the next
4101 ifx conditional branch then generate
4102 code a little differently */
4104 genIfxJump (ifx, "c");
4107 /* leave the result in acc */
4111 /*-----------------------------------------------------------------*/
4112 /* genCmpGt :- greater than comparison */
4113 /*-----------------------------------------------------------------*/
4115 genCmpGt (iCode * ic, iCode * ifx)
4117 operand *left, *right, *result;
4118 sym_link *letype, *retype;
4121 D(emitcode ("; genCmpGt",""));
4123 left = IC_LEFT (ic);
4124 right = IC_RIGHT (ic);
4125 result = IC_RESULT (ic);
4127 letype = getSpec (operandType (left));
4128 retype = getSpec (operandType (right));
4129 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4130 /* assign the amsops */
4131 aopOp (left, ic, FALSE);
4132 aopOp (right, ic, FALSE);
4133 aopOp (result, ic, TRUE);
4135 genCmp (right, left, result, ifx, sign,ic);
4137 freeAsmop (result, NULL, ic, TRUE);
4140 /*-----------------------------------------------------------------*/
4141 /* genCmpLt - less than comparisons */
4142 /*-----------------------------------------------------------------*/
4144 genCmpLt (iCode * ic, iCode * ifx)
4146 operand *left, *right, *result;
4147 sym_link *letype, *retype;
4150 D(emitcode ("; genCmpLt",""));
4152 left = IC_LEFT (ic);
4153 right = IC_RIGHT (ic);
4154 result = IC_RESULT (ic);
4156 letype = getSpec (operandType (left));
4157 retype = getSpec (operandType (right));
4158 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4160 /* assign the amsops */
4161 aopOp (left, ic, FALSE);
4162 aopOp (right, ic, FALSE);
4163 aopOp (result, ic, TRUE);
4165 genCmp (left, right, result, ifx, sign,ic);
4167 freeAsmop (result, NULL, ic, TRUE);
4170 /*-----------------------------------------------------------------*/
4171 /* gencjneshort - compare and jump if not equal */
4172 /*-----------------------------------------------------------------*/
4174 gencjneshort (operand * left, operand * right, symbol * lbl)
4176 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4178 unsigned long lit = 0L;
4180 /* if the left side is a literal or
4181 if the right is in a pointer register and left
4183 if ((AOP_TYPE (left) == AOP_LIT) ||
4184 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4190 if (AOP_TYPE (right) == AOP_LIT)
4191 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4193 /* if the right side is a literal then anything goes */
4194 if (AOP_TYPE (right) == AOP_LIT &&
4195 AOP_TYPE (left) != AOP_DIR)
4199 emitcode ("cjne", "%s,%s,%05d$",
4200 aopGet (AOP (left), offset, FALSE, FALSE),
4201 aopGet (AOP (right), offset, FALSE, FALSE),
4207 /* if the right side is in a register or in direct space or
4208 if the left is a pointer register & right is not */
4209 else if (AOP_TYPE (right) == AOP_REG ||
4210 AOP_TYPE (right) == AOP_DIR ||
4211 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4212 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4216 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4217 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4218 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4219 emitcode ("jnz", "%05d$", lbl->key + 100);
4221 emitcode ("cjne", "a,%s,%05d$",
4222 aopGet (AOP (right), offset, FALSE, TRUE),
4229 /* right is a pointer reg need both a & b */
4232 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4233 if (strcmp (l, "b"))
4234 emitcode ("mov", "b,%s", l);
4235 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4236 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4242 /*-----------------------------------------------------------------*/
4243 /* gencjne - compare and jump if not equal */
4244 /*-----------------------------------------------------------------*/
4246 gencjne (operand * left, operand * right, symbol * lbl)
4248 symbol *tlbl = newiTempLabel (NULL);
4250 gencjneshort (left, right, lbl);
4252 emitcode ("mov", "a,%s", one);
4253 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4254 emitcode ("", "%05d$:", lbl->key + 100);
4255 emitcode ("clr", "a");
4256 emitcode ("", "%05d$:", tlbl->key + 100);
4259 /*-----------------------------------------------------------------*/
4260 /* genCmpEq - generates code for equal to */
4261 /*-----------------------------------------------------------------*/
4263 genCmpEq (iCode * ic, iCode * ifx)
4265 operand *left, *right, *result;
4267 D(emitcode ("; genCmpEq",""));
4269 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4270 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4271 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4273 /* if literal, literal on the right or
4274 if the right is in a pointer register and left
4276 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4277 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4279 operand *t = IC_RIGHT (ic);
4280 IC_RIGHT (ic) = IC_LEFT (ic);
4284 if (ifx && !AOP_SIZE (result))
4287 /* if they are both bit variables */
4288 if (AOP_TYPE (left) == AOP_CRY &&
4289 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4291 if (AOP_TYPE (right) == AOP_LIT)
4293 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4297 emitcode ("cpl", "c");
4301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4305 emitcode ("clr", "c");
4307 /* AOP_TYPE(right) == AOP_CRY */
4311 symbol *lbl = newiTempLabel (NULL);
4312 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4313 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4314 emitcode ("cpl", "c");
4315 emitcode ("", "%05d$:", (lbl->key + 100));
4317 /* if true label then we jump if condition
4319 tlbl = newiTempLabel (NULL);
4322 emitcode ("jnc", "%05d$", tlbl->key + 100);
4323 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4327 emitcode ("jc", "%05d$", tlbl->key + 100);
4328 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4330 emitcode ("", "%05d$:", tlbl->key + 100);
4334 tlbl = newiTempLabel (NULL);
4335 gencjneshort (left, right, tlbl);
4338 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4339 emitcode ("", "%05d$:", tlbl->key + 100);
4343 symbol *lbl = newiTempLabel (NULL);
4344 emitcode ("sjmp", "%05d$", lbl->key + 100);
4345 emitcode ("", "%05d$:", tlbl->key + 100);
4346 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4347 emitcode ("", "%05d$:", lbl->key + 100);
4350 /* mark the icode as generated */
4355 /* if they are both bit variables */
4356 if (AOP_TYPE (left) == AOP_CRY &&
4357 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4359 if (AOP_TYPE (right) == AOP_LIT)
4361 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4364 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4365 emitcode ("cpl", "c");
4369 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4373 emitcode ("clr", "c");
4375 /* AOP_TYPE(right) == AOP_CRY */
4379 symbol *lbl = newiTempLabel (NULL);
4380 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4381 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4382 emitcode ("cpl", "c");
4383 emitcode ("", "%05d$:", (lbl->key + 100));
4386 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4393 genIfxJump (ifx, "c");
4396 /* if the result is used in an arithmetic operation
4397 then put the result in place */
4402 gencjne (left, right, newiTempLabel (NULL));
4403 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4405 aopPut (AOP (result), "a", 0);
4410 genIfxJump (ifx, "a");
4413 /* if the result is used in an arithmetic operation
4414 then put the result in place */
4415 if (AOP_TYPE (result) != AOP_CRY)
4417 /* leave the result in acc */
4421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4423 freeAsmop (result, NULL, ic, TRUE);
4426 /*-----------------------------------------------------------------*/
4427 /* ifxForOp - returns the icode containing the ifx for operand */
4428 /*-----------------------------------------------------------------*/
4430 ifxForOp (operand * op, iCode * ic)
4432 /* if true symbol then needs to be assigned */
4433 if (IS_TRUE_SYMOP (op))
4436 /* if this has register type condition and
4437 the next instruction is ifx with the same operand
4438 and live to of the operand is upto the ifx only then */
4440 ic->next->op == IFX &&
4441 IC_COND (ic->next)->key == op->key &&
4442 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4448 /*-----------------------------------------------------------------*/
4449 /* hasInc - operand is incremented before any other use */
4450 /*-----------------------------------------------------------------*/
4452 hasInc (operand *op, iCode *ic,int osize)
4454 sym_link *type = operandType(op);
4455 sym_link *retype = getSpec (type);
4456 iCode *lic = ic->next;
4459 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4460 if (!IS_SYMOP(op)) return NULL;
4462 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4463 if (IS_AGGREGATE(type->next)) return NULL;
4464 if (osize != (isize = getSize(type->next))) return NULL;
4467 /* if operand of the form op = op + <sizeof *op> */
4468 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4469 isOperandEqual(IC_RESULT(lic),op) &&
4470 isOperandLiteral(IC_RIGHT(lic)) &&
4471 operandLitValue(IC_RIGHT(lic)) == isize) {
4474 /* if the operand used or deffed */
4475 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4478 /* if GOTO or IFX */
4479 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4485 /*-----------------------------------------------------------------*/
4486 /* genAndOp - for && operation */
4487 /*-----------------------------------------------------------------*/
4489 genAndOp (iCode * ic)
4491 operand *left, *right, *result;
4494 D(emitcode ("; genAndOp",""));
4496 /* note here that && operations that are in an
4497 if statement are taken away by backPatchLabels
4498 only those used in arthmetic operations remain */
4499 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4500 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4501 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4503 /* if both are bit variables */
4504 if (AOP_TYPE (left) == AOP_CRY &&
4505 AOP_TYPE (right) == AOP_CRY)
4507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4508 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4513 tlbl = newiTempLabel (NULL);
4515 emitcode ("jz", "%05d$", tlbl->key + 100);
4517 emitcode ("", "%05d$:", tlbl->key + 100);
4521 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4522 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4523 freeAsmop (result, NULL, ic, TRUE);
4527 /*-----------------------------------------------------------------*/
4528 /* genOrOp - for || operation */
4529 /*-----------------------------------------------------------------*/
4531 genOrOp (iCode * ic)
4533 operand *left, *right, *result;
4536 D(emitcode ("; genOrOp",""));
4538 /* note here that || operations that are in an
4539 if statement are taken away by backPatchLabels
4540 only those used in arthmetic operations remain */
4541 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4542 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4543 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4545 /* if both are bit variables */
4546 if (AOP_TYPE (left) == AOP_CRY &&
4547 AOP_TYPE (right) == AOP_CRY)
4549 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4550 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4555 tlbl = newiTempLabel (NULL);
4557 emitcode ("jnz", "%05d$", tlbl->key + 100);
4559 emitcode ("", "%05d$:", tlbl->key + 100);
4563 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4564 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4565 freeAsmop (result, NULL, ic, TRUE);
4568 /*-----------------------------------------------------------------*/
4569 /* isLiteralBit - test if lit == 2^n */
4570 /*-----------------------------------------------------------------*/
4572 isLiteralBit (unsigned long lit)
4574 unsigned long pw[32] =
4575 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4576 0x100L, 0x200L, 0x400L, 0x800L,
4577 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4578 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4579 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4580 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4581 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4584 for (idx = 0; idx < 32; idx++)
4590 /*-----------------------------------------------------------------*/
4591 /* continueIfTrue - */
4592 /*-----------------------------------------------------------------*/
4594 continueIfTrue (iCode * ic)
4597 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4601 /*-----------------------------------------------------------------*/
4603 /*-----------------------------------------------------------------*/
4605 jumpIfTrue (iCode * ic)
4608 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4612 /*-----------------------------------------------------------------*/
4613 /* jmpTrueOrFalse - */
4614 /*-----------------------------------------------------------------*/
4616 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4618 // ugly but optimized by peephole
4621 symbol *nlbl = newiTempLabel (NULL);
4622 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4623 emitcode ("", "%05d$:", tlbl->key + 100);
4624 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4625 emitcode ("", "%05d$:", nlbl->key + 100);
4629 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4630 emitcode ("", "%05d$:", tlbl->key + 100);
4635 /*-----------------------------------------------------------------*/
4636 /* genAnd - code for and */
4637 /*-----------------------------------------------------------------*/
4639 genAnd (iCode * ic, iCode * ifx)
4641 operand *left, *right, *result;
4642 int size, offset = 0;
4643 unsigned long lit = 0L;
4647 D(emitcode ("; genAnd",""));
4649 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4650 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4651 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4654 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4656 AOP_TYPE (left), AOP_TYPE (right));
4657 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4659 AOP_SIZE (left), AOP_SIZE (right));
4662 /* if left is a literal & right is not then exchange them */
4663 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4664 AOP_NEEDSACC (left))
4666 operand *tmp = right;
4671 /* if result = right then exchange them */
4672 if (sameRegs (AOP (result), AOP (right)))
4674 operand *tmp = right;
4679 /* if right is bit then exchange them */
4680 if (AOP_TYPE (right) == AOP_CRY &&
4681 AOP_TYPE (left) != AOP_CRY)
4683 operand *tmp = right;
4687 if (AOP_TYPE (right) == AOP_LIT)
4688 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4690 size = AOP_SIZE (result);
4693 // result = bit & yy;
4694 if (AOP_TYPE (left) == AOP_CRY)
4696 // c = bit & literal;
4697 if (AOP_TYPE (right) == AOP_LIT)
4701 if (size && sameRegs (AOP (result), AOP (left)))
4704 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4709 if (size && (AOP_TYPE (result) == AOP_CRY))
4711 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4714 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4719 emitcode ("clr", "c");
4724 if (AOP_TYPE (right) == AOP_CRY)
4727 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4728 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4733 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4735 emitcode ("rrc", "a");
4736 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4744 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4745 genIfxJump (ifx, "c");
4749 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4750 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4751 if ((AOP_TYPE (right) == AOP_LIT) &&
4752 (AOP_TYPE (result) == AOP_CRY) &&
4753 (AOP_TYPE (left) != AOP_CRY))
4755 int posbit = isLiteralBit (lit);
4760 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4763 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4769 sprintf (buffer, "acc.%d", posbit & 0x07);
4770 genIfxJump (ifx, buffer);
4777 symbol *tlbl = newiTempLabel (NULL);
4778 int sizel = AOP_SIZE (left);
4780 emitcode ("setb", "c");
4783 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4785 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4787 if ((posbit = isLiteralBit (bytelit)) != 0)
4788 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4791 if (bytelit != 0x0FFL)
4792 emitcode ("anl", "a,%s",
4793 aopGet (AOP (right), offset, FALSE, TRUE));
4794 emitcode ("jnz", "%05d$", tlbl->key + 100);
4799 // bit = left & literal
4802 emitcode ("clr", "c");
4803 emitcode ("", "%05d$:", tlbl->key + 100);
4805 // if(left & literal)
4809 jmpTrueOrFalse (ifx, tlbl);
4817 /* if left is same as result */
4818 if (sameRegs (AOP (result), AOP (left)))
4820 for (; size--; offset++)
4822 if (AOP_TYPE (right) == AOP_LIT)
4824 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4826 else if (bytelit == 0)
4827 aopPut (AOP (result), zero, offset);
4828 else if (IS_AOP_PREG (result))
4830 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4831 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4832 aopPut (AOP (result), "a", offset);
4835 emitcode ("anl", "%s,%s",
4836 aopGet (AOP (left), offset, FALSE, TRUE),
4837 aopGet (AOP (right), offset, FALSE, FALSE));
4841 if (AOP_TYPE (left) == AOP_ACC)
4842 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4845 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4846 if (IS_AOP_PREG (result))
4848 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4849 aopPut (AOP (result), "a", offset);
4853 emitcode ("anl", "%s,a",
4854 aopGet (AOP (left), offset, FALSE, TRUE));
4861 // left & result in different registers
4862 if (AOP_TYPE (result) == AOP_CRY)
4865 // if(size), result in bit
4866 // if(!size && ifx), conditional oper: if(left & right)
4867 symbol *tlbl = newiTempLabel (NULL);
4868 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4870 emitcode ("setb", "c");
4873 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4874 emitcode ("anl", "a,%s",
4875 aopGet (AOP (right), offset, FALSE, FALSE));
4877 if (AOP_TYPE(left)==AOP_ACC) {
4878 emitcode("mov", "b,a");
4879 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4880 emitcode("anl", "a,b");
4882 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4883 emitcode ("anl", "a,%s",
4884 aopGet (AOP (left), offset, FALSE, FALSE));
4887 emitcode ("jnz", "%05d$", tlbl->key + 100);
4893 emitcode ("", "%05d$:", tlbl->key + 100);
4897 jmpTrueOrFalse (ifx, tlbl);
4901 for (; (size--); offset++)
4904 // result = left & right
4905 if (AOP_TYPE (right) == AOP_LIT)
4907 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4909 aopPut (AOP (result),
4910 aopGet (AOP (left), offset, FALSE, FALSE),
4914 else if (bytelit == 0)
4916 aopPut (AOP (result), zero, offset);
4920 // faster than result <- left, anl result,right
4921 // and better if result is SFR
4922 if (AOP_TYPE (left) == AOP_ACC)
4923 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4926 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4927 emitcode ("anl", "a,%s",
4928 aopGet (AOP (left), offset, FALSE, FALSE));
4930 aopPut (AOP (result), "a", offset);
4936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 freeAsmop (result, NULL, ic, TRUE);
4941 /*-----------------------------------------------------------------*/
4942 /* genOr - code for or */
4943 /*-----------------------------------------------------------------*/
4945 genOr (iCode * ic, iCode * ifx)
4947 operand *left, *right, *result;
4948 int size, offset = 0;
4949 unsigned long lit = 0L;
4951 D(emitcode ("; genOr",""));
4953 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4954 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4955 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4958 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4960 AOP_TYPE (left), AOP_TYPE (right));
4961 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4963 AOP_SIZE (left), AOP_SIZE (right));
4966 /* if left is a literal & right is not then exchange them */
4967 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4968 AOP_NEEDSACC (left))
4970 operand *tmp = right;
4975 /* if result = right then exchange them */
4976 if (sameRegs (AOP (result), AOP (right)))
4978 operand *tmp = right;
4983 /* if right is bit then exchange them */
4984 if (AOP_TYPE (right) == AOP_CRY &&
4985 AOP_TYPE (left) != AOP_CRY)
4987 operand *tmp = right;
4991 if (AOP_TYPE (right) == AOP_LIT)
4992 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4994 size = AOP_SIZE (result);
4998 if (AOP_TYPE (left) == AOP_CRY)
5000 if (AOP_TYPE (right) == AOP_LIT)
5002 // c = bit | literal;
5005 // lit != 0 => result = 1
5006 if (AOP_TYPE (result) == AOP_CRY)
5009 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5011 continueIfTrue (ifx);
5014 emitcode ("setb", "c");
5018 // lit == 0 => result = left
5019 if (size && sameRegs (AOP (result), AOP (left)))
5021 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5026 if (AOP_TYPE (right) == AOP_CRY)
5029 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5030 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5035 symbol *tlbl = newiTempLabel (NULL);
5036 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5037 emitcode ("setb", "c");
5038 emitcode ("jb", "%s,%05d$",
5039 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5041 emitcode ("jnz", "%05d$", tlbl->key + 100);
5042 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5044 jmpTrueOrFalse (ifx, tlbl);
5050 emitcode ("", "%05d$:", tlbl->key + 100);
5059 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5060 genIfxJump (ifx, "c");
5064 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5065 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5066 if ((AOP_TYPE (right) == AOP_LIT) &&
5067 (AOP_TYPE (result) == AOP_CRY) &&
5068 (AOP_TYPE (left) != AOP_CRY))
5074 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5076 continueIfTrue (ifx);
5081 // lit = 0, result = boolean(left)
5083 emitcode ("setb", "c");
5087 symbol *tlbl = newiTempLabel (NULL);
5088 emitcode ("jnz", "%05d$", tlbl->key + 100);
5090 emitcode ("", "%05d$:", tlbl->key + 100);
5094 genIfxJump (ifx, "a");
5102 /* if left is same as result */
5103 if (sameRegs (AOP (result), AOP (left)))
5105 for (; size--; offset++)
5107 if (AOP_TYPE (right) == AOP_LIT)
5109 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5111 else if (IS_AOP_PREG (left))
5113 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5114 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5115 aopPut (AOP (result), "a", offset);
5118 emitcode ("orl", "%s,%s",
5119 aopGet (AOP (left), offset, FALSE, TRUE),
5120 aopGet (AOP (right), offset, FALSE, FALSE));
5124 if (AOP_TYPE (left) == AOP_ACC)
5125 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5128 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5129 if (IS_AOP_PREG (left))
5131 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5132 aopPut (AOP (result), "a", offset);
5135 emitcode ("orl", "%s,a",
5136 aopGet (AOP (left), offset, FALSE, TRUE));
5143 // left & result in different registers
5144 if (AOP_TYPE (result) == AOP_CRY)
5147 // if(size), result in bit
5148 // if(!size && ifx), conditional oper: if(left | right)
5149 symbol *tlbl = newiTempLabel (NULL);
5150 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5152 emitcode ("setb", "c");
5155 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5156 emitcode ("orl", "a,%s",
5157 aopGet (AOP (right), offset, FALSE, FALSE));
5159 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5160 emitcode ("orl", "a,%s",
5161 aopGet (AOP (left), offset, FALSE, FALSE));
5163 emitcode ("jnz", "%05d$", tlbl->key + 100);
5169 emitcode ("", "%05d$:", tlbl->key + 100);
5173 jmpTrueOrFalse (ifx, tlbl);
5176 for (; (size--); offset++)
5179 // result = left & right
5180 if (AOP_TYPE (right) == AOP_LIT)
5182 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5184 aopPut (AOP (result),
5185 aopGet (AOP (left), offset, FALSE, FALSE),
5190 // faster than result <- left, anl result,right
5191 // and better if result is SFR
5192 if (AOP_TYPE (left) == AOP_ACC)
5193 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5196 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5197 emitcode ("orl", "a,%s",
5198 aopGet (AOP (left), offset, FALSE, FALSE));
5200 aopPut (AOP (result), "a", offset);
5205 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5206 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5207 freeAsmop (result, NULL, ic, TRUE);
5210 /*-----------------------------------------------------------------*/
5211 /* genXor - code for xclusive or */
5212 /*-----------------------------------------------------------------*/
5214 genXor (iCode * ic, iCode * ifx)
5216 operand *left, *right, *result;
5217 int size, offset = 0;
5218 unsigned long lit = 0L;
5220 D(emitcode ("; genXor",""));
5222 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5223 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5224 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5227 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5229 AOP_TYPE (left), AOP_TYPE (right));
5230 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5232 AOP_SIZE (left), AOP_SIZE (right));
5235 /* if left is a literal & right is not ||
5236 if left needs acc & right does not */
5237 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5238 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5240 operand *tmp = right;
5245 /* if result = right then exchange them */
5246 if (sameRegs (AOP (result), AOP (right)))
5248 operand *tmp = right;
5253 /* if right is bit then exchange them */
5254 if (AOP_TYPE (right) == AOP_CRY &&
5255 AOP_TYPE (left) != AOP_CRY)
5257 operand *tmp = right;
5261 if (AOP_TYPE (right) == AOP_LIT)
5262 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5264 size = AOP_SIZE (result);
5268 if (AOP_TYPE (left) == AOP_CRY)
5270 if (AOP_TYPE (right) == AOP_LIT)
5272 // c = bit & literal;
5275 // lit>>1 != 0 => result = 1
5276 if (AOP_TYPE (result) == AOP_CRY)
5279 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5281 continueIfTrue (ifx);
5284 emitcode ("setb", "c");
5291 // lit == 0, result = left
5292 if (size && sameRegs (AOP (result), AOP (left)))
5294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5298 // lit == 1, result = not(left)
5299 if (size && sameRegs (AOP (result), AOP (left)))
5301 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5306 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5307 emitcode ("cpl", "c");
5316 symbol *tlbl = newiTempLabel (NULL);
5317 if (AOP_TYPE (right) == AOP_CRY)
5320 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5324 int sizer = AOP_SIZE (right);
5326 // if val>>1 != 0, result = 1
5327 emitcode ("setb", "c");
5330 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5332 // test the msb of the lsb
5333 emitcode ("anl", "a,#0xfe");
5334 emitcode ("jnz", "%05d$", tlbl->key + 100);
5338 emitcode ("rrc", "a");
5340 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5341 emitcode ("cpl", "c");
5342 emitcode ("", "%05d$:", (tlbl->key + 100));
5349 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5350 genIfxJump (ifx, "c");
5354 if (sameRegs (AOP (result), AOP (left)))
5356 /* if left is same as result */
5357 for (; size--; offset++)
5359 if (AOP_TYPE (right) == AOP_LIT)
5361 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5363 else if (IS_AOP_PREG (left))
5365 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5366 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5367 aopPut (AOP (result), "a", offset);
5370 emitcode ("xrl", "%s,%s",
5371 aopGet (AOP (left), offset, FALSE, TRUE),
5372 aopGet (AOP (right), offset, FALSE, FALSE));
5376 if (AOP_TYPE (left) == AOP_ACC)
5377 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5380 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5381 if (IS_AOP_PREG (left))
5383 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5384 aopPut (AOP (result), "a", offset);
5387 emitcode ("xrl", "%s,a",
5388 aopGet (AOP (left), offset, FALSE, TRUE));
5395 // left & result in different registers
5396 if (AOP_TYPE (result) == AOP_CRY)
5399 // if(size), result in bit
5400 // if(!size && ifx), conditional oper: if(left ^ right)
5401 symbol *tlbl = newiTempLabel (NULL);
5402 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5404 emitcode ("setb", "c");
5407 if ((AOP_TYPE (right) == AOP_LIT) &&
5408 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5410 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5414 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5415 emitcode ("xrl", "a,%s",
5416 aopGet (AOP (right), offset, FALSE, FALSE));
5418 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5419 emitcode ("xrl", "a,%s",
5420 aopGet (AOP (left), offset, FALSE, FALSE));
5423 emitcode ("jnz", "%05d$", tlbl->key + 100);
5429 emitcode ("", "%05d$:", tlbl->key + 100);
5433 jmpTrueOrFalse (ifx, tlbl);
5436 for (; (size--); offset++)
5439 // result = left & right
5440 if (AOP_TYPE (right) == AOP_LIT)
5442 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5444 aopPut (AOP (result),
5445 aopGet (AOP (left), offset, FALSE, FALSE),
5450 // faster than result <- left, anl result,right
5451 // and better if result is SFR
5452 if (AOP_TYPE (left) == AOP_ACC)
5453 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5456 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5457 emitcode ("xrl", "a,%s",
5458 aopGet (AOP (left), offset, FALSE, TRUE));
5460 aopPut (AOP (result), "a", offset);
5465 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5466 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5467 freeAsmop (result, NULL, ic, TRUE);
5470 /*-----------------------------------------------------------------*/
5471 /* genInline - write the inline code out */
5472 /*-----------------------------------------------------------------*/
5474 genInline (iCode * ic)
5476 char *buffer, *bp, *bp1;
5478 D(emitcode ("; genInline",""));
5480 _G.inLine += (!options.asmpeep);
5482 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5483 strcpy (buffer, IC_INLINE (ic));
5485 /* emit each line as a code */
5510 /* emitcode("",buffer); */
5511 _G.inLine -= (!options.asmpeep);
5514 /*-----------------------------------------------------------------*/
5515 /* genRRC - rotate right with carry */
5516 /*-----------------------------------------------------------------*/
5520 operand *left, *result;
5521 int size, offset = 0;
5524 D(emitcode ("; genRRC",""));
5526 /* rotate right with carry */
5527 left = IC_LEFT (ic);
5528 result = IC_RESULT (ic);
5529 aopOp (left, ic, FALSE);
5530 aopOp (result, ic, FALSE);
5532 /* move it to the result */
5533 size = AOP_SIZE (result);
5535 if (size == 1) { /* special case for 1 byte */
5536 l = aopGet (AOP (left), offset, FALSE, FALSE);
5538 emitcode ("rr", "a");
5544 l = aopGet (AOP (left), offset, FALSE, FALSE);
5546 emitcode ("rrc", "a");
5547 if (AOP_SIZE (result) > 1)
5548 aopPut (AOP (result), "a", offset--);
5550 /* now we need to put the carry into the
5551 highest order byte of the result */
5552 if (AOP_SIZE (result) > 1)
5554 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5557 emitcode ("mov", "acc.7,c");
5559 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5560 freeAsmop (left, NULL, ic, TRUE);
5561 freeAsmop (result, NULL, ic, TRUE);
5564 /*-----------------------------------------------------------------*/
5565 /* genRLC - generate code for rotate left with carry */
5566 /*-----------------------------------------------------------------*/
5570 operand *left, *result;
5571 int size, offset = 0;
5574 D(emitcode ("; genRLC",""));
5576 /* rotate right with carry */
5577 left = IC_LEFT (ic);
5578 result = IC_RESULT (ic);
5579 aopOp (left, ic, FALSE);
5580 aopOp (result, ic, FALSE);
5582 /* move it to the result */
5583 size = AOP_SIZE (result);
5587 l = aopGet (AOP (left), offset, FALSE, FALSE);
5589 if (size == 0) { /* special case for 1 byte */
5593 emitcode ("add", "a,acc");
5594 if (AOP_SIZE (result) > 1)
5595 aopPut (AOP (result), "a", offset++);
5598 l = aopGet (AOP (left), offset, FALSE, FALSE);
5600 emitcode ("rlc", "a");
5601 if (AOP_SIZE (result) > 1)
5602 aopPut (AOP (result), "a", offset++);
5605 /* now we need to put the carry into the
5606 highest order byte of the result */
5607 if (AOP_SIZE (result) > 1)
5609 l = aopGet (AOP (result), 0, FALSE, FALSE);
5612 emitcode ("mov", "acc.0,c");
5614 aopPut (AOP (result), "a", 0);
5615 freeAsmop (left, NULL, ic, TRUE);
5616 freeAsmop (result, NULL, ic, TRUE);
5619 /*-----------------------------------------------------------------*/
5620 /* genGetHbit - generates code get highest order bit */
5621 /*-----------------------------------------------------------------*/
5623 genGetHbit (iCode * ic)
5625 operand *left, *result;
5627 D(emitcode ("; genGetHbit",""));
5629 left = IC_LEFT (ic);
5630 result = IC_RESULT (ic);
5631 aopOp (left, ic, FALSE);
5632 aopOp (result, ic, FALSE);
5634 /* get the highest order byte into a */
5635 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5636 if (AOP_TYPE (result) == AOP_CRY)
5638 emitcode ("rlc", "a");
5643 emitcode ("rl", "a");
5644 emitcode ("anl", "a,#0x01");
5649 freeAsmop (left, NULL, ic, TRUE);
5650 freeAsmop (result, NULL, ic, TRUE);
5653 /*-----------------------------------------------------------------*/
5654 /* AccRol - rotate left accumulator by known count */
5655 /*-----------------------------------------------------------------*/
5657 AccRol (int shCount)
5659 shCount &= 0x0007; // shCount : 0..7
5666 emitcode ("rl", "a");
5669 emitcode ("rl", "a");
5670 emitcode ("rl", "a");
5673 emitcode ("swap", "a");
5674 emitcode ("rr", "a");
5677 emitcode ("swap", "a");
5680 emitcode ("swap", "a");
5681 emitcode ("rl", "a");
5684 emitcode ("rr", "a");
5685 emitcode ("rr", "a");
5688 emitcode ("rr", "a");
5693 /*-----------------------------------------------------------------*/
5694 /* AccLsh - left shift accumulator by known count */
5695 /*-----------------------------------------------------------------*/
5697 AccLsh (int shCount)
5702 emitcode ("add", "a,acc");
5703 else if (shCount == 2)
5705 emitcode ("add", "a,acc");
5706 emitcode ("add", "a,acc");
5710 /* rotate left accumulator */
5712 /* and kill the lower order bits */
5713 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5718 /*-----------------------------------------------------------------*/
5719 /* AccRsh - right shift accumulator by known count */
5720 /*-----------------------------------------------------------------*/
5722 AccRsh (int shCount)
5729 emitcode ("rrc", "a");
5733 /* rotate right accumulator */
5734 AccRol (8 - shCount);
5735 /* and kill the higher order bits */
5736 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5741 /*-----------------------------------------------------------------*/
5742 /* AccSRsh - signed right shift accumulator by known count */
5743 /*-----------------------------------------------------------------*/
5745 AccSRsh (int shCount)
5752 emitcode ("mov", "c,acc.7");
5753 emitcode ("rrc", "a");
5755 else if (shCount == 2)
5757 emitcode ("mov", "c,acc.7");
5758 emitcode ("rrc", "a");
5759 emitcode ("mov", "c,acc.7");
5760 emitcode ("rrc", "a");
5764 tlbl = newiTempLabel (NULL);
5765 /* rotate right accumulator */
5766 AccRol (8 - shCount);
5767 /* and kill the higher order bits */
5768 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5769 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5770 emitcode ("orl", "a,#0x%02x",
5771 (unsigned char) ~SRMask[shCount]);
5772 emitcode ("", "%05d$:", tlbl->key + 100);
5777 /*-----------------------------------------------------------------*/
5778 /* shiftR1Left2Result - shift right one byte from left to result */
5779 /*-----------------------------------------------------------------*/
5781 shiftR1Left2Result (operand * left, int offl,
5782 operand * result, int offr,
5783 int shCount, int sign)
5785 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5786 /* shift right accumulator */
5791 aopPut (AOP (result), "a", offr);
5794 /*-----------------------------------------------------------------*/
5795 /* shiftL1Left2Result - shift left one byte from left to result */
5796 /*-----------------------------------------------------------------*/
5798 shiftL1Left2Result (operand * left, int offl,
5799 operand * result, int offr, int shCount)
5802 l = aopGet (AOP (left), offl, FALSE, FALSE);
5804 /* shift left accumulator */
5806 aopPut (AOP (result), "a", offr);
5809 /*-----------------------------------------------------------------*/
5810 /* movLeft2Result - move byte from left to result */
5811 /*-----------------------------------------------------------------*/
5813 movLeft2Result (operand * left, int offl,
5814 operand * result, int offr, int sign)
5817 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5819 l = aopGet (AOP (left), offl, FALSE, FALSE);
5821 if (*l == '@' && (IS_AOP_PREG (result)))
5823 emitcode ("mov", "a,%s", l);
5824 aopPut (AOP (result), "a", offr);
5829 aopPut (AOP (result), l, offr);
5832 /* MSB sign in acc.7 ! */
5833 if (getDataSize (left) == offl + 1)
5835 emitcode ("mov", "a,%s", l);
5836 aopPut (AOP (result), "a", offr);
5843 /*-----------------------------------------------------------------*/
5844 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5845 /*-----------------------------------------------------------------*/
5849 emitcode ("rrc", "a");
5850 emitcode ("xch", "a,%s", x);
5851 emitcode ("rrc", "a");
5852 emitcode ("xch", "a,%s", x);
5855 /*-----------------------------------------------------------------*/
5856 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5857 /*-----------------------------------------------------------------*/
5861 emitcode ("xch", "a,%s", x);
5862 emitcode ("rlc", "a");
5863 emitcode ("xch", "a,%s", x);
5864 emitcode ("rlc", "a");
5867 /*-----------------------------------------------------------------*/
5868 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5869 /*-----------------------------------------------------------------*/
5873 emitcode ("xch", "a,%s", x);
5874 emitcode ("add", "a,acc");
5875 emitcode ("xch", "a,%s", x);
5876 emitcode ("rlc", "a");
5879 /*-----------------------------------------------------------------*/
5880 /* AccAXLsh - left shift a:x by known count (0..7) */
5881 /*-----------------------------------------------------------------*/
5883 AccAXLsh (char *x, int shCount)
5898 case 5: // AAAAABBB:CCCCCDDD
5900 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5902 emitcode ("anl", "a,#0x%02x",
5903 SLMask[shCount]); // BBB00000:CCCCCDDD
5905 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5907 AccRol (shCount); // DDDCCCCC:BBB00000
5909 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5911 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5913 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5915 emitcode ("anl", "a,#0x%02x",
5916 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5918 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5920 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5923 case 6: // AAAAAABB:CCCCCCDD
5924 emitcode ("anl", "a,#0x%02x",
5925 SRMask[shCount]); // 000000BB:CCCCCCDD
5926 emitcode ("mov", "c,acc.0"); // c = B
5927 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5929 AccAXRrl1 (x); // BCCCCCCD:D000000B
5930 AccAXRrl1 (x); // BBCCCCCC:DD000000
5932 emitcode("rrc","a");
5933 emitcode("xch","a,%s", x);
5934 emitcode("rrc","a");
5935 emitcode("mov","c,acc.0"); //<< get correct bit
5936 emitcode("xch","a,%s", x);
5938 emitcode("rrc","a");
5939 emitcode("xch","a,%s", x);
5940 emitcode("rrc","a");
5941 emitcode("xch","a,%s", x);
5944 case 7: // a:x <<= 7
5946 emitcode ("anl", "a,#0x%02x",
5947 SRMask[shCount]); // 0000000B:CCCCCCCD
5949 emitcode ("mov", "c,acc.0"); // c = B
5951 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5953 AccAXRrl1 (x); // BCCCCCCC:D0000000
5961 /*-----------------------------------------------------------------*/
5962 /* AccAXRsh - right shift a:x known count (0..7) */
5963 /*-----------------------------------------------------------------*/
5965 AccAXRsh (char *x, int shCount)
5973 AccAXRrl1 (x); // 0->a:x
5978 AccAXRrl1 (x); // 0->a:x
5981 AccAXRrl1 (x); // 0->a:x
5986 case 5: // AAAAABBB:CCCCCDDD = a:x
5988 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5990 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5992 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5994 emitcode ("anl", "a,#0x%02x",
5995 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5997 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5999 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6001 emitcode ("anl", "a,#0x%02x",
6002 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6004 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6006 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6008 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6011 case 6: // AABBBBBB:CCDDDDDD
6013 emitcode ("mov", "c,acc.7");
6014 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6016 emitcode ("mov", "c,acc.7");
6017 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6019 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6021 emitcode ("anl", "a,#0x%02x",
6022 SRMask[shCount]); // 000000AA:BBBBBBCC
6025 case 7: // ABBBBBBB:CDDDDDDD
6027 emitcode ("mov", "c,acc.7"); // c = A
6029 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6031 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6033 emitcode ("anl", "a,#0x%02x",
6034 SRMask[shCount]); // 0000000A:BBBBBBBC
6042 /*-----------------------------------------------------------------*/
6043 /* AccAXRshS - right shift signed a:x known count (0..7) */
6044 /*-----------------------------------------------------------------*/
6046 AccAXRshS (char *x, int shCount)
6054 emitcode ("mov", "c,acc.7");
6055 AccAXRrl1 (x); // s->a:x
6059 emitcode ("mov", "c,acc.7");
6060 AccAXRrl1 (x); // s->a:x
6062 emitcode ("mov", "c,acc.7");
6063 AccAXRrl1 (x); // s->a:x
6068 case 5: // AAAAABBB:CCCCCDDD = a:x
6070 tlbl = newiTempLabel (NULL);
6071 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6073 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6075 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6077 emitcode ("anl", "a,#0x%02x",
6078 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6080 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6082 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6084 emitcode ("anl", "a,#0x%02x",
6085 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6087 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6089 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6091 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6093 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6094 emitcode ("orl", "a,#0x%02x",
6095 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6097 emitcode ("", "%05d$:", tlbl->key + 100);
6098 break; // SSSSAAAA:BBBCCCCC
6100 case 6: // AABBBBBB:CCDDDDDD
6102 tlbl = newiTempLabel (NULL);
6103 emitcode ("mov", "c,acc.7");
6104 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6106 emitcode ("mov", "c,acc.7");
6107 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6109 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6111 emitcode ("anl", "a,#0x%02x",
6112 SRMask[shCount]); // 000000AA:BBBBBBCC
6114 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6115 emitcode ("orl", "a,#0x%02x",
6116 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6118 emitcode ("", "%05d$:", tlbl->key + 100);
6120 case 7: // ABBBBBBB:CDDDDDDD
6122 tlbl = newiTempLabel (NULL);
6123 emitcode ("mov", "c,acc.7"); // c = A
6125 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6127 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6129 emitcode ("anl", "a,#0x%02x",
6130 SRMask[shCount]); // 0000000A:BBBBBBBC
6132 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6133 emitcode ("orl", "a,#0x%02x",
6134 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6136 emitcode ("", "%05d$:", tlbl->key + 100);
6143 /*-----------------------------------------------------------------*/
6144 /* shiftL2Left2Result - shift left two bytes from left to result */
6145 /*-----------------------------------------------------------------*/
6147 shiftL2Left2Result (operand * left, int offl,
6148 operand * result, int offr, int shCount)
6150 if (sameRegs (AOP (result), AOP (left)) &&
6151 ((offl + MSB16) == offr))
6153 /* don't crash result[offr] */
6154 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6155 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6159 movLeft2Result (left, offl, result, offr, 0);
6160 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6162 /* ax << shCount (x = lsb(result)) */
6163 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6164 aopPut (AOP (result), "a", offr + MSB16);
6168 /*-----------------------------------------------------------------*/
6169 /* shiftR2Left2Result - shift right two bytes from left to result */
6170 /*-----------------------------------------------------------------*/
6172 shiftR2Left2Result (operand * left, int offl,
6173 operand * result, int offr,
6174 int shCount, int sign)
6176 if (sameRegs (AOP (result), AOP (left)) &&
6177 ((offl + MSB16) == offr))
6179 /* don't crash result[offr] */
6180 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6181 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6185 movLeft2Result (left, offl, result, offr, 0);
6186 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6188 /* a:x >> shCount (x = lsb(result)) */
6190 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6192 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6193 if (getDataSize (result) > 1)
6194 aopPut (AOP (result), "a", offr + MSB16);
6197 /*-----------------------------------------------------------------*/
6198 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6199 /*-----------------------------------------------------------------*/
6201 shiftLLeftOrResult (operand * left, int offl,
6202 operand * result, int offr, int shCount)
6204 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6205 /* shift left accumulator */
6207 /* or with result */
6208 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6209 /* back to result */
6210 aopPut (AOP (result), "a", offr);
6213 /*-----------------------------------------------------------------*/
6214 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6215 /*-----------------------------------------------------------------*/
6217 shiftRLeftOrResult (operand * left, int offl,
6218 operand * result, int offr, int shCount)
6220 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6221 /* shift right accumulator */
6223 /* or with result */
6224 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6225 /* back to result */
6226 aopPut (AOP (result), "a", offr);
6229 /*-----------------------------------------------------------------*/
6230 /* genlshOne - left shift a one byte quantity by known count */
6231 /*-----------------------------------------------------------------*/
6233 genlshOne (operand * result, operand * left, int shCount)
6235 D(emitcode ("; genlshOne",""));
6237 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6240 /*-----------------------------------------------------------------*/
6241 /* genlshTwo - left shift two bytes by known amount != 0 */
6242 /*-----------------------------------------------------------------*/
6244 genlshTwo (operand * result, operand * left, int shCount)
6248 D(emitcode ("; genlshTwo",""));
6250 size = getDataSize (result);
6252 /* if shCount >= 8 */
6260 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6262 movLeft2Result (left, LSB, result, MSB16, 0);
6264 aopPut (AOP (result), zero, LSB);
6267 /* 1 <= shCount <= 7 */
6271 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6273 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6277 /*-----------------------------------------------------------------*/
6278 /* shiftLLong - shift left one long from left to result */
6279 /* offl = LSB or MSB16 */
6280 /*-----------------------------------------------------------------*/
6282 shiftLLong (operand * left, operand * result, int offr)
6285 int size = AOP_SIZE (result);
6287 if (size >= LSB + offr)
6289 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6291 emitcode ("add", "a,acc");
6292 if (sameRegs (AOP (left), AOP (result)) &&
6293 size >= MSB16 + offr && offr != LSB)
6294 emitcode ("xch", "a,%s",
6295 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6297 aopPut (AOP (result), "a", LSB + offr);
6300 if (size >= MSB16 + offr)
6302 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6304 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6307 emitcode ("rlc", "a");
6308 if (sameRegs (AOP (left), AOP (result)) &&
6309 size >= MSB24 + offr && offr != LSB)
6310 emitcode ("xch", "a,%s",
6311 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6313 aopPut (AOP (result), "a", MSB16 + offr);
6316 if (size >= MSB24 + offr)
6318 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6320 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6323 emitcode ("rlc", "a");
6324 if (sameRegs (AOP (left), AOP (result)) &&
6325 size >= MSB32 + offr && offr != LSB)
6326 emitcode ("xch", "a,%s",
6327 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6329 aopPut (AOP (result), "a", MSB24 + offr);
6332 if (size > MSB32 + offr)
6334 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6336 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6339 emitcode ("rlc", "a");
6340 aopPut (AOP (result), "a", MSB32 + offr);
6343 aopPut (AOP (result), zero, LSB);
6346 /*-----------------------------------------------------------------*/
6347 /* genlshFour - shift four byte by a known amount != 0 */
6348 /*-----------------------------------------------------------------*/
6350 genlshFour (operand * result, operand * left, int shCount)
6354 D(emitcode ("; genlshFour",""));
6356 size = AOP_SIZE (result);
6358 /* if shifting more that 3 bytes */
6363 /* lowest order of left goes to the highest
6364 order of the destination */
6365 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6367 movLeft2Result (left, LSB, result, MSB32, 0);
6368 aopPut (AOP (result), zero, LSB);
6369 aopPut (AOP (result), zero, MSB16);
6370 aopPut (AOP (result), zero, MSB24);
6374 /* more than two bytes */
6375 else if (shCount >= 16)
6377 /* lower order two bytes goes to higher order two bytes */
6379 /* if some more remaining */
6381 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6384 movLeft2Result (left, MSB16, result, MSB32, 0);
6385 movLeft2Result (left, LSB, result, MSB24, 0);
6387 aopPut (AOP (result), zero, MSB16);
6388 aopPut (AOP (result), zero, LSB);
6392 /* if more than 1 byte */
6393 else if (shCount >= 8)
6395 /* lower order three bytes goes to higher order three bytes */
6400 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6402 movLeft2Result (left, LSB, result, MSB16, 0);
6408 movLeft2Result (left, MSB24, result, MSB32, 0);
6409 movLeft2Result (left, MSB16, result, MSB24, 0);
6410 movLeft2Result (left, LSB, result, MSB16, 0);
6411 aopPut (AOP (result), zero, LSB);
6413 else if (shCount == 1)
6414 shiftLLong (left, result, MSB16);
6417 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6418 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6419 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6420 aopPut (AOP (result), zero, LSB);
6425 /* 1 <= shCount <= 7 */
6426 else if (shCount <= 2)
6428 shiftLLong (left, result, LSB);
6430 shiftLLong (result, result, LSB);
6432 /* 3 <= shCount <= 7, optimize */
6435 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6436 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6437 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6441 /*-----------------------------------------------------------------*/
6442 /* genLeftShiftLiteral - left shifting by known count */
6443 /*-----------------------------------------------------------------*/
6445 genLeftShiftLiteral (operand * left,
6450 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6453 D(emitcode ("; genLeftShiftLiteral",""));
6455 freeAsmop (right, NULL, ic, TRUE);
6457 aopOp (left, ic, FALSE);
6458 aopOp (result, ic, FALSE);
6460 size = getSize (operandType (result));
6463 emitcode ("; shift left ", "result %d, left %d", size,
6467 /* I suppose that the left size >= result size */
6472 movLeft2Result (left, size, result, size, 0);
6476 else if (shCount >= (size * 8))
6478 aopPut (AOP (result), zero, size);
6484 genlshOne (result, left, shCount);
6488 genlshTwo (result, left, shCount);
6492 genlshFour (result, left, shCount);
6495 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6496 "*** ack! mystery literal shift!\n");
6500 freeAsmop (left, NULL, ic, TRUE);
6501 freeAsmop (result, NULL, ic, TRUE);
6504 /*-----------------------------------------------------------------*/
6505 /* genLeftShift - generates code for left shifting */
6506 /*-----------------------------------------------------------------*/
6508 genLeftShift (iCode * ic)
6510 operand *left, *right, *result;
6513 symbol *tlbl, *tlbl1;
6515 D(emitcode ("; genLeftShift",""));
6517 right = IC_RIGHT (ic);
6518 left = IC_LEFT (ic);
6519 result = IC_RESULT (ic);
6521 aopOp (right, ic, FALSE);
6523 /* if the shift count is known then do it
6524 as efficiently as possible */
6525 if (AOP_TYPE (right) == AOP_LIT)
6527 genLeftShiftLiteral (left, right, result, ic);
6531 /* shift count is unknown then we have to form
6532 a loop get the loop count in B : Note: we take
6533 only the lower order byte since shifting
6534 more that 32 bits make no sense anyway, ( the
6535 largest size of an object can be only 32 bits ) */
6537 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6538 emitcode ("inc", "b");
6539 freeAsmop (right, NULL, ic, TRUE);
6540 aopOp (left, ic, FALSE);
6541 aopOp (result, ic, FALSE);
6543 /* now move the left to the result if they are not the
6545 if (!sameRegs (AOP (left), AOP (result)) &&
6546 AOP_SIZE (result) > 1)
6549 size = AOP_SIZE (result);
6553 l = aopGet (AOP (left), offset, FALSE, TRUE);
6554 if (*l == '@' && (IS_AOP_PREG (result)))
6557 emitcode ("mov", "a,%s", l);
6558 aopPut (AOP (result), "a", offset);
6561 aopPut (AOP (result), l, offset);
6566 tlbl = newiTempLabel (NULL);
6567 size = AOP_SIZE (result);
6569 tlbl1 = newiTempLabel (NULL);
6571 /* if it is only one byte then */
6574 symbol *tlbl1 = newiTempLabel (NULL);
6576 l = aopGet (AOP (left), 0, FALSE, FALSE);
6578 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6579 emitcode ("", "%05d$:", tlbl->key + 100);
6580 emitcode ("add", "a,acc");
6581 emitcode ("", "%05d$:", tlbl1->key + 100);
6582 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6583 aopPut (AOP (result), "a", 0);
6587 reAdjustPreg (AOP (result));
6589 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6590 emitcode ("", "%05d$:", tlbl->key + 100);
6591 l = aopGet (AOP (result), offset, FALSE, FALSE);
6593 emitcode ("add", "a,acc");
6594 aopPut (AOP (result), "a", offset++);
6597 l = aopGet (AOP (result), offset, FALSE, FALSE);
6599 emitcode ("rlc", "a");
6600 aopPut (AOP (result), "a", offset++);
6602 reAdjustPreg (AOP (result));
6604 emitcode ("", "%05d$:", tlbl1->key + 100);
6605 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6607 freeAsmop (left, NULL, ic, TRUE);
6608 freeAsmop (result, NULL, ic, TRUE);
6611 /*-----------------------------------------------------------------*/
6612 /* genrshOne - right shift a one byte quantity by known count */
6613 /*-----------------------------------------------------------------*/
6615 genrshOne (operand * result, operand * left,
6616 int shCount, int sign)
6618 D(emitcode ("; genrshOne",""));
6620 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6623 /*-----------------------------------------------------------------*/
6624 /* genrshTwo - right shift two bytes by known amount != 0 */
6625 /*-----------------------------------------------------------------*/
6627 genrshTwo (operand * result, operand * left,
6628 int shCount, int sign)
6630 D(emitcode ("; genrshTwo",""));
6632 /* if shCount >= 8 */
6637 shiftR1Left2Result (left, MSB16, result, LSB,
6640 movLeft2Result (left, MSB16, result, LSB, sign);
6641 addSign (result, MSB16, sign);
6644 /* 1 <= shCount <= 7 */
6646 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6649 /*-----------------------------------------------------------------*/
6650 /* shiftRLong - shift right one long from left to result */
6651 /* offl = LSB or MSB16 */
6652 /*-----------------------------------------------------------------*/
6654 shiftRLong (operand * left, int offl,
6655 operand * result, int sign)
6657 int isSameRegs=sameRegs(AOP(left),AOP(result));
6659 if (isSameRegs && offl>1) {
6660 // we are in big trouble, but this shouldn't happen
6661 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6664 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6669 emitcode ("rlc", "a");
6670 emitcode ("subb", "a,acc");
6672 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6674 aopPut (AOP (result), "a", MSB32);
6675 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6678 aopPut (AOP(result), zero, MSB32);
6683 emitcode ("clr", "c");
6685 emitcode ("mov", "c,acc.7");
6688 emitcode ("rrc", "a");
6690 if (isSameRegs && offl==MSB16) {
6691 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6693 aopPut (AOP (result), "a", MSB32-offl);
6694 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6697 emitcode ("rrc", "a");
6698 if (isSameRegs && offl==1) {
6699 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6701 aopPut (AOP (result), "a", MSB24-offl);
6702 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6704 emitcode ("rrc", "a");
6705 aopPut (AOP (result), "a", MSB16 - offl);
6709 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6710 emitcode ("rrc", "a");
6711 aopPut (AOP (result), "a", LSB);
6715 /*-----------------------------------------------------------------*/
6716 /* genrshFour - shift four byte by a known amount != 0 */
6717 /*-----------------------------------------------------------------*/
6719 genrshFour (operand * result, operand * left,
6720 int shCount, int sign)
6722 D(emitcode ("; genrshFour",""));
6724 /* if shifting more that 3 bytes */
6729 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6731 movLeft2Result (left, MSB32, result, LSB, sign);
6732 addSign (result, MSB16, sign);
6734 else if (shCount >= 16)
6738 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6741 movLeft2Result (left, MSB24, result, LSB, 0);
6742 movLeft2Result (left, MSB32, result, MSB16, sign);
6744 addSign (result, MSB24, sign);
6746 else if (shCount >= 8)
6750 shiftRLong (left, MSB16, result, sign);
6751 else if (shCount == 0)
6753 movLeft2Result (left, MSB16, result, LSB, 0);
6754 movLeft2Result (left, MSB24, result, MSB16, 0);
6755 movLeft2Result (left, MSB32, result, MSB24, sign);
6756 addSign (result, MSB32, sign);
6760 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6761 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6762 /* the last shift is signed */
6763 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6764 addSign (result, MSB32, sign);
6768 { /* 1 <= shCount <= 7 */
6771 shiftRLong (left, LSB, result, sign);
6773 shiftRLong (result, LSB, result, sign);
6777 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6778 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6779 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6784 /*-----------------------------------------------------------------*/
6785 /* genRightShiftLiteral - right shifting by known count */
6786 /*-----------------------------------------------------------------*/
6788 genRightShiftLiteral (operand * left,
6794 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6797 D(emitcode ("; genRightShiftLiteral",""));
6799 freeAsmop (right, NULL, ic, TRUE);
6801 aopOp (left, ic, FALSE);
6802 aopOp (result, ic, FALSE);
6805 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6809 size = getDataSize (left);
6810 /* test the LEFT size !!! */
6812 /* I suppose that the left size >= result size */
6815 size = getDataSize (result);
6817 movLeft2Result (left, size, result, size, 0);
6820 else if (shCount >= (size * 8))
6823 /* get sign in acc.7 */
6824 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6826 addSign (result, LSB, sign);
6833 genrshOne (result, left, shCount, sign);
6837 genrshTwo (result, left, shCount, sign);
6841 genrshFour (result, left, shCount, sign);
6847 freeAsmop (left, NULL, ic, TRUE);
6848 freeAsmop (result, NULL, ic, TRUE);
6851 /*-----------------------------------------------------------------*/
6852 /* genSignedRightShift - right shift of signed number */
6853 /*-----------------------------------------------------------------*/
6855 genSignedRightShift (iCode * ic)
6857 operand *right, *left, *result;
6860 symbol *tlbl, *tlbl1;
6862 D(emitcode ("; genSignedRightShift",""));
6864 /* we do it the hard way put the shift count in b
6865 and loop thru preserving the sign */
6867 right = IC_RIGHT (ic);
6868 left = IC_LEFT (ic);
6869 result = IC_RESULT (ic);
6871 aopOp (right, ic, FALSE);
6874 if (AOP_TYPE (right) == AOP_LIT)
6876 genRightShiftLiteral (left, right, result, ic, 1);
6879 /* shift count is unknown then we have to form
6880 a loop get the loop count in B : Note: we take
6881 only the lower order byte since shifting
6882 more that 32 bits make no sense anyway, ( the
6883 largest size of an object can be only 32 bits ) */
6885 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6886 emitcode ("inc", "b");
6887 freeAsmop (right, NULL, ic, TRUE);
6888 aopOp (left, ic, FALSE);
6889 aopOp (result, ic, FALSE);
6891 /* now move the left to the result if they are not the
6893 if (!sameRegs (AOP (left), AOP (result)) &&
6894 AOP_SIZE (result) > 1)
6897 size = AOP_SIZE (result);
6901 l = aopGet (AOP (left), offset, FALSE, TRUE);
6902 if (*l == '@' && IS_AOP_PREG (result))
6905 emitcode ("mov", "a,%s", l);
6906 aopPut (AOP (result), "a", offset);
6909 aopPut (AOP (result), l, offset);
6914 /* mov the highest order bit to OVR */
6915 tlbl = newiTempLabel (NULL);
6916 tlbl1 = newiTempLabel (NULL);
6918 size = AOP_SIZE (result);
6920 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6921 emitcode ("rlc", "a");
6922 emitcode ("mov", "ov,c");
6923 /* if it is only one byte then */
6926 l = aopGet (AOP (left), 0, FALSE, FALSE);
6928 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6929 emitcode ("", "%05d$:", tlbl->key + 100);
6930 emitcode ("mov", "c,ov");
6931 emitcode ("rrc", "a");
6932 emitcode ("", "%05d$:", tlbl1->key + 100);
6933 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6934 aopPut (AOP (result), "a", 0);
6938 reAdjustPreg (AOP (result));
6939 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6940 emitcode ("", "%05d$:", tlbl->key + 100);
6941 emitcode ("mov", "c,ov");
6944 l = aopGet (AOP (result), offset, FALSE, FALSE);
6946 emitcode ("rrc", "a");
6947 aopPut (AOP (result), "a", offset--);
6949 reAdjustPreg (AOP (result));
6950 emitcode ("", "%05d$:", tlbl1->key + 100);
6951 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6954 freeAsmop (left, NULL, ic, TRUE);
6955 freeAsmop (result, NULL, ic, TRUE);
6958 /*-----------------------------------------------------------------*/
6959 /* genRightShift - generate code for right shifting */
6960 /*-----------------------------------------------------------------*/
6962 genRightShift (iCode * ic)
6964 operand *right, *left, *result;
6968 symbol *tlbl, *tlbl1;
6970 D(emitcode ("; genRightShift",""));
6972 /* if signed then we do it the hard way preserve the
6973 sign bit moving it inwards */
6974 retype = getSpec (operandType (IC_RESULT (ic)));
6976 if (!SPEC_USIGN (retype))
6978 genSignedRightShift (ic);
6982 /* signed & unsigned types are treated the same : i.e. the
6983 signed is NOT propagated inwards : quoting from the
6984 ANSI - standard : "for E1 >> E2, is equivalent to division
6985 by 2**E2 if unsigned or if it has a non-negative value,
6986 otherwise the result is implementation defined ", MY definition
6987 is that the sign does not get propagated */
6989 right = IC_RIGHT (ic);
6990 left = IC_LEFT (ic);
6991 result = IC_RESULT (ic);
6993 aopOp (right, ic, FALSE);
6995 /* if the shift count is known then do it
6996 as efficiently as possible */
6997 if (AOP_TYPE (right) == AOP_LIT)
6999 genRightShiftLiteral (left, right, result, ic, 0);
7003 /* shift count is unknown then we have to form
7004 a loop get the loop count in B : Note: we take
7005 only the lower order byte since shifting
7006 more that 32 bits make no sense anyway, ( the
7007 largest size of an object can be only 32 bits ) */
7009 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7010 emitcode ("inc", "b");
7011 freeAsmop (right, NULL, ic, TRUE);
7012 aopOp (left, ic, FALSE);
7013 aopOp (result, ic, FALSE);
7015 /* now move the left to the result if they are not the
7017 if (!sameRegs (AOP (left), AOP (result)) &&
7018 AOP_SIZE (result) > 1)
7021 size = AOP_SIZE (result);
7025 l = aopGet (AOP (left), offset, FALSE, TRUE);
7026 if (*l == '@' && IS_AOP_PREG (result))
7029 emitcode ("mov", "a,%s", l);
7030 aopPut (AOP (result), "a", offset);
7033 aopPut (AOP (result), l, offset);
7038 tlbl = newiTempLabel (NULL);
7039 tlbl1 = newiTempLabel (NULL);
7040 size = AOP_SIZE (result);
7043 /* if it is only one byte then */
7046 l = aopGet (AOP (left), 0, FALSE, FALSE);
7048 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7049 emitcode ("", "%05d$:", tlbl->key + 100);
7051 emitcode ("rrc", "a");
7052 emitcode ("", "%05d$:", tlbl1->key + 100);
7053 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7054 aopPut (AOP (result), "a", 0);
7058 reAdjustPreg (AOP (result));
7059 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7060 emitcode ("", "%05d$:", tlbl->key + 100);
7064 l = aopGet (AOP (result), offset, FALSE, FALSE);
7066 emitcode ("rrc", "a");
7067 aopPut (AOP (result), "a", offset--);
7069 reAdjustPreg (AOP (result));
7071 emitcode ("", "%05d$:", tlbl1->key + 100);
7072 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7075 freeAsmop (left, NULL, ic, TRUE);
7076 freeAsmop (result, NULL, ic, TRUE);
7079 /*-----------------------------------------------------------------*/
7080 /* genUnpackBits - generates code for unpacking bits */
7081 /*-----------------------------------------------------------------*/
7083 genUnpackBits (operand * result, char *rname, int ptype)
7091 D(emitcode ("; genUnpackBits",""));
7093 etype = getSpec (operandType (result));
7094 rsize = getSize (operandType (result));
7095 /* read the first byte */
7101 emitcode ("mov", "a,@%s", rname);
7105 emitcode ("movx", "a,@%s", rname);
7109 emitcode ("movx", "a,@dptr");
7113 emitcode ("clr", "a");
7114 emitcode ("movc", "a,@a+dptr");
7118 emitcode ("lcall", "__gptrget");
7122 rlen = SPEC_BLEN (etype);
7124 /* if we have bitdisplacement then it fits */
7125 /* into this byte completely or if length is */
7126 /* less than a byte */
7127 if ((shCnt = SPEC_BSTR (etype)) ||
7128 (SPEC_BLEN (etype) <= 8))
7131 /* shift right acc */
7134 emitcode ("anl", "a,#0x%02x",
7135 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7136 aopPut (AOP (result), "a", offset++);
7140 /* bit field did not fit in a byte */
7141 aopPut (AOP (result), "a", offset++);
7150 emitcode ("inc", "%s", rname);
7151 emitcode ("mov", "a,@%s", rname);
7155 emitcode ("inc", "%s", rname);
7156 emitcode ("movx", "a,@%s", rname);
7160 emitcode ("inc", "dptr");
7161 emitcode ("movx", "a,@dptr");
7165 emitcode ("clr", "a");
7166 emitcode ("inc", "dptr");
7167 emitcode ("movc", "a,@a+dptr");
7171 emitcode ("inc", "dptr");
7172 emitcode ("lcall", "__gptrget");
7177 /* if we are done */
7181 aopPut (AOP (result), "a", offset++);
7187 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7189 aopPut (AOP (result), "a", offset++);
7197 aopPut (AOP (result), zero, offset++);
7203 /*-----------------------------------------------------------------*/
7204 /* genDataPointerGet - generates code when ptr offset is known */
7205 /*-----------------------------------------------------------------*/
7207 genDataPointerGet (operand * left,
7213 int size, offset = 0;
7215 D(emitcode ("; genDataPointerGet",""));
7217 aopOp (result, ic, TRUE);
7219 /* get the string representation of the name */
7220 l = aopGet (AOP (left), 0, FALSE, TRUE);
7221 size = AOP_SIZE (result);
7225 sprintf (buffer, "(%s + %d)", l + 1, offset);
7227 sprintf (buffer, "%s", l + 1);
7228 aopPut (AOP (result), buffer, offset++);
7231 freeAsmop (left, NULL, ic, TRUE);
7232 freeAsmop (result, NULL, ic, TRUE);
7235 /*-----------------------------------------------------------------*/
7236 /* genNearPointerGet - emitcode for near pointer fetch */
7237 /*-----------------------------------------------------------------*/
7239 genNearPointerGet (operand * left,
7247 sym_link *rtype, *retype;
7248 sym_link *ltype = operandType (left);
7251 D(emitcode ("; genNearPointerGet",""));
7253 rtype = operandType (result);
7254 retype = getSpec (rtype);
7256 aopOp (left, ic, FALSE);
7258 /* if left is rematerialisable and
7259 result is not bit variable type and
7260 the left is pointer to data space i.e
7261 lower 128 bytes of space */
7262 if (AOP_TYPE (left) == AOP_IMMD &&
7263 !IS_BITVAR (retype) &&
7264 DCL_TYPE (ltype) == POINTER)
7266 genDataPointerGet (left, result, ic);
7270 /* if the value is already in a pointer register
7271 then don't need anything more */
7272 if (!AOP_INPREG (AOP (left)))
7274 /* otherwise get a free pointer register */
7276 preg = getFreePtr (ic, &aop, FALSE);
7277 emitcode ("mov", "%s,%s",
7279 aopGet (AOP (left), 0, FALSE, TRUE));
7283 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7285 //aopOp (result, ic, FALSE);
7286 aopOp (result, ic, result?TRUE:FALSE);
7288 /* if bitfield then unpack the bits */
7289 if (IS_BITVAR (retype))
7290 genUnpackBits (result, rname, POINTER);
7293 /* we have can just get the values */
7294 int size = AOP_SIZE (result);
7299 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7302 emitcode ("mov", "a,@%s", rname);
7303 aopPut (AOP (result), "a", offset);
7307 sprintf (buffer, "@%s", rname);
7308 aopPut (AOP (result), buffer, offset);
7312 emitcode ("inc", "%s", rname);
7316 /* now some housekeeping stuff */
7317 if (aop) /* we had to allocate for this iCode */
7319 if (pi) { /* post increment present */
7320 aopPut(AOP ( left ),rname,0);
7322 freeAsmop (NULL, aop, ic, TRUE);
7326 /* we did not allocate which means left
7327 already in a pointer register, then
7328 if size > 0 && this could be used again
7329 we have to point it back to where it
7331 if ((AOP_SIZE (result) > 1 &&
7332 !OP_SYMBOL (left)->remat &&
7333 (OP_SYMBOL (left)->liveTo > ic->seq ||
7337 int size = AOP_SIZE (result) - 1;
7339 emitcode ("dec", "%s", rname);
7344 freeAsmop (left, NULL, ic, TRUE);
7345 freeAsmop (result, NULL, ic, TRUE);
7346 if (pi) pi->generated = 1;
7349 /*-----------------------------------------------------------------*/
7350 /* genPagedPointerGet - emitcode for paged pointer fetch */
7351 /*-----------------------------------------------------------------*/
7353 genPagedPointerGet (operand * left,
7361 sym_link *rtype, *retype;
7363 D(emitcode ("; genPagedPointerGet",""));
7365 rtype = operandType (result);
7366 retype = getSpec (rtype);
7368 aopOp (left, ic, FALSE);
7370 /* if the value is already in a pointer register
7371 then don't need anything more */
7372 if (!AOP_INPREG (AOP (left)))
7374 /* otherwise get a free pointer register */
7376 preg = getFreePtr (ic, &aop, FALSE);
7377 emitcode ("mov", "%s,%s",
7379 aopGet (AOP (left), 0, FALSE, TRUE));
7383 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7385 aopOp (result, ic, FALSE);
7387 /* if bitfield then unpack the bits */
7388 if (IS_BITVAR (retype))
7389 genUnpackBits (result, rname, PPOINTER);
7392 /* we have can just get the values */
7393 int size = AOP_SIZE (result);
7399 emitcode ("movx", "a,@%s", rname);
7400 aopPut (AOP (result), "a", offset);
7405 emitcode ("inc", "%s", rname);
7409 /* now some housekeeping stuff */
7410 if (aop) /* we had to allocate for this iCode */
7412 if (pi) aopPut ( AOP (left), rname, 0);
7413 freeAsmop (NULL, aop, ic, TRUE);
7417 /* we did not allocate which means left
7418 already in a pointer register, then
7419 if size > 0 && this could be used again
7420 we have to point it back to where it
7422 if ((AOP_SIZE (result) > 1 &&
7423 !OP_SYMBOL (left)->remat &&
7424 (OP_SYMBOL (left)->liveTo > ic->seq ||
7428 int size = AOP_SIZE (result) - 1;
7430 emitcode ("dec", "%s", rname);
7435 freeAsmop (left, NULL, ic, TRUE);
7436 freeAsmop (result, NULL, ic, TRUE);
7437 if (pi) pi->generated = 1;
7441 /*-----------------------------------------------------------------*/
7442 /* genFarPointerGet - gget value from far space */
7443 /*-----------------------------------------------------------------*/
7445 genFarPointerGet (operand * left,
7446 operand * result, iCode * ic, iCode * pi)
7449 sym_link *retype = getSpec (operandType (result));
7451 D(emitcode ("; genFarPointerGet",""));
7453 aopOp (left, ic, FALSE);
7455 /* if the operand is already in dptr
7456 then we do nothing else we move the value to dptr */
7457 if (AOP_TYPE (left) != AOP_STR)
7459 /* if this is remateriazable */
7460 if (AOP_TYPE (left) == AOP_IMMD)
7461 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7463 { /* we need to get it byte by byte */
7464 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7465 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7468 /* so dptr know contains the address */
7469 aopOp (result, ic, FALSE);
7471 /* if bit then unpack */
7472 if (IS_BITVAR (retype))
7473 genUnpackBits (result, "dptr", FPOINTER);
7476 size = AOP_SIZE (result);
7481 emitcode ("movx", "a,@dptr");
7482 aopPut (AOP (result), "a", offset++);
7484 emitcode ("inc", "dptr");
7488 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7489 aopPut ( AOP (left), "dpl", 0);
7490 aopPut ( AOP (left), "dph", 1);
7493 freeAsmop (left, NULL, ic, TRUE);
7494 freeAsmop (result, NULL, ic, TRUE);
7497 /*-----------------------------------------------------------------*/
7498 /* genCodePointerGet - gget value from code space */
7499 /*-----------------------------------------------------------------*/
7501 genCodePointerGet (operand * left,
7502 operand * result, iCode * ic, iCode *pi)
7505 sym_link *retype = getSpec (operandType (result));
7507 D(emitcode ("; genCodePointerGet",""));
7509 aopOp (left, ic, FALSE);
7511 /* if the operand is already in dptr
7512 then we do nothing else we move the value to dptr */
7513 if (AOP_TYPE (left) != AOP_STR)
7515 /* if this is remateriazable */
7516 if (AOP_TYPE (left) == AOP_IMMD)
7517 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7519 { /* we need to get it byte by byte */
7520 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7521 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7524 /* so dptr know contains the address */
7525 aopOp (result, ic, FALSE);
7527 /* if bit then unpack */
7528 if (IS_BITVAR (retype))
7529 genUnpackBits (result, "dptr", CPOINTER);
7532 size = AOP_SIZE (result);
7539 emitcode ("clr", "a");
7540 emitcode ("movc", "a,@a+dptr");
7541 aopPut (AOP (result), "a", offset++);
7542 emitcode ("inc", "dptr");
7546 emitcode ("mov", "a,#0x%02x", offset);
7547 emitcode ("movc", "a,@a+dptr");
7548 aopPut (AOP (result), "a", offset++);
7553 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7554 aopPut ( AOP (left), "dpl", 0);
7555 aopPut ( AOP (left), "dph", 1);
7558 freeAsmop (left, NULL, ic, TRUE);
7559 freeAsmop (result, NULL, ic, TRUE);
7562 /*-----------------------------------------------------------------*/
7563 /* genGenPointerGet - gget value from generic pointer space */
7564 /*-----------------------------------------------------------------*/
7566 genGenPointerGet (operand * left,
7567 operand * result, iCode * ic, iCode *pi)
7570 sym_link *retype = getSpec (operandType (result));
7572 D(emitcode ("; genGenPointerGet",""));
7574 aopOp (left, ic, FALSE);
7576 /* if the operand is already in dptr
7577 then we do nothing else we move the value to dptr */
7578 if (AOP_TYPE (left) != AOP_STR)
7580 /* if this is remateriazable */
7581 if (AOP_TYPE (left) == AOP_IMMD)
7583 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7584 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7585 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7587 emitcode ("mov", "b,#%d", pointerCode (retype));
7590 { /* we need to get it byte by byte */
7591 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7592 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7593 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7596 /* so dptr know contains the address */
7597 aopOp (result, ic, FALSE);
7599 /* if bit then unpack */
7600 if (IS_BITVAR (retype))
7601 genUnpackBits (result, "dptr", GPOINTER);
7604 size = AOP_SIZE (result);
7609 emitcode ("lcall", "__gptrget");
7610 aopPut (AOP (result), "a", offset++);
7612 emitcode ("inc", "dptr");
7616 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7617 aopPut ( AOP (left), "dpl", 0);
7618 aopPut ( AOP (left), "dph", 1);
7619 aopPut ( AOP (left), "b", 2);
7622 freeAsmop (left, NULL, ic, TRUE);
7623 freeAsmop (result, NULL, ic, TRUE);
7626 /*-----------------------------------------------------------------*/
7627 /* genPointerGet - generate code for pointer get */
7628 /*-----------------------------------------------------------------*/
7630 genPointerGet (iCode * ic, iCode *pi)
7632 operand *left, *result;
7633 sym_link *type, *etype;
7636 D(emitcode ("; genPointerGet",""));
7638 left = IC_LEFT (ic);
7639 result = IC_RESULT (ic);
7641 /* depending on the type of pointer we need to
7642 move it to the correct pointer register */
7643 type = operandType (left);
7644 etype = getSpec (type);
7645 /* if left is of type of pointer then it is simple */
7646 if (IS_PTR (type) && !IS_FUNC (type->next))
7647 p_type = DCL_TYPE (type);
7650 /* we have to go by the storage class */
7651 p_type = PTR_TYPE (SPEC_OCLS (etype));
7654 /* special case when cast remat */
7655 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7656 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7657 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7658 type = operandType (left);
7659 p_type = DCL_TYPE (type);
7661 /* now that we have the pointer type we assign
7662 the pointer values */
7668 genNearPointerGet (left, result, ic, pi);
7672 genPagedPointerGet (left, result, ic, pi);
7676 genFarPointerGet (left, result, ic, pi);
7680 genCodePointerGet (left, result, ic, pi);
7684 genGenPointerGet (left, result, ic, pi);
7690 /*-----------------------------------------------------------------*/
7691 /* genPackBits - generates code for packed bit storage */
7692 /*-----------------------------------------------------------------*/
7694 genPackBits (sym_link * etype,
7696 char *rname, int p_type)
7704 D(emitcode ("; genPackBits",""));
7706 blen = SPEC_BLEN (etype);
7707 bstr = SPEC_BSTR (etype);
7709 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7712 /* if the bit lenth is less than or */
7713 /* it exactly fits a byte then */
7714 if (SPEC_BLEN (etype) <= 8)
7716 shCount = SPEC_BSTR (etype);
7718 /* shift left acc */
7721 if (SPEC_BLEN (etype) < 8)
7722 { /* if smaller than a byte */
7728 emitcode ("mov", "b,a");
7729 emitcode ("mov", "a,@%s", rname);
7733 emitcode ("mov", "b,a");
7734 emitcode ("movx", "a,@dptr");
7738 emitcode ("push", "b");
7739 emitcode ("push", "acc");
7740 emitcode ("lcall", "__gptrget");
7741 emitcode ("pop", "b");
7745 emitcode ("anl", "a,#0x%02x", (unsigned char)
7746 ((unsigned char) (0xFF << (blen + bstr)) |
7747 (unsigned char) (0xFF >> (8 - bstr))));
7748 emitcode ("orl", "a,b");
7749 if (p_type == GPOINTER)
7750 emitcode ("pop", "b");
7757 emitcode ("mov", "@%s,a", rname);
7761 emitcode ("movx", "@dptr,a");
7765 emitcode ("lcall", "__gptrput");
7770 if (SPEC_BLEN (etype) <= 8)
7773 emitcode ("inc", "%s", rname);
7774 rLen = SPEC_BLEN (etype);
7776 /* now generate for lengths greater than one byte */
7780 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7792 emitcode ("mov", "@%s,a", rname);
7795 emitcode ("mov", "@%s,%s", rname, l);
7800 emitcode ("movx", "@dptr,a");
7805 emitcode ("lcall", "__gptrput");
7808 emitcode ("inc", "%s", rname);
7813 /* last last was not complete */
7816 /* save the byte & read byte */
7820 emitcode ("mov", "b,a");
7821 emitcode ("mov", "a,@%s", rname);
7825 emitcode ("mov", "b,a");
7826 emitcode ("movx", "a,@dptr");
7830 emitcode ("push", "b");
7831 emitcode ("push", "acc");
7832 emitcode ("lcall", "__gptrget");
7833 emitcode ("pop", "b");
7837 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7838 emitcode ("orl", "a,b");
7841 if (p_type == GPOINTER)
7842 emitcode ("pop", "b");
7848 emitcode ("mov", "@%s,a", rname);
7852 emitcode ("movx", "@dptr,a");
7856 emitcode ("lcall", "__gptrput");
7860 /*-----------------------------------------------------------------*/
7861 /* genDataPointerSet - remat pointer to data space */
7862 /*-----------------------------------------------------------------*/
7864 genDataPointerSet (operand * right,
7868 int size, offset = 0;
7869 char *l, buffer[256];
7871 D(emitcode ("; genDataPointerSet",""));
7873 aopOp (right, ic, FALSE);
7875 l = aopGet (AOP (result), 0, FALSE, TRUE);
7876 size = AOP_SIZE (right);
7880 sprintf (buffer, "(%s + %d)", l + 1, offset);
7882 sprintf (buffer, "%s", l + 1);
7883 emitcode ("mov", "%s,%s", buffer,
7884 aopGet (AOP (right), offset++, FALSE, FALSE));
7887 freeAsmop (right, NULL, ic, TRUE);
7888 freeAsmop (result, NULL, ic, TRUE);
7891 /*-----------------------------------------------------------------*/
7892 /* genNearPointerSet - emitcode for near pointer put */
7893 /*-----------------------------------------------------------------*/
7895 genNearPointerSet (operand * right,
7903 sym_link *retype, *letype;
7904 sym_link *ptype = operandType (result);
7906 D(emitcode ("; genNearPointerSet",""));
7908 retype = getSpec (operandType (right));
7909 letype = getSpec (ptype);
7910 aopOp (result, ic, FALSE);
7912 /* if the result is rematerializable &
7913 in data space & not a bit variable */
7914 if (AOP_TYPE (result) == AOP_IMMD &&
7915 DCL_TYPE (ptype) == POINTER &&
7916 !IS_BITVAR (retype) &&
7917 !IS_BITVAR (letype))
7919 genDataPointerSet (right, result, ic);
7923 /* if the value is already in a pointer register
7924 then don't need anything more */
7925 if (!AOP_INPREG (AOP (result)))
7928 //AOP_TYPE (result) == AOP_STK
7932 // Aha, it is a pointer, just in disguise.
7933 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7936 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7937 __FILE__, __LINE__);
7942 rname++; // skip the '@'.
7947 /* otherwise get a free pointer register */
7949 preg = getFreePtr (ic, &aop, FALSE);
7950 emitcode ("mov", "%s,%s",
7952 aopGet (AOP (result), 0, FALSE, TRUE));
7958 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7961 aopOp (right, ic, FALSE);
7963 /* if bitfield then unpack the bits */
7964 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7965 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7968 /* we have can just get the values */
7969 int size = AOP_SIZE (right);
7974 l = aopGet (AOP (right), offset, FALSE, TRUE);
7978 emitcode ("mov", "@%s,a", rname);
7981 emitcode ("mov", "@%s,%s", rname, l);
7983 emitcode ("inc", "%s", rname);
7988 /* now some housekeeping stuff */
7989 if (aop) /* we had to allocate for this iCode */
7991 if (pi) aopPut (AOP (result),rname,0);
7992 freeAsmop (NULL, aop, ic, TRUE);
7996 /* we did not allocate which means left
7997 already in a pointer register, then
7998 if size > 0 && this could be used again
7999 we have to point it back to where it
8001 if ((AOP_SIZE (right) > 1 &&
8002 !OP_SYMBOL (result)->remat &&
8003 (OP_SYMBOL (result)->liveTo > ic->seq ||
8007 int size = AOP_SIZE (right) - 1;
8009 emitcode ("dec", "%s", rname);
8014 if (pi) pi->generated = 1;
8015 freeAsmop (result, NULL, ic, TRUE);
8016 freeAsmop (right, NULL, ic, TRUE);
8019 /*-----------------------------------------------------------------*/
8020 /* genPagedPointerSet - emitcode for Paged pointer put */
8021 /*-----------------------------------------------------------------*/
8023 genPagedPointerSet (operand * right,
8031 sym_link *retype, *letype;
8033 D(emitcode ("; genPagedPointerSet",""));
8035 retype = getSpec (operandType (right));
8036 letype = getSpec (operandType (result));
8038 aopOp (result, ic, FALSE);
8040 /* if the value is already in a pointer register
8041 then don't need anything more */
8042 if (!AOP_INPREG (AOP (result)))
8044 /* otherwise get a free pointer register */
8046 preg = getFreePtr (ic, &aop, FALSE);
8047 emitcode ("mov", "%s,%s",
8049 aopGet (AOP (result), 0, FALSE, TRUE));
8053 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8055 aopOp (right, ic, FALSE);
8057 /* if bitfield then unpack the bits */
8058 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8059 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8062 /* we have can just get the values */
8063 int size = AOP_SIZE (right);
8068 l = aopGet (AOP (right), offset, FALSE, TRUE);
8071 emitcode ("movx", "@%s,a", rname);
8074 emitcode ("inc", "%s", rname);
8080 /* now some housekeeping stuff */
8081 if (aop) /* we had to allocate for this iCode */
8083 if (pi) aopPut (AOP (result),rname,0);
8084 freeAsmop (NULL, aop, ic, TRUE);
8088 /* we did not allocate which means left
8089 already in a pointer register, then
8090 if size > 0 && this could be used again
8091 we have to point it back to where it
8093 if (AOP_SIZE (right) > 1 &&
8094 !OP_SYMBOL (result)->remat &&
8095 (OP_SYMBOL (result)->liveTo > ic->seq ||
8098 int size = AOP_SIZE (right) - 1;
8100 emitcode ("dec", "%s", rname);
8105 if (pi) pi->generated = 1;
8106 freeAsmop (result, NULL, ic, TRUE);
8107 freeAsmop (right, NULL, ic, TRUE);
8112 /*-----------------------------------------------------------------*/
8113 /* genFarPointerSet - set value from far space */
8114 /*-----------------------------------------------------------------*/
8116 genFarPointerSet (operand * right,
8117 operand * result, iCode * ic, iCode * pi)
8120 sym_link *retype = getSpec (operandType (right));
8121 sym_link *letype = getSpec (operandType (result));
8123 D(emitcode ("; genFarPointerSet",""));
8125 aopOp (result, ic, FALSE);
8127 /* if the operand is already in dptr
8128 then we do nothing else we move the value to dptr */
8129 if (AOP_TYPE (result) != AOP_STR)
8131 /* if this is remateriazable */
8132 if (AOP_TYPE (result) == AOP_IMMD)
8133 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8135 { /* we need to get it byte by byte */
8136 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8137 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8140 /* so dptr know contains the address */
8141 aopOp (right, ic, FALSE);
8143 /* if bit then unpack */
8144 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8145 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8148 size = AOP_SIZE (right);
8153 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8155 emitcode ("movx", "@dptr,a");
8157 emitcode ("inc", "dptr");
8160 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8161 aopPut (AOP(result),"dpl",0);
8162 aopPut (AOP(result),"dph",1);
8165 freeAsmop (result, NULL, ic, TRUE);
8166 freeAsmop (right, NULL, ic, TRUE);
8169 /*-----------------------------------------------------------------*/
8170 /* genGenPointerSet - set value from generic pointer space */
8171 /*-----------------------------------------------------------------*/
8173 genGenPointerSet (operand * right,
8174 operand * result, iCode * ic, iCode * pi)
8177 sym_link *retype = getSpec (operandType (right));
8178 sym_link *letype = getSpec (operandType (result));
8180 D(emitcode ("; genGenPointerSet",""));
8182 aopOp (result, ic, FALSE);
8184 /* if the operand is already in dptr
8185 then we do nothing else we move the value to dptr */
8186 if (AOP_TYPE (result) != AOP_STR)
8188 /* if this is remateriazable */
8189 if (AOP_TYPE (result) == AOP_IMMD)
8191 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8192 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8193 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8195 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8198 { /* we need to get it byte by byte */
8199 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8200 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8201 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8204 /* so dptr know contains the address */
8205 aopOp (right, ic, FALSE);
8207 /* if bit then unpack */
8208 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8209 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8212 size = AOP_SIZE (right);
8217 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8219 emitcode ("lcall", "__gptrput");
8221 emitcode ("inc", "dptr");
8225 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8226 aopPut (AOP(result),"dpl",0);
8227 aopPut (AOP(result),"dph",1);
8228 aopPut (AOP(result),"b",2);
8231 freeAsmop (result, NULL, ic, TRUE);
8232 freeAsmop (right, NULL, ic, TRUE);
8235 /*-----------------------------------------------------------------*/
8236 /* genPointerSet - stores the value into a pointer location */
8237 /*-----------------------------------------------------------------*/
8239 genPointerSet (iCode * ic, iCode *pi)
8241 operand *right, *result;
8242 sym_link *type, *etype;
8245 D(emitcode ("; genPointerSet",""));
8247 right = IC_RIGHT (ic);
8248 result = IC_RESULT (ic);
8250 /* depending on the type of pointer we need to
8251 move it to the correct pointer register */
8252 type = operandType (result);
8253 etype = getSpec (type);
8254 /* if left is of type of pointer then it is simple */
8255 if (IS_PTR (type) && !IS_FUNC (type->next))
8257 p_type = DCL_TYPE (type);
8261 /* we have to go by the storage class */
8262 p_type = PTR_TYPE (SPEC_OCLS (etype));
8265 /* special case when cast remat */
8266 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8267 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8268 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8269 type = operandType (result);
8270 p_type = DCL_TYPE (type);
8272 /* now that we have the pointer type we assign
8273 the pointer values */
8279 genNearPointerSet (right, result, ic, pi);
8283 genPagedPointerSet (right, result, ic, pi);
8287 genFarPointerSet (right, result, ic, pi);
8291 genGenPointerSet (right, result, ic, pi);
8295 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8296 "genPointerSet: illegal pointer type");
8301 /*-----------------------------------------------------------------*/
8302 /* genIfx - generate code for Ifx statement */
8303 /*-----------------------------------------------------------------*/
8305 genIfx (iCode * ic, iCode * popIc)
8307 operand *cond = IC_COND (ic);
8310 D(emitcode ("; genIfx",""));
8312 aopOp (cond, ic, FALSE);
8314 /* get the value into acc */
8315 if (AOP_TYPE (cond) != AOP_CRY)
8319 /* the result is now in the accumulator */
8320 freeAsmop (cond, NULL, ic, TRUE);
8322 /* if there was something to be popped then do it */
8326 /* if the condition is a bit variable */
8327 if (isbit && IS_ITEMP (cond) &&
8329 genIfxJump (ic, SPIL_LOC (cond)->rname);
8330 else if (isbit && !IS_ITEMP (cond))
8331 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8333 genIfxJump (ic, "a");
8338 /*-----------------------------------------------------------------*/
8339 /* genAddrOf - generates code for address of */
8340 /*-----------------------------------------------------------------*/
8342 genAddrOf (iCode * ic)
8344 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8347 D(emitcode ("; genAddrOf",""));
8349 aopOp (IC_RESULT (ic), ic, FALSE);
8351 /* if the operand is on the stack then we
8352 need to get the stack offset of this
8356 /* if it has an offset then we need to compute
8360 emitcode ("mov", "a,_bp");
8361 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8362 ((char) (sym->stack - _G.nRegsSaved)) :
8363 ((char) sym->stack)) & 0xff);
8364 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8368 /* we can just move _bp */
8369 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8371 /* fill the result with zero */
8372 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8377 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8383 /* object not on stack then we need the name */
8384 size = AOP_SIZE (IC_RESULT (ic));
8389 char s[SDCC_NAME_MAX];
8391 sprintf (s, "#(%s >> %d)",
8395 sprintf (s, "#%s", sym->rname);
8396 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8400 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8404 /*-----------------------------------------------------------------*/
8405 /* genFarFarAssign - assignment when both are in far space */
8406 /*-----------------------------------------------------------------*/
8408 genFarFarAssign (operand * result, operand * right, iCode * ic)
8410 int size = AOP_SIZE (right);
8414 D(emitcode ("; genFarFarAssign",""));
8416 /* first push the right side on to the stack */
8419 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8421 emitcode ("push", "acc");
8424 freeAsmop (right, NULL, ic, FALSE);
8425 /* now assign DPTR to result */
8426 aopOp (result, ic, FALSE);
8427 size = AOP_SIZE (result);
8430 emitcode ("pop", "acc");
8431 aopPut (AOP (result), "a", --offset);
8433 freeAsmop (result, NULL, ic, FALSE);
8437 /*-----------------------------------------------------------------*/
8438 /* genAssign - generate code for assignment */
8439 /*-----------------------------------------------------------------*/
8441 genAssign (iCode * ic)
8443 operand *result, *right;
8445 unsigned long lit = 0L;
8447 D(emitcode("; genAssign",""));
8449 result = IC_RESULT (ic);
8450 right = IC_RIGHT (ic);
8452 /* if they are the same */
8453 if (operandsEqu (result, right)) {
8457 aopOp (right, ic, FALSE);
8459 /* special case both in far space */
8460 if (AOP_TYPE (right) == AOP_DPTR &&
8461 IS_TRUE_SYMOP (result) &&
8462 isOperandInFarSpace (result))
8465 genFarFarAssign (result, right, ic);
8469 aopOp (result, ic, TRUE);
8471 /* if they are the same registers */
8472 if (sameRegs (AOP (right), AOP (result)))
8475 /* if the result is a bit */
8476 if (AOP_TYPE (result) == AOP_CRY)
8479 /* if the right size is a literal then
8480 we know what the value is */
8481 if (AOP_TYPE (right) == AOP_LIT)
8483 if (((int) operandLitValue (right)))
8484 aopPut (AOP (result), one, 0);
8486 aopPut (AOP (result), zero, 0);
8490 /* the right is also a bit variable */
8491 if (AOP_TYPE (right) == AOP_CRY)
8493 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8494 aopPut (AOP (result), "c", 0);
8500 aopPut (AOP (result), "a", 0);
8504 /* bit variables done */
8506 size = AOP_SIZE (result);
8508 if (AOP_TYPE (right) == AOP_LIT)
8509 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8511 (AOP_TYPE (result) != AOP_REG) &&
8512 (AOP_TYPE (right) == AOP_LIT) &&
8513 !IS_FLOAT (operandType (right)) &&
8516 emitcode ("clr", "a");
8519 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8520 aopPut (AOP (result), "a", size);
8522 aopPut (AOP (result),
8523 aopGet (AOP (right), size, FALSE, FALSE),
8531 aopPut (AOP (result),
8532 aopGet (AOP (right), offset, FALSE, FALSE),
8539 freeAsmop (right, NULL, ic, TRUE);
8540 freeAsmop (result, NULL, ic, TRUE);
8543 /*-----------------------------------------------------------------*/
8544 /* genJumpTab - genrates code for jump table */
8545 /*-----------------------------------------------------------------*/
8547 genJumpTab (iCode * ic)
8552 D(emitcode ("; genJumpTab",""));
8554 aopOp (IC_JTCOND (ic), ic, FALSE);
8555 /* get the condition into accumulator */
8556 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8558 /* multiply by three */
8559 emitcode ("add", "a,acc");
8560 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8561 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8563 jtab = newiTempLabel (NULL);
8564 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8565 emitcode ("jmp", "@a+dptr");
8566 emitcode ("", "%05d$:", jtab->key + 100);
8567 /* now generate the jump labels */
8568 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8569 jtab = setNextItem (IC_JTLABELS (ic)))
8570 emitcode ("ljmp", "%05d$", jtab->key + 100);
8574 /*-----------------------------------------------------------------*/
8575 /* genCast - gen code for casting */
8576 /*-----------------------------------------------------------------*/
8578 genCast (iCode * ic)
8580 operand *result = IC_RESULT (ic);
8581 sym_link *ctype = operandType (IC_LEFT (ic));
8582 sym_link *rtype = operandType (IC_RIGHT (ic));
8583 operand *right = IC_RIGHT (ic);
8586 D(emitcode("; genCast",""));
8588 /* if they are equivalent then do nothing */
8589 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8592 aopOp (right, ic, FALSE);
8593 aopOp (result, ic, FALSE);
8595 /* if the result is a bit */
8596 if (IS_BITVAR(OP_SYMBOL(result)->type))
8598 /* if the right size is a literal then
8599 we know what the value is */
8600 if (AOP_TYPE (right) == AOP_LIT)
8602 if (((int) operandLitValue (right)))
8603 aopPut (AOP (result), one, 0);
8605 aopPut (AOP (result), zero, 0);
8610 /* the right is also a bit variable */
8611 if (AOP_TYPE (right) == AOP_CRY)
8613 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8614 aopPut (AOP (result), "c", 0);
8620 aopPut (AOP (result), "a", 0);
8624 /* if they are the same size : or less */
8625 if (AOP_SIZE (result) <= AOP_SIZE (right))
8628 /* if they are in the same place */
8629 if (sameRegs (AOP (right), AOP (result)))
8632 /* if they in different places then copy */
8633 size = AOP_SIZE (result);
8637 aopPut (AOP (result),
8638 aopGet (AOP (right), offset, FALSE, FALSE),
8646 /* if the result is of type pointer */
8651 sym_link *type = operandType (right);
8652 sym_link *etype = getSpec (type);
8654 /* pointer to generic pointer */
8655 if (IS_GENPTR (ctype))
8658 p_type = DCL_TYPE (type);
8661 if (SPEC_SCLS(etype)==S_REGISTER) {
8662 // let's assume it is a generic pointer
8665 /* we have to go by the storage class */
8666 p_type = PTR_TYPE (SPEC_OCLS (etype));
8670 /* the first two bytes are known */
8671 size = GPTRSIZE - 1;
8675 aopPut (AOP (result),
8676 aopGet (AOP (right), offset, FALSE, FALSE),
8680 /* the last byte depending on type */
8682 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8687 // pointerTypeToGPByte will have bitched.
8691 sprintf(gpValStr, "#0x%d", gpVal);
8692 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8697 /* just copy the pointers */
8698 size = AOP_SIZE (result);
8702 aopPut (AOP (result),
8703 aopGet (AOP (right), offset, FALSE, FALSE),
8710 /* so we now know that the size of destination is greater
8711 than the size of the source */
8712 /* we move to result for the size of source */
8713 size = AOP_SIZE (right);
8717 aopPut (AOP (result),
8718 aopGet (AOP (right), offset, FALSE, FALSE),
8723 /* now depending on the sign of the source && destination */
8724 size = AOP_SIZE (result) - AOP_SIZE (right);
8725 /* if unsigned or not an integral type */
8726 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8729 aopPut (AOP (result), zero, offset++);
8733 /* we need to extend the sign :{ */
8734 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8737 emitcode ("rlc", "a");
8738 emitcode ("subb", "a,acc");
8740 aopPut (AOP (result), "a", offset++);
8743 /* we are done hurray !!!! */
8746 freeAsmop (right, NULL, ic, TRUE);
8747 freeAsmop (result, NULL, ic, TRUE);
8751 /*-----------------------------------------------------------------*/
8752 /* genDjnz - generate decrement & jump if not zero instrucion */
8753 /*-----------------------------------------------------------------*/
8755 genDjnz (iCode * ic, iCode * ifx)
8761 D(emitcode ("; genDjnz",""));
8763 /* if the if condition has a false label
8764 then we cannot save */
8768 /* if the minus is not of the form
8770 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8771 !IS_OP_LITERAL (IC_RIGHT (ic)))
8774 if (operandLitValue (IC_RIGHT (ic)) != 1)
8777 /* if the size of this greater than one then no
8779 if (getSize (operandType (IC_RESULT (ic))) > 1)
8782 /* otherwise we can save BIG */
8783 lbl = newiTempLabel (NULL);
8784 lbl1 = newiTempLabel (NULL);
8786 aopOp (IC_RESULT (ic), ic, FALSE);
8788 if (AOP_NEEDSACC(IC_RESULT(ic)))
8790 /* If the result is accessed indirectly via
8791 * the accumulator, we must explicitly write
8792 * it back after the decrement.
8794 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8796 if (strcmp(rByte, "a"))
8798 /* Something is hopelessly wrong */
8799 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8800 __FILE__, __LINE__);
8801 /* We can just give up; the generated code will be inefficient,
8804 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8807 emitcode ("dec", "%s", rByte);
8808 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8809 emitcode ("jnz", "%05d$", lbl->key + 100);
8811 else if (IS_AOP_PREG (IC_RESULT (ic)))
8813 emitcode ("dec", "%s",
8814 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8815 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8816 emitcode ("jnz", "%05d$", lbl->key + 100);
8820 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8823 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8824 emitcode ("", "%05d$:", lbl->key + 100);
8825 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8826 emitcode ("", "%05d$:", lbl1->key + 100);
8828 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8833 /*-----------------------------------------------------------------*/
8834 /* genReceive - generate code for a receive iCode */
8835 /*-----------------------------------------------------------------*/
8837 genReceive (iCode * ic)
8839 int size = getSize (operandType (IC_RESULT (ic)));
8841 D(emitcode ("; genReceive",""));
8843 if (ic->argreg == 1) { /* first parameter */
8844 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8845 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8846 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8848 offset = fReturnSizeMCS51 - size;
8850 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8851 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8854 aopOp (IC_RESULT (ic), ic, FALSE);
8855 size = AOP_SIZE (IC_RESULT (ic));
8858 emitcode ("pop", "acc");
8859 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8864 aopOp (IC_RESULT (ic), ic, FALSE);
8866 assignResultValue (IC_RESULT (ic));
8868 } else { /* second receive onwards */
8870 aopOp (IC_RESULT (ic), ic, FALSE);
8871 rb1off = ic->argreg;
8873 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8876 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8879 /*-----------------------------------------------------------------*/
8880 /* gen51Code - generate code for 8051 based controllers */
8881 /*-----------------------------------------------------------------*/
8883 gen51Code (iCode * lic)
8888 lineHead = lineCurr = NULL;
8890 /* print the allocation information */
8891 if (allocInfo && currFunc)
8892 printAllocInfo (currFunc, codeOutFile);
8893 /* if debug information required */
8894 if (options.debug && currFunc)
8896 debugFile->writeFunction(currFunc);
8898 if (IS_STATIC (currFunc->etype))
8899 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8901 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8904 /* stack pointer name */
8905 if (options.useXstack)
8911 for (ic = lic; ic; ic = ic->next)
8914 if (ic->lineno && cln != ic->lineno)
8919 emitcode ("", "C$%s$%d$%d$%d ==.",
8920 FileBaseName (ic->filename), ic->lineno,
8921 ic->level, ic->block);
8924 if (!options.noCcodeInAsm) {
8925 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8926 printCLine(ic->filename, ic->lineno));
8930 if (options.iCodeInAsm) {
8934 for (i=0; i<8; i++) {
8935 sprintf (®sInUse[i],
8936 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8939 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8941 /* if the result is marked as
8942 spilt and rematerializable or code for
8943 this has already been generated then
8945 if (resultRemat (ic) || ic->generated)
8948 /* depending on the operation */
8968 /* IPOP happens only when trying to restore a
8969 spilt live range, if there is an ifx statement
8970 following this pop then the if statement might
8971 be using some of the registers being popped which
8972 would destory the contents of the register so
8973 we need to check for this condition and handle it */
8975 ic->next->op == IFX &&
8976 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8977 genIfx (ic->next, ic);
8995 genEndFunction (ic);
9015 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9032 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9036 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9043 /* note these two are xlated by algebraic equivalence
9044 during parsing SDCC.y */
9045 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9046 "got '>=' or '<=' shouldn't have come here");
9050 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9062 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9066 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9070 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9097 case GET_VALUE_AT_ADDRESS:
9098 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9102 if (POINTER_SET (ic))
9103 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9129 addSet (&_G.sendSet, ic);
9138 /* now we are ready to call the
9139 peep hole optimizer */
9140 if (!options.nopeep)
9141 peepHole (&lineHead);
9143 /* now do the actual printing */
9144 printLine (lineHead, codeOutFile);