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"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 static char *rb1regs[] = {
97 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
100 extern int mcs51_ptrRegReq;
101 extern int mcs51_nRegs;
102 extern FILE *codeOutFile;
103 static void saveRBank (int, iCode *, bool);
104 #define RESULTONSTACK(x) \
105 (IC_RESULT(x) && IC_RESULT(x)->aop && \
106 IC_RESULT(x)->aop->type == AOP_STK )
108 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
109 #define CLRC emitcode("clr","c")
110 #define SETC emitcode("setb","c")
112 static lineNode *lineHead = NULL;
113 static lineNode *lineCurr = NULL;
115 static unsigned char SLMask[] =
116 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
117 0xE0, 0xC0, 0x80, 0x00};
118 static unsigned char SRMask[] =
119 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
120 0x07, 0x03, 0x01, 0x00};
127 /*-----------------------------------------------------------------*/
128 /* emitcode - writes the code into a file : for now it is simple */
129 /*-----------------------------------------------------------------*/
131 emitcode (char *inst, char *fmt,...)
134 char lb[INITIAL_INLINEASM];
142 sprintf (lb, "%s\t", inst);
144 sprintf (lb, "%s", inst);
145 vsprintf (lb + (strlen (lb)), fmt, ap);
148 vsprintf (lb, fmt, ap);
150 while (isspace (*lbp))
154 lineCurr = (lineCurr ?
155 connectLine (lineCurr, newLineNode (lb)) :
156 (lineHead = newLineNode (lb)));
157 lineCurr->isInline = _G.inLine;
158 lineCurr->isDebug = _G.debugLine;
162 /*-----------------------------------------------------------------*/
163 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
164 /*-----------------------------------------------------------------*/
166 getFreePtr (iCode * ic, asmop ** aopp, bool result)
168 bool r0iu = FALSE, r1iu = FALSE;
169 bool r0ou = FALSE, r1ou = FALSE;
171 /* the logic: if r0 & r1 used in the instruction
172 then we are in trouble otherwise */
174 /* first check if r0 & r1 are used by this
175 instruction, in which case we are in trouble */
176 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
177 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
182 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
183 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
185 /* if no usage of r0 then return it */
188 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
189 (*aopp)->type = AOP_R0;
191 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
194 /* if no usage of r1 then return it */
197 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
198 (*aopp)->type = AOP_R1;
200 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
203 /* now we know they both have usage */
204 /* if r0 not used in this instruction */
207 /* push it if not already pushed */
210 emitcode ("push", "%s",
211 mcs51_regWithIdx (R0_IDX)->dname);
215 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
216 (*aopp)->type = AOP_R0;
218 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
221 /* if r1 not used then */
225 /* push it if not already pushed */
228 emitcode ("push", "%s",
229 mcs51_regWithIdx (R1_IDX)->dname);
233 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
234 (*aopp)->type = AOP_R1;
235 return mcs51_regWithIdx (R1_IDX);
239 /* I said end of world but not quite end of world yet */
240 /* if this is a result then we can push it on the stack */
243 (*aopp)->type = AOP_STK;
247 /* other wise this is true end of the world */
248 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
249 "getFreePtr should never reach here");
253 /*-----------------------------------------------------------------*/
254 /* newAsmop - creates a new asmOp */
255 /*-----------------------------------------------------------------*/
257 newAsmop (short type)
261 aop = Safe_calloc (1, sizeof (asmop));
266 /*-----------------------------------------------------------------*/
267 /* pointerCode - returns the code for a pointer type */
268 /*-----------------------------------------------------------------*/
270 pointerCode (sym_link * etype)
273 return PTR_TYPE (SPEC_OCLS (etype));
277 /*-----------------------------------------------------------------*/
278 /* aopForSym - for a true symbol */
279 /*-----------------------------------------------------------------*/
281 aopForSym (iCode * ic, symbol * sym, bool result)
286 wassertl (ic != NULL, "Got a null iCode");
287 wassertl (sym != NULL, "Got a null symbol");
289 space = SPEC_OCLS (sym->etype);
291 /* if already has one */
295 /* assign depending on the storage class */
296 /* if it is on the stack or indirectly addressable */
297 /* space we need to assign either r0 or r1 to it */
298 if (sym->onStack || sym->iaccess)
300 sym->aop = aop = newAsmop (0);
301 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
302 aop->size = getSize (sym->type);
304 /* now assign the address of the variable to
305 the pointer register */
306 if (aop->type != AOP_STK)
312 emitcode ("push", "acc");
314 emitcode ("mov", "a,_bp");
315 emitcode ("add", "a,#0x%02x",
317 ((char) (sym->stack - _G.nRegsSaved)) :
318 ((char) sym->stack)) & 0xff);
319 emitcode ("mov", "%s,a",
320 aop->aopu.aop_ptr->name);
323 emitcode ("pop", "acc");
326 emitcode ("mov", "%s,#%s",
327 aop->aopu.aop_ptr->name,
329 aop->paged = space->paged;
332 aop->aopu.aop_stk = sym->stack;
336 /* if in bit space */
337 if (IN_BITSPACE (space))
339 sym->aop = aop = newAsmop (AOP_CRY);
340 aop->aopu.aop_dir = sym->rname;
341 aop->size = getSize (sym->type);
344 /* if it is in direct space */
345 if (IN_DIRSPACE (space))
347 sym->aop = aop = newAsmop (AOP_DIR);
348 aop->aopu.aop_dir = sym->rname;
349 aop->size = getSize (sym->type);
353 /* special case for a function */
354 if (IS_FUNC (sym->type))
356 sym->aop = aop = newAsmop (AOP_IMMD);
357 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
358 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
359 aop->size = FPTRSIZE;
363 /* only remaining is far space */
364 /* in which case DPTR gets the address */
365 sym->aop = aop = newAsmop (AOP_DPTR);
366 emitcode ("mov", "dptr,#%s", sym->rname);
367 aop->size = getSize (sym->type);
369 /* if it is in code space */
370 if (IN_CODESPACE (space))
376 /*-----------------------------------------------------------------*/
377 /* aopForRemat - rematerialzes an object */
378 /*-----------------------------------------------------------------*/
380 aopForRemat (symbol * sym)
382 iCode *ic = sym->rematiCode;
383 asmop *aop = newAsmop (AOP_IMMD);
390 val += (int) operandLitValue (IC_RIGHT (ic));
391 else if (ic->op == '-')
392 val -= (int) operandLitValue (IC_RIGHT (ic));
393 else if (IS_CAST_ICODE(ic)) {
394 sym_link *from_type = operandType(IC_RIGHT(ic));
395 aop->aopu.aop_immd.from_cast_remat = 1;
396 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
397 ptr_type = DCL_TYPE(from_type);
398 if (ptr_type == IPOINTER) {
405 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
409 sprintf (buffer, "(%s %c 0x%04x)",
410 OP_SYMBOL (IC_LEFT (ic))->rname,
411 val >= 0 ? '+' : '-',
414 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
416 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
417 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
418 /* set immd2 field if required */
419 if (aop->aopu.aop_immd.from_cast_remat) {
420 sprintf(buffer,"#0x%02x",ptr_type);
421 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
422 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
428 /*-----------------------------------------------------------------*/
429 /* regsInCommon - two operands have some registers in common */
430 /*-----------------------------------------------------------------*/
432 regsInCommon (operand * op1, operand * op2)
437 /* if they have registers in common */
438 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
441 sym1 = OP_SYMBOL (op1);
442 sym2 = OP_SYMBOL (op2);
444 if (sym1->nRegs == 0 || sym2->nRegs == 0)
447 for (i = 0; i < sym1->nRegs; i++)
453 for (j = 0; j < sym2->nRegs; j++)
458 if (sym2->regs[j] == sym1->regs[i])
466 /*-----------------------------------------------------------------*/
467 /* operandsEqu - equivalent */
468 /*-----------------------------------------------------------------*/
470 operandsEqu (operand * op1, operand * op2)
474 /* if they not symbols */
475 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
478 sym1 = OP_SYMBOL (op1);
479 sym2 = OP_SYMBOL (op2);
481 /* if both are itemps & one is spilt
482 and the other is not then false */
483 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
484 sym1->isspilt != sym2->isspilt)
487 /* if they are the same */
491 if (strcmp (sym1->rname, sym2->rname) == 0)
495 /* if left is a tmp & right is not */
496 if (IS_ITEMP (op1) &&
499 (sym1->usl.spillLoc == sym2))
502 if (IS_ITEMP (op2) &&
506 (sym2->usl.spillLoc == sym1))
512 /*-----------------------------------------------------------------*/
513 /* sameRegs - two asmops have the same registers */
514 /*-----------------------------------------------------------------*/
516 sameRegs (asmop * aop1, asmop * aop2)
523 if (aop1->type != AOP_REG ||
524 aop2->type != AOP_REG)
527 if (aop1->size != aop2->size)
530 for (i = 0; i < aop1->size; i++)
531 if (aop1->aopu.aop_reg[i] !=
532 aop2->aopu.aop_reg[i])
538 /*-----------------------------------------------------------------*/
539 /* aopOp - allocates an asmop for an operand : */
540 /*-----------------------------------------------------------------*/
542 aopOp (operand * op, iCode * ic, bool result)
551 /* if this a literal */
552 if (IS_OP_LITERAL (op))
554 op->aop = aop = newAsmop (AOP_LIT);
555 aop->aopu.aop_lit = op->operand.valOperand;
556 aop->size = getSize (operandType (op));
560 /* if already has a asmop then continue */
564 /* if the underlying symbol has a aop */
565 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
567 op->aop = OP_SYMBOL (op)->aop;
571 /* if this is a true symbol */
572 if (IS_TRUE_SYMOP (op))
574 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
578 /* this is a temporary : this has
584 e) can be a return use only */
586 sym = OP_SYMBOL (op);
588 /* if the type is a conditional */
589 if (sym->regType == REG_CND)
591 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
596 /* if it is spilt then two situations
598 b) has a spill location */
599 if (sym->isspilt || sym->nRegs == 0)
602 /* rematerialize it NOW */
605 sym->aop = op->aop = aop =
607 aop->size = getSize (sym->type);
614 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
615 aop->size = getSize (sym->type);
616 for (i = 0; i < 2; i++)
617 aop->aopu.aop_str[i] = accUse[i];
625 aop = op->aop = sym->aop = newAsmop (AOP_STR);
626 aop->size = getSize (sym->type);
627 for (i = 0; i < fReturnSizeMCS51; i++)
628 aop->aopu.aop_str[i] = fReturn[i];
632 /* else spill location */
633 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
634 /* force a new aop if sizes differ */
635 sym->usl.spillLoc->aop = NULL;
637 sym->aop = op->aop = aop =
638 aopForSym (ic, sym->usl.spillLoc, result);
639 aop->size = getSize (sym->type);
643 /* must be in a register */
644 sym->aop = op->aop = aop = newAsmop (AOP_REG);
645 aop->size = sym->nRegs;
646 for (i = 0; i < sym->nRegs; i++)
647 aop->aopu.aop_reg[i] = sym->regs[i];
650 /*-----------------------------------------------------------------*/
651 /* freeAsmop - free up the asmop given to an operand */
652 /*----------------------------------------------------------------*/
654 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
671 /* depending on the asmop type only three cases need work AOP_RO
672 , AOP_R1 && AOP_STK */
680 emitcode ("pop", "ar0");
684 bitVectUnSetBit (ic->rUsed, R0_IDX);
692 emitcode ("pop", "ar1");
696 bitVectUnSetBit (ic->rUsed, R1_IDX);
702 int stk = aop->aopu.aop_stk + aop->size;
703 bitVectUnSetBit (ic->rUsed, R0_IDX);
704 bitVectUnSetBit (ic->rUsed, R1_IDX);
706 getFreePtr (ic, &aop, FALSE);
710 emitcode ("mov", "a,_bp");
711 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
712 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
716 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
721 emitcode ("pop", "acc");
722 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
725 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
728 freeAsmop (op, NULL, ic, TRUE);
731 emitcode ("pop", "ar0");
737 emitcode ("pop", "ar1");
744 /* all other cases just dealloc */
750 OP_SYMBOL (op)->aop = NULL;
751 /* if the symbol has a spill */
753 SPIL_LOC (op)->aop = NULL;
758 /*-----------------------------------------------------------------*/
759 /* aopGet - for fetching value of the aop */
760 /*-----------------------------------------------------------------*/
762 aopGet (asmop * aop, int offset, bool bit16, bool dname)
767 /* offset is greater than
769 if (offset > (aop->size - 1) &&
770 aop->type != AOP_LIT)
773 /* depending on type */
779 /* if we need to increment it */
780 while (offset > aop->coff)
782 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
786 while (offset < aop->coff)
788 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
795 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
796 return (dname ? "acc" : "a");
798 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
799 rs = Safe_calloc (1, strlen (s) + 1);
804 while (offset > aop->coff)
806 emitcode ("inc", "dptr");
810 while (offset < aop->coff)
812 emitcode ("lcall", "__decdptr");
819 emitcode ("clr", "a");
820 emitcode ("movc", "a,@a+dptr");
824 emitcode ("movx", "a,@dptr");
826 return (dname ? "acc" : "a");
830 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
831 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
833 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
835 sprintf (s, "#(%s >> %d)",
836 aop->aopu.aop_immd.aop_immd1,
840 aop->aopu.aop_immd.aop_immd1);
841 rs = Safe_calloc (1, strlen (s) + 1);
847 sprintf (s, "(%s + %d)",
851 sprintf (s, "%s", aop->aopu.aop_dir);
852 rs = Safe_calloc (1, strlen (s) + 1);
858 return aop->aopu.aop_reg[offset]->dname;
860 return aop->aopu.aop_reg[offset]->name;
863 emitcode ("clr", "a");
864 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
865 emitcode ("rlc", "a");
866 return (dname ? "acc" : "a");
869 if (!offset && dname)
871 return aop->aopu.aop_str[offset];
874 return aopLiteral (aop->aopu.aop_lit, offset);
878 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
882 return aop->aopu.aop_str[offset];
886 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
887 "aopget got unsupported aop->type");
890 /*-----------------------------------------------------------------*/
891 /* aopPut - puts a string for a aop */
892 /*-----------------------------------------------------------------*/
894 aopPut (asmop * aop, char *s, int offset)
898 if (aop->size && offset > (aop->size - 1))
900 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
901 "aopPut got offset > aop->size");
905 /* will assign value to value */
906 /* depending on where it is ofcourse */
911 sprintf (d, "(%s + %d)",
912 aop->aopu.aop_dir, offset);
914 sprintf (d, "%s", aop->aopu.aop_dir);
917 emitcode ("mov", "%s,%s", d, s);
922 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
923 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
926 strcmp (s, "r0") == 0 ||
927 strcmp (s, "r1") == 0 ||
928 strcmp (s, "r2") == 0 ||
929 strcmp (s, "r3") == 0 ||
930 strcmp (s, "r4") == 0 ||
931 strcmp (s, "r5") == 0 ||
932 strcmp (s, "r6") == 0 ||
933 strcmp (s, "r7") == 0)
934 emitcode ("mov", "%s,%s",
935 aop->aopu.aop_reg[offset]->dname, s);
937 emitcode ("mov", "%s,%s",
938 aop->aopu.aop_reg[offset]->name, s);
945 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
946 "aopPut writting to code space");
950 while (offset > aop->coff)
953 emitcode ("inc", "dptr");
956 while (offset < aop->coff)
959 emitcode ("lcall", "__decdptr");
964 /* if not in accumulater */
967 emitcode ("movx", "@dptr,a");
972 while (offset > aop->coff)
975 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
977 while (offset < aop->coff)
980 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
993 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
995 else if (strcmp (s, "r0") == 0 ||
996 strcmp (s, "r1") == 0 ||
997 strcmp (s, "r2") == 0 ||
998 strcmp (s, "r3") == 0 ||
999 strcmp (s, "r4") == 0 ||
1000 strcmp (s, "r5") == 0 ||
1001 strcmp (s, "r6") == 0 ||
1002 strcmp (s, "r7") == 0)
1005 sprintf (buffer, "a%s", s);
1006 emitcode ("mov", "@%s,%s",
1007 aop->aopu.aop_ptr->name, buffer);
1010 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1015 if (strcmp (s, "a") == 0)
1016 emitcode ("push", "acc");
1020 emitcode ("push", "acc");
1022 emitcode ("push", s);
1028 /* if bit variable */
1029 if (!aop->aopu.aop_dir)
1031 emitcode ("clr", "a");
1032 emitcode ("rlc", "a");
1037 emitcode ("clr", "%s", aop->aopu.aop_dir);
1039 emitcode ("setb", "%s", aop->aopu.aop_dir);
1040 else if (!strcmp (s, "c"))
1041 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1044 if (strcmp (s, "a"))
1049 symbol *lbl = newiTempLabel (NULL);
1050 emitcode ("clr", "c");
1051 emitcode ("jz", "%05d$", lbl->key + 100);
1052 emitcode ("cpl", "c");
1053 emitcode ("", "%05d$:", lbl->key + 100);
1054 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1062 if (strcmp (aop->aopu.aop_str[offset], s))
1063 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1068 if (!offset && (strcmp (s, "acc") == 0))
1071 if (strcmp (aop->aopu.aop_str[offset], s))
1072 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1076 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1077 "aopPut got unsupported aop->type");
1085 /*-----------------------------------------------------------------*/
1086 /* pointToEnd :- points to the last byte of the operand */
1087 /*-----------------------------------------------------------------*/
1089 pointToEnd (asmop * aop)
1095 aop->coff = count = (aop->size - 1);
1101 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1105 emitcode ("inc", "dptr");
1112 /*-----------------------------------------------------------------*/
1113 /* reAdjustPreg - points a register back to where it should */
1114 /*-----------------------------------------------------------------*/
1116 reAdjustPreg (asmop * aop)
1118 if ((aop->coff==0) || aop->size <= 1)
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1131 emitcode ("lcall", "__decdptr");
1138 #define AOP(op) op->aop
1139 #define AOP_TYPE(op) AOP(op)->type
1140 #define AOP_SIZE(op) AOP(op)->size
1141 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1142 AOP_TYPE(x) == AOP_R0))
1144 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1145 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1147 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1148 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1149 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1151 /*-----------------------------------------------------------------*/
1152 /* genNotFloat - generates not for float operations */
1153 /*-----------------------------------------------------------------*/
1155 genNotFloat (operand * op, operand * res)
1161 D(emitcode (";", "genNotFloat"));
1163 /* we will put 127 in the first byte of
1165 aopPut (AOP (res), "#127", 0);
1166 size = AOP_SIZE (op) - 1;
1169 l = aopGet (op->aop, offset++, FALSE, FALSE);
1174 emitcode ("orl", "a,%s",
1176 offset++, FALSE, FALSE));
1179 tlbl = newiTempLabel (NULL);
1180 aopPut (res->aop, one, 1);
1181 emitcode ("jz", "%05d$", (tlbl->key + 100));
1182 aopPut (res->aop, zero, 1);
1183 emitcode ("", "%05d$:", (tlbl->key + 100));
1185 size = res->aop->size - 2;
1187 /* put zeros in the rest */
1189 aopPut (res->aop, zero, offset++);
1192 /*-----------------------------------------------------------------*/
1193 /* opIsGptr: returns non-zero if the passed operand is */
1194 /* a generic pointer type. */
1195 /*-----------------------------------------------------------------*/
1197 opIsGptr (operand * op)
1199 sym_link *type = operandType (op);
1201 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1208 /*-----------------------------------------------------------------*/
1209 /* getDataSize - get the operand data size */
1210 /*-----------------------------------------------------------------*/
1212 getDataSize (operand * op)
1215 size = AOP_SIZE (op);
1216 if (size == GPTRSIZE)
1218 sym_link *type = operandType (op);
1219 if (IS_GENPTR (type))
1221 /* generic pointer; arithmetic operations
1222 * should ignore the high byte (pointer type).
1230 /*-----------------------------------------------------------------*/
1231 /* outAcc - output Acc */
1232 /*-----------------------------------------------------------------*/
1234 outAcc (operand * result)
1237 size = getDataSize (result);
1240 aopPut (AOP (result), "a", 0);
1243 /* unsigned or positive */
1246 aopPut (AOP (result), zero, offset++);
1251 /*-----------------------------------------------------------------*/
1252 /* outBitC - output a bit C */
1253 /*-----------------------------------------------------------------*/
1255 outBitC (operand * result)
1257 /* if the result is bit */
1258 if (AOP_TYPE (result) == AOP_CRY)
1259 aopPut (AOP (result), "c", 0);
1262 emitcode ("clr", "a");
1263 emitcode ("rlc", "a");
1268 /*-----------------------------------------------------------------*/
1269 /* toBoolean - emit code for orl a,operator(sizeop) */
1270 /*-----------------------------------------------------------------*/
1272 toBoolean (operand * oper)
1274 int size = AOP_SIZE (oper) - 1;
1276 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1278 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1282 /*-----------------------------------------------------------------*/
1283 /* genNot - generate code for ! operation */
1284 /*-----------------------------------------------------------------*/
1289 sym_link *optype = operandType (IC_LEFT (ic));
1291 D(emitcode (";", "genNot"));
1293 /* assign asmOps to operand & result */
1294 aopOp (IC_LEFT (ic), ic, FALSE);
1295 aopOp (IC_RESULT (ic), ic, TRUE);
1297 /* if in bit space then a special case */
1298 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1300 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1301 emitcode ("cpl", "c");
1302 outBitC (IC_RESULT (ic));
1306 /* if type float then do float */
1307 if (IS_FLOAT (optype))
1309 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1313 toBoolean (IC_LEFT (ic));
1315 tlbl = newiTempLabel (NULL);
1316 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1317 emitcode ("", "%05d$:", tlbl->key + 100);
1318 outBitC (IC_RESULT (ic));
1321 /* release the aops */
1322 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1323 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1327 /*-----------------------------------------------------------------*/
1328 /* genCpl - generate code for complement */
1329 /*-----------------------------------------------------------------*/
1337 D(emitcode (";", "genCpl"));
1339 /* assign asmOps to operand & result */
1340 aopOp (IC_LEFT (ic), ic, FALSE);
1341 aopOp (IC_RESULT (ic), ic, TRUE);
1343 /* special case if in bit space */
1344 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1345 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1346 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1347 emitcode ("cpl", "c");
1348 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1351 tlbl=newiTempLabel(NULL);
1352 emitcode ("cjne", "%s,#0x01,%05d$",
1353 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1354 emitcode ("", "%05d$:", tlbl->key+100);
1355 outBitC (IC_RESULT(ic));
1359 size = AOP_SIZE (IC_RESULT (ic));
1362 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1364 emitcode ("cpl", "a");
1365 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1370 /* release the aops */
1371 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1372 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1375 /*-----------------------------------------------------------------*/
1376 /* genUminusFloat - unary minus for floating points */
1377 /*-----------------------------------------------------------------*/
1379 genUminusFloat (operand * op, operand * result)
1381 int size, offset = 0;
1384 D(emitcode (";", "genUminusFloat"));
1386 /* for this we just need to flip the
1387 first it then copy the rest in place */
1388 size = AOP_SIZE (op) - 1;
1389 l = aopGet (AOP (op), 3, FALSE, FALSE);
1393 emitcode ("cpl", "acc.7");
1394 aopPut (AOP (result), "a", 3);
1398 aopPut (AOP (result),
1399 aopGet (AOP (op), offset, FALSE, FALSE),
1405 /*-----------------------------------------------------------------*/
1406 /* genUminus - unary minus code generation */
1407 /*-----------------------------------------------------------------*/
1409 genUminus (iCode * ic)
1412 sym_link *optype, *rtype;
1415 D(emitcode (";", "genUminus"));
1418 aopOp (IC_LEFT (ic), ic, FALSE);
1419 aopOp (IC_RESULT (ic), ic, TRUE);
1421 /* if both in bit space then special
1423 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1424 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1427 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1428 emitcode ("cpl", "c");
1429 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1433 optype = operandType (IC_LEFT (ic));
1434 rtype = operandType (IC_RESULT (ic));
1436 /* if float then do float stuff */
1437 if (IS_FLOAT (optype))
1439 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1443 /* otherwise subtract from zero */
1444 size = AOP_SIZE (IC_LEFT (ic));
1449 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1450 if (!strcmp (l, "a"))
1454 emitcode ("cpl", "a");
1455 emitcode ("addc", "a,#0");
1461 emitcode ("clr", "a");
1462 emitcode ("subb", "a,%s", l);
1464 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1467 /* if any remaining bytes in the result */
1468 /* we just need to propagate the sign */
1469 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1471 emitcode ("rlc", "a");
1472 emitcode ("subb", "a,acc");
1474 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1478 /* release the aops */
1479 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1480 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1483 /*-----------------------------------------------------------------*/
1484 /* saveRegisters - will look for a call and save the registers */
1485 /*-----------------------------------------------------------------*/
1487 saveRegisters (iCode * lic)
1494 for (ic = lic; ic; ic = ic->next)
1495 if (ic->op == CALL || ic->op == PCALL)
1500 fprintf (stderr, "found parameter push with no function call\n");
1504 /* if the registers have been saved already or don't need to be then
1506 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1507 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1510 /* safe the registers in use at this time but skip the
1511 ones for the result */
1512 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1513 mcs51_rUmaskForOp (IC_RESULT(ic)));
1516 if (options.useXstack)
1518 if (bitVectBitValue (rsave, R0_IDX))
1519 emitcode ("mov", "b,r0");
1520 emitcode ("mov", "r0,%s", spname);
1521 for (i = 0; i < mcs51_nRegs; i++)
1523 if (bitVectBitValue (rsave, i))
1526 emitcode ("mov", "a,b");
1528 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1529 emitcode ("movx", "@r0,a");
1530 emitcode ("inc", "r0");
1533 emitcode ("mov", "%s,r0", spname);
1534 if (bitVectBitValue (rsave, R0_IDX))
1535 emitcode ("mov", "r0,b");
1538 for (i = 0; i < mcs51_nRegs; i++)
1540 if (bitVectBitValue (rsave, i))
1541 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1545 /*-----------------------------------------------------------------*/
1546 /* unsaveRegisters - pop the pushed registers */
1547 /*-----------------------------------------------------------------*/
1549 unsaveRegisters (iCode * ic)
1554 /* restore the registers in use at this time but skip the
1555 ones for the result */
1556 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1557 mcs51_rUmaskForOp (IC_RESULT(ic)));
1559 if (options.useXstack)
1561 emitcode ("mov", "r0,%s", spname);
1562 for (i = mcs51_nRegs; i >= 0; i--)
1564 if (bitVectBitValue (rsave, i))
1566 emitcode ("dec", "r0");
1567 emitcode ("movx", "a,@r0");
1569 emitcode ("mov", "b,a");
1571 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1575 emitcode ("mov", "%s,r0", spname);
1576 if (bitVectBitValue (rsave, R0_IDX))
1577 emitcode ("mov", "r0,b");
1580 for (i = mcs51_nRegs; i >= 0; i--)
1582 if (bitVectBitValue (rsave, i))
1583 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1589 /*-----------------------------------------------------------------*/
1591 /*-----------------------------------------------------------------*/
1593 pushSide (operand * oper, int size)
1598 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1599 if (AOP_TYPE (oper) != AOP_REG &&
1600 AOP_TYPE (oper) != AOP_DIR &&
1603 emitcode ("mov", "a,%s", l);
1604 emitcode ("push", "acc");
1607 emitcode ("push", "%s", l);
1611 /*-----------------------------------------------------------------*/
1612 /* assignResultValue - */
1613 /*-----------------------------------------------------------------*/
1615 assignResultValue (operand * oper)
1618 int size = AOP_SIZE (oper);
1621 aopPut (AOP (oper), fReturn[offset], offset);
1627 /*-----------------------------------------------------------------*/
1628 /* genXpush - pushes onto the external stack */
1629 /*-----------------------------------------------------------------*/
1631 genXpush (iCode * ic)
1633 asmop *aop = newAsmop (0);
1635 int size, offset = 0;
1637 D(emitcode (";", "genXpush"));
1639 aopOp (IC_LEFT (ic), ic, FALSE);
1640 r = getFreePtr (ic, &aop, FALSE);
1643 emitcode ("mov", "%s,_spx", r->name);
1645 size = AOP_SIZE (IC_LEFT (ic));
1649 char *l = aopGet (AOP (IC_LEFT (ic)),
1650 offset++, FALSE, FALSE);
1652 emitcode ("movx", "@%s,a", r->name);
1653 emitcode ("inc", "%s", r->name);
1658 emitcode ("mov", "_spx,%s", r->name);
1660 freeAsmop (NULL, aop, ic, TRUE);
1661 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1664 /*-----------------------------------------------------------------*/
1665 /* genIpush - genrate code for pushing this gets a little complex */
1666 /*-----------------------------------------------------------------*/
1668 genIpush (iCode * ic)
1670 int size, offset = 0;
1673 D(emitcode (";", "genIpush"));
1675 /* if this is not a parm push : ie. it is spill push
1676 and spill push is always done on the local stack */
1680 /* and the item is spilt then do nothing */
1681 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1684 aopOp (IC_LEFT (ic), ic, FALSE);
1685 size = AOP_SIZE (IC_LEFT (ic));
1686 /* push it on the stack */
1689 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1695 emitcode ("push", "%s", l);
1700 /* this is a paramter push: in this case we call
1701 the routine to find the call and save those
1702 registers that need to be saved */
1705 /* if use external stack then call the external
1706 stack pushing routine */
1707 if (options.useXstack)
1713 /* then do the push */
1714 aopOp (IC_LEFT (ic), ic, FALSE);
1717 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1718 size = AOP_SIZE (IC_LEFT (ic));
1722 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1723 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1724 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1727 emitcode ("mov", "a,%s", l);
1728 emitcode ("push", "acc");
1731 emitcode ("push", "%s", l);
1734 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1737 /*-----------------------------------------------------------------*/
1738 /* genIpop - recover the registers: can happen only for spilling */
1739 /*-----------------------------------------------------------------*/
1741 genIpop (iCode * ic)
1745 D(emitcode (";", "genIpop"));
1747 /* if the temp was not pushed then */
1748 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1751 aopOp (IC_LEFT (ic), ic, FALSE);
1752 size = AOP_SIZE (IC_LEFT (ic));
1753 offset = (size - 1);
1755 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1758 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1761 /*-----------------------------------------------------------------*/
1762 /* unsaveRBank - restores the resgister bank from stack */
1763 /*-----------------------------------------------------------------*/
1765 unsaveRBank (int bank, iCode * ic, bool popPsw)
1771 if (options.useXstack)
1775 /* Assume r0 is available for use. */
1776 r = mcs51_regWithIdx (R0_IDX);;
1781 r = getFreePtr (ic, &aop, FALSE);
1783 emitcode ("mov", "%s,_spx", r->name);
1788 if (options.useXstack)
1790 emitcode ("movx", "a,@%s", r->name);
1791 emitcode ("mov", "psw,a");
1792 emitcode ("dec", "%s", r->name);
1796 emitcode ("pop", "psw");
1800 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1802 if (options.useXstack)
1804 emitcode ("movx", "a,@%s", r->name);
1805 emitcode ("mov", "(%s+%d),a",
1806 regs8051[i].base, 8 * bank + regs8051[i].offset);
1807 emitcode ("dec", "%s", r->name);
1811 emitcode ("pop", "(%s+%d)",
1812 regs8051[i].base, 8 * bank + regs8051[i].offset);
1815 if (options.useXstack)
1817 emitcode ("mov", "_spx,%s", r->name);
1822 freeAsmop (NULL, aop, ic, TRUE);
1826 /*-----------------------------------------------------------------*/
1827 /* saveRBank - saves an entire register bank on the stack */
1828 /*-----------------------------------------------------------------*/
1830 saveRBank (int bank, iCode * ic, bool pushPsw)
1836 if (options.useXstack)
1840 /* Assume r0 is available for use. */
1841 r = mcs51_regWithIdx (R0_IDX);;
1846 r = getFreePtr (ic, &aop, FALSE);
1848 emitcode ("mov", "%s,_spx", r->name);
1851 for (i = 0; i < mcs51_nRegs; i++)
1853 if (options.useXstack)
1855 emitcode ("inc", "%s", r->name);
1856 emitcode ("mov", "a,(%s+%d)",
1857 regs8051[i].base, 8 * bank + regs8051[i].offset);
1858 emitcode ("movx", "@%s,a", r->name);
1861 emitcode ("push", "(%s+%d)",
1862 regs8051[i].base, 8 * bank + regs8051[i].offset);
1867 if (options.useXstack)
1869 emitcode ("mov", "a,psw");
1870 emitcode ("movx", "@%s,a", r->name);
1871 emitcode ("inc", "%s", r->name);
1872 emitcode ("mov", "_spx,%s", r->name);
1877 emitcode ("push", "psw");
1880 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1885 freeAsmop (NULL, aop, ic, TRUE);
1894 /*-----------------------------------------------------------------*/
1895 /* genSend - gen code for SEND */
1896 /*-----------------------------------------------------------------*/
1897 static void genSend(set *sendSet)
1902 for (sic = setFirstItem (_G.sendSet); sic;
1903 sic = setNextItem (_G.sendSet)) {
1904 int size, offset = 0;
1905 aopOp (IC_LEFT (sic), sic, FALSE);
1906 size = AOP_SIZE (IC_LEFT (sic));
1908 if (sic->argreg == 1) {
1910 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1912 if (strcmp (l, fReturn[offset]))
1913 emitcode ("mov", "%s,%s", fReturn[offset], l);
1919 emitcode ("mov","b1_%d,%s",rb1_count++,
1920 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1923 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1927 /*-----------------------------------------------------------------*/
1928 /* genCall - generates a call statement */
1929 /*-----------------------------------------------------------------*/
1931 genCall (iCode * ic)
1934 // bool restoreBank = FALSE;
1935 bool swapBanks = FALSE;
1937 D(emitcode(";", "genCall"));
1939 dtype = operandType (IC_LEFT (ic));
1940 /* if send set is not empty the assign */
1943 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1944 genSend(reverseSet(_G.sendSet));
1946 genSend(_G.sendSet);
1952 /* if we are calling a not _naked function that is not using
1953 the same register bank then we need to save the
1954 destination registers on the stack */
1955 dtype = operandType (IC_LEFT (ic));
1956 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1957 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1958 !IFFUNC_ISISR (dtype))
1963 /* if caller saves & we have not saved then */
1969 emitcode ("mov", "psw,#0x%02x",
1970 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1974 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1975 OP_SYMBOL (IC_LEFT (ic))->rname :
1976 OP_SYMBOL (IC_LEFT (ic))->name));
1980 emitcode ("mov", "psw,#0x%02x",
1981 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1984 /* if we need assign a result value */
1985 if ((IS_ITEMP (IC_RESULT (ic)) &&
1986 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1987 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1988 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1989 IS_TRUE_SYMOP (IC_RESULT (ic)))
1993 aopOp (IC_RESULT (ic), ic, FALSE);
1996 assignResultValue (IC_RESULT (ic));
1998 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2001 /* adjust the stack for parameters if
2006 if (ic->parmBytes > 3)
2008 emitcode ("mov", "a,%s", spname);
2009 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2010 emitcode ("mov", "%s,a", spname);
2013 for (i = 0; i < ic->parmBytes; i++)
2014 emitcode ("dec", "%s", spname);
2017 /* if we hade saved some registers then unsave them */
2018 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2019 unsaveRegisters (ic);
2021 // /* if register bank was saved then pop them */
2023 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2026 /*-----------------------------------------------------------------*/
2027 /* -10l - generates a call by pointer statement */
2028 /*-----------------------------------------------------------------*/
2030 genPcall (iCode * ic)
2033 symbol *rlbl = newiTempLabel (NULL);
2034 // bool restoreBank=FALSE;
2035 bool swapBanks = FALSE;
2037 D(emitcode(";", "genPCall"));
2039 /* if caller saves & we have not saved then */
2043 /* if we are calling a not _naked function that is not using
2044 the same register bank then we need to save the
2045 destination registers on the stack */
2046 dtype = operandType (IC_LEFT (ic))->next;
2047 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2048 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2049 !IFFUNC_ISISR (dtype))
2051 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2052 // restoreBank=TRUE;
2054 // need caution message to user here
2057 /* push the return address on to the stack */
2058 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2059 emitcode ("push", "acc");
2060 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2061 emitcode ("push", "acc");
2063 /* now push the calling address */
2064 aopOp (IC_LEFT (ic), ic, FALSE);
2066 pushSide (IC_LEFT (ic), FPTRSIZE);
2068 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2070 /* if send set is not empty the assign */
2073 genSend(reverseSet(_G.sendSet));
2079 emitcode ("mov", "psw,#0x%02x",
2080 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2084 emitcode ("ret", "");
2085 emitcode ("", "%05d$:", (rlbl->key + 100));
2090 emitcode ("mov", "psw,#0x%02x",
2091 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2094 /* if we need assign a result value */
2095 if ((IS_ITEMP (IC_RESULT (ic)) &&
2096 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2097 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2098 IS_TRUE_SYMOP (IC_RESULT (ic)))
2102 aopOp (IC_RESULT (ic), ic, FALSE);
2105 assignResultValue (IC_RESULT (ic));
2107 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2110 /* adjust the stack for parameters if
2115 if (ic->parmBytes > 3)
2117 emitcode ("mov", "a,%s", spname);
2118 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2119 emitcode ("mov", "%s,a", spname);
2122 for (i = 0; i < ic->parmBytes; i++)
2123 emitcode ("dec", "%s", spname);
2127 // /* if register bank was saved then unsave them */
2129 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2131 /* if we hade saved some registers then
2133 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2134 unsaveRegisters (ic);
2137 /*-----------------------------------------------------------------*/
2138 /* resultRemat - result is rematerializable */
2139 /*-----------------------------------------------------------------*/
2141 resultRemat (iCode * ic)
2143 if (SKIP_IC (ic) || ic->op == IFX)
2146 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2148 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2149 if (sym->remat && !POINTER_SET (ic))
2156 #if defined(__BORLANDC__) || defined(_MSC_VER)
2157 #define STRCASECMP stricmp
2159 #define STRCASECMP strcasecmp
2162 /*-----------------------------------------------------------------*/
2163 /* inExcludeList - return 1 if the string is in exclude Reg list */
2164 /*-----------------------------------------------------------------*/
2166 inExcludeList (char *s)
2170 if (options.excludeRegs[i] &&
2171 STRCASECMP (options.excludeRegs[i], "none") == 0)
2174 for (i = 0; options.excludeRegs[i]; i++)
2176 if (options.excludeRegs[i] &&
2177 STRCASECMP (s, options.excludeRegs[i]) == 0)
2183 /*-----------------------------------------------------------------*/
2184 /* genFunction - generated code for function entry */
2185 /*-----------------------------------------------------------------*/
2187 genFunction (iCode * ic)
2191 bool switchedPSW = FALSE;
2192 int calleesaves_saved_register = -1;
2195 /* create the function header */
2196 emitcode (";", "-----------------------------------------");
2197 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2198 emitcode (";", "-----------------------------------------");
2200 emitcode ("", "%s:", sym->rname);
2201 ftype = operandType (IC_LEFT (ic));
2203 if (IFFUNC_ISNAKED(ftype))
2205 emitcode(";", "naked function: no prologue.");
2209 /* if critical function then turn interrupts off */
2210 if (IFFUNC_ISCRITICAL (ftype))
2211 emitcode ("clr", "ea");
2213 /* here we need to generate the equates for the
2214 register bank if required */
2215 if (FUNC_REGBANK (ftype) != rbank)
2219 rbank = FUNC_REGBANK (ftype);
2220 for (i = 0; i < mcs51_nRegs; i++)
2222 if (strcmp (regs8051[i].base, "0") == 0)
2223 emitcode ("", "%s = 0x%02x",
2225 8 * rbank + regs8051[i].offset);
2227 emitcode ("", "%s = %s + 0x%02x",
2230 8 * rbank + regs8051[i].offset);
2234 /* if this is an interrupt service routine then
2235 save acc, b, dpl, dph */
2236 if (IFFUNC_ISISR (sym->type))
2239 if (!inExcludeList ("acc"))
2240 emitcode ("push", "acc");
2241 if (!inExcludeList ("b"))
2242 emitcode ("push", "b");
2243 if (!inExcludeList ("dpl"))
2244 emitcode ("push", "dpl");
2245 if (!inExcludeList ("dph"))
2246 emitcode ("push", "dph");
2247 /* if this isr has no bank i.e. is going to
2248 run with bank 0 , then we need to save more
2250 if (!FUNC_REGBANK (sym->type))
2253 /* if this function does not call any other
2254 function then we can be economical and
2255 save only those registers that are used */
2256 if (!IFFUNC_HASFCALL(sym->type))
2260 /* if any registers used */
2263 /* save the registers used */
2264 for (i = 0; i < sym->regsUsed->size; i++)
2266 if (bitVectBitValue (sym->regsUsed, i) ||
2267 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2268 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2276 /* this function has a function call cannot
2277 determines register usage so we will have to push the
2279 saveRBank (0, ic, FALSE);
2280 if (options.parms_in_bank1) {
2282 for (i=0; i < 8 ; i++ ) {
2283 emitcode ("push","%s",rb1regs[i]);
2290 /* This ISR uses a non-zero bank.
2292 * We assume that the bank is available for our
2295 * However, if this ISR calls a function which uses some
2296 * other bank, we must save that bank entirely.
2298 unsigned long banksToSave = 0;
2300 if (IFFUNC_HASFCALL(sym->type))
2303 #define MAX_REGISTER_BANKS 4
2308 for (i = ic; i; i = i->next)
2310 if (i->op == ENDFUNCTION)
2312 /* we got to the end OK. */
2320 dtype = operandType (IC_LEFT(i));
2322 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2324 /* Mark this bank for saving. */
2325 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2327 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2331 banksToSave |= (1 << FUNC_REGBANK(dtype));
2334 /* And note that we don't need to do it in
2342 /* This is a mess; we have no idea what
2343 * register bank the called function might
2346 * The only thing I can think of to do is
2347 * throw a warning and hope.
2349 werror(W_FUNCPTR_IN_USING_ISR);
2353 if (banksToSave && options.useXstack)
2355 /* Since we aren't passing it an ic,
2356 * saveRBank will assume r0 is available to abuse.
2358 * So switch to our (trashable) bank now, so
2359 * the caller's R0 isn't trashed.
2361 emitcode ("push", "psw");
2362 emitcode ("mov", "psw,#0x%02x",
2363 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2367 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2369 if (banksToSave & (1 << ix))
2371 saveRBank(ix, NULL, FALSE);
2375 // jwk: this needs a closer look
2376 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2381 /* if callee-save to be used for this function
2382 then save the registers being used in this function */
2383 if (IFFUNC_CALLEESAVES(sym->type))
2387 /* if any registers used */
2390 /* save the registers used */
2391 for (i = 0; i < sym->regsUsed->size; i++)
2393 if (bitVectBitValue (sym->regsUsed, i) ||
2394 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2396 /* remember one saved register for later usage */
2397 if (calleesaves_saved_register < 0)
2398 calleesaves_saved_register = i;
2399 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2407 /* set the register bank to the desired value */
2408 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2411 emitcode ("push", "psw");
2412 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2415 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2418 if (options.useXstack)
2420 emitcode ("mov", "r0,%s", spname);
2421 emitcode ("mov", "a,_bp");
2422 emitcode ("movx", "@r0,a");
2423 emitcode ("inc", "%s", spname);
2427 /* set up the stack */
2428 emitcode ("push", "_bp"); /* save the callers stack */
2430 emitcode ("mov", "_bp,%s", spname);
2433 /* adjust the stack for the function */
2439 werror (W_STACK_OVERFLOW, sym->name);
2441 if (i > 3 && sym->recvSize < 4)
2444 emitcode ("mov", "a,sp");
2445 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2446 emitcode ("mov", "sp,a");
2451 if (IFFUNC_CALLEESAVES(sym->type))
2453 /* if it's a callee-saves function we need a saved register */
2454 if (calleesaves_saved_register >= 0)
2456 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2457 emitcode ("mov", "a,sp");
2458 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2459 emitcode ("mov", "sp,a");
2460 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2463 /* do it the hard way */
2465 emitcode ("inc", "sp");
2469 /* not callee-saves, we can clobber ar0 */
2470 emitcode ("mov", "ar0,a");
2471 emitcode ("mov", "a,sp");
2472 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2473 emitcode ("mov", "sp,a");
2474 emitcode ("mov", "a,ar0");
2479 emitcode ("inc", "sp");
2485 emitcode ("mov", "a,_spx");
2486 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2487 emitcode ("mov", "_spx,a");
2492 /*-----------------------------------------------------------------*/
2493 /* genEndFunction - generates epilogue for functions */
2494 /*-----------------------------------------------------------------*/
2496 genEndFunction (iCode * ic)
2498 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2500 if (IFFUNC_ISNAKED(sym->type))
2502 emitcode(";", "naked function: no epilogue.");
2506 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2508 emitcode ("mov", "%s,_bp", spname);
2511 /* if use external stack but some variables were
2512 added to the local stack then decrement the
2514 if (options.useXstack && sym->stack)
2516 emitcode ("mov", "a,sp");
2517 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2518 emitcode ("mov", "sp,a");
2522 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2524 if (options.useXstack)
2526 emitcode ("mov", "r0,%s", spname);
2527 emitcode ("movx", "a,@r0");
2528 emitcode ("mov", "_bp,a");
2529 emitcode ("dec", "%s", spname);
2533 emitcode ("pop", "_bp");
2537 /* restore the register bank */
2538 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2540 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2541 || !options.useXstack)
2543 /* Special case of ISR using non-zero bank with useXstack
2546 emitcode ("pop", "psw");
2550 if (IFFUNC_ISISR (sym->type))
2553 /* now we need to restore the registers */
2554 /* if this isr has no bank i.e. is going to
2555 run with bank 0 , then we need to save more
2557 if (!FUNC_REGBANK (sym->type))
2559 /* if this function does not call any other
2560 function then we can be economical and
2561 save only those registers that are used */
2562 if (!IFFUNC_HASFCALL(sym->type))
2566 /* if any registers used */
2569 /* save the registers used */
2570 for (i = sym->regsUsed->size; i >= 0; i--)
2572 if (bitVectBitValue (sym->regsUsed, i) ||
2573 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2574 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2581 if (options.parms_in_bank1) {
2583 for (i = 7 ; i >= 0 ; i-- ) {
2584 emitcode ("pop","%s",rb1regs[i]);
2587 /* this function has a function call cannot
2588 determines register usage so we will have to pop the
2590 unsaveRBank (0, ic, FALSE);
2595 /* This ISR uses a non-zero bank.
2597 * Restore any register banks saved by genFunction
2600 // jwk: this needs a closer look
2601 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2604 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2606 if (savedBanks & (1 << ix))
2608 unsaveRBank(ix, NULL, FALSE);
2612 if (options.useXstack)
2614 /* Restore bank AFTER calling unsaveRBank,
2615 * since it can trash r0.
2617 emitcode ("pop", "psw");
2621 if (!inExcludeList ("dph"))
2622 emitcode ("pop", "dph");
2623 if (!inExcludeList ("dpl"))
2624 emitcode ("pop", "dpl");
2625 if (!inExcludeList ("b"))
2626 emitcode ("pop", "b");
2627 if (!inExcludeList ("acc"))
2628 emitcode ("pop", "acc");
2630 if (IFFUNC_ISCRITICAL (sym->type))
2631 emitcode ("setb", "ea");
2633 /* if debug then send end of function */
2634 if (options.debug && currFunc)
2637 emitcode ("", "C$%s$%d$%d$%d ==.",
2638 FileBaseName (ic->filename), currFunc->lastLine,
2639 ic->level, ic->block);
2640 if (IS_STATIC (currFunc->etype))
2641 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2643 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2647 emitcode ("reti", "");
2651 if (IFFUNC_ISCRITICAL (sym->type))
2652 emitcode ("setb", "ea");
2654 if (IFFUNC_CALLEESAVES(sym->type))
2658 /* if any registers used */
2661 /* save the registers used */
2662 for (i = sym->regsUsed->size; i >= 0; i--)
2664 if (bitVectBitValue (sym->regsUsed, i) ||
2665 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2666 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2672 /* if debug then send end of function */
2673 if (options.debug && currFunc)
2676 emitcode ("", "C$%s$%d$%d$%d ==.",
2677 FileBaseName (ic->filename), currFunc->lastLine,
2678 ic->level, ic->block);
2679 if (IS_STATIC (currFunc->etype))
2680 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2682 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2686 emitcode ("ret", "");
2691 /*-----------------------------------------------------------------*/
2692 /* genRet - generate code for return statement */
2693 /*-----------------------------------------------------------------*/
2697 int size, offset = 0, pushed = 0;
2699 D(emitcode (";", "genRet"));
2701 /* if we have no return value then
2702 just generate the "ret" */
2706 /* we have something to return then
2707 move the return value into place */
2708 aopOp (IC_LEFT (ic), ic, FALSE);
2709 size = AOP_SIZE (IC_LEFT (ic));
2714 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2717 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2719 emitcode ("push", "%s", l);
2724 l = aopGet (AOP (IC_LEFT (ic)), offset,
2726 if (strcmp (fReturn[offset], l))
2727 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2736 if (strcmp (fReturn[pushed], "a"))
2737 emitcode ("pop", fReturn[pushed]);
2739 emitcode ("pop", "acc");
2742 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2745 /* generate a jump to the return label
2746 if the next is not the return statement */
2747 if (!(ic->next && ic->next->op == LABEL &&
2748 IC_LABEL (ic->next) == returnLabel))
2750 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2754 /*-----------------------------------------------------------------*/
2755 /* genLabel - generates a label */
2756 /*-----------------------------------------------------------------*/
2758 genLabel (iCode * ic)
2760 /* special case never generate */
2761 if (IC_LABEL (ic) == entryLabel)
2764 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2767 /*-----------------------------------------------------------------*/
2768 /* genGoto - generates a ljmp */
2769 /*-----------------------------------------------------------------*/
2771 genGoto (iCode * ic)
2773 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2776 /*-----------------------------------------------------------------*/
2777 /* findLabelBackwards: walks back through the iCode chain looking */
2778 /* for the given label. Returns number of iCode instructions */
2779 /* between that label and given ic. */
2780 /* Returns zero if label not found. */
2781 /*-----------------------------------------------------------------*/
2783 findLabelBackwards (iCode * ic, int key)
2792 /* If we have any pushes or pops, we cannot predict the distance.
2793 I don't like this at all, this should be dealt with in the
2795 if (ic->op == IPUSH || ic->op == IPOP) {
2799 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2808 /*-----------------------------------------------------------------*/
2809 /* genPlusIncr :- does addition with increment if possible */
2810 /*-----------------------------------------------------------------*/
2812 genPlusIncr (iCode * ic)
2814 unsigned int icount;
2815 unsigned int size = getDataSize (IC_RESULT (ic));
2817 /* will try to generate an increment */
2818 /* if the right side is not a literal
2820 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2823 /* if the literal value of the right hand side
2824 is greater than 4 then it is not worth it */
2825 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2828 D(emitcode (";", "genPlusIncr"));
2830 /* if increment 16 bits in register */
2831 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2832 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2840 /* If the next instruction is a goto and the goto target
2841 * is < 10 instructions previous to this, we can generate
2842 * jumps straight to that target.
2844 if (ic->next && ic->next->op == GOTO
2845 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2846 && labelRange <= 10)
2848 emitcode (";", "tail increment optimized");
2849 tlbl = IC_LABEL (ic->next);
2854 tlbl = newiTempLabel (NULL);
2857 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2858 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2859 IS_AOP_PREG (IC_RESULT (ic)))
2860 emitcode ("cjne", "%s,#0x00,%05d$",
2861 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2865 emitcode ("clr", "a");
2866 emitcode ("cjne", "a,%s,%05d$",
2867 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2871 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2874 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2875 IS_AOP_PREG (IC_RESULT (ic)))
2876 emitcode ("cjne", "%s,#0x00,%05d$",
2877 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2880 emitcode ("cjne", "a,%s,%05d$",
2881 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2884 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2888 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2889 IS_AOP_PREG (IC_RESULT (ic)))
2890 emitcode ("cjne", "%s,#0x00,%05d$",
2891 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2895 emitcode ("cjne", "a,%s,%05d$",
2896 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2899 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2904 emitcode ("", "%05d$:", tlbl->key + 100);
2909 /* if the sizes are greater than 1 then we cannot */
2910 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2911 AOP_SIZE (IC_LEFT (ic)) > 1)
2914 /* we can if the aops of the left & result match or
2915 if they are in registers and the registers are the
2917 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2922 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2923 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2924 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2930 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2939 /*-----------------------------------------------------------------*/
2940 /* outBitAcc - output a bit in acc */
2941 /*-----------------------------------------------------------------*/
2943 outBitAcc (operand * result)
2945 symbol *tlbl = newiTempLabel (NULL);
2946 /* if the result is a bit */
2947 if (AOP_TYPE (result) == AOP_CRY)
2949 aopPut (AOP (result), "a", 0);
2953 emitcode ("jz", "%05d$", tlbl->key + 100);
2954 emitcode ("mov", "a,%s", one);
2955 emitcode ("", "%05d$:", tlbl->key + 100);
2960 /*-----------------------------------------------------------------*/
2961 /* genPlusBits - generates code for addition of two bits */
2962 /*-----------------------------------------------------------------*/
2964 genPlusBits (iCode * ic)
2966 D(emitcode (";", "genPlusBits"));
2968 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2970 symbol *lbl = newiTempLabel (NULL);
2971 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2972 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2973 emitcode ("cpl", "c");
2974 emitcode ("", "%05d$:", (lbl->key + 100));
2975 outBitC (IC_RESULT (ic));
2979 emitcode ("clr", "a");
2980 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2981 emitcode ("rlc", "a");
2982 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2983 emitcode ("addc", "a,#0x00");
2984 outAcc (IC_RESULT (ic));
2989 /* This is the original version of this code.
2991 * This is being kept around for reference,
2992 * because I am not entirely sure I got it right...
2995 adjustArithmeticResult (iCode * ic)
2997 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2998 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2999 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3000 aopPut (AOP (IC_RESULT (ic)),
3001 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3004 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3005 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3006 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3007 aopPut (AOP (IC_RESULT (ic)),
3008 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3011 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3012 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3013 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3014 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3015 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3018 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3019 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3023 /* This is the pure and virtuous version of this code.
3024 * I'm pretty certain it's right, but not enough to toss the old
3028 adjustArithmeticResult (iCode * ic)
3030 if (opIsGptr (IC_RESULT (ic)) &&
3031 opIsGptr (IC_LEFT (ic)) &&
3032 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3034 aopPut (AOP (IC_RESULT (ic)),
3035 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3039 if (opIsGptr (IC_RESULT (ic)) &&
3040 opIsGptr (IC_RIGHT (ic)) &&
3041 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3043 aopPut (AOP (IC_RESULT (ic)),
3044 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3048 if (opIsGptr (IC_RESULT (ic)) &&
3049 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3050 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3051 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3052 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3055 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3056 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3061 /*-----------------------------------------------------------------*/
3062 /* genPlus - generates code for addition */
3063 /*-----------------------------------------------------------------*/
3065 genPlus (iCode * ic)
3067 int size, offset = 0;
3069 /* special cases :- */
3071 D(emitcode (";", "genPlus"));
3073 aopOp (IC_LEFT (ic), ic, FALSE);
3074 aopOp (IC_RIGHT (ic), ic, FALSE);
3075 aopOp (IC_RESULT (ic), ic, TRUE);
3077 /* if literal, literal on the right or
3078 if left requires ACC or right is already
3080 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3081 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3082 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3084 operand *t = IC_RIGHT (ic);
3085 IC_RIGHT (ic) = IC_LEFT (ic);
3089 /* if both left & right are in bit
3091 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3092 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3098 /* if left in bit space & right literal */
3099 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3100 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3102 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3103 /* if result in bit space */
3104 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3106 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3107 emitcode ("cpl", "c");
3108 outBitC (IC_RESULT (ic));
3112 size = getDataSize (IC_RESULT (ic));
3115 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3116 emitcode ("addc", "a,#00");
3117 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3123 /* if I can do an increment instead
3124 of add then GOOD for ME */
3125 if (genPlusIncr (ic) == TRUE)
3128 size = getDataSize (IC_RESULT (ic));
3132 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3134 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3136 emitcode ("add", "a,%s",
3137 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3139 emitcode ("addc", "a,%s",
3140 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3144 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3146 emitcode ("add", "a,%s",
3147 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3149 emitcode ("addc", "a,%s",
3150 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3152 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3155 adjustArithmeticResult (ic);
3158 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3159 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3160 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3163 /*-----------------------------------------------------------------*/
3164 /* genMinusDec :- does subtraction with deccrement if possible */
3165 /*-----------------------------------------------------------------*/
3167 genMinusDec (iCode * ic)
3169 unsigned int icount;
3170 unsigned int size = getDataSize (IC_RESULT (ic));
3172 /* will try to generate an increment */
3173 /* if the right side is not a literal
3175 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3178 /* if the literal value of the right hand side
3179 is greater than 4 then it is not worth it */
3180 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3183 D(emitcode (";", "genMinusDec"));
3185 /* if decrement 16 bits in register */
3186 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3187 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3195 /* If the next instruction is a goto and the goto target
3196 * is <= 10 instructions previous to this, we can generate
3197 * jumps straight to that target.
3199 if (ic->next && ic->next->op == GOTO
3200 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3201 && labelRange <= 10)
3203 emitcode (";", "tail decrement optimized");
3204 tlbl = IC_LABEL (ic->next);
3209 tlbl = newiTempLabel (NULL);
3213 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3214 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3215 IS_AOP_PREG (IC_RESULT (ic)))
3216 emitcode ("cjne", "%s,#0xff,%05d$"
3217 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3221 emitcode ("mov", "a,#0xff");
3222 emitcode ("cjne", "a,%s,%05d$"
3223 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3226 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3229 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3230 IS_AOP_PREG (IC_RESULT (ic)))
3231 emitcode ("cjne", "%s,#0xff,%05d$"
3232 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3236 emitcode ("cjne", "a,%s,%05d$"
3237 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3240 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3244 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3245 IS_AOP_PREG (IC_RESULT (ic)))
3246 emitcode ("cjne", "%s,#0xff,%05d$"
3247 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3251 emitcode ("cjne", "a,%s,%05d$"
3252 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3255 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3259 emitcode ("", "%05d$:", tlbl->key + 100);
3264 /* if the sizes are greater than 1 then we cannot */
3265 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3266 AOP_SIZE (IC_LEFT (ic)) > 1)
3269 /* we can if the aops of the left & result match or
3270 if they are in registers and the registers are the
3272 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3276 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3284 /*-----------------------------------------------------------------*/
3285 /* addSign - complete with sign */
3286 /*-----------------------------------------------------------------*/
3288 addSign (operand * result, int offset, int sign)
3290 int size = (getDataSize (result) - offset);
3295 emitcode ("rlc", "a");
3296 emitcode ("subb", "a,acc");
3298 aopPut (AOP (result), "a", offset++);
3302 aopPut (AOP (result), zero, offset++);
3306 /*-----------------------------------------------------------------*/
3307 /* genMinusBits - generates code for subtraction of two bits */
3308 /*-----------------------------------------------------------------*/
3310 genMinusBits (iCode * ic)
3312 symbol *lbl = newiTempLabel (NULL);
3314 D(emitcode (";", "genMinusBits"));
3316 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3318 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3319 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3320 emitcode ("cpl", "c");
3321 emitcode ("", "%05d$:", (lbl->key + 100));
3322 outBitC (IC_RESULT (ic));
3326 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3327 emitcode ("subb", "a,acc");
3328 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3329 emitcode ("inc", "a");
3330 emitcode ("", "%05d$:", (lbl->key + 100));
3331 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3332 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3336 /*-----------------------------------------------------------------*/
3337 /* genMinus - generates code for subtraction */
3338 /*-----------------------------------------------------------------*/
3340 genMinus (iCode * ic)
3342 int size, offset = 0;
3343 unsigned long lit = 0L;
3345 D(emitcode (";", "genMinus"));
3347 aopOp (IC_LEFT (ic), ic, FALSE);
3348 aopOp (IC_RIGHT (ic), ic, FALSE);
3349 aopOp (IC_RESULT (ic), ic, TRUE);
3351 /* special cases :- */
3352 /* if both left & right are in bit space */
3353 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3354 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3360 /* if I can do an decrement instead
3361 of subtract then GOOD for ME */
3362 if (genMinusDec (ic) == TRUE)
3365 size = getDataSize (IC_RESULT (ic));
3367 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3373 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3377 /* if literal, add a,#-lit, else normal subb */
3380 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3381 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3382 emitcode ("subb", "a,%s",
3383 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3386 /* first add without previous c */
3388 if (!size && lit==-1) {
3389 emitcode ("dec", "a");
3391 emitcode ("add", "a,#0x%02x",
3392 (unsigned int) (lit & 0x0FFL));
3395 emitcode ("addc", "a,#0x%02x",
3396 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3399 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3402 adjustArithmeticResult (ic);
3405 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3406 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3407 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3411 /*-----------------------------------------------------------------*/
3412 /* genMultbits :- multiplication of bits */
3413 /*-----------------------------------------------------------------*/
3415 genMultbits (operand * left,
3419 D(emitcode (";", "genMultbits"));
3421 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3422 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3427 /*-----------------------------------------------------------------*/
3428 /* genMultOneByte : 8*8=8/16 bit multiplication */
3429 /*-----------------------------------------------------------------*/
3431 genMultOneByte (operand * left,
3435 sym_link *opetype = operandType (result);
3437 int size=AOP_SIZE(result);
3439 D(emitcode (";", "genMultOneByte"));
3441 if (size<1 || size>2) {
3442 // this should never happen
3443 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3444 AOP_SIZE(result), __FILE__, lineno);
3448 /* (if two literals: the value is computed before) */
3449 /* if one literal, literal on the right */
3450 if (AOP_TYPE (left) == AOP_LIT)
3455 //emitcode (";", "swapped left and right");
3458 if (SPEC_USIGN(opetype)
3459 // ignore the sign of left and right, what else can we do?
3460 || (SPEC_USIGN(operandType(left)) &&
3461 SPEC_USIGN(operandType(right)))) {
3462 // just an unsigned 8*8=8/16 multiply
3463 //emitcode (";","unsigned");
3464 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3465 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3466 emitcode ("mul", "ab");
3467 aopPut (AOP (result), "a", 0);
3469 aopPut (AOP (result), "b", 1);
3474 // we have to do a signed multiply
3476 //emitcode (";", "signed");
3477 emitcode ("clr", "F0"); // reset sign flag
3478 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3480 lbl=newiTempLabel(NULL);
3481 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3482 // left side is negative, 8-bit two's complement, this fails for -128
3483 emitcode ("setb", "F0"); // set sign flag
3484 emitcode ("cpl", "a");
3485 emitcode ("inc", "a");
3487 emitcode ("", "%05d$:", lbl->key+100);
3490 if (AOP_TYPE(right)==AOP_LIT) {
3491 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3492 /* AND literal negative */
3494 emitcode ("cpl", "F0"); // complement sign flag
3495 emitcode ("mov", "b,#0x%02x", -val);
3497 emitcode ("mov", "b,#0x%02x", val);
3500 lbl=newiTempLabel(NULL);
3501 emitcode ("mov", "b,a");
3502 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3503 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3504 // right side is negative, 8-bit two's complement
3505 emitcode ("cpl", "F0"); // complement sign flag
3506 emitcode ("cpl", "a");
3507 emitcode ("inc", "a");
3508 emitcode ("", "%05d$:", lbl->key+100);
3510 emitcode ("mul", "ab");
3512 lbl=newiTempLabel(NULL);
3513 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3514 // only ONE op was negative, we have to do a 8/16-bit two's complement
3515 emitcode ("cpl", "a"); // lsb
3517 emitcode ("inc", "a");
3519 emitcode ("add", "a,#1");
3520 emitcode ("xch", "a,b");
3521 emitcode ("cpl", "a"); // msb
3522 emitcode ("addc", "a,#0");
3523 emitcode ("xch", "a,b");
3526 emitcode ("", "%05d$:", lbl->key+100);
3527 aopPut (AOP (result), "a", 0);
3529 aopPut (AOP (result), "b", 1);
3533 /*-----------------------------------------------------------------*/
3534 /* genMult - generates code for multiplication */
3535 /*-----------------------------------------------------------------*/
3537 genMult (iCode * ic)
3539 operand *left = IC_LEFT (ic);
3540 operand *right = IC_RIGHT (ic);
3541 operand *result = IC_RESULT (ic);
3543 D(emitcode (";", "genMult"));
3545 /* assign the amsops */
3546 aopOp (left, ic, FALSE);
3547 aopOp (right, ic, FALSE);
3548 aopOp (result, ic, TRUE);
3550 /* special cases first */
3552 if (AOP_TYPE (left) == AOP_CRY &&
3553 AOP_TYPE (right) == AOP_CRY)
3555 genMultbits (left, right, result);
3559 /* if both are of size == 1 */
3560 #if 0 // one of them can be a sloc shared with the result
3561 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3563 if (getSize(operandType(left)) == 1 &&
3564 getSize(operandType(right)) == 1)
3567 genMultOneByte (left, right, result);
3571 /* should have been converted to function call */
3572 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3573 getSize(OP_SYMBOL(right)->type));
3577 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3578 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3579 freeAsmop (result, NULL, ic, TRUE);
3582 /*-----------------------------------------------------------------*/
3583 /* genDivbits :- division of bits */
3584 /*-----------------------------------------------------------------*/
3586 genDivbits (operand * left,
3593 D(emitcode (";", "genDivbits"));
3595 /* the result must be bit */
3596 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3597 l = aopGet (AOP (left), 0, FALSE, FALSE);
3601 emitcode ("div", "ab");
3602 emitcode ("rrc", "a");
3603 aopPut (AOP (result), "c", 0);
3606 /*-----------------------------------------------------------------*/
3607 /* genDivOneByte : 8 bit division */
3608 /*-----------------------------------------------------------------*/
3610 genDivOneByte (operand * left,
3614 sym_link *opetype = operandType (result);
3619 D(emitcode (";", "genDivOneByte"));
3621 size = AOP_SIZE (result) - 1;
3623 /* signed or unsigned */
3624 if (SPEC_USIGN (opetype))
3626 /* unsigned is easy */
3627 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3628 l = aopGet (AOP (left), 0, FALSE, FALSE);
3630 emitcode ("div", "ab");
3631 aopPut (AOP (result), "a", 0);
3633 aopPut (AOP (result), zero, offset++);
3637 /* signed is a little bit more difficult */
3639 /* save the signs of the operands */
3640 l = aopGet (AOP (left), 0, FALSE, FALSE);
3642 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3643 emitcode ("push", "acc"); /* save it on the stack */
3645 /* now sign adjust for both left & right */
3646 l = aopGet (AOP (right), 0, FALSE, FALSE);
3648 lbl = newiTempLabel (NULL);
3649 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3650 emitcode ("cpl", "a");
3651 emitcode ("inc", "a");
3652 emitcode ("", "%05d$:", (lbl->key + 100));
3653 emitcode ("mov", "b,a");
3655 /* sign adjust left side */
3656 l = aopGet (AOP (left), 0, FALSE, FALSE);
3659 lbl = newiTempLabel (NULL);
3660 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3661 emitcode ("cpl", "a");
3662 emitcode ("inc", "a");
3663 emitcode ("", "%05d$:", (lbl->key + 100));
3665 /* now the division */
3666 emitcode ("div", "ab");
3667 /* we are interested in the lower order
3669 emitcode ("mov", "b,a");
3670 lbl = newiTempLabel (NULL);
3671 emitcode ("pop", "acc");
3672 /* if there was an over flow we don't
3673 adjust the sign of the result */
3674 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3675 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3677 emitcode ("clr", "a");
3678 emitcode ("subb", "a,b");
3679 emitcode ("mov", "b,a");
3680 emitcode ("", "%05d$:", (lbl->key + 100));
3682 /* now we are done */
3683 aopPut (AOP (result), "b", 0);
3686 emitcode ("mov", "c,b.7");
3687 emitcode ("subb", "a,acc");
3690 aopPut (AOP (result), "a", offset++);
3694 /*-----------------------------------------------------------------*/
3695 /* genDiv - generates code for division */
3696 /*-----------------------------------------------------------------*/
3700 operand *left = IC_LEFT (ic);
3701 operand *right = IC_RIGHT (ic);
3702 operand *result = IC_RESULT (ic);
3704 D(emitcode (";", "genDiv"));
3706 /* assign the amsops */
3707 aopOp (left, ic, FALSE);
3708 aopOp (right, ic, FALSE);
3709 aopOp (result, ic, TRUE);
3711 /* special cases first */
3713 if (AOP_TYPE (left) == AOP_CRY &&
3714 AOP_TYPE (right) == AOP_CRY)
3716 genDivbits (left, right, result);
3720 /* if both are of size == 1 */
3721 if (AOP_SIZE (left) == 1 &&
3722 AOP_SIZE (right) == 1)
3724 genDivOneByte (left, right, result);
3728 /* should have been converted to function call */
3731 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3732 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3733 freeAsmop (result, NULL, ic, TRUE);
3736 /*-----------------------------------------------------------------*/
3737 /* genModbits :- modulus of bits */
3738 /*-----------------------------------------------------------------*/
3740 genModbits (operand * left,
3747 D(emitcode (";", "genModbits"));
3749 /* the result must be bit */
3750 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3751 l = aopGet (AOP (left), 0, FALSE, FALSE);
3755 emitcode ("div", "ab");
3756 emitcode ("mov", "a,b");
3757 emitcode ("rrc", "a");
3758 aopPut (AOP (result), "c", 0);
3761 /*-----------------------------------------------------------------*/
3762 /* genModOneByte : 8 bit modulus */
3763 /*-----------------------------------------------------------------*/
3765 genModOneByte (operand * left,
3769 sym_link *opetype = operandType (result);
3773 D(emitcode (";", "genModOneByte"));
3775 /* signed or unsigned */
3776 if (SPEC_USIGN (opetype))
3778 /* unsigned is easy */
3779 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3780 l = aopGet (AOP (left), 0, FALSE, FALSE);
3782 emitcode ("div", "ab");
3783 aopPut (AOP (result), "b", 0);
3787 /* signed is a little bit more difficult */
3789 /* save the signs of the operands */
3790 l = aopGet (AOP (left), 0, FALSE, FALSE);
3793 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3794 emitcode ("push", "acc"); /* save it on the stack */
3796 /* now sign adjust for both left & right */
3797 l = aopGet (AOP (right), 0, FALSE, FALSE);
3800 lbl = newiTempLabel (NULL);
3801 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3802 emitcode ("cpl", "a");
3803 emitcode ("inc", "a");
3804 emitcode ("", "%05d$:", (lbl->key + 100));
3805 emitcode ("mov", "b,a");
3807 /* sign adjust left side */
3808 l = aopGet (AOP (left), 0, FALSE, FALSE);
3811 lbl = newiTempLabel (NULL);
3812 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3813 emitcode ("cpl", "a");
3814 emitcode ("inc", "a");
3815 emitcode ("", "%05d$:", (lbl->key + 100));
3817 /* now the multiplication */
3818 emitcode ("div", "ab");
3819 /* we are interested in the lower order
3821 lbl = newiTempLabel (NULL);
3822 emitcode ("pop", "acc");
3823 /* if there was an over flow we don't
3824 adjust the sign of the result */
3825 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3826 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3828 emitcode ("clr", "a");
3829 emitcode ("subb", "a,b");
3830 emitcode ("mov", "b,a");
3831 emitcode ("", "%05d$:", (lbl->key + 100));
3833 /* now we are done */
3834 aopPut (AOP (result), "b", 0);
3838 /*-----------------------------------------------------------------*/
3839 /* genMod - generates code for division */
3840 /*-----------------------------------------------------------------*/
3844 operand *left = IC_LEFT (ic);
3845 operand *right = IC_RIGHT (ic);
3846 operand *result = IC_RESULT (ic);
3848 D(emitcode (";", "genMod"));
3850 /* assign the amsops */
3851 aopOp (left, ic, FALSE);
3852 aopOp (right, ic, FALSE);
3853 aopOp (result, ic, TRUE);
3855 /* special cases first */
3857 if (AOP_TYPE (left) == AOP_CRY &&
3858 AOP_TYPE (right) == AOP_CRY)
3860 genModbits (left, right, result);
3864 /* if both are of size == 1 */
3865 if (AOP_SIZE (left) == 1 &&
3866 AOP_SIZE (right) == 1)
3868 genModOneByte (left, right, result);
3872 /* should have been converted to function call */
3876 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3877 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3878 freeAsmop (result, NULL, ic, TRUE);
3881 /*-----------------------------------------------------------------*/
3882 /* genIfxJump :- will create a jump depending on the ifx */
3883 /*-----------------------------------------------------------------*/
3885 genIfxJump (iCode * ic, char *jval)
3888 symbol *tlbl = newiTempLabel (NULL);
3891 D(emitcode (";", "genIfxJump"));
3893 /* if true label then we jump if condition
3897 jlbl = IC_TRUE (ic);
3898 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3899 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3903 /* false label is present */
3904 jlbl = IC_FALSE (ic);
3905 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3906 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3908 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3909 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3911 emitcode (inst, "%05d$", tlbl->key + 100);
3912 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3913 emitcode ("", "%05d$:", tlbl->key + 100);
3915 /* mark the icode as generated */
3919 /*-----------------------------------------------------------------*/
3920 /* genCmp :- greater or less than comparison */
3921 /*-----------------------------------------------------------------*/
3923 genCmp (operand * left, operand * right,
3924 operand * result, iCode * ifx, int sign, iCode *ic)
3926 int size, offset = 0;
3927 unsigned long lit = 0L;
3929 D(emitcode (";", "genCmp"));
3931 /* if left & right are bit variables */
3932 if (AOP_TYPE (left) == AOP_CRY &&
3933 AOP_TYPE (right) == AOP_CRY)
3935 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3936 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3940 /* subtract right from left if at the
3941 end the carry flag is set then we know that
3942 left is greater than right */
3943 size = max (AOP_SIZE (left), AOP_SIZE (right));
3945 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3946 if ((size == 1) && !sign &&
3947 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3949 symbol *lbl = newiTempLabel (NULL);
3950 emitcode ("cjne", "%s,%s,%05d$",
3951 aopGet (AOP (left), offset, FALSE, FALSE),
3952 aopGet (AOP (right), offset, FALSE, FALSE),
3954 emitcode ("", "%05d$:", lbl->key + 100);
3958 if (AOP_TYPE (right) == AOP_LIT)
3960 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3961 /* optimize if(x < 0) or if(x >= 0) */
3970 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3971 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3973 genIfxJump (ifx, "acc.7");
3977 emitcode ("rlc", "a");
3985 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3986 if (sign && size == 0)
3988 emitcode ("xrl", "a,#0x80");
3989 if (AOP_TYPE (right) == AOP_LIT)
3991 unsigned long lit = (unsigned long)
3992 floatFromVal (AOP (right)->aopu.aop_lit);
3993 emitcode ("subb", "a,#0x%02x",
3994 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3998 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3999 emitcode ("xrl", "b,#0x80");
4000 emitcode ("subb", "a,b");
4004 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4010 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4011 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4012 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4018 /* if the result is used in the next
4019 ifx conditional branch then generate
4020 code a little differently */
4022 genIfxJump (ifx, "c");
4025 /* leave the result in acc */
4029 /*-----------------------------------------------------------------*/
4030 /* genCmpGt :- greater than comparison */
4031 /*-----------------------------------------------------------------*/
4033 genCmpGt (iCode * ic, iCode * ifx)
4035 operand *left, *right, *result;
4036 sym_link *letype, *retype;
4039 D(emitcode (";", "genCmpGt"));
4041 left = IC_LEFT (ic);
4042 right = IC_RIGHT (ic);
4043 result = IC_RESULT (ic);
4045 letype = getSpec (operandType (left));
4046 retype = getSpec (operandType (right));
4047 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4048 /* assign the amsops */
4049 aopOp (left, ic, FALSE);
4050 aopOp (right, ic, FALSE);
4051 aopOp (result, ic, TRUE);
4053 genCmp (right, left, result, ifx, sign,ic);
4055 freeAsmop (result, NULL, ic, TRUE);
4058 /*-----------------------------------------------------------------*/
4059 /* genCmpLt - less than comparisons */
4060 /*-----------------------------------------------------------------*/
4062 genCmpLt (iCode * ic, iCode * ifx)
4064 operand *left, *right, *result;
4065 sym_link *letype, *retype;
4068 D(emitcode (";", "genCmpLt"));
4070 left = IC_LEFT (ic);
4071 right = IC_RIGHT (ic);
4072 result = IC_RESULT (ic);
4074 letype = getSpec (operandType (left));
4075 retype = getSpec (operandType (right));
4076 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4078 /* assign the amsops */
4079 aopOp (left, ic, FALSE);
4080 aopOp (right, ic, FALSE);
4081 aopOp (result, ic, TRUE);
4083 genCmp (left, right, result, ifx, sign,ic);
4085 freeAsmop (result, NULL, ic, TRUE);
4088 /*-----------------------------------------------------------------*/
4089 /* gencjneshort - compare and jump if not equal */
4090 /*-----------------------------------------------------------------*/
4092 gencjneshort (operand * left, operand * right, symbol * lbl)
4094 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4096 unsigned long lit = 0L;
4098 /* if the left side is a literal or
4099 if the right is in a pointer register and left
4101 if ((AOP_TYPE (left) == AOP_LIT) ||
4102 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4108 if (AOP_TYPE (right) == AOP_LIT)
4109 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4111 /* if the right side is a literal then anything goes */
4112 if (AOP_TYPE (right) == AOP_LIT &&
4113 AOP_TYPE (left) != AOP_DIR)
4117 emitcode ("cjne", "%s,%s,%05d$",
4118 aopGet (AOP (left), offset, FALSE, FALSE),
4119 aopGet (AOP (right), offset, FALSE, FALSE),
4125 /* if the right side is in a register or in direct space or
4126 if the left is a pointer register & right is not */
4127 else if (AOP_TYPE (right) == AOP_REG ||
4128 AOP_TYPE (right) == AOP_DIR ||
4129 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4130 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4134 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4135 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4136 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4137 emitcode ("jnz", "%05d$", lbl->key + 100);
4139 emitcode ("cjne", "a,%s,%05d$",
4140 aopGet (AOP (right), offset, FALSE, TRUE),
4147 /* right is a pointer reg need both a & b */
4150 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4151 if (strcmp (l, "b"))
4152 emitcode ("mov", "b,%s", l);
4153 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4154 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4160 /*-----------------------------------------------------------------*/
4161 /* gencjne - compare and jump if not equal */
4162 /*-----------------------------------------------------------------*/
4164 gencjne (operand * left, operand * right, symbol * lbl)
4166 symbol *tlbl = newiTempLabel (NULL);
4168 gencjneshort (left, right, lbl);
4170 emitcode ("mov", "a,%s", one);
4171 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4172 emitcode ("", "%05d$:", lbl->key + 100);
4173 emitcode ("clr", "a");
4174 emitcode ("", "%05d$:", tlbl->key + 100);
4177 /*-----------------------------------------------------------------*/
4178 /* genCmpEq - generates code for equal to */
4179 /*-----------------------------------------------------------------*/
4181 genCmpEq (iCode * ic, iCode * ifx)
4183 operand *left, *right, *result;
4185 D(emitcode (";", "genCmpEq"));
4187 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4188 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4189 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4191 /* if literal, literal on the right or
4192 if the right is in a pointer register and left
4194 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4195 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4197 operand *t = IC_RIGHT (ic);
4198 IC_RIGHT (ic) = IC_LEFT (ic);
4202 if (ifx && !AOP_SIZE (result))
4205 /* if they are both bit variables */
4206 if (AOP_TYPE (left) == AOP_CRY &&
4207 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4209 if (AOP_TYPE (right) == AOP_LIT)
4211 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4214 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4215 emitcode ("cpl", "c");
4219 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4223 emitcode ("clr", "c");
4225 /* AOP_TYPE(right) == AOP_CRY */
4229 symbol *lbl = newiTempLabel (NULL);
4230 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4231 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4232 emitcode ("cpl", "c");
4233 emitcode ("", "%05d$:", (lbl->key + 100));
4235 /* if true label then we jump if condition
4237 tlbl = newiTempLabel (NULL);
4240 emitcode ("jnc", "%05d$", tlbl->key + 100);
4241 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4245 emitcode ("jc", "%05d$", tlbl->key + 100);
4246 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4248 emitcode ("", "%05d$:", tlbl->key + 100);
4252 tlbl = newiTempLabel (NULL);
4253 gencjneshort (left, right, tlbl);
4256 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4257 emitcode ("", "%05d$:", tlbl->key + 100);
4261 symbol *lbl = newiTempLabel (NULL);
4262 emitcode ("sjmp", "%05d$", lbl->key + 100);
4263 emitcode ("", "%05d$:", tlbl->key + 100);
4264 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4265 emitcode ("", "%05d$:", lbl->key + 100);
4268 /* mark the icode as generated */
4273 /* if they are both bit variables */
4274 if (AOP_TYPE (left) == AOP_CRY &&
4275 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4277 if (AOP_TYPE (right) == AOP_LIT)
4279 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4282 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4283 emitcode ("cpl", "c");
4287 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4291 emitcode ("clr", "c");
4293 /* AOP_TYPE(right) == AOP_CRY */
4297 symbol *lbl = newiTempLabel (NULL);
4298 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4299 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4300 emitcode ("cpl", "c");
4301 emitcode ("", "%05d$:", (lbl->key + 100));
4304 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4311 genIfxJump (ifx, "c");
4314 /* if the result is used in an arithmetic operation
4315 then put the result in place */
4320 gencjne (left, right, newiTempLabel (NULL));
4321 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4323 aopPut (AOP (result), "a", 0);
4328 genIfxJump (ifx, "a");
4331 /* if the result is used in an arithmetic operation
4332 then put the result in place */
4333 if (AOP_TYPE (result) != AOP_CRY)
4335 /* leave the result in acc */
4339 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4340 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4341 freeAsmop (result, NULL, ic, TRUE);
4344 /*-----------------------------------------------------------------*/
4345 /* ifxForOp - returns the icode containing the ifx for operand */
4346 /*-----------------------------------------------------------------*/
4348 ifxForOp (operand * op, iCode * ic)
4350 /* if true symbol then needs to be assigned */
4351 if (IS_TRUE_SYMOP (op))
4354 /* if this has register type condition and
4355 the next instruction is ifx with the same operand
4356 and live to of the operand is upto the ifx only then */
4358 ic->next->op == IFX &&
4359 IC_COND (ic->next)->key == op->key &&
4360 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4366 /*-----------------------------------------------------------------*/
4367 /* hasInc - operand is incremented before any other use */
4368 /*-----------------------------------------------------------------*/
4370 hasInc (operand *op, iCode *ic,int osize)
4372 sym_link *type = operandType(op);
4373 sym_link *retype = getSpec (type);
4374 iCode *lic = ic->next;
4377 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4378 if (!IS_SYMOP(op)) return NULL;
4380 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4381 if (IS_AGGREGATE(type->next)) return NULL;
4382 if (osize != (isize = getSize(type->next))) return NULL;
4385 /* if operand of the form op = op + <sizeof *op> */
4386 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4387 isOperandEqual(IC_RESULT(lic),op) &&
4388 isOperandLiteral(IC_RIGHT(lic)) &&
4389 operandLitValue(IC_RIGHT(lic)) == isize) {
4392 /* if the operand used or deffed */
4393 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4396 /* if GOTO or IFX */
4397 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4403 /*-----------------------------------------------------------------*/
4404 /* genAndOp - for && operation */
4405 /*-----------------------------------------------------------------*/
4407 genAndOp (iCode * ic)
4409 operand *left, *right, *result;
4412 D(emitcode (";", "genAndOp"));
4414 /* note here that && operations that are in an
4415 if statement are taken away by backPatchLabels
4416 only those used in arthmetic operations remain */
4417 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4418 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4419 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4421 /* if both are bit variables */
4422 if (AOP_TYPE (left) == AOP_CRY &&
4423 AOP_TYPE (right) == AOP_CRY)
4425 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4426 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4431 tlbl = newiTempLabel (NULL);
4433 emitcode ("jz", "%05d$", tlbl->key + 100);
4435 emitcode ("", "%05d$:", tlbl->key + 100);
4439 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4440 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4441 freeAsmop (result, NULL, ic, TRUE);
4445 /*-----------------------------------------------------------------*/
4446 /* genOrOp - for || operation */
4447 /*-----------------------------------------------------------------*/
4449 genOrOp (iCode * ic)
4451 operand *left, *right, *result;
4454 D(emitcode (";", "genOrOp"));
4456 /* note here that || operations that are in an
4457 if statement are taken away by backPatchLabels
4458 only those used in arthmetic operations remain */
4459 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4460 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4461 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4463 /* if both are bit variables */
4464 if (AOP_TYPE (left) == AOP_CRY &&
4465 AOP_TYPE (right) == AOP_CRY)
4467 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4468 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4473 tlbl = newiTempLabel (NULL);
4475 emitcode ("jnz", "%05d$", tlbl->key + 100);
4477 emitcode ("", "%05d$:", tlbl->key + 100);
4481 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4482 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4483 freeAsmop (result, NULL, ic, TRUE);
4486 /*-----------------------------------------------------------------*/
4487 /* isLiteralBit - test if lit == 2^n */
4488 /*-----------------------------------------------------------------*/
4490 isLiteralBit (unsigned long lit)
4492 unsigned long pw[32] =
4493 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4494 0x100L, 0x200L, 0x400L, 0x800L,
4495 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4496 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4497 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4498 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4499 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4502 for (idx = 0; idx < 32; idx++)
4508 /*-----------------------------------------------------------------*/
4509 /* continueIfTrue - */
4510 /*-----------------------------------------------------------------*/
4512 continueIfTrue (iCode * ic)
4515 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4519 /*-----------------------------------------------------------------*/
4521 /*-----------------------------------------------------------------*/
4523 jumpIfTrue (iCode * ic)
4526 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4530 /*-----------------------------------------------------------------*/
4531 /* jmpTrueOrFalse - */
4532 /*-----------------------------------------------------------------*/
4534 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4536 // ugly but optimized by peephole
4539 symbol *nlbl = newiTempLabel (NULL);
4540 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4541 emitcode ("", "%05d$:", tlbl->key + 100);
4542 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4543 emitcode ("", "%05d$:", nlbl->key + 100);
4547 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4548 emitcode ("", "%05d$:", tlbl->key + 100);
4553 /*-----------------------------------------------------------------*/
4554 /* genAnd - code for and */
4555 /*-----------------------------------------------------------------*/
4557 genAnd (iCode * ic, iCode * ifx)
4559 operand *left, *right, *result;
4560 int size, offset = 0;
4561 unsigned long lit = 0L;
4565 D(emitcode (";", "genAnd"));
4567 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4568 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4569 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4572 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4574 AOP_TYPE (left), AOP_TYPE (right));
4575 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4577 AOP_SIZE (left), AOP_SIZE (right));
4580 /* if left is a literal & right is not then exchange them */
4581 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4582 AOP_NEEDSACC (left))
4584 operand *tmp = right;
4589 /* if result = right then exchange them */
4590 if (sameRegs (AOP (result), AOP (right)))
4592 operand *tmp = right;
4597 /* if right is bit then exchange them */
4598 if (AOP_TYPE (right) == AOP_CRY &&
4599 AOP_TYPE (left) != AOP_CRY)
4601 operand *tmp = right;
4605 if (AOP_TYPE (right) == AOP_LIT)
4606 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4608 size = AOP_SIZE (result);
4611 // result = bit & yy;
4612 if (AOP_TYPE (left) == AOP_CRY)
4614 // c = bit & literal;
4615 if (AOP_TYPE (right) == AOP_LIT)
4619 if (size && sameRegs (AOP (result), AOP (left)))
4622 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4627 if (size && (AOP_TYPE (result) == AOP_CRY))
4629 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4632 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4637 emitcode ("clr", "c");
4642 if (AOP_TYPE (right) == AOP_CRY)
4645 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4646 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4651 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4653 emitcode ("rrc", "a");
4654 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4662 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4663 genIfxJump (ifx, "c");
4667 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4668 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4669 if ((AOP_TYPE (right) == AOP_LIT) &&
4670 (AOP_TYPE (result) == AOP_CRY) &&
4671 (AOP_TYPE (left) != AOP_CRY))
4673 int posbit = isLiteralBit (lit);
4678 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4681 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4687 sprintf (buffer, "acc.%d", posbit & 0x07);
4688 genIfxJump (ifx, buffer);
4695 symbol *tlbl = newiTempLabel (NULL);
4696 int sizel = AOP_SIZE (left);
4698 emitcode ("setb", "c");
4701 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4703 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4705 if ((posbit = isLiteralBit (bytelit)) != 0)
4706 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4709 if (bytelit != 0x0FFL)
4710 emitcode ("anl", "a,%s",
4711 aopGet (AOP (right), offset, FALSE, TRUE));
4712 emitcode ("jnz", "%05d$", tlbl->key + 100);
4717 // bit = left & literal
4720 emitcode ("clr", "c");
4721 emitcode ("", "%05d$:", tlbl->key + 100);
4723 // if(left & literal)
4727 jmpTrueOrFalse (ifx, tlbl);
4735 /* if left is same as result */
4736 if (sameRegs (AOP (result), AOP (left)))
4738 for (; size--; offset++)
4740 if (AOP_TYPE (right) == AOP_LIT)
4742 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4744 else if (bytelit == 0)
4745 aopPut (AOP (result), zero, offset);
4746 else if (IS_AOP_PREG (result))
4748 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4749 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4750 aopPut (AOP (result), "a", offset);
4753 emitcode ("anl", "%s,%s",
4754 aopGet (AOP (left), offset, FALSE, TRUE),
4755 aopGet (AOP (right), offset, FALSE, FALSE));
4759 if (AOP_TYPE (left) == AOP_ACC)
4760 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4763 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4764 if (IS_AOP_PREG (result))
4766 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4767 aopPut (AOP (result), "a", offset);
4771 emitcode ("anl", "%s,a",
4772 aopGet (AOP (left), offset, FALSE, TRUE));
4779 // left & result in different registers
4780 if (AOP_TYPE (result) == AOP_CRY)
4783 // if(size), result in bit
4784 // if(!size && ifx), conditional oper: if(left & right)
4785 symbol *tlbl = newiTempLabel (NULL);
4786 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4788 emitcode ("setb", "c");
4791 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4792 emitcode ("anl", "a,%s",
4793 aopGet (AOP (right), offset, FALSE, FALSE));
4795 if (AOP_TYPE(left)==AOP_ACC) {
4796 emitcode("mov", "b,a");
4797 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4798 emitcode("anl", "a,b");
4800 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4801 emitcode ("anl", "a,%s",
4802 aopGet (AOP (left), offset, FALSE, FALSE));
4805 emitcode ("jnz", "%05d$", tlbl->key + 100);
4811 emitcode ("", "%05d$:", tlbl->key + 100);
4815 jmpTrueOrFalse (ifx, tlbl);
4819 for (; (size--); offset++)
4822 // result = left & right
4823 if (AOP_TYPE (right) == AOP_LIT)
4825 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4827 aopPut (AOP (result),
4828 aopGet (AOP (left), offset, FALSE, FALSE),
4832 else if (bytelit == 0)
4834 aopPut (AOP (result), zero, offset);
4838 // faster than result <- left, anl result,right
4839 // and better if result is SFR
4840 if (AOP_TYPE (left) == AOP_ACC)
4841 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4844 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4845 emitcode ("anl", "a,%s",
4846 aopGet (AOP (left), offset, FALSE, FALSE));
4848 aopPut (AOP (result), "a", offset);
4854 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4855 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4856 freeAsmop (result, NULL, ic, TRUE);
4859 /*-----------------------------------------------------------------*/
4860 /* genOr - code for or */
4861 /*-----------------------------------------------------------------*/
4863 genOr (iCode * ic, iCode * ifx)
4865 operand *left, *right, *result;
4866 int size, offset = 0;
4867 unsigned long lit = 0L;
4869 D(emitcode (";", "genOr"));
4871 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4872 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4873 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4876 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4878 AOP_TYPE (left), AOP_TYPE (right));
4879 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4881 AOP_SIZE (left), AOP_SIZE (right));
4884 /* if left is a literal & right is not then exchange them */
4885 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4886 AOP_NEEDSACC (left))
4888 operand *tmp = right;
4893 /* if result = right then exchange them */
4894 if (sameRegs (AOP (result), AOP (right)))
4896 operand *tmp = right;
4901 /* if right is bit then exchange them */
4902 if (AOP_TYPE (right) == AOP_CRY &&
4903 AOP_TYPE (left) != AOP_CRY)
4905 operand *tmp = right;
4909 if (AOP_TYPE (right) == AOP_LIT)
4910 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4912 size = AOP_SIZE (result);
4916 if (AOP_TYPE (left) == AOP_CRY)
4918 if (AOP_TYPE (right) == AOP_LIT)
4920 // c = bit | literal;
4923 // lit != 0 => result = 1
4924 if (AOP_TYPE (result) == AOP_CRY)
4927 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4929 continueIfTrue (ifx);
4932 emitcode ("setb", "c");
4936 // lit == 0 => result = left
4937 if (size && sameRegs (AOP (result), AOP (left)))
4939 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4944 if (AOP_TYPE (right) == AOP_CRY)
4947 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4948 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4953 symbol *tlbl = newiTempLabel (NULL);
4954 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4955 emitcode ("setb", "c");
4956 emitcode ("jb", "%s,%05d$",
4957 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4959 emitcode ("jnz", "%05d$", tlbl->key + 100);
4960 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4962 jmpTrueOrFalse (ifx, tlbl);
4968 emitcode ("", "%05d$:", tlbl->key + 100);
4977 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4978 genIfxJump (ifx, "c");
4982 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4983 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4984 if ((AOP_TYPE (right) == AOP_LIT) &&
4985 (AOP_TYPE (result) == AOP_CRY) &&
4986 (AOP_TYPE (left) != AOP_CRY))
4992 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4994 continueIfTrue (ifx);
4999 // lit = 0, result = boolean(left)
5001 emitcode ("setb", "c");
5005 symbol *tlbl = newiTempLabel (NULL);
5006 emitcode ("jnz", "%05d$", tlbl->key + 100);
5008 emitcode ("", "%05d$:", tlbl->key + 100);
5012 genIfxJump (ifx, "a");
5020 /* if left is same as result */
5021 if (sameRegs (AOP (result), AOP (left)))
5023 for (; size--; offset++)
5025 if (AOP_TYPE (right) == AOP_LIT)
5027 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5029 else if (IS_AOP_PREG (left))
5031 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5032 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5033 aopPut (AOP (result), "a", offset);
5036 emitcode ("orl", "%s,%s",
5037 aopGet (AOP (left), offset, FALSE, TRUE),
5038 aopGet (AOP (right), offset, FALSE, FALSE));
5042 if (AOP_TYPE (left) == AOP_ACC)
5043 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5046 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5047 if (IS_AOP_PREG (left))
5049 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5050 aopPut (AOP (result), "a", offset);
5053 emitcode ("orl", "%s,a",
5054 aopGet (AOP (left), offset, FALSE, TRUE));
5061 // left & result in different registers
5062 if (AOP_TYPE (result) == AOP_CRY)
5065 // if(size), result in bit
5066 // if(!size && ifx), conditional oper: if(left | right)
5067 symbol *tlbl = newiTempLabel (NULL);
5068 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5070 emitcode ("setb", "c");
5073 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5074 emitcode ("orl", "a,%s",
5075 aopGet (AOP (right), offset, FALSE, FALSE));
5077 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5078 emitcode ("orl", "a,%s",
5079 aopGet (AOP (left), offset, FALSE, FALSE));
5081 emitcode ("jnz", "%05d$", tlbl->key + 100);
5087 emitcode ("", "%05d$:", tlbl->key + 100);
5091 jmpTrueOrFalse (ifx, tlbl);
5094 for (; (size--); offset++)
5097 // result = left & right
5098 if (AOP_TYPE (right) == AOP_LIT)
5100 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5102 aopPut (AOP (result),
5103 aopGet (AOP (left), offset, FALSE, FALSE),
5108 // faster than result <- left, anl result,right
5109 // and better if result is SFR
5110 if (AOP_TYPE (left) == AOP_ACC)
5111 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5114 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5115 emitcode ("orl", "a,%s",
5116 aopGet (AOP (left), offset, FALSE, FALSE));
5118 aopPut (AOP (result), "a", offset);
5123 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5124 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5125 freeAsmop (result, NULL, ic, TRUE);
5128 /*-----------------------------------------------------------------*/
5129 /* genXor - code for xclusive or */
5130 /*-----------------------------------------------------------------*/
5132 genXor (iCode * ic, iCode * ifx)
5134 operand *left, *right, *result;
5135 int size, offset = 0;
5136 unsigned long lit = 0L;
5138 D(emitcode (";", "genXor"));
5140 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5141 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5142 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5145 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5147 AOP_TYPE (left), AOP_TYPE (right));
5148 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5150 AOP_SIZE (left), AOP_SIZE (right));
5153 /* if left is a literal & right is not ||
5154 if left needs acc & right does not */
5155 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5156 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5158 operand *tmp = right;
5163 /* if result = right then exchange them */
5164 if (sameRegs (AOP (result), AOP (right)))
5166 operand *tmp = right;
5171 /* if right is bit then exchange them */
5172 if (AOP_TYPE (right) == AOP_CRY &&
5173 AOP_TYPE (left) != AOP_CRY)
5175 operand *tmp = right;
5179 if (AOP_TYPE (right) == AOP_LIT)
5180 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5182 size = AOP_SIZE (result);
5186 if (AOP_TYPE (left) == AOP_CRY)
5188 if (AOP_TYPE (right) == AOP_LIT)
5190 // c = bit & literal;
5193 // lit>>1 != 0 => result = 1
5194 if (AOP_TYPE (result) == AOP_CRY)
5197 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5199 continueIfTrue (ifx);
5202 emitcode ("setb", "c");
5209 // lit == 0, result = left
5210 if (size && sameRegs (AOP (result), AOP (left)))
5212 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5216 // lit == 1, result = not(left)
5217 if (size && sameRegs (AOP (result), AOP (left)))
5219 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5224 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5225 emitcode ("cpl", "c");
5234 symbol *tlbl = newiTempLabel (NULL);
5235 if (AOP_TYPE (right) == AOP_CRY)
5238 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5242 int sizer = AOP_SIZE (right);
5244 // if val>>1 != 0, result = 1
5245 emitcode ("setb", "c");
5248 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5250 // test the msb of the lsb
5251 emitcode ("anl", "a,#0xfe");
5252 emitcode ("jnz", "%05d$", tlbl->key + 100);
5256 emitcode ("rrc", "a");
5258 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5259 emitcode ("cpl", "c");
5260 emitcode ("", "%05d$:", (tlbl->key + 100));
5267 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5268 genIfxJump (ifx, "c");
5272 if (sameRegs (AOP (result), AOP (left)))
5274 /* if left is same as result */
5275 for (; size--; offset++)
5277 if (AOP_TYPE (right) == AOP_LIT)
5279 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5281 else if (IS_AOP_PREG (left))
5283 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5284 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5285 aopPut (AOP (result), "a", offset);
5288 emitcode ("xrl", "%s,%s",
5289 aopGet (AOP (left), offset, FALSE, TRUE),
5290 aopGet (AOP (right), offset, FALSE, FALSE));
5294 if (AOP_TYPE (left) == AOP_ACC)
5295 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5298 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5299 if (IS_AOP_PREG (left))
5301 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5302 aopPut (AOP (result), "a", offset);
5305 emitcode ("xrl", "%s,a",
5306 aopGet (AOP (left), offset, FALSE, TRUE));
5313 // left & result in different registers
5314 if (AOP_TYPE (result) == AOP_CRY)
5317 // if(size), result in bit
5318 // if(!size && ifx), conditional oper: if(left ^ right)
5319 symbol *tlbl = newiTempLabel (NULL);
5320 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5322 emitcode ("setb", "c");
5325 if ((AOP_TYPE (right) == AOP_LIT) &&
5326 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5328 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5332 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5333 emitcode ("xrl", "a,%s",
5334 aopGet (AOP (right), offset, FALSE, FALSE));
5336 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5337 emitcode ("xrl", "a,%s",
5338 aopGet (AOP (left), offset, FALSE, FALSE));
5341 emitcode ("jnz", "%05d$", tlbl->key + 100);
5347 emitcode ("", "%05d$:", tlbl->key + 100);
5351 jmpTrueOrFalse (ifx, tlbl);
5354 for (; (size--); offset++)
5357 // result = left & right
5358 if (AOP_TYPE (right) == AOP_LIT)
5360 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5362 aopPut (AOP (result),
5363 aopGet (AOP (left), offset, FALSE, FALSE),
5368 // faster than result <- left, anl result,right
5369 // and better if result is SFR
5370 if (AOP_TYPE (left) == AOP_ACC)
5371 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5374 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5375 emitcode ("xrl", "a,%s",
5376 aopGet (AOP (left), offset, FALSE, TRUE));
5378 aopPut (AOP (result), "a", offset);
5383 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5384 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5385 freeAsmop (result, NULL, ic, TRUE);
5388 /*-----------------------------------------------------------------*/
5389 /* genInline - write the inline code out */
5390 /*-----------------------------------------------------------------*/
5392 genInline (iCode * ic)
5394 char *buffer, *bp, *bp1;
5396 D(emitcode (";", "genInline"));
5398 _G.inLine += (!options.asmpeep);
5400 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5401 strcpy (buffer, IC_INLINE (ic));
5403 /* emit each line as a code */
5428 /* emitcode("",buffer); */
5429 _G.inLine -= (!options.asmpeep);
5432 /*-----------------------------------------------------------------*/
5433 /* genRRC - rotate right with carry */
5434 /*-----------------------------------------------------------------*/
5438 operand *left, *result;
5439 int size, offset = 0;
5442 D(emitcode (";", "genRRC"));
5444 /* rotate right with carry */
5445 left = IC_LEFT (ic);
5446 result = IC_RESULT (ic);
5447 aopOp (left, ic, FALSE);
5448 aopOp (result, ic, FALSE);
5450 /* move it to the result */
5451 size = AOP_SIZE (result);
5453 if (size == 1) { /* special case for 1 byte */
5454 l = aopGet (AOP (left), offset, FALSE, FALSE);
5456 emitcode ("rr", "a");
5462 l = aopGet (AOP (left), offset, FALSE, FALSE);
5464 emitcode ("rrc", "a");
5465 if (AOP_SIZE (result) > 1)
5466 aopPut (AOP (result), "a", offset--);
5468 /* now we need to put the carry into the
5469 highest order byte of the result */
5470 if (AOP_SIZE (result) > 1)
5472 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5475 emitcode ("mov", "acc.7,c");
5477 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5478 freeAsmop (left, NULL, ic, TRUE);
5479 freeAsmop (result, NULL, ic, TRUE);
5482 /*-----------------------------------------------------------------*/
5483 /* genRLC - generate code for rotate left with carry */
5484 /*-----------------------------------------------------------------*/
5488 operand *left, *result;
5489 int size, offset = 0;
5492 D(emitcode (";", "genRLC"));
5494 /* rotate right with carry */
5495 left = IC_LEFT (ic);
5496 result = IC_RESULT (ic);
5497 aopOp (left, ic, FALSE);
5498 aopOp (result, ic, FALSE);
5500 /* move it to the result */
5501 size = AOP_SIZE (result);
5505 l = aopGet (AOP (left), offset, FALSE, FALSE);
5507 if (size == 0) { /* special case for 1 byte */
5511 emitcode ("add", "a,acc");
5512 if (AOP_SIZE (result) > 1)
5513 aopPut (AOP (result), "a", offset++);
5516 l = aopGet (AOP (left), offset, FALSE, FALSE);
5518 emitcode ("rlc", "a");
5519 if (AOP_SIZE (result) > 1)
5520 aopPut (AOP (result), "a", offset++);
5523 /* now we need to put the carry into the
5524 highest order byte of the result */
5525 if (AOP_SIZE (result) > 1)
5527 l = aopGet (AOP (result), 0, FALSE, FALSE);
5530 emitcode ("mov", "acc.0,c");
5532 aopPut (AOP (result), "a", 0);
5533 freeAsmop (left, NULL, ic, TRUE);
5534 freeAsmop (result, NULL, ic, TRUE);
5537 /*-----------------------------------------------------------------*/
5538 /* genGetHbit - generates code get highest order bit */
5539 /*-----------------------------------------------------------------*/
5541 genGetHbit (iCode * ic)
5543 operand *left, *result;
5545 D(emitcode (";", "genGetHbit"));
5547 left = IC_LEFT (ic);
5548 result = IC_RESULT (ic);
5549 aopOp (left, ic, FALSE);
5550 aopOp (result, ic, FALSE);
5552 /* get the highest order byte into a */
5553 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5554 if (AOP_TYPE (result) == AOP_CRY)
5556 emitcode ("rlc", "a");
5561 emitcode ("rl", "a");
5562 emitcode ("anl", "a,#0x01");
5567 freeAsmop (left, NULL, ic, TRUE);
5568 freeAsmop (result, NULL, ic, TRUE);
5571 /*-----------------------------------------------------------------*/
5572 /* AccRol - rotate left accumulator by known count */
5573 /*-----------------------------------------------------------------*/
5575 AccRol (int shCount)
5577 shCount &= 0x0007; // shCount : 0..7
5584 emitcode ("rl", "a");
5587 emitcode ("rl", "a");
5588 emitcode ("rl", "a");
5591 emitcode ("swap", "a");
5592 emitcode ("rr", "a");
5595 emitcode ("swap", "a");
5598 emitcode ("swap", "a");
5599 emitcode ("rl", "a");
5602 emitcode ("rr", "a");
5603 emitcode ("rr", "a");
5606 emitcode ("rr", "a");
5611 /*-----------------------------------------------------------------*/
5612 /* AccLsh - left shift accumulator by known count */
5613 /*-----------------------------------------------------------------*/
5615 AccLsh (int shCount)
5620 emitcode ("add", "a,acc");
5621 else if (shCount == 2)
5623 emitcode ("add", "a,acc");
5624 emitcode ("add", "a,acc");
5628 /* rotate left accumulator */
5630 /* and kill the lower order bits */
5631 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5636 /*-----------------------------------------------------------------*/
5637 /* AccRsh - right shift accumulator by known count */
5638 /*-----------------------------------------------------------------*/
5640 AccRsh (int shCount)
5647 emitcode ("rrc", "a");
5651 /* rotate right accumulator */
5652 AccRol (8 - shCount);
5653 /* and kill the higher order bits */
5654 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5659 /*-----------------------------------------------------------------*/
5660 /* AccSRsh - signed right shift accumulator by known count */
5661 /*-----------------------------------------------------------------*/
5663 AccSRsh (int shCount)
5670 emitcode ("mov", "c,acc.7");
5671 emitcode ("rrc", "a");
5673 else if (shCount == 2)
5675 emitcode ("mov", "c,acc.7");
5676 emitcode ("rrc", "a");
5677 emitcode ("mov", "c,acc.7");
5678 emitcode ("rrc", "a");
5682 tlbl = newiTempLabel (NULL);
5683 /* rotate right accumulator */
5684 AccRol (8 - shCount);
5685 /* and kill the higher order bits */
5686 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5687 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5688 emitcode ("orl", "a,#0x%02x",
5689 (unsigned char) ~SRMask[shCount]);
5690 emitcode ("", "%05d$:", tlbl->key + 100);
5695 /*-----------------------------------------------------------------*/
5696 /* shiftR1Left2Result - shift right one byte from left to result */
5697 /*-----------------------------------------------------------------*/
5699 shiftR1Left2Result (operand * left, int offl,
5700 operand * result, int offr,
5701 int shCount, int sign)
5703 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5704 /* shift right accumulator */
5709 aopPut (AOP (result), "a", offr);
5712 /*-----------------------------------------------------------------*/
5713 /* shiftL1Left2Result - shift left one byte from left to result */
5714 /*-----------------------------------------------------------------*/
5716 shiftL1Left2Result (operand * left, int offl,
5717 operand * result, int offr, int shCount)
5720 l = aopGet (AOP (left), offl, FALSE, FALSE);
5722 /* shift left accumulator */
5724 aopPut (AOP (result), "a", offr);
5727 /*-----------------------------------------------------------------*/
5728 /* movLeft2Result - move byte from left to result */
5729 /*-----------------------------------------------------------------*/
5731 movLeft2Result (operand * left, int offl,
5732 operand * result, int offr, int sign)
5735 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5737 l = aopGet (AOP (left), offl, FALSE, FALSE);
5739 if (*l == '@' && (IS_AOP_PREG (result)))
5741 emitcode ("mov", "a,%s", l);
5742 aopPut (AOP (result), "a", offr);
5747 aopPut (AOP (result), l, offr);
5750 /* MSB sign in acc.7 ! */
5751 if (getDataSize (left) == offl + 1)
5753 emitcode ("mov", "a,%s", l);
5754 aopPut (AOP (result), "a", offr);
5761 /*-----------------------------------------------------------------*/
5762 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5763 /*-----------------------------------------------------------------*/
5767 emitcode ("rrc", "a");
5768 emitcode ("xch", "a,%s", x);
5769 emitcode ("rrc", "a");
5770 emitcode ("xch", "a,%s", x);
5773 /*-----------------------------------------------------------------*/
5774 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5775 /*-----------------------------------------------------------------*/
5779 emitcode ("xch", "a,%s", x);
5780 emitcode ("rlc", "a");
5781 emitcode ("xch", "a,%s", x);
5782 emitcode ("rlc", "a");
5785 /*-----------------------------------------------------------------*/
5786 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5787 /*-----------------------------------------------------------------*/
5791 emitcode ("xch", "a,%s", x);
5792 emitcode ("add", "a,acc");
5793 emitcode ("xch", "a,%s", x);
5794 emitcode ("rlc", "a");
5797 /*-----------------------------------------------------------------*/
5798 /* AccAXLsh - left shift a:x by known count (0..7) */
5799 /*-----------------------------------------------------------------*/
5801 AccAXLsh (char *x, int shCount)
5816 case 5: // AAAAABBB:CCCCCDDD
5818 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5820 emitcode ("anl", "a,#0x%02x",
5821 SLMask[shCount]); // BBB00000:CCCCCDDD
5823 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5825 AccRol (shCount); // DDDCCCCC:BBB00000
5827 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5829 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5831 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5833 emitcode ("anl", "a,#0x%02x",
5834 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5836 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5838 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5841 case 6: // AAAAAABB:CCCCCCDD
5842 emitcode ("anl", "a,#0x%02x",
5843 SRMask[shCount]); // 000000BB:CCCCCCDD
5844 emitcode ("mov", "c,acc.0"); // c = B
5845 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5847 AccAXRrl1 (x); // BCCCCCCD:D000000B
5848 AccAXRrl1 (x); // BBCCCCCC:DD000000
5850 emitcode("rrc","a");
5851 emitcode("xch","a,%s", x);
5852 emitcode("rrc","a");
5853 emitcode("mov","c,acc.0"); //<< get correct bit
5854 emitcode("xch","a,%s", x);
5856 emitcode("rrc","a");
5857 emitcode("xch","a,%s", x);
5858 emitcode("rrc","a");
5859 emitcode("xch","a,%s", x);
5862 case 7: // a:x <<= 7
5864 emitcode ("anl", "a,#0x%02x",
5865 SRMask[shCount]); // 0000000B:CCCCCCCD
5867 emitcode ("mov", "c,acc.0"); // c = B
5869 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5871 AccAXRrl1 (x); // BCCCCCCC:D0000000
5879 /*-----------------------------------------------------------------*/
5880 /* AccAXRsh - right shift a:x known count (0..7) */
5881 /*-----------------------------------------------------------------*/
5883 AccAXRsh (char *x, int shCount)
5891 AccAXRrl1 (x); // 0->a:x
5896 AccAXRrl1 (x); // 0->a:x
5899 AccAXRrl1 (x); // 0->a:x
5904 case 5: // AAAAABBB:CCCCCDDD = a:x
5906 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5908 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5910 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5912 emitcode ("anl", "a,#0x%02x",
5913 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5915 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5917 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5919 emitcode ("anl", "a,#0x%02x",
5920 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5922 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5924 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5926 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5929 case 6: // AABBBBBB:CCDDDDDD
5931 emitcode ("mov", "c,acc.7");
5932 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5934 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5936 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5938 emitcode ("anl", "a,#0x%02x",
5939 SRMask[shCount]); // 000000AA:BBBBBBCC
5942 case 7: // ABBBBBBB:CDDDDDDD
5944 emitcode ("mov", "c,acc.7"); // c = A
5946 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5948 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5950 emitcode ("anl", "a,#0x%02x",
5951 SRMask[shCount]); // 0000000A:BBBBBBBC
5959 /*-----------------------------------------------------------------*/
5960 /* AccAXRshS - right shift signed a:x known count (0..7) */
5961 /*-----------------------------------------------------------------*/
5963 AccAXRshS (char *x, int shCount)
5971 emitcode ("mov", "c,acc.7");
5972 AccAXRrl1 (x); // s->a:x
5976 emitcode ("mov", "c,acc.7");
5977 AccAXRrl1 (x); // s->a:x
5979 emitcode ("mov", "c,acc.7");
5980 AccAXRrl1 (x); // s->a:x
5985 case 5: // AAAAABBB:CCCCCDDD = a:x
5987 tlbl = newiTempLabel (NULL);
5988 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5990 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5992 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5994 emitcode ("anl", "a,#0x%02x",
5995 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5997 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5999 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6001 emitcode ("anl", "a,#0x%02x",
6002 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6004 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6006 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6008 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6010 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6011 emitcode ("orl", "a,#0x%02x",
6012 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6014 emitcode ("", "%05d$:", tlbl->key + 100);
6015 break; // SSSSAAAA:BBBCCCCC
6017 case 6: // AABBBBBB:CCDDDDDD
6019 tlbl = newiTempLabel (NULL);
6020 emitcode ("mov", "c,acc.7");
6021 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6023 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6025 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6027 emitcode ("anl", "a,#0x%02x",
6028 SRMask[shCount]); // 000000AA:BBBBBBCC
6030 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6031 emitcode ("orl", "a,#0x%02x",
6032 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6034 emitcode ("", "%05d$:", tlbl->key + 100);
6036 case 7: // ABBBBBBB:CDDDDDDD
6038 tlbl = newiTempLabel (NULL);
6039 emitcode ("mov", "c,acc.7"); // c = A
6041 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6043 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6045 emitcode ("anl", "a,#0x%02x",
6046 SRMask[shCount]); // 0000000A:BBBBBBBC
6048 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6049 emitcode ("orl", "a,#0x%02x",
6050 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6052 emitcode ("", "%05d$:", tlbl->key + 100);
6059 /*-----------------------------------------------------------------*/
6060 /* shiftL2Left2Result - shift left two bytes from left to result */
6061 /*-----------------------------------------------------------------*/
6063 shiftL2Left2Result (operand * left, int offl,
6064 operand * result, int offr, int shCount)
6066 if (sameRegs (AOP (result), AOP (left)) &&
6067 ((offl + MSB16) == offr))
6069 /* don't crash result[offr] */
6070 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6071 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6075 movLeft2Result (left, offl, result, offr, 0);
6076 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6078 /* ax << shCount (x = lsb(result)) */
6079 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6080 aopPut (AOP (result), "a", offr + MSB16);
6084 /*-----------------------------------------------------------------*/
6085 /* shiftR2Left2Result - shift right two bytes from left to result */
6086 /*-----------------------------------------------------------------*/
6088 shiftR2Left2Result (operand * left, int offl,
6089 operand * result, int offr,
6090 int shCount, int sign)
6092 if (sameRegs (AOP (result), AOP (left)) &&
6093 ((offl + MSB16) == offr))
6095 /* don't crash result[offr] */
6096 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6097 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6101 movLeft2Result (left, offl, result, offr, 0);
6102 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6104 /* a:x >> shCount (x = lsb(result)) */
6106 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6108 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6109 if (getDataSize (result) > 1)
6110 aopPut (AOP (result), "a", offr + MSB16);
6113 /*-----------------------------------------------------------------*/
6114 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6115 /*-----------------------------------------------------------------*/
6117 shiftLLeftOrResult (operand * left, int offl,
6118 operand * result, int offr, int shCount)
6120 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6121 /* shift left accumulator */
6123 /* or with result */
6124 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6125 /* back to result */
6126 aopPut (AOP (result), "a", offr);
6129 /*-----------------------------------------------------------------*/
6130 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6131 /*-----------------------------------------------------------------*/
6133 shiftRLeftOrResult (operand * left, int offl,
6134 operand * result, int offr, int shCount)
6136 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6137 /* shift right accumulator */
6139 /* or with result */
6140 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6141 /* back to result */
6142 aopPut (AOP (result), "a", offr);
6145 /*-----------------------------------------------------------------*/
6146 /* genlshOne - left shift a one byte quantity by known count */
6147 /*-----------------------------------------------------------------*/
6149 genlshOne (operand * result, operand * left, int shCount)
6151 D(emitcode (";", "genlshOne"));
6153 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6156 /*-----------------------------------------------------------------*/
6157 /* genlshTwo - left shift two bytes by known amount != 0 */
6158 /*-----------------------------------------------------------------*/
6160 genlshTwo (operand * result, operand * left, int shCount)
6164 D(emitcode (";", "genlshTwo"));
6166 size = getDataSize (result);
6168 /* if shCount >= 8 */
6176 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6178 movLeft2Result (left, LSB, result, MSB16, 0);
6180 aopPut (AOP (result), zero, LSB);
6183 /* 1 <= shCount <= 7 */
6187 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6189 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6193 /*-----------------------------------------------------------------*/
6194 /* shiftLLong - shift left one long from left to result */
6195 /* offl = LSB or MSB16 */
6196 /*-----------------------------------------------------------------*/
6198 shiftLLong (operand * left, operand * result, int offr)
6201 int size = AOP_SIZE (result);
6203 if (size >= LSB + offr)
6205 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6207 emitcode ("add", "a,acc");
6208 if (sameRegs (AOP (left), AOP (result)) &&
6209 size >= MSB16 + offr && offr != LSB)
6210 emitcode ("xch", "a,%s",
6211 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6213 aopPut (AOP (result), "a", LSB + offr);
6216 if (size >= MSB16 + offr)
6218 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6220 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6223 emitcode ("rlc", "a");
6224 if (sameRegs (AOP (left), AOP (result)) &&
6225 size >= MSB24 + offr && offr != LSB)
6226 emitcode ("xch", "a,%s",
6227 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6229 aopPut (AOP (result), "a", MSB16 + offr);
6232 if (size >= MSB24 + offr)
6234 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6236 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6239 emitcode ("rlc", "a");
6240 if (sameRegs (AOP (left), AOP (result)) &&
6241 size >= MSB32 + offr && offr != LSB)
6242 emitcode ("xch", "a,%s",
6243 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6245 aopPut (AOP (result), "a", MSB24 + offr);
6248 if (size > MSB32 + offr)
6250 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6252 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6255 emitcode ("rlc", "a");
6256 aopPut (AOP (result), "a", MSB32 + offr);
6259 aopPut (AOP (result), zero, LSB);
6262 /*-----------------------------------------------------------------*/
6263 /* genlshFour - shift four byte by a known amount != 0 */
6264 /*-----------------------------------------------------------------*/
6266 genlshFour (operand * result, operand * left, int shCount)
6270 D(emitcode (";", "genlshFour"));
6272 size = AOP_SIZE (result);
6274 /* if shifting more that 3 bytes */
6279 /* lowest order of left goes to the highest
6280 order of the destination */
6281 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6283 movLeft2Result (left, LSB, result, MSB32, 0);
6284 aopPut (AOP (result), zero, LSB);
6285 aopPut (AOP (result), zero, MSB16);
6286 aopPut (AOP (result), zero, MSB24);
6290 /* more than two bytes */
6291 else if (shCount >= 16)
6293 /* lower order two bytes goes to higher order two bytes */
6295 /* if some more remaining */
6297 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6300 movLeft2Result (left, MSB16, result, MSB32, 0);
6301 movLeft2Result (left, LSB, result, MSB24, 0);
6303 aopPut (AOP (result), zero, MSB16);
6304 aopPut (AOP (result), zero, LSB);
6308 /* if more than 1 byte */
6309 else if (shCount >= 8)
6311 /* lower order three bytes goes to higher order three bytes */
6316 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6318 movLeft2Result (left, LSB, result, MSB16, 0);
6324 movLeft2Result (left, MSB24, result, MSB32, 0);
6325 movLeft2Result (left, MSB16, result, MSB24, 0);
6326 movLeft2Result (left, LSB, result, MSB16, 0);
6327 aopPut (AOP (result), zero, LSB);
6329 else if (shCount == 1)
6330 shiftLLong (left, result, MSB16);
6333 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6334 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6335 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6336 aopPut (AOP (result), zero, LSB);
6341 /* 1 <= shCount <= 7 */
6342 else if (shCount <= 2)
6344 shiftLLong (left, result, LSB);
6346 shiftLLong (result, result, LSB);
6348 /* 3 <= shCount <= 7, optimize */
6351 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6352 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6353 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6357 /*-----------------------------------------------------------------*/
6358 /* genLeftShiftLiteral - left shifting by known count */
6359 /*-----------------------------------------------------------------*/
6361 genLeftShiftLiteral (operand * left,
6366 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6369 D(emitcode (";", "genLeftShiftLiteral"));
6371 freeAsmop (right, NULL, ic, TRUE);
6373 aopOp (left, ic, FALSE);
6374 aopOp (result, ic, FALSE);
6376 size = getSize (operandType (result));
6379 emitcode ("; shift left ", "result %d, left %d", size,
6383 /* I suppose that the left size >= result size */
6388 movLeft2Result (left, size, result, size, 0);
6392 else if (shCount >= (size * 8))
6394 aopPut (AOP (result), zero, size);
6400 genlshOne (result, left, shCount);
6404 genlshTwo (result, left, shCount);
6408 genlshFour (result, left, shCount);
6411 fprintf(stderr, "*** ack! mystery literal shift!\n");
6415 freeAsmop (left, NULL, ic, TRUE);
6416 freeAsmop (result, NULL, ic, TRUE);
6419 /*-----------------------------------------------------------------*/
6420 /* genLeftShift - generates code for left shifting */
6421 /*-----------------------------------------------------------------*/
6423 genLeftShift (iCode * ic)
6425 operand *left, *right, *result;
6428 symbol *tlbl, *tlbl1;
6430 D(emitcode (";", "genLeftShift"));
6432 right = IC_RIGHT (ic);
6433 left = IC_LEFT (ic);
6434 result = IC_RESULT (ic);
6436 aopOp (right, ic, FALSE);
6438 /* if the shift count is known then do it
6439 as efficiently as possible */
6440 if (AOP_TYPE (right) == AOP_LIT)
6442 genLeftShiftLiteral (left, right, result, ic);
6446 /* shift count is unknown then we have to form
6447 a loop get the loop count in B : Note: we take
6448 only the lower order byte since shifting
6449 more that 32 bits make no sense anyway, ( the
6450 largest size of an object can be only 32 bits ) */
6452 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6453 emitcode ("inc", "b");
6454 freeAsmop (right, NULL, ic, TRUE);
6455 aopOp (left, ic, FALSE);
6456 aopOp (result, ic, FALSE);
6458 /* now move the left to the result if they are not the
6460 if (!sameRegs (AOP (left), AOP (result)) &&
6461 AOP_SIZE (result) > 1)
6464 size = AOP_SIZE (result);
6468 l = aopGet (AOP (left), offset, FALSE, TRUE);
6469 if (*l == '@' && (IS_AOP_PREG (result)))
6472 emitcode ("mov", "a,%s", l);
6473 aopPut (AOP (result), "a", offset);
6476 aopPut (AOP (result), l, offset);
6481 tlbl = newiTempLabel (NULL);
6482 size = AOP_SIZE (result);
6484 tlbl1 = newiTempLabel (NULL);
6486 /* if it is only one byte then */
6489 symbol *tlbl1 = newiTempLabel (NULL);
6491 l = aopGet (AOP (left), 0, FALSE, FALSE);
6493 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6494 emitcode ("", "%05d$:", tlbl->key + 100);
6495 emitcode ("add", "a,acc");
6496 emitcode ("", "%05d$:", tlbl1->key + 100);
6497 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6498 aopPut (AOP (result), "a", 0);
6502 reAdjustPreg (AOP (result));
6504 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6505 emitcode ("", "%05d$:", tlbl->key + 100);
6506 l = aopGet (AOP (result), offset, FALSE, FALSE);
6508 emitcode ("add", "a,acc");
6509 aopPut (AOP (result), "a", offset++);
6512 l = aopGet (AOP (result), offset, FALSE, FALSE);
6514 emitcode ("rlc", "a");
6515 aopPut (AOP (result), "a", offset++);
6517 reAdjustPreg (AOP (result));
6519 emitcode ("", "%05d$:", tlbl1->key + 100);
6520 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6522 freeAsmop (left, NULL, ic, TRUE);
6523 freeAsmop (result, NULL, ic, TRUE);
6526 /*-----------------------------------------------------------------*/
6527 /* genrshOne - right shift a one byte quantity by known count */
6528 /*-----------------------------------------------------------------*/
6530 genrshOne (operand * result, operand * left,
6531 int shCount, int sign)
6533 D(emitcode (";", "genrshOne"));
6535 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6538 /*-----------------------------------------------------------------*/
6539 /* genrshTwo - right shift two bytes by known amount != 0 */
6540 /*-----------------------------------------------------------------*/
6542 genrshTwo (operand * result, operand * left,
6543 int shCount, int sign)
6545 D(emitcode (";", "genrshTwo"));
6547 /* if shCount >= 8 */
6552 shiftR1Left2Result (left, MSB16, result, LSB,
6555 movLeft2Result (left, MSB16, result, LSB, sign);
6556 addSign (result, MSB16, sign);
6559 /* 1 <= shCount <= 7 */
6561 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6564 /*-----------------------------------------------------------------*/
6565 /* shiftRLong - shift right one long from left to result */
6566 /* offl = LSB or MSB16 */
6567 /*-----------------------------------------------------------------*/
6569 shiftRLong (operand * left, int offl,
6570 operand * result, int sign)
6572 int isSameRegs=sameRegs(AOP(left),AOP(result));
6574 if (isSameRegs && offl>1) {
6575 // we are in big trouble, but this shouldn't happen
6576 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6579 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6584 emitcode ("rlc", "a");
6585 emitcode ("subb", "a,acc");
6586 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6588 aopPut (AOP(result), zero, MSB32);
6593 emitcode ("clr", "c");
6595 emitcode ("mov", "c,acc.7");
6598 emitcode ("rrc", "a");
6600 if (isSameRegs && offl==MSB16) {
6601 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6603 aopPut (AOP (result), "a", MSB32);
6604 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6607 emitcode ("rrc", "a");
6608 if (isSameRegs && offl==1) {
6609 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6611 aopPut (AOP (result), "a", MSB24);
6612 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6614 emitcode ("rrc", "a");
6615 aopPut (AOP (result), "a", MSB16 - offl);
6619 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6620 emitcode ("rrc", "a");
6621 aopPut (AOP (result), "a", LSB);
6625 /*-----------------------------------------------------------------*/
6626 /* genrshFour - shift four byte by a known amount != 0 */
6627 /*-----------------------------------------------------------------*/
6629 genrshFour (operand * result, operand * left,
6630 int shCount, int sign)
6632 D(emitcode (";", "genrshFour"));
6634 /* if shifting more that 3 bytes */
6639 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6641 movLeft2Result (left, MSB32, result, LSB, sign);
6642 addSign (result, MSB16, sign);
6644 else if (shCount >= 16)
6648 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6651 movLeft2Result (left, MSB24, result, LSB, 0);
6652 movLeft2Result (left, MSB32, result, MSB16, sign);
6654 addSign (result, MSB24, sign);
6656 else if (shCount >= 8)
6660 shiftRLong (left, MSB16, result, sign);
6661 else if (shCount == 0)
6663 movLeft2Result (left, MSB16, result, LSB, 0);
6664 movLeft2Result (left, MSB24, result, MSB16, 0);
6665 movLeft2Result (left, MSB32, result, MSB24, sign);
6666 addSign (result, MSB32, sign);
6670 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6671 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6672 /* the last shift is signed */
6673 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6674 addSign (result, MSB32, sign);
6678 { /* 1 <= shCount <= 7 */
6681 shiftRLong (left, LSB, result, sign);
6683 shiftRLong (result, LSB, result, sign);
6687 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6688 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6689 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6694 /*-----------------------------------------------------------------*/
6695 /* genRightShiftLiteral - right shifting by known count */
6696 /*-----------------------------------------------------------------*/
6698 genRightShiftLiteral (operand * left,
6704 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6707 D(emitcode (";", "genRightShiftLiteral"));
6709 freeAsmop (right, NULL, ic, TRUE);
6711 aopOp (left, ic, FALSE);
6712 aopOp (result, ic, FALSE);
6715 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6719 size = getDataSize (left);
6720 /* test the LEFT size !!! */
6722 /* I suppose that the left size >= result size */
6725 size = getDataSize (result);
6727 movLeft2Result (left, size, result, size, 0);
6730 else if (shCount >= (size * 8))
6733 /* get sign in acc.7 */
6734 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6735 addSign (result, LSB, sign);
6742 genrshOne (result, left, shCount, sign);
6746 genrshTwo (result, left, shCount, sign);
6750 genrshFour (result, left, shCount, sign);
6756 freeAsmop (left, NULL, ic, TRUE);
6757 freeAsmop (result, NULL, ic, TRUE);
6761 /*-----------------------------------------------------------------*/
6762 /* genSignedRightShift - right shift of signed number */
6763 /*-----------------------------------------------------------------*/
6765 genSignedRightShift (iCode * ic)
6767 operand *right, *left, *result;
6770 symbol *tlbl, *tlbl1;
6772 D(emitcode (";", "genSignedRightShift"));
6774 /* we do it the hard way put the shift count in b
6775 and loop thru preserving the sign */
6777 right = IC_RIGHT (ic);
6778 left = IC_LEFT (ic);
6779 result = IC_RESULT (ic);
6781 aopOp (right, ic, FALSE);
6784 if (AOP_TYPE (right) == AOP_LIT)
6786 genRightShiftLiteral (left, right, result, ic, 1);
6789 /* shift count is unknown then we have to form
6790 a loop get the loop count in B : Note: we take
6791 only the lower order byte since shifting
6792 more that 32 bits make no sense anyway, ( the
6793 largest size of an object can be only 32 bits ) */
6795 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6796 emitcode ("inc", "b");
6797 freeAsmop (right, NULL, ic, TRUE);
6798 aopOp (left, ic, FALSE);
6799 aopOp (result, ic, FALSE);
6801 /* now move the left to the result if they are not the
6803 if (!sameRegs (AOP (left), AOP (result)) &&
6804 AOP_SIZE (result) > 1)
6807 size = AOP_SIZE (result);
6811 l = aopGet (AOP (left), offset, FALSE, TRUE);
6812 if (*l == '@' && IS_AOP_PREG (result))
6815 emitcode ("mov", "a,%s", l);
6816 aopPut (AOP (result), "a", offset);
6819 aopPut (AOP (result), l, offset);
6824 /* mov the highest order bit to OVR */
6825 tlbl = newiTempLabel (NULL);
6826 tlbl1 = newiTempLabel (NULL);
6828 size = AOP_SIZE (result);
6830 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6831 emitcode ("rlc", "a");
6832 emitcode ("mov", "ov,c");
6833 /* if it is only one byte then */
6836 l = aopGet (AOP (left), 0, FALSE, FALSE);
6838 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6839 emitcode ("", "%05d$:", tlbl->key + 100);
6840 emitcode ("mov", "c,ov");
6841 emitcode ("rrc", "a");
6842 emitcode ("", "%05d$:", tlbl1->key + 100);
6843 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6844 aopPut (AOP (result), "a", 0);
6848 reAdjustPreg (AOP (result));
6849 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6850 emitcode ("", "%05d$:", tlbl->key + 100);
6851 emitcode ("mov", "c,ov");
6854 l = aopGet (AOP (result), offset, FALSE, FALSE);
6856 emitcode ("rrc", "a");
6857 aopPut (AOP (result), "a", offset--);
6859 reAdjustPreg (AOP (result));
6860 emitcode ("", "%05d$:", tlbl1->key + 100);
6861 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6864 freeAsmop (left, NULL, ic, TRUE);
6865 freeAsmop (result, NULL, ic, TRUE);
6868 /*-----------------------------------------------------------------*/
6869 /* genRightShift - generate code for right shifting */
6870 /*-----------------------------------------------------------------*/
6872 genRightShift (iCode * ic)
6874 operand *right, *left, *result;
6878 symbol *tlbl, *tlbl1;
6880 D(emitcode (";", "genRightShift"));
6882 /* if signed then we do it the hard way preserve the
6883 sign bit moving it inwards */
6884 retype = getSpec (operandType (IC_RESULT (ic)));
6886 if (!SPEC_USIGN (retype))
6888 genSignedRightShift (ic);
6892 /* signed & unsigned types are treated the same : i.e. the
6893 signed is NOT propagated inwards : quoting from the
6894 ANSI - standard : "for E1 >> E2, is equivalent to division
6895 by 2**E2 if unsigned or if it has a non-negative value,
6896 otherwise the result is implementation defined ", MY definition
6897 is that the sign does not get propagated */
6899 right = IC_RIGHT (ic);
6900 left = IC_LEFT (ic);
6901 result = IC_RESULT (ic);
6903 aopOp (right, ic, FALSE);
6905 /* if the shift count is known then do it
6906 as efficiently as possible */
6907 if (AOP_TYPE (right) == AOP_LIT)
6909 genRightShiftLiteral (left, right, result, ic, 0);
6913 /* shift count is unknown then we have to form
6914 a loop get the loop count in B : Note: we take
6915 only the lower order byte since shifting
6916 more that 32 bits make no sense anyway, ( the
6917 largest size of an object can be only 32 bits ) */
6919 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6920 emitcode ("inc", "b");
6921 freeAsmop (right, NULL, ic, TRUE);
6922 aopOp (left, ic, FALSE);
6923 aopOp (result, ic, FALSE);
6925 /* now move the left to the result if they are not the
6927 if (!sameRegs (AOP (left), AOP (result)) &&
6928 AOP_SIZE (result) > 1)
6931 size = AOP_SIZE (result);
6935 l = aopGet (AOP (left), offset, FALSE, TRUE);
6936 if (*l == '@' && IS_AOP_PREG (result))
6939 emitcode ("mov", "a,%s", l);
6940 aopPut (AOP (result), "a", offset);
6943 aopPut (AOP (result), l, offset);
6948 tlbl = newiTempLabel (NULL);
6949 tlbl1 = newiTempLabel (NULL);
6950 size = AOP_SIZE (result);
6953 /* if it is only one byte then */
6956 l = aopGet (AOP (left), 0, FALSE, FALSE);
6958 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6959 emitcode ("", "%05d$:", tlbl->key + 100);
6961 emitcode ("rrc", "a");
6962 emitcode ("", "%05d$:", tlbl1->key + 100);
6963 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6964 aopPut (AOP (result), "a", 0);
6968 reAdjustPreg (AOP (result));
6969 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6970 emitcode ("", "%05d$:", tlbl->key + 100);
6974 l = aopGet (AOP (result), offset, FALSE, FALSE);
6976 emitcode ("rrc", "a");
6977 aopPut (AOP (result), "a", offset--);
6979 reAdjustPreg (AOP (result));
6981 emitcode ("", "%05d$:", tlbl1->key + 100);
6982 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6985 freeAsmop (left, NULL, ic, TRUE);
6986 freeAsmop (result, NULL, ic, TRUE);
6989 /*-----------------------------------------------------------------*/
6990 /* genUnpackBits - generates code for unpacking bits */
6991 /*-----------------------------------------------------------------*/
6993 genUnpackBits (operand * result, char *rname, int ptype)
7001 D(emitcode (";", "genUnpackBits"));
7003 etype = getSpec (operandType (result));
7004 rsize = getSize (operandType (result));
7005 /* read the first byte */
7011 emitcode ("mov", "a,@%s", rname);
7015 emitcode ("movx", "a,@%s", rname);
7019 emitcode ("movx", "a,@dptr");
7023 emitcode ("clr", "a");
7024 emitcode ("movc", "a,@a+dptr");
7028 emitcode ("lcall", "__gptrget");
7032 rlen = SPEC_BLEN (etype);
7034 /* if we have bitdisplacement then it fits */
7035 /* into this byte completely or if length is */
7036 /* less than a byte */
7037 if ((shCnt = SPEC_BSTR (etype)) ||
7038 (SPEC_BLEN (etype) <= 8))
7041 /* shift right acc */
7044 emitcode ("anl", "a,#0x%02x",
7045 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7046 aopPut (AOP (result), "a", offset++);
7050 /* bit field did not fit in a byte */
7051 aopPut (AOP (result), "a", offset++);
7060 emitcode ("inc", "%s", rname);
7061 emitcode ("mov", "a,@%s", rname);
7065 emitcode ("inc", "%s", rname);
7066 emitcode ("movx", "a,@%s", rname);
7070 emitcode ("inc", "dptr");
7071 emitcode ("movx", "a,@dptr");
7075 emitcode ("clr", "a");
7076 emitcode ("inc", "dptr");
7077 emitcode ("movc", "a,@a+dptr");
7081 emitcode ("inc", "dptr");
7082 emitcode ("lcall", "__gptrget");
7087 /* if we are done */
7091 aopPut (AOP (result), "a", offset++);
7097 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7099 aopPut (AOP (result), "a", offset++);
7107 aopPut (AOP (result), zero, offset++);
7113 /*-----------------------------------------------------------------*/
7114 /* genDataPointerGet - generates code when ptr offset is known */
7115 /*-----------------------------------------------------------------*/
7117 genDataPointerGet (operand * left,
7123 int size, offset = 0;
7125 D(emitcode (";", "genDataPointerGet"));
7127 aopOp (result, ic, TRUE);
7129 /* get the string representation of the name */
7130 l = aopGet (AOP (left), 0, FALSE, TRUE);
7131 size = AOP_SIZE (result);
7135 sprintf (buffer, "(%s + %d)", l + 1, offset);
7137 sprintf (buffer, "%s", l + 1);
7138 aopPut (AOP (result), buffer, offset++);
7141 freeAsmop (left, NULL, ic, TRUE);
7142 freeAsmop (result, NULL, ic, TRUE);
7145 /*-----------------------------------------------------------------*/
7146 /* genNearPointerGet - emitcode for near pointer fetch */
7147 /*-----------------------------------------------------------------*/
7149 genNearPointerGet (operand * left,
7157 sym_link *rtype, *retype;
7158 sym_link *ltype = operandType (left);
7161 D(emitcode (";", "genNearPointerGet"));
7163 rtype = operandType (result);
7164 retype = getSpec (rtype);
7166 aopOp (left, ic, FALSE);
7168 /* if left is rematerialisable and
7169 result is not bit variable type and
7170 the left is pointer to data space i.e
7171 lower 128 bytes of space */
7172 if (AOP_TYPE (left) == AOP_IMMD &&
7173 !IS_BITVAR (retype) &&
7174 DCL_TYPE (ltype) == POINTER)
7176 genDataPointerGet (left, result, ic);
7180 /* if the value is already in a pointer register
7181 then don't need anything more */
7182 if (!AOP_INPREG (AOP (left)))
7184 /* otherwise get a free pointer register */
7186 preg = getFreePtr (ic, &aop, FALSE);
7187 emitcode ("mov", "%s,%s",
7189 aopGet (AOP (left), 0, FALSE, TRUE));
7193 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7195 //aopOp (result, ic, FALSE);
7196 aopOp (result, ic, result?TRUE:FALSE);
7198 /* if bitfield then unpack the bits */
7199 if (IS_BITVAR (retype))
7200 genUnpackBits (result, rname, POINTER);
7203 /* we have can just get the values */
7204 int size = AOP_SIZE (result);
7209 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7212 emitcode ("mov", "a,@%s", rname);
7213 aopPut (AOP (result), "a", offset);
7217 sprintf (buffer, "@%s", rname);
7218 aopPut (AOP (result), buffer, offset);
7222 emitcode ("inc", "%s", rname);
7226 /* now some housekeeping stuff */
7227 if (aop) /* we had to allocate for this iCode */
7229 if (pi) { /* post increment present */
7230 aopPut(AOP ( left ),rname,0);
7232 freeAsmop (NULL, aop, ic, TRUE);
7236 /* we did not allocate which means left
7237 already in a pointer register, then
7238 if size > 0 && this could be used again
7239 we have to point it back to where it
7241 if ((AOP_SIZE (result) > 1 &&
7242 !OP_SYMBOL (left)->remat &&
7243 (OP_SYMBOL (left)->liveTo > ic->seq ||
7247 int size = AOP_SIZE (result) - 1;
7249 emitcode ("dec", "%s", rname);
7254 freeAsmop (left, NULL, ic, TRUE);
7255 freeAsmop (result, NULL, ic, TRUE);
7256 if (pi) pi->generated = 1;
7259 /*-----------------------------------------------------------------*/
7260 /* genPagedPointerGet - emitcode for paged pointer fetch */
7261 /*-----------------------------------------------------------------*/
7263 genPagedPointerGet (operand * left,
7271 sym_link *rtype, *retype;
7273 D(emitcode (";", "genPagedPointerGet"));
7275 rtype = operandType (result);
7276 retype = getSpec (rtype);
7278 aopOp (left, ic, FALSE);
7280 /* if the value is already in a pointer register
7281 then don't need anything more */
7282 if (!AOP_INPREG (AOP (left)))
7284 /* otherwise get a free pointer register */
7286 preg = getFreePtr (ic, &aop, FALSE);
7287 emitcode ("mov", "%s,%s",
7289 aopGet (AOP (left), 0, FALSE, TRUE));
7293 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7295 aopOp (result, ic, FALSE);
7297 /* if bitfield then unpack the bits */
7298 if (IS_BITVAR (retype))
7299 genUnpackBits (result, rname, PPOINTER);
7302 /* we have can just get the values */
7303 int size = AOP_SIZE (result);
7309 emitcode ("movx", "a,@%s", rname);
7310 aopPut (AOP (result), "a", offset);
7315 emitcode ("inc", "%s", rname);
7319 /* now some housekeeping stuff */
7320 if (aop) /* we had to allocate for this iCode */
7322 if (pi) aopPut ( AOP (left), rname, 0);
7323 freeAsmop (NULL, aop, ic, TRUE);
7327 /* we did not allocate which means left
7328 already in a pointer register, then
7329 if size > 0 && this could be used again
7330 we have to point it back to where it
7332 if ((AOP_SIZE (result) > 1 &&
7333 !OP_SYMBOL (left)->remat &&
7334 (OP_SYMBOL (left)->liveTo > ic->seq ||
7338 int size = AOP_SIZE (result) - 1;
7340 emitcode ("dec", "%s", rname);
7345 freeAsmop (left, NULL, ic, TRUE);
7346 freeAsmop (result, NULL, ic, TRUE);
7347 if (pi) pi->generated = 1;
7351 /*-----------------------------------------------------------------*/
7352 /* genFarPointerGet - gget value from far space */
7353 /*-----------------------------------------------------------------*/
7355 genFarPointerGet (operand * left,
7356 operand * result, iCode * ic, iCode * pi)
7359 sym_link *retype = getSpec (operandType (result));
7361 D(emitcode (";", "genFarPointerGet"));
7363 aopOp (left, ic, FALSE);
7365 /* if the operand is already in dptr
7366 then we do nothing else we move the value to dptr */
7367 if (AOP_TYPE (left) != AOP_STR)
7369 /* if this is remateriazable */
7370 if (AOP_TYPE (left) == AOP_IMMD)
7371 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7373 { /* we need to get it byte by byte */
7374 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7375 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7378 /* so dptr know contains the address */
7379 aopOp (result, ic, FALSE);
7381 /* if bit then unpack */
7382 if (IS_BITVAR (retype))
7383 genUnpackBits (result, "dptr", FPOINTER);
7386 size = AOP_SIZE (result);
7391 emitcode ("movx", "a,@dptr");
7392 aopPut (AOP (result), "a", offset++);
7394 emitcode ("inc", "dptr");
7398 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7399 aopPut ( AOP (left), "dpl", 0);
7400 aopPut ( AOP (left), "dph", 1);
7403 freeAsmop (left, NULL, ic, TRUE);
7404 freeAsmop (result, NULL, ic, TRUE);
7407 /*-----------------------------------------------------------------*/
7408 /* genCodePointerGet - gget value from code space */
7409 /*-----------------------------------------------------------------*/
7411 genCodePointerGet (operand * left,
7412 operand * result, iCode * ic, iCode *pi)
7415 sym_link *retype = getSpec (operandType (result));
7417 D(emitcode (";", "genCodePointerGet"));
7419 aopOp (left, ic, FALSE);
7421 /* if the operand is already in dptr
7422 then we do nothing else we move the value to dptr */
7423 if (AOP_TYPE (left) != AOP_STR)
7425 /* if this is remateriazable */
7426 if (AOP_TYPE (left) == AOP_IMMD)
7427 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7429 { /* we need to get it byte by byte */
7430 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7431 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7434 /* so dptr know contains the address */
7435 aopOp (result, ic, FALSE);
7437 /* if bit then unpack */
7438 if (IS_BITVAR (retype))
7439 genUnpackBits (result, "dptr", CPOINTER);
7442 size = AOP_SIZE (result);
7447 emitcode ("clr", "a");
7448 emitcode ("movc", "a,@a+dptr");
7449 aopPut (AOP (result), "a", offset++);
7451 emitcode ("inc", "dptr");
7455 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7456 aopPut ( AOP (left), "dpl", 0);
7457 aopPut ( AOP (left), "dph", 1);
7460 freeAsmop (left, NULL, ic, TRUE);
7461 freeAsmop (result, NULL, ic, TRUE);
7464 /*-----------------------------------------------------------------*/
7465 /* genGenPointerGet - gget value from generic pointer space */
7466 /*-----------------------------------------------------------------*/
7468 genGenPointerGet (operand * left,
7469 operand * result, iCode * ic, iCode *pi)
7472 sym_link *retype = getSpec (operandType (result));
7474 D(emitcode (";", "genGenPointerGet"));
7476 aopOp (left, ic, FALSE);
7478 /* if the operand is already in dptr
7479 then we do nothing else we move the value to dptr */
7480 if (AOP_TYPE (left) != AOP_STR)
7482 /* if this is remateriazable */
7483 if (AOP_TYPE (left) == AOP_IMMD)
7485 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7486 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7487 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7489 emitcode ("mov", "b,#%d", pointerCode (retype));
7492 { /* we need to get it byte by byte */
7493 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7494 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7495 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7498 /* so dptr know contains the address */
7499 aopOp (result, ic, FALSE);
7501 /* if bit then unpack */
7502 if (IS_BITVAR (retype))
7503 genUnpackBits (result, "dptr", GPOINTER);
7506 size = AOP_SIZE (result);
7511 emitcode ("lcall", "__gptrget");
7512 aopPut (AOP (result), "a", offset++);
7514 emitcode ("inc", "dptr");
7518 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7519 aopPut ( AOP (left), "dpl", 0);
7520 aopPut ( AOP (left), "dph", 1);
7521 aopPut ( AOP (left), "b", 2);
7524 freeAsmop (left, NULL, ic, TRUE);
7525 freeAsmop (result, NULL, ic, TRUE);
7528 /*-----------------------------------------------------------------*/
7529 /* genPointerGet - generate code for pointer get */
7530 /*-----------------------------------------------------------------*/
7532 genPointerGet (iCode * ic, iCode *pi)
7534 operand *left, *result;
7535 sym_link *type, *etype;
7538 D(emitcode (";", "genPointerGet"));
7540 left = IC_LEFT (ic);
7541 result = IC_RESULT (ic);
7543 /* depending on the type of pointer we need to
7544 move it to the correct pointer register */
7545 type = operandType (left);
7546 etype = getSpec (type);
7547 /* if left is of type of pointer then it is simple */
7548 if (IS_PTR (type) && !IS_FUNC (type->next))
7549 p_type = DCL_TYPE (type);
7552 /* we have to go by the storage class */
7553 p_type = PTR_TYPE (SPEC_OCLS (etype));
7556 /* special case when cast remat */
7557 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7558 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7559 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7560 type = type = operandType (left);
7561 p_type = DCL_TYPE (type);
7563 /* now that we have the pointer type we assign
7564 the pointer values */
7570 genNearPointerGet (left, result, ic, pi);
7574 genPagedPointerGet (left, result, ic, pi);
7578 genFarPointerGet (left, result, ic, pi);
7582 genCodePointerGet (left, result, ic, pi);
7586 genGenPointerGet (left, result, ic, pi);
7592 /*-----------------------------------------------------------------*/
7593 /* genPackBits - generates code for packed bit storage */
7594 /*-----------------------------------------------------------------*/
7596 genPackBits (sym_link * etype,
7598 char *rname, int p_type)
7606 D(emitcode (";", "genPackBits"));
7608 blen = SPEC_BLEN (etype);
7609 bstr = SPEC_BSTR (etype);
7611 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7614 /* if the bit lenth is less than or */
7615 /* it exactly fits a byte then */
7616 if (SPEC_BLEN (etype) <= 8)
7618 shCount = SPEC_BSTR (etype);
7620 /* shift left acc */
7623 if (SPEC_BLEN (etype) < 8)
7624 { /* if smaller than a byte */
7630 emitcode ("mov", "b,a");
7631 emitcode ("mov", "a,@%s", rname);
7635 emitcode ("mov", "b,a");
7636 emitcode ("movx", "a,@dptr");
7640 emitcode ("push", "b");
7641 emitcode ("push", "acc");
7642 emitcode ("lcall", "__gptrget");
7643 emitcode ("pop", "b");
7647 emitcode ("anl", "a,#0x%02x", (unsigned char)
7648 ((unsigned char) (0xFF << (blen + bstr)) |
7649 (unsigned char) (0xFF >> (8 - bstr))));
7650 emitcode ("orl", "a,b");
7651 if (p_type == GPOINTER)
7652 emitcode ("pop", "b");
7659 emitcode ("mov", "@%s,a", rname);
7663 emitcode ("movx", "@dptr,a");
7667 emitcode ("lcall", "__gptrput");
7672 if (SPEC_BLEN (etype) <= 8)
7675 emitcode ("inc", "%s", rname);
7676 rLen = SPEC_BLEN (etype);
7678 /* now generate for lengths greater than one byte */
7682 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7694 emitcode ("mov", "@%s,a", rname);
7697 emitcode ("mov", "@%s,%s", rname, l);
7702 emitcode ("movx", "@dptr,a");
7707 emitcode ("lcall", "__gptrput");
7710 emitcode ("inc", "%s", rname);
7715 /* last last was not complete */
7718 /* save the byte & read byte */
7722 emitcode ("mov", "b,a");
7723 emitcode ("mov", "a,@%s", rname);
7727 emitcode ("mov", "b,a");
7728 emitcode ("movx", "a,@dptr");
7732 emitcode ("push", "b");
7733 emitcode ("push", "acc");
7734 emitcode ("lcall", "__gptrget");
7735 emitcode ("pop", "b");
7739 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7740 emitcode ("orl", "a,b");
7743 if (p_type == GPOINTER)
7744 emitcode ("pop", "b");
7750 emitcode ("mov", "@%s,a", rname);
7754 emitcode ("movx", "@dptr,a");
7758 emitcode ("lcall", "__gptrput");
7762 /*-----------------------------------------------------------------*/
7763 /* genDataPointerSet - remat pointer to data space */
7764 /*-----------------------------------------------------------------*/
7766 genDataPointerSet (operand * right,
7770 int size, offset = 0;
7771 char *l, buffer[256];
7773 D(emitcode (";", "genDataPointerSet"));
7775 aopOp (right, ic, FALSE);
7777 l = aopGet (AOP (result), 0, FALSE, TRUE);
7778 size = AOP_SIZE (right);
7782 sprintf (buffer, "(%s + %d)", l + 1, offset);
7784 sprintf (buffer, "%s", l + 1);
7785 emitcode ("mov", "%s,%s", buffer,
7786 aopGet (AOP (right), offset++, FALSE, FALSE));
7789 freeAsmop (right, NULL, ic, TRUE);
7790 freeAsmop (result, NULL, ic, TRUE);
7793 /*-----------------------------------------------------------------*/
7794 /* genNearPointerSet - emitcode for near pointer put */
7795 /*-----------------------------------------------------------------*/
7797 genNearPointerSet (operand * right,
7805 sym_link *retype, *letype;
7806 sym_link *ptype = operandType (result);
7808 D(emitcode (";", "genNearPointerSet"));
7810 retype = getSpec (operandType (right));
7811 letype = getSpec (ptype);
7812 aopOp (result, ic, FALSE);
7814 /* if the result is rematerializable &
7815 in data space & not a bit variable */
7816 if (AOP_TYPE (result) == AOP_IMMD &&
7817 DCL_TYPE (ptype) == POINTER &&
7818 !IS_BITVAR (retype) &&
7819 !IS_BITVAR (letype))
7821 genDataPointerSet (right, result, ic);
7825 /* if the value is already in a pointer register
7826 then don't need anything more */
7827 if (!AOP_INPREG (AOP (result)))
7830 //AOP_TYPE (result) == AOP_STK
7834 // Aha, it is a pointer, just in disguise.
7835 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7838 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7839 __FILE__, __LINE__);
7844 rname++; // skip the '@'.
7849 /* otherwise get a free pointer register */
7851 preg = getFreePtr (ic, &aop, FALSE);
7852 emitcode ("mov", "%s,%s",
7854 aopGet (AOP (result), 0, FALSE, TRUE));
7860 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7863 aopOp (right, ic, FALSE);
7865 /* if bitfield then unpack the bits */
7866 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7867 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7870 /* we have can just get the values */
7871 int size = AOP_SIZE (right);
7876 l = aopGet (AOP (right), offset, FALSE, TRUE);
7880 emitcode ("mov", "@%s,a", rname);
7883 emitcode ("mov", "@%s,%s", rname, l);
7885 emitcode ("inc", "%s", rname);
7890 /* now some housekeeping stuff */
7891 if (aop) /* we had to allocate for this iCode */
7893 if (pi) aopPut (AOP (result),rname,0);
7894 freeAsmop (NULL, aop, ic, TRUE);
7898 /* we did not allocate which means left
7899 already in a pointer register, then
7900 if size > 0 && this could be used again
7901 we have to point it back to where it
7903 if ((AOP_SIZE (right) > 1 &&
7904 !OP_SYMBOL (result)->remat &&
7905 (OP_SYMBOL (result)->liveTo > ic->seq ||
7909 int size = AOP_SIZE (right) - 1;
7911 emitcode ("dec", "%s", rname);
7916 if (pi) pi->generated = 1;
7917 freeAsmop (result, NULL, ic, TRUE);
7918 freeAsmop (right, NULL, ic, TRUE);
7921 /*-----------------------------------------------------------------*/
7922 /* genPagedPointerSet - emitcode for Paged pointer put */
7923 /*-----------------------------------------------------------------*/
7925 genPagedPointerSet (operand * right,
7933 sym_link *retype, *letype;
7935 D(emitcode (";", "genPagedPointerSet"));
7937 retype = getSpec (operandType (right));
7938 letype = getSpec (operandType (result));
7940 aopOp (result, ic, FALSE);
7942 /* if the value is already in a pointer register
7943 then don't need anything more */
7944 if (!AOP_INPREG (AOP (result)))
7946 /* otherwise get a free pointer register */
7948 preg = getFreePtr (ic, &aop, FALSE);
7949 emitcode ("mov", "%s,%s",
7951 aopGet (AOP (result), 0, FALSE, TRUE));
7955 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7957 aopOp (right, ic, FALSE);
7959 /* if bitfield then unpack the bits */
7960 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7961 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7964 /* we have can just get the values */
7965 int size = AOP_SIZE (right);
7970 l = aopGet (AOP (right), offset, FALSE, TRUE);
7973 emitcode ("movx", "@%s,a", rname);
7976 emitcode ("inc", "%s", rname);
7982 /* now some housekeeping stuff */
7983 if (aop) /* we had to allocate for this iCode */
7985 if (pi) aopPut (AOP (result),rname,0);
7986 freeAsmop (NULL, aop, ic, TRUE);
7990 /* we did not allocate which means left
7991 already in a pointer register, then
7992 if size > 0 && this could be used again
7993 we have to point it back to where it
7995 if (AOP_SIZE (right) > 1 &&
7996 !OP_SYMBOL (result)->remat &&
7997 (OP_SYMBOL (result)->liveTo > ic->seq ||
8000 int size = AOP_SIZE (right) - 1;
8002 emitcode ("dec", "%s", rname);
8007 if (pi) pi->generated = 1;
8008 freeAsmop (result, NULL, ic, TRUE);
8009 freeAsmop (right, NULL, ic, TRUE);
8014 /*-----------------------------------------------------------------*/
8015 /* genFarPointerSet - set value from far space */
8016 /*-----------------------------------------------------------------*/
8018 genFarPointerSet (operand * right,
8019 operand * result, iCode * ic, iCode * pi)
8022 sym_link *retype = getSpec (operandType (right));
8023 sym_link *letype = getSpec (operandType (result));
8025 D(emitcode (";", "genFarPointerSet"));
8027 aopOp (result, ic, FALSE);
8029 /* if the operand is already in dptr
8030 then we do nothing else we move the value to dptr */
8031 if (AOP_TYPE (result) != AOP_STR)
8033 /* if this is remateriazable */
8034 if (AOP_TYPE (result) == AOP_IMMD)
8035 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8037 { /* we need to get it byte by byte */
8038 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8039 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8042 /* so dptr know contains the address */
8043 aopOp (right, ic, FALSE);
8045 /* if bit then unpack */
8046 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8047 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8050 size = AOP_SIZE (right);
8055 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8057 emitcode ("movx", "@dptr,a");
8059 emitcode ("inc", "dptr");
8062 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8063 aopPut (AOP(result),"dpl",0);
8064 aopPut (AOP(result),"dph",1);
8067 freeAsmop (result, NULL, ic, TRUE);
8068 freeAsmop (right, NULL, ic, TRUE);
8071 /*-----------------------------------------------------------------*/
8072 /* genGenPointerSet - set value from generic pointer space */
8073 /*-----------------------------------------------------------------*/
8075 genGenPointerSet (operand * right,
8076 operand * result, iCode * ic, iCode * pi)
8079 sym_link *retype = getSpec (operandType (right));
8080 sym_link *letype = getSpec (operandType (result));
8082 D(emitcode (";", "genGenPointerSet"));
8084 aopOp (result, ic, FALSE);
8086 /* if the operand is already in dptr
8087 then we do nothing else we move the value to dptr */
8088 if (AOP_TYPE (result) != AOP_STR)
8090 /* if this is remateriazable */
8091 if (AOP_TYPE (result) == AOP_IMMD)
8093 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8094 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8095 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8097 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8100 { /* we need to get it byte by byte */
8101 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8102 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8103 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8106 /* so dptr know contains the address */
8107 aopOp (right, ic, FALSE);
8109 /* if bit then unpack */
8110 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8111 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8114 size = AOP_SIZE (right);
8119 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8121 emitcode ("lcall", "__gptrput");
8123 emitcode ("inc", "dptr");
8127 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8128 aopPut (AOP(result),"dpl",0);
8129 aopPut (AOP(result),"dph",1);
8130 aopPut (AOP(result),"b",2);
8133 freeAsmop (result, NULL, ic, TRUE);
8134 freeAsmop (right, NULL, ic, TRUE);
8137 /*-----------------------------------------------------------------*/
8138 /* genPointerSet - stores the value into a pointer location */
8139 /*-----------------------------------------------------------------*/
8141 genPointerSet (iCode * ic, iCode *pi)
8143 operand *right, *result;
8144 sym_link *type, *etype;
8147 D(emitcode (";", "genPointerSet"));
8149 right = IC_RIGHT (ic);
8150 result = IC_RESULT (ic);
8152 /* depending on the type of pointer we need to
8153 move it to the correct pointer register */
8154 type = operandType (result);
8155 etype = getSpec (type);
8156 /* if left is of type of pointer then it is simple */
8157 if (IS_PTR (type) && !IS_FUNC (type->next))
8159 p_type = DCL_TYPE (type);
8163 /* we have to go by the storage class */
8164 p_type = PTR_TYPE (SPEC_OCLS (etype));
8167 /* special case when cast remat */
8168 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8169 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8170 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8171 type = type = operandType (result);
8172 p_type = DCL_TYPE (type);
8174 /* now that we have the pointer type we assign
8175 the pointer values */
8181 genNearPointerSet (right, result, ic, pi);
8185 genPagedPointerSet (right, result, ic, pi);
8189 genFarPointerSet (right, result, ic, pi);
8193 genGenPointerSet (right, result, ic, pi);
8199 /*-----------------------------------------------------------------*/
8200 /* genIfx - generate code for Ifx statement */
8201 /*-----------------------------------------------------------------*/
8203 genIfx (iCode * ic, iCode * popIc)
8205 operand *cond = IC_COND (ic);
8208 D(emitcode (";", "genIfx"));
8210 aopOp (cond, ic, FALSE);
8212 /* get the value into acc */
8213 if (AOP_TYPE (cond) != AOP_CRY)
8217 /* the result is now in the accumulator */
8218 freeAsmop (cond, NULL, ic, TRUE);
8220 /* if there was something to be popped then do it */
8224 /* if the condition is a bit variable */
8225 if (isbit && IS_ITEMP (cond) &&
8227 genIfxJump (ic, SPIL_LOC (cond)->rname);
8228 else if (isbit && !IS_ITEMP (cond))
8229 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8231 genIfxJump (ic, "a");
8236 /*-----------------------------------------------------------------*/
8237 /* genAddrOf - generates code for address of */
8238 /*-----------------------------------------------------------------*/
8240 genAddrOf (iCode * ic)
8242 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8245 D(emitcode (";", "genAddrOf"));
8247 aopOp (IC_RESULT (ic), ic, FALSE);
8249 /* if the operand is on the stack then we
8250 need to get the stack offset of this
8254 /* if it has an offset then we need to compute
8258 emitcode ("mov", "a,_bp");
8259 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8260 ((char) (sym->stack - _G.nRegsSaved)) :
8261 ((char) sym->stack)) & 0xff);
8262 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8266 /* we can just move _bp */
8267 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8269 /* fill the result with zero */
8270 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8275 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8281 /* object not on stack then we need the name */
8282 size = AOP_SIZE (IC_RESULT (ic));
8287 char s[SDCC_NAME_MAX];
8289 sprintf (s, "#(%s >> %d)",
8293 sprintf (s, "#%s", sym->rname);
8294 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8298 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8302 /*-----------------------------------------------------------------*/
8303 /* genFarFarAssign - assignment when both are in far space */
8304 /*-----------------------------------------------------------------*/
8306 genFarFarAssign (operand * result, operand * right, iCode * ic)
8308 int size = AOP_SIZE (right);
8312 D(emitcode (";", "genFarFarAssign"));
8314 /* first push the right side on to the stack */
8317 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8319 emitcode ("push", "acc");
8322 freeAsmop (right, NULL, ic, FALSE);
8323 /* now assign DPTR to result */
8324 aopOp (result, ic, FALSE);
8325 size = AOP_SIZE (result);
8328 emitcode ("pop", "acc");
8329 aopPut (AOP (result), "a", --offset);
8331 freeAsmop (result, NULL, ic, FALSE);
8335 /*-----------------------------------------------------------------*/
8336 /* genAssign - generate code for assignment */
8337 /*-----------------------------------------------------------------*/
8339 genAssign (iCode * ic)
8341 operand *result, *right;
8343 unsigned long lit = 0L;
8345 D(emitcode(";","genAssign"));
8347 result = IC_RESULT (ic);
8348 right = IC_RIGHT (ic);
8350 /* if they are the same */
8351 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8354 aopOp (right, ic, FALSE);
8356 /* special case both in far space */
8357 if (AOP_TYPE (right) == AOP_DPTR &&
8358 IS_TRUE_SYMOP (result) &&
8359 isOperandInFarSpace (result))
8362 genFarFarAssign (result, right, ic);
8366 aopOp (result, ic, TRUE);
8368 /* if they are the same registers */
8369 if (sameRegs (AOP (right), AOP (result)))
8372 /* if the result is a bit */
8373 if (AOP_TYPE (result) == AOP_CRY)
8376 /* if the right size is a literal then
8377 we know what the value is */
8378 if (AOP_TYPE (right) == AOP_LIT)
8380 if (((int) operandLitValue (right)))
8381 aopPut (AOP (result), one, 0);
8383 aopPut (AOP (result), zero, 0);
8387 /* the right is also a bit variable */
8388 if (AOP_TYPE (right) == AOP_CRY)
8390 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8391 aopPut (AOP (result), "c", 0);
8397 aopPut (AOP (result), "a", 0);
8401 /* bit variables done */
8403 size = AOP_SIZE (result);
8405 if (AOP_TYPE (right) == AOP_LIT)
8406 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8408 (AOP_TYPE (result) != AOP_REG) &&
8409 (AOP_TYPE (right) == AOP_LIT) &&
8410 !IS_FLOAT (operandType (right)) &&
8413 emitcode ("clr", "a");
8416 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8417 aopPut (AOP (result), "a", size);
8419 aopPut (AOP (result),
8420 aopGet (AOP (right), size, FALSE, FALSE),
8428 aopPut (AOP (result),
8429 aopGet (AOP (right), offset, FALSE, FALSE),
8436 freeAsmop (right, NULL, ic, TRUE);
8437 freeAsmop (result, NULL, ic, TRUE);
8440 /*-----------------------------------------------------------------*/
8441 /* genJumpTab - genrates code for jump table */
8442 /*-----------------------------------------------------------------*/
8444 genJumpTab (iCode * ic)
8449 D(emitcode (";", "genJumpTab"));
8451 aopOp (IC_JTCOND (ic), ic, FALSE);
8452 /* get the condition into accumulator */
8453 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8455 /* multiply by three */
8456 emitcode ("add", "a,acc");
8457 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8458 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8460 jtab = newiTempLabel (NULL);
8461 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8462 emitcode ("jmp", "@a+dptr");
8463 emitcode ("", "%05d$:", jtab->key + 100);
8464 /* now generate the jump labels */
8465 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8466 jtab = setNextItem (IC_JTLABELS (ic)))
8467 emitcode ("ljmp", "%05d$", jtab->key + 100);
8471 /*-----------------------------------------------------------------*/
8472 /* genCast - gen code for casting */
8473 /*-----------------------------------------------------------------*/
8475 genCast (iCode * ic)
8477 operand *result = IC_RESULT (ic);
8478 sym_link *ctype = operandType (IC_LEFT (ic));
8479 sym_link *rtype = operandType (IC_RIGHT (ic));
8480 operand *right = IC_RIGHT (ic);
8483 D(emitcode(";", "genCast"));
8485 /* if they are equivalent then do nothing */
8486 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8489 aopOp (right, ic, FALSE);
8490 aopOp (result, ic, FALSE);
8492 /* if the result is a bit */
8493 if (IS_BITVAR(OP_SYMBOL(result)->type))
8495 /* if the right size is a literal then
8496 we know what the value is */
8497 if (AOP_TYPE (right) == AOP_LIT)
8499 if (((int) operandLitValue (right)))
8500 aopPut (AOP (result), one, 0);
8502 aopPut (AOP (result), zero, 0);
8507 /* the right is also a bit variable */
8508 if (AOP_TYPE (right) == AOP_CRY)
8510 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8511 aopPut (AOP (result), "c", 0);
8517 aopPut (AOP (result), "a", 0);
8521 /* if they are the same size : or less */
8522 if (AOP_SIZE (result) <= AOP_SIZE (right))
8525 /* if they are in the same place */
8526 if (sameRegs (AOP (right), AOP (result)))
8529 /* if they in different places then copy */
8530 size = AOP_SIZE (result);
8534 aopPut (AOP (result),
8535 aopGet (AOP (right), offset, FALSE, FALSE),
8543 /* if the result is of type pointer */
8548 sym_link *type = operandType (right);
8549 sym_link *etype = getSpec (type);
8551 /* pointer to generic pointer */
8552 if (IS_GENPTR (ctype))
8557 p_type = DCL_TYPE (type);
8560 if (SPEC_SCLS(etype)==S_REGISTER) {
8561 // let's assume it is a generic pointer
8564 /* we have to go by the storage class */
8565 p_type = PTR_TYPE (SPEC_OCLS (etype));
8569 /* the first two bytes are known */
8570 size = GPTRSIZE - 1;
8574 aopPut (AOP (result),
8575 aopGet (AOP (right), offset, FALSE, FALSE),
8579 /* the last byte depending on type */
8595 case PPOINTER: // what the fck is this?
8600 /* this should never happen */
8601 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8602 "got unknown pointer type");
8605 aopPut (AOP (result), l, GPTRSIZE - 1);
8609 /* just copy the pointers */
8610 size = AOP_SIZE (result);
8614 aopPut (AOP (result),
8615 aopGet (AOP (right), offset, FALSE, FALSE),
8622 /* so we now know that the size of destination is greater
8623 than the size of the source */
8624 /* we move to result for the size of source */
8625 size = AOP_SIZE (right);
8629 aopPut (AOP (result),
8630 aopGet (AOP (right), offset, FALSE, FALSE),
8635 /* now depending on the sign of the source && destination */
8636 size = AOP_SIZE (result) - AOP_SIZE (right);
8637 /* if unsigned or not an integral type */
8638 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8641 aopPut (AOP (result), zero, offset++);
8645 /* we need to extend the sign :{ */
8646 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8649 emitcode ("rlc", "a");
8650 emitcode ("subb", "a,acc");
8652 aopPut (AOP (result), "a", offset++);
8655 /* we are done hurray !!!! */
8658 freeAsmop (right, NULL, ic, TRUE);
8659 freeAsmop (result, NULL, ic, TRUE);
8663 /*-----------------------------------------------------------------*/
8664 /* genDjnz - generate decrement & jump if not zero instrucion */
8665 /*-----------------------------------------------------------------*/
8667 genDjnz (iCode * ic, iCode * ifx)
8673 D(emitcode (";", "genDjnz"));
8675 /* if the if condition has a false label
8676 then we cannot save */
8680 /* if the minus is not of the form
8682 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8683 !IS_OP_LITERAL (IC_RIGHT (ic)))
8686 if (operandLitValue (IC_RIGHT (ic)) != 1)
8689 /* if the size of this greater than one then no
8691 if (getSize (operandType (IC_RESULT (ic))) > 1)
8694 /* otherwise we can save BIG */
8695 lbl = newiTempLabel (NULL);
8696 lbl1 = newiTempLabel (NULL);
8698 aopOp (IC_RESULT (ic), ic, FALSE);
8700 if (AOP_NEEDSACC(IC_RESULT(ic)))
8702 /* If the result is accessed indirectly via
8703 * the accumulator, we must explicitly write
8704 * it back after the decrement.
8706 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8708 if (strcmp(rByte, "a"))
8710 /* Something is hopelessly wrong */
8711 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8712 __FILE__, __LINE__);
8713 /* We can just give up; the generated code will be inefficient,
8716 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8719 emitcode ("dec", "%s", rByte);
8720 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8721 emitcode ("jnz", "%05d$", lbl->key + 100);
8723 else if (IS_AOP_PREG (IC_RESULT (ic)))
8725 emitcode ("dec", "%s",
8726 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8727 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8728 emitcode ("jnz", "%05d$", lbl->key + 100);
8732 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8735 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8736 emitcode ("", "%05d$:", lbl->key + 100);
8737 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8738 emitcode ("", "%05d$:", lbl1->key + 100);
8740 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8745 /*-----------------------------------------------------------------*/
8746 /* genReceive - generate code for a receive iCode */
8747 /*-----------------------------------------------------------------*/
8749 genReceive (iCode * ic)
8751 int size = getSize (operandType (IC_RESULT (ic)));
8753 D(emitcode (";", "genReceive"));
8755 if (ic->argreg == 1) { /* first parameter */
8756 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8757 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8758 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8760 offset = fReturnSizeMCS51 - size;
8762 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8763 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8766 aopOp (IC_RESULT (ic), ic, FALSE);
8767 size = AOP_SIZE (IC_RESULT (ic));
8770 emitcode ("pop", "acc");
8771 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8776 aopOp (IC_RESULT (ic), ic, FALSE);
8778 assignResultValue (IC_RESULT (ic));
8780 } else { /* second receive onwards */
8782 aopOp (IC_RESULT (ic), ic, FALSE);
8783 rb1off = ic->argreg;
8785 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8788 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8791 /*-----------------------------------------------------------------*/
8792 /* gen51Code - generate code for 8051 based controllers */
8793 /*-----------------------------------------------------------------*/
8795 gen51Code (iCode * lic)
8800 lineHead = lineCurr = NULL;
8802 /* print the allocation information */
8804 printAllocInfo (currFunc, codeOutFile);
8805 /* if debug information required */
8806 if (options.debug && currFunc)
8808 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8810 if (IS_STATIC (currFunc->etype))
8811 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8813 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8816 /* stack pointer name */
8817 if (options.useXstack)
8823 for (ic = lic; ic; ic = ic->next)
8826 if (ic->lineno && cln != ic->lineno)
8831 emitcode ("", "C$%s$%d$%d$%d ==.",
8832 FileBaseName (ic->filename), ic->lineno,
8833 ic->level, ic->block);
8836 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
8837 printCLine(ic->filename, ic->lineno));
8840 /* if the result is marked as
8841 spilt and rematerializable or code for
8842 this has already been generated then
8844 if (resultRemat (ic) || ic->generated)
8847 /* depending on the operation */
8867 /* IPOP happens only when trying to restore a
8868 spilt live range, if there is an ifx statement
8869 following this pop then the if statement might
8870 be using some of the registers being popped which
8871 would destory the contents of the register so
8872 we need to check for this condition and handle it */
8874 ic->next->op == IFX &&
8875 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8876 genIfx (ic->next, ic);
8894 genEndFunction (ic);
8914 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8931 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8935 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8942 /* note these two are xlated by algebraic equivalence
8943 during parsing SDCC.y */
8944 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8945 "got '>=' or '<=' shouldn't have come here");
8949 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8961 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8965 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8969 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8996 case GET_VALUE_AT_ADDRESS:
8997 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9001 if (POINTER_SET (ic))
9002 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9028 addSet (&_G.sendSet, ic);
9037 /* now we are ready to call the
9038 peep hole optimizer */
9039 if (!options.nopeep)
9040 peepHole (&lineHead);
9042 /* now do the actual printing */
9043 printLine (lineHead, codeOutFile);