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 regsCmp(void *p1, void *p2)
2225 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2229 inExcludeList (char *s)
2231 const char *p = setFirstItem(options.excludeRegsSet);
2233 if (p == NULL || STRCASECMP(p, "none") == 0)
2237 return isinSetWith(options.excludeRegsSet, s, regsCmp);
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 &&
4196 AOP_TYPE (left) != AOP_IMMD)
4200 emitcode ("cjne", "%s,%s,%05d$",
4201 aopGet (AOP (left), offset, FALSE, FALSE),
4202 aopGet (AOP (right), offset, FALSE, FALSE),
4208 /* if the right side is in a register or in direct space or
4209 if the left is a pointer register & right is not */
4210 else if (AOP_TYPE (right) == AOP_REG ||
4211 AOP_TYPE (right) == AOP_DIR ||
4212 AOP_TYPE (right) == AOP_LIT ||
4213 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4214 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4218 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4219 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4220 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4221 emitcode ("jnz", "%05d$", lbl->key + 100);
4223 emitcode ("cjne", "a,%s,%05d$",
4224 aopGet (AOP (right), offset, FALSE, TRUE),
4231 /* right is a pointer reg need both a & b */
4234 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4235 if (strcmp (l, "b"))
4236 emitcode ("mov", "b,%s", l);
4237 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4238 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4244 /*-----------------------------------------------------------------*/
4245 /* gencjne - compare and jump if not equal */
4246 /*-----------------------------------------------------------------*/
4248 gencjne (operand * left, operand * right, symbol * lbl)
4250 symbol *tlbl = newiTempLabel (NULL);
4252 gencjneshort (left, right, lbl);
4254 emitcode ("mov", "a,%s", one);
4255 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4256 emitcode ("", "%05d$:", lbl->key + 100);
4257 emitcode ("clr", "a");
4258 emitcode ("", "%05d$:", tlbl->key + 100);
4261 /*-----------------------------------------------------------------*/
4262 /* genCmpEq - generates code for equal to */
4263 /*-----------------------------------------------------------------*/
4265 genCmpEq (iCode * ic, iCode * ifx)
4267 operand *left, *right, *result;
4269 D(emitcode ("; genCmpEq",""));
4271 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4272 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4273 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4275 /* if literal, literal on the right or
4276 if the right is in a pointer register and left
4278 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4279 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4281 operand *t = IC_RIGHT (ic);
4282 IC_RIGHT (ic) = IC_LEFT (ic);
4286 if (ifx && !AOP_SIZE (result))
4289 /* if they are both bit variables */
4290 if (AOP_TYPE (left) == AOP_CRY &&
4291 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4293 if (AOP_TYPE (right) == AOP_LIT)
4295 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4298 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4299 emitcode ("cpl", "c");
4303 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4307 emitcode ("clr", "c");
4309 /* AOP_TYPE(right) == AOP_CRY */
4313 symbol *lbl = newiTempLabel (NULL);
4314 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4315 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4316 emitcode ("cpl", "c");
4317 emitcode ("", "%05d$:", (lbl->key + 100));
4319 /* if true label then we jump if condition
4321 tlbl = newiTempLabel (NULL);
4324 emitcode ("jnc", "%05d$", tlbl->key + 100);
4325 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4329 emitcode ("jc", "%05d$", tlbl->key + 100);
4330 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4332 emitcode ("", "%05d$:", tlbl->key + 100);
4336 tlbl = newiTempLabel (NULL);
4337 gencjneshort (left, right, tlbl);
4340 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4341 emitcode ("", "%05d$:", tlbl->key + 100);
4345 symbol *lbl = newiTempLabel (NULL);
4346 emitcode ("sjmp", "%05d$", lbl->key + 100);
4347 emitcode ("", "%05d$:", tlbl->key + 100);
4348 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4349 emitcode ("", "%05d$:", lbl->key + 100);
4352 /* mark the icode as generated */
4357 /* if they are both bit variables */
4358 if (AOP_TYPE (left) == AOP_CRY &&
4359 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4361 if (AOP_TYPE (right) == AOP_LIT)
4363 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4366 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4367 emitcode ("cpl", "c");
4371 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4375 emitcode ("clr", "c");
4377 /* AOP_TYPE(right) == AOP_CRY */
4381 symbol *lbl = newiTempLabel (NULL);
4382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4383 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4384 emitcode ("cpl", "c");
4385 emitcode ("", "%05d$:", (lbl->key + 100));
4388 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4395 genIfxJump (ifx, "c");
4398 /* if the result is used in an arithmetic operation
4399 then put the result in place */
4404 gencjne (left, right, newiTempLabel (NULL));
4405 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4407 aopPut (AOP (result), "a", 0);
4412 genIfxJump (ifx, "a");
4415 /* if the result is used in an arithmetic operation
4416 then put the result in place */
4417 if (AOP_TYPE (result) != AOP_CRY)
4419 /* leave the result in acc */
4423 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4424 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4425 freeAsmop (result, NULL, ic, TRUE);
4428 /*-----------------------------------------------------------------*/
4429 /* ifxForOp - returns the icode containing the ifx for operand */
4430 /*-----------------------------------------------------------------*/
4432 ifxForOp (operand * op, iCode * ic)
4434 /* if true symbol then needs to be assigned */
4435 if (IS_TRUE_SYMOP (op))
4438 /* if this has register type condition and
4439 the next instruction is ifx with the same operand
4440 and live to of the operand is upto the ifx only then */
4442 ic->next->op == IFX &&
4443 IC_COND (ic->next)->key == op->key &&
4444 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4450 /*-----------------------------------------------------------------*/
4451 /* hasInc - operand is incremented before any other use */
4452 /*-----------------------------------------------------------------*/
4454 hasInc (operand *op, iCode *ic,int osize)
4456 sym_link *type = operandType(op);
4457 sym_link *retype = getSpec (type);
4458 iCode *lic = ic->next;
4461 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4462 if (!IS_SYMOP(op)) return NULL;
4464 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4465 if (IS_AGGREGATE(type->next)) return NULL;
4466 if (osize != (isize = getSize(type->next))) return NULL;
4469 /* if operand of the form op = op + <sizeof *op> */
4470 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4471 isOperandEqual(IC_RESULT(lic),op) &&
4472 isOperandLiteral(IC_RIGHT(lic)) &&
4473 operandLitValue(IC_RIGHT(lic)) == isize) {
4476 /* if the operand used or deffed */
4477 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4480 /* if GOTO or IFX */
4481 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4487 /*-----------------------------------------------------------------*/
4488 /* genAndOp - for && operation */
4489 /*-----------------------------------------------------------------*/
4491 genAndOp (iCode * ic)
4493 operand *left, *right, *result;
4496 D(emitcode ("; genAndOp",""));
4498 /* note here that && operations that are in an
4499 if statement are taken away by backPatchLabels
4500 only those used in arthmetic operations remain */
4501 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4502 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4503 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4505 /* if both are bit variables */
4506 if (AOP_TYPE (left) == AOP_CRY &&
4507 AOP_TYPE (right) == AOP_CRY)
4509 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4510 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4515 tlbl = newiTempLabel (NULL);
4517 emitcode ("jz", "%05d$", tlbl->key + 100);
4519 emitcode ("", "%05d$:", tlbl->key + 100);
4523 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4524 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4525 freeAsmop (result, NULL, ic, TRUE);
4529 /*-----------------------------------------------------------------*/
4530 /* genOrOp - for || operation */
4531 /*-----------------------------------------------------------------*/
4533 genOrOp (iCode * ic)
4535 operand *left, *right, *result;
4538 D(emitcode ("; genOrOp",""));
4540 /* note here that || operations that are in an
4541 if statement are taken away by backPatchLabels
4542 only those used in arthmetic operations remain */
4543 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4544 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4545 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4547 /* if both are bit variables */
4548 if (AOP_TYPE (left) == AOP_CRY &&
4549 AOP_TYPE (right) == AOP_CRY)
4551 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4552 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4557 tlbl = newiTempLabel (NULL);
4559 emitcode ("jnz", "%05d$", tlbl->key + 100);
4561 emitcode ("", "%05d$:", tlbl->key + 100);
4565 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4567 freeAsmop (result, NULL, ic, TRUE);
4570 /*-----------------------------------------------------------------*/
4571 /* isLiteralBit - test if lit == 2^n */
4572 /*-----------------------------------------------------------------*/
4574 isLiteralBit (unsigned long lit)
4576 unsigned long pw[32] =
4577 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4578 0x100L, 0x200L, 0x400L, 0x800L,
4579 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4580 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4581 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4582 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4583 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4586 for (idx = 0; idx < 32; idx++)
4592 /*-----------------------------------------------------------------*/
4593 /* continueIfTrue - */
4594 /*-----------------------------------------------------------------*/
4596 continueIfTrue (iCode * ic)
4599 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4603 /*-----------------------------------------------------------------*/
4605 /*-----------------------------------------------------------------*/
4607 jumpIfTrue (iCode * ic)
4610 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4614 /*-----------------------------------------------------------------*/
4615 /* jmpTrueOrFalse - */
4616 /*-----------------------------------------------------------------*/
4618 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4620 // ugly but optimized by peephole
4623 symbol *nlbl = newiTempLabel (NULL);
4624 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4625 emitcode ("", "%05d$:", tlbl->key + 100);
4626 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4627 emitcode ("", "%05d$:", nlbl->key + 100);
4631 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4632 emitcode ("", "%05d$:", tlbl->key + 100);
4637 /*-----------------------------------------------------------------*/
4638 /* genAnd - code for and */
4639 /*-----------------------------------------------------------------*/
4641 genAnd (iCode * ic, iCode * ifx)
4643 operand *left, *right, *result;
4644 int size, offset = 0;
4645 unsigned long lit = 0L;
4649 D(emitcode ("; genAnd",""));
4651 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4652 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4653 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4656 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4658 AOP_TYPE (left), AOP_TYPE (right));
4659 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4661 AOP_SIZE (left), AOP_SIZE (right));
4664 /* if left is a literal & right is not then exchange them */
4665 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4666 AOP_NEEDSACC (left))
4668 operand *tmp = right;
4673 /* if result = right then exchange them */
4674 if (sameRegs (AOP (result), AOP (right)))
4676 operand *tmp = right;
4681 /* if right is bit then exchange them */
4682 if (AOP_TYPE (right) == AOP_CRY &&
4683 AOP_TYPE (left) != AOP_CRY)
4685 operand *tmp = right;
4689 if (AOP_TYPE (right) == AOP_LIT)
4690 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4692 size = AOP_SIZE (result);
4695 // result = bit & yy;
4696 if (AOP_TYPE (left) == AOP_CRY)
4698 // c = bit & literal;
4699 if (AOP_TYPE (right) == AOP_LIT)
4703 if (size && sameRegs (AOP (result), AOP (left)))
4706 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4711 if (size && (AOP_TYPE (result) == AOP_CRY))
4713 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4716 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4721 emitcode ("clr", "c");
4726 if (AOP_TYPE (right) == AOP_CRY)
4729 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4730 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4735 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4737 emitcode ("rrc", "a");
4738 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4746 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4747 genIfxJump (ifx, "c");
4751 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4752 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4753 if ((AOP_TYPE (right) == AOP_LIT) &&
4754 (AOP_TYPE (result) == AOP_CRY) &&
4755 (AOP_TYPE (left) != AOP_CRY))
4757 int posbit = isLiteralBit (lit);
4762 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4765 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4771 sprintf (buffer, "acc.%d", posbit & 0x07);
4772 genIfxJump (ifx, buffer);
4779 symbol *tlbl = newiTempLabel (NULL);
4780 int sizel = AOP_SIZE (left);
4782 emitcode ("setb", "c");
4785 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4787 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4789 if ((posbit = isLiteralBit (bytelit)) != 0)
4790 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4793 if (bytelit != 0x0FFL)
4794 emitcode ("anl", "a,%s",
4795 aopGet (AOP (right), offset, FALSE, TRUE));
4796 emitcode ("jnz", "%05d$", tlbl->key + 100);
4801 // bit = left & literal
4804 emitcode ("clr", "c");
4805 emitcode ("", "%05d$:", tlbl->key + 100);
4807 // if(left & literal)
4811 jmpTrueOrFalse (ifx, tlbl);
4819 /* if left is same as result */
4820 if (sameRegs (AOP (result), AOP (left)))
4822 for (; size--; offset++)
4824 if (AOP_TYPE (right) == AOP_LIT)
4826 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4828 else if (bytelit == 0)
4829 aopPut (AOP (result), zero, offset);
4830 else if (IS_AOP_PREG (result))
4832 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4833 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4834 aopPut (AOP (result), "a", offset);
4837 emitcode ("anl", "%s,%s",
4838 aopGet (AOP (left), offset, FALSE, TRUE),
4839 aopGet (AOP (right), offset, FALSE, FALSE));
4843 if (AOP_TYPE (left) == AOP_ACC)
4844 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4847 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4848 if (IS_AOP_PREG (result))
4850 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4851 aopPut (AOP (result), "a", offset);
4855 emitcode ("anl", "%s,a",
4856 aopGet (AOP (left), offset, FALSE, TRUE));
4863 // left & result in different registers
4864 if (AOP_TYPE (result) == AOP_CRY)
4867 // if(size), result in bit
4868 // if(!size && ifx), conditional oper: if(left & right)
4869 symbol *tlbl = newiTempLabel (NULL);
4870 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4872 emitcode ("setb", "c");
4875 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4876 emitcode ("anl", "a,%s",
4877 aopGet (AOP (right), offset, FALSE, FALSE));
4879 if (AOP_TYPE(left)==AOP_ACC) {
4880 emitcode("mov", "b,a");
4881 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4882 emitcode("anl", "a,b");
4884 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4885 emitcode ("anl", "a,%s",
4886 aopGet (AOP (left), offset, FALSE, FALSE));
4889 emitcode ("jnz", "%05d$", tlbl->key + 100);
4895 emitcode ("", "%05d$:", tlbl->key + 100);
4899 jmpTrueOrFalse (ifx, tlbl);
4903 for (; (size--); offset++)
4906 // result = left & right
4907 if (AOP_TYPE (right) == AOP_LIT)
4909 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4911 aopPut (AOP (result),
4912 aopGet (AOP (left), offset, FALSE, FALSE),
4916 else if (bytelit == 0)
4918 aopPut (AOP (result), zero, offset);
4922 // faster than result <- left, anl result,right
4923 // and better if result is SFR
4924 if (AOP_TYPE (left) == AOP_ACC)
4925 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4928 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4929 emitcode ("anl", "a,%s",
4930 aopGet (AOP (left), offset, FALSE, FALSE));
4932 aopPut (AOP (result), "a", offset);
4938 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4939 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4940 freeAsmop (result, NULL, ic, TRUE);
4943 /*-----------------------------------------------------------------*/
4944 /* genOr - code for or */
4945 /*-----------------------------------------------------------------*/
4947 genOr (iCode * ic, iCode * ifx)
4949 operand *left, *right, *result;
4950 int size, offset = 0;
4951 unsigned long lit = 0L;
4953 D(emitcode ("; genOr",""));
4955 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4956 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4957 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4960 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4962 AOP_TYPE (left), AOP_TYPE (right));
4963 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4965 AOP_SIZE (left), AOP_SIZE (right));
4968 /* if left is a literal & right is not then exchange them */
4969 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4970 AOP_NEEDSACC (left))
4972 operand *tmp = right;
4977 /* if result = right then exchange them */
4978 if (sameRegs (AOP (result), AOP (right)))
4980 operand *tmp = right;
4985 /* if right is bit then exchange them */
4986 if (AOP_TYPE (right) == AOP_CRY &&
4987 AOP_TYPE (left) != AOP_CRY)
4989 operand *tmp = right;
4993 if (AOP_TYPE (right) == AOP_LIT)
4994 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4996 size = AOP_SIZE (result);
5000 if (AOP_TYPE (left) == AOP_CRY)
5002 if (AOP_TYPE (right) == AOP_LIT)
5004 // c = bit | literal;
5007 // lit != 0 => result = 1
5008 if (AOP_TYPE (result) == AOP_CRY)
5011 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5013 continueIfTrue (ifx);
5016 emitcode ("setb", "c");
5020 // lit == 0 => result = left
5021 if (size && sameRegs (AOP (result), AOP (left)))
5023 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5028 if (AOP_TYPE (right) == AOP_CRY)
5031 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5032 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5037 symbol *tlbl = newiTempLabel (NULL);
5038 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5039 emitcode ("setb", "c");
5040 emitcode ("jb", "%s,%05d$",
5041 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5043 emitcode ("jnz", "%05d$", tlbl->key + 100);
5044 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5046 jmpTrueOrFalse (ifx, tlbl);
5052 emitcode ("", "%05d$:", tlbl->key + 100);
5061 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5062 genIfxJump (ifx, "c");
5066 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5067 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5068 if ((AOP_TYPE (right) == AOP_LIT) &&
5069 (AOP_TYPE (result) == AOP_CRY) &&
5070 (AOP_TYPE (left) != AOP_CRY))
5076 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5078 continueIfTrue (ifx);
5083 // lit = 0, result = boolean(left)
5085 emitcode ("setb", "c");
5089 symbol *tlbl = newiTempLabel (NULL);
5090 emitcode ("jnz", "%05d$", tlbl->key + 100);
5092 emitcode ("", "%05d$:", tlbl->key + 100);
5096 genIfxJump (ifx, "a");
5104 /* if left is same as result */
5105 if (sameRegs (AOP (result), AOP (left)))
5107 for (; size--; offset++)
5109 if (AOP_TYPE (right) == AOP_LIT)
5111 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5113 else if (IS_AOP_PREG (left))
5115 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5116 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5117 aopPut (AOP (result), "a", offset);
5120 emitcode ("orl", "%s,%s",
5121 aopGet (AOP (left), offset, FALSE, TRUE),
5122 aopGet (AOP (right), offset, FALSE, FALSE));
5126 if (AOP_TYPE (left) == AOP_ACC)
5127 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5130 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5131 if (IS_AOP_PREG (left))
5133 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5134 aopPut (AOP (result), "a", offset);
5137 emitcode ("orl", "%s,a",
5138 aopGet (AOP (left), offset, FALSE, TRUE));
5145 // left & result in different registers
5146 if (AOP_TYPE (result) == AOP_CRY)
5149 // if(size), result in bit
5150 // if(!size && ifx), conditional oper: if(left | right)
5151 symbol *tlbl = newiTempLabel (NULL);
5152 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5154 emitcode ("setb", "c");
5157 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5158 emitcode ("orl", "a,%s",
5159 aopGet (AOP (right), offset, FALSE, FALSE));
5161 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5162 emitcode ("orl", "a,%s",
5163 aopGet (AOP (left), offset, FALSE, FALSE));
5165 emitcode ("jnz", "%05d$", tlbl->key + 100);
5171 emitcode ("", "%05d$:", tlbl->key + 100);
5175 jmpTrueOrFalse (ifx, tlbl);
5178 for (; (size--); offset++)
5181 // result = left & right
5182 if (AOP_TYPE (right) == AOP_LIT)
5184 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5186 aopPut (AOP (result),
5187 aopGet (AOP (left), offset, FALSE, FALSE),
5192 // faster than result <- left, anl result,right
5193 // and better if result is SFR
5194 if (AOP_TYPE (left) == AOP_ACC)
5195 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5198 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5199 emitcode ("orl", "a,%s",
5200 aopGet (AOP (left), offset, FALSE, FALSE));
5202 aopPut (AOP (result), "a", offset);
5207 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5208 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5209 freeAsmop (result, NULL, ic, TRUE);
5212 /*-----------------------------------------------------------------*/
5213 /* genXor - code for xclusive or */
5214 /*-----------------------------------------------------------------*/
5216 genXor (iCode * ic, iCode * ifx)
5218 operand *left, *right, *result;
5219 int size, offset = 0;
5220 unsigned long lit = 0L;
5222 D(emitcode ("; genXor",""));
5224 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5225 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5226 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5229 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5231 AOP_TYPE (left), AOP_TYPE (right));
5232 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5234 AOP_SIZE (left), AOP_SIZE (right));
5237 /* if left is a literal & right is not ||
5238 if left needs acc & right does not */
5239 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5240 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5242 operand *tmp = right;
5247 /* if result = right then exchange them */
5248 if (sameRegs (AOP (result), AOP (right)))
5250 operand *tmp = right;
5255 /* if right is bit then exchange them */
5256 if (AOP_TYPE (right) == AOP_CRY &&
5257 AOP_TYPE (left) != AOP_CRY)
5259 operand *tmp = right;
5263 if (AOP_TYPE (right) == AOP_LIT)
5264 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5266 size = AOP_SIZE (result);
5270 if (AOP_TYPE (left) == AOP_CRY)
5272 if (AOP_TYPE (right) == AOP_LIT)
5274 // c = bit & literal;
5277 // lit>>1 != 0 => result = 1
5278 if (AOP_TYPE (result) == AOP_CRY)
5281 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5283 continueIfTrue (ifx);
5286 emitcode ("setb", "c");
5293 // lit == 0, result = left
5294 if (size && sameRegs (AOP (result), AOP (left)))
5296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5300 // lit == 1, result = not(left)
5301 if (size && sameRegs (AOP (result), AOP (left)))
5303 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5308 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5309 emitcode ("cpl", "c");
5318 symbol *tlbl = newiTempLabel (NULL);
5319 if (AOP_TYPE (right) == AOP_CRY)
5322 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5326 int sizer = AOP_SIZE (right);
5328 // if val>>1 != 0, result = 1
5329 emitcode ("setb", "c");
5332 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5334 // test the msb of the lsb
5335 emitcode ("anl", "a,#0xfe");
5336 emitcode ("jnz", "%05d$", tlbl->key + 100);
5340 emitcode ("rrc", "a");
5342 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5343 emitcode ("cpl", "c");
5344 emitcode ("", "%05d$:", (tlbl->key + 100));
5351 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5352 genIfxJump (ifx, "c");
5356 if (sameRegs (AOP (result), AOP (left)))
5358 /* if left is same as result */
5359 for (; size--; offset++)
5361 if (AOP_TYPE (right) == AOP_LIT)
5363 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5365 else if (IS_AOP_PREG (left))
5367 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5368 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5369 aopPut (AOP (result), "a", offset);
5372 emitcode ("xrl", "%s,%s",
5373 aopGet (AOP (left), offset, FALSE, TRUE),
5374 aopGet (AOP (right), offset, FALSE, FALSE));
5378 if (AOP_TYPE (left) == AOP_ACC)
5379 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5382 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5383 if (IS_AOP_PREG (left))
5385 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5386 aopPut (AOP (result), "a", offset);
5389 emitcode ("xrl", "%s,a",
5390 aopGet (AOP (left), offset, FALSE, TRUE));
5397 // left & result in different registers
5398 if (AOP_TYPE (result) == AOP_CRY)
5401 // if(size), result in bit
5402 // if(!size && ifx), conditional oper: if(left ^ right)
5403 symbol *tlbl = newiTempLabel (NULL);
5404 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5406 emitcode ("setb", "c");
5409 if ((AOP_TYPE (right) == AOP_LIT) &&
5410 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5412 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5416 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5417 emitcode ("xrl", "a,%s",
5418 aopGet (AOP (right), offset, FALSE, FALSE));
5420 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5421 emitcode ("xrl", "a,%s",
5422 aopGet (AOP (left), offset, FALSE, FALSE));
5425 emitcode ("jnz", "%05d$", tlbl->key + 100);
5431 emitcode ("", "%05d$:", tlbl->key + 100);
5435 jmpTrueOrFalse (ifx, tlbl);
5438 for (; (size--); offset++)
5441 // result = left & right
5442 if (AOP_TYPE (right) == AOP_LIT)
5444 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5446 aopPut (AOP (result),
5447 aopGet (AOP (left), offset, FALSE, FALSE),
5452 // faster than result <- left, anl result,right
5453 // and better if result is SFR
5454 if (AOP_TYPE (left) == AOP_ACC)
5455 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5458 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5459 emitcode ("xrl", "a,%s",
5460 aopGet (AOP (left), offset, FALSE, TRUE));
5462 aopPut (AOP (result), "a", offset);
5467 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5468 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5469 freeAsmop (result, NULL, ic, TRUE);
5472 /*-----------------------------------------------------------------*/
5473 /* genInline - write the inline code out */
5474 /*-----------------------------------------------------------------*/
5476 genInline (iCode * ic)
5478 char *buffer, *bp, *bp1;
5480 D(emitcode ("; genInline",""));
5482 _G.inLine += (!options.asmpeep);
5484 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5485 strcpy (buffer, IC_INLINE (ic));
5487 /* emit each line as a code */
5512 /* emitcode("",buffer); */
5513 _G.inLine -= (!options.asmpeep);
5516 /*-----------------------------------------------------------------*/
5517 /* genRRC - rotate right with carry */
5518 /*-----------------------------------------------------------------*/
5522 operand *left, *result;
5523 int size, offset = 0;
5526 D(emitcode ("; genRRC",""));
5528 /* rotate right with carry */
5529 left = IC_LEFT (ic);
5530 result = IC_RESULT (ic);
5531 aopOp (left, ic, FALSE);
5532 aopOp (result, ic, FALSE);
5534 /* move it to the result */
5535 size = AOP_SIZE (result);
5537 if (size == 1) { /* special case for 1 byte */
5538 l = aopGet (AOP (left), offset, FALSE, FALSE);
5540 emitcode ("rr", "a");
5546 l = aopGet (AOP (left), offset, FALSE, FALSE);
5548 emitcode ("rrc", "a");
5549 if (AOP_SIZE (result) > 1)
5550 aopPut (AOP (result), "a", offset--);
5552 /* now we need to put the carry into the
5553 highest order byte of the result */
5554 if (AOP_SIZE (result) > 1)
5556 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5559 emitcode ("mov", "acc.7,c");
5561 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5562 freeAsmop (left, NULL, ic, TRUE);
5563 freeAsmop (result, NULL, ic, TRUE);
5566 /*-----------------------------------------------------------------*/
5567 /* genRLC - generate code for rotate left with carry */
5568 /*-----------------------------------------------------------------*/
5572 operand *left, *result;
5573 int size, offset = 0;
5576 D(emitcode ("; genRLC",""));
5578 /* rotate right with carry */
5579 left = IC_LEFT (ic);
5580 result = IC_RESULT (ic);
5581 aopOp (left, ic, FALSE);
5582 aopOp (result, ic, FALSE);
5584 /* move it to the result */
5585 size = AOP_SIZE (result);
5589 l = aopGet (AOP (left), offset, FALSE, FALSE);
5591 if (size == 0) { /* special case for 1 byte */
5595 emitcode ("add", "a,acc");
5596 if (AOP_SIZE (result) > 1)
5597 aopPut (AOP (result), "a", offset++);
5600 l = aopGet (AOP (left), offset, FALSE, FALSE);
5602 emitcode ("rlc", "a");
5603 if (AOP_SIZE (result) > 1)
5604 aopPut (AOP (result), "a", offset++);
5607 /* now we need to put the carry into the
5608 highest order byte of the result */
5609 if (AOP_SIZE (result) > 1)
5611 l = aopGet (AOP (result), 0, FALSE, FALSE);
5614 emitcode ("mov", "acc.0,c");
5616 aopPut (AOP (result), "a", 0);
5617 freeAsmop (left, NULL, ic, TRUE);
5618 freeAsmop (result, NULL, ic, TRUE);
5621 /*-----------------------------------------------------------------*/
5622 /* genGetHbit - generates code get highest order bit */
5623 /*-----------------------------------------------------------------*/
5625 genGetHbit (iCode * ic)
5627 operand *left, *result;
5629 D(emitcode ("; genGetHbit",""));
5631 left = IC_LEFT (ic);
5632 result = IC_RESULT (ic);
5633 aopOp (left, ic, FALSE);
5634 aopOp (result, ic, FALSE);
5636 /* get the highest order byte into a */
5637 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5638 if (AOP_TYPE (result) == AOP_CRY)
5640 emitcode ("rlc", "a");
5645 emitcode ("rl", "a");
5646 emitcode ("anl", "a,#0x01");
5651 freeAsmop (left, NULL, ic, TRUE);
5652 freeAsmop (result, NULL, ic, TRUE);
5655 /*-----------------------------------------------------------------*/
5656 /* AccRol - rotate left accumulator by known count */
5657 /*-----------------------------------------------------------------*/
5659 AccRol (int shCount)
5661 shCount &= 0x0007; // shCount : 0..7
5668 emitcode ("rl", "a");
5671 emitcode ("rl", "a");
5672 emitcode ("rl", "a");
5675 emitcode ("swap", "a");
5676 emitcode ("rr", "a");
5679 emitcode ("swap", "a");
5682 emitcode ("swap", "a");
5683 emitcode ("rl", "a");
5686 emitcode ("rr", "a");
5687 emitcode ("rr", "a");
5690 emitcode ("rr", "a");
5695 /*-----------------------------------------------------------------*/
5696 /* AccLsh - left shift accumulator by known count */
5697 /*-----------------------------------------------------------------*/
5699 AccLsh (int shCount)
5704 emitcode ("add", "a,acc");
5705 else if (shCount == 2)
5707 emitcode ("add", "a,acc");
5708 emitcode ("add", "a,acc");
5712 /* rotate left accumulator */
5714 /* and kill the lower order bits */
5715 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5720 /*-----------------------------------------------------------------*/
5721 /* AccRsh - right shift accumulator by known count */
5722 /*-----------------------------------------------------------------*/
5724 AccRsh (int shCount)
5731 emitcode ("rrc", "a");
5735 /* rotate right accumulator */
5736 AccRol (8 - shCount);
5737 /* and kill the higher order bits */
5738 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5743 /*-----------------------------------------------------------------*/
5744 /* AccSRsh - signed right shift accumulator by known count */
5745 /*-----------------------------------------------------------------*/
5747 AccSRsh (int shCount)
5754 emitcode ("mov", "c,acc.7");
5755 emitcode ("rrc", "a");
5757 else if (shCount == 2)
5759 emitcode ("mov", "c,acc.7");
5760 emitcode ("rrc", "a");
5761 emitcode ("mov", "c,acc.7");
5762 emitcode ("rrc", "a");
5766 tlbl = newiTempLabel (NULL);
5767 /* rotate right accumulator */
5768 AccRol (8 - shCount);
5769 /* and kill the higher order bits */
5770 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5771 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5772 emitcode ("orl", "a,#0x%02x",
5773 (unsigned char) ~SRMask[shCount]);
5774 emitcode ("", "%05d$:", tlbl->key + 100);
5779 /*-----------------------------------------------------------------*/
5780 /* shiftR1Left2Result - shift right one byte from left to result */
5781 /*-----------------------------------------------------------------*/
5783 shiftR1Left2Result (operand * left, int offl,
5784 operand * result, int offr,
5785 int shCount, int sign)
5787 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5788 /* shift right accumulator */
5793 aopPut (AOP (result), "a", offr);
5796 /*-----------------------------------------------------------------*/
5797 /* shiftL1Left2Result - shift left one byte from left to result */
5798 /*-----------------------------------------------------------------*/
5800 shiftL1Left2Result (operand * left, int offl,
5801 operand * result, int offr, int shCount)
5804 l = aopGet (AOP (left), offl, FALSE, FALSE);
5806 /* shift left accumulator */
5808 aopPut (AOP (result), "a", offr);
5811 /*-----------------------------------------------------------------*/
5812 /* movLeft2Result - move byte from left to result */
5813 /*-----------------------------------------------------------------*/
5815 movLeft2Result (operand * left, int offl,
5816 operand * result, int offr, int sign)
5819 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5821 l = aopGet (AOP (left), offl, FALSE, FALSE);
5823 if (*l == '@' && (IS_AOP_PREG (result)))
5825 emitcode ("mov", "a,%s", l);
5826 aopPut (AOP (result), "a", offr);
5831 aopPut (AOP (result), l, offr);
5834 /* MSB sign in acc.7 ! */
5835 if (getDataSize (left) == offl + 1)
5837 emitcode ("mov", "a,%s", l);
5838 aopPut (AOP (result), "a", offr);
5845 /*-----------------------------------------------------------------*/
5846 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5847 /*-----------------------------------------------------------------*/
5851 emitcode ("rrc", "a");
5852 emitcode ("xch", "a,%s", x);
5853 emitcode ("rrc", "a");
5854 emitcode ("xch", "a,%s", x);
5857 /*-----------------------------------------------------------------*/
5858 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5859 /*-----------------------------------------------------------------*/
5863 emitcode ("xch", "a,%s", x);
5864 emitcode ("rlc", "a");
5865 emitcode ("xch", "a,%s", x);
5866 emitcode ("rlc", "a");
5869 /*-----------------------------------------------------------------*/
5870 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5871 /*-----------------------------------------------------------------*/
5875 emitcode ("xch", "a,%s", x);
5876 emitcode ("add", "a,acc");
5877 emitcode ("xch", "a,%s", x);
5878 emitcode ("rlc", "a");
5881 /*-----------------------------------------------------------------*/
5882 /* AccAXLsh - left shift a:x by known count (0..7) */
5883 /*-----------------------------------------------------------------*/
5885 AccAXLsh (char *x, int shCount)
5900 case 5: // AAAAABBB:CCCCCDDD
5902 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5904 emitcode ("anl", "a,#0x%02x",
5905 SLMask[shCount]); // BBB00000:CCCCCDDD
5907 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5909 AccRol (shCount); // DDDCCCCC:BBB00000
5911 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5913 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5915 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5917 emitcode ("anl", "a,#0x%02x",
5918 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5920 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5922 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5925 case 6: // AAAAAABB:CCCCCCDD
5926 emitcode ("anl", "a,#0x%02x",
5927 SRMask[shCount]); // 000000BB:CCCCCCDD
5928 emitcode ("mov", "c,acc.0"); // c = B
5929 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5931 AccAXRrl1 (x); // BCCCCCCD:D000000B
5932 AccAXRrl1 (x); // BBCCCCCC:DD000000
5934 emitcode("rrc","a");
5935 emitcode("xch","a,%s", x);
5936 emitcode("rrc","a");
5937 emitcode("mov","c,acc.0"); //<< get correct bit
5938 emitcode("xch","a,%s", x);
5940 emitcode("rrc","a");
5941 emitcode("xch","a,%s", x);
5942 emitcode("rrc","a");
5943 emitcode("xch","a,%s", x);
5946 case 7: // a:x <<= 7
5948 emitcode ("anl", "a,#0x%02x",
5949 SRMask[shCount]); // 0000000B:CCCCCCCD
5951 emitcode ("mov", "c,acc.0"); // c = B
5953 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5955 AccAXRrl1 (x); // BCCCCCCC:D0000000
5963 /*-----------------------------------------------------------------*/
5964 /* AccAXRsh - right shift a:x known count (0..7) */
5965 /*-----------------------------------------------------------------*/
5967 AccAXRsh (char *x, int shCount)
5975 AccAXRrl1 (x); // 0->a:x
5980 AccAXRrl1 (x); // 0->a:x
5983 AccAXRrl1 (x); // 0->a:x
5988 case 5: // AAAAABBB:CCCCCDDD = a:x
5990 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5992 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5994 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5996 emitcode ("anl", "a,#0x%02x",
5997 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5999 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6001 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6003 emitcode ("anl", "a,#0x%02x",
6004 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6006 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6008 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6010 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6013 case 6: // AABBBBBB:CCDDDDDD
6015 emitcode ("mov", "c,acc.7");
6016 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6018 emitcode ("mov", "c,acc.7");
6019 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6021 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6023 emitcode ("anl", "a,#0x%02x",
6024 SRMask[shCount]); // 000000AA:BBBBBBCC
6027 case 7: // ABBBBBBB:CDDDDDDD
6029 emitcode ("mov", "c,acc.7"); // c = A
6031 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6033 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6035 emitcode ("anl", "a,#0x%02x",
6036 SRMask[shCount]); // 0000000A:BBBBBBBC
6044 /*-----------------------------------------------------------------*/
6045 /* AccAXRshS - right shift signed a:x known count (0..7) */
6046 /*-----------------------------------------------------------------*/
6048 AccAXRshS (char *x, int shCount)
6056 emitcode ("mov", "c,acc.7");
6057 AccAXRrl1 (x); // s->a:x
6061 emitcode ("mov", "c,acc.7");
6062 AccAXRrl1 (x); // s->a:x
6064 emitcode ("mov", "c,acc.7");
6065 AccAXRrl1 (x); // s->a:x
6070 case 5: // AAAAABBB:CCCCCDDD = a:x
6072 tlbl = newiTempLabel (NULL);
6073 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6075 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6077 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6079 emitcode ("anl", "a,#0x%02x",
6080 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6082 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6084 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6086 emitcode ("anl", "a,#0x%02x",
6087 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6089 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6091 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6093 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6095 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6096 emitcode ("orl", "a,#0x%02x",
6097 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6099 emitcode ("", "%05d$:", tlbl->key + 100);
6100 break; // SSSSAAAA:BBBCCCCC
6102 case 6: // AABBBBBB:CCDDDDDD
6104 tlbl = newiTempLabel (NULL);
6105 emitcode ("mov", "c,acc.7");
6106 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6108 emitcode ("mov", "c,acc.7");
6109 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6111 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6113 emitcode ("anl", "a,#0x%02x",
6114 SRMask[shCount]); // 000000AA:BBBBBBCC
6116 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6117 emitcode ("orl", "a,#0x%02x",
6118 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6120 emitcode ("", "%05d$:", tlbl->key + 100);
6122 case 7: // ABBBBBBB:CDDDDDDD
6124 tlbl = newiTempLabel (NULL);
6125 emitcode ("mov", "c,acc.7"); // c = A
6127 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6129 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6131 emitcode ("anl", "a,#0x%02x",
6132 SRMask[shCount]); // 0000000A:BBBBBBBC
6134 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6135 emitcode ("orl", "a,#0x%02x",
6136 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6138 emitcode ("", "%05d$:", tlbl->key + 100);
6145 /*-----------------------------------------------------------------*/
6146 /* shiftL2Left2Result - shift left two bytes from left to result */
6147 /*-----------------------------------------------------------------*/
6149 shiftL2Left2Result (operand * left, int offl,
6150 operand * result, int offr, int shCount)
6152 if (sameRegs (AOP (result), AOP (left)) &&
6153 ((offl + MSB16) == offr))
6155 /* don't crash result[offr] */
6156 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6157 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6161 movLeft2Result (left, offl, result, offr, 0);
6162 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6164 /* ax << shCount (x = lsb(result)) */
6165 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6166 aopPut (AOP (result), "a", offr + MSB16);
6170 /*-----------------------------------------------------------------*/
6171 /* shiftR2Left2Result - shift right two bytes from left to result */
6172 /*-----------------------------------------------------------------*/
6174 shiftR2Left2Result (operand * left, int offl,
6175 operand * result, int offr,
6176 int shCount, int sign)
6178 if (sameRegs (AOP (result), AOP (left)) &&
6179 ((offl + MSB16) == offr))
6181 /* don't crash result[offr] */
6182 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6183 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6187 movLeft2Result (left, offl, result, offr, 0);
6188 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6190 /* a:x >> shCount (x = lsb(result)) */
6192 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6194 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6195 if (getDataSize (result) > 1)
6196 aopPut (AOP (result), "a", offr + MSB16);
6199 /*-----------------------------------------------------------------*/
6200 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6201 /*-----------------------------------------------------------------*/
6203 shiftLLeftOrResult (operand * left, int offl,
6204 operand * result, int offr, int shCount)
6206 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6207 /* shift left accumulator */
6209 /* or with result */
6210 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6211 /* back to result */
6212 aopPut (AOP (result), "a", offr);
6215 /*-----------------------------------------------------------------*/
6216 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6217 /*-----------------------------------------------------------------*/
6219 shiftRLeftOrResult (operand * left, int offl,
6220 operand * result, int offr, int shCount)
6222 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6223 /* shift right accumulator */
6225 /* or with result */
6226 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6227 /* back to result */
6228 aopPut (AOP (result), "a", offr);
6231 /*-----------------------------------------------------------------*/
6232 /* genlshOne - left shift a one byte quantity by known count */
6233 /*-----------------------------------------------------------------*/
6235 genlshOne (operand * result, operand * left, int shCount)
6237 D(emitcode ("; genlshOne",""));
6239 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6242 /*-----------------------------------------------------------------*/
6243 /* genlshTwo - left shift two bytes by known amount != 0 */
6244 /*-----------------------------------------------------------------*/
6246 genlshTwo (operand * result, operand * left, int shCount)
6250 D(emitcode ("; genlshTwo",""));
6252 size = getDataSize (result);
6254 /* if shCount >= 8 */
6262 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6264 movLeft2Result (left, LSB, result, MSB16, 0);
6266 aopPut (AOP (result), zero, LSB);
6269 /* 1 <= shCount <= 7 */
6273 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6275 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6279 /*-----------------------------------------------------------------*/
6280 /* shiftLLong - shift left one long from left to result */
6281 /* offl = LSB or MSB16 */
6282 /*-----------------------------------------------------------------*/
6284 shiftLLong (operand * left, operand * result, int offr)
6287 int size = AOP_SIZE (result);
6289 if (size >= LSB + offr)
6291 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6293 emitcode ("add", "a,acc");
6294 if (sameRegs (AOP (left), AOP (result)) &&
6295 size >= MSB16 + offr && offr != LSB)
6296 emitcode ("xch", "a,%s",
6297 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6299 aopPut (AOP (result), "a", LSB + offr);
6302 if (size >= MSB16 + offr)
6304 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6306 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6309 emitcode ("rlc", "a");
6310 if (sameRegs (AOP (left), AOP (result)) &&
6311 size >= MSB24 + offr && offr != LSB)
6312 emitcode ("xch", "a,%s",
6313 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6315 aopPut (AOP (result), "a", MSB16 + offr);
6318 if (size >= MSB24 + offr)
6320 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6322 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6325 emitcode ("rlc", "a");
6326 if (sameRegs (AOP (left), AOP (result)) &&
6327 size >= MSB32 + offr && offr != LSB)
6328 emitcode ("xch", "a,%s",
6329 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6331 aopPut (AOP (result), "a", MSB24 + offr);
6334 if (size > MSB32 + offr)
6336 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6338 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6341 emitcode ("rlc", "a");
6342 aopPut (AOP (result), "a", MSB32 + offr);
6345 aopPut (AOP (result), zero, LSB);
6348 /*-----------------------------------------------------------------*/
6349 /* genlshFour - shift four byte by a known amount != 0 */
6350 /*-----------------------------------------------------------------*/
6352 genlshFour (operand * result, operand * left, int shCount)
6356 D(emitcode ("; genlshFour",""));
6358 size = AOP_SIZE (result);
6360 /* if shifting more that 3 bytes */
6365 /* lowest order of left goes to the highest
6366 order of the destination */
6367 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6369 movLeft2Result (left, LSB, result, MSB32, 0);
6370 aopPut (AOP (result), zero, LSB);
6371 aopPut (AOP (result), zero, MSB16);
6372 aopPut (AOP (result), zero, MSB24);
6376 /* more than two bytes */
6377 else if (shCount >= 16)
6379 /* lower order two bytes goes to higher order two bytes */
6381 /* if some more remaining */
6383 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6386 movLeft2Result (left, MSB16, result, MSB32, 0);
6387 movLeft2Result (left, LSB, result, MSB24, 0);
6389 aopPut (AOP (result), zero, MSB16);
6390 aopPut (AOP (result), zero, LSB);
6394 /* if more than 1 byte */
6395 else if (shCount >= 8)
6397 /* lower order three bytes goes to higher order three bytes */
6402 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6404 movLeft2Result (left, LSB, result, MSB16, 0);
6410 movLeft2Result (left, MSB24, result, MSB32, 0);
6411 movLeft2Result (left, MSB16, result, MSB24, 0);
6412 movLeft2Result (left, LSB, result, MSB16, 0);
6413 aopPut (AOP (result), zero, LSB);
6415 else if (shCount == 1)
6416 shiftLLong (left, result, MSB16);
6419 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6420 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6421 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6422 aopPut (AOP (result), zero, LSB);
6427 /* 1 <= shCount <= 7 */
6428 else if (shCount <= 2)
6430 shiftLLong (left, result, LSB);
6432 shiftLLong (result, result, LSB);
6434 /* 3 <= shCount <= 7, optimize */
6437 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6438 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6439 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6443 /*-----------------------------------------------------------------*/
6444 /* genLeftShiftLiteral - left shifting by known count */
6445 /*-----------------------------------------------------------------*/
6447 genLeftShiftLiteral (operand * left,
6452 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6455 D(emitcode ("; genLeftShiftLiteral",""));
6457 freeAsmop (right, NULL, ic, TRUE);
6459 aopOp (left, ic, FALSE);
6460 aopOp (result, ic, FALSE);
6462 size = getSize (operandType (result));
6465 emitcode ("; shift left ", "result %d, left %d", size,
6469 /* I suppose that the left size >= result size */
6474 movLeft2Result (left, size, result, size, 0);
6478 else if (shCount >= (size * 8))
6480 aopPut (AOP (result), zero, size);
6486 genlshOne (result, left, shCount);
6490 genlshTwo (result, left, shCount);
6494 genlshFour (result, left, shCount);
6497 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6498 "*** ack! mystery literal shift!\n");
6502 freeAsmop (left, NULL, ic, TRUE);
6503 freeAsmop (result, NULL, ic, TRUE);
6506 /*-----------------------------------------------------------------*/
6507 /* genLeftShift - generates code for left shifting */
6508 /*-----------------------------------------------------------------*/
6510 genLeftShift (iCode * ic)
6512 operand *left, *right, *result;
6515 symbol *tlbl, *tlbl1;
6517 D(emitcode ("; genLeftShift",""));
6519 right = IC_RIGHT (ic);
6520 left = IC_LEFT (ic);
6521 result = IC_RESULT (ic);
6523 aopOp (right, ic, FALSE);
6525 /* if the shift count is known then do it
6526 as efficiently as possible */
6527 if (AOP_TYPE (right) == AOP_LIT)
6529 genLeftShiftLiteral (left, right, result, ic);
6533 /* shift count is unknown then we have to form
6534 a loop get the loop count in B : Note: we take
6535 only the lower order byte since shifting
6536 more that 32 bits make no sense anyway, ( the
6537 largest size of an object can be only 32 bits ) */
6539 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6540 emitcode ("inc", "b");
6541 freeAsmop (right, NULL, ic, TRUE);
6542 aopOp (left, ic, FALSE);
6543 aopOp (result, ic, FALSE);
6545 /* now move the left to the result if they are not the
6547 if (!sameRegs (AOP (left), AOP (result)) &&
6548 AOP_SIZE (result) > 1)
6551 size = AOP_SIZE (result);
6555 l = aopGet (AOP (left), offset, FALSE, TRUE);
6556 if (*l == '@' && (IS_AOP_PREG (result)))
6559 emitcode ("mov", "a,%s", l);
6560 aopPut (AOP (result), "a", offset);
6563 aopPut (AOP (result), l, offset);
6568 tlbl = newiTempLabel (NULL);
6569 size = AOP_SIZE (result);
6571 tlbl1 = newiTempLabel (NULL);
6573 /* if it is only one byte then */
6576 symbol *tlbl1 = newiTempLabel (NULL);
6578 l = aopGet (AOP (left), 0, FALSE, FALSE);
6580 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6581 emitcode ("", "%05d$:", tlbl->key + 100);
6582 emitcode ("add", "a,acc");
6583 emitcode ("", "%05d$:", tlbl1->key + 100);
6584 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6585 aopPut (AOP (result), "a", 0);
6589 reAdjustPreg (AOP (result));
6591 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6592 emitcode ("", "%05d$:", tlbl->key + 100);
6593 l = aopGet (AOP (result), offset, FALSE, FALSE);
6595 emitcode ("add", "a,acc");
6596 aopPut (AOP (result), "a", offset++);
6599 l = aopGet (AOP (result), offset, FALSE, FALSE);
6601 emitcode ("rlc", "a");
6602 aopPut (AOP (result), "a", offset++);
6604 reAdjustPreg (AOP (result));
6606 emitcode ("", "%05d$:", tlbl1->key + 100);
6607 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6609 freeAsmop (left, NULL, ic, TRUE);
6610 freeAsmop (result, NULL, ic, TRUE);
6613 /*-----------------------------------------------------------------*/
6614 /* genrshOne - right shift a one byte quantity by known count */
6615 /*-----------------------------------------------------------------*/
6617 genrshOne (operand * result, operand * left,
6618 int shCount, int sign)
6620 D(emitcode ("; genrshOne",""));
6622 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6625 /*-----------------------------------------------------------------*/
6626 /* genrshTwo - right shift two bytes by known amount != 0 */
6627 /*-----------------------------------------------------------------*/
6629 genrshTwo (operand * result, operand * left,
6630 int shCount, int sign)
6632 D(emitcode ("; genrshTwo",""));
6634 /* if shCount >= 8 */
6639 shiftR1Left2Result (left, MSB16, result, LSB,
6642 movLeft2Result (left, MSB16, result, LSB, sign);
6643 addSign (result, MSB16, sign);
6646 /* 1 <= shCount <= 7 */
6648 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6651 /*-----------------------------------------------------------------*/
6652 /* shiftRLong - shift right one long from left to result */
6653 /* offl = LSB or MSB16 */
6654 /*-----------------------------------------------------------------*/
6656 shiftRLong (operand * left, int offl,
6657 operand * result, int sign)
6659 int isSameRegs=sameRegs(AOP(left),AOP(result));
6661 if (isSameRegs && offl>1) {
6662 // we are in big trouble, but this shouldn't happen
6663 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6666 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6671 emitcode ("rlc", "a");
6672 emitcode ("subb", "a,acc");
6674 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6676 aopPut (AOP (result), "a", MSB32);
6677 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6680 aopPut (AOP(result), zero, MSB32);
6685 emitcode ("clr", "c");
6687 emitcode ("mov", "c,acc.7");
6690 emitcode ("rrc", "a");
6692 if (isSameRegs && offl==MSB16) {
6693 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6695 aopPut (AOP (result), "a", MSB32-offl);
6696 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6699 emitcode ("rrc", "a");
6700 if (isSameRegs && offl==1) {
6701 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6703 aopPut (AOP (result), "a", MSB24-offl);
6704 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6706 emitcode ("rrc", "a");
6707 aopPut (AOP (result), "a", MSB16 - offl);
6711 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6712 emitcode ("rrc", "a");
6713 aopPut (AOP (result), "a", LSB);
6717 /*-----------------------------------------------------------------*/
6718 /* genrshFour - shift four byte by a known amount != 0 */
6719 /*-----------------------------------------------------------------*/
6721 genrshFour (operand * result, operand * left,
6722 int shCount, int sign)
6724 D(emitcode ("; genrshFour",""));
6726 /* if shifting more that 3 bytes */
6731 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6733 movLeft2Result (left, MSB32, result, LSB, sign);
6734 addSign (result, MSB16, sign);
6736 else if (shCount >= 16)
6740 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6743 movLeft2Result (left, MSB24, result, LSB, 0);
6744 movLeft2Result (left, MSB32, result, MSB16, sign);
6746 addSign (result, MSB24, sign);
6748 else if (shCount >= 8)
6752 shiftRLong (left, MSB16, result, sign);
6753 else if (shCount == 0)
6755 movLeft2Result (left, MSB16, result, LSB, 0);
6756 movLeft2Result (left, MSB24, result, MSB16, 0);
6757 movLeft2Result (left, MSB32, result, MSB24, sign);
6758 addSign (result, MSB32, sign);
6762 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6763 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6764 /* the last shift is signed */
6765 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6766 addSign (result, MSB32, sign);
6770 { /* 1 <= shCount <= 7 */
6773 shiftRLong (left, LSB, result, sign);
6775 shiftRLong (result, LSB, result, sign);
6779 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6780 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6781 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6786 /*-----------------------------------------------------------------*/
6787 /* genRightShiftLiteral - right shifting by known count */
6788 /*-----------------------------------------------------------------*/
6790 genRightShiftLiteral (operand * left,
6796 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6799 D(emitcode ("; genRightShiftLiteral",""));
6801 freeAsmop (right, NULL, ic, TRUE);
6803 aopOp (left, ic, FALSE);
6804 aopOp (result, ic, FALSE);
6807 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6811 size = getDataSize (left);
6812 /* test the LEFT size !!! */
6814 /* I suppose that the left size >= result size */
6817 size = getDataSize (result);
6819 movLeft2Result (left, size, result, size, 0);
6822 else if (shCount >= (size * 8))
6825 /* get sign in acc.7 */
6826 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6828 addSign (result, LSB, sign);
6835 genrshOne (result, left, shCount, sign);
6839 genrshTwo (result, left, shCount, sign);
6843 genrshFour (result, left, shCount, sign);
6849 freeAsmop (left, NULL, ic, TRUE);
6850 freeAsmop (result, NULL, ic, TRUE);
6853 /*-----------------------------------------------------------------*/
6854 /* genSignedRightShift - right shift of signed number */
6855 /*-----------------------------------------------------------------*/
6857 genSignedRightShift (iCode * ic)
6859 operand *right, *left, *result;
6862 symbol *tlbl, *tlbl1;
6864 D(emitcode ("; genSignedRightShift",""));
6866 /* we do it the hard way put the shift count in b
6867 and loop thru preserving the sign */
6869 right = IC_RIGHT (ic);
6870 left = IC_LEFT (ic);
6871 result = IC_RESULT (ic);
6873 aopOp (right, ic, FALSE);
6876 if (AOP_TYPE (right) == AOP_LIT)
6878 genRightShiftLiteral (left, right, result, ic, 1);
6881 /* shift count is unknown then we have to form
6882 a loop get the loop count in B : Note: we take
6883 only the lower order byte since shifting
6884 more that 32 bits make no sense anyway, ( the
6885 largest size of an object can be only 32 bits ) */
6887 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6888 emitcode ("inc", "b");
6889 freeAsmop (right, NULL, ic, TRUE);
6890 aopOp (left, ic, FALSE);
6891 aopOp (result, ic, FALSE);
6893 /* now move the left to the result if they are not the
6895 if (!sameRegs (AOP (left), AOP (result)) &&
6896 AOP_SIZE (result) > 1)
6899 size = AOP_SIZE (result);
6903 l = aopGet (AOP (left), offset, FALSE, TRUE);
6904 if (*l == '@' && IS_AOP_PREG (result))
6907 emitcode ("mov", "a,%s", l);
6908 aopPut (AOP (result), "a", offset);
6911 aopPut (AOP (result), l, offset);
6916 /* mov the highest order bit to OVR */
6917 tlbl = newiTempLabel (NULL);
6918 tlbl1 = newiTempLabel (NULL);
6920 size = AOP_SIZE (result);
6922 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6923 emitcode ("rlc", "a");
6924 emitcode ("mov", "ov,c");
6925 /* if it is only one byte then */
6928 l = aopGet (AOP (left), 0, FALSE, FALSE);
6930 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6931 emitcode ("", "%05d$:", tlbl->key + 100);
6932 emitcode ("mov", "c,ov");
6933 emitcode ("rrc", "a");
6934 emitcode ("", "%05d$:", tlbl1->key + 100);
6935 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6936 aopPut (AOP (result), "a", 0);
6940 reAdjustPreg (AOP (result));
6941 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6942 emitcode ("", "%05d$:", tlbl->key + 100);
6943 emitcode ("mov", "c,ov");
6946 l = aopGet (AOP (result), offset, FALSE, FALSE);
6948 emitcode ("rrc", "a");
6949 aopPut (AOP (result), "a", offset--);
6951 reAdjustPreg (AOP (result));
6952 emitcode ("", "%05d$:", tlbl1->key + 100);
6953 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6956 freeAsmop (left, NULL, ic, TRUE);
6957 freeAsmop (result, NULL, ic, TRUE);
6960 /*-----------------------------------------------------------------*/
6961 /* genRightShift - generate code for right shifting */
6962 /*-----------------------------------------------------------------*/
6964 genRightShift (iCode * ic)
6966 operand *right, *left, *result;
6970 symbol *tlbl, *tlbl1;
6972 D(emitcode ("; genRightShift",""));
6974 /* if signed then we do it the hard way preserve the
6975 sign bit moving it inwards */
6976 retype = getSpec (operandType (IC_RESULT (ic)));
6978 if (!SPEC_USIGN (retype))
6980 genSignedRightShift (ic);
6984 /* signed & unsigned types are treated the same : i.e. the
6985 signed is NOT propagated inwards : quoting from the
6986 ANSI - standard : "for E1 >> E2, is equivalent to division
6987 by 2**E2 if unsigned or if it has a non-negative value,
6988 otherwise the result is implementation defined ", MY definition
6989 is that the sign does not get propagated */
6991 right = IC_RIGHT (ic);
6992 left = IC_LEFT (ic);
6993 result = IC_RESULT (ic);
6995 aopOp (right, ic, FALSE);
6997 /* if the shift count is known then do it
6998 as efficiently as possible */
6999 if (AOP_TYPE (right) == AOP_LIT)
7001 genRightShiftLiteral (left, right, result, ic, 0);
7005 /* shift count is unknown then we have to form
7006 a loop get the loop count in B : Note: we take
7007 only the lower order byte since shifting
7008 more that 32 bits make no sense anyway, ( the
7009 largest size of an object can be only 32 bits ) */
7011 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7012 emitcode ("inc", "b");
7013 freeAsmop (right, NULL, ic, TRUE);
7014 aopOp (left, ic, FALSE);
7015 aopOp (result, ic, FALSE);
7017 /* now move the left to the result if they are not the
7019 if (!sameRegs (AOP (left), AOP (result)) &&
7020 AOP_SIZE (result) > 1)
7023 size = AOP_SIZE (result);
7027 l = aopGet (AOP (left), offset, FALSE, TRUE);
7028 if (*l == '@' && IS_AOP_PREG (result))
7031 emitcode ("mov", "a,%s", l);
7032 aopPut (AOP (result), "a", offset);
7035 aopPut (AOP (result), l, offset);
7040 tlbl = newiTempLabel (NULL);
7041 tlbl1 = newiTempLabel (NULL);
7042 size = AOP_SIZE (result);
7045 /* if it is only one byte then */
7048 l = aopGet (AOP (left), 0, FALSE, FALSE);
7050 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7051 emitcode ("", "%05d$:", tlbl->key + 100);
7053 emitcode ("rrc", "a");
7054 emitcode ("", "%05d$:", tlbl1->key + 100);
7055 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7056 aopPut (AOP (result), "a", 0);
7060 reAdjustPreg (AOP (result));
7061 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7062 emitcode ("", "%05d$:", tlbl->key + 100);
7066 l = aopGet (AOP (result), offset, FALSE, FALSE);
7068 emitcode ("rrc", "a");
7069 aopPut (AOP (result), "a", offset--);
7071 reAdjustPreg (AOP (result));
7073 emitcode ("", "%05d$:", tlbl1->key + 100);
7074 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7077 freeAsmop (left, NULL, ic, TRUE);
7078 freeAsmop (result, NULL, ic, TRUE);
7081 /*-----------------------------------------------------------------*/
7082 /* genUnpackBits - generates code for unpacking bits */
7083 /*-----------------------------------------------------------------*/
7085 genUnpackBits (operand * result, char *rname, int ptype)
7093 D(emitcode ("; genUnpackBits",""));
7095 etype = getSpec (operandType (result));
7096 rsize = getSize (operandType (result));
7097 /* read the first byte */
7103 emitcode ("mov", "a,@%s", rname);
7107 emitcode ("movx", "a,@%s", rname);
7111 emitcode ("movx", "a,@dptr");
7115 emitcode ("clr", "a");
7116 emitcode ("movc", "a,@a+dptr");
7120 emitcode ("lcall", "__gptrget");
7124 rlen = SPEC_BLEN (etype);
7126 /* if we have bitdisplacement then it fits */
7127 /* into this byte completely or if length is */
7128 /* less than a byte */
7129 if ((shCnt = SPEC_BSTR (etype)) ||
7130 (SPEC_BLEN (etype) <= 8))
7133 /* shift right acc */
7136 emitcode ("anl", "a,#0x%02x",
7137 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7138 aopPut (AOP (result), "a", offset++);
7142 /* bit field did not fit in a byte */
7143 aopPut (AOP (result), "a", offset++);
7152 emitcode ("inc", "%s", rname);
7153 emitcode ("mov", "a,@%s", rname);
7157 emitcode ("inc", "%s", rname);
7158 emitcode ("movx", "a,@%s", rname);
7162 emitcode ("inc", "dptr");
7163 emitcode ("movx", "a,@dptr");
7167 emitcode ("clr", "a");
7168 emitcode ("inc", "dptr");
7169 emitcode ("movc", "a,@a+dptr");
7173 emitcode ("inc", "dptr");
7174 emitcode ("lcall", "__gptrget");
7179 /* if we are done */
7183 aopPut (AOP (result), "a", offset++);
7189 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7191 aopPut (AOP (result), "a", offset++);
7199 aopPut (AOP (result), zero, offset++);
7205 /*-----------------------------------------------------------------*/
7206 /* genDataPointerGet - generates code when ptr offset is known */
7207 /*-----------------------------------------------------------------*/
7209 genDataPointerGet (operand * left,
7215 int size, offset = 0;
7217 D(emitcode ("; genDataPointerGet",""));
7219 aopOp (result, ic, TRUE);
7221 /* get the string representation of the name */
7222 l = aopGet (AOP (left), 0, FALSE, TRUE);
7223 size = AOP_SIZE (result);
7227 sprintf (buffer, "(%s + %d)", l + 1, offset);
7229 sprintf (buffer, "%s", l + 1);
7230 aopPut (AOP (result), buffer, offset++);
7233 freeAsmop (left, NULL, ic, TRUE);
7234 freeAsmop (result, NULL, ic, TRUE);
7237 /*-----------------------------------------------------------------*/
7238 /* genNearPointerGet - emitcode for near pointer fetch */
7239 /*-----------------------------------------------------------------*/
7241 genNearPointerGet (operand * left,
7249 sym_link *rtype, *retype;
7250 sym_link *ltype = operandType (left);
7253 D(emitcode ("; genNearPointerGet",""));
7255 rtype = operandType (result);
7256 retype = getSpec (rtype);
7258 aopOp (left, ic, FALSE);
7260 /* if left is rematerialisable and
7261 result is not bit variable type and
7262 the left is pointer to data space i.e
7263 lower 128 bytes of space */
7264 if (AOP_TYPE (left) == AOP_IMMD &&
7265 !IS_BITVAR (retype) &&
7266 DCL_TYPE (ltype) == POINTER)
7268 genDataPointerGet (left, result, ic);
7272 /* if the value is already in a pointer register
7273 then don't need anything more */
7274 if (!AOP_INPREG (AOP (left)))
7276 /* otherwise get a free pointer register */
7278 preg = getFreePtr (ic, &aop, FALSE);
7279 emitcode ("mov", "%s,%s",
7281 aopGet (AOP (left), 0, FALSE, TRUE));
7285 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7287 //aopOp (result, ic, FALSE);
7288 aopOp (result, ic, result?TRUE:FALSE);
7290 /* if bitfield then unpack the bits */
7291 if (IS_BITVAR (retype))
7292 genUnpackBits (result, rname, POINTER);
7295 /* we have can just get the values */
7296 int size = AOP_SIZE (result);
7301 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7304 emitcode ("mov", "a,@%s", rname);
7305 aopPut (AOP (result), "a", offset);
7309 sprintf (buffer, "@%s", rname);
7310 aopPut (AOP (result), buffer, offset);
7314 emitcode ("inc", "%s", rname);
7318 /* now some housekeeping stuff */
7319 if (aop) /* we had to allocate for this iCode */
7321 if (pi) { /* post increment present */
7322 aopPut(AOP ( left ),rname,0);
7324 freeAsmop (NULL, aop, ic, TRUE);
7328 /* we did not allocate which means left
7329 already in a pointer register, then
7330 if size > 0 && this could be used again
7331 we have to point it back to where it
7333 if ((AOP_SIZE (result) > 1 &&
7334 !OP_SYMBOL (left)->remat &&
7335 (OP_SYMBOL (left)->liveTo > ic->seq ||
7339 int size = AOP_SIZE (result) - 1;
7341 emitcode ("dec", "%s", rname);
7346 freeAsmop (left, NULL, ic, TRUE);
7347 freeAsmop (result, NULL, ic, TRUE);
7348 if (pi) pi->generated = 1;
7351 /*-----------------------------------------------------------------*/
7352 /* genPagedPointerGet - emitcode for paged pointer fetch */
7353 /*-----------------------------------------------------------------*/
7355 genPagedPointerGet (operand * left,
7363 sym_link *rtype, *retype;
7365 D(emitcode ("; genPagedPointerGet",""));
7367 rtype = operandType (result);
7368 retype = getSpec (rtype);
7370 aopOp (left, ic, FALSE);
7372 /* if the value is already in a pointer register
7373 then don't need anything more */
7374 if (!AOP_INPREG (AOP (left)))
7376 /* otherwise get a free pointer register */
7378 preg = getFreePtr (ic, &aop, FALSE);
7379 emitcode ("mov", "%s,%s",
7381 aopGet (AOP (left), 0, FALSE, TRUE));
7385 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7387 aopOp (result, ic, FALSE);
7389 /* if bitfield then unpack the bits */
7390 if (IS_BITVAR (retype))
7391 genUnpackBits (result, rname, PPOINTER);
7394 /* we have can just get the values */
7395 int size = AOP_SIZE (result);
7401 emitcode ("movx", "a,@%s", rname);
7402 aopPut (AOP (result), "a", offset);
7407 emitcode ("inc", "%s", rname);
7411 /* now some housekeeping stuff */
7412 if (aop) /* we had to allocate for this iCode */
7414 if (pi) aopPut ( AOP (left), rname, 0);
7415 freeAsmop (NULL, aop, ic, TRUE);
7419 /* we did not allocate which means left
7420 already in a pointer register, then
7421 if size > 0 && this could be used again
7422 we have to point it back to where it
7424 if ((AOP_SIZE (result) > 1 &&
7425 !OP_SYMBOL (left)->remat &&
7426 (OP_SYMBOL (left)->liveTo > ic->seq ||
7430 int size = AOP_SIZE (result) - 1;
7432 emitcode ("dec", "%s", rname);
7437 freeAsmop (left, NULL, ic, TRUE);
7438 freeAsmop (result, NULL, ic, TRUE);
7439 if (pi) pi->generated = 1;
7443 /*-----------------------------------------------------------------*/
7444 /* genFarPointerGet - gget value from far space */
7445 /*-----------------------------------------------------------------*/
7447 genFarPointerGet (operand * left,
7448 operand * result, iCode * ic, iCode * pi)
7451 sym_link *retype = getSpec (operandType (result));
7453 D(emitcode ("; genFarPointerGet",""));
7455 aopOp (left, ic, FALSE);
7457 /* if the operand is already in dptr
7458 then we do nothing else we move the value to dptr */
7459 if (AOP_TYPE (left) != AOP_STR)
7461 /* if this is remateriazable */
7462 if (AOP_TYPE (left) == AOP_IMMD)
7463 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7465 { /* we need to get it byte by byte */
7466 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7467 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7470 /* so dptr know contains the address */
7471 aopOp (result, ic, FALSE);
7473 /* if bit then unpack */
7474 if (IS_BITVAR (retype))
7475 genUnpackBits (result, "dptr", FPOINTER);
7478 size = AOP_SIZE (result);
7483 emitcode ("movx", "a,@dptr");
7484 aopPut (AOP (result), "a", offset++);
7486 emitcode ("inc", "dptr");
7490 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7491 aopPut ( AOP (left), "dpl", 0);
7492 aopPut ( AOP (left), "dph", 1);
7495 freeAsmop (left, NULL, ic, TRUE);
7496 freeAsmop (result, NULL, ic, TRUE);
7499 /*-----------------------------------------------------------------*/
7500 /* genCodePointerGet - gget value from code space */
7501 /*-----------------------------------------------------------------*/
7503 genCodePointerGet (operand * left,
7504 operand * result, iCode * ic, iCode *pi)
7507 sym_link *retype = getSpec (operandType (result));
7509 D(emitcode ("; genCodePointerGet",""));
7511 aopOp (left, ic, FALSE);
7513 /* if the operand is already in dptr
7514 then we do nothing else we move the value to dptr */
7515 if (AOP_TYPE (left) != AOP_STR)
7517 /* if this is remateriazable */
7518 if (AOP_TYPE (left) == AOP_IMMD)
7519 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7521 { /* we need to get it byte by byte */
7522 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7523 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7526 /* so dptr know contains the address */
7527 aopOp (result, ic, FALSE);
7529 /* if bit then unpack */
7530 if (IS_BITVAR (retype))
7531 genUnpackBits (result, "dptr", CPOINTER);
7534 size = AOP_SIZE (result);
7541 emitcode ("clr", "a");
7542 emitcode ("movc", "a,@a+dptr");
7543 aopPut (AOP (result), "a", offset++);
7544 emitcode ("inc", "dptr");
7548 emitcode ("mov", "a,#0x%02x", offset);
7549 emitcode ("movc", "a,@a+dptr");
7550 aopPut (AOP (result), "a", offset++);
7555 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7556 aopPut ( AOP (left), "dpl", 0);
7557 aopPut ( AOP (left), "dph", 1);
7560 freeAsmop (left, NULL, ic, TRUE);
7561 freeAsmop (result, NULL, ic, TRUE);
7564 /*-----------------------------------------------------------------*/
7565 /* genGenPointerGet - gget value from generic pointer space */
7566 /*-----------------------------------------------------------------*/
7568 genGenPointerGet (operand * left,
7569 operand * result, iCode * ic, iCode *pi)
7572 sym_link *retype = getSpec (operandType (result));
7574 D(emitcode ("; genGenPointerGet",""));
7576 aopOp (left, ic, FALSE);
7578 /* if the operand is already in dptr
7579 then we do nothing else we move the value to dptr */
7580 if (AOP_TYPE (left) != AOP_STR)
7582 /* if this is remateriazable */
7583 if (AOP_TYPE (left) == AOP_IMMD)
7585 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7586 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7587 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7589 emitcode ("mov", "b,#%d", pointerCode (retype));
7592 { /* we need to get it byte by byte */
7593 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7594 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7595 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7598 /* so dptr know contains the address */
7599 aopOp (result, ic, FALSE);
7601 /* if bit then unpack */
7602 if (IS_BITVAR (retype))
7603 genUnpackBits (result, "dptr", GPOINTER);
7606 size = AOP_SIZE (result);
7611 emitcode ("lcall", "__gptrget");
7612 aopPut (AOP (result), "a", offset++);
7614 emitcode ("inc", "dptr");
7618 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7619 aopPut ( AOP (left), "dpl", 0);
7620 aopPut ( AOP (left), "dph", 1);
7621 aopPut ( AOP (left), "b", 2);
7624 freeAsmop (left, NULL, ic, TRUE);
7625 freeAsmop (result, NULL, ic, TRUE);
7628 /*-----------------------------------------------------------------*/
7629 /* genPointerGet - generate code for pointer get */
7630 /*-----------------------------------------------------------------*/
7632 genPointerGet (iCode * ic, iCode *pi)
7634 operand *left, *result;
7635 sym_link *type, *etype;
7638 D(emitcode ("; genPointerGet",""));
7640 left = IC_LEFT (ic);
7641 result = IC_RESULT (ic);
7643 /* depending on the type of pointer we need to
7644 move it to the correct pointer register */
7645 type = operandType (left);
7646 etype = getSpec (type);
7647 /* if left is of type of pointer then it is simple */
7648 if (IS_PTR (type) && !IS_FUNC (type->next))
7649 p_type = DCL_TYPE (type);
7652 /* we have to go by the storage class */
7653 p_type = PTR_TYPE (SPEC_OCLS (etype));
7656 /* special case when cast remat */
7657 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7658 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7659 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7660 type = operandType (left);
7661 p_type = DCL_TYPE (type);
7663 /* now that we have the pointer type we assign
7664 the pointer values */
7670 genNearPointerGet (left, result, ic, pi);
7674 genPagedPointerGet (left, result, ic, pi);
7678 genFarPointerGet (left, result, ic, pi);
7682 genCodePointerGet (left, result, ic, pi);
7686 genGenPointerGet (left, result, ic, pi);
7692 /*-----------------------------------------------------------------*/
7693 /* genPackBits - generates code for packed bit storage */
7694 /*-----------------------------------------------------------------*/
7696 genPackBits (sym_link * etype,
7698 char *rname, int p_type)
7706 D(emitcode ("; genPackBits",""));
7708 blen = SPEC_BLEN (etype);
7709 bstr = SPEC_BSTR (etype);
7711 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7714 /* if the bit lenth is less than or */
7715 /* it exactly fits a byte then */
7716 if (SPEC_BLEN (etype) <= 8)
7718 shCount = SPEC_BSTR (etype);
7720 /* shift left acc */
7723 if (SPEC_BLEN (etype) < 8)
7724 { /* if smaller than a byte */
7730 emitcode ("mov", "b,a");
7731 emitcode ("mov", "a,@%s", rname);
7735 emitcode ("mov", "b,a");
7736 emitcode ("movx", "a,@dptr");
7740 emitcode ("push", "b");
7741 emitcode ("push", "acc");
7742 emitcode ("lcall", "__gptrget");
7743 emitcode ("pop", "b");
7747 emitcode ("anl", "a,#0x%02x", (unsigned char)
7748 ((unsigned char) (0xFF << (blen + bstr)) |
7749 (unsigned char) (0xFF >> (8 - bstr))));
7750 emitcode ("orl", "a,b");
7751 if (p_type == GPOINTER)
7752 emitcode ("pop", "b");
7759 emitcode ("mov", "@%s,a", rname);
7763 emitcode ("movx", "@dptr,a");
7767 emitcode ("lcall", "__gptrput");
7772 if (SPEC_BLEN (etype) <= 8)
7775 emitcode ("inc", "%s", rname);
7776 rLen = SPEC_BLEN (etype);
7778 /* now generate for lengths greater than one byte */
7782 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7794 emitcode ("mov", "@%s,a", rname);
7797 emitcode ("mov", "@%s,%s", rname, l);
7802 emitcode ("movx", "@dptr,a");
7807 emitcode ("lcall", "__gptrput");
7810 emitcode ("inc", "%s", rname);
7815 /* last last was not complete */
7818 /* save the byte & read byte */
7822 emitcode ("mov", "b,a");
7823 emitcode ("mov", "a,@%s", rname);
7827 emitcode ("mov", "b,a");
7828 emitcode ("movx", "a,@dptr");
7832 emitcode ("push", "b");
7833 emitcode ("push", "acc");
7834 emitcode ("lcall", "__gptrget");
7835 emitcode ("pop", "b");
7839 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7840 emitcode ("orl", "a,b");
7843 if (p_type == GPOINTER)
7844 emitcode ("pop", "b");
7850 emitcode ("mov", "@%s,a", rname);
7854 emitcode ("movx", "@dptr,a");
7858 emitcode ("lcall", "__gptrput");
7862 /*-----------------------------------------------------------------*/
7863 /* genDataPointerSet - remat pointer to data space */
7864 /*-----------------------------------------------------------------*/
7866 genDataPointerSet (operand * right,
7870 int size, offset = 0;
7871 char *l, buffer[256];
7873 D(emitcode ("; genDataPointerSet",""));
7875 aopOp (right, ic, FALSE);
7877 l = aopGet (AOP (result), 0, FALSE, TRUE);
7878 size = AOP_SIZE (right);
7882 sprintf (buffer, "(%s + %d)", l + 1, offset);
7884 sprintf (buffer, "%s", l + 1);
7885 emitcode ("mov", "%s,%s", buffer,
7886 aopGet (AOP (right), offset++, FALSE, FALSE));
7889 freeAsmop (right, NULL, ic, TRUE);
7890 freeAsmop (result, NULL, ic, TRUE);
7893 /*-----------------------------------------------------------------*/
7894 /* genNearPointerSet - emitcode for near pointer put */
7895 /*-----------------------------------------------------------------*/
7897 genNearPointerSet (operand * right,
7905 sym_link *retype, *letype;
7906 sym_link *ptype = operandType (result);
7908 D(emitcode ("; genNearPointerSet",""));
7910 retype = getSpec (operandType (right));
7911 letype = getSpec (ptype);
7912 aopOp (result, ic, FALSE);
7914 /* if the result is rematerializable &
7915 in data space & not a bit variable */
7916 if (AOP_TYPE (result) == AOP_IMMD &&
7917 DCL_TYPE (ptype) == POINTER &&
7918 !IS_BITVAR (retype) &&
7919 !IS_BITVAR (letype))
7921 genDataPointerSet (right, result, ic);
7925 /* if the value is already in a pointer register
7926 then don't need anything more */
7927 if (!AOP_INPREG (AOP (result)))
7930 //AOP_TYPE (result) == AOP_STK
7934 // Aha, it is a pointer, just in disguise.
7935 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7938 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7939 __FILE__, __LINE__);
7944 rname++; // skip the '@'.
7949 /* otherwise get a free pointer register */
7951 preg = getFreePtr (ic, &aop, FALSE);
7952 emitcode ("mov", "%s,%s",
7954 aopGet (AOP (result), 0, FALSE, TRUE));
7960 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7963 aopOp (right, ic, FALSE);
7965 /* if bitfield then unpack the bits */
7966 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7967 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7970 /* we have can just get the values */
7971 int size = AOP_SIZE (right);
7976 l = aopGet (AOP (right), offset, FALSE, TRUE);
7980 emitcode ("mov", "@%s,a", rname);
7983 emitcode ("mov", "@%s,%s", rname, l);
7985 emitcode ("inc", "%s", rname);
7990 /* now some housekeeping stuff */
7991 if (aop) /* we had to allocate for this iCode */
7993 if (pi) aopPut (AOP (result),rname,0);
7994 freeAsmop (NULL, aop, ic, TRUE);
7998 /* we did not allocate which means left
7999 already in a pointer register, then
8000 if size > 0 && this could be used again
8001 we have to point it back to where it
8003 if ((AOP_SIZE (right) > 1 &&
8004 !OP_SYMBOL (result)->remat &&
8005 (OP_SYMBOL (result)->liveTo > ic->seq ||
8009 int size = AOP_SIZE (right) - 1;
8011 emitcode ("dec", "%s", rname);
8016 if (pi) pi->generated = 1;
8017 freeAsmop (result, NULL, ic, TRUE);
8018 freeAsmop (right, NULL, ic, TRUE);
8021 /*-----------------------------------------------------------------*/
8022 /* genPagedPointerSet - emitcode for Paged pointer put */
8023 /*-----------------------------------------------------------------*/
8025 genPagedPointerSet (operand * right,
8033 sym_link *retype, *letype;
8035 D(emitcode ("; genPagedPointerSet",""));
8037 retype = getSpec (operandType (right));
8038 letype = getSpec (operandType (result));
8040 aopOp (result, ic, FALSE);
8042 /* if the value is already in a pointer register
8043 then don't need anything more */
8044 if (!AOP_INPREG (AOP (result)))
8046 /* otherwise get a free pointer register */
8048 preg = getFreePtr (ic, &aop, FALSE);
8049 emitcode ("mov", "%s,%s",
8051 aopGet (AOP (result), 0, FALSE, TRUE));
8055 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8057 aopOp (right, ic, FALSE);
8059 /* if bitfield then unpack the bits */
8060 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8061 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8064 /* we have can just get the values */
8065 int size = AOP_SIZE (right);
8070 l = aopGet (AOP (right), offset, FALSE, TRUE);
8073 emitcode ("movx", "@%s,a", rname);
8076 emitcode ("inc", "%s", rname);
8082 /* now some housekeeping stuff */
8083 if (aop) /* we had to allocate for this iCode */
8085 if (pi) aopPut (AOP (result),rname,0);
8086 freeAsmop (NULL, aop, ic, TRUE);
8090 /* we did not allocate which means left
8091 already in a pointer register, then
8092 if size > 0 && this could be used again
8093 we have to point it back to where it
8095 if (AOP_SIZE (right) > 1 &&
8096 !OP_SYMBOL (result)->remat &&
8097 (OP_SYMBOL (result)->liveTo > ic->seq ||
8100 int size = AOP_SIZE (right) - 1;
8102 emitcode ("dec", "%s", rname);
8107 if (pi) pi->generated = 1;
8108 freeAsmop (result, NULL, ic, TRUE);
8109 freeAsmop (right, NULL, ic, TRUE);
8114 /*-----------------------------------------------------------------*/
8115 /* genFarPointerSet - set value from far space */
8116 /*-----------------------------------------------------------------*/
8118 genFarPointerSet (operand * right,
8119 operand * result, iCode * ic, iCode * pi)
8122 sym_link *retype = getSpec (operandType (right));
8123 sym_link *letype = getSpec (operandType (result));
8125 D(emitcode ("; genFarPointerSet",""));
8127 aopOp (result, ic, FALSE);
8129 /* if the operand is already in dptr
8130 then we do nothing else we move the value to dptr */
8131 if (AOP_TYPE (result) != AOP_STR)
8133 /* if this is remateriazable */
8134 if (AOP_TYPE (result) == AOP_IMMD)
8135 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8137 { /* we need to get it byte by byte */
8138 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8139 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8142 /* so dptr know contains the address */
8143 aopOp (right, ic, FALSE);
8145 /* if bit then unpack */
8146 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8147 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8150 size = AOP_SIZE (right);
8155 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8157 emitcode ("movx", "@dptr,a");
8159 emitcode ("inc", "dptr");
8162 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8163 aopPut (AOP(result),"dpl",0);
8164 aopPut (AOP(result),"dph",1);
8167 freeAsmop (result, NULL, ic, TRUE);
8168 freeAsmop (right, NULL, ic, TRUE);
8171 /*-----------------------------------------------------------------*/
8172 /* genGenPointerSet - set value from generic pointer space */
8173 /*-----------------------------------------------------------------*/
8175 genGenPointerSet (operand * right,
8176 operand * result, iCode * ic, iCode * pi)
8179 sym_link *retype = getSpec (operandType (right));
8180 sym_link *letype = getSpec (operandType (result));
8182 D(emitcode ("; genGenPointerSet",""));
8184 aopOp (result, ic, FALSE);
8186 /* if the operand is already in dptr
8187 then we do nothing else we move the value to dptr */
8188 if (AOP_TYPE (result) != AOP_STR)
8190 /* if this is remateriazable */
8191 if (AOP_TYPE (result) == AOP_IMMD)
8193 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8194 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8195 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8197 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8200 { /* we need to get it byte by byte */
8201 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8202 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8203 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8206 /* so dptr know contains the address */
8207 aopOp (right, ic, FALSE);
8209 /* if bit then unpack */
8210 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8211 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8214 size = AOP_SIZE (right);
8219 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8221 emitcode ("lcall", "__gptrput");
8223 emitcode ("inc", "dptr");
8227 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8228 aopPut (AOP(result),"dpl",0);
8229 aopPut (AOP(result),"dph",1);
8230 aopPut (AOP(result),"b",2);
8233 freeAsmop (result, NULL, ic, TRUE);
8234 freeAsmop (right, NULL, ic, TRUE);
8237 /*-----------------------------------------------------------------*/
8238 /* genPointerSet - stores the value into a pointer location */
8239 /*-----------------------------------------------------------------*/
8241 genPointerSet (iCode * ic, iCode *pi)
8243 operand *right, *result;
8244 sym_link *type, *etype;
8247 D(emitcode ("; genPointerSet",""));
8249 right = IC_RIGHT (ic);
8250 result = IC_RESULT (ic);
8252 /* depending on the type of pointer we need to
8253 move it to the correct pointer register */
8254 type = operandType (result);
8255 etype = getSpec (type);
8256 /* if left is of type of pointer then it is simple */
8257 if (IS_PTR (type) && !IS_FUNC (type->next))
8259 p_type = DCL_TYPE (type);
8263 /* we have to go by the storage class */
8264 p_type = PTR_TYPE (SPEC_OCLS (etype));
8267 /* special case when cast remat */
8268 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8269 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8270 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8271 type = operandType (result);
8272 p_type = DCL_TYPE (type);
8274 /* now that we have the pointer type we assign
8275 the pointer values */
8281 genNearPointerSet (right, result, ic, pi);
8285 genPagedPointerSet (right, result, ic, pi);
8289 genFarPointerSet (right, result, ic, pi);
8293 genGenPointerSet (right, result, ic, pi);
8297 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8298 "genPointerSet: illegal pointer type");
8303 /*-----------------------------------------------------------------*/
8304 /* genIfx - generate code for Ifx statement */
8305 /*-----------------------------------------------------------------*/
8307 genIfx (iCode * ic, iCode * popIc)
8309 operand *cond = IC_COND (ic);
8312 D(emitcode ("; genIfx",""));
8314 aopOp (cond, ic, FALSE);
8316 /* get the value into acc */
8317 if (AOP_TYPE (cond) != AOP_CRY)
8321 /* the result is now in the accumulator */
8322 freeAsmop (cond, NULL, ic, TRUE);
8324 /* if there was something to be popped then do it */
8328 /* if the condition is a bit variable */
8329 if (isbit && IS_ITEMP (cond) &&
8331 genIfxJump (ic, SPIL_LOC (cond)->rname);
8332 else if (isbit && !IS_ITEMP (cond))
8333 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8335 genIfxJump (ic, "a");
8340 /*-----------------------------------------------------------------*/
8341 /* genAddrOf - generates code for address of */
8342 /*-----------------------------------------------------------------*/
8344 genAddrOf (iCode * ic)
8346 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8349 D(emitcode ("; genAddrOf",""));
8351 aopOp (IC_RESULT (ic), ic, FALSE);
8353 /* if the operand is on the stack then we
8354 need to get the stack offset of this
8358 /* if it has an offset then we need to compute
8362 emitcode ("mov", "a,_bp");
8363 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8364 ((char) (sym->stack - _G.nRegsSaved)) :
8365 ((char) sym->stack)) & 0xff);
8366 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8370 /* we can just move _bp */
8371 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8373 /* fill the result with zero */
8374 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8379 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8385 /* object not on stack then we need the name */
8386 size = AOP_SIZE (IC_RESULT (ic));
8391 char s[SDCC_NAME_MAX];
8393 sprintf (s, "#(%s >> %d)",
8397 sprintf (s, "#%s", sym->rname);
8398 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8402 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8406 /*-----------------------------------------------------------------*/
8407 /* genFarFarAssign - assignment when both are in far space */
8408 /*-----------------------------------------------------------------*/
8410 genFarFarAssign (operand * result, operand * right, iCode * ic)
8412 int size = AOP_SIZE (right);
8416 D(emitcode ("; genFarFarAssign",""));
8418 /* first push the right side on to the stack */
8421 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8423 emitcode ("push", "acc");
8426 freeAsmop (right, NULL, ic, FALSE);
8427 /* now assign DPTR to result */
8428 aopOp (result, ic, FALSE);
8429 size = AOP_SIZE (result);
8432 emitcode ("pop", "acc");
8433 aopPut (AOP (result), "a", --offset);
8435 freeAsmop (result, NULL, ic, FALSE);
8439 /*-----------------------------------------------------------------*/
8440 /* genAssign - generate code for assignment */
8441 /*-----------------------------------------------------------------*/
8443 genAssign (iCode * ic)
8445 operand *result, *right;
8447 unsigned long lit = 0L;
8449 D(emitcode("; genAssign",""));
8451 result = IC_RESULT (ic);
8452 right = IC_RIGHT (ic);
8454 /* if they are the same */
8455 if (operandsEqu (result, right)) {
8459 aopOp (right, ic, FALSE);
8461 /* special case both in far space */
8462 if (AOP_TYPE (right) == AOP_DPTR &&
8463 IS_TRUE_SYMOP (result) &&
8464 isOperandInFarSpace (result))
8467 genFarFarAssign (result, right, ic);
8471 aopOp (result, ic, TRUE);
8473 /* if they are the same registers */
8474 if (sameRegs (AOP (right), AOP (result)))
8477 /* if the result is a bit */
8478 if (AOP_TYPE (result) == AOP_CRY)
8481 /* if the right size is a literal then
8482 we know what the value is */
8483 if (AOP_TYPE (right) == AOP_LIT)
8485 if (((int) operandLitValue (right)))
8486 aopPut (AOP (result), one, 0);
8488 aopPut (AOP (result), zero, 0);
8492 /* the right is also a bit variable */
8493 if (AOP_TYPE (right) == AOP_CRY)
8495 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8496 aopPut (AOP (result), "c", 0);
8502 aopPut (AOP (result), "a", 0);
8506 /* bit variables done */
8508 size = AOP_SIZE (result);
8510 if (AOP_TYPE (right) == AOP_LIT)
8511 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8513 (AOP_TYPE (result) != AOP_REG) &&
8514 (AOP_TYPE (right) == AOP_LIT) &&
8515 !IS_FLOAT (operandType (right)) &&
8518 emitcode ("clr", "a");
8521 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8522 aopPut (AOP (result), "a", size);
8524 aopPut (AOP (result),
8525 aopGet (AOP (right), size, FALSE, FALSE),
8533 aopPut (AOP (result),
8534 aopGet (AOP (right), offset, FALSE, FALSE),
8541 freeAsmop (right, NULL, ic, TRUE);
8542 freeAsmop (result, NULL, ic, TRUE);
8545 /*-----------------------------------------------------------------*/
8546 /* genJumpTab - genrates code for jump table */
8547 /*-----------------------------------------------------------------*/
8549 genJumpTab (iCode * ic)
8554 D(emitcode ("; genJumpTab",""));
8556 aopOp (IC_JTCOND (ic), ic, FALSE);
8557 /* get the condition into accumulator */
8558 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8560 /* multiply by three */
8561 emitcode ("add", "a,acc");
8562 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8563 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8565 jtab = newiTempLabel (NULL);
8566 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8567 emitcode ("jmp", "@a+dptr");
8568 emitcode ("", "%05d$:", jtab->key + 100);
8569 /* now generate the jump labels */
8570 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8571 jtab = setNextItem (IC_JTLABELS (ic)))
8572 emitcode ("ljmp", "%05d$", jtab->key + 100);
8576 /*-----------------------------------------------------------------*/
8577 /* genCast - gen code for casting */
8578 /*-----------------------------------------------------------------*/
8580 genCast (iCode * ic)
8582 operand *result = IC_RESULT (ic);
8583 sym_link *ctype = operandType (IC_LEFT (ic));
8584 sym_link *rtype = operandType (IC_RIGHT (ic));
8585 operand *right = IC_RIGHT (ic);
8588 D(emitcode("; genCast",""));
8590 /* if they are equivalent then do nothing */
8591 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8594 aopOp (right, ic, FALSE);
8595 aopOp (result, ic, FALSE);
8597 /* if the result is a bit */
8598 if (IS_BITVAR(OP_SYMBOL(result)->type))
8600 /* if the right size is a literal then
8601 we know what the value is */
8602 if (AOP_TYPE (right) == AOP_LIT)
8604 if (((int) operandLitValue (right)))
8605 aopPut (AOP (result), one, 0);
8607 aopPut (AOP (result), zero, 0);
8612 /* the right is also a bit variable */
8613 if (AOP_TYPE (right) == AOP_CRY)
8615 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8616 aopPut (AOP (result), "c", 0);
8622 aopPut (AOP (result), "a", 0);
8626 /* if they are the same size : or less */
8627 if (AOP_SIZE (result) <= AOP_SIZE (right))
8630 /* if they are in the same place */
8631 if (sameRegs (AOP (right), AOP (result)))
8634 /* if they in different places then copy */
8635 size = AOP_SIZE (result);
8639 aopPut (AOP (result),
8640 aopGet (AOP (right), offset, FALSE, FALSE),
8648 /* if the result is of type pointer */
8653 sym_link *type = operandType (right);
8654 sym_link *etype = getSpec (type);
8656 /* pointer to generic pointer */
8657 if (IS_GENPTR (ctype))
8660 p_type = DCL_TYPE (type);
8663 if (SPEC_SCLS(etype)==S_REGISTER) {
8664 // let's assume it is a generic pointer
8667 /* we have to go by the storage class */
8668 p_type = PTR_TYPE (SPEC_OCLS (etype));
8672 /* the first two bytes are known */
8673 size = GPTRSIZE - 1;
8677 aopPut (AOP (result),
8678 aopGet (AOP (right), offset, FALSE, FALSE),
8682 /* the last byte depending on type */
8684 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8689 // pointerTypeToGPByte will have bitched.
8693 sprintf(gpValStr, "#0x%d", gpVal);
8694 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8699 /* just copy the pointers */
8700 size = AOP_SIZE (result);
8704 aopPut (AOP (result),
8705 aopGet (AOP (right), offset, FALSE, FALSE),
8712 /* so we now know that the size of destination is greater
8713 than the size of the source */
8714 /* we move to result for the size of source */
8715 size = AOP_SIZE (right);
8719 aopPut (AOP (result),
8720 aopGet (AOP (right), offset, FALSE, FALSE),
8725 /* now depending on the sign of the source && destination */
8726 size = AOP_SIZE (result) - AOP_SIZE (right);
8727 /* if unsigned or not an integral type */
8728 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8731 aopPut (AOP (result), zero, offset++);
8735 /* we need to extend the sign :{ */
8736 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8739 emitcode ("rlc", "a");
8740 emitcode ("subb", "a,acc");
8742 aopPut (AOP (result), "a", offset++);
8745 /* we are done hurray !!!! */
8748 freeAsmop (right, NULL, ic, TRUE);
8749 freeAsmop (result, NULL, ic, TRUE);
8753 /*-----------------------------------------------------------------*/
8754 /* genDjnz - generate decrement & jump if not zero instrucion */
8755 /*-----------------------------------------------------------------*/
8757 genDjnz (iCode * ic, iCode * ifx)
8763 D(emitcode ("; genDjnz",""));
8765 /* if the if condition has a false label
8766 then we cannot save */
8770 /* if the minus is not of the form
8772 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8773 !IS_OP_LITERAL (IC_RIGHT (ic)))
8776 if (operandLitValue (IC_RIGHT (ic)) != 1)
8779 /* if the size of this greater than one then no
8781 if (getSize (operandType (IC_RESULT (ic))) > 1)
8784 /* otherwise we can save BIG */
8785 lbl = newiTempLabel (NULL);
8786 lbl1 = newiTempLabel (NULL);
8788 aopOp (IC_RESULT (ic), ic, FALSE);
8790 if (AOP_NEEDSACC(IC_RESULT(ic)))
8792 /* If the result is accessed indirectly via
8793 * the accumulator, we must explicitly write
8794 * it back after the decrement.
8796 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8798 if (strcmp(rByte, "a"))
8800 /* Something is hopelessly wrong */
8801 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8802 __FILE__, __LINE__);
8803 /* We can just give up; the generated code will be inefficient,
8806 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8809 emitcode ("dec", "%s", rByte);
8810 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8811 emitcode ("jnz", "%05d$", lbl->key + 100);
8813 else if (IS_AOP_PREG (IC_RESULT (ic)))
8815 emitcode ("dec", "%s",
8816 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8817 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8818 emitcode ("jnz", "%05d$", lbl->key + 100);
8822 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8825 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8826 emitcode ("", "%05d$:", lbl->key + 100);
8827 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8828 emitcode ("", "%05d$:", lbl1->key + 100);
8830 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8835 /*-----------------------------------------------------------------*/
8836 /* genReceive - generate code for a receive iCode */
8837 /*-----------------------------------------------------------------*/
8839 genReceive (iCode * ic)
8841 int size = getSize (operandType (IC_RESULT (ic)));
8843 D(emitcode ("; genReceive",""));
8845 if (ic->argreg == 1) { /* first parameter */
8846 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8847 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8848 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8850 offset = fReturnSizeMCS51 - size;
8852 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8853 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8856 aopOp (IC_RESULT (ic), ic, FALSE);
8857 size = AOP_SIZE (IC_RESULT (ic));
8860 emitcode ("pop", "acc");
8861 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8866 aopOp (IC_RESULT (ic), ic, FALSE);
8868 assignResultValue (IC_RESULT (ic));
8870 } else { /* second receive onwards */
8872 aopOp (IC_RESULT (ic), ic, FALSE);
8873 rb1off = ic->argreg;
8875 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8878 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8881 /*-----------------------------------------------------------------*/
8882 /* gen51Code - generate code for 8051 based controllers */
8883 /*-----------------------------------------------------------------*/
8885 gen51Code (iCode * lic)
8890 lineHead = lineCurr = NULL;
8892 /* print the allocation information */
8893 if (allocInfo && currFunc)
8894 printAllocInfo (currFunc, codeOutFile);
8895 /* if debug information required */
8896 if (options.debug && currFunc)
8898 debugFile->writeFunction(currFunc);
8900 if (IS_STATIC (currFunc->etype))
8901 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8903 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8906 /* stack pointer name */
8907 if (options.useXstack)
8913 for (ic = lic; ic; ic = ic->next)
8916 if (ic->lineno && cln != ic->lineno)
8921 emitcode ("", "C$%s$%d$%d$%d ==.",
8922 FileBaseName (ic->filename), ic->lineno,
8923 ic->level, ic->block);
8926 if (!options.noCcodeInAsm) {
8927 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8928 printCLine(ic->filename, ic->lineno));
8932 if (options.iCodeInAsm) {
8936 for (i=0; i<8; i++) {
8937 sprintf (®sInUse[i],
8938 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8941 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8943 /* if the result is marked as
8944 spilt and rematerializable or code for
8945 this has already been generated then
8947 if (resultRemat (ic) || ic->generated)
8950 /* depending on the operation */
8970 /* IPOP happens only when trying to restore a
8971 spilt live range, if there is an ifx statement
8972 following this pop then the if statement might
8973 be using some of the registers being popped which
8974 would destory the contents of the register so
8975 we need to check for this condition and handle it */
8977 ic->next->op == IFX &&
8978 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8979 genIfx (ic->next, ic);
8997 genEndFunction (ic);
9017 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9034 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9038 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9045 /* note these two are xlated by algebraic equivalence
9046 during parsing SDCC.y */
9047 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9048 "got '>=' or '<=' shouldn't have come here");
9052 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9064 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9068 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9072 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9099 case GET_VALUE_AT_ADDRESS:
9100 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9104 if (POINTER_SET (ic))
9105 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9131 addSet (&_G.sendSet, ic);
9140 /* now we are ready to call the
9141 peep hole optimizer */
9142 if (!options.nopeep)
9143 peepHole (&lineHead);
9145 /* now do the actual printing */
9146 printLine (lineHead, codeOutFile);