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;
4012 D(emitcode ("; genCmp",""));
4014 /* if left & right are bit variables */
4015 if (AOP_TYPE (left) == AOP_CRY &&
4016 AOP_TYPE (right) == AOP_CRY)
4018 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4019 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4023 /* subtract right from left if at the
4024 end the carry flag is set then we know that
4025 left is greater than right */
4026 size = max (AOP_SIZE (left), AOP_SIZE (right));
4028 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4029 if ((size == 1) && !sign &&
4030 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4032 symbol *lbl = newiTempLabel (NULL);
4033 emitcode ("cjne", "%s,%s,%05d$",
4034 aopGet (AOP (left), offset, FALSE, FALSE),
4035 aopGet (AOP (right), offset, FALSE, FALSE),
4037 emitcode ("", "%05d$:", lbl->key + 100);
4041 if (AOP_TYPE (right) == AOP_LIT)
4043 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4044 /* optimize if(x < 0) or if(x >= 0) */
4053 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4054 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4056 genIfxJump (ifx, "acc.7");
4060 emitcode ("rlc", "a");
4068 rightInB = aopGetUsesAcc(AOP (right), offset);
4070 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4071 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4072 if (sign && size == 0)
4074 emitcode ("xrl", "a,#0x80");
4075 if (AOP_TYPE (right) == AOP_LIT)
4077 unsigned long lit = (unsigned long)
4078 floatFromVal (AOP (right)->aopu.aop_lit);
4079 emitcode ("subb", "a,#0x%02x",
4080 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4085 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4086 emitcode ("xrl", "b,#0x80");
4087 emitcode ("subb", "a,b");
4093 emitcode ("subb", "a,b");
4095 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4103 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4104 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4105 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4111 /* if the result is used in the next
4112 ifx conditional branch then generate
4113 code a little differently */
4115 genIfxJump (ifx, "c");
4118 /* leave the result in acc */
4122 /*-----------------------------------------------------------------*/
4123 /* genCmpGt :- greater than comparison */
4124 /*-----------------------------------------------------------------*/
4126 genCmpGt (iCode * ic, iCode * ifx)
4128 operand *left, *right, *result;
4129 sym_link *letype, *retype;
4132 D(emitcode ("; genCmpGt",""));
4134 left = IC_LEFT (ic);
4135 right = IC_RIGHT (ic);
4136 result = IC_RESULT (ic);
4138 letype = getSpec (operandType (left));
4139 retype = getSpec (operandType (right));
4140 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4141 /* assign the amsops */
4142 aopOp (left, ic, FALSE);
4143 aopOp (right, ic, FALSE);
4144 aopOp (result, ic, TRUE);
4146 genCmp (right, left, result, ifx, sign,ic);
4148 freeAsmop (result, NULL, ic, TRUE);
4151 /*-----------------------------------------------------------------*/
4152 /* genCmpLt - less than comparisons */
4153 /*-----------------------------------------------------------------*/
4155 genCmpLt (iCode * ic, iCode * ifx)
4157 operand *left, *right, *result;
4158 sym_link *letype, *retype;
4161 D(emitcode ("; genCmpLt",""));
4163 left = IC_LEFT (ic);
4164 right = IC_RIGHT (ic);
4165 result = IC_RESULT (ic);
4167 letype = getSpec (operandType (left));
4168 retype = getSpec (operandType (right));
4169 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4171 /* assign the amsops */
4172 aopOp (left, ic, FALSE);
4173 aopOp (right, ic, FALSE);
4174 aopOp (result, ic, TRUE);
4176 genCmp (left, right, result, ifx, sign,ic);
4178 freeAsmop (result, NULL, ic, TRUE);
4181 /*-----------------------------------------------------------------*/
4182 /* gencjneshort - compare and jump if not equal */
4183 /*-----------------------------------------------------------------*/
4185 gencjneshort (operand * left, operand * right, symbol * lbl)
4187 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4189 unsigned long lit = 0L;
4191 /* if the left side is a literal or
4192 if the right is in a pointer register and left
4194 if ((AOP_TYPE (left) == AOP_LIT) ||
4195 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4201 if (AOP_TYPE (right) == AOP_LIT)
4202 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4204 /* if the right side is a literal then anything goes */
4205 if (AOP_TYPE (right) == AOP_LIT &&
4206 AOP_TYPE (left) != AOP_DIR &&
4207 AOP_TYPE (left) != AOP_IMMD)
4211 emitcode ("cjne", "%s,%s,%05d$",
4212 aopGet (AOP (left), offset, FALSE, FALSE),
4213 aopGet (AOP (right), offset, FALSE, FALSE),
4219 /* if the right side is in a register or in direct space or
4220 if the left is a pointer register & right is not */
4221 else if (AOP_TYPE (right) == AOP_REG ||
4222 AOP_TYPE (right) == AOP_DIR ||
4223 AOP_TYPE (right) == AOP_LIT ||
4224 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4225 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4229 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4230 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4231 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4232 emitcode ("jnz", "%05d$", lbl->key + 100);
4234 emitcode ("cjne", "a,%s,%05d$",
4235 aopGet (AOP (right), offset, FALSE, TRUE),
4242 /* right is a pointer reg need both a & b */
4245 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4246 if (strcmp (l, "b"))
4247 emitcode ("mov", "b,%s", l);
4248 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4249 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4255 /*-----------------------------------------------------------------*/
4256 /* gencjne - compare and jump if not equal */
4257 /*-----------------------------------------------------------------*/
4259 gencjne (operand * left, operand * right, symbol * lbl)
4261 symbol *tlbl = newiTempLabel (NULL);
4263 gencjneshort (left, right, lbl);
4265 emitcode ("mov", "a,%s", one);
4266 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4267 emitcode ("", "%05d$:", lbl->key + 100);
4268 emitcode ("clr", "a");
4269 emitcode ("", "%05d$:", tlbl->key + 100);
4272 /*-----------------------------------------------------------------*/
4273 /* genCmpEq - generates code for equal to */
4274 /*-----------------------------------------------------------------*/
4276 genCmpEq (iCode * ic, iCode * ifx)
4278 operand *left, *right, *result;
4280 D(emitcode ("; genCmpEq",""));
4282 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4283 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4284 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4286 /* if literal, literal on the right or
4287 if the right is in a pointer register and left
4289 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4290 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4292 operand *t = IC_RIGHT (ic);
4293 IC_RIGHT (ic) = IC_LEFT (ic);
4297 if (ifx && !AOP_SIZE (result))
4300 /* if they are both bit variables */
4301 if (AOP_TYPE (left) == AOP_CRY &&
4302 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4304 if (AOP_TYPE (right) == AOP_LIT)
4306 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4309 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4310 emitcode ("cpl", "c");
4314 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4318 emitcode ("clr", "c");
4320 /* AOP_TYPE(right) == AOP_CRY */
4324 symbol *lbl = newiTempLabel (NULL);
4325 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4326 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4327 emitcode ("cpl", "c");
4328 emitcode ("", "%05d$:", (lbl->key + 100));
4330 /* if true label then we jump if condition
4332 tlbl = newiTempLabel (NULL);
4335 emitcode ("jnc", "%05d$", tlbl->key + 100);
4336 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4340 emitcode ("jc", "%05d$", tlbl->key + 100);
4341 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4343 emitcode ("", "%05d$:", tlbl->key + 100);
4347 tlbl = newiTempLabel (NULL);
4348 gencjneshort (left, right, tlbl);
4351 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4352 emitcode ("", "%05d$:", tlbl->key + 100);
4356 symbol *lbl = newiTempLabel (NULL);
4357 emitcode ("sjmp", "%05d$", lbl->key + 100);
4358 emitcode ("", "%05d$:", tlbl->key + 100);
4359 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4360 emitcode ("", "%05d$:", lbl->key + 100);
4363 /* mark the icode as generated */
4368 /* if they are both bit variables */
4369 if (AOP_TYPE (left) == AOP_CRY &&
4370 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4372 if (AOP_TYPE (right) == AOP_LIT)
4374 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4377 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4378 emitcode ("cpl", "c");
4382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4386 emitcode ("clr", "c");
4388 /* AOP_TYPE(right) == AOP_CRY */
4392 symbol *lbl = newiTempLabel (NULL);
4393 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4394 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4395 emitcode ("cpl", "c");
4396 emitcode ("", "%05d$:", (lbl->key + 100));
4399 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4406 genIfxJump (ifx, "c");
4409 /* if the result is used in an arithmetic operation
4410 then put the result in place */
4415 gencjne (left, right, newiTempLabel (NULL));
4416 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4418 aopPut (AOP (result), "a", 0);
4423 genIfxJump (ifx, "a");
4426 /* if the result is used in an arithmetic operation
4427 then put the result in place */
4428 if (AOP_TYPE (result) != AOP_CRY)
4430 /* leave the result in acc */
4434 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4435 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4436 freeAsmop (result, NULL, ic, TRUE);
4439 /*-----------------------------------------------------------------*/
4440 /* ifxForOp - returns the icode containing the ifx for operand */
4441 /*-----------------------------------------------------------------*/
4443 ifxForOp (operand * op, iCode * ic)
4445 /* if true symbol then needs to be assigned */
4446 if (IS_TRUE_SYMOP (op))
4449 /* if this has register type condition and
4450 the next instruction is ifx with the same operand
4451 and live to of the operand is upto the ifx only then */
4453 ic->next->op == IFX &&
4454 IC_COND (ic->next)->key == op->key &&
4455 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4461 /*-----------------------------------------------------------------*/
4462 /* hasInc - operand is incremented before any other use */
4463 /*-----------------------------------------------------------------*/
4465 hasInc (operand *op, iCode *ic,int osize)
4467 sym_link *type = operandType(op);
4468 sym_link *retype = getSpec (type);
4469 iCode *lic = ic->next;
4472 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4473 if (!IS_SYMOP(op)) return NULL;
4475 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4476 if (IS_AGGREGATE(type->next)) return NULL;
4477 if (osize != (isize = getSize(type->next))) return NULL;
4480 /* if operand of the form op = op + <sizeof *op> */
4481 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4482 isOperandEqual(IC_RESULT(lic),op) &&
4483 isOperandLiteral(IC_RIGHT(lic)) &&
4484 operandLitValue(IC_RIGHT(lic)) == isize) {
4487 /* if the operand used or deffed */
4488 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4491 /* if GOTO or IFX */
4492 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4498 /*-----------------------------------------------------------------*/
4499 /* genAndOp - for && operation */
4500 /*-----------------------------------------------------------------*/
4502 genAndOp (iCode * ic)
4504 operand *left, *right, *result;
4507 D(emitcode ("; genAndOp",""));
4509 /* note here that && operations that are in an
4510 if statement are taken away by backPatchLabels
4511 only those used in arthmetic operations remain */
4512 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4513 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4514 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4516 /* if both are bit variables */
4517 if (AOP_TYPE (left) == AOP_CRY &&
4518 AOP_TYPE (right) == AOP_CRY)
4520 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4521 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4526 tlbl = newiTempLabel (NULL);
4528 emitcode ("jz", "%05d$", tlbl->key + 100);
4530 emitcode ("", "%05d$:", tlbl->key + 100);
4534 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4535 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4536 freeAsmop (result, NULL, ic, TRUE);
4540 /*-----------------------------------------------------------------*/
4541 /* genOrOp - for || operation */
4542 /*-----------------------------------------------------------------*/
4544 genOrOp (iCode * ic)
4546 operand *left, *right, *result;
4549 D(emitcode ("; genOrOp",""));
4551 /* note here that || operations that are in an
4552 if statement are taken away by backPatchLabels
4553 only those used in arthmetic operations remain */
4554 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4555 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4556 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4558 /* if both are bit variables */
4559 if (AOP_TYPE (left) == AOP_CRY &&
4560 AOP_TYPE (right) == AOP_CRY)
4562 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4563 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4568 tlbl = newiTempLabel (NULL);
4570 emitcode ("jnz", "%05d$", tlbl->key + 100);
4572 emitcode ("", "%05d$:", tlbl->key + 100);
4576 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4577 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 freeAsmop (result, NULL, ic, TRUE);
4581 /*-----------------------------------------------------------------*/
4582 /* isLiteralBit - test if lit == 2^n */
4583 /*-----------------------------------------------------------------*/
4585 isLiteralBit (unsigned long lit)
4587 unsigned long pw[32] =
4588 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4589 0x100L, 0x200L, 0x400L, 0x800L,
4590 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4591 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4592 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4593 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4594 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4597 for (idx = 0; idx < 32; idx++)
4603 /*-----------------------------------------------------------------*/
4604 /* continueIfTrue - */
4605 /*-----------------------------------------------------------------*/
4607 continueIfTrue (iCode * ic)
4610 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4614 /*-----------------------------------------------------------------*/
4616 /*-----------------------------------------------------------------*/
4618 jumpIfTrue (iCode * ic)
4621 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4625 /*-----------------------------------------------------------------*/
4626 /* jmpTrueOrFalse - */
4627 /*-----------------------------------------------------------------*/
4629 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4631 // ugly but optimized by peephole
4634 symbol *nlbl = newiTempLabel (NULL);
4635 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4636 emitcode ("", "%05d$:", tlbl->key + 100);
4637 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4638 emitcode ("", "%05d$:", nlbl->key + 100);
4642 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4643 emitcode ("", "%05d$:", tlbl->key + 100);
4648 /*-----------------------------------------------------------------*/
4649 /* genAnd - code for and */
4650 /*-----------------------------------------------------------------*/
4652 genAnd (iCode * ic, iCode * ifx)
4654 operand *left, *right, *result;
4655 int size, offset = 0;
4656 unsigned long lit = 0L;
4660 D(emitcode ("; genAnd",""));
4662 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4663 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4664 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4667 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4669 AOP_TYPE (left), AOP_TYPE (right));
4670 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4672 AOP_SIZE (left), AOP_SIZE (right));
4675 /* if left is a literal & right is not then exchange them */
4676 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4677 AOP_NEEDSACC (left))
4679 operand *tmp = right;
4684 /* if result = right then exchange them */
4685 if (sameRegs (AOP (result), AOP (right)))
4687 operand *tmp = right;
4692 /* if right is bit then exchange them */
4693 if (AOP_TYPE (right) == AOP_CRY &&
4694 AOP_TYPE (left) != AOP_CRY)
4696 operand *tmp = right;
4700 if (AOP_TYPE (right) == AOP_LIT)
4701 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4703 size = AOP_SIZE (result);
4706 // result = bit & yy;
4707 if (AOP_TYPE (left) == AOP_CRY)
4709 // c = bit & literal;
4710 if (AOP_TYPE (right) == AOP_LIT)
4714 if (size && sameRegs (AOP (result), AOP (left)))
4717 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4722 if (size && (AOP_TYPE (result) == AOP_CRY))
4724 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4727 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4732 emitcode ("clr", "c");
4737 if (AOP_TYPE (right) == AOP_CRY)
4740 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4741 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4746 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4748 emitcode ("rrc", "a");
4749 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4757 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4758 genIfxJump (ifx, "c");
4762 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4763 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4764 if ((AOP_TYPE (right) == AOP_LIT) &&
4765 (AOP_TYPE (result) == AOP_CRY) &&
4766 (AOP_TYPE (left) != AOP_CRY))
4768 int posbit = isLiteralBit (lit);
4773 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4776 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4782 sprintf (buffer, "acc.%d", posbit & 0x07);
4783 genIfxJump (ifx, buffer);
4790 symbol *tlbl = newiTempLabel (NULL);
4791 int sizel = AOP_SIZE (left);
4793 emitcode ("setb", "c");
4796 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4798 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4800 if ((posbit = isLiteralBit (bytelit)) != 0)
4801 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4804 if (bytelit != 0x0FFL)
4805 emitcode ("anl", "a,%s",
4806 aopGet (AOP (right), offset, FALSE, TRUE));
4807 emitcode ("jnz", "%05d$", tlbl->key + 100);
4812 // bit = left & literal
4815 emitcode ("clr", "c");
4816 emitcode ("", "%05d$:", tlbl->key + 100);
4818 // if(left & literal)
4822 jmpTrueOrFalse (ifx, tlbl);
4830 /* if left is same as result */
4831 if (sameRegs (AOP (result), AOP (left)))
4833 for (; size--; offset++)
4835 if (AOP_TYPE (right) == AOP_LIT)
4837 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4839 else if (bytelit == 0)
4840 aopPut (AOP (result), zero, offset);
4841 else if (IS_AOP_PREG (result))
4843 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4844 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4845 aopPut (AOP (result), "a", offset);
4848 emitcode ("anl", "%s,%s",
4849 aopGet (AOP (left), offset, FALSE, TRUE),
4850 aopGet (AOP (right), offset, FALSE, FALSE));
4854 if (AOP_TYPE (left) == AOP_ACC)
4855 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4858 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4859 if (IS_AOP_PREG (result))
4861 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4862 aopPut (AOP (result), "a", offset);
4866 emitcode ("anl", "%s,a",
4867 aopGet (AOP (left), offset, FALSE, TRUE));
4874 // left & result in different registers
4875 if (AOP_TYPE (result) == AOP_CRY)
4878 // if(size), result in bit
4879 // if(!size && ifx), conditional oper: if(left & right)
4880 symbol *tlbl = newiTempLabel (NULL);
4881 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4883 emitcode ("setb", "c");
4886 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4887 emitcode ("anl", "a,%s",
4888 aopGet (AOP (right), offset, FALSE, FALSE));
4890 if (AOP_TYPE(left)==AOP_ACC) {
4891 emitcode("mov", "b,a");
4892 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4893 emitcode("anl", "a,b");
4895 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4896 emitcode ("anl", "a,%s",
4897 aopGet (AOP (left), offset, FALSE, FALSE));
4900 emitcode ("jnz", "%05d$", tlbl->key + 100);
4906 emitcode ("", "%05d$:", tlbl->key + 100);
4910 jmpTrueOrFalse (ifx, tlbl);
4914 for (; (size--); offset++)
4917 // result = left & right
4918 if (AOP_TYPE (right) == AOP_LIT)
4920 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4922 aopPut (AOP (result),
4923 aopGet (AOP (left), offset, FALSE, FALSE),
4927 else if (bytelit == 0)
4929 aopPut (AOP (result), zero, offset);
4933 // faster than result <- left, anl result,right
4934 // and better if result is SFR
4935 if (AOP_TYPE (left) == AOP_ACC)
4936 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4939 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4940 emitcode ("anl", "a,%s",
4941 aopGet (AOP (left), offset, FALSE, FALSE));
4943 aopPut (AOP (result), "a", offset);
4949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4951 freeAsmop (result, NULL, ic, TRUE);
4954 /*-----------------------------------------------------------------*/
4955 /* genOr - code for or */
4956 /*-----------------------------------------------------------------*/
4958 genOr (iCode * ic, iCode * ifx)
4960 operand *left, *right, *result;
4961 int size, offset = 0;
4962 unsigned long lit = 0L;
4964 D(emitcode ("; genOr",""));
4966 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4967 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4968 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4971 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4973 AOP_TYPE (left), AOP_TYPE (right));
4974 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4976 AOP_SIZE (left), AOP_SIZE (right));
4979 /* if left is a literal & right is not then exchange them */
4980 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4981 AOP_NEEDSACC (left))
4983 operand *tmp = right;
4988 /* if result = right then exchange them */
4989 if (sameRegs (AOP (result), AOP (right)))
4991 operand *tmp = right;
4996 /* if right is bit then exchange them */
4997 if (AOP_TYPE (right) == AOP_CRY &&
4998 AOP_TYPE (left) != AOP_CRY)
5000 operand *tmp = right;
5004 if (AOP_TYPE (right) == AOP_LIT)
5005 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5007 size = AOP_SIZE (result);
5011 if (AOP_TYPE (left) == AOP_CRY)
5013 if (AOP_TYPE (right) == AOP_LIT)
5015 // c = bit | literal;
5018 // lit != 0 => result = 1
5019 if (AOP_TYPE (result) == AOP_CRY)
5022 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5024 continueIfTrue (ifx);
5027 emitcode ("setb", "c");
5031 // lit == 0 => result = left
5032 if (size && sameRegs (AOP (result), AOP (left)))
5034 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5039 if (AOP_TYPE (right) == AOP_CRY)
5042 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5043 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5048 symbol *tlbl = newiTempLabel (NULL);
5049 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5050 emitcode ("setb", "c");
5051 emitcode ("jb", "%s,%05d$",
5052 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5054 emitcode ("jnz", "%05d$", tlbl->key + 100);
5055 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5057 jmpTrueOrFalse (ifx, tlbl);
5063 emitcode ("", "%05d$:", tlbl->key + 100);
5072 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5073 genIfxJump (ifx, "c");
5077 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5078 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5079 if ((AOP_TYPE (right) == AOP_LIT) &&
5080 (AOP_TYPE (result) == AOP_CRY) &&
5081 (AOP_TYPE (left) != AOP_CRY))
5087 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5089 continueIfTrue (ifx);
5094 // lit = 0, result = boolean(left)
5096 emitcode ("setb", "c");
5100 symbol *tlbl = newiTempLabel (NULL);
5101 emitcode ("jnz", "%05d$", tlbl->key + 100);
5103 emitcode ("", "%05d$:", tlbl->key + 100);
5107 genIfxJump (ifx, "a");
5115 /* if left is same as result */
5116 if (sameRegs (AOP (result), AOP (left)))
5118 for (; size--; offset++)
5120 if (AOP_TYPE (right) == AOP_LIT)
5122 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5124 else if (IS_AOP_PREG (left))
5126 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5127 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5128 aopPut (AOP (result), "a", offset);
5131 emitcode ("orl", "%s,%s",
5132 aopGet (AOP (left), offset, FALSE, TRUE),
5133 aopGet (AOP (right), offset, FALSE, FALSE));
5137 if (AOP_TYPE (left) == AOP_ACC)
5138 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5141 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5142 if (IS_AOP_PREG (left))
5144 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5145 aopPut (AOP (result), "a", offset);
5148 emitcode ("orl", "%s,a",
5149 aopGet (AOP (left), offset, FALSE, TRUE));
5156 // left & result in different registers
5157 if (AOP_TYPE (result) == AOP_CRY)
5160 // if(size), result in bit
5161 // if(!size && ifx), conditional oper: if(left | right)
5162 symbol *tlbl = newiTempLabel (NULL);
5163 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5165 emitcode ("setb", "c");
5168 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5169 emitcode ("orl", "a,%s",
5170 aopGet (AOP (right), offset, FALSE, FALSE));
5172 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5173 emitcode ("orl", "a,%s",
5174 aopGet (AOP (left), offset, FALSE, FALSE));
5176 emitcode ("jnz", "%05d$", tlbl->key + 100);
5182 emitcode ("", "%05d$:", tlbl->key + 100);
5186 jmpTrueOrFalse (ifx, tlbl);
5189 for (; (size--); offset++)
5192 // result = left & right
5193 if (AOP_TYPE (right) == AOP_LIT)
5195 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5197 aopPut (AOP (result),
5198 aopGet (AOP (left), offset, FALSE, FALSE),
5203 // faster than result <- left, anl result,right
5204 // and better if result is SFR
5205 if (AOP_TYPE (left) == AOP_ACC)
5206 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5209 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5210 emitcode ("orl", "a,%s",
5211 aopGet (AOP (left), offset, FALSE, FALSE));
5213 aopPut (AOP (result), "a", offset);
5218 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5219 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5220 freeAsmop (result, NULL, ic, TRUE);
5223 /*-----------------------------------------------------------------*/
5224 /* genXor - code for xclusive or */
5225 /*-----------------------------------------------------------------*/
5227 genXor (iCode * ic, iCode * ifx)
5229 operand *left, *right, *result;
5230 int size, offset = 0;
5231 unsigned long lit = 0L;
5233 D(emitcode ("; genXor",""));
5235 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5236 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5237 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5240 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5242 AOP_TYPE (left), AOP_TYPE (right));
5243 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5245 AOP_SIZE (left), AOP_SIZE (right));
5248 /* if left is a literal & right is not ||
5249 if left needs acc & right does not */
5250 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5251 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5253 operand *tmp = right;
5258 /* if result = right then exchange them */
5259 if (sameRegs (AOP (result), AOP (right)))
5261 operand *tmp = right;
5266 /* if right is bit then exchange them */
5267 if (AOP_TYPE (right) == AOP_CRY &&
5268 AOP_TYPE (left) != AOP_CRY)
5270 operand *tmp = right;
5274 if (AOP_TYPE (right) == AOP_LIT)
5275 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5277 size = AOP_SIZE (result);
5281 if (AOP_TYPE (left) == AOP_CRY)
5283 if (AOP_TYPE (right) == AOP_LIT)
5285 // c = bit & literal;
5288 // lit>>1 != 0 => result = 1
5289 if (AOP_TYPE (result) == AOP_CRY)
5292 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5294 continueIfTrue (ifx);
5297 emitcode ("setb", "c");
5304 // lit == 0, result = left
5305 if (size && sameRegs (AOP (result), AOP (left)))
5307 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5311 // lit == 1, result = not(left)
5312 if (size && sameRegs (AOP (result), AOP (left)))
5314 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5320 emitcode ("cpl", "c");
5329 symbol *tlbl = newiTempLabel (NULL);
5330 if (AOP_TYPE (right) == AOP_CRY)
5333 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5337 int sizer = AOP_SIZE (right);
5339 // if val>>1 != 0, result = 1
5340 emitcode ("setb", "c");
5343 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5345 // test the msb of the lsb
5346 emitcode ("anl", "a,#0xfe");
5347 emitcode ("jnz", "%05d$", tlbl->key + 100);
5351 emitcode ("rrc", "a");
5353 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5354 emitcode ("cpl", "c");
5355 emitcode ("", "%05d$:", (tlbl->key + 100));
5362 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5363 genIfxJump (ifx, "c");
5367 if (sameRegs (AOP (result), AOP (left)))
5369 /* if left is same as result */
5370 for (; size--; offset++)
5372 if (AOP_TYPE (right) == AOP_LIT)
5374 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5376 else if (IS_AOP_PREG (left))
5378 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5379 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5380 aopPut (AOP (result), "a", offset);
5383 emitcode ("xrl", "%s,%s",
5384 aopGet (AOP (left), offset, FALSE, TRUE),
5385 aopGet (AOP (right), offset, FALSE, FALSE));
5389 if (AOP_TYPE (left) == AOP_ACC)
5390 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5393 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5394 if (IS_AOP_PREG (left))
5396 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5397 aopPut (AOP (result), "a", offset);
5400 emitcode ("xrl", "%s,a",
5401 aopGet (AOP (left), offset, FALSE, TRUE));
5408 // left & result in different registers
5409 if (AOP_TYPE (result) == AOP_CRY)
5412 // if(size), result in bit
5413 // if(!size && ifx), conditional oper: if(left ^ right)
5414 symbol *tlbl = newiTempLabel (NULL);
5415 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5417 emitcode ("setb", "c");
5420 if ((AOP_TYPE (right) == AOP_LIT) &&
5421 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5423 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5427 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5428 emitcode ("xrl", "a,%s",
5429 aopGet (AOP (right), offset, FALSE, FALSE));
5431 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5432 emitcode ("xrl", "a,%s",
5433 aopGet (AOP (left), offset, FALSE, FALSE));
5436 emitcode ("jnz", "%05d$", tlbl->key + 100);
5442 emitcode ("", "%05d$:", tlbl->key + 100);
5446 jmpTrueOrFalse (ifx, tlbl);
5449 for (; (size--); offset++)
5452 // result = left & right
5453 if (AOP_TYPE (right) == AOP_LIT)
5455 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5457 aopPut (AOP (result),
5458 aopGet (AOP (left), offset, FALSE, FALSE),
5463 // faster than result <- left, anl result,right
5464 // and better if result is SFR
5465 if (AOP_TYPE (left) == AOP_ACC)
5466 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5469 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5470 emitcode ("xrl", "a,%s",
5471 aopGet (AOP (left), offset, FALSE, TRUE));
5473 aopPut (AOP (result), "a", offset);
5478 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5479 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5480 freeAsmop (result, NULL, ic, TRUE);
5483 /*-----------------------------------------------------------------*/
5484 /* genInline - write the inline code out */
5485 /*-----------------------------------------------------------------*/
5487 genInline (iCode * ic)
5489 char *buffer, *bp, *bp1;
5491 D(emitcode ("; genInline",""));
5493 _G.inLine += (!options.asmpeep);
5495 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5496 strcpy (buffer, IC_INLINE (ic));
5498 /* emit each line as a code */
5523 /* emitcode("",buffer); */
5524 _G.inLine -= (!options.asmpeep);
5527 /*-----------------------------------------------------------------*/
5528 /* genRRC - rotate right with carry */
5529 /*-----------------------------------------------------------------*/
5533 operand *left, *result;
5534 int size, offset = 0;
5537 D(emitcode ("; genRRC",""));
5539 /* rotate right with carry */
5540 left = IC_LEFT (ic);
5541 result = IC_RESULT (ic);
5542 aopOp (left, ic, FALSE);
5543 aopOp (result, ic, FALSE);
5545 /* move it to the result */
5546 size = AOP_SIZE (result);
5548 if (size == 1) { /* special case for 1 byte */
5549 l = aopGet (AOP (left), offset, FALSE, FALSE);
5551 emitcode ("rr", "a");
5557 l = aopGet (AOP (left), offset, FALSE, FALSE);
5559 emitcode ("rrc", "a");
5560 if (AOP_SIZE (result) > 1)
5561 aopPut (AOP (result), "a", offset--);
5563 /* now we need to put the carry into the
5564 highest order byte of the result */
5565 if (AOP_SIZE (result) > 1)
5567 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5570 emitcode ("mov", "acc.7,c");
5572 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5573 freeAsmop (left, NULL, ic, TRUE);
5574 freeAsmop (result, NULL, ic, TRUE);
5577 /*-----------------------------------------------------------------*/
5578 /* genRLC - generate code for rotate left with carry */
5579 /*-----------------------------------------------------------------*/
5583 operand *left, *result;
5584 int size, offset = 0;
5587 D(emitcode ("; genRLC",""));
5589 /* rotate right with carry */
5590 left = IC_LEFT (ic);
5591 result = IC_RESULT (ic);
5592 aopOp (left, ic, FALSE);
5593 aopOp (result, ic, FALSE);
5595 /* move it to the result */
5596 size = AOP_SIZE (result);
5600 l = aopGet (AOP (left), offset, FALSE, FALSE);
5602 if (size == 0) { /* special case for 1 byte */
5606 emitcode ("add", "a,acc");
5607 if (AOP_SIZE (result) > 1)
5608 aopPut (AOP (result), "a", offset++);
5611 l = aopGet (AOP (left), offset, FALSE, FALSE);
5613 emitcode ("rlc", "a");
5614 if (AOP_SIZE (result) > 1)
5615 aopPut (AOP (result), "a", offset++);
5618 /* now we need to put the carry into the
5619 highest order byte of the result */
5620 if (AOP_SIZE (result) > 1)
5622 l = aopGet (AOP (result), 0, FALSE, FALSE);
5625 emitcode ("mov", "acc.0,c");
5627 aopPut (AOP (result), "a", 0);
5628 freeAsmop (left, NULL, ic, TRUE);
5629 freeAsmop (result, NULL, ic, TRUE);
5632 /*-----------------------------------------------------------------*/
5633 /* genGetHbit - generates code get highest order bit */
5634 /*-----------------------------------------------------------------*/
5636 genGetHbit (iCode * ic)
5638 operand *left, *result;
5640 D(emitcode ("; genGetHbit",""));
5642 left = IC_LEFT (ic);
5643 result = IC_RESULT (ic);
5644 aopOp (left, ic, FALSE);
5645 aopOp (result, ic, FALSE);
5647 /* get the highest order byte into a */
5648 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5649 if (AOP_TYPE (result) == AOP_CRY)
5651 emitcode ("rlc", "a");
5656 emitcode ("rl", "a");
5657 emitcode ("anl", "a,#0x01");
5662 freeAsmop (left, NULL, ic, TRUE);
5663 freeAsmop (result, NULL, ic, TRUE);
5666 /*-----------------------------------------------------------------*/
5667 /* AccRol - rotate left accumulator by known count */
5668 /*-----------------------------------------------------------------*/
5670 AccRol (int shCount)
5672 shCount &= 0x0007; // shCount : 0..7
5679 emitcode ("rl", "a");
5682 emitcode ("rl", "a");
5683 emitcode ("rl", "a");
5686 emitcode ("swap", "a");
5687 emitcode ("rr", "a");
5690 emitcode ("swap", "a");
5693 emitcode ("swap", "a");
5694 emitcode ("rl", "a");
5697 emitcode ("rr", "a");
5698 emitcode ("rr", "a");
5701 emitcode ("rr", "a");
5706 /*-----------------------------------------------------------------*/
5707 /* AccLsh - left shift accumulator by known count */
5708 /*-----------------------------------------------------------------*/
5710 AccLsh (int shCount)
5715 emitcode ("add", "a,acc");
5716 else if (shCount == 2)
5718 emitcode ("add", "a,acc");
5719 emitcode ("add", "a,acc");
5723 /* rotate left accumulator */
5725 /* and kill the lower order bits */
5726 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5731 /*-----------------------------------------------------------------*/
5732 /* AccRsh - right shift accumulator by known count */
5733 /*-----------------------------------------------------------------*/
5735 AccRsh (int shCount)
5742 emitcode ("rrc", "a");
5746 /* rotate right accumulator */
5747 AccRol (8 - shCount);
5748 /* and kill the higher order bits */
5749 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5754 /*-----------------------------------------------------------------*/
5755 /* AccSRsh - signed right shift accumulator by known count */
5756 /*-----------------------------------------------------------------*/
5758 AccSRsh (int shCount)
5765 emitcode ("mov", "c,acc.7");
5766 emitcode ("rrc", "a");
5768 else if (shCount == 2)
5770 emitcode ("mov", "c,acc.7");
5771 emitcode ("rrc", "a");
5772 emitcode ("mov", "c,acc.7");
5773 emitcode ("rrc", "a");
5777 tlbl = newiTempLabel (NULL);
5778 /* rotate right accumulator */
5779 AccRol (8 - shCount);
5780 /* and kill the higher order bits */
5781 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5782 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5783 emitcode ("orl", "a,#0x%02x",
5784 (unsigned char) ~SRMask[shCount]);
5785 emitcode ("", "%05d$:", tlbl->key + 100);
5790 /*-----------------------------------------------------------------*/
5791 /* shiftR1Left2Result - shift right one byte from left to result */
5792 /*-----------------------------------------------------------------*/
5794 shiftR1Left2Result (operand * left, int offl,
5795 operand * result, int offr,
5796 int shCount, int sign)
5798 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5799 /* shift right accumulator */
5804 aopPut (AOP (result), "a", offr);
5807 /*-----------------------------------------------------------------*/
5808 /* shiftL1Left2Result - shift left one byte from left to result */
5809 /*-----------------------------------------------------------------*/
5811 shiftL1Left2Result (operand * left, int offl,
5812 operand * result, int offr, int shCount)
5815 l = aopGet (AOP (left), offl, FALSE, FALSE);
5817 /* shift left accumulator */
5819 aopPut (AOP (result), "a", offr);
5822 /*-----------------------------------------------------------------*/
5823 /* movLeft2Result - move byte from left to result */
5824 /*-----------------------------------------------------------------*/
5826 movLeft2Result (operand * left, int offl,
5827 operand * result, int offr, int sign)
5830 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5832 l = aopGet (AOP (left), offl, FALSE, FALSE);
5834 if (*l == '@' && (IS_AOP_PREG (result)))
5836 emitcode ("mov", "a,%s", l);
5837 aopPut (AOP (result), "a", offr);
5842 aopPut (AOP (result), l, offr);
5845 /* MSB sign in acc.7 ! */
5846 if (getDataSize (left) == offl + 1)
5848 emitcode ("mov", "a,%s", l);
5849 aopPut (AOP (result), "a", offr);
5856 /*-----------------------------------------------------------------*/
5857 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5858 /*-----------------------------------------------------------------*/
5862 emitcode ("rrc", "a");
5863 emitcode ("xch", "a,%s", x);
5864 emitcode ("rrc", "a");
5865 emitcode ("xch", "a,%s", x);
5868 /*-----------------------------------------------------------------*/
5869 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5870 /*-----------------------------------------------------------------*/
5874 emitcode ("xch", "a,%s", x);
5875 emitcode ("rlc", "a");
5876 emitcode ("xch", "a,%s", x);
5877 emitcode ("rlc", "a");
5880 /*-----------------------------------------------------------------*/
5881 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5882 /*-----------------------------------------------------------------*/
5886 emitcode ("xch", "a,%s", x);
5887 emitcode ("add", "a,acc");
5888 emitcode ("xch", "a,%s", x);
5889 emitcode ("rlc", "a");
5892 /*-----------------------------------------------------------------*/
5893 /* AccAXLsh - left shift a:x by known count (0..7) */
5894 /*-----------------------------------------------------------------*/
5896 AccAXLsh (char *x, int shCount)
5911 case 5: // AAAAABBB:CCCCCDDD
5913 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5915 emitcode ("anl", "a,#0x%02x",
5916 SLMask[shCount]); // BBB00000:CCCCCDDD
5918 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5920 AccRol (shCount); // DDDCCCCC:BBB00000
5922 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5924 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5926 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5928 emitcode ("anl", "a,#0x%02x",
5929 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5931 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5933 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5936 case 6: // AAAAAABB:CCCCCCDD
5937 emitcode ("anl", "a,#0x%02x",
5938 SRMask[shCount]); // 000000BB:CCCCCCDD
5939 emitcode ("mov", "c,acc.0"); // c = B
5940 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5942 AccAXRrl1 (x); // BCCCCCCD:D000000B
5943 AccAXRrl1 (x); // BBCCCCCC:DD000000
5945 emitcode("rrc","a");
5946 emitcode("xch","a,%s", x);
5947 emitcode("rrc","a");
5948 emitcode("mov","c,acc.0"); //<< get correct bit
5949 emitcode("xch","a,%s", x);
5951 emitcode("rrc","a");
5952 emitcode("xch","a,%s", x);
5953 emitcode("rrc","a");
5954 emitcode("xch","a,%s", x);
5957 case 7: // a:x <<= 7
5959 emitcode ("anl", "a,#0x%02x",
5960 SRMask[shCount]); // 0000000B:CCCCCCCD
5962 emitcode ("mov", "c,acc.0"); // c = B
5964 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5966 AccAXRrl1 (x); // BCCCCCCC:D0000000
5974 /*-----------------------------------------------------------------*/
5975 /* AccAXRsh - right shift a:x known count (0..7) */
5976 /*-----------------------------------------------------------------*/
5978 AccAXRsh (char *x, int shCount)
5986 AccAXRrl1 (x); // 0->a:x
5991 AccAXRrl1 (x); // 0->a:x
5994 AccAXRrl1 (x); // 0->a:x
5999 case 5: // AAAAABBB:CCCCCDDD = a:x
6001 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6003 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6005 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6007 emitcode ("anl", "a,#0x%02x",
6008 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6010 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6012 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6014 emitcode ("anl", "a,#0x%02x",
6015 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6017 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6019 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6021 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6024 case 6: // AABBBBBB:CCDDDDDD
6026 emitcode ("mov", "c,acc.7");
6027 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6029 emitcode ("mov", "c,acc.7");
6030 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6032 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6034 emitcode ("anl", "a,#0x%02x",
6035 SRMask[shCount]); // 000000AA:BBBBBBCC
6038 case 7: // ABBBBBBB:CDDDDDDD
6040 emitcode ("mov", "c,acc.7"); // c = A
6042 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6044 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6046 emitcode ("anl", "a,#0x%02x",
6047 SRMask[shCount]); // 0000000A:BBBBBBBC
6055 /*-----------------------------------------------------------------*/
6056 /* AccAXRshS - right shift signed a:x known count (0..7) */
6057 /*-----------------------------------------------------------------*/
6059 AccAXRshS (char *x, int shCount)
6067 emitcode ("mov", "c,acc.7");
6068 AccAXRrl1 (x); // s->a:x
6072 emitcode ("mov", "c,acc.7");
6073 AccAXRrl1 (x); // s->a:x
6075 emitcode ("mov", "c,acc.7");
6076 AccAXRrl1 (x); // s->a:x
6081 case 5: // AAAAABBB:CCCCCDDD = a:x
6083 tlbl = newiTempLabel (NULL);
6084 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6086 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6088 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6090 emitcode ("anl", "a,#0x%02x",
6091 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6093 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6095 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6097 emitcode ("anl", "a,#0x%02x",
6098 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6100 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6102 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6104 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6106 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6107 emitcode ("orl", "a,#0x%02x",
6108 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6110 emitcode ("", "%05d$:", tlbl->key + 100);
6111 break; // SSSSAAAA:BBBCCCCC
6113 case 6: // AABBBBBB:CCDDDDDD
6115 tlbl = newiTempLabel (NULL);
6116 emitcode ("mov", "c,acc.7");
6117 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6119 emitcode ("mov", "c,acc.7");
6120 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6122 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6124 emitcode ("anl", "a,#0x%02x",
6125 SRMask[shCount]); // 000000AA:BBBBBBCC
6127 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6128 emitcode ("orl", "a,#0x%02x",
6129 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6131 emitcode ("", "%05d$:", tlbl->key + 100);
6133 case 7: // ABBBBBBB:CDDDDDDD
6135 tlbl = newiTempLabel (NULL);
6136 emitcode ("mov", "c,acc.7"); // c = A
6138 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6140 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6142 emitcode ("anl", "a,#0x%02x",
6143 SRMask[shCount]); // 0000000A:BBBBBBBC
6145 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6146 emitcode ("orl", "a,#0x%02x",
6147 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6149 emitcode ("", "%05d$:", tlbl->key + 100);
6156 /*-----------------------------------------------------------------*/
6157 /* shiftL2Left2Result - shift left two bytes from left to result */
6158 /*-----------------------------------------------------------------*/
6160 shiftL2Left2Result (operand * left, int offl,
6161 operand * result, int offr, int shCount)
6163 if (sameRegs (AOP (result), AOP (left)) &&
6164 ((offl + MSB16) == offr))
6166 /* don't crash result[offr] */
6167 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6168 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6172 movLeft2Result (left, offl, result, offr, 0);
6173 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6175 /* ax << shCount (x = lsb(result)) */
6176 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6177 aopPut (AOP (result), "a", offr + MSB16);
6181 /*-----------------------------------------------------------------*/
6182 /* shiftR2Left2Result - shift right two bytes from left to result */
6183 /*-----------------------------------------------------------------*/
6185 shiftR2Left2Result (operand * left, int offl,
6186 operand * result, int offr,
6187 int shCount, int sign)
6189 if (sameRegs (AOP (result), AOP (left)) &&
6190 ((offl + MSB16) == offr))
6192 /* don't crash result[offr] */
6193 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6194 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6198 movLeft2Result (left, offl, result, offr, 0);
6199 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6201 /* a:x >> shCount (x = lsb(result)) */
6203 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6205 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6206 if (getDataSize (result) > 1)
6207 aopPut (AOP (result), "a", offr + MSB16);
6210 /*-----------------------------------------------------------------*/
6211 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6212 /*-----------------------------------------------------------------*/
6214 shiftLLeftOrResult (operand * left, int offl,
6215 operand * result, int offr, int shCount)
6217 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6218 /* shift left accumulator */
6220 /* or with result */
6221 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6222 /* back to result */
6223 aopPut (AOP (result), "a", offr);
6226 /*-----------------------------------------------------------------*/
6227 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6228 /*-----------------------------------------------------------------*/
6230 shiftRLeftOrResult (operand * left, int offl,
6231 operand * result, int offr, int shCount)
6233 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6234 /* shift right accumulator */
6236 /* or with result */
6237 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6238 /* back to result */
6239 aopPut (AOP (result), "a", offr);
6242 /*-----------------------------------------------------------------*/
6243 /* genlshOne - left shift a one byte quantity by known count */
6244 /*-----------------------------------------------------------------*/
6246 genlshOne (operand * result, operand * left, int shCount)
6248 D(emitcode ("; genlshOne",""));
6250 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6253 /*-----------------------------------------------------------------*/
6254 /* genlshTwo - left shift two bytes by known amount != 0 */
6255 /*-----------------------------------------------------------------*/
6257 genlshTwo (operand * result, operand * left, int shCount)
6261 D(emitcode ("; genlshTwo",""));
6263 size = getDataSize (result);
6265 /* if shCount >= 8 */
6273 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6275 movLeft2Result (left, LSB, result, MSB16, 0);
6277 aopPut (AOP (result), zero, LSB);
6280 /* 1 <= shCount <= 7 */
6284 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6286 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6290 /*-----------------------------------------------------------------*/
6291 /* shiftLLong - shift left one long from left to result */
6292 /* offl = LSB or MSB16 */
6293 /*-----------------------------------------------------------------*/
6295 shiftLLong (operand * left, operand * result, int offr)
6298 int size = AOP_SIZE (result);
6300 if (size >= LSB + offr)
6302 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6304 emitcode ("add", "a,acc");
6305 if (sameRegs (AOP (left), AOP (result)) &&
6306 size >= MSB16 + offr && offr != LSB)
6307 emitcode ("xch", "a,%s",
6308 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6310 aopPut (AOP (result), "a", LSB + offr);
6313 if (size >= MSB16 + offr)
6315 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6317 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6320 emitcode ("rlc", "a");
6321 if (sameRegs (AOP (left), AOP (result)) &&
6322 size >= MSB24 + offr && offr != LSB)
6323 emitcode ("xch", "a,%s",
6324 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6326 aopPut (AOP (result), "a", MSB16 + offr);
6329 if (size >= MSB24 + offr)
6331 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6333 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6336 emitcode ("rlc", "a");
6337 if (sameRegs (AOP (left), AOP (result)) &&
6338 size >= MSB32 + offr && offr != LSB)
6339 emitcode ("xch", "a,%s",
6340 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6342 aopPut (AOP (result), "a", MSB24 + offr);
6345 if (size > MSB32 + offr)
6347 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6349 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6352 emitcode ("rlc", "a");
6353 aopPut (AOP (result), "a", MSB32 + offr);
6356 aopPut (AOP (result), zero, LSB);
6359 /*-----------------------------------------------------------------*/
6360 /* genlshFour - shift four byte by a known amount != 0 */
6361 /*-----------------------------------------------------------------*/
6363 genlshFour (operand * result, operand * left, int shCount)
6367 D(emitcode ("; genlshFour",""));
6369 size = AOP_SIZE (result);
6371 /* if shifting more that 3 bytes */
6376 /* lowest order of left goes to the highest
6377 order of the destination */
6378 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6380 movLeft2Result (left, LSB, result, MSB32, 0);
6381 aopPut (AOP (result), zero, LSB);
6382 aopPut (AOP (result), zero, MSB16);
6383 aopPut (AOP (result), zero, MSB24);
6387 /* more than two bytes */
6388 else if (shCount >= 16)
6390 /* lower order two bytes goes to higher order two bytes */
6392 /* if some more remaining */
6394 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6397 movLeft2Result (left, MSB16, result, MSB32, 0);
6398 movLeft2Result (left, LSB, result, MSB24, 0);
6400 aopPut (AOP (result), zero, MSB16);
6401 aopPut (AOP (result), zero, LSB);
6405 /* if more than 1 byte */
6406 else if (shCount >= 8)
6408 /* lower order three bytes goes to higher order three bytes */
6413 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6415 movLeft2Result (left, LSB, result, MSB16, 0);
6421 movLeft2Result (left, MSB24, result, MSB32, 0);
6422 movLeft2Result (left, MSB16, result, MSB24, 0);
6423 movLeft2Result (left, LSB, result, MSB16, 0);
6424 aopPut (AOP (result), zero, LSB);
6426 else if (shCount == 1)
6427 shiftLLong (left, result, MSB16);
6430 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6431 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6432 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6433 aopPut (AOP (result), zero, LSB);
6438 /* 1 <= shCount <= 7 */
6439 else if (shCount <= 2)
6441 shiftLLong (left, result, LSB);
6443 shiftLLong (result, result, LSB);
6445 /* 3 <= shCount <= 7, optimize */
6448 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6449 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6450 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6454 /*-----------------------------------------------------------------*/
6455 /* genLeftShiftLiteral - left shifting by known count */
6456 /*-----------------------------------------------------------------*/
6458 genLeftShiftLiteral (operand * left,
6463 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6466 D(emitcode ("; genLeftShiftLiteral",""));
6468 freeAsmop (right, NULL, ic, TRUE);
6470 aopOp (left, ic, FALSE);
6471 aopOp (result, ic, FALSE);
6473 size = getSize (operandType (result));
6476 emitcode ("; shift left ", "result %d, left %d", size,
6480 /* I suppose that the left size >= result size */
6485 movLeft2Result (left, size, result, size, 0);
6489 else if (shCount >= (size * 8))
6491 aopPut (AOP (result), zero, size);
6497 genlshOne (result, left, shCount);
6501 genlshTwo (result, left, shCount);
6505 genlshFour (result, left, shCount);
6508 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6509 "*** ack! mystery literal shift!\n");
6513 freeAsmop (left, NULL, ic, TRUE);
6514 freeAsmop (result, NULL, ic, TRUE);
6517 /*-----------------------------------------------------------------*/
6518 /* genLeftShift - generates code for left shifting */
6519 /*-----------------------------------------------------------------*/
6521 genLeftShift (iCode * ic)
6523 operand *left, *right, *result;
6526 symbol *tlbl, *tlbl1;
6528 D(emitcode ("; genLeftShift",""));
6530 right = IC_RIGHT (ic);
6531 left = IC_LEFT (ic);
6532 result = IC_RESULT (ic);
6534 aopOp (right, ic, FALSE);
6536 /* if the shift count is known then do it
6537 as efficiently as possible */
6538 if (AOP_TYPE (right) == AOP_LIT)
6540 genLeftShiftLiteral (left, right, result, ic);
6544 /* shift count is unknown then we have to form
6545 a loop get the loop count in B : Note: we take
6546 only the lower order byte since shifting
6547 more that 32 bits make no sense anyway, ( the
6548 largest size of an object can be only 32 bits ) */
6550 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6551 emitcode ("inc", "b");
6552 freeAsmop (right, NULL, ic, TRUE);
6553 aopOp (left, ic, FALSE);
6554 aopOp (result, ic, FALSE);
6556 /* now move the left to the result if they are not the
6558 if (!sameRegs (AOP (left), AOP (result)) &&
6559 AOP_SIZE (result) > 1)
6562 size = AOP_SIZE (result);
6566 l = aopGet (AOP (left), offset, FALSE, TRUE);
6567 if (*l == '@' && (IS_AOP_PREG (result)))
6570 emitcode ("mov", "a,%s", l);
6571 aopPut (AOP (result), "a", offset);
6574 aopPut (AOP (result), l, offset);
6579 tlbl = newiTempLabel (NULL);
6580 size = AOP_SIZE (result);
6582 tlbl1 = newiTempLabel (NULL);
6584 /* if it is only one byte then */
6587 symbol *tlbl1 = newiTempLabel (NULL);
6589 l = aopGet (AOP (left), 0, FALSE, FALSE);
6591 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6592 emitcode ("", "%05d$:", tlbl->key + 100);
6593 emitcode ("add", "a,acc");
6594 emitcode ("", "%05d$:", tlbl1->key + 100);
6595 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6596 aopPut (AOP (result), "a", 0);
6600 reAdjustPreg (AOP (result));
6602 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6603 emitcode ("", "%05d$:", tlbl->key + 100);
6604 l = aopGet (AOP (result), offset, FALSE, FALSE);
6606 emitcode ("add", "a,acc");
6607 aopPut (AOP (result), "a", offset++);
6610 l = aopGet (AOP (result), offset, FALSE, FALSE);
6612 emitcode ("rlc", "a");
6613 aopPut (AOP (result), "a", offset++);
6615 reAdjustPreg (AOP (result));
6617 emitcode ("", "%05d$:", tlbl1->key + 100);
6618 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6620 freeAsmop (left, NULL, ic, TRUE);
6621 freeAsmop (result, NULL, ic, TRUE);
6624 /*-----------------------------------------------------------------*/
6625 /* genrshOne - right shift a one byte quantity by known count */
6626 /*-----------------------------------------------------------------*/
6628 genrshOne (operand * result, operand * left,
6629 int shCount, int sign)
6631 D(emitcode ("; genrshOne",""));
6633 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6636 /*-----------------------------------------------------------------*/
6637 /* genrshTwo - right shift two bytes by known amount != 0 */
6638 /*-----------------------------------------------------------------*/
6640 genrshTwo (operand * result, operand * left,
6641 int shCount, int sign)
6643 D(emitcode ("; genrshTwo",""));
6645 /* if shCount >= 8 */
6650 shiftR1Left2Result (left, MSB16, result, LSB,
6653 movLeft2Result (left, MSB16, result, LSB, sign);
6654 addSign (result, MSB16, sign);
6657 /* 1 <= shCount <= 7 */
6659 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6662 /*-----------------------------------------------------------------*/
6663 /* shiftRLong - shift right one long from left to result */
6664 /* offl = LSB or MSB16 */
6665 /*-----------------------------------------------------------------*/
6667 shiftRLong (operand * left, int offl,
6668 operand * result, int sign)
6670 int isSameRegs=sameRegs(AOP(left),AOP(result));
6672 if (isSameRegs && offl>1) {
6673 // we are in big trouble, but this shouldn't happen
6674 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6677 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6682 emitcode ("rlc", "a");
6683 emitcode ("subb", "a,acc");
6685 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6687 aopPut (AOP (result), "a", MSB32);
6688 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6691 aopPut (AOP(result), zero, MSB32);
6696 emitcode ("clr", "c");
6698 emitcode ("mov", "c,acc.7");
6701 emitcode ("rrc", "a");
6703 if (isSameRegs && offl==MSB16) {
6704 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6706 aopPut (AOP (result), "a", MSB32-offl);
6707 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6710 emitcode ("rrc", "a");
6711 if (isSameRegs && offl==1) {
6712 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6714 aopPut (AOP (result), "a", MSB24-offl);
6715 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6717 emitcode ("rrc", "a");
6718 aopPut (AOP (result), "a", MSB16 - offl);
6722 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6723 emitcode ("rrc", "a");
6724 aopPut (AOP (result), "a", LSB);
6728 /*-----------------------------------------------------------------*/
6729 /* genrshFour - shift four byte by a known amount != 0 */
6730 /*-----------------------------------------------------------------*/
6732 genrshFour (operand * result, operand * left,
6733 int shCount, int sign)
6735 D(emitcode ("; genrshFour",""));
6737 /* if shifting more that 3 bytes */
6742 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6744 movLeft2Result (left, MSB32, result, LSB, sign);
6745 addSign (result, MSB16, sign);
6747 else if (shCount >= 16)
6751 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6754 movLeft2Result (left, MSB24, result, LSB, 0);
6755 movLeft2Result (left, MSB32, result, MSB16, sign);
6757 addSign (result, MSB24, sign);
6759 else if (shCount >= 8)
6763 shiftRLong (left, MSB16, result, sign);
6764 else if (shCount == 0)
6766 movLeft2Result (left, MSB16, result, LSB, 0);
6767 movLeft2Result (left, MSB24, result, MSB16, 0);
6768 movLeft2Result (left, MSB32, result, MSB24, sign);
6769 addSign (result, MSB32, sign);
6773 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6774 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6775 /* the last shift is signed */
6776 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6777 addSign (result, MSB32, sign);
6781 { /* 1 <= shCount <= 7 */
6784 shiftRLong (left, LSB, result, sign);
6786 shiftRLong (result, LSB, result, sign);
6790 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6791 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6792 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6797 /*-----------------------------------------------------------------*/
6798 /* genRightShiftLiteral - right shifting by known count */
6799 /*-----------------------------------------------------------------*/
6801 genRightShiftLiteral (operand * left,
6807 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6810 D(emitcode ("; genRightShiftLiteral",""));
6812 freeAsmop (right, NULL, ic, TRUE);
6814 aopOp (left, ic, FALSE);
6815 aopOp (result, ic, FALSE);
6818 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6822 size = getDataSize (left);
6823 /* test the LEFT size !!! */
6825 /* I suppose that the left size >= result size */
6828 size = getDataSize (result);
6830 movLeft2Result (left, size, result, size, 0);
6833 else if (shCount >= (size * 8))
6836 /* get sign in acc.7 */
6837 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6839 addSign (result, LSB, sign);
6846 genrshOne (result, left, shCount, sign);
6850 genrshTwo (result, left, shCount, sign);
6854 genrshFour (result, left, shCount, sign);
6860 freeAsmop (left, NULL, ic, TRUE);
6861 freeAsmop (result, NULL, ic, TRUE);
6864 /*-----------------------------------------------------------------*/
6865 /* genSignedRightShift - right shift of signed number */
6866 /*-----------------------------------------------------------------*/
6868 genSignedRightShift (iCode * ic)
6870 operand *right, *left, *result;
6873 symbol *tlbl, *tlbl1;
6875 D(emitcode ("; genSignedRightShift",""));
6877 /* we do it the hard way put the shift count in b
6878 and loop thru preserving the sign */
6880 right = IC_RIGHT (ic);
6881 left = IC_LEFT (ic);
6882 result = IC_RESULT (ic);
6884 aopOp (right, ic, FALSE);
6887 if (AOP_TYPE (right) == AOP_LIT)
6889 genRightShiftLiteral (left, right, result, ic, 1);
6892 /* shift count is unknown then we have to form
6893 a loop get the loop count in B : Note: we take
6894 only the lower order byte since shifting
6895 more that 32 bits make no sense anyway, ( the
6896 largest size of an object can be only 32 bits ) */
6898 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6899 emitcode ("inc", "b");
6900 freeAsmop (right, NULL, ic, TRUE);
6901 aopOp (left, ic, FALSE);
6902 aopOp (result, ic, FALSE);
6904 /* now move the left to the result if they are not the
6906 if (!sameRegs (AOP (left), AOP (result)) &&
6907 AOP_SIZE (result) > 1)
6910 size = AOP_SIZE (result);
6914 l = aopGet (AOP (left), offset, FALSE, TRUE);
6915 if (*l == '@' && IS_AOP_PREG (result))
6918 emitcode ("mov", "a,%s", l);
6919 aopPut (AOP (result), "a", offset);
6922 aopPut (AOP (result), l, offset);
6927 /* mov the highest order bit to OVR */
6928 tlbl = newiTempLabel (NULL);
6929 tlbl1 = newiTempLabel (NULL);
6931 size = AOP_SIZE (result);
6933 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6934 emitcode ("rlc", "a");
6935 emitcode ("mov", "ov,c");
6936 /* if it is only one byte then */
6939 l = aopGet (AOP (left), 0, FALSE, FALSE);
6941 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6942 emitcode ("", "%05d$:", tlbl->key + 100);
6943 emitcode ("mov", "c,ov");
6944 emitcode ("rrc", "a");
6945 emitcode ("", "%05d$:", tlbl1->key + 100);
6946 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6947 aopPut (AOP (result), "a", 0);
6951 reAdjustPreg (AOP (result));
6952 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6953 emitcode ("", "%05d$:", tlbl->key + 100);
6954 emitcode ("mov", "c,ov");
6957 l = aopGet (AOP (result), offset, FALSE, FALSE);
6959 emitcode ("rrc", "a");
6960 aopPut (AOP (result), "a", offset--);
6962 reAdjustPreg (AOP (result));
6963 emitcode ("", "%05d$:", tlbl1->key + 100);
6964 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6967 freeAsmop (left, NULL, ic, TRUE);
6968 freeAsmop (result, NULL, ic, TRUE);
6971 /*-----------------------------------------------------------------*/
6972 /* genRightShift - generate code for right shifting */
6973 /*-----------------------------------------------------------------*/
6975 genRightShift (iCode * ic)
6977 operand *right, *left, *result;
6981 symbol *tlbl, *tlbl1;
6983 D(emitcode ("; genRightShift",""));
6985 /* if signed then we do it the hard way preserve the
6986 sign bit moving it inwards */
6987 retype = getSpec (operandType (IC_RESULT (ic)));
6989 if (!SPEC_USIGN (retype))
6991 genSignedRightShift (ic);
6995 /* signed & unsigned types are treated the same : i.e. the
6996 signed is NOT propagated inwards : quoting from the
6997 ANSI - standard : "for E1 >> E2, is equivalent to division
6998 by 2**E2 if unsigned or if it has a non-negative value,
6999 otherwise the result is implementation defined ", MY definition
7000 is that the sign does not get propagated */
7002 right = IC_RIGHT (ic);
7003 left = IC_LEFT (ic);
7004 result = IC_RESULT (ic);
7006 aopOp (right, ic, FALSE);
7008 /* if the shift count is known then do it
7009 as efficiently as possible */
7010 if (AOP_TYPE (right) == AOP_LIT)
7012 genRightShiftLiteral (left, right, result, ic, 0);
7016 /* shift count is unknown then we have to form
7017 a loop get the loop count in B : Note: we take
7018 only the lower order byte since shifting
7019 more that 32 bits make no sense anyway, ( the
7020 largest size of an object can be only 32 bits ) */
7022 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7023 emitcode ("inc", "b");
7024 freeAsmop (right, NULL, ic, TRUE);
7025 aopOp (left, ic, FALSE);
7026 aopOp (result, ic, FALSE);
7028 /* now move the left to the result if they are not the
7030 if (!sameRegs (AOP (left), AOP (result)) &&
7031 AOP_SIZE (result) > 1)
7034 size = AOP_SIZE (result);
7038 l = aopGet (AOP (left), offset, FALSE, TRUE);
7039 if (*l == '@' && IS_AOP_PREG (result))
7042 emitcode ("mov", "a,%s", l);
7043 aopPut (AOP (result), "a", offset);
7046 aopPut (AOP (result), l, offset);
7051 tlbl = newiTempLabel (NULL);
7052 tlbl1 = newiTempLabel (NULL);
7053 size = AOP_SIZE (result);
7056 /* if it is only one byte then */
7059 l = aopGet (AOP (left), 0, FALSE, FALSE);
7061 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7062 emitcode ("", "%05d$:", tlbl->key + 100);
7064 emitcode ("rrc", "a");
7065 emitcode ("", "%05d$:", tlbl1->key + 100);
7066 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7067 aopPut (AOP (result), "a", 0);
7071 reAdjustPreg (AOP (result));
7072 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7073 emitcode ("", "%05d$:", tlbl->key + 100);
7077 l = aopGet (AOP (result), offset, FALSE, FALSE);
7079 emitcode ("rrc", "a");
7080 aopPut (AOP (result), "a", offset--);
7082 reAdjustPreg (AOP (result));
7084 emitcode ("", "%05d$:", tlbl1->key + 100);
7085 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7088 freeAsmop (left, NULL, ic, TRUE);
7089 freeAsmop (result, NULL, ic, TRUE);
7092 /*-----------------------------------------------------------------*/
7093 /* genUnpackBits - generates code for unpacking bits */
7094 /*-----------------------------------------------------------------*/
7096 genUnpackBits (operand * result, char *rname, int ptype)
7104 D(emitcode ("; genUnpackBits",""));
7106 etype = getSpec (operandType (result));
7107 rsize = getSize (operandType (result));
7108 /* read the first byte */
7114 emitcode ("mov", "a,@%s", rname);
7118 emitcode ("movx", "a,@%s", rname);
7122 emitcode ("movx", "a,@dptr");
7126 emitcode ("clr", "a");
7127 emitcode ("movc", "a,@a+dptr");
7131 emitcode ("lcall", "__gptrget");
7135 rlen = SPEC_BLEN (etype);
7137 /* if we have bitdisplacement then it fits */
7138 /* into this byte completely or if length is */
7139 /* less than a byte */
7140 if ((shCnt = SPEC_BSTR (etype)) ||
7141 (SPEC_BLEN (etype) <= 8))
7144 /* shift right acc */
7147 emitcode ("anl", "a,#0x%02x",
7148 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7149 aopPut (AOP (result), "a", offset++);
7153 /* bit field did not fit in a byte */
7154 aopPut (AOP (result), "a", offset++);
7163 emitcode ("inc", "%s", rname);
7164 emitcode ("mov", "a,@%s", rname);
7168 emitcode ("inc", "%s", rname);
7169 emitcode ("movx", "a,@%s", rname);
7173 emitcode ("inc", "dptr");
7174 emitcode ("movx", "a,@dptr");
7178 emitcode ("clr", "a");
7179 emitcode ("inc", "dptr");
7180 emitcode ("movc", "a,@a+dptr");
7184 emitcode ("inc", "dptr");
7185 emitcode ("lcall", "__gptrget");
7190 /* if we are done */
7194 aopPut (AOP (result), "a", offset++);
7200 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7202 aopPut (AOP (result), "a", offset++);
7210 aopPut (AOP (result), zero, offset++);
7216 /*-----------------------------------------------------------------*/
7217 /* genDataPointerGet - generates code when ptr offset is known */
7218 /*-----------------------------------------------------------------*/
7220 genDataPointerGet (operand * left,
7226 int size, offset = 0;
7228 D(emitcode ("; genDataPointerGet",""));
7230 aopOp (result, ic, TRUE);
7232 /* get the string representation of the name */
7233 l = aopGet (AOP (left), 0, FALSE, TRUE);
7234 size = AOP_SIZE (result);
7238 sprintf (buffer, "(%s + %d)", l + 1, offset);
7240 sprintf (buffer, "%s", l + 1);
7241 aopPut (AOP (result), buffer, offset++);
7244 freeAsmop (left, NULL, ic, TRUE);
7245 freeAsmop (result, NULL, ic, TRUE);
7248 /*-----------------------------------------------------------------*/
7249 /* genNearPointerGet - emitcode for near pointer fetch */
7250 /*-----------------------------------------------------------------*/
7252 genNearPointerGet (operand * left,
7260 sym_link *rtype, *retype;
7261 sym_link *ltype = operandType (left);
7264 D(emitcode ("; genNearPointerGet",""));
7266 rtype = operandType (result);
7267 retype = getSpec (rtype);
7269 aopOp (left, ic, FALSE);
7271 /* if left is rematerialisable and
7272 result is not bit variable type and
7273 the left is pointer to data space i.e
7274 lower 128 bytes of space */
7275 if (AOP_TYPE (left) == AOP_IMMD &&
7276 !IS_BITVAR (retype) &&
7277 DCL_TYPE (ltype) == POINTER)
7279 genDataPointerGet (left, result, ic);
7283 /* if the value is already in a pointer register
7284 then don't need anything more */
7285 if (!AOP_INPREG (AOP (left)))
7287 /* otherwise get a free pointer register */
7289 preg = getFreePtr (ic, &aop, FALSE);
7290 emitcode ("mov", "%s,%s",
7292 aopGet (AOP (left), 0, FALSE, TRUE));
7296 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7298 //aopOp (result, ic, FALSE);
7299 aopOp (result, ic, result?TRUE:FALSE);
7301 /* if bitfield then unpack the bits */
7302 if (IS_BITVAR (retype))
7303 genUnpackBits (result, rname, POINTER);
7306 /* we have can just get the values */
7307 int size = AOP_SIZE (result);
7312 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7315 emitcode ("mov", "a,@%s", rname);
7316 aopPut (AOP (result), "a", offset);
7320 sprintf (buffer, "@%s", rname);
7321 aopPut (AOP (result), buffer, offset);
7325 emitcode ("inc", "%s", rname);
7329 /* now some housekeeping stuff */
7330 if (aop) /* we had to allocate for this iCode */
7332 if (pi) { /* post increment present */
7333 aopPut(AOP ( left ),rname,0);
7335 freeAsmop (NULL, aop, ic, TRUE);
7339 /* we did not allocate which means left
7340 already in a pointer register, then
7341 if size > 0 && this could be used again
7342 we have to point it back to where it
7344 if ((AOP_SIZE (result) > 1 &&
7345 !OP_SYMBOL (left)->remat &&
7346 (OP_SYMBOL (left)->liveTo > ic->seq ||
7350 int size = AOP_SIZE (result) - 1;
7352 emitcode ("dec", "%s", rname);
7357 freeAsmop (left, NULL, ic, TRUE);
7358 freeAsmop (result, NULL, ic, TRUE);
7359 if (pi) pi->generated = 1;
7362 /*-----------------------------------------------------------------*/
7363 /* genPagedPointerGet - emitcode for paged pointer fetch */
7364 /*-----------------------------------------------------------------*/
7366 genPagedPointerGet (operand * left,
7374 sym_link *rtype, *retype;
7376 D(emitcode ("; genPagedPointerGet",""));
7378 rtype = operandType (result);
7379 retype = getSpec (rtype);
7381 aopOp (left, ic, FALSE);
7383 /* if the value is already in a pointer register
7384 then don't need anything more */
7385 if (!AOP_INPREG (AOP (left)))
7387 /* otherwise get a free pointer register */
7389 preg = getFreePtr (ic, &aop, FALSE);
7390 emitcode ("mov", "%s,%s",
7392 aopGet (AOP (left), 0, FALSE, TRUE));
7396 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7398 aopOp (result, ic, FALSE);
7400 /* if bitfield then unpack the bits */
7401 if (IS_BITVAR (retype))
7402 genUnpackBits (result, rname, PPOINTER);
7405 /* we have can just get the values */
7406 int size = AOP_SIZE (result);
7412 emitcode ("movx", "a,@%s", rname);
7413 aopPut (AOP (result), "a", offset);
7418 emitcode ("inc", "%s", rname);
7422 /* now some housekeeping stuff */
7423 if (aop) /* we had to allocate for this iCode */
7425 if (pi) aopPut ( AOP (left), rname, 0);
7426 freeAsmop (NULL, aop, ic, TRUE);
7430 /* we did not allocate which means left
7431 already in a pointer register, then
7432 if size > 0 && this could be used again
7433 we have to point it back to where it
7435 if ((AOP_SIZE (result) > 1 &&
7436 !OP_SYMBOL (left)->remat &&
7437 (OP_SYMBOL (left)->liveTo > ic->seq ||
7441 int size = AOP_SIZE (result) - 1;
7443 emitcode ("dec", "%s", rname);
7448 freeAsmop (left, NULL, ic, TRUE);
7449 freeAsmop (result, NULL, ic, TRUE);
7450 if (pi) pi->generated = 1;
7454 /*-----------------------------------------------------------------*/
7455 /* genFarPointerGet - gget value from far space */
7456 /*-----------------------------------------------------------------*/
7458 genFarPointerGet (operand * left,
7459 operand * result, iCode * ic, iCode * pi)
7462 sym_link *retype = getSpec (operandType (result));
7464 D(emitcode ("; genFarPointerGet",""));
7466 aopOp (left, ic, FALSE);
7468 /* if the operand is already in dptr
7469 then we do nothing else we move the value to dptr */
7470 if (AOP_TYPE (left) != AOP_STR)
7472 /* if this is remateriazable */
7473 if (AOP_TYPE (left) == AOP_IMMD)
7474 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7476 { /* we need to get it byte by byte */
7477 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7478 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7481 /* so dptr know contains the address */
7482 aopOp (result, ic, FALSE);
7484 /* if bit then unpack */
7485 if (IS_BITVAR (retype))
7486 genUnpackBits (result, "dptr", FPOINTER);
7489 size = AOP_SIZE (result);
7494 emitcode ("movx", "a,@dptr");
7495 aopPut (AOP (result), "a", offset++);
7497 emitcode ("inc", "dptr");
7501 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7502 aopPut ( AOP (left), "dpl", 0);
7503 aopPut ( AOP (left), "dph", 1);
7506 freeAsmop (left, NULL, ic, TRUE);
7507 freeAsmop (result, NULL, ic, TRUE);
7510 /*-----------------------------------------------------------------*/
7511 /* genCodePointerGet - gget value from code space */
7512 /*-----------------------------------------------------------------*/
7514 genCodePointerGet (operand * left,
7515 operand * result, iCode * ic, iCode *pi)
7518 sym_link *retype = getSpec (operandType (result));
7520 D(emitcode ("; genCodePointerGet",""));
7522 aopOp (left, ic, FALSE);
7524 /* if the operand is already in dptr
7525 then we do nothing else we move the value to dptr */
7526 if (AOP_TYPE (left) != AOP_STR)
7528 /* if this is remateriazable */
7529 if (AOP_TYPE (left) == AOP_IMMD)
7530 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7532 { /* we need to get it byte by byte */
7533 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7534 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7537 /* so dptr know contains the address */
7538 aopOp (result, ic, FALSE);
7540 /* if bit then unpack */
7541 if (IS_BITVAR (retype))
7542 genUnpackBits (result, "dptr", CPOINTER);
7545 size = AOP_SIZE (result);
7552 emitcode ("clr", "a");
7553 emitcode ("movc", "a,@a+dptr");
7554 aopPut (AOP (result), "a", offset++);
7555 emitcode ("inc", "dptr");
7559 emitcode ("mov", "a,#0x%02x", offset);
7560 emitcode ("movc", "a,@a+dptr");
7561 aopPut (AOP (result), "a", offset++);
7566 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7567 aopPut ( AOP (left), "dpl", 0);
7568 aopPut ( AOP (left), "dph", 1);
7571 freeAsmop (left, NULL, ic, TRUE);
7572 freeAsmop (result, NULL, ic, TRUE);
7575 /*-----------------------------------------------------------------*/
7576 /* genGenPointerGet - gget value from generic pointer space */
7577 /*-----------------------------------------------------------------*/
7579 genGenPointerGet (operand * left,
7580 operand * result, iCode * ic, iCode *pi)
7583 sym_link *retype = getSpec (operandType (result));
7585 D(emitcode ("; genGenPointerGet",""));
7587 aopOp (left, ic, FALSE);
7589 /* if the operand is already in dptr
7590 then we do nothing else we move the value to dptr */
7591 if (AOP_TYPE (left) != AOP_STR)
7593 /* if this is remateriazable */
7594 if (AOP_TYPE (left) == AOP_IMMD)
7596 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7597 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7598 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7600 emitcode ("mov", "b,#%d", pointerCode (retype));
7603 { /* we need to get it byte by byte */
7604 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7605 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7606 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7609 /* so dptr know contains the address */
7610 aopOp (result, ic, FALSE);
7612 /* if bit then unpack */
7613 if (IS_BITVAR (retype))
7614 genUnpackBits (result, "dptr", GPOINTER);
7617 size = AOP_SIZE (result);
7622 emitcode ("lcall", "__gptrget");
7623 aopPut (AOP (result), "a", offset++);
7625 emitcode ("inc", "dptr");
7629 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7630 aopPut ( AOP (left), "dpl", 0);
7631 aopPut ( AOP (left), "dph", 1);
7634 freeAsmop (left, NULL, ic, TRUE);
7635 freeAsmop (result, NULL, ic, TRUE);
7638 /*-----------------------------------------------------------------*/
7639 /* genPointerGet - generate code for pointer get */
7640 /*-----------------------------------------------------------------*/
7642 genPointerGet (iCode * ic, iCode *pi)
7644 operand *left, *result;
7645 sym_link *type, *etype;
7648 D(emitcode ("; genPointerGet",""));
7650 left = IC_LEFT (ic);
7651 result = IC_RESULT (ic);
7653 /* depending on the type of pointer we need to
7654 move it to the correct pointer register */
7655 type = operandType (left);
7656 etype = getSpec (type);
7657 /* if left is of type of pointer then it is simple */
7658 if (IS_PTR (type) && !IS_FUNC (type->next))
7659 p_type = DCL_TYPE (type);
7662 /* we have to go by the storage class */
7663 p_type = PTR_TYPE (SPEC_OCLS (etype));
7666 /* special case when cast remat */
7667 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7668 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7669 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7670 type = operandType (left);
7671 p_type = DCL_TYPE (type);
7673 /* now that we have the pointer type we assign
7674 the pointer values */
7680 genNearPointerGet (left, result, ic, pi);
7684 genPagedPointerGet (left, result, ic, pi);
7688 genFarPointerGet (left, result, ic, pi);
7692 genCodePointerGet (left, result, ic, pi);
7696 genGenPointerGet (left, result, ic, pi);
7702 /*-----------------------------------------------------------------*/
7703 /* genPackBits - generates code for packed bit storage */
7704 /*-----------------------------------------------------------------*/
7706 genPackBits (sym_link * etype,
7708 char *rname, int p_type)
7716 D(emitcode ("; genPackBits",""));
7718 blen = SPEC_BLEN (etype);
7719 bstr = SPEC_BSTR (etype);
7721 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7724 /* if the bit lenth is less than or */
7725 /* it exactly fits a byte then */
7726 if (SPEC_BLEN (etype) <= 8)
7728 shCount = SPEC_BSTR (etype);
7730 /* shift left acc */
7733 if (SPEC_BLEN (etype) < 8)
7734 { /* if smaller than a byte */
7740 emitcode ("mov", "b,a");
7741 emitcode ("mov", "a,@%s", rname);
7745 emitcode ("mov", "b,a");
7746 emitcode ("movx", "a,@dptr");
7750 emitcode ("push", "b");
7751 emitcode ("push", "acc");
7752 emitcode ("lcall", "__gptrget");
7753 emitcode ("pop", "b");
7757 emitcode ("anl", "a,#0x%02x", (unsigned char)
7758 ((unsigned char) (0xFF << (blen + bstr)) |
7759 (unsigned char) (0xFF >> (8 - bstr))));
7760 emitcode ("orl", "a,b");
7761 if (p_type == GPOINTER)
7762 emitcode ("pop", "b");
7769 emitcode ("mov", "@%s,a", rname);
7773 emitcode ("movx", "@dptr,a");
7777 emitcode ("lcall", "__gptrput");
7782 if (SPEC_BLEN (etype) <= 8)
7785 emitcode ("inc", "%s", rname);
7786 rLen = SPEC_BLEN (etype);
7788 /* now generate for lengths greater than one byte */
7792 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7804 emitcode ("mov", "@%s,a", rname);
7807 emitcode ("mov", "@%s,%s", rname, l);
7812 emitcode ("movx", "@dptr,a");
7817 emitcode ("lcall", "__gptrput");
7820 emitcode ("inc", "%s", rname);
7825 /* last last was not complete */
7828 /* save the byte & read byte */
7832 emitcode ("mov", "b,a");
7833 emitcode ("mov", "a,@%s", rname);
7837 emitcode ("mov", "b,a");
7838 emitcode ("movx", "a,@dptr");
7842 emitcode ("push", "b");
7843 emitcode ("push", "acc");
7844 emitcode ("lcall", "__gptrget");
7845 emitcode ("pop", "b");
7849 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7850 emitcode ("orl", "a,b");
7853 if (p_type == GPOINTER)
7854 emitcode ("pop", "b");
7860 emitcode ("mov", "@%s,a", rname);
7864 emitcode ("movx", "@dptr,a");
7868 emitcode ("lcall", "__gptrput");
7872 /*-----------------------------------------------------------------*/
7873 /* genDataPointerSet - remat pointer to data space */
7874 /*-----------------------------------------------------------------*/
7876 genDataPointerSet (operand * right,
7880 int size, offset = 0;
7881 char *l, buffer[256];
7883 D(emitcode ("; genDataPointerSet",""));
7885 aopOp (right, ic, FALSE);
7887 l = aopGet (AOP (result), 0, FALSE, TRUE);
7888 size = AOP_SIZE (right);
7892 sprintf (buffer, "(%s + %d)", l + 1, offset);
7894 sprintf (buffer, "%s", l + 1);
7895 emitcode ("mov", "%s,%s", buffer,
7896 aopGet (AOP (right), offset++, FALSE, FALSE));
7899 freeAsmop (right, NULL, ic, TRUE);
7900 freeAsmop (result, NULL, ic, TRUE);
7903 /*-----------------------------------------------------------------*/
7904 /* genNearPointerSet - emitcode for near pointer put */
7905 /*-----------------------------------------------------------------*/
7907 genNearPointerSet (operand * right,
7915 sym_link *retype, *letype;
7916 sym_link *ptype = operandType (result);
7918 D(emitcode ("; genNearPointerSet",""));
7920 retype = getSpec (operandType (right));
7921 letype = getSpec (ptype);
7922 aopOp (result, ic, FALSE);
7924 /* if the result is rematerializable &
7925 in data space & not a bit variable */
7926 if (AOP_TYPE (result) == AOP_IMMD &&
7927 DCL_TYPE (ptype) == POINTER &&
7928 !IS_BITVAR (retype) &&
7929 !IS_BITVAR (letype))
7931 genDataPointerSet (right, result, ic);
7935 /* if the value is already in a pointer register
7936 then don't need anything more */
7937 if (!AOP_INPREG (AOP (result)))
7940 //AOP_TYPE (result) == AOP_STK
7944 // Aha, it is a pointer, just in disguise.
7945 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7948 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7949 __FILE__, __LINE__);
7954 rname++; // skip the '@'.
7959 /* otherwise get a free pointer register */
7961 preg = getFreePtr (ic, &aop, FALSE);
7962 emitcode ("mov", "%s,%s",
7964 aopGet (AOP (result), 0, FALSE, TRUE));
7970 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7973 aopOp (right, ic, FALSE);
7975 /* if bitfield then unpack the bits */
7976 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7977 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7980 /* we have can just get the values */
7981 int size = AOP_SIZE (right);
7986 l = aopGet (AOP (right), offset, FALSE, TRUE);
7990 emitcode ("mov", "@%s,a", rname);
7993 emitcode ("mov", "@%s,%s", rname, l);
7995 emitcode ("inc", "%s", rname);
8000 /* now some housekeeping stuff */
8001 if (aop) /* we had to allocate for this iCode */
8003 if (pi) aopPut (AOP (result),rname,0);
8004 freeAsmop (NULL, aop, ic, TRUE);
8008 /* we did not allocate which means left
8009 already in a pointer register, then
8010 if size > 0 && this could be used again
8011 we have to point it back to where it
8013 if ((AOP_SIZE (right) > 1 &&
8014 !OP_SYMBOL (result)->remat &&
8015 (OP_SYMBOL (result)->liveTo > ic->seq ||
8019 int size = AOP_SIZE (right) - 1;
8021 emitcode ("dec", "%s", rname);
8026 if (pi) pi->generated = 1;
8027 freeAsmop (result, NULL, ic, TRUE);
8028 freeAsmop (right, NULL, ic, TRUE);
8031 /*-----------------------------------------------------------------*/
8032 /* genPagedPointerSet - emitcode for Paged pointer put */
8033 /*-----------------------------------------------------------------*/
8035 genPagedPointerSet (operand * right,
8043 sym_link *retype, *letype;
8045 D(emitcode ("; genPagedPointerSet",""));
8047 retype = getSpec (operandType (right));
8048 letype = getSpec (operandType (result));
8050 aopOp (result, ic, FALSE);
8052 /* if the value is already in a pointer register
8053 then don't need anything more */
8054 if (!AOP_INPREG (AOP (result)))
8056 /* otherwise get a free pointer register */
8058 preg = getFreePtr (ic, &aop, FALSE);
8059 emitcode ("mov", "%s,%s",
8061 aopGet (AOP (result), 0, FALSE, TRUE));
8065 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8067 aopOp (right, ic, FALSE);
8069 /* if bitfield then unpack the bits */
8070 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8071 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8074 /* we have can just get the values */
8075 int size = AOP_SIZE (right);
8080 l = aopGet (AOP (right), offset, FALSE, TRUE);
8083 emitcode ("movx", "@%s,a", rname);
8086 emitcode ("inc", "%s", rname);
8092 /* now some housekeeping stuff */
8093 if (aop) /* we had to allocate for this iCode */
8095 if (pi) aopPut (AOP (result),rname,0);
8096 freeAsmop (NULL, aop, ic, TRUE);
8100 /* we did not allocate which means left
8101 already in a pointer register, then
8102 if size > 0 && this could be used again
8103 we have to point it back to where it
8105 if (AOP_SIZE (right) > 1 &&
8106 !OP_SYMBOL (result)->remat &&
8107 (OP_SYMBOL (result)->liveTo > ic->seq ||
8110 int size = AOP_SIZE (right) - 1;
8112 emitcode ("dec", "%s", rname);
8117 if (pi) pi->generated = 1;
8118 freeAsmop (result, NULL, ic, TRUE);
8119 freeAsmop (right, NULL, ic, TRUE);
8124 /*-----------------------------------------------------------------*/
8125 /* genFarPointerSet - set value from far space */
8126 /*-----------------------------------------------------------------*/
8128 genFarPointerSet (operand * right,
8129 operand * result, iCode * ic, iCode * pi)
8132 sym_link *retype = getSpec (operandType (right));
8133 sym_link *letype = getSpec (operandType (result));
8135 D(emitcode ("; genFarPointerSet",""));
8137 aopOp (result, ic, FALSE);
8139 /* if the operand is already in dptr
8140 then we do nothing else we move the value to dptr */
8141 if (AOP_TYPE (result) != AOP_STR)
8143 /* if this is remateriazable */
8144 if (AOP_TYPE (result) == AOP_IMMD)
8145 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8147 { /* we need to get it byte by byte */
8148 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8149 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8152 /* so dptr know contains the address */
8153 aopOp (right, ic, FALSE);
8155 /* if bit then unpack */
8156 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8157 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8160 size = AOP_SIZE (right);
8165 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8167 emitcode ("movx", "@dptr,a");
8169 emitcode ("inc", "dptr");
8172 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8173 aopPut (AOP(result),"dpl",0);
8174 aopPut (AOP(result),"dph",1);
8177 freeAsmop (result, NULL, ic, TRUE);
8178 freeAsmop (right, NULL, ic, TRUE);
8181 /*-----------------------------------------------------------------*/
8182 /* genGenPointerSet - set value from generic pointer space */
8183 /*-----------------------------------------------------------------*/
8185 genGenPointerSet (operand * right,
8186 operand * result, iCode * ic, iCode * pi)
8189 sym_link *retype = getSpec (operandType (right));
8190 sym_link *letype = getSpec (operandType (result));
8192 D(emitcode ("; genGenPointerSet",""));
8194 aopOp (result, ic, FALSE);
8196 /* if the operand is already in dptr
8197 then we do nothing else we move the value to dptr */
8198 if (AOP_TYPE (result) != AOP_STR)
8200 /* if this is remateriazable */
8201 if (AOP_TYPE (result) == AOP_IMMD)
8203 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8204 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8205 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8207 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8210 { /* we need to get it byte by byte */
8211 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8212 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8213 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8216 /* so dptr know contains the address */
8217 aopOp (right, ic, FALSE);
8219 /* if bit then unpack */
8220 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8221 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8224 size = AOP_SIZE (right);
8229 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8231 emitcode ("lcall", "__gptrput");
8233 emitcode ("inc", "dptr");
8237 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8238 aopPut (AOP(result),"dpl",0);
8239 aopPut (AOP(result),"dph",1);
8242 freeAsmop (result, NULL, ic, TRUE);
8243 freeAsmop (right, NULL, ic, TRUE);
8246 /*-----------------------------------------------------------------*/
8247 /* genPointerSet - stores the value into a pointer location */
8248 /*-----------------------------------------------------------------*/
8250 genPointerSet (iCode * ic, iCode *pi)
8252 operand *right, *result;
8253 sym_link *type, *etype;
8256 D(emitcode ("; genPointerSet",""));
8258 right = IC_RIGHT (ic);
8259 result = IC_RESULT (ic);
8261 /* depending on the type of pointer we need to
8262 move it to the correct pointer register */
8263 type = operandType (result);
8264 etype = getSpec (type);
8265 /* if left is of type of pointer then it is simple */
8266 if (IS_PTR (type) && !IS_FUNC (type->next))
8268 p_type = DCL_TYPE (type);
8272 /* we have to go by the storage class */
8273 p_type = PTR_TYPE (SPEC_OCLS (etype));
8276 /* special case when cast remat */
8277 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8278 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8279 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8280 type = operandType (result);
8281 p_type = DCL_TYPE (type);
8283 /* now that we have the pointer type we assign
8284 the pointer values */
8290 genNearPointerSet (right, result, ic, pi);
8294 genPagedPointerSet (right, result, ic, pi);
8298 genFarPointerSet (right, result, ic, pi);
8302 genGenPointerSet (right, result, ic, pi);
8306 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8307 "genPointerSet: illegal pointer type");
8312 /*-----------------------------------------------------------------*/
8313 /* genIfx - generate code for Ifx statement */
8314 /*-----------------------------------------------------------------*/
8316 genIfx (iCode * ic, iCode * popIc)
8318 operand *cond = IC_COND (ic);
8321 D(emitcode ("; genIfx",""));
8323 aopOp (cond, ic, FALSE);
8325 /* get the value into acc */
8326 if (AOP_TYPE (cond) != AOP_CRY)
8330 /* the result is now in the accumulator */
8331 freeAsmop (cond, NULL, ic, TRUE);
8333 /* if there was something to be popped then do it */
8337 /* if the condition is a bit variable */
8338 if (isbit && IS_ITEMP (cond) &&
8340 genIfxJump (ic, SPIL_LOC (cond)->rname);
8341 else if (isbit && !IS_ITEMP (cond))
8342 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8344 genIfxJump (ic, "a");
8349 /*-----------------------------------------------------------------*/
8350 /* genAddrOf - generates code for address of */
8351 /*-----------------------------------------------------------------*/
8353 genAddrOf (iCode * ic)
8355 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8358 D(emitcode ("; genAddrOf",""));
8360 aopOp (IC_RESULT (ic), ic, FALSE);
8362 /* if the operand is on the stack then we
8363 need to get the stack offset of this
8367 /* if it has an offset then we need to compute
8371 emitcode ("mov", "a,_bp");
8372 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8373 ((char) (sym->stack - _G.nRegsSaved)) :
8374 ((char) sym->stack)) & 0xff);
8375 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8379 /* we can just move _bp */
8380 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8382 /* fill the result with zero */
8383 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8388 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8394 /* object not on stack then we need the name */
8395 size = AOP_SIZE (IC_RESULT (ic));
8400 char s[SDCC_NAME_MAX];
8402 sprintf (s, "#(%s >> %d)",
8406 sprintf (s, "#%s", sym->rname);
8407 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8411 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8415 /*-----------------------------------------------------------------*/
8416 /* genFarFarAssign - assignment when both are in far space */
8417 /*-----------------------------------------------------------------*/
8419 genFarFarAssign (operand * result, operand * right, iCode * ic)
8421 int size = AOP_SIZE (right);
8425 D(emitcode ("; genFarFarAssign",""));
8427 /* first push the right side on to the stack */
8430 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8432 emitcode ("push", "acc");
8435 freeAsmop (right, NULL, ic, FALSE);
8436 /* now assign DPTR to result */
8437 aopOp (result, ic, FALSE);
8438 size = AOP_SIZE (result);
8441 emitcode ("pop", "acc");
8442 aopPut (AOP (result), "a", --offset);
8444 freeAsmop (result, NULL, ic, FALSE);
8448 /*-----------------------------------------------------------------*/
8449 /* genAssign - generate code for assignment */
8450 /*-----------------------------------------------------------------*/
8452 genAssign (iCode * ic)
8454 operand *result, *right;
8456 unsigned long lit = 0L;
8458 D(emitcode("; genAssign",""));
8460 result = IC_RESULT (ic);
8461 right = IC_RIGHT (ic);
8463 /* if they are the same */
8464 if (operandsEqu (result, right)) {
8468 aopOp (right, ic, FALSE);
8470 /* special case both in far space */
8471 if (AOP_TYPE (right) == AOP_DPTR &&
8472 IS_TRUE_SYMOP (result) &&
8473 isOperandInFarSpace (result))
8476 genFarFarAssign (result, right, ic);
8480 aopOp (result, ic, TRUE);
8482 /* if they are the same registers */
8483 if (sameRegs (AOP (right), AOP (result)))
8486 /* if the result is a bit */
8487 if (AOP_TYPE (result) == AOP_CRY)
8490 /* if the right size is a literal then
8491 we know what the value is */
8492 if (AOP_TYPE (right) == AOP_LIT)
8494 if (((int) operandLitValue (right)))
8495 aopPut (AOP (result), one, 0);
8497 aopPut (AOP (result), zero, 0);
8501 /* the right is also a bit variable */
8502 if (AOP_TYPE (right) == AOP_CRY)
8504 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8505 aopPut (AOP (result), "c", 0);
8511 aopPut (AOP (result), "a", 0);
8515 /* bit variables done */
8517 size = AOP_SIZE (result);
8519 if (AOP_TYPE (right) == AOP_LIT)
8520 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8522 (AOP_TYPE (result) != AOP_REG) &&
8523 (AOP_TYPE (right) == AOP_LIT) &&
8524 !IS_FLOAT (operandType (right)) &&
8527 emitcode ("clr", "a");
8530 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8531 aopPut (AOP (result), "a", size);
8533 aopPut (AOP (result),
8534 aopGet (AOP (right), size, FALSE, FALSE),
8542 aopPut (AOP (result),
8543 aopGet (AOP (right), offset, FALSE, FALSE),
8550 freeAsmop (right, NULL, ic, TRUE);
8551 freeAsmop (result, NULL, ic, TRUE);
8554 /*-----------------------------------------------------------------*/
8555 /* genJumpTab - genrates code for jump table */
8556 /*-----------------------------------------------------------------*/
8558 genJumpTab (iCode * ic)
8563 D(emitcode ("; genJumpTab",""));
8565 aopOp (IC_JTCOND (ic), ic, FALSE);
8566 /* get the condition into accumulator */
8567 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8569 /* multiply by three */
8570 emitcode ("add", "a,acc");
8571 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8572 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8574 jtab = newiTempLabel (NULL);
8575 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8576 emitcode ("jmp", "@a+dptr");
8577 emitcode ("", "%05d$:", jtab->key + 100);
8578 /* now generate the jump labels */
8579 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8580 jtab = setNextItem (IC_JTLABELS (ic)))
8581 emitcode ("ljmp", "%05d$", jtab->key + 100);
8585 /*-----------------------------------------------------------------*/
8586 /* genCast - gen code for casting */
8587 /*-----------------------------------------------------------------*/
8589 genCast (iCode * ic)
8591 operand *result = IC_RESULT (ic);
8592 sym_link *ctype = operandType (IC_LEFT (ic));
8593 sym_link *rtype = operandType (IC_RIGHT (ic));
8594 operand *right = IC_RIGHT (ic);
8597 D(emitcode("; genCast",""));
8599 /* if they are equivalent then do nothing */
8600 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8603 aopOp (right, ic, FALSE);
8604 aopOp (result, ic, FALSE);
8606 /* if the result is a bit */
8607 if (IS_BITVAR(OP_SYMBOL(result)->type))
8609 /* if the right size is a literal then
8610 we know what the value is */
8611 if (AOP_TYPE (right) == AOP_LIT)
8613 if (((int) operandLitValue (right)))
8614 aopPut (AOP (result), one, 0);
8616 aopPut (AOP (result), zero, 0);
8621 /* the right is also a bit variable */
8622 if (AOP_TYPE (right) == AOP_CRY)
8624 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8625 aopPut (AOP (result), "c", 0);
8631 aopPut (AOP (result), "a", 0);
8635 /* if they are the same size : or less */
8636 if (AOP_SIZE (result) <= AOP_SIZE (right))
8639 /* if they are in the same place */
8640 if (sameRegs (AOP (right), AOP (result)))
8643 /* if they in different places then copy */
8644 size = AOP_SIZE (result);
8648 aopPut (AOP (result),
8649 aopGet (AOP (right), offset, FALSE, FALSE),
8657 /* if the result is of type pointer */
8662 sym_link *type = operandType (right);
8663 sym_link *etype = getSpec (type);
8665 /* pointer to generic pointer */
8666 if (IS_GENPTR (ctype))
8669 p_type = DCL_TYPE (type);
8672 if (SPEC_SCLS(etype)==S_REGISTER) {
8673 // let's assume it is a generic pointer
8676 /* we have to go by the storage class */
8677 p_type = PTR_TYPE (SPEC_OCLS (etype));
8681 /* the first two bytes are known */
8682 size = GPTRSIZE - 1;
8686 aopPut (AOP (result),
8687 aopGet (AOP (right), offset, FALSE, FALSE),
8691 /* the last byte depending on type */
8693 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8698 // pointerTypeToGPByte will have bitched.
8702 sprintf(gpValStr, "#0x%d", gpVal);
8703 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8708 /* just copy the pointers */
8709 size = AOP_SIZE (result);
8713 aopPut (AOP (result),
8714 aopGet (AOP (right), offset, FALSE, FALSE),
8721 /* so we now know that the size of destination is greater
8722 than the size of the source */
8723 /* we move to result for the size of source */
8724 size = AOP_SIZE (right);
8728 aopPut (AOP (result),
8729 aopGet (AOP (right), offset, FALSE, FALSE),
8734 /* now depending on the sign of the source && destination */
8735 size = AOP_SIZE (result) - AOP_SIZE (right);
8736 /* if unsigned or not an integral type */
8737 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8740 aopPut (AOP (result), zero, offset++);
8744 /* we need to extend the sign :{ */
8745 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8748 emitcode ("rlc", "a");
8749 emitcode ("subb", "a,acc");
8751 aopPut (AOP (result), "a", offset++);
8754 /* we are done hurray !!!! */
8757 freeAsmop (right, NULL, ic, TRUE);
8758 freeAsmop (result, NULL, ic, TRUE);
8762 /*-----------------------------------------------------------------*/
8763 /* genDjnz - generate decrement & jump if not zero instrucion */
8764 /*-----------------------------------------------------------------*/
8766 genDjnz (iCode * ic, iCode * ifx)
8772 D(emitcode ("; genDjnz",""));
8774 /* if the if condition has a false label
8775 then we cannot save */
8779 /* if the minus is not of the form
8781 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8782 !IS_OP_LITERAL (IC_RIGHT (ic)))
8785 if (operandLitValue (IC_RIGHT (ic)) != 1)
8788 /* if the size of this greater than one then no
8790 if (getSize (operandType (IC_RESULT (ic))) > 1)
8793 /* otherwise we can save BIG */
8794 lbl = newiTempLabel (NULL);
8795 lbl1 = newiTempLabel (NULL);
8797 aopOp (IC_RESULT (ic), ic, FALSE);
8799 if (AOP_NEEDSACC(IC_RESULT(ic)))
8801 /* If the result is accessed indirectly via
8802 * the accumulator, we must explicitly write
8803 * it back after the decrement.
8805 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8807 if (strcmp(rByte, "a"))
8809 /* Something is hopelessly wrong */
8810 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8811 __FILE__, __LINE__);
8812 /* We can just give up; the generated code will be inefficient,
8815 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8818 emitcode ("dec", "%s", rByte);
8819 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8820 emitcode ("jnz", "%05d$", lbl->key + 100);
8822 else if (IS_AOP_PREG (IC_RESULT (ic)))
8824 emitcode ("dec", "%s",
8825 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8826 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8827 emitcode ("jnz", "%05d$", lbl->key + 100);
8831 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8834 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8835 emitcode ("", "%05d$:", lbl->key + 100);
8836 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8837 emitcode ("", "%05d$:", lbl1->key + 100);
8839 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8844 /*-----------------------------------------------------------------*/
8845 /* genReceive - generate code for a receive iCode */
8846 /*-----------------------------------------------------------------*/
8848 genReceive (iCode * ic)
8850 int size = getSize (operandType (IC_RESULT (ic)));
8852 D(emitcode ("; genReceive",""));
8854 if (ic->argreg == 1) { /* first parameter */
8855 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8856 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8857 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8859 offset = fReturnSizeMCS51 - size;
8861 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8862 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8865 aopOp (IC_RESULT (ic), ic, FALSE);
8866 size = AOP_SIZE (IC_RESULT (ic));
8869 emitcode ("pop", "acc");
8870 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8875 aopOp (IC_RESULT (ic), ic, FALSE);
8877 assignResultValue (IC_RESULT (ic));
8879 } else { /* second receive onwards */
8881 aopOp (IC_RESULT (ic), ic, FALSE);
8882 rb1off = ic->argreg;
8884 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8887 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8890 /*-----------------------------------------------------------------*/
8891 /* gen51Code - generate code for 8051 based controllers */
8892 /*-----------------------------------------------------------------*/
8894 gen51Code (iCode * lic)
8899 lineHead = lineCurr = NULL;
8901 /* print the allocation information */
8902 if (allocInfo && currFunc)
8903 printAllocInfo (currFunc, codeOutFile);
8904 /* if debug information required */
8905 if (options.debug && currFunc)
8907 debugFile->writeFunction(currFunc);
8909 if (IS_STATIC (currFunc->etype))
8910 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8912 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8915 /* stack pointer name */
8916 if (options.useXstack)
8922 for (ic = lic; ic; ic = ic->next)
8925 if (ic->lineno && cln != ic->lineno)
8930 emitcode ("", "C$%s$%d$%d$%d ==.",
8931 FileBaseName (ic->filename), ic->lineno,
8932 ic->level, ic->block);
8935 if (!options.noCcodeInAsm) {
8936 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8937 printCLine(ic->filename, ic->lineno));
8941 if (options.iCodeInAsm) {
8945 for (i=0; i<8; i++) {
8946 sprintf (®sInUse[i],
8947 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8950 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8952 /* if the result is marked as
8953 spilt and rematerializable or code for
8954 this has already been generated then
8956 if (resultRemat (ic) || ic->generated)
8959 /* depending on the operation */
8979 /* IPOP happens only when trying to restore a
8980 spilt live range, if there is an ifx statement
8981 following this pop then the if statement might
8982 be using some of the registers being popped which
8983 would destory the contents of the register so
8984 we need to check for this condition and handle it */
8986 ic->next->op == IFX &&
8987 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8988 genIfx (ic->next, ic);
9006 genEndFunction (ic);
9026 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9043 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9047 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9054 /* note these two are xlated by algebraic equivalence
9055 during parsing SDCC.y */
9056 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9057 "got '>=' or '<=' shouldn't have come here");
9061 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9073 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9077 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9081 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9108 case GET_VALUE_AT_ADDRESS:
9109 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9113 if (POINTER_SET (ic))
9114 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9140 addSet (&_G.sendSet, ic);
9149 /* now we are ready to call the
9150 peep hole optimizer */
9151 if (!options.nopeep)
9152 peepHole (&lineHead);
9154 /* now do the actual printing */
9155 printLine (lineHead, codeOutFile);