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 /* set C, if a >= 1 */
1050 emitcode ("add", "a,#0xff");
1051 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1059 if (strcmp (aop->aopu.aop_str[offset], s))
1060 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1065 if (!offset && (strcmp (s, "acc") == 0))
1068 if (strcmp (aop->aopu.aop_str[offset], s))
1069 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1073 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1074 "aopPut got unsupported aop->type");
1082 /*-----------------------------------------------------------------*/
1083 /* pointToEnd :- points to the last byte of the operand */
1084 /*-----------------------------------------------------------------*/
1086 pointToEnd (asmop * aop)
1092 aop->coff = count = (aop->size - 1);
1098 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1102 emitcode ("inc", "dptr");
1109 /*-----------------------------------------------------------------*/
1110 /* reAdjustPreg - points a register back to where it should */
1111 /*-----------------------------------------------------------------*/
1113 reAdjustPreg (asmop * aop)
1115 if ((aop->coff==0) || aop->size <= 1)
1123 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1128 emitcode ("lcall", "__decdptr");
1135 #define AOP(op) op->aop
1136 #define AOP_TYPE(op) AOP(op)->type
1137 #define AOP_SIZE(op) AOP(op)->size
1138 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1139 AOP_TYPE(x) == AOP_R0))
1141 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1142 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1144 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1145 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1146 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1148 /*-----------------------------------------------------------------*/
1149 /* genNotFloat - generates not for float operations */
1150 /*-----------------------------------------------------------------*/
1152 genNotFloat (operand * op, operand * res)
1158 D(emitcode (";", "genNotFloat"));
1160 /* we will put 127 in the first byte of
1162 aopPut (AOP (res), "#127", 0);
1163 size = AOP_SIZE (op) - 1;
1166 l = aopGet (op->aop, offset++, FALSE, FALSE);
1171 emitcode ("orl", "a,%s",
1173 offset++, FALSE, FALSE));
1176 tlbl = newiTempLabel (NULL);
1177 aopPut (res->aop, one, 1);
1178 emitcode ("jz", "%05d$", (tlbl->key + 100));
1179 aopPut (res->aop, zero, 1);
1180 emitcode ("", "%05d$:", (tlbl->key + 100));
1182 size = res->aop->size - 2;
1184 /* put zeros in the rest */
1186 aopPut (res->aop, zero, offset++);
1189 /*-----------------------------------------------------------------*/
1190 /* opIsGptr: returns non-zero if the passed operand is */
1191 /* a generic pointer type. */
1192 /*-----------------------------------------------------------------*/
1194 opIsGptr (operand * op)
1196 sym_link *type = operandType (op);
1198 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1205 /*-----------------------------------------------------------------*/
1206 /* getDataSize - get the operand data size */
1207 /*-----------------------------------------------------------------*/
1209 getDataSize (operand * op)
1212 size = AOP_SIZE (op);
1213 if (size == GPTRSIZE)
1215 sym_link *type = operandType (op);
1216 if (IS_GENPTR (type))
1218 /* generic pointer; arithmetic operations
1219 * should ignore the high byte (pointer type).
1227 /*-----------------------------------------------------------------*/
1228 /* outAcc - output Acc */
1229 /*-----------------------------------------------------------------*/
1231 outAcc (operand * result)
1234 size = getDataSize (result);
1237 aopPut (AOP (result), "a", 0);
1240 /* unsigned or positive */
1243 aopPut (AOP (result), zero, offset++);
1248 /*-----------------------------------------------------------------*/
1249 /* outBitC - output a bit C */
1250 /*-----------------------------------------------------------------*/
1252 outBitC (operand * result)
1254 /* if the result is bit */
1255 if (AOP_TYPE (result) == AOP_CRY)
1256 aopPut (AOP (result), "c", 0);
1259 emitcode ("clr", "a");
1260 emitcode ("rlc", "a");
1265 /*-----------------------------------------------------------------*/
1266 /* toBoolean - emit code for orl a,operator(sizeop) */
1267 /*-----------------------------------------------------------------*/
1269 toBoolean (operand * oper)
1271 int size = AOP_SIZE (oper) - 1;
1273 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1275 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1279 /*-----------------------------------------------------------------*/
1280 /* genNot - generate code for ! operation */
1281 /*-----------------------------------------------------------------*/
1286 sym_link *optype = operandType (IC_LEFT (ic));
1288 D(emitcode (";", "genNot"));
1290 /* assign asmOps to operand & result */
1291 aopOp (IC_LEFT (ic), ic, FALSE);
1292 aopOp (IC_RESULT (ic), ic, TRUE);
1294 /* if in bit space then a special case */
1295 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1297 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1298 emitcode ("cpl", "c");
1299 outBitC (IC_RESULT (ic));
1303 /* if type float then do float */
1304 if (IS_FLOAT (optype))
1306 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1310 toBoolean (IC_LEFT (ic));
1312 tlbl = newiTempLabel (NULL);
1313 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1314 emitcode ("", "%05d$:", tlbl->key + 100);
1315 outBitC (IC_RESULT (ic));
1318 /* release the aops */
1319 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1320 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1324 /*-----------------------------------------------------------------*/
1325 /* genCpl - generate code for complement */
1326 /*-----------------------------------------------------------------*/
1334 D(emitcode (";", "genCpl"));
1336 /* assign asmOps to operand & result */
1337 aopOp (IC_LEFT (ic), ic, FALSE);
1338 aopOp (IC_RESULT (ic), ic, TRUE);
1340 /* special case if in bit space */
1341 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1342 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1343 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1344 emitcode ("cpl", "c");
1345 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1348 tlbl=newiTempLabel(NULL);
1349 emitcode ("cjne", "%s,#0x01,%05d$",
1350 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1351 emitcode ("", "%05d$:", tlbl->key+100);
1352 outBitC (IC_RESULT(ic));
1356 size = AOP_SIZE (IC_RESULT (ic));
1359 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1361 emitcode ("cpl", "a");
1362 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1367 /* release the aops */
1368 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1372 /*-----------------------------------------------------------------*/
1373 /* genUminusFloat - unary minus for floating points */
1374 /*-----------------------------------------------------------------*/
1376 genUminusFloat (operand * op, operand * result)
1378 int size, offset = 0;
1381 D(emitcode (";", "genUminusFloat"));
1383 /* for this we just need to flip the
1384 first it then copy the rest in place */
1385 size = AOP_SIZE (op) - 1;
1386 l = aopGet (AOP (op), 3, FALSE, FALSE);
1390 emitcode ("cpl", "acc.7");
1391 aopPut (AOP (result), "a", 3);
1395 aopPut (AOP (result),
1396 aopGet (AOP (op), offset, FALSE, FALSE),
1402 /*-----------------------------------------------------------------*/
1403 /* genUminus - unary minus code generation */
1404 /*-----------------------------------------------------------------*/
1406 genUminus (iCode * ic)
1409 sym_link *optype, *rtype;
1412 D(emitcode (";", "genUminus"));
1415 aopOp (IC_LEFT (ic), ic, FALSE);
1416 aopOp (IC_RESULT (ic), ic, TRUE);
1418 /* if both in bit space then special
1420 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1421 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1424 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1425 emitcode ("cpl", "c");
1426 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1430 optype = operandType (IC_LEFT (ic));
1431 rtype = operandType (IC_RESULT (ic));
1433 /* if float then do float stuff */
1434 if (IS_FLOAT (optype))
1436 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1440 /* otherwise subtract from zero */
1441 size = AOP_SIZE (IC_LEFT (ic));
1446 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1447 if (!strcmp (l, "a"))
1451 emitcode ("cpl", "a");
1452 emitcode ("addc", "a,#0");
1458 emitcode ("clr", "a");
1459 emitcode ("subb", "a,%s", l);
1461 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1464 /* if any remaining bytes in the result */
1465 /* we just need to propagate the sign */
1466 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1468 emitcode ("rlc", "a");
1469 emitcode ("subb", "a,acc");
1471 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1475 /* release the aops */
1476 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1477 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1480 /*-----------------------------------------------------------------*/
1481 /* saveRegisters - will look for a call and save the registers */
1482 /*-----------------------------------------------------------------*/
1484 saveRegisters (iCode * lic)
1491 for (ic = lic; ic; ic = ic->next)
1492 if (ic->op == CALL || ic->op == PCALL)
1497 fprintf (stderr, "found parameter push with no function call\n");
1501 /* if the registers have been saved already or don't need to be then
1503 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1504 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1507 /* safe the registers in use at this time but skip the
1508 ones for the result */
1509 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1510 mcs51_rUmaskForOp (IC_RESULT(ic)));
1513 if (options.useXstack)
1515 if (bitVectBitValue (rsave, R0_IDX))
1516 emitcode ("mov", "b,r0");
1517 emitcode ("mov", "r0,%s", spname);
1518 for (i = 0; i < mcs51_nRegs; i++)
1520 if (bitVectBitValue (rsave, i))
1523 emitcode ("mov", "a,b");
1525 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1526 emitcode ("movx", "@r0,a");
1527 emitcode ("inc", "r0");
1530 emitcode ("mov", "%s,r0", spname);
1531 if (bitVectBitValue (rsave, R0_IDX))
1532 emitcode ("mov", "r0,b");
1535 for (i = 0; i < mcs51_nRegs; i++)
1537 if (bitVectBitValue (rsave, i))
1538 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1542 /*-----------------------------------------------------------------*/
1543 /* unsaveRegisters - pop the pushed registers */
1544 /*-----------------------------------------------------------------*/
1546 unsaveRegisters (iCode * ic)
1551 /* restore the registers in use at this time but skip the
1552 ones for the result */
1553 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1554 mcs51_rUmaskForOp (IC_RESULT(ic)));
1556 if (options.useXstack)
1558 emitcode ("mov", "r0,%s", spname);
1559 for (i = mcs51_nRegs; i >= 0; i--)
1561 if (bitVectBitValue (rsave, i))
1563 emitcode ("dec", "r0");
1564 emitcode ("movx", "a,@r0");
1566 emitcode ("mov", "b,a");
1568 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1572 emitcode ("mov", "%s,r0", spname);
1573 if (bitVectBitValue (rsave, R0_IDX))
1574 emitcode ("mov", "r0,b");
1577 for (i = mcs51_nRegs; i >= 0; i--)
1579 if (bitVectBitValue (rsave, i))
1580 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1586 /*-----------------------------------------------------------------*/
1588 /*-----------------------------------------------------------------*/
1590 pushSide (operand * oper, int size)
1595 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1596 if (AOP_TYPE (oper) != AOP_REG &&
1597 AOP_TYPE (oper) != AOP_DIR &&
1600 emitcode ("mov", "a,%s", l);
1601 emitcode ("push", "acc");
1604 emitcode ("push", "%s", l);
1608 /*-----------------------------------------------------------------*/
1609 /* assignResultValue - */
1610 /*-----------------------------------------------------------------*/
1612 assignResultValue (operand * oper)
1615 int size = AOP_SIZE (oper);
1618 aopPut (AOP (oper), fReturn[offset], offset);
1624 /*-----------------------------------------------------------------*/
1625 /* genXpush - pushes onto the external stack */
1626 /*-----------------------------------------------------------------*/
1628 genXpush (iCode * ic)
1630 asmop *aop = newAsmop (0);
1632 int size, offset = 0;
1634 D(emitcode (";", "genXpush"));
1636 aopOp (IC_LEFT (ic), ic, FALSE);
1637 r = getFreePtr (ic, &aop, FALSE);
1640 emitcode ("mov", "%s,_spx", r->name);
1642 size = AOP_SIZE (IC_LEFT (ic));
1646 char *l = aopGet (AOP (IC_LEFT (ic)),
1647 offset++, FALSE, FALSE);
1649 emitcode ("movx", "@%s,a", r->name);
1650 emitcode ("inc", "%s", r->name);
1655 emitcode ("mov", "_spx,%s", r->name);
1657 freeAsmop (NULL, aop, ic, TRUE);
1658 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1661 /*-----------------------------------------------------------------*/
1662 /* genIpush - genrate code for pushing this gets a little complex */
1663 /*-----------------------------------------------------------------*/
1665 genIpush (iCode * ic)
1667 int size, offset = 0;
1670 D(emitcode (";", "genIpush"));
1672 /* if this is not a parm push : ie. it is spill push
1673 and spill push is always done on the local stack */
1677 /* and the item is spilt then do nothing */
1678 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1681 aopOp (IC_LEFT (ic), ic, FALSE);
1682 size = AOP_SIZE (IC_LEFT (ic));
1683 /* push it on the stack */
1686 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1692 emitcode ("push", "%s", l);
1697 /* this is a paramter push: in this case we call
1698 the routine to find the call and save those
1699 registers that need to be saved */
1702 /* if use external stack then call the external
1703 stack pushing routine */
1704 if (options.useXstack)
1710 /* then do the push */
1711 aopOp (IC_LEFT (ic), ic, FALSE);
1714 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1715 size = AOP_SIZE (IC_LEFT (ic));
1719 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1720 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1721 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1724 emitcode ("mov", "a,%s", l);
1725 emitcode ("push", "acc");
1728 emitcode ("push", "%s", l);
1731 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1734 /*-----------------------------------------------------------------*/
1735 /* genIpop - recover the registers: can happen only for spilling */
1736 /*-----------------------------------------------------------------*/
1738 genIpop (iCode * ic)
1742 D(emitcode (";", "genIpop"));
1744 /* if the temp was not pushed then */
1745 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1748 aopOp (IC_LEFT (ic), ic, FALSE);
1749 size = AOP_SIZE (IC_LEFT (ic));
1750 offset = (size - 1);
1752 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1755 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1758 /*-----------------------------------------------------------------*/
1759 /* unsaveRBank - restores the resgister bank from stack */
1760 /*-----------------------------------------------------------------*/
1762 unsaveRBank (int bank, iCode * ic, bool popPsw)
1768 if (options.useXstack)
1772 /* Assume r0 is available for use. */
1773 r = mcs51_regWithIdx (R0_IDX);;
1778 r = getFreePtr (ic, &aop, FALSE);
1780 emitcode ("mov", "%s,_spx", r->name);
1785 if (options.useXstack)
1787 emitcode ("movx", "a,@%s", r->name);
1788 emitcode ("mov", "psw,a");
1789 emitcode ("dec", "%s", r->name);
1793 emitcode ("pop", "psw");
1797 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1799 if (options.useXstack)
1801 emitcode ("movx", "a,@%s", r->name);
1802 emitcode ("mov", "(%s+%d),a",
1803 regs8051[i].base, 8 * bank + regs8051[i].offset);
1804 emitcode ("dec", "%s", r->name);
1808 emitcode ("pop", "(%s+%d)",
1809 regs8051[i].base, 8 * bank + regs8051[i].offset);
1812 if (options.useXstack)
1814 emitcode ("mov", "_spx,%s", r->name);
1819 freeAsmop (NULL, aop, ic, TRUE);
1823 /*-----------------------------------------------------------------*/
1824 /* saveRBank - saves an entire register bank on the stack */
1825 /*-----------------------------------------------------------------*/
1827 saveRBank (int bank, iCode * ic, bool pushPsw)
1833 if (options.useXstack)
1837 /* Assume r0 is available for use. */
1838 r = mcs51_regWithIdx (R0_IDX);;
1843 r = getFreePtr (ic, &aop, FALSE);
1845 emitcode ("mov", "%s,_spx", r->name);
1848 for (i = 0; i < mcs51_nRegs; i++)
1850 if (options.useXstack)
1852 emitcode ("inc", "%s", r->name);
1853 emitcode ("mov", "a,(%s+%d)",
1854 regs8051[i].base, 8 * bank + regs8051[i].offset);
1855 emitcode ("movx", "@%s,a", r->name);
1858 emitcode ("push", "(%s+%d)",
1859 regs8051[i].base, 8 * bank + regs8051[i].offset);
1864 if (options.useXstack)
1866 emitcode ("mov", "a,psw");
1867 emitcode ("movx", "@%s,a", r->name);
1868 emitcode ("inc", "%s", r->name);
1869 emitcode ("mov", "_spx,%s", r->name);
1874 emitcode ("push", "psw");
1877 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1882 freeAsmop (NULL, aop, ic, TRUE);
1891 /*-----------------------------------------------------------------*/
1892 /* genSend - gen code for SEND */
1893 /*-----------------------------------------------------------------*/
1894 static void genSend(set *sendSet)
1899 for (sic = setFirstItem (_G.sendSet); sic;
1900 sic = setNextItem (_G.sendSet)) {
1901 int size, offset = 0;
1902 aopOp (IC_LEFT (sic), sic, FALSE);
1903 size = AOP_SIZE (IC_LEFT (sic));
1905 if (sic->argreg == 1) {
1907 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1909 if (strcmp (l, fReturn[offset]))
1910 emitcode ("mov", "%s,%s", fReturn[offset], l);
1916 emitcode ("mov","b1_%d,%s",rb1_count++,
1917 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1920 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1924 /*-----------------------------------------------------------------*/
1925 /* genCall - generates a call statement */
1926 /*-----------------------------------------------------------------*/
1928 genCall (iCode * ic)
1931 // bool restoreBank = FALSE;
1932 bool swapBanks = FALSE;
1934 D(emitcode(";", "genCall"));
1936 dtype = operandType (IC_LEFT (ic));
1937 /* if send set is not empty the assign */
1940 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1941 genSend(reverseSet(_G.sendSet));
1943 genSend(_G.sendSet);
1949 /* if we are calling a not _naked function that is not using
1950 the same register bank then we need to save the
1951 destination registers on the stack */
1952 dtype = operandType (IC_LEFT (ic));
1953 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1954 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1955 !IFFUNC_ISISR (dtype))
1960 /* if caller saves & we have not saved then */
1966 emitcode ("mov", "psw,#0x%02x",
1967 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1971 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1972 OP_SYMBOL (IC_LEFT (ic))->rname :
1973 OP_SYMBOL (IC_LEFT (ic))->name));
1977 emitcode ("mov", "psw,#0x%02x",
1978 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1981 /* if we need assign a result value */
1982 if ((IS_ITEMP (IC_RESULT (ic)) &&
1983 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1984 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1985 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1986 IS_TRUE_SYMOP (IC_RESULT (ic)))
1990 aopOp (IC_RESULT (ic), ic, FALSE);
1993 assignResultValue (IC_RESULT (ic));
1995 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1998 /* adjust the stack for parameters if
2003 if (ic->parmBytes > 3)
2005 emitcode ("mov", "a,%s", spname);
2006 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2007 emitcode ("mov", "%s,a", spname);
2010 for (i = 0; i < ic->parmBytes; i++)
2011 emitcode ("dec", "%s", spname);
2014 /* if we hade saved some registers then unsave them */
2015 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2016 unsaveRegisters (ic);
2018 // /* if register bank was saved then pop them */
2020 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2023 /*-----------------------------------------------------------------*/
2024 /* -10l - generates a call by pointer statement */
2025 /*-----------------------------------------------------------------*/
2027 genPcall (iCode * ic)
2030 symbol *rlbl = newiTempLabel (NULL);
2031 // bool restoreBank=FALSE;
2032 bool swapBanks = FALSE;
2034 D(emitcode(";", "genPCall"));
2036 /* if caller saves & we have not saved then */
2040 /* if we are calling a not _naked function that is not using
2041 the same register bank then we need to save the
2042 destination registers on the stack */
2043 dtype = operandType (IC_LEFT (ic))->next;
2044 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2045 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2046 !IFFUNC_ISISR (dtype))
2048 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2049 // restoreBank=TRUE;
2051 // need caution message to user here
2054 /* push the return address on to the stack */
2055 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2056 emitcode ("push", "acc");
2057 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2058 emitcode ("push", "acc");
2060 /* now push the calling address */
2061 aopOp (IC_LEFT (ic), ic, FALSE);
2063 pushSide (IC_LEFT (ic), FPTRSIZE);
2065 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2067 /* if send set is not empty the assign */
2070 genSend(reverseSet(_G.sendSet));
2076 emitcode ("mov", "psw,#0x%02x",
2077 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2081 emitcode ("ret", "");
2082 emitcode ("", "%05d$:", (rlbl->key + 100));
2087 emitcode ("mov", "psw,#0x%02x",
2088 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2091 /* if we need assign a result value */
2092 if ((IS_ITEMP (IC_RESULT (ic)) &&
2093 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2094 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2095 IS_TRUE_SYMOP (IC_RESULT (ic)))
2099 aopOp (IC_RESULT (ic), ic, FALSE);
2102 assignResultValue (IC_RESULT (ic));
2104 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2107 /* adjust the stack for parameters if
2112 if (ic->parmBytes > 3)
2114 emitcode ("mov", "a,%s", spname);
2115 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2116 emitcode ("mov", "%s,a", spname);
2119 for (i = 0; i < ic->parmBytes; i++)
2120 emitcode ("dec", "%s", spname);
2124 // /* if register bank was saved then unsave them */
2126 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2128 /* if we hade saved some registers then
2130 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2131 unsaveRegisters (ic);
2134 /*-----------------------------------------------------------------*/
2135 /* resultRemat - result is rematerializable */
2136 /*-----------------------------------------------------------------*/
2138 resultRemat (iCode * ic)
2140 if (SKIP_IC (ic) || ic->op == IFX)
2143 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2145 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2146 if (sym->remat && !POINTER_SET (ic))
2153 #if defined(__BORLANDC__) || defined(_MSC_VER)
2154 #define STRCASECMP stricmp
2156 #define STRCASECMP strcasecmp
2159 /*-----------------------------------------------------------------*/
2160 /* inExcludeList - return 1 if the string is in exclude Reg list */
2161 /*-----------------------------------------------------------------*/
2163 inExcludeList (char *s)
2167 if (options.excludeRegs[i] &&
2168 STRCASECMP (options.excludeRegs[i], "none") == 0)
2171 for (i = 0; options.excludeRegs[i]; i++)
2173 if (options.excludeRegs[i] &&
2174 STRCASECMP (s, options.excludeRegs[i]) == 0)
2180 /*-----------------------------------------------------------------*/
2181 /* genFunction - generated code for function entry */
2182 /*-----------------------------------------------------------------*/
2184 genFunction (iCode * ic)
2188 bool switchedPSW = FALSE;
2189 int calleesaves_saved_register = -1;
2192 /* create the function header */
2193 emitcode (";", "-----------------------------------------");
2194 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2195 emitcode (";", "-----------------------------------------");
2197 emitcode ("", "%s:", sym->rname);
2198 ftype = operandType (IC_LEFT (ic));
2200 if (IFFUNC_ISNAKED(ftype))
2202 emitcode(";", "naked function: no prologue.");
2206 /* if critical function then turn interrupts off */
2207 if (IFFUNC_ISCRITICAL (ftype))
2208 emitcode ("clr", "ea");
2210 /* here we need to generate the equates for the
2211 register bank if required */
2212 if (FUNC_REGBANK (ftype) != rbank)
2216 rbank = FUNC_REGBANK (ftype);
2217 for (i = 0; i < mcs51_nRegs; i++)
2219 if (strcmp (regs8051[i].base, "0") == 0)
2220 emitcode ("", "%s = 0x%02x",
2222 8 * rbank + regs8051[i].offset);
2224 emitcode ("", "%s = %s + 0x%02x",
2227 8 * rbank + regs8051[i].offset);
2231 /* if this is an interrupt service routine then
2232 save acc, b, dpl, dph */
2233 if (IFFUNC_ISISR (sym->type))
2236 if (!inExcludeList ("acc"))
2237 emitcode ("push", "acc");
2238 if (!inExcludeList ("b"))
2239 emitcode ("push", "b");
2240 if (!inExcludeList ("dpl"))
2241 emitcode ("push", "dpl");
2242 if (!inExcludeList ("dph"))
2243 emitcode ("push", "dph");
2244 /* if this isr has no bank i.e. is going to
2245 run with bank 0 , then we need to save more
2247 if (!FUNC_REGBANK (sym->type))
2250 /* if this function does not call any other
2251 function then we can be economical and
2252 save only those registers that are used */
2253 if (!IFFUNC_HASFCALL(sym->type))
2257 /* if any registers used */
2260 /* save the registers used */
2261 for (i = 0; i < sym->regsUsed->size; i++)
2263 if (bitVectBitValue (sym->regsUsed, i) ||
2264 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2265 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2273 /* this function has a function call cannot
2274 determines register usage so we will have to push the
2276 saveRBank (0, ic, FALSE);
2277 if (options.parms_in_bank1) {
2279 for (i=0; i < 8 ; i++ ) {
2280 emitcode ("push","%s",rb1regs[i]);
2287 /* This ISR uses a non-zero bank.
2289 * We assume that the bank is available for our
2292 * However, if this ISR calls a function which uses some
2293 * other bank, we must save that bank entirely.
2295 unsigned long banksToSave = 0;
2297 if (IFFUNC_HASFCALL(sym->type))
2300 #define MAX_REGISTER_BANKS 4
2305 for (i = ic; i; i = i->next)
2307 if (i->op == ENDFUNCTION)
2309 /* we got to the end OK. */
2317 dtype = operandType (IC_LEFT(i));
2319 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2321 /* Mark this bank for saving. */
2322 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2324 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2328 banksToSave |= (1 << FUNC_REGBANK(dtype));
2331 /* And note that we don't need to do it in
2339 /* This is a mess; we have no idea what
2340 * register bank the called function might
2343 * The only thing I can think of to do is
2344 * throw a warning and hope.
2346 werror(W_FUNCPTR_IN_USING_ISR);
2350 if (banksToSave && options.useXstack)
2352 /* Since we aren't passing it an ic,
2353 * saveRBank will assume r0 is available to abuse.
2355 * So switch to our (trashable) bank now, so
2356 * the caller's R0 isn't trashed.
2358 emitcode ("push", "psw");
2359 emitcode ("mov", "psw,#0x%02x",
2360 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2364 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2366 if (banksToSave & (1 << ix))
2368 saveRBank(ix, NULL, FALSE);
2372 // jwk: this needs a closer look
2373 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2378 /* if callee-save to be used for this function
2379 then save the registers being used in this function */
2380 if (IFFUNC_CALLEESAVES(sym->type))
2384 /* if any registers used */
2387 /* save the registers used */
2388 for (i = 0; i < sym->regsUsed->size; i++)
2390 if (bitVectBitValue (sym->regsUsed, i) ||
2391 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2393 /* remember one saved register for later usage */
2394 if (calleesaves_saved_register < 0)
2395 calleesaves_saved_register = i;
2396 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2404 /* set the register bank to the desired value */
2405 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2408 emitcode ("push", "psw");
2409 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2412 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2415 if (options.useXstack)
2417 emitcode ("mov", "r0,%s", spname);
2418 emitcode ("mov", "a,_bp");
2419 emitcode ("movx", "@r0,a");
2420 emitcode ("inc", "%s", spname);
2424 /* set up the stack */
2425 emitcode ("push", "_bp"); /* save the callers stack */
2427 emitcode ("mov", "_bp,%s", spname);
2430 /* adjust the stack for the function */
2436 werror (W_STACK_OVERFLOW, sym->name);
2438 if (i > 3 && sym->recvSize < 4)
2441 emitcode ("mov", "a,sp");
2442 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2443 emitcode ("mov", "sp,a");
2448 if (IFFUNC_CALLEESAVES(sym->type))
2450 /* if it's a callee-saves function we need a saved register */
2451 if (calleesaves_saved_register >= 0)
2453 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2454 emitcode ("mov", "a,sp");
2455 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2456 emitcode ("mov", "sp,a");
2457 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2460 /* do it the hard way */
2462 emitcode ("inc", "sp");
2466 /* not callee-saves, we can clobber ar0 */
2467 emitcode ("mov", "ar0,a");
2468 emitcode ("mov", "a,sp");
2469 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2470 emitcode ("mov", "sp,a");
2471 emitcode ("mov", "a,ar0");
2476 emitcode ("inc", "sp");
2482 emitcode ("mov", "a,_spx");
2483 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2484 emitcode ("mov", "_spx,a");
2489 /*-----------------------------------------------------------------*/
2490 /* genEndFunction - generates epilogue for functions */
2491 /*-----------------------------------------------------------------*/
2493 genEndFunction (iCode * ic)
2495 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2497 if (IFFUNC_ISNAKED(sym->type))
2499 emitcode(";", "naked function: no epilogue.");
2503 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2505 emitcode ("mov", "%s,_bp", spname);
2508 /* if use external stack but some variables were
2509 added to the local stack then decrement the
2511 if (options.useXstack && sym->stack)
2513 emitcode ("mov", "a,sp");
2514 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2515 emitcode ("mov", "sp,a");
2519 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2521 if (options.useXstack)
2523 emitcode ("mov", "r0,%s", spname);
2524 emitcode ("movx", "a,@r0");
2525 emitcode ("mov", "_bp,a");
2526 emitcode ("dec", "%s", spname);
2530 emitcode ("pop", "_bp");
2534 /* restore the register bank */
2535 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2537 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2538 || !options.useXstack)
2540 /* Special case of ISR using non-zero bank with useXstack
2543 emitcode ("pop", "psw");
2547 if (IFFUNC_ISISR (sym->type))
2550 /* now we need to restore the registers */
2551 /* if this isr has no bank i.e. is going to
2552 run with bank 0 , then we need to save more
2554 if (!FUNC_REGBANK (sym->type))
2556 /* if this function does not call any other
2557 function then we can be economical and
2558 save only those registers that are used */
2559 if (!IFFUNC_HASFCALL(sym->type))
2563 /* if any registers used */
2566 /* save the registers used */
2567 for (i = sym->regsUsed->size; i >= 0; i--)
2569 if (bitVectBitValue (sym->regsUsed, i) ||
2570 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2571 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2578 if (options.parms_in_bank1) {
2580 for (i = 7 ; i >= 0 ; i-- ) {
2581 emitcode ("pop","%s",rb1regs[i]);
2584 /* this function has a function call cannot
2585 determines register usage so we will have to pop the
2587 unsaveRBank (0, ic, FALSE);
2592 /* This ISR uses a non-zero bank.
2594 * Restore any register banks saved by genFunction
2597 // jwk: this needs a closer look
2598 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2601 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2603 if (savedBanks & (1 << ix))
2605 unsaveRBank(ix, NULL, FALSE);
2609 if (options.useXstack)
2611 /* Restore bank AFTER calling unsaveRBank,
2612 * since it can trash r0.
2614 emitcode ("pop", "psw");
2618 if (!inExcludeList ("dph"))
2619 emitcode ("pop", "dph");
2620 if (!inExcludeList ("dpl"))
2621 emitcode ("pop", "dpl");
2622 if (!inExcludeList ("b"))
2623 emitcode ("pop", "b");
2624 if (!inExcludeList ("acc"))
2625 emitcode ("pop", "acc");
2627 if (IFFUNC_ISCRITICAL (sym->type))
2628 emitcode ("setb", "ea");
2630 /* if debug then send end of function */
2631 if (options.debug && currFunc)
2634 emitcode ("", "C$%s$%d$%d$%d ==.",
2635 FileBaseName (ic->filename), currFunc->lastLine,
2636 ic->level, ic->block);
2637 if (IS_STATIC (currFunc->etype))
2638 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2640 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2644 emitcode ("reti", "");
2648 if (IFFUNC_ISCRITICAL (sym->type))
2649 emitcode ("setb", "ea");
2651 if (IFFUNC_CALLEESAVES(sym->type))
2655 /* if any registers used */
2658 /* save the registers used */
2659 for (i = sym->regsUsed->size; i >= 0; i--)
2661 if (bitVectBitValue (sym->regsUsed, i) ||
2662 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2663 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2669 /* if debug then send end of function */
2670 if (options.debug && currFunc)
2673 emitcode ("", "C$%s$%d$%d$%d ==.",
2674 FileBaseName (ic->filename), currFunc->lastLine,
2675 ic->level, ic->block);
2676 if (IS_STATIC (currFunc->etype))
2677 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2679 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2683 emitcode ("ret", "");
2688 /*-----------------------------------------------------------------*/
2689 /* genRet - generate code for return statement */
2690 /*-----------------------------------------------------------------*/
2694 int size, offset = 0, pushed = 0;
2696 D(emitcode (";", "genRet"));
2698 /* if we have no return value then
2699 just generate the "ret" */
2703 /* we have something to return then
2704 move the return value into place */
2705 aopOp (IC_LEFT (ic), ic, FALSE);
2706 size = AOP_SIZE (IC_LEFT (ic));
2711 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2714 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2716 emitcode ("push", "%s", l);
2721 l = aopGet (AOP (IC_LEFT (ic)), offset,
2723 if (strcmp (fReturn[offset], l))
2724 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2733 if (strcmp (fReturn[pushed], "a"))
2734 emitcode ("pop", fReturn[pushed]);
2736 emitcode ("pop", "acc");
2739 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2742 /* generate a jump to the return label
2743 if the next is not the return statement */
2744 if (!(ic->next && ic->next->op == LABEL &&
2745 IC_LABEL (ic->next) == returnLabel))
2747 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2751 /*-----------------------------------------------------------------*/
2752 /* genLabel - generates a label */
2753 /*-----------------------------------------------------------------*/
2755 genLabel (iCode * ic)
2757 /* special case never generate */
2758 if (IC_LABEL (ic) == entryLabel)
2761 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2764 /*-----------------------------------------------------------------*/
2765 /* genGoto - generates a ljmp */
2766 /*-----------------------------------------------------------------*/
2768 genGoto (iCode * ic)
2770 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2773 /*-----------------------------------------------------------------*/
2774 /* findLabelBackwards: walks back through the iCode chain looking */
2775 /* for the given label. Returns number of iCode instructions */
2776 /* between that label and given ic. */
2777 /* Returns zero if label not found. */
2778 /*-----------------------------------------------------------------*/
2780 findLabelBackwards (iCode * ic, int key)
2789 /* If we have any pushes or pops, we cannot predict the distance.
2790 I don't like this at all, this should be dealt with in the
2792 if (ic->op == IPUSH || ic->op == IPOP) {
2796 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2805 /*-----------------------------------------------------------------*/
2806 /* genPlusIncr :- does addition with increment if possible */
2807 /*-----------------------------------------------------------------*/
2809 genPlusIncr (iCode * ic)
2811 unsigned int icount;
2812 unsigned int size = getDataSize (IC_RESULT (ic));
2814 /* will try to generate an increment */
2815 /* if the right side is not a literal
2817 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2820 /* if the literal value of the right hand side
2821 is greater than 4 then it is not worth it */
2822 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2825 D(emitcode (";", "genPlusIncr"));
2827 /* if increment 16 bits in register */
2828 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2829 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2837 /* If the next instruction is a goto and the goto target
2838 * is < 10 instructions previous to this, we can generate
2839 * jumps straight to that target.
2841 if (ic->next && ic->next->op == GOTO
2842 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2843 && labelRange <= 10)
2845 emitcode (";", "tail increment optimized");
2846 tlbl = IC_LABEL (ic->next);
2851 tlbl = newiTempLabel (NULL);
2854 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2855 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2856 IS_AOP_PREG (IC_RESULT (ic)))
2857 emitcode ("cjne", "%s,#0x00,%05d$",
2858 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2862 emitcode ("clr", "a");
2863 emitcode ("cjne", "a,%s,%05d$",
2864 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2868 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2871 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2872 IS_AOP_PREG (IC_RESULT (ic)))
2873 emitcode ("cjne", "%s,#0x00,%05d$",
2874 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2877 emitcode ("cjne", "a,%s,%05d$",
2878 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2881 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2885 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2886 IS_AOP_PREG (IC_RESULT (ic)))
2887 emitcode ("cjne", "%s,#0x00,%05d$",
2888 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2892 emitcode ("cjne", "a,%s,%05d$",
2893 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2896 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2901 emitcode ("", "%05d$:", tlbl->key + 100);
2906 /* if the sizes are greater than 1 then we cannot */
2907 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2908 AOP_SIZE (IC_LEFT (ic)) > 1)
2911 /* we can if the aops of the left & result match or
2912 if they are in registers and the registers are the
2914 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2919 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2920 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2921 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2927 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2936 /*-----------------------------------------------------------------*/
2937 /* outBitAcc - output a bit in acc */
2938 /*-----------------------------------------------------------------*/
2940 outBitAcc (operand * result)
2942 symbol *tlbl = newiTempLabel (NULL);
2943 /* if the result is a bit */
2944 if (AOP_TYPE (result) == AOP_CRY)
2946 aopPut (AOP (result), "a", 0);
2950 emitcode ("jz", "%05d$", tlbl->key + 100);
2951 emitcode ("mov", "a,%s", one);
2952 emitcode ("", "%05d$:", tlbl->key + 100);
2957 /*-----------------------------------------------------------------*/
2958 /* genPlusBits - generates code for addition of two bits */
2959 /*-----------------------------------------------------------------*/
2961 genPlusBits (iCode * ic)
2963 D(emitcode (";", "genPlusBits"));
2965 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2967 symbol *lbl = newiTempLabel (NULL);
2968 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2969 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2970 emitcode ("cpl", "c");
2971 emitcode ("", "%05d$:", (lbl->key + 100));
2972 outBitC (IC_RESULT (ic));
2976 emitcode ("clr", "a");
2977 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2978 emitcode ("rlc", "a");
2979 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2980 emitcode ("addc", "a,#0x00");
2981 outAcc (IC_RESULT (ic));
2986 /* This is the original version of this code.
2988 * This is being kept around for reference,
2989 * because I am not entirely sure I got it right...
2992 adjustArithmeticResult (iCode * ic)
2994 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2995 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2996 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2997 aopPut (AOP (IC_RESULT (ic)),
2998 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3001 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3002 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3003 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3004 aopPut (AOP (IC_RESULT (ic)),
3005 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3008 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3009 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3010 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3011 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3012 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3015 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3016 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3020 /* This is the pure and virtuous version of this code.
3021 * I'm pretty certain it's right, but not enough to toss the old
3025 adjustArithmeticResult (iCode * ic)
3027 if (opIsGptr (IC_RESULT (ic)) &&
3028 opIsGptr (IC_LEFT (ic)) &&
3029 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3031 aopPut (AOP (IC_RESULT (ic)),
3032 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3036 if (opIsGptr (IC_RESULT (ic)) &&
3037 opIsGptr (IC_RIGHT (ic)) &&
3038 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3040 aopPut (AOP (IC_RESULT (ic)),
3041 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3045 if (opIsGptr (IC_RESULT (ic)) &&
3046 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3047 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3048 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3049 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3052 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3053 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3058 /*-----------------------------------------------------------------*/
3059 /* genPlus - generates code for addition */
3060 /*-----------------------------------------------------------------*/
3062 genPlus (iCode * ic)
3064 int size, offset = 0;
3066 /* special cases :- */
3068 D(emitcode (";", "genPlus"));
3070 aopOp (IC_LEFT (ic), ic, FALSE);
3071 aopOp (IC_RIGHT (ic), ic, FALSE);
3072 aopOp (IC_RESULT (ic), ic, TRUE);
3074 /* if literal, literal on the right or
3075 if left requires ACC or right is already
3077 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3078 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3079 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3081 operand *t = IC_RIGHT (ic);
3082 IC_RIGHT (ic) = IC_LEFT (ic);
3086 /* if both left & right are in bit
3088 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3089 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3095 /* if left in bit space & right literal */
3096 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3097 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3099 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3100 /* if result in bit space */
3101 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3103 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3104 emitcode ("cpl", "c");
3105 outBitC (IC_RESULT (ic));
3109 size = getDataSize (IC_RESULT (ic));
3112 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3113 emitcode ("addc", "a,#00");
3114 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3120 /* if I can do an increment instead
3121 of add then GOOD for ME */
3122 if (genPlusIncr (ic) == TRUE)
3125 size = getDataSize (IC_RESULT (ic));
3129 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3131 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3133 emitcode ("add", "a,%s",
3134 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3136 emitcode ("addc", "a,%s",
3137 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3141 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3143 emitcode ("add", "a,%s",
3144 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3146 emitcode ("addc", "a,%s",
3147 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3149 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3152 adjustArithmeticResult (ic);
3155 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3156 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3157 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3160 /*-----------------------------------------------------------------*/
3161 /* genMinusDec :- does subtraction with deccrement if possible */
3162 /*-----------------------------------------------------------------*/
3164 genMinusDec (iCode * ic)
3166 unsigned int icount;
3167 unsigned int size = getDataSize (IC_RESULT (ic));
3169 /* will try to generate an increment */
3170 /* if the right side is not a literal
3172 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3175 /* if the literal value of the right hand side
3176 is greater than 4 then it is not worth it */
3177 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3180 D(emitcode (";", "genMinusDec"));
3182 /* if decrement 16 bits in register */
3183 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3184 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3192 /* If the next instruction is a goto and the goto target
3193 * is <= 10 instructions previous to this, we can generate
3194 * jumps straight to that target.
3196 if (ic->next && ic->next->op == GOTO
3197 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3198 && labelRange <= 10)
3200 emitcode (";", "tail decrement optimized");
3201 tlbl = IC_LABEL (ic->next);
3206 tlbl = newiTempLabel (NULL);
3210 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3211 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3212 IS_AOP_PREG (IC_RESULT (ic)))
3213 emitcode ("cjne", "%s,#0xff,%05d$"
3214 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3218 emitcode ("mov", "a,#0xff");
3219 emitcode ("cjne", "a,%s,%05d$"
3220 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3223 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3226 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3227 IS_AOP_PREG (IC_RESULT (ic)))
3228 emitcode ("cjne", "%s,#0xff,%05d$"
3229 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3233 emitcode ("cjne", "a,%s,%05d$"
3234 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3237 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3241 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242 IS_AOP_PREG (IC_RESULT (ic)))
3243 emitcode ("cjne", "%s,#0xff,%05d$"
3244 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3248 emitcode ("cjne", "a,%s,%05d$"
3249 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3252 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3256 emitcode ("", "%05d$:", tlbl->key + 100);
3261 /* if the sizes are greater than 1 then we cannot */
3262 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3263 AOP_SIZE (IC_LEFT (ic)) > 1)
3266 /* we can if the aops of the left & result match or
3267 if they are in registers and the registers are the
3269 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3273 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3281 /*-----------------------------------------------------------------*/
3282 /* addSign - complete with sign */
3283 /*-----------------------------------------------------------------*/
3285 addSign (operand * result, int offset, int sign)
3287 int size = (getDataSize (result) - offset);
3292 emitcode ("rlc", "a");
3293 emitcode ("subb", "a,acc");
3295 aopPut (AOP (result), "a", offset++);
3299 aopPut (AOP (result), zero, offset++);
3303 /*-----------------------------------------------------------------*/
3304 /* genMinusBits - generates code for subtraction of two bits */
3305 /*-----------------------------------------------------------------*/
3307 genMinusBits (iCode * ic)
3309 symbol *lbl = newiTempLabel (NULL);
3311 D(emitcode (";", "genMinusBits"));
3313 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3315 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3316 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3317 emitcode ("cpl", "c");
3318 emitcode ("", "%05d$:", (lbl->key + 100));
3319 outBitC (IC_RESULT (ic));
3323 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3324 emitcode ("subb", "a,acc");
3325 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3326 emitcode ("inc", "a");
3327 emitcode ("", "%05d$:", (lbl->key + 100));
3328 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3329 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3333 /*-----------------------------------------------------------------*/
3334 /* genMinus - generates code for subtraction */
3335 /*-----------------------------------------------------------------*/
3337 genMinus (iCode * ic)
3339 int size, offset = 0;
3340 unsigned long lit = 0L;
3342 D(emitcode (";", "genMinus"));
3344 aopOp (IC_LEFT (ic), ic, FALSE);
3345 aopOp (IC_RIGHT (ic), ic, FALSE);
3346 aopOp (IC_RESULT (ic), ic, TRUE);
3348 /* special cases :- */
3349 /* if both left & right are in bit space */
3350 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3351 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3357 /* if I can do an decrement instead
3358 of subtract then GOOD for ME */
3359 if (genMinusDec (ic) == TRUE)
3362 size = getDataSize (IC_RESULT (ic));
3364 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3370 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3374 /* if literal, add a,#-lit, else normal subb */
3377 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3378 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3379 emitcode ("subb", "a,%s",
3380 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3383 /* first add without previous c */
3385 if (!size && lit==-1) {
3386 emitcode ("dec", "a");
3388 emitcode ("add", "a,#0x%02x",
3389 (unsigned int) (lit & 0x0FFL));
3392 emitcode ("addc", "a,#0x%02x",
3393 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3396 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3399 adjustArithmeticResult (ic);
3402 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3403 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3404 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3408 /*-----------------------------------------------------------------*/
3409 /* genMultbits :- multiplication of bits */
3410 /*-----------------------------------------------------------------*/
3412 genMultbits (operand * left,
3416 D(emitcode (";", "genMultbits"));
3418 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3419 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3424 /*-----------------------------------------------------------------*/
3425 /* genMultOneByte : 8*8=8/16 bit multiplication */
3426 /*-----------------------------------------------------------------*/
3428 genMultOneByte (operand * left,
3432 sym_link *opetype = operandType (result);
3434 int size=AOP_SIZE(result);
3436 D(emitcode (";", "genMultOneByte"));
3438 if (size<1 || size>2) {
3439 // this should never happen
3440 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3441 AOP_SIZE(result), __FILE__, lineno);
3445 /* (if two literals: the value is computed before) */
3446 /* if one literal, literal on the right */
3447 if (AOP_TYPE (left) == AOP_LIT)
3452 //emitcode (";", "swapped left and right");
3455 if (SPEC_USIGN(opetype)
3456 // ignore the sign of left and right, what else can we do?
3457 || (SPEC_USIGN(operandType(left)) &&
3458 SPEC_USIGN(operandType(right)))) {
3459 // just an unsigned 8*8=8/16 multiply
3460 //emitcode (";","unsigned");
3461 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3462 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3463 emitcode ("mul", "ab");
3464 aopPut (AOP (result), "a", 0);
3466 aopPut (AOP (result), "b", 1);
3471 // we have to do a signed multiply
3473 //emitcode (";", "signed");
3474 emitcode ("clr", "F0"); // reset sign flag
3475 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3477 lbl=newiTempLabel(NULL);
3478 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3479 // left side is negative, 8-bit two's complement, this fails for -128
3480 emitcode ("setb", "F0"); // set sign flag
3481 emitcode ("cpl", "a");
3482 emitcode ("inc", "a");
3484 emitcode ("", "%05d$:", lbl->key+100);
3487 if (AOP_TYPE(right)==AOP_LIT) {
3488 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3489 /* AND literal negative */
3491 emitcode ("cpl", "F0"); // complement sign flag
3492 emitcode ("mov", "b,#0x%02x", -val);
3494 emitcode ("mov", "b,#0x%02x", val);
3497 lbl=newiTempLabel(NULL);
3498 emitcode ("mov", "b,a");
3499 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3500 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3501 // right side is negative, 8-bit two's complement
3502 emitcode ("cpl", "F0"); // complement sign flag
3503 emitcode ("cpl", "a");
3504 emitcode ("inc", "a");
3505 emitcode ("", "%05d$:", lbl->key+100);
3507 emitcode ("mul", "ab");
3509 lbl=newiTempLabel(NULL);
3510 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3511 // only ONE op was negative, we have to do a 8/16-bit two's complement
3512 emitcode ("cpl", "a"); // lsb
3514 emitcode ("inc", "a");
3516 emitcode ("add", "a,#1");
3517 emitcode ("xch", "a,b");
3518 emitcode ("cpl", "a"); // msb
3519 emitcode ("addc", "a,#0");
3520 emitcode ("xch", "a,b");
3523 emitcode ("", "%05d$:", lbl->key+100);
3524 aopPut (AOP (result), "a", 0);
3526 aopPut (AOP (result), "b", 1);
3530 /*-----------------------------------------------------------------*/
3531 /* genMult - generates code for multiplication */
3532 /*-----------------------------------------------------------------*/
3534 genMult (iCode * ic)
3536 operand *left = IC_LEFT (ic);
3537 operand *right = IC_RIGHT (ic);
3538 operand *result = IC_RESULT (ic);
3540 D(emitcode (";", "genMult"));
3542 /* assign the amsops */
3543 aopOp (left, ic, FALSE);
3544 aopOp (right, ic, FALSE);
3545 aopOp (result, ic, TRUE);
3547 /* special cases first */
3549 if (AOP_TYPE (left) == AOP_CRY &&
3550 AOP_TYPE (right) == AOP_CRY)
3552 genMultbits (left, right, result);
3556 /* if both are of size == 1 */
3557 #if 0 // one of them can be a sloc shared with the result
3558 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3560 if (getSize(operandType(left)) == 1 &&
3561 getSize(operandType(right)) == 1)
3564 genMultOneByte (left, right, result);
3568 /* should have been converted to function call */
3569 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3570 getSize(OP_SYMBOL(right)->type));
3574 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3575 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3576 freeAsmop (result, NULL, ic, TRUE);
3579 /*-----------------------------------------------------------------*/
3580 /* genDivbits :- division of bits */
3581 /*-----------------------------------------------------------------*/
3583 genDivbits (operand * left,
3590 D(emitcode (";", "genDivbits"));
3592 /* the result must be bit */
3593 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3594 l = aopGet (AOP (left), 0, FALSE, FALSE);
3598 emitcode ("div", "ab");
3599 emitcode ("rrc", "a");
3600 aopPut (AOP (result), "c", 0);
3603 /*-----------------------------------------------------------------*/
3604 /* genDivOneByte : 8 bit division */
3605 /*-----------------------------------------------------------------*/
3607 genDivOneByte (operand * left,
3611 sym_link *opetype = operandType (result);
3616 D(emitcode (";", "genDivOneByte"));
3618 size = AOP_SIZE (result) - 1;
3620 /* signed or unsigned */
3621 if (SPEC_USIGN (opetype))
3623 /* unsigned is easy */
3624 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3625 l = aopGet (AOP (left), 0, FALSE, FALSE);
3627 emitcode ("div", "ab");
3628 aopPut (AOP (result), "a", 0);
3630 aopPut (AOP (result), zero, offset++);
3634 /* signed is a little bit more difficult */
3636 /* save the signs of the operands */
3637 l = aopGet (AOP (left), 0, FALSE, FALSE);
3639 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3640 emitcode ("push", "acc"); /* save it on the stack */
3642 /* now sign adjust for both left & right */
3643 l = aopGet (AOP (right), 0, FALSE, FALSE);
3645 lbl = newiTempLabel (NULL);
3646 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3647 emitcode ("cpl", "a");
3648 emitcode ("inc", "a");
3649 emitcode ("", "%05d$:", (lbl->key + 100));
3650 emitcode ("mov", "b,a");
3652 /* sign adjust left side */
3653 l = aopGet (AOP (left), 0, FALSE, FALSE);
3656 lbl = newiTempLabel (NULL);
3657 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3658 emitcode ("cpl", "a");
3659 emitcode ("inc", "a");
3660 emitcode ("", "%05d$:", (lbl->key + 100));
3662 /* now the division */
3663 emitcode ("div", "ab");
3664 /* we are interested in the lower order
3666 emitcode ("mov", "b,a");
3667 lbl = newiTempLabel (NULL);
3668 emitcode ("pop", "acc");
3669 /* if there was an over flow we don't
3670 adjust the sign of the result */
3671 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3672 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3674 emitcode ("clr", "a");
3675 emitcode ("subb", "a,b");
3676 emitcode ("mov", "b,a");
3677 emitcode ("", "%05d$:", (lbl->key + 100));
3679 /* now we are done */
3680 aopPut (AOP (result), "b", 0);
3683 emitcode ("mov", "c,b.7");
3684 emitcode ("subb", "a,acc");
3687 aopPut (AOP (result), "a", offset++);
3691 /*-----------------------------------------------------------------*/
3692 /* genDiv - generates code for division */
3693 /*-----------------------------------------------------------------*/
3697 operand *left = IC_LEFT (ic);
3698 operand *right = IC_RIGHT (ic);
3699 operand *result = IC_RESULT (ic);
3701 D(emitcode (";", "genDiv"));
3703 /* assign the amsops */
3704 aopOp (left, ic, FALSE);
3705 aopOp (right, ic, FALSE);
3706 aopOp (result, ic, TRUE);
3708 /* special cases first */
3710 if (AOP_TYPE (left) == AOP_CRY &&
3711 AOP_TYPE (right) == AOP_CRY)
3713 genDivbits (left, right, result);
3717 /* if both are of size == 1 */
3718 if (AOP_SIZE (left) == 1 &&
3719 AOP_SIZE (right) == 1)
3721 genDivOneByte (left, right, result);
3725 /* should have been converted to function call */
3728 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3729 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3730 freeAsmop (result, NULL, ic, TRUE);
3733 /*-----------------------------------------------------------------*/
3734 /* genModbits :- modulus of bits */
3735 /*-----------------------------------------------------------------*/
3737 genModbits (operand * left,
3744 D(emitcode (";", "genModbits"));
3746 /* the result must be bit */
3747 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3748 l = aopGet (AOP (left), 0, FALSE, FALSE);
3752 emitcode ("div", "ab");
3753 emitcode ("mov", "a,b");
3754 emitcode ("rrc", "a");
3755 aopPut (AOP (result), "c", 0);
3758 /*-----------------------------------------------------------------*/
3759 /* genModOneByte : 8 bit modulus */
3760 /*-----------------------------------------------------------------*/
3762 genModOneByte (operand * left,
3766 sym_link *opetype = operandType (result);
3770 D(emitcode (";", "genModOneByte"));
3772 /* signed or unsigned */
3773 if (SPEC_USIGN (opetype))
3775 /* unsigned is easy */
3776 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3777 l = aopGet (AOP (left), 0, FALSE, FALSE);
3779 emitcode ("div", "ab");
3780 aopPut (AOP (result), "b", 0);
3784 /* signed is a little bit more difficult */
3786 /* save the signs of the operands */
3787 l = aopGet (AOP (left), 0, FALSE, FALSE);
3790 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3791 emitcode ("push", "acc"); /* save it on the stack */
3793 /* now sign adjust for both left & right */
3794 l = aopGet (AOP (right), 0, FALSE, FALSE);
3797 lbl = newiTempLabel (NULL);
3798 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3799 emitcode ("cpl", "a");
3800 emitcode ("inc", "a");
3801 emitcode ("", "%05d$:", (lbl->key + 100));
3802 emitcode ("mov", "b,a");
3804 /* sign adjust left side */
3805 l = aopGet (AOP (left), 0, FALSE, FALSE);
3808 lbl = newiTempLabel (NULL);
3809 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3810 emitcode ("cpl", "a");
3811 emitcode ("inc", "a");
3812 emitcode ("", "%05d$:", (lbl->key + 100));
3814 /* now the multiplication */
3815 emitcode ("div", "ab");
3816 /* we are interested in the lower order
3818 lbl = newiTempLabel (NULL);
3819 emitcode ("pop", "acc");
3820 /* if there was an over flow we don't
3821 adjust the sign of the result */
3822 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3823 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3825 emitcode ("clr", "a");
3826 emitcode ("subb", "a,b");
3827 emitcode ("mov", "b,a");
3828 emitcode ("", "%05d$:", (lbl->key + 100));
3830 /* now we are done */
3831 aopPut (AOP (result), "b", 0);
3835 /*-----------------------------------------------------------------*/
3836 /* genMod - generates code for division */
3837 /*-----------------------------------------------------------------*/
3841 operand *left = IC_LEFT (ic);
3842 operand *right = IC_RIGHT (ic);
3843 operand *result = IC_RESULT (ic);
3845 D(emitcode (";", "genMod"));
3847 /* assign the amsops */
3848 aopOp (left, ic, FALSE);
3849 aopOp (right, ic, FALSE);
3850 aopOp (result, ic, TRUE);
3852 /* special cases first */
3854 if (AOP_TYPE (left) == AOP_CRY &&
3855 AOP_TYPE (right) == AOP_CRY)
3857 genModbits (left, right, result);
3861 /* if both are of size == 1 */
3862 if (AOP_SIZE (left) == 1 &&
3863 AOP_SIZE (right) == 1)
3865 genModOneByte (left, right, result);
3869 /* should have been converted to function call */
3873 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3874 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3875 freeAsmop (result, NULL, ic, TRUE);
3878 /*-----------------------------------------------------------------*/
3879 /* genIfxJump :- will create a jump depending on the ifx */
3880 /*-----------------------------------------------------------------*/
3882 genIfxJump (iCode * ic, char *jval)
3885 symbol *tlbl = newiTempLabel (NULL);
3888 D(emitcode (";", "genIfxJump"));
3890 /* if true label then we jump if condition
3894 jlbl = IC_TRUE (ic);
3895 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3896 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3900 /* false label is present */
3901 jlbl = IC_FALSE (ic);
3902 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3903 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3905 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3906 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3908 emitcode (inst, "%05d$", tlbl->key + 100);
3909 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3910 emitcode ("", "%05d$:", tlbl->key + 100);
3912 /* mark the icode as generated */
3916 /*-----------------------------------------------------------------*/
3917 /* genCmp :- greater or less than comparison */
3918 /*-----------------------------------------------------------------*/
3920 genCmp (operand * left, operand * right,
3921 operand * result, iCode * ifx, int sign, iCode *ic)
3923 int size, offset = 0;
3924 unsigned long lit = 0L;
3926 D(emitcode (";", "genCmp"));
3928 /* if left & right are bit variables */
3929 if (AOP_TYPE (left) == AOP_CRY &&
3930 AOP_TYPE (right) == AOP_CRY)
3932 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3933 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3937 /* subtract right from left if at the
3938 end the carry flag is set then we know that
3939 left is greater than right */
3940 size = max (AOP_SIZE (left), AOP_SIZE (right));
3942 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3943 if ((size == 1) && !sign &&
3944 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3946 symbol *lbl = newiTempLabel (NULL);
3947 emitcode ("cjne", "%s,%s,%05d$",
3948 aopGet (AOP (left), offset, FALSE, FALSE),
3949 aopGet (AOP (right), offset, FALSE, FALSE),
3951 emitcode ("", "%05d$:", lbl->key + 100);
3955 if (AOP_TYPE (right) == AOP_LIT)
3957 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3958 /* optimize if(x < 0) or if(x >= 0) */
3967 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3968 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3970 genIfxJump (ifx, "acc.7");
3974 emitcode ("rlc", "a");
3982 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3983 if (sign && size == 0)
3985 emitcode ("xrl", "a,#0x80");
3986 if (AOP_TYPE (right) == AOP_LIT)
3988 unsigned long lit = (unsigned long)
3989 floatFromVal (AOP (right)->aopu.aop_lit);
3990 emitcode ("subb", "a,#0x%02x",
3991 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3995 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3996 emitcode ("xrl", "b,#0x80");
3997 emitcode ("subb", "a,b");
4001 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4007 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4008 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4009 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4015 /* if the result is used in the next
4016 ifx conditional branch then generate
4017 code a little differently */
4019 genIfxJump (ifx, "c");
4022 /* leave the result in acc */
4026 /*-----------------------------------------------------------------*/
4027 /* genCmpGt :- greater than comparison */
4028 /*-----------------------------------------------------------------*/
4030 genCmpGt (iCode * ic, iCode * ifx)
4032 operand *left, *right, *result;
4033 sym_link *letype, *retype;
4036 D(emitcode (";", "genCmpGt"));
4038 left = IC_LEFT (ic);
4039 right = IC_RIGHT (ic);
4040 result = IC_RESULT (ic);
4042 letype = getSpec (operandType (left));
4043 retype = getSpec (operandType (right));
4044 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4045 /* assign the amsops */
4046 aopOp (left, ic, FALSE);
4047 aopOp (right, ic, FALSE);
4048 aopOp (result, ic, TRUE);
4050 genCmp (right, left, result, ifx, sign,ic);
4052 freeAsmop (result, NULL, ic, TRUE);
4055 /*-----------------------------------------------------------------*/
4056 /* genCmpLt - less than comparisons */
4057 /*-----------------------------------------------------------------*/
4059 genCmpLt (iCode * ic, iCode * ifx)
4061 operand *left, *right, *result;
4062 sym_link *letype, *retype;
4065 D(emitcode (";", "genCmpLt"));
4067 left = IC_LEFT (ic);
4068 right = IC_RIGHT (ic);
4069 result = IC_RESULT (ic);
4071 letype = getSpec (operandType (left));
4072 retype = getSpec (operandType (right));
4073 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4075 /* assign the amsops */
4076 aopOp (left, ic, FALSE);
4077 aopOp (right, ic, FALSE);
4078 aopOp (result, ic, TRUE);
4080 genCmp (left, right, result, ifx, sign,ic);
4082 freeAsmop (result, NULL, ic, TRUE);
4085 /*-----------------------------------------------------------------*/
4086 /* gencjneshort - compare and jump if not equal */
4087 /*-----------------------------------------------------------------*/
4089 gencjneshort (operand * left, operand * right, symbol * lbl)
4091 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4093 unsigned long lit = 0L;
4095 /* if the left side is a literal or
4096 if the right is in a pointer register and left
4098 if ((AOP_TYPE (left) == AOP_LIT) ||
4099 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4105 if (AOP_TYPE (right) == AOP_LIT)
4106 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4108 /* if the right side is a literal then anything goes */
4109 if (AOP_TYPE (right) == AOP_LIT &&
4110 AOP_TYPE (left) != AOP_DIR)
4114 emitcode ("cjne", "%s,%s,%05d$",
4115 aopGet (AOP (left), offset, FALSE, FALSE),
4116 aopGet (AOP (right), offset, FALSE, FALSE),
4122 /* if the right side is in a register or in direct space or
4123 if the left is a pointer register & right is not */
4124 else if (AOP_TYPE (right) == AOP_REG ||
4125 AOP_TYPE (right) == AOP_DIR ||
4126 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4127 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4131 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4132 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4133 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4134 emitcode ("jnz", "%05d$", lbl->key + 100);
4136 emitcode ("cjne", "a,%s,%05d$",
4137 aopGet (AOP (right), offset, FALSE, TRUE),
4144 /* right is a pointer reg need both a & b */
4147 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4148 if (strcmp (l, "b"))
4149 emitcode ("mov", "b,%s", l);
4150 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4151 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4157 /*-----------------------------------------------------------------*/
4158 /* gencjne - compare and jump if not equal */
4159 /*-----------------------------------------------------------------*/
4161 gencjne (operand * left, operand * right, symbol * lbl)
4163 symbol *tlbl = newiTempLabel (NULL);
4165 gencjneshort (left, right, lbl);
4167 emitcode ("mov", "a,%s", one);
4168 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4169 emitcode ("", "%05d$:", lbl->key + 100);
4170 emitcode ("clr", "a");
4171 emitcode ("", "%05d$:", tlbl->key + 100);
4174 /*-----------------------------------------------------------------*/
4175 /* genCmpEq - generates code for equal to */
4176 /*-----------------------------------------------------------------*/
4178 genCmpEq (iCode * ic, iCode * ifx)
4180 operand *left, *right, *result;
4182 D(emitcode (";", "genCmpEq"));
4184 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4185 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4186 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4188 /* if literal, literal on the right or
4189 if the right is in a pointer register and left
4191 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4192 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4194 operand *t = IC_RIGHT (ic);
4195 IC_RIGHT (ic) = IC_LEFT (ic);
4199 if (ifx && !AOP_SIZE (result))
4202 /* if they are both bit variables */
4203 if (AOP_TYPE (left) == AOP_CRY &&
4204 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4206 if (AOP_TYPE (right) == AOP_LIT)
4208 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4211 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4212 emitcode ("cpl", "c");
4216 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4220 emitcode ("clr", "c");
4222 /* AOP_TYPE(right) == AOP_CRY */
4226 symbol *lbl = newiTempLabel (NULL);
4227 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4228 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4229 emitcode ("cpl", "c");
4230 emitcode ("", "%05d$:", (lbl->key + 100));
4232 /* if true label then we jump if condition
4234 tlbl = newiTempLabel (NULL);
4237 emitcode ("jnc", "%05d$", tlbl->key + 100);
4238 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4242 emitcode ("jc", "%05d$", tlbl->key + 100);
4243 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4245 emitcode ("", "%05d$:", tlbl->key + 100);
4249 tlbl = newiTempLabel (NULL);
4250 gencjneshort (left, right, tlbl);
4253 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4254 emitcode ("", "%05d$:", tlbl->key + 100);
4258 symbol *lbl = newiTempLabel (NULL);
4259 emitcode ("sjmp", "%05d$", lbl->key + 100);
4260 emitcode ("", "%05d$:", tlbl->key + 100);
4261 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4262 emitcode ("", "%05d$:", lbl->key + 100);
4265 /* mark the icode as generated */
4270 /* if they are both bit variables */
4271 if (AOP_TYPE (left) == AOP_CRY &&
4272 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4274 if (AOP_TYPE (right) == AOP_LIT)
4276 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4279 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4280 emitcode ("cpl", "c");
4284 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4288 emitcode ("clr", "c");
4290 /* AOP_TYPE(right) == AOP_CRY */
4294 symbol *lbl = newiTempLabel (NULL);
4295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4296 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4297 emitcode ("cpl", "c");
4298 emitcode ("", "%05d$:", (lbl->key + 100));
4301 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4308 genIfxJump (ifx, "c");
4311 /* if the result is used in an arithmetic operation
4312 then put the result in place */
4317 gencjne (left, right, newiTempLabel (NULL));
4318 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4320 aopPut (AOP (result), "a", 0);
4325 genIfxJump (ifx, "a");
4328 /* if the result is used in an arithmetic operation
4329 then put the result in place */
4330 if (AOP_TYPE (result) != AOP_CRY)
4332 /* leave the result in acc */
4336 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4337 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4338 freeAsmop (result, NULL, ic, TRUE);
4341 /*-----------------------------------------------------------------*/
4342 /* ifxForOp - returns the icode containing the ifx for operand */
4343 /*-----------------------------------------------------------------*/
4345 ifxForOp (operand * op, iCode * ic)
4347 /* if true symbol then needs to be assigned */
4348 if (IS_TRUE_SYMOP (op))
4351 /* if this has register type condition and
4352 the next instruction is ifx with the same operand
4353 and live to of the operand is upto the ifx only then */
4355 ic->next->op == IFX &&
4356 IC_COND (ic->next)->key == op->key &&
4357 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4363 /*-----------------------------------------------------------------*/
4364 /* hasInc - operand is incremented before any other use */
4365 /*-----------------------------------------------------------------*/
4367 hasInc (operand *op, iCode *ic,int osize)
4369 sym_link *type = operandType(op);
4370 sym_link *retype = getSpec (type);
4371 iCode *lic = ic->next;
4374 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4375 if (!IS_SYMOP(op)) return NULL;
4377 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4378 if (IS_AGGREGATE(type->next)) return NULL;
4379 if (osize != (isize = getSize(type->next))) return NULL;
4382 /* if operand of the form op = op + <sizeof *op> */
4383 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4384 isOperandEqual(IC_RESULT(lic),op) &&
4385 isOperandLiteral(IC_RIGHT(lic)) &&
4386 operandLitValue(IC_RIGHT(lic)) == isize) {
4389 /* if the operand used or deffed */
4390 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4393 /* if GOTO or IFX */
4394 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4400 /*-----------------------------------------------------------------*/
4401 /* genAndOp - for && operation */
4402 /*-----------------------------------------------------------------*/
4404 genAndOp (iCode * ic)
4406 operand *left, *right, *result;
4409 D(emitcode (";", "genAndOp"));
4411 /* note here that && operations that are in an
4412 if statement are taken away by backPatchLabels
4413 only those used in arthmetic operations remain */
4414 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4415 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4416 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4418 /* if both are bit variables */
4419 if (AOP_TYPE (left) == AOP_CRY &&
4420 AOP_TYPE (right) == AOP_CRY)
4422 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4423 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4428 tlbl = newiTempLabel (NULL);
4430 emitcode ("jz", "%05d$", tlbl->key + 100);
4432 emitcode ("", "%05d$:", tlbl->key + 100);
4436 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4437 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4438 freeAsmop (result, NULL, ic, TRUE);
4442 /*-----------------------------------------------------------------*/
4443 /* genOrOp - for || operation */
4444 /*-----------------------------------------------------------------*/
4446 genOrOp (iCode * ic)
4448 operand *left, *right, *result;
4451 D(emitcode (";", "genOrOp"));
4453 /* note here that || operations that are in an
4454 if statement are taken away by backPatchLabels
4455 only those used in arthmetic operations remain */
4456 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4457 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4458 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4460 /* if both are bit variables */
4461 if (AOP_TYPE (left) == AOP_CRY &&
4462 AOP_TYPE (right) == AOP_CRY)
4464 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4465 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4470 tlbl = newiTempLabel (NULL);
4472 emitcode ("jnz", "%05d$", tlbl->key + 100);
4474 emitcode ("", "%05d$:", tlbl->key + 100);
4478 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4479 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4480 freeAsmop (result, NULL, ic, TRUE);
4483 /*-----------------------------------------------------------------*/
4484 /* isLiteralBit - test if lit == 2^n */
4485 /*-----------------------------------------------------------------*/
4487 isLiteralBit (unsigned long lit)
4489 unsigned long pw[32] =
4490 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4491 0x100L, 0x200L, 0x400L, 0x800L,
4492 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4493 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4494 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4495 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4496 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4499 for (idx = 0; idx < 32; idx++)
4505 /*-----------------------------------------------------------------*/
4506 /* continueIfTrue - */
4507 /*-----------------------------------------------------------------*/
4509 continueIfTrue (iCode * ic)
4512 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4516 /*-----------------------------------------------------------------*/
4518 /*-----------------------------------------------------------------*/
4520 jumpIfTrue (iCode * ic)
4523 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4527 /*-----------------------------------------------------------------*/
4528 /* jmpTrueOrFalse - */
4529 /*-----------------------------------------------------------------*/
4531 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4533 // ugly but optimized by peephole
4536 symbol *nlbl = newiTempLabel (NULL);
4537 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4538 emitcode ("", "%05d$:", tlbl->key + 100);
4539 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4540 emitcode ("", "%05d$:", nlbl->key + 100);
4544 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4545 emitcode ("", "%05d$:", tlbl->key + 100);
4550 /*-----------------------------------------------------------------*/
4551 /* genAnd - code for and */
4552 /*-----------------------------------------------------------------*/
4554 genAnd (iCode * ic, iCode * ifx)
4556 operand *left, *right, *result;
4557 int size, offset = 0;
4558 unsigned long lit = 0L;
4562 D(emitcode (";", "genAnd"));
4564 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4565 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4566 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4569 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4571 AOP_TYPE (left), AOP_TYPE (right));
4572 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4574 AOP_SIZE (left), AOP_SIZE (right));
4577 /* if left is a literal & right is not then exchange them */
4578 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4579 AOP_NEEDSACC (left))
4581 operand *tmp = right;
4586 /* if result = right then exchange them */
4587 if (sameRegs (AOP (result), AOP (right)))
4589 operand *tmp = right;
4594 /* if right is bit then exchange them */
4595 if (AOP_TYPE (right) == AOP_CRY &&
4596 AOP_TYPE (left) != AOP_CRY)
4598 operand *tmp = right;
4602 if (AOP_TYPE (right) == AOP_LIT)
4603 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4605 size = AOP_SIZE (result);
4608 // result = bit & yy;
4609 if (AOP_TYPE (left) == AOP_CRY)
4611 // c = bit & literal;
4612 if (AOP_TYPE (right) == AOP_LIT)
4616 if (size && sameRegs (AOP (result), AOP (left)))
4619 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4624 if (size && (AOP_TYPE (result) == AOP_CRY))
4626 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4629 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4634 emitcode ("clr", "c");
4639 if (AOP_TYPE (right) == AOP_CRY)
4642 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4643 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4648 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4650 emitcode ("rrc", "a");
4651 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4659 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4660 genIfxJump (ifx, "c");
4664 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4665 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4666 if ((AOP_TYPE (right) == AOP_LIT) &&
4667 (AOP_TYPE (result) == AOP_CRY) &&
4668 (AOP_TYPE (left) != AOP_CRY))
4670 int posbit = isLiteralBit (lit);
4675 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4678 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4684 sprintf (buffer, "acc.%d", posbit & 0x07);
4685 genIfxJump (ifx, buffer);
4692 symbol *tlbl = newiTempLabel (NULL);
4693 int sizel = AOP_SIZE (left);
4695 emitcode ("setb", "c");
4698 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4700 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4702 if ((posbit = isLiteralBit (bytelit)) != 0)
4703 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4706 if (bytelit != 0x0FFL)
4707 emitcode ("anl", "a,%s",
4708 aopGet (AOP (right), offset, FALSE, TRUE));
4709 emitcode ("jnz", "%05d$", tlbl->key + 100);
4714 // bit = left & literal
4717 emitcode ("clr", "c");
4718 emitcode ("", "%05d$:", tlbl->key + 100);
4720 // if(left & literal)
4724 jmpTrueOrFalse (ifx, tlbl);
4732 /* if left is same as result */
4733 if (sameRegs (AOP (result), AOP (left)))
4735 for (; size--; offset++)
4737 if (AOP_TYPE (right) == AOP_LIT)
4739 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4741 else if (bytelit == 0)
4742 aopPut (AOP (result), zero, offset);
4743 else if (IS_AOP_PREG (result))
4745 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4746 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4747 aopPut (AOP (result), "a", offset);
4750 emitcode ("anl", "%s,%s",
4751 aopGet (AOP (left), offset, FALSE, TRUE),
4752 aopGet (AOP (right), offset, FALSE, FALSE));
4756 if (AOP_TYPE (left) == AOP_ACC)
4757 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4760 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4761 if (IS_AOP_PREG (result))
4763 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4764 aopPut (AOP (result), "a", offset);
4768 emitcode ("anl", "%s,a",
4769 aopGet (AOP (left), offset, FALSE, TRUE));
4776 // left & result in different registers
4777 if (AOP_TYPE (result) == AOP_CRY)
4780 // if(size), result in bit
4781 // if(!size && ifx), conditional oper: if(left & right)
4782 symbol *tlbl = newiTempLabel (NULL);
4783 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4785 emitcode ("setb", "c");
4788 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4789 emitcode ("anl", "a,%s",
4790 aopGet (AOP (right), offset, FALSE, FALSE));
4792 if (AOP_TYPE(left)==AOP_ACC) {
4793 emitcode("mov", "b,a");
4794 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4795 emitcode("anl", "a,b");
4797 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4798 emitcode ("anl", "a,%s",
4799 aopGet (AOP (left), offset, FALSE, FALSE));
4802 emitcode ("jnz", "%05d$", tlbl->key + 100);
4808 emitcode ("", "%05d$:", tlbl->key + 100);
4812 jmpTrueOrFalse (ifx, tlbl);
4816 for (; (size--); offset++)
4819 // result = left & right
4820 if (AOP_TYPE (right) == AOP_LIT)
4822 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4824 aopPut (AOP (result),
4825 aopGet (AOP (left), offset, FALSE, FALSE),
4829 else if (bytelit == 0)
4831 aopPut (AOP (result), zero, offset);
4835 // faster than result <- left, anl result,right
4836 // and better if result is SFR
4837 if (AOP_TYPE (left) == AOP_ACC)
4838 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4841 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4842 emitcode ("anl", "a,%s",
4843 aopGet (AOP (left), offset, FALSE, FALSE));
4845 aopPut (AOP (result), "a", offset);
4851 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4852 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (result, NULL, ic, TRUE);
4856 /*-----------------------------------------------------------------*/
4857 /* genOr - code for or */
4858 /*-----------------------------------------------------------------*/
4860 genOr (iCode * ic, iCode * ifx)
4862 operand *left, *right, *result;
4863 int size, offset = 0;
4864 unsigned long lit = 0L;
4866 D(emitcode (";", "genOr"));
4868 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4869 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4870 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4873 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4875 AOP_TYPE (left), AOP_TYPE (right));
4876 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4878 AOP_SIZE (left), AOP_SIZE (right));
4881 /* if left is a literal & right is not then exchange them */
4882 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4883 AOP_NEEDSACC (left))
4885 operand *tmp = right;
4890 /* if result = right then exchange them */
4891 if (sameRegs (AOP (result), AOP (right)))
4893 operand *tmp = right;
4898 /* if right is bit then exchange them */
4899 if (AOP_TYPE (right) == AOP_CRY &&
4900 AOP_TYPE (left) != AOP_CRY)
4902 operand *tmp = right;
4906 if (AOP_TYPE (right) == AOP_LIT)
4907 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4909 size = AOP_SIZE (result);
4913 if (AOP_TYPE (left) == AOP_CRY)
4915 if (AOP_TYPE (right) == AOP_LIT)
4917 // c = bit | literal;
4920 // lit != 0 => result = 1
4921 if (AOP_TYPE (result) == AOP_CRY)
4924 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4926 continueIfTrue (ifx);
4929 emitcode ("setb", "c");
4933 // lit == 0 => result = left
4934 if (size && sameRegs (AOP (result), AOP (left)))
4936 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4941 if (AOP_TYPE (right) == AOP_CRY)
4944 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4945 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4950 symbol *tlbl = newiTempLabel (NULL);
4951 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4952 emitcode ("setb", "c");
4953 emitcode ("jb", "%s,%05d$",
4954 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4956 emitcode ("jnz", "%05d$", tlbl->key + 100);
4957 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4959 jmpTrueOrFalse (ifx, tlbl);
4965 emitcode ("", "%05d$:", tlbl->key + 100);
4974 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4975 genIfxJump (ifx, "c");
4979 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4980 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4981 if ((AOP_TYPE (right) == AOP_LIT) &&
4982 (AOP_TYPE (result) == AOP_CRY) &&
4983 (AOP_TYPE (left) != AOP_CRY))
4989 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4991 continueIfTrue (ifx);
4996 // lit = 0, result = boolean(left)
4998 emitcode ("setb", "c");
5002 symbol *tlbl = newiTempLabel (NULL);
5003 emitcode ("jnz", "%05d$", tlbl->key + 100);
5005 emitcode ("", "%05d$:", tlbl->key + 100);
5009 genIfxJump (ifx, "a");
5017 /* if left is same as result */
5018 if (sameRegs (AOP (result), AOP (left)))
5020 for (; size--; offset++)
5022 if (AOP_TYPE (right) == AOP_LIT)
5024 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5026 else if (IS_AOP_PREG (left))
5028 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5029 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5030 aopPut (AOP (result), "a", offset);
5033 emitcode ("orl", "%s,%s",
5034 aopGet (AOP (left), offset, FALSE, TRUE),
5035 aopGet (AOP (right), offset, FALSE, FALSE));
5039 if (AOP_TYPE (left) == AOP_ACC)
5040 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5043 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5044 if (IS_AOP_PREG (left))
5046 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5047 aopPut (AOP (result), "a", offset);
5050 emitcode ("orl", "%s,a",
5051 aopGet (AOP (left), offset, FALSE, TRUE));
5058 // left & result in different registers
5059 if (AOP_TYPE (result) == AOP_CRY)
5062 // if(size), result in bit
5063 // if(!size && ifx), conditional oper: if(left | right)
5064 symbol *tlbl = newiTempLabel (NULL);
5065 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5067 emitcode ("setb", "c");
5070 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5071 emitcode ("orl", "a,%s",
5072 aopGet (AOP (right), offset, FALSE, FALSE));
5074 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5075 emitcode ("orl", "a,%s",
5076 aopGet (AOP (left), offset, FALSE, FALSE));
5078 emitcode ("jnz", "%05d$", tlbl->key + 100);
5084 emitcode ("", "%05d$:", tlbl->key + 100);
5088 jmpTrueOrFalse (ifx, tlbl);
5091 for (; (size--); offset++)
5094 // result = left & right
5095 if (AOP_TYPE (right) == AOP_LIT)
5097 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5099 aopPut (AOP (result),
5100 aopGet (AOP (left), offset, FALSE, FALSE),
5105 // faster than result <- left, anl result,right
5106 // and better if result is SFR
5107 if (AOP_TYPE (left) == AOP_ACC)
5108 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5111 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5112 emitcode ("orl", "a,%s",
5113 aopGet (AOP (left), offset, FALSE, FALSE));
5115 aopPut (AOP (result), "a", offset);
5120 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5121 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122 freeAsmop (result, NULL, ic, TRUE);
5125 /*-----------------------------------------------------------------*/
5126 /* genXor - code for xclusive or */
5127 /*-----------------------------------------------------------------*/
5129 genXor (iCode * ic, iCode * ifx)
5131 operand *left, *right, *result;
5132 int size, offset = 0;
5133 unsigned long lit = 0L;
5135 D(emitcode (";", "genXor"));
5137 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5138 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5139 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5142 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5144 AOP_TYPE (left), AOP_TYPE (right));
5145 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5147 AOP_SIZE (left), AOP_SIZE (right));
5150 /* if left is a literal & right is not ||
5151 if left needs acc & right does not */
5152 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5153 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5155 operand *tmp = right;
5160 /* if result = right then exchange them */
5161 if (sameRegs (AOP (result), AOP (right)))
5163 operand *tmp = right;
5168 /* if right is bit then exchange them */
5169 if (AOP_TYPE (right) == AOP_CRY &&
5170 AOP_TYPE (left) != AOP_CRY)
5172 operand *tmp = right;
5176 if (AOP_TYPE (right) == AOP_LIT)
5177 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5179 size = AOP_SIZE (result);
5183 if (AOP_TYPE (left) == AOP_CRY)
5185 if (AOP_TYPE (right) == AOP_LIT)
5187 // c = bit & literal;
5190 // lit>>1 != 0 => result = 1
5191 if (AOP_TYPE (result) == AOP_CRY)
5194 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5196 continueIfTrue (ifx);
5199 emitcode ("setb", "c");
5206 // lit == 0, result = left
5207 if (size && sameRegs (AOP (result), AOP (left)))
5209 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5213 // lit == 1, result = not(left)
5214 if (size && sameRegs (AOP (result), AOP (left)))
5216 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5221 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5222 emitcode ("cpl", "c");
5231 symbol *tlbl = newiTempLabel (NULL);
5232 if (AOP_TYPE (right) == AOP_CRY)
5235 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5239 int sizer = AOP_SIZE (right);
5241 // if val>>1 != 0, result = 1
5242 emitcode ("setb", "c");
5245 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5247 // test the msb of the lsb
5248 emitcode ("anl", "a,#0xfe");
5249 emitcode ("jnz", "%05d$", tlbl->key + 100);
5253 emitcode ("rrc", "a");
5255 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5256 emitcode ("cpl", "c");
5257 emitcode ("", "%05d$:", (tlbl->key + 100));
5264 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5265 genIfxJump (ifx, "c");
5269 if (sameRegs (AOP (result), AOP (left)))
5271 /* if left is same as result */
5272 for (; size--; offset++)
5274 if (AOP_TYPE (right) == AOP_LIT)
5276 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5278 else if (IS_AOP_PREG (left))
5280 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5281 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5282 aopPut (AOP (result), "a", offset);
5285 emitcode ("xrl", "%s,%s",
5286 aopGet (AOP (left), offset, FALSE, TRUE),
5287 aopGet (AOP (right), offset, FALSE, FALSE));
5291 if (AOP_TYPE (left) == AOP_ACC)
5292 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5295 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5296 if (IS_AOP_PREG (left))
5298 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5299 aopPut (AOP (result), "a", offset);
5302 emitcode ("xrl", "%s,a",
5303 aopGet (AOP (left), offset, FALSE, TRUE));
5310 // left & result in different registers
5311 if (AOP_TYPE (result) == AOP_CRY)
5314 // if(size), result in bit
5315 // if(!size && ifx), conditional oper: if(left ^ right)
5316 symbol *tlbl = newiTempLabel (NULL);
5317 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5319 emitcode ("setb", "c");
5322 if ((AOP_TYPE (right) == AOP_LIT) &&
5323 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5325 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5329 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5330 emitcode ("xrl", "a,%s",
5331 aopGet (AOP (right), offset, FALSE, FALSE));
5333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5334 emitcode ("xrl", "a,%s",
5335 aopGet (AOP (left), offset, FALSE, FALSE));
5338 emitcode ("jnz", "%05d$", tlbl->key + 100);
5344 emitcode ("", "%05d$:", tlbl->key + 100);
5348 jmpTrueOrFalse (ifx, tlbl);
5351 for (; (size--); offset++)
5354 // result = left & right
5355 if (AOP_TYPE (right) == AOP_LIT)
5357 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5359 aopPut (AOP (result),
5360 aopGet (AOP (left), offset, FALSE, FALSE),
5365 // faster than result <- left, anl result,right
5366 // and better if result is SFR
5367 if (AOP_TYPE (left) == AOP_ACC)
5368 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5371 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5372 emitcode ("xrl", "a,%s",
5373 aopGet (AOP (left), offset, FALSE, TRUE));
5375 aopPut (AOP (result), "a", offset);
5380 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5381 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5382 freeAsmop (result, NULL, ic, TRUE);
5385 /*-----------------------------------------------------------------*/
5386 /* genInline - write the inline code out */
5387 /*-----------------------------------------------------------------*/
5389 genInline (iCode * ic)
5391 char *buffer, *bp, *bp1;
5393 D(emitcode (";", "genInline"));
5395 _G.inLine += (!options.asmpeep);
5397 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5398 strcpy (buffer, IC_INLINE (ic));
5400 /* emit each line as a code */
5425 /* emitcode("",buffer); */
5426 _G.inLine -= (!options.asmpeep);
5429 /*-----------------------------------------------------------------*/
5430 /* genRRC - rotate right with carry */
5431 /*-----------------------------------------------------------------*/
5435 operand *left, *result;
5436 int size, offset = 0;
5439 D(emitcode (";", "genRRC"));
5441 /* rotate right with carry */
5442 left = IC_LEFT (ic);
5443 result = IC_RESULT (ic);
5444 aopOp (left, ic, FALSE);
5445 aopOp (result, ic, FALSE);
5447 /* move it to the result */
5448 size = AOP_SIZE (result);
5450 if (size == 1) { /* special case for 1 byte */
5451 l = aopGet (AOP (left), offset, FALSE, FALSE);
5453 emitcode ("rr", "a");
5459 l = aopGet (AOP (left), offset, FALSE, FALSE);
5461 emitcode ("rrc", "a");
5462 if (AOP_SIZE (result) > 1)
5463 aopPut (AOP (result), "a", offset--);
5465 /* now we need to put the carry into the
5466 highest order byte of the result */
5467 if (AOP_SIZE (result) > 1)
5469 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5472 emitcode ("mov", "acc.7,c");
5474 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5475 freeAsmop (left, NULL, ic, TRUE);
5476 freeAsmop (result, NULL, ic, TRUE);
5479 /*-----------------------------------------------------------------*/
5480 /* genRLC - generate code for rotate left with carry */
5481 /*-----------------------------------------------------------------*/
5485 operand *left, *result;
5486 int size, offset = 0;
5489 D(emitcode (";", "genRLC"));
5491 /* rotate right with carry */
5492 left = IC_LEFT (ic);
5493 result = IC_RESULT (ic);
5494 aopOp (left, ic, FALSE);
5495 aopOp (result, ic, FALSE);
5497 /* move it to the result */
5498 size = AOP_SIZE (result);
5502 l = aopGet (AOP (left), offset, FALSE, FALSE);
5504 if (size == 0) { /* special case for 1 byte */
5508 emitcode ("add", "a,acc");
5509 if (AOP_SIZE (result) > 1)
5510 aopPut (AOP (result), "a", offset++);
5513 l = aopGet (AOP (left), offset, FALSE, FALSE);
5515 emitcode ("rlc", "a");
5516 if (AOP_SIZE (result) > 1)
5517 aopPut (AOP (result), "a", offset++);
5520 /* now we need to put the carry into the
5521 highest order byte of the result */
5522 if (AOP_SIZE (result) > 1)
5524 l = aopGet (AOP (result), 0, FALSE, FALSE);
5527 emitcode ("mov", "acc.0,c");
5529 aopPut (AOP (result), "a", 0);
5530 freeAsmop (left, NULL, ic, TRUE);
5531 freeAsmop (result, NULL, ic, TRUE);
5534 /*-----------------------------------------------------------------*/
5535 /* genGetHbit - generates code get highest order bit */
5536 /*-----------------------------------------------------------------*/
5538 genGetHbit (iCode * ic)
5540 operand *left, *result;
5542 D(emitcode (";", "genGetHbit"));
5544 left = IC_LEFT (ic);
5545 result = IC_RESULT (ic);
5546 aopOp (left, ic, FALSE);
5547 aopOp (result, ic, FALSE);
5549 /* get the highest order byte into a */
5550 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5551 if (AOP_TYPE (result) == AOP_CRY)
5553 emitcode ("rlc", "a");
5558 emitcode ("rl", "a");
5559 emitcode ("anl", "a,#0x01");
5564 freeAsmop (left, NULL, ic, TRUE);
5565 freeAsmop (result, NULL, ic, TRUE);
5568 /*-----------------------------------------------------------------*/
5569 /* AccRol - rotate left accumulator by known count */
5570 /*-----------------------------------------------------------------*/
5572 AccRol (int shCount)
5574 shCount &= 0x0007; // shCount : 0..7
5581 emitcode ("rl", "a");
5584 emitcode ("rl", "a");
5585 emitcode ("rl", "a");
5588 emitcode ("swap", "a");
5589 emitcode ("rr", "a");
5592 emitcode ("swap", "a");
5595 emitcode ("swap", "a");
5596 emitcode ("rl", "a");
5599 emitcode ("rr", "a");
5600 emitcode ("rr", "a");
5603 emitcode ("rr", "a");
5608 /*-----------------------------------------------------------------*/
5609 /* AccLsh - left shift accumulator by known count */
5610 /*-----------------------------------------------------------------*/
5612 AccLsh (int shCount)
5617 emitcode ("add", "a,acc");
5618 else if (shCount == 2)
5620 emitcode ("add", "a,acc");
5621 emitcode ("add", "a,acc");
5625 /* rotate left accumulator */
5627 /* and kill the lower order bits */
5628 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5633 /*-----------------------------------------------------------------*/
5634 /* AccRsh - right shift accumulator by known count */
5635 /*-----------------------------------------------------------------*/
5637 AccRsh (int shCount)
5644 emitcode ("rrc", "a");
5648 /* rotate right accumulator */
5649 AccRol (8 - shCount);
5650 /* and kill the higher order bits */
5651 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5656 /*-----------------------------------------------------------------*/
5657 /* AccSRsh - signed right shift accumulator by known count */
5658 /*-----------------------------------------------------------------*/
5660 AccSRsh (int shCount)
5667 emitcode ("mov", "c,acc.7");
5668 emitcode ("rrc", "a");
5670 else if (shCount == 2)
5672 emitcode ("mov", "c,acc.7");
5673 emitcode ("rrc", "a");
5674 emitcode ("mov", "c,acc.7");
5675 emitcode ("rrc", "a");
5679 tlbl = newiTempLabel (NULL);
5680 /* rotate right accumulator */
5681 AccRol (8 - shCount);
5682 /* and kill the higher order bits */
5683 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5684 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5685 emitcode ("orl", "a,#0x%02x",
5686 (unsigned char) ~SRMask[shCount]);
5687 emitcode ("", "%05d$:", tlbl->key + 100);
5692 /*-----------------------------------------------------------------*/
5693 /* shiftR1Left2Result - shift right one byte from left to result */
5694 /*-----------------------------------------------------------------*/
5696 shiftR1Left2Result (operand * left, int offl,
5697 operand * result, int offr,
5698 int shCount, int sign)
5700 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5701 /* shift right accumulator */
5706 aopPut (AOP (result), "a", offr);
5709 /*-----------------------------------------------------------------*/
5710 /* shiftL1Left2Result - shift left one byte from left to result */
5711 /*-----------------------------------------------------------------*/
5713 shiftL1Left2Result (operand * left, int offl,
5714 operand * result, int offr, int shCount)
5717 l = aopGet (AOP (left), offl, FALSE, FALSE);
5719 /* shift left accumulator */
5721 aopPut (AOP (result), "a", offr);
5724 /*-----------------------------------------------------------------*/
5725 /* movLeft2Result - move byte from left to result */
5726 /*-----------------------------------------------------------------*/
5728 movLeft2Result (operand * left, int offl,
5729 operand * result, int offr, int sign)
5732 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5734 l = aopGet (AOP (left), offl, FALSE, FALSE);
5736 if (*l == '@' && (IS_AOP_PREG (result)))
5738 emitcode ("mov", "a,%s", l);
5739 aopPut (AOP (result), "a", offr);
5744 aopPut (AOP (result), l, offr);
5747 /* MSB sign in acc.7 ! */
5748 if (getDataSize (left) == offl + 1)
5750 emitcode ("mov", "a,%s", l);
5751 aopPut (AOP (result), "a", offr);
5758 /*-----------------------------------------------------------------*/
5759 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5760 /*-----------------------------------------------------------------*/
5764 emitcode ("rrc", "a");
5765 emitcode ("xch", "a,%s", x);
5766 emitcode ("rrc", "a");
5767 emitcode ("xch", "a,%s", x);
5770 /*-----------------------------------------------------------------*/
5771 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5772 /*-----------------------------------------------------------------*/
5776 emitcode ("xch", "a,%s", x);
5777 emitcode ("rlc", "a");
5778 emitcode ("xch", "a,%s", x);
5779 emitcode ("rlc", "a");
5782 /*-----------------------------------------------------------------*/
5783 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5784 /*-----------------------------------------------------------------*/
5788 emitcode ("xch", "a,%s", x);
5789 emitcode ("add", "a,acc");
5790 emitcode ("xch", "a,%s", x);
5791 emitcode ("rlc", "a");
5794 /*-----------------------------------------------------------------*/
5795 /* AccAXLsh - left shift a:x by known count (0..7) */
5796 /*-----------------------------------------------------------------*/
5798 AccAXLsh (char *x, int shCount)
5813 case 5: // AAAAABBB:CCCCCDDD
5815 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5817 emitcode ("anl", "a,#0x%02x",
5818 SLMask[shCount]); // BBB00000:CCCCCDDD
5820 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5822 AccRol (shCount); // DDDCCCCC:BBB00000
5824 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5826 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5828 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5830 emitcode ("anl", "a,#0x%02x",
5831 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5833 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5835 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5838 case 6: // AAAAAABB:CCCCCCDD
5839 emitcode ("anl", "a,#0x%02x",
5840 SRMask[shCount]); // 000000BB:CCCCCCDD
5841 emitcode ("mov", "c,acc.0"); // c = B
5842 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5844 AccAXRrl1 (x); // BCCCCCCD:D000000B
5845 AccAXRrl1 (x); // BBCCCCCC:DD000000
5847 emitcode("rrc","a");
5848 emitcode("xch","a,%s", x);
5849 emitcode("rrc","a");
5850 emitcode("mov","c,acc.0"); //<< get correct bit
5851 emitcode("xch","a,%s", x);
5853 emitcode("rrc","a");
5854 emitcode("xch","a,%s", x);
5855 emitcode("rrc","a");
5856 emitcode("xch","a,%s", x);
5859 case 7: // a:x <<= 7
5861 emitcode ("anl", "a,#0x%02x",
5862 SRMask[shCount]); // 0000000B:CCCCCCCD
5864 emitcode ("mov", "c,acc.0"); // c = B
5866 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5868 AccAXRrl1 (x); // BCCCCCCC:D0000000
5876 /*-----------------------------------------------------------------*/
5877 /* AccAXRsh - right shift a:x known count (0..7) */
5878 /*-----------------------------------------------------------------*/
5880 AccAXRsh (char *x, int shCount)
5888 AccAXRrl1 (x); // 0->a:x
5893 AccAXRrl1 (x); // 0->a:x
5896 AccAXRrl1 (x); // 0->a:x
5901 case 5: // AAAAABBB:CCCCCDDD = a:x
5903 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5905 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5907 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5909 emitcode ("anl", "a,#0x%02x",
5910 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5912 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5914 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5916 emitcode ("anl", "a,#0x%02x",
5917 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5919 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5921 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5923 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5926 case 6: // AABBBBBB:CCDDDDDD
5928 emitcode ("mov", "c,acc.7");
5929 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5931 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5933 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5935 emitcode ("anl", "a,#0x%02x",
5936 SRMask[shCount]); // 000000AA:BBBBBBCC
5939 case 7: // ABBBBBBB:CDDDDDDD
5941 emitcode ("mov", "c,acc.7"); // c = A
5943 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5945 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5947 emitcode ("anl", "a,#0x%02x",
5948 SRMask[shCount]); // 0000000A:BBBBBBBC
5956 /*-----------------------------------------------------------------*/
5957 /* AccAXRshS - right shift signed a:x known count (0..7) */
5958 /*-----------------------------------------------------------------*/
5960 AccAXRshS (char *x, int shCount)
5968 emitcode ("mov", "c,acc.7");
5969 AccAXRrl1 (x); // s->a:x
5973 emitcode ("mov", "c,acc.7");
5974 AccAXRrl1 (x); // s->a:x
5976 emitcode ("mov", "c,acc.7");
5977 AccAXRrl1 (x); // s->a:x
5982 case 5: // AAAAABBB:CCCCCDDD = a:x
5984 tlbl = newiTempLabel (NULL);
5985 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5987 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5989 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5991 emitcode ("anl", "a,#0x%02x",
5992 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5994 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5996 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5998 emitcode ("anl", "a,#0x%02x",
5999 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6001 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6003 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6005 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6007 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6008 emitcode ("orl", "a,#0x%02x",
6009 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6011 emitcode ("", "%05d$:", tlbl->key + 100);
6012 break; // SSSSAAAA:BBBCCCCC
6014 case 6: // AABBBBBB:CCDDDDDD
6016 tlbl = newiTempLabel (NULL);
6017 emitcode ("mov", "c,acc.7");
6018 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6020 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6022 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6024 emitcode ("anl", "a,#0x%02x",
6025 SRMask[shCount]); // 000000AA:BBBBBBCC
6027 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6028 emitcode ("orl", "a,#0x%02x",
6029 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6031 emitcode ("", "%05d$:", tlbl->key + 100);
6033 case 7: // ABBBBBBB:CDDDDDDD
6035 tlbl = newiTempLabel (NULL);
6036 emitcode ("mov", "c,acc.7"); // c = A
6038 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6040 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6042 emitcode ("anl", "a,#0x%02x",
6043 SRMask[shCount]); // 0000000A:BBBBBBBC
6045 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6046 emitcode ("orl", "a,#0x%02x",
6047 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6049 emitcode ("", "%05d$:", tlbl->key + 100);
6056 /*-----------------------------------------------------------------*/
6057 /* shiftL2Left2Result - shift left two bytes from left to result */
6058 /*-----------------------------------------------------------------*/
6060 shiftL2Left2Result (operand * left, int offl,
6061 operand * result, int offr, int shCount)
6063 if (sameRegs (AOP (result), AOP (left)) &&
6064 ((offl + MSB16) == offr))
6066 /* don't crash result[offr] */
6067 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6068 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6072 movLeft2Result (left, offl, result, offr, 0);
6073 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6075 /* ax << shCount (x = lsb(result)) */
6076 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6077 aopPut (AOP (result), "a", offr + MSB16);
6081 /*-----------------------------------------------------------------*/
6082 /* shiftR2Left2Result - shift right two bytes from left to result */
6083 /*-----------------------------------------------------------------*/
6085 shiftR2Left2Result (operand * left, int offl,
6086 operand * result, int offr,
6087 int shCount, int sign)
6089 if (sameRegs (AOP (result), AOP (left)) &&
6090 ((offl + MSB16) == offr))
6092 /* don't crash result[offr] */
6093 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6094 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6098 movLeft2Result (left, offl, result, offr, 0);
6099 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6101 /* a:x >> shCount (x = lsb(result)) */
6103 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6105 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6106 if (getDataSize (result) > 1)
6107 aopPut (AOP (result), "a", offr + MSB16);
6110 /*-----------------------------------------------------------------*/
6111 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6112 /*-----------------------------------------------------------------*/
6114 shiftLLeftOrResult (operand * left, int offl,
6115 operand * result, int offr, int shCount)
6117 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6118 /* shift left accumulator */
6120 /* or with result */
6121 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6122 /* back to result */
6123 aopPut (AOP (result), "a", offr);
6126 /*-----------------------------------------------------------------*/
6127 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6128 /*-----------------------------------------------------------------*/
6130 shiftRLeftOrResult (operand * left, int offl,
6131 operand * result, int offr, int shCount)
6133 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6134 /* shift right accumulator */
6136 /* or with result */
6137 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6138 /* back to result */
6139 aopPut (AOP (result), "a", offr);
6142 /*-----------------------------------------------------------------*/
6143 /* genlshOne - left shift a one byte quantity by known count */
6144 /*-----------------------------------------------------------------*/
6146 genlshOne (operand * result, operand * left, int shCount)
6148 D(emitcode (";", "genlshOne"));
6150 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6153 /*-----------------------------------------------------------------*/
6154 /* genlshTwo - left shift two bytes by known amount != 0 */
6155 /*-----------------------------------------------------------------*/
6157 genlshTwo (operand * result, operand * left, int shCount)
6161 D(emitcode (";", "genlshTwo"));
6163 size = getDataSize (result);
6165 /* if shCount >= 8 */
6173 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6175 movLeft2Result (left, LSB, result, MSB16, 0);
6177 aopPut (AOP (result), zero, LSB);
6180 /* 1 <= shCount <= 7 */
6184 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6186 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6190 /*-----------------------------------------------------------------*/
6191 /* shiftLLong - shift left one long from left to result */
6192 /* offl = LSB or MSB16 */
6193 /*-----------------------------------------------------------------*/
6195 shiftLLong (operand * left, operand * result, int offr)
6198 int size = AOP_SIZE (result);
6200 if (size >= LSB + offr)
6202 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6204 emitcode ("add", "a,acc");
6205 if (sameRegs (AOP (left), AOP (result)) &&
6206 size >= MSB16 + offr && offr != LSB)
6207 emitcode ("xch", "a,%s",
6208 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6210 aopPut (AOP (result), "a", LSB + offr);
6213 if (size >= MSB16 + offr)
6215 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6217 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6220 emitcode ("rlc", "a");
6221 if (sameRegs (AOP (left), AOP (result)) &&
6222 size >= MSB24 + offr && offr != LSB)
6223 emitcode ("xch", "a,%s",
6224 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6226 aopPut (AOP (result), "a", MSB16 + offr);
6229 if (size >= MSB24 + offr)
6231 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6233 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6236 emitcode ("rlc", "a");
6237 if (sameRegs (AOP (left), AOP (result)) &&
6238 size >= MSB32 + offr && offr != LSB)
6239 emitcode ("xch", "a,%s",
6240 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6242 aopPut (AOP (result), "a", MSB24 + offr);
6245 if (size > MSB32 + offr)
6247 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6249 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6252 emitcode ("rlc", "a");
6253 aopPut (AOP (result), "a", MSB32 + offr);
6256 aopPut (AOP (result), zero, LSB);
6259 /*-----------------------------------------------------------------*/
6260 /* genlshFour - shift four byte by a known amount != 0 */
6261 /*-----------------------------------------------------------------*/
6263 genlshFour (operand * result, operand * left, int shCount)
6267 D(emitcode (";", "genlshFour"));
6269 size = AOP_SIZE (result);
6271 /* if shifting more that 3 bytes */
6276 /* lowest order of left goes to the highest
6277 order of the destination */
6278 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6280 movLeft2Result (left, LSB, result, MSB32, 0);
6281 aopPut (AOP (result), zero, LSB);
6282 aopPut (AOP (result), zero, MSB16);
6283 aopPut (AOP (result), zero, MSB24);
6287 /* more than two bytes */
6288 else if (shCount >= 16)
6290 /* lower order two bytes goes to higher order two bytes */
6292 /* if some more remaining */
6294 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6297 movLeft2Result (left, MSB16, result, MSB32, 0);
6298 movLeft2Result (left, LSB, result, MSB24, 0);
6300 aopPut (AOP (result), zero, MSB16);
6301 aopPut (AOP (result), zero, LSB);
6305 /* if more than 1 byte */
6306 else if (shCount >= 8)
6308 /* lower order three bytes goes to higher order three bytes */
6313 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6315 movLeft2Result (left, LSB, result, MSB16, 0);
6321 movLeft2Result (left, MSB24, result, MSB32, 0);
6322 movLeft2Result (left, MSB16, result, MSB24, 0);
6323 movLeft2Result (left, LSB, result, MSB16, 0);
6324 aopPut (AOP (result), zero, LSB);
6326 else if (shCount == 1)
6327 shiftLLong (left, result, MSB16);
6330 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6331 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6332 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6333 aopPut (AOP (result), zero, LSB);
6338 /* 1 <= shCount <= 7 */
6339 else if (shCount <= 2)
6341 shiftLLong (left, result, LSB);
6343 shiftLLong (result, result, LSB);
6345 /* 3 <= shCount <= 7, optimize */
6348 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6349 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6350 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6354 /*-----------------------------------------------------------------*/
6355 /* genLeftShiftLiteral - left shifting by known count */
6356 /*-----------------------------------------------------------------*/
6358 genLeftShiftLiteral (operand * left,
6363 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6366 D(emitcode (";", "genLeftShiftLiteral"));
6368 freeAsmop (right, NULL, ic, TRUE);
6370 aopOp (left, ic, FALSE);
6371 aopOp (result, ic, FALSE);
6373 size = getSize (operandType (result));
6376 emitcode ("; shift left ", "result %d, left %d", size,
6380 /* I suppose that the left size >= result size */
6385 movLeft2Result (left, size, result, size, 0);
6389 else if (shCount >= (size * 8))
6391 aopPut (AOP (result), zero, size);
6397 genlshOne (result, left, shCount);
6401 genlshTwo (result, left, shCount);
6405 genlshFour (result, left, shCount);
6408 fprintf(stderr, "*** ack! mystery literal shift!\n");
6412 freeAsmop (left, NULL, ic, TRUE);
6413 freeAsmop (result, NULL, ic, TRUE);
6416 /*-----------------------------------------------------------------*/
6417 /* genLeftShift - generates code for left shifting */
6418 /*-----------------------------------------------------------------*/
6420 genLeftShift (iCode * ic)
6422 operand *left, *right, *result;
6425 symbol *tlbl, *tlbl1;
6427 D(emitcode (";", "genLeftShift"));
6429 right = IC_RIGHT (ic);
6430 left = IC_LEFT (ic);
6431 result = IC_RESULT (ic);
6433 aopOp (right, ic, FALSE);
6435 /* if the shift count is known then do it
6436 as efficiently as possible */
6437 if (AOP_TYPE (right) == AOP_LIT)
6439 genLeftShiftLiteral (left, right, result, ic);
6443 /* shift count is unknown then we have to form
6444 a loop get the loop count in B : Note: we take
6445 only the lower order byte since shifting
6446 more that 32 bits make no sense anyway, ( the
6447 largest size of an object can be only 32 bits ) */
6449 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6450 emitcode ("inc", "b");
6451 freeAsmop (right, NULL, ic, TRUE);
6452 aopOp (left, ic, FALSE);
6453 aopOp (result, ic, FALSE);
6455 /* now move the left to the result if they are not the
6457 if (!sameRegs (AOP (left), AOP (result)) &&
6458 AOP_SIZE (result) > 1)
6461 size = AOP_SIZE (result);
6465 l = aopGet (AOP (left), offset, FALSE, TRUE);
6466 if (*l == '@' && (IS_AOP_PREG (result)))
6469 emitcode ("mov", "a,%s", l);
6470 aopPut (AOP (result), "a", offset);
6473 aopPut (AOP (result), l, offset);
6478 tlbl = newiTempLabel (NULL);
6479 size = AOP_SIZE (result);
6481 tlbl1 = newiTempLabel (NULL);
6483 /* if it is only one byte then */
6486 symbol *tlbl1 = newiTempLabel (NULL);
6488 l = aopGet (AOP (left), 0, FALSE, FALSE);
6490 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6491 emitcode ("", "%05d$:", tlbl->key + 100);
6492 emitcode ("add", "a,acc");
6493 emitcode ("", "%05d$:", tlbl1->key + 100);
6494 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6495 aopPut (AOP (result), "a", 0);
6499 reAdjustPreg (AOP (result));
6501 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6502 emitcode ("", "%05d$:", tlbl->key + 100);
6503 l = aopGet (AOP (result), offset, FALSE, FALSE);
6505 emitcode ("add", "a,acc");
6506 aopPut (AOP (result), "a", offset++);
6509 l = aopGet (AOP (result), offset, FALSE, FALSE);
6511 emitcode ("rlc", "a");
6512 aopPut (AOP (result), "a", offset++);
6514 reAdjustPreg (AOP (result));
6516 emitcode ("", "%05d$:", tlbl1->key + 100);
6517 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6519 freeAsmop (left, NULL, ic, TRUE);
6520 freeAsmop (result, NULL, ic, TRUE);
6523 /*-----------------------------------------------------------------*/
6524 /* genrshOne - right shift a one byte quantity by known count */
6525 /*-----------------------------------------------------------------*/
6527 genrshOne (operand * result, operand * left,
6528 int shCount, int sign)
6530 D(emitcode (";", "genrshOne"));
6532 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6535 /*-----------------------------------------------------------------*/
6536 /* genrshTwo - right shift two bytes by known amount != 0 */
6537 /*-----------------------------------------------------------------*/
6539 genrshTwo (operand * result, operand * left,
6540 int shCount, int sign)
6542 D(emitcode (";", "genrshTwo"));
6544 /* if shCount >= 8 */
6549 shiftR1Left2Result (left, MSB16, result, LSB,
6552 movLeft2Result (left, MSB16, result, LSB, sign);
6553 addSign (result, MSB16, sign);
6556 /* 1 <= shCount <= 7 */
6558 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6561 /*-----------------------------------------------------------------*/
6562 /* shiftRLong - shift right one long from left to result */
6563 /* offl = LSB or MSB16 */
6564 /*-----------------------------------------------------------------*/
6566 shiftRLong (operand * left, int offl,
6567 operand * result, int sign)
6569 int isSameRegs=sameRegs(AOP(left),AOP(result));
6571 if (isSameRegs && offl>1) {
6572 // we are in big trouble, but this shouldn't happen
6573 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6576 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6581 emitcode ("rlc", "a");
6582 emitcode ("subb", "a,acc");
6583 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6585 aopPut (AOP(result), zero, MSB32);
6590 emitcode ("clr", "c");
6592 emitcode ("mov", "c,acc.7");
6595 emitcode ("rrc", "a");
6597 if (isSameRegs && offl==MSB16) {
6598 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6600 aopPut (AOP (result), "a", MSB32);
6601 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6604 emitcode ("rrc", "a");
6605 if (isSameRegs && offl==1) {
6606 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6608 aopPut (AOP (result), "a", MSB24);
6609 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6611 emitcode ("rrc", "a");
6612 aopPut (AOP (result), "a", MSB16 - offl);
6616 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6617 emitcode ("rrc", "a");
6618 aopPut (AOP (result), "a", LSB);
6622 /*-----------------------------------------------------------------*/
6623 /* genrshFour - shift four byte by a known amount != 0 */
6624 /*-----------------------------------------------------------------*/
6626 genrshFour (operand * result, operand * left,
6627 int shCount, int sign)
6629 D(emitcode (";", "genrshFour"));
6631 /* if shifting more that 3 bytes */
6636 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6638 movLeft2Result (left, MSB32, result, LSB, sign);
6639 addSign (result, MSB16, sign);
6641 else if (shCount >= 16)
6645 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6648 movLeft2Result (left, MSB24, result, LSB, 0);
6649 movLeft2Result (left, MSB32, result, MSB16, sign);
6651 addSign (result, MSB24, sign);
6653 else if (shCount >= 8)
6657 shiftRLong (left, MSB16, result, sign);
6658 else if (shCount == 0)
6660 movLeft2Result (left, MSB16, result, LSB, 0);
6661 movLeft2Result (left, MSB24, result, MSB16, 0);
6662 movLeft2Result (left, MSB32, result, MSB24, sign);
6663 addSign (result, MSB32, sign);
6667 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6668 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6669 /* the last shift is signed */
6670 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6671 addSign (result, MSB32, sign);
6675 { /* 1 <= shCount <= 7 */
6678 shiftRLong (left, LSB, result, sign);
6680 shiftRLong (result, LSB, result, sign);
6684 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6685 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6686 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6691 /*-----------------------------------------------------------------*/
6692 /* genRightShiftLiteral - right shifting by known count */
6693 /*-----------------------------------------------------------------*/
6695 genRightShiftLiteral (operand * left,
6701 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6704 D(emitcode (";", "genRightShiftLiteral"));
6706 freeAsmop (right, NULL, ic, TRUE);
6708 aopOp (left, ic, FALSE);
6709 aopOp (result, ic, FALSE);
6712 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6716 size = getDataSize (left);
6717 /* test the LEFT size !!! */
6719 /* I suppose that the left size >= result size */
6722 size = getDataSize (result);
6724 movLeft2Result (left, size, result, size, 0);
6727 else if (shCount >= (size * 8))
6730 /* get sign in acc.7 */
6731 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6732 addSign (result, LSB, sign);
6739 genrshOne (result, left, shCount, sign);
6743 genrshTwo (result, left, shCount, sign);
6747 genrshFour (result, left, shCount, sign);
6753 freeAsmop (left, NULL, ic, TRUE);
6754 freeAsmop (result, NULL, ic, TRUE);
6758 /*-----------------------------------------------------------------*/
6759 /* genSignedRightShift - right shift of signed number */
6760 /*-----------------------------------------------------------------*/
6762 genSignedRightShift (iCode * ic)
6764 operand *right, *left, *result;
6767 symbol *tlbl, *tlbl1;
6769 D(emitcode (";", "genSignedRightShift"));
6771 /* we do it the hard way put the shift count in b
6772 and loop thru preserving the sign */
6774 right = IC_RIGHT (ic);
6775 left = IC_LEFT (ic);
6776 result = IC_RESULT (ic);
6778 aopOp (right, ic, FALSE);
6781 if (AOP_TYPE (right) == AOP_LIT)
6783 genRightShiftLiteral (left, right, result, ic, 1);
6786 /* shift count is unknown then we have to form
6787 a loop get the loop count in B : Note: we take
6788 only the lower order byte since shifting
6789 more that 32 bits make no sense anyway, ( the
6790 largest size of an object can be only 32 bits ) */
6792 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6793 emitcode ("inc", "b");
6794 freeAsmop (right, NULL, ic, TRUE);
6795 aopOp (left, ic, FALSE);
6796 aopOp (result, ic, FALSE);
6798 /* now move the left to the result if they are not the
6800 if (!sameRegs (AOP (left), AOP (result)) &&
6801 AOP_SIZE (result) > 1)
6804 size = AOP_SIZE (result);
6808 l = aopGet (AOP (left), offset, FALSE, TRUE);
6809 if (*l == '@' && IS_AOP_PREG (result))
6812 emitcode ("mov", "a,%s", l);
6813 aopPut (AOP (result), "a", offset);
6816 aopPut (AOP (result), l, offset);
6821 /* mov the highest order bit to OVR */
6822 tlbl = newiTempLabel (NULL);
6823 tlbl1 = newiTempLabel (NULL);
6825 size = AOP_SIZE (result);
6827 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6828 emitcode ("rlc", "a");
6829 emitcode ("mov", "ov,c");
6830 /* if it is only one byte then */
6833 l = aopGet (AOP (left), 0, FALSE, FALSE);
6835 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6836 emitcode ("", "%05d$:", tlbl->key + 100);
6837 emitcode ("mov", "c,ov");
6838 emitcode ("rrc", "a");
6839 emitcode ("", "%05d$:", tlbl1->key + 100);
6840 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6841 aopPut (AOP (result), "a", 0);
6845 reAdjustPreg (AOP (result));
6846 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6847 emitcode ("", "%05d$:", tlbl->key + 100);
6848 emitcode ("mov", "c,ov");
6851 l = aopGet (AOP (result), offset, FALSE, FALSE);
6853 emitcode ("rrc", "a");
6854 aopPut (AOP (result), "a", offset--);
6856 reAdjustPreg (AOP (result));
6857 emitcode ("", "%05d$:", tlbl1->key + 100);
6858 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6861 freeAsmop (left, NULL, ic, TRUE);
6862 freeAsmop (result, NULL, ic, TRUE);
6865 /*-----------------------------------------------------------------*/
6866 /* genRightShift - generate code for right shifting */
6867 /*-----------------------------------------------------------------*/
6869 genRightShift (iCode * ic)
6871 operand *right, *left, *result;
6875 symbol *tlbl, *tlbl1;
6877 D(emitcode (";", "genRightShift"));
6879 /* if signed then we do it the hard way preserve the
6880 sign bit moving it inwards */
6881 retype = getSpec (operandType (IC_RESULT (ic)));
6883 if (!SPEC_USIGN (retype))
6885 genSignedRightShift (ic);
6889 /* signed & unsigned types are treated the same : i.e. the
6890 signed is NOT propagated inwards : quoting from the
6891 ANSI - standard : "for E1 >> E2, is equivalent to division
6892 by 2**E2 if unsigned or if it has a non-negative value,
6893 otherwise the result is implementation defined ", MY definition
6894 is that the sign does not get propagated */
6896 right = IC_RIGHT (ic);
6897 left = IC_LEFT (ic);
6898 result = IC_RESULT (ic);
6900 aopOp (right, ic, FALSE);
6902 /* if the shift count is known then do it
6903 as efficiently as possible */
6904 if (AOP_TYPE (right) == AOP_LIT)
6906 genRightShiftLiteral (left, right, result, ic, 0);
6910 /* shift count is unknown then we have to form
6911 a loop get the loop count in B : Note: we take
6912 only the lower order byte since shifting
6913 more that 32 bits make no sense anyway, ( the
6914 largest size of an object can be only 32 bits ) */
6916 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6917 emitcode ("inc", "b");
6918 freeAsmop (right, NULL, ic, TRUE);
6919 aopOp (left, ic, FALSE);
6920 aopOp (result, ic, FALSE);
6922 /* now move the left to the result if they are not the
6924 if (!sameRegs (AOP (left), AOP (result)) &&
6925 AOP_SIZE (result) > 1)
6928 size = AOP_SIZE (result);
6932 l = aopGet (AOP (left), offset, FALSE, TRUE);
6933 if (*l == '@' && IS_AOP_PREG (result))
6936 emitcode ("mov", "a,%s", l);
6937 aopPut (AOP (result), "a", offset);
6940 aopPut (AOP (result), l, offset);
6945 tlbl = newiTempLabel (NULL);
6946 tlbl1 = newiTempLabel (NULL);
6947 size = AOP_SIZE (result);
6950 /* if it is only one byte then */
6953 l = aopGet (AOP (left), 0, FALSE, FALSE);
6955 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6956 emitcode ("", "%05d$:", tlbl->key + 100);
6958 emitcode ("rrc", "a");
6959 emitcode ("", "%05d$:", tlbl1->key + 100);
6960 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6961 aopPut (AOP (result), "a", 0);
6965 reAdjustPreg (AOP (result));
6966 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6967 emitcode ("", "%05d$:", tlbl->key + 100);
6971 l = aopGet (AOP (result), offset, FALSE, FALSE);
6973 emitcode ("rrc", "a");
6974 aopPut (AOP (result), "a", offset--);
6976 reAdjustPreg (AOP (result));
6978 emitcode ("", "%05d$:", tlbl1->key + 100);
6979 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6982 freeAsmop (left, NULL, ic, TRUE);
6983 freeAsmop (result, NULL, ic, TRUE);
6986 /*-----------------------------------------------------------------*/
6987 /* genUnpackBits - generates code for unpacking bits */
6988 /*-----------------------------------------------------------------*/
6990 genUnpackBits (operand * result, char *rname, int ptype)
6998 D(emitcode (";", "genUnpackBits"));
7000 etype = getSpec (operandType (result));
7001 rsize = getSize (operandType (result));
7002 /* read the first byte */
7008 emitcode ("mov", "a,@%s", rname);
7012 emitcode ("movx", "a,@%s", rname);
7016 emitcode ("movx", "a,@dptr");
7020 emitcode ("clr", "a");
7021 emitcode ("movc", "a,@a+dptr");
7025 emitcode ("lcall", "__gptrget");
7029 rlen = SPEC_BLEN (etype);
7031 /* if we have bitdisplacement then it fits */
7032 /* into this byte completely or if length is */
7033 /* less than a byte */
7034 if ((shCnt = SPEC_BSTR (etype)) ||
7035 (SPEC_BLEN (etype) <= 8))
7038 /* shift right acc */
7041 emitcode ("anl", "a,#0x%02x",
7042 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7043 aopPut (AOP (result), "a", offset++);
7047 /* bit field did not fit in a byte */
7048 aopPut (AOP (result), "a", offset++);
7057 emitcode ("inc", "%s", rname);
7058 emitcode ("mov", "a,@%s", rname);
7062 emitcode ("inc", "%s", rname);
7063 emitcode ("movx", "a,@%s", rname);
7067 emitcode ("inc", "dptr");
7068 emitcode ("movx", "a,@dptr");
7072 emitcode ("clr", "a");
7073 emitcode ("inc", "dptr");
7074 emitcode ("movc", "a,@a+dptr");
7078 emitcode ("inc", "dptr");
7079 emitcode ("lcall", "__gptrget");
7084 /* if we are done */
7088 aopPut (AOP (result), "a", offset++);
7094 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7096 aopPut (AOP (result), "a", offset++);
7104 aopPut (AOP (result), zero, offset++);
7110 /*-----------------------------------------------------------------*/
7111 /* genDataPointerGet - generates code when ptr offset is known */
7112 /*-----------------------------------------------------------------*/
7114 genDataPointerGet (operand * left,
7120 int size, offset = 0;
7122 D(emitcode (";", "genDataPointerGet"));
7124 aopOp (result, ic, TRUE);
7126 /* get the string representation of the name */
7127 l = aopGet (AOP (left), 0, FALSE, TRUE);
7128 size = AOP_SIZE (result);
7132 sprintf (buffer, "(%s + %d)", l + 1, offset);
7134 sprintf (buffer, "%s", l + 1);
7135 aopPut (AOP (result), buffer, offset++);
7138 freeAsmop (left, NULL, ic, TRUE);
7139 freeAsmop (result, NULL, ic, TRUE);
7142 /*-----------------------------------------------------------------*/
7143 /* genNearPointerGet - emitcode for near pointer fetch */
7144 /*-----------------------------------------------------------------*/
7146 genNearPointerGet (operand * left,
7154 sym_link *rtype, *retype;
7155 sym_link *ltype = operandType (left);
7158 D(emitcode (";", "genNearPointerGet"));
7160 rtype = operandType (result);
7161 retype = getSpec (rtype);
7163 aopOp (left, ic, FALSE);
7165 /* if left is rematerialisable and
7166 result is not bit variable type and
7167 the left is pointer to data space i.e
7168 lower 128 bytes of space */
7169 if (AOP_TYPE (left) == AOP_IMMD &&
7170 !IS_BITVAR (retype) &&
7171 DCL_TYPE (ltype) == POINTER)
7173 genDataPointerGet (left, result, ic);
7177 /* if the value is already in a pointer register
7178 then don't need anything more */
7179 if (!AOP_INPREG (AOP (left)))
7181 /* otherwise get a free pointer register */
7183 preg = getFreePtr (ic, &aop, FALSE);
7184 emitcode ("mov", "%s,%s",
7186 aopGet (AOP (left), 0, FALSE, TRUE));
7190 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7192 //aopOp (result, ic, FALSE);
7193 aopOp (result, ic, result?TRUE:FALSE);
7195 /* if bitfield then unpack the bits */
7196 if (IS_BITVAR (retype))
7197 genUnpackBits (result, rname, POINTER);
7200 /* we have can just get the values */
7201 int size = AOP_SIZE (result);
7206 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7209 emitcode ("mov", "a,@%s", rname);
7210 aopPut (AOP (result), "a", offset);
7214 sprintf (buffer, "@%s", rname);
7215 aopPut (AOP (result), buffer, offset);
7219 emitcode ("inc", "%s", rname);
7223 /* now some housekeeping stuff */
7224 if (aop) /* we had to allocate for this iCode */
7226 if (pi) { /* post increment present */
7227 aopPut(AOP ( left ),rname,0);
7229 freeAsmop (NULL, aop, ic, TRUE);
7233 /* we did not allocate which means left
7234 already in a pointer register, then
7235 if size > 0 && this could be used again
7236 we have to point it back to where it
7238 if ((AOP_SIZE (result) > 1 &&
7239 !OP_SYMBOL (left)->remat &&
7240 (OP_SYMBOL (left)->liveTo > ic->seq ||
7244 int size = AOP_SIZE (result) - 1;
7246 emitcode ("dec", "%s", rname);
7251 freeAsmop (left, NULL, ic, TRUE);
7252 freeAsmop (result, NULL, ic, TRUE);
7253 if (pi) pi->generated = 1;
7256 /*-----------------------------------------------------------------*/
7257 /* genPagedPointerGet - emitcode for paged pointer fetch */
7258 /*-----------------------------------------------------------------*/
7260 genPagedPointerGet (operand * left,
7268 sym_link *rtype, *retype;
7270 D(emitcode (";", "genPagedPointerGet"));
7272 rtype = operandType (result);
7273 retype = getSpec (rtype);
7275 aopOp (left, ic, FALSE);
7277 /* if the value is already in a pointer register
7278 then don't need anything more */
7279 if (!AOP_INPREG (AOP (left)))
7281 /* otherwise get a free pointer register */
7283 preg = getFreePtr (ic, &aop, FALSE);
7284 emitcode ("mov", "%s,%s",
7286 aopGet (AOP (left), 0, FALSE, TRUE));
7290 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7292 aopOp (result, ic, FALSE);
7294 /* if bitfield then unpack the bits */
7295 if (IS_BITVAR (retype))
7296 genUnpackBits (result, rname, PPOINTER);
7299 /* we have can just get the values */
7300 int size = AOP_SIZE (result);
7306 emitcode ("movx", "a,@%s", rname);
7307 aopPut (AOP (result), "a", offset);
7312 emitcode ("inc", "%s", rname);
7316 /* now some housekeeping stuff */
7317 if (aop) /* we had to allocate for this iCode */
7319 if (pi) aopPut ( AOP (left), rname, 0);
7320 freeAsmop (NULL, aop, ic, TRUE);
7324 /* we did not allocate which means left
7325 already in a pointer register, then
7326 if size > 0 && this could be used again
7327 we have to point it back to where it
7329 if ((AOP_SIZE (result) > 1 &&
7330 !OP_SYMBOL (left)->remat &&
7331 (OP_SYMBOL (left)->liveTo > ic->seq ||
7335 int size = AOP_SIZE (result) - 1;
7337 emitcode ("dec", "%s", rname);
7342 freeAsmop (left, NULL, ic, TRUE);
7343 freeAsmop (result, NULL, ic, TRUE);
7344 if (pi) pi->generated = 1;
7348 /*-----------------------------------------------------------------*/
7349 /* genFarPointerGet - gget value from far space */
7350 /*-----------------------------------------------------------------*/
7352 genFarPointerGet (operand * left,
7353 operand * result, iCode * ic, iCode * pi)
7356 sym_link *retype = getSpec (operandType (result));
7358 D(emitcode (";", "genFarPointerGet"));
7360 aopOp (left, ic, FALSE);
7362 /* if the operand is already in dptr
7363 then we do nothing else we move the value to dptr */
7364 if (AOP_TYPE (left) != AOP_STR)
7366 /* if this is remateriazable */
7367 if (AOP_TYPE (left) == AOP_IMMD)
7368 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7370 { /* we need to get it byte by byte */
7371 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7372 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7375 /* so dptr know contains the address */
7376 aopOp (result, ic, FALSE);
7378 /* if bit then unpack */
7379 if (IS_BITVAR (retype))
7380 genUnpackBits (result, "dptr", FPOINTER);
7383 size = AOP_SIZE (result);
7388 emitcode ("movx", "a,@dptr");
7389 aopPut (AOP (result), "a", offset++);
7391 emitcode ("inc", "dptr");
7395 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7396 aopPut ( AOP (left), "dpl", 0);
7397 aopPut ( AOP (left), "dph", 1);
7400 freeAsmop (left, NULL, ic, TRUE);
7401 freeAsmop (result, NULL, ic, TRUE);
7404 /*-----------------------------------------------------------------*/
7405 /* genCodePointerGet - gget value from code space */
7406 /*-----------------------------------------------------------------*/
7408 genCodePointerGet (operand * left,
7409 operand * result, iCode * ic, iCode *pi)
7412 sym_link *retype = getSpec (operandType (result));
7414 D(emitcode (";", "genCodePointerGet"));
7416 aopOp (left, ic, FALSE);
7418 /* if the operand is already in dptr
7419 then we do nothing else we move the value to dptr */
7420 if (AOP_TYPE (left) != AOP_STR)
7422 /* if this is remateriazable */
7423 if (AOP_TYPE (left) == AOP_IMMD)
7424 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7426 { /* we need to get it byte by byte */
7427 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7428 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7431 /* so dptr know contains the address */
7432 aopOp (result, ic, FALSE);
7434 /* if bit then unpack */
7435 if (IS_BITVAR (retype))
7436 genUnpackBits (result, "dptr", CPOINTER);
7439 size = AOP_SIZE (result);
7444 emitcode ("clr", "a");
7445 emitcode ("movc", "a,@a+dptr");
7446 aopPut (AOP (result), "a", offset++);
7448 emitcode ("inc", "dptr");
7452 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7453 aopPut ( AOP (left), "dpl", 0);
7454 aopPut ( AOP (left), "dph", 1);
7457 freeAsmop (left, NULL, ic, TRUE);
7458 freeAsmop (result, NULL, ic, TRUE);
7461 /*-----------------------------------------------------------------*/
7462 /* genGenPointerGet - gget value from generic pointer space */
7463 /*-----------------------------------------------------------------*/
7465 genGenPointerGet (operand * left,
7466 operand * result, iCode * ic, iCode *pi)
7469 sym_link *retype = getSpec (operandType (result));
7471 D(emitcode (";", "genGenPointerGet"));
7473 aopOp (left, ic, FALSE);
7475 /* if the operand is already in dptr
7476 then we do nothing else we move the value to dptr */
7477 if (AOP_TYPE (left) != AOP_STR)
7479 /* if this is remateriazable */
7480 if (AOP_TYPE (left) == AOP_IMMD)
7482 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7483 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7484 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7486 emitcode ("mov", "b,#%d", pointerCode (retype));
7489 { /* we need to get it byte by byte */
7490 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7491 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7492 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7495 /* so dptr know contains the address */
7496 aopOp (result, ic, FALSE);
7498 /* if bit then unpack */
7499 if (IS_BITVAR (retype))
7500 genUnpackBits (result, "dptr", GPOINTER);
7503 size = AOP_SIZE (result);
7508 emitcode ("lcall", "__gptrget");
7509 aopPut (AOP (result), "a", offset++);
7511 emitcode ("inc", "dptr");
7515 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7516 aopPut ( AOP (left), "dpl", 0);
7517 aopPut ( AOP (left), "dph", 1);
7518 aopPut ( AOP (left), "b", 2);
7521 freeAsmop (left, NULL, ic, TRUE);
7522 freeAsmop (result, NULL, ic, TRUE);
7525 /*-----------------------------------------------------------------*/
7526 /* genPointerGet - generate code for pointer get */
7527 /*-----------------------------------------------------------------*/
7529 genPointerGet (iCode * ic, iCode *pi)
7531 operand *left, *result;
7532 sym_link *type, *etype;
7535 D(emitcode (";", "genPointerGet"));
7537 left = IC_LEFT (ic);
7538 result = IC_RESULT (ic);
7540 /* depending on the type of pointer we need to
7541 move it to the correct pointer register */
7542 type = operandType (left);
7543 etype = getSpec (type);
7544 /* if left is of type of pointer then it is simple */
7545 if (IS_PTR (type) && !IS_FUNC (type->next))
7546 p_type = DCL_TYPE (type);
7549 /* we have to go by the storage class */
7550 p_type = PTR_TYPE (SPEC_OCLS (etype));
7553 /* special case when cast remat */
7554 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7555 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7556 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7557 type = type = operandType (left);
7558 p_type = DCL_TYPE (type);
7560 /* now that we have the pointer type we assign
7561 the pointer values */
7567 genNearPointerGet (left, result, ic, pi);
7571 genPagedPointerGet (left, result, ic, pi);
7575 genFarPointerGet (left, result, ic, pi);
7579 genCodePointerGet (left, result, ic, pi);
7583 genGenPointerGet (left, result, ic, pi);
7589 /*-----------------------------------------------------------------*/
7590 /* genPackBits - generates code for packed bit storage */
7591 /*-----------------------------------------------------------------*/
7593 genPackBits (sym_link * etype,
7595 char *rname, int p_type)
7603 D(emitcode (";", "genPackBits"));
7605 blen = SPEC_BLEN (etype);
7606 bstr = SPEC_BSTR (etype);
7608 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7611 /* if the bit lenth is less than or */
7612 /* it exactly fits a byte then */
7613 if (SPEC_BLEN (etype) <= 8)
7615 shCount = SPEC_BSTR (etype);
7617 /* shift left acc */
7620 if (SPEC_BLEN (etype) < 8)
7621 { /* if smaller than a byte */
7627 emitcode ("mov", "b,a");
7628 emitcode ("mov", "a,@%s", rname);
7632 emitcode ("mov", "b,a");
7633 emitcode ("movx", "a,@dptr");
7637 emitcode ("push", "b");
7638 emitcode ("push", "acc");
7639 emitcode ("lcall", "__gptrget");
7640 emitcode ("pop", "b");
7644 emitcode ("anl", "a,#0x%02x", (unsigned char)
7645 ((unsigned char) (0xFF << (blen + bstr)) |
7646 (unsigned char) (0xFF >> (8 - bstr))));
7647 emitcode ("orl", "a,b");
7648 if (p_type == GPOINTER)
7649 emitcode ("pop", "b");
7656 emitcode ("mov", "@%s,a", rname);
7660 emitcode ("movx", "@dptr,a");
7664 emitcode ("lcall", "__gptrput");
7669 if (SPEC_BLEN (etype) <= 8)
7672 emitcode ("inc", "%s", rname);
7673 rLen = SPEC_BLEN (etype);
7675 /* now generate for lengths greater than one byte */
7679 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7691 emitcode ("mov", "@%s,a", rname);
7694 emitcode ("mov", "@%s,%s", rname, l);
7699 emitcode ("movx", "@dptr,a");
7704 emitcode ("lcall", "__gptrput");
7707 emitcode ("inc", "%s", rname);
7712 /* last last was not complete */
7715 /* save the byte & read byte */
7719 emitcode ("mov", "b,a");
7720 emitcode ("mov", "a,@%s", rname);
7724 emitcode ("mov", "b,a");
7725 emitcode ("movx", "a,@dptr");
7729 emitcode ("push", "b");
7730 emitcode ("push", "acc");
7731 emitcode ("lcall", "__gptrget");
7732 emitcode ("pop", "b");
7736 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7737 emitcode ("orl", "a,b");
7740 if (p_type == GPOINTER)
7741 emitcode ("pop", "b");
7747 emitcode ("mov", "@%s,a", rname);
7751 emitcode ("movx", "@dptr,a");
7755 emitcode ("lcall", "__gptrput");
7759 /*-----------------------------------------------------------------*/
7760 /* genDataPointerSet - remat pointer to data space */
7761 /*-----------------------------------------------------------------*/
7763 genDataPointerSet (operand * right,
7767 int size, offset = 0;
7768 char *l, buffer[256];
7770 D(emitcode (";", "genDataPointerSet"));
7772 aopOp (right, ic, FALSE);
7774 l = aopGet (AOP (result), 0, FALSE, TRUE);
7775 size = AOP_SIZE (right);
7779 sprintf (buffer, "(%s + %d)", l + 1, offset);
7781 sprintf (buffer, "%s", l + 1);
7782 emitcode ("mov", "%s,%s", buffer,
7783 aopGet (AOP (right), offset++, FALSE, FALSE));
7786 freeAsmop (right, NULL, ic, TRUE);
7787 freeAsmop (result, NULL, ic, TRUE);
7790 /*-----------------------------------------------------------------*/
7791 /* genNearPointerSet - emitcode for near pointer put */
7792 /*-----------------------------------------------------------------*/
7794 genNearPointerSet (operand * right,
7802 sym_link *retype, *letype;
7803 sym_link *ptype = operandType (result);
7805 D(emitcode (";", "genNearPointerSet"));
7807 retype = getSpec (operandType (right));
7808 letype = getSpec (ptype);
7809 aopOp (result, ic, FALSE);
7811 /* if the result is rematerializable &
7812 in data space & not a bit variable */
7813 if (AOP_TYPE (result) == AOP_IMMD &&
7814 DCL_TYPE (ptype) == POINTER &&
7815 !IS_BITVAR (retype) &&
7816 !IS_BITVAR (letype))
7818 genDataPointerSet (right, result, ic);
7822 /* if the value is already in a pointer register
7823 then don't need anything more */
7824 if (!AOP_INPREG (AOP (result)))
7827 //AOP_TYPE (result) == AOP_STK
7831 // Aha, it is a pointer, just in disguise.
7832 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7835 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7836 __FILE__, __LINE__);
7841 rname++; // skip the '@'.
7846 /* otherwise get a free pointer register */
7848 preg = getFreePtr (ic, &aop, FALSE);
7849 emitcode ("mov", "%s,%s",
7851 aopGet (AOP (result), 0, FALSE, TRUE));
7857 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7860 aopOp (right, ic, FALSE);
7862 /* if bitfield then unpack the bits */
7863 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7864 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7867 /* we have can just get the values */
7868 int size = AOP_SIZE (right);
7873 l = aopGet (AOP (right), offset, FALSE, TRUE);
7877 emitcode ("mov", "@%s,a", rname);
7880 emitcode ("mov", "@%s,%s", rname, l);
7882 emitcode ("inc", "%s", rname);
7887 /* now some housekeeping stuff */
7888 if (aop) /* we had to allocate for this iCode */
7890 if (pi) aopPut (AOP (result),rname,0);
7891 freeAsmop (NULL, aop, ic, TRUE);
7895 /* we did not allocate which means left
7896 already in a pointer register, then
7897 if size > 0 && this could be used again
7898 we have to point it back to where it
7900 if ((AOP_SIZE (right) > 1 &&
7901 !OP_SYMBOL (result)->remat &&
7902 (OP_SYMBOL (result)->liveTo > ic->seq ||
7906 int size = AOP_SIZE (right) - 1;
7908 emitcode ("dec", "%s", rname);
7913 if (pi) pi->generated = 1;
7914 freeAsmop (result, NULL, ic, TRUE);
7915 freeAsmop (right, NULL, ic, TRUE);
7918 /*-----------------------------------------------------------------*/
7919 /* genPagedPointerSet - emitcode for Paged pointer put */
7920 /*-----------------------------------------------------------------*/
7922 genPagedPointerSet (operand * right,
7930 sym_link *retype, *letype;
7932 D(emitcode (";", "genPagedPointerSet"));
7934 retype = getSpec (operandType (right));
7935 letype = getSpec (operandType (result));
7937 aopOp (result, ic, FALSE);
7939 /* if the value is already in a pointer register
7940 then don't need anything more */
7941 if (!AOP_INPREG (AOP (result)))
7943 /* otherwise get a free pointer register */
7945 preg = getFreePtr (ic, &aop, FALSE);
7946 emitcode ("mov", "%s,%s",
7948 aopGet (AOP (result), 0, FALSE, TRUE));
7952 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7954 aopOp (right, ic, FALSE);
7956 /* if bitfield then unpack the bits */
7957 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7958 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7961 /* we have can just get the values */
7962 int size = AOP_SIZE (right);
7967 l = aopGet (AOP (right), offset, FALSE, TRUE);
7970 emitcode ("movx", "@%s,a", rname);
7973 emitcode ("inc", "%s", rname);
7979 /* now some housekeeping stuff */
7980 if (aop) /* we had to allocate for this iCode */
7982 if (pi) aopPut (AOP (result),rname,0);
7983 freeAsmop (NULL, aop, ic, TRUE);
7987 /* we did not allocate which means left
7988 already in a pointer register, then
7989 if size > 0 && this could be used again
7990 we have to point it back to where it
7992 if (AOP_SIZE (right) > 1 &&
7993 !OP_SYMBOL (result)->remat &&
7994 (OP_SYMBOL (result)->liveTo > ic->seq ||
7997 int size = AOP_SIZE (right) - 1;
7999 emitcode ("dec", "%s", rname);
8004 if (pi) pi->generated = 1;
8005 freeAsmop (result, NULL, ic, TRUE);
8006 freeAsmop (right, NULL, ic, TRUE);
8011 /*-----------------------------------------------------------------*/
8012 /* genFarPointerSet - set value from far space */
8013 /*-----------------------------------------------------------------*/
8015 genFarPointerSet (operand * right,
8016 operand * result, iCode * ic, iCode * pi)
8019 sym_link *retype = getSpec (operandType (right));
8020 sym_link *letype = getSpec (operandType (result));
8022 D(emitcode (";", "genFarPointerSet"));
8024 aopOp (result, ic, FALSE);
8026 /* if the operand is already in dptr
8027 then we do nothing else we move the value to dptr */
8028 if (AOP_TYPE (result) != AOP_STR)
8030 /* if this is remateriazable */
8031 if (AOP_TYPE (result) == AOP_IMMD)
8032 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8034 { /* we need to get it byte by byte */
8035 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8036 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8039 /* so dptr know contains the address */
8040 aopOp (right, ic, FALSE);
8042 /* if bit then unpack */
8043 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8044 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8047 size = AOP_SIZE (right);
8052 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8054 emitcode ("movx", "@dptr,a");
8056 emitcode ("inc", "dptr");
8059 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8060 aopPut (AOP(result),"dpl",0);
8061 aopPut (AOP(result),"dph",1);
8064 freeAsmop (result, NULL, ic, TRUE);
8065 freeAsmop (right, NULL, ic, TRUE);
8068 /*-----------------------------------------------------------------*/
8069 /* genGenPointerSet - set value from generic pointer space */
8070 /*-----------------------------------------------------------------*/
8072 genGenPointerSet (operand * right,
8073 operand * result, iCode * ic, iCode * pi)
8076 sym_link *retype = getSpec (operandType (right));
8077 sym_link *letype = getSpec (operandType (result));
8079 D(emitcode (";", "genGenPointerSet"));
8081 aopOp (result, ic, FALSE);
8083 /* if the operand is already in dptr
8084 then we do nothing else we move the value to dptr */
8085 if (AOP_TYPE (result) != AOP_STR)
8087 /* if this is remateriazable */
8088 if (AOP_TYPE (result) == AOP_IMMD)
8090 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8091 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8092 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8094 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8097 { /* we need to get it byte by byte */
8098 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8099 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8100 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8103 /* so dptr know contains the address */
8104 aopOp (right, ic, FALSE);
8106 /* if bit then unpack */
8107 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8108 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8111 size = AOP_SIZE (right);
8116 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8118 emitcode ("lcall", "__gptrput");
8120 emitcode ("inc", "dptr");
8124 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8125 aopPut (AOP(result),"dpl",0);
8126 aopPut (AOP(result),"dph",1);
8127 aopPut (AOP(result),"b",2);
8130 freeAsmop (result, NULL, ic, TRUE);
8131 freeAsmop (right, NULL, ic, TRUE);
8134 /*-----------------------------------------------------------------*/
8135 /* genPointerSet - stores the value into a pointer location */
8136 /*-----------------------------------------------------------------*/
8138 genPointerSet (iCode * ic, iCode *pi)
8140 operand *right, *result;
8141 sym_link *type, *etype;
8144 D(emitcode (";", "genPointerSet"));
8146 right = IC_RIGHT (ic);
8147 result = IC_RESULT (ic);
8149 /* depending on the type of pointer we need to
8150 move it to the correct pointer register */
8151 type = operandType (result);
8152 etype = getSpec (type);
8153 /* if left is of type of pointer then it is simple */
8154 if (IS_PTR (type) && !IS_FUNC (type->next))
8156 p_type = DCL_TYPE (type);
8160 /* we have to go by the storage class */
8161 p_type = PTR_TYPE (SPEC_OCLS (etype));
8164 /* special case when cast remat */
8165 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8166 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8167 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8168 type = type = operandType (result);
8169 p_type = DCL_TYPE (type);
8171 /* now that we have the pointer type we assign
8172 the pointer values */
8178 genNearPointerSet (right, result, ic, pi);
8182 genPagedPointerSet (right, result, ic, pi);
8186 genFarPointerSet (right, result, ic, pi);
8190 genGenPointerSet (right, result, ic, pi);
8194 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8195 "genPointerSet: illegal pointer type");
8200 /*-----------------------------------------------------------------*/
8201 /* genIfx - generate code for Ifx statement */
8202 /*-----------------------------------------------------------------*/
8204 genIfx (iCode * ic, iCode * popIc)
8206 operand *cond = IC_COND (ic);
8209 D(emitcode (";", "genIfx"));
8211 aopOp (cond, ic, FALSE);
8213 /* get the value into acc */
8214 if (AOP_TYPE (cond) != AOP_CRY)
8218 /* the result is now in the accumulator */
8219 freeAsmop (cond, NULL, ic, TRUE);
8221 /* if there was something to be popped then do it */
8225 /* if the condition is a bit variable */
8226 if (isbit && IS_ITEMP (cond) &&
8228 genIfxJump (ic, SPIL_LOC (cond)->rname);
8229 else if (isbit && !IS_ITEMP (cond))
8230 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8232 genIfxJump (ic, "a");
8237 /*-----------------------------------------------------------------*/
8238 /* genAddrOf - generates code for address of */
8239 /*-----------------------------------------------------------------*/
8241 genAddrOf (iCode * ic)
8243 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8246 D(emitcode (";", "genAddrOf"));
8248 aopOp (IC_RESULT (ic), ic, FALSE);
8250 /* if the operand is on the stack then we
8251 need to get the stack offset of this
8255 /* if it has an offset then we need to compute
8259 emitcode ("mov", "a,_bp");
8260 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8261 ((char) (sym->stack - _G.nRegsSaved)) :
8262 ((char) sym->stack)) & 0xff);
8263 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8267 /* we can just move _bp */
8268 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8270 /* fill the result with zero */
8271 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8276 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8282 /* object not on stack then we need the name */
8283 size = AOP_SIZE (IC_RESULT (ic));
8288 char s[SDCC_NAME_MAX];
8290 sprintf (s, "#(%s >> %d)",
8294 sprintf (s, "#%s", sym->rname);
8295 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8303 /*-----------------------------------------------------------------*/
8304 /* genFarFarAssign - assignment when both are in far space */
8305 /*-----------------------------------------------------------------*/
8307 genFarFarAssign (operand * result, operand * right, iCode * ic)
8309 int size = AOP_SIZE (right);
8313 D(emitcode (";", "genFarFarAssign"));
8315 /* first push the right side on to the stack */
8318 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8320 emitcode ("push", "acc");
8323 freeAsmop (right, NULL, ic, FALSE);
8324 /* now assign DPTR to result */
8325 aopOp (result, ic, FALSE);
8326 size = AOP_SIZE (result);
8329 emitcode ("pop", "acc");
8330 aopPut (AOP (result), "a", --offset);
8332 freeAsmop (result, NULL, ic, FALSE);
8336 /*-----------------------------------------------------------------*/
8337 /* genAssign - generate code for assignment */
8338 /*-----------------------------------------------------------------*/
8340 genAssign (iCode * ic)
8342 operand *result, *right;
8344 unsigned long lit = 0L;
8346 D(emitcode(";","genAssign"));
8348 result = IC_RESULT (ic);
8349 right = IC_RIGHT (ic);
8351 /* if they are the same */
8352 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8355 aopOp (right, ic, FALSE);
8357 /* special case both in far space */
8358 if (AOP_TYPE (right) == AOP_DPTR &&
8359 IS_TRUE_SYMOP (result) &&
8360 isOperandInFarSpace (result))
8363 genFarFarAssign (result, right, ic);
8367 aopOp (result, ic, TRUE);
8369 /* if they are the same registers */
8370 if (sameRegs (AOP (right), AOP (result)))
8373 /* if the result is a bit */
8374 if (AOP_TYPE (result) == AOP_CRY)
8377 /* if the right size is a literal then
8378 we know what the value is */
8379 if (AOP_TYPE (right) == AOP_LIT)
8381 if (((int) operandLitValue (right)))
8382 aopPut (AOP (result), one, 0);
8384 aopPut (AOP (result), zero, 0);
8388 /* the right is also a bit variable */
8389 if (AOP_TYPE (right) == AOP_CRY)
8391 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8392 aopPut (AOP (result), "c", 0);
8398 aopPut (AOP (result), "a", 0);
8402 /* bit variables done */
8404 size = AOP_SIZE (result);
8406 if (AOP_TYPE (right) == AOP_LIT)
8407 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8409 (AOP_TYPE (result) != AOP_REG) &&
8410 (AOP_TYPE (right) == AOP_LIT) &&
8411 !IS_FLOAT (operandType (right)) &&
8414 emitcode ("clr", "a");
8417 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8418 aopPut (AOP (result), "a", size);
8420 aopPut (AOP (result),
8421 aopGet (AOP (right), size, FALSE, FALSE),
8429 aopPut (AOP (result),
8430 aopGet (AOP (right), offset, FALSE, FALSE),
8437 freeAsmop (right, NULL, ic, TRUE);
8438 freeAsmop (result, NULL, ic, TRUE);
8441 /*-----------------------------------------------------------------*/
8442 /* genJumpTab - genrates code for jump table */
8443 /*-----------------------------------------------------------------*/
8445 genJumpTab (iCode * ic)
8450 D(emitcode (";", "genJumpTab"));
8452 aopOp (IC_JTCOND (ic), ic, FALSE);
8453 /* get the condition into accumulator */
8454 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8456 /* multiply by three */
8457 emitcode ("add", "a,acc");
8458 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8459 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8461 jtab = newiTempLabel (NULL);
8462 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8463 emitcode ("jmp", "@a+dptr");
8464 emitcode ("", "%05d$:", jtab->key + 100);
8465 /* now generate the jump labels */
8466 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8467 jtab = setNextItem (IC_JTLABELS (ic)))
8468 emitcode ("ljmp", "%05d$", jtab->key + 100);
8472 /*-----------------------------------------------------------------*/
8473 /* genCast - gen code for casting */
8474 /*-----------------------------------------------------------------*/
8476 genCast (iCode * ic)
8478 operand *result = IC_RESULT (ic);
8479 sym_link *ctype = operandType (IC_LEFT (ic));
8480 sym_link *rtype = operandType (IC_RIGHT (ic));
8481 operand *right = IC_RIGHT (ic);
8484 D(emitcode(";", "genCast"));
8486 /* if they are equivalent then do nothing */
8487 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8490 aopOp (right, ic, FALSE);
8491 aopOp (result, ic, FALSE);
8493 /* if the result is a bit */
8494 if (IS_BITVAR(OP_SYMBOL(result)->type))
8496 /* if the right size is a literal then
8497 we know what the value is */
8498 if (AOP_TYPE (right) == AOP_LIT)
8500 if (((int) operandLitValue (right)))
8501 aopPut (AOP (result), one, 0);
8503 aopPut (AOP (result), zero, 0);
8508 /* the right is also a bit variable */
8509 if (AOP_TYPE (right) == AOP_CRY)
8511 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8512 aopPut (AOP (result), "c", 0);
8518 aopPut (AOP (result), "a", 0);
8522 /* if they are the same size : or less */
8523 if (AOP_SIZE (result) <= AOP_SIZE (right))
8526 /* if they are in the same place */
8527 if (sameRegs (AOP (right), AOP (result)))
8530 /* if they in different places then copy */
8531 size = AOP_SIZE (result);
8535 aopPut (AOP (result),
8536 aopGet (AOP (right), offset, FALSE, FALSE),
8544 /* if the result is of type pointer */
8549 sym_link *type = operandType (right);
8550 sym_link *etype = getSpec (type);
8552 /* pointer to generic pointer */
8553 if (IS_GENPTR (ctype))
8558 p_type = DCL_TYPE (type);
8561 if (SPEC_SCLS(etype)==S_REGISTER) {
8562 // let's assume it is a generic pointer
8565 /* we have to go by the storage class */
8566 p_type = PTR_TYPE (SPEC_OCLS (etype));
8570 /* the first two bytes are known */
8571 size = GPTRSIZE - 1;
8575 aopPut (AOP (result),
8576 aopGet (AOP (right), offset, FALSE, FALSE),
8580 /* the last byte depending on type */
8596 case PPOINTER: // what the fck is this?
8601 /* this should never happen */
8602 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8603 "got unknown pointer type");
8606 aopPut (AOP (result), l, GPTRSIZE - 1);
8610 /* just copy the pointers */
8611 size = AOP_SIZE (result);
8615 aopPut (AOP (result),
8616 aopGet (AOP (right), offset, FALSE, FALSE),
8623 /* so we now know that the size of destination is greater
8624 than the size of the source */
8625 /* we move to result for the size of source */
8626 size = AOP_SIZE (right);
8630 aopPut (AOP (result),
8631 aopGet (AOP (right), offset, FALSE, FALSE),
8636 /* now depending on the sign of the source && destination */
8637 size = AOP_SIZE (result) - AOP_SIZE (right);
8638 /* if unsigned or not an integral type */
8639 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8642 aopPut (AOP (result), zero, offset++);
8646 /* we need to extend the sign :{ */
8647 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8650 emitcode ("rlc", "a");
8651 emitcode ("subb", "a,acc");
8653 aopPut (AOP (result), "a", offset++);
8656 /* we are done hurray !!!! */
8659 freeAsmop (right, NULL, ic, TRUE);
8660 freeAsmop (result, NULL, ic, TRUE);
8664 /*-----------------------------------------------------------------*/
8665 /* genDjnz - generate decrement & jump if not zero instrucion */
8666 /*-----------------------------------------------------------------*/
8668 genDjnz (iCode * ic, iCode * ifx)
8674 D(emitcode (";", "genDjnz"));
8676 /* if the if condition has a false label
8677 then we cannot save */
8681 /* if the minus is not of the form
8683 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8684 !IS_OP_LITERAL (IC_RIGHT (ic)))
8687 if (operandLitValue (IC_RIGHT (ic)) != 1)
8690 /* if the size of this greater than one then no
8692 if (getSize (operandType (IC_RESULT (ic))) > 1)
8695 /* otherwise we can save BIG */
8696 lbl = newiTempLabel (NULL);
8697 lbl1 = newiTempLabel (NULL);
8699 aopOp (IC_RESULT (ic), ic, FALSE);
8701 if (AOP_NEEDSACC(IC_RESULT(ic)))
8703 /* If the result is accessed indirectly via
8704 * the accumulator, we must explicitly write
8705 * it back after the decrement.
8707 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8709 if (strcmp(rByte, "a"))
8711 /* Something is hopelessly wrong */
8712 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8713 __FILE__, __LINE__);
8714 /* We can just give up; the generated code will be inefficient,
8717 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8720 emitcode ("dec", "%s", rByte);
8721 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8722 emitcode ("jnz", "%05d$", lbl->key + 100);
8724 else if (IS_AOP_PREG (IC_RESULT (ic)))
8726 emitcode ("dec", "%s",
8727 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8728 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8729 emitcode ("jnz", "%05d$", lbl->key + 100);
8733 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8736 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8737 emitcode ("", "%05d$:", lbl->key + 100);
8738 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8739 emitcode ("", "%05d$:", lbl1->key + 100);
8741 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8746 /*-----------------------------------------------------------------*/
8747 /* genReceive - generate code for a receive iCode */
8748 /*-----------------------------------------------------------------*/
8750 genReceive (iCode * ic)
8752 int size = getSize (operandType (IC_RESULT (ic)));
8754 D(emitcode (";", "genReceive"));
8756 if (ic->argreg == 1) { /* first parameter */
8757 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8758 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8759 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8761 offset = fReturnSizeMCS51 - size;
8763 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8764 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8767 aopOp (IC_RESULT (ic), ic, FALSE);
8768 size = AOP_SIZE (IC_RESULT (ic));
8771 emitcode ("pop", "acc");
8772 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8777 aopOp (IC_RESULT (ic), ic, FALSE);
8779 assignResultValue (IC_RESULT (ic));
8781 } else { /* second receive onwards */
8783 aopOp (IC_RESULT (ic), ic, FALSE);
8784 rb1off = ic->argreg;
8786 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8789 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8792 /*-----------------------------------------------------------------*/
8793 /* gen51Code - generate code for 8051 based controllers */
8794 /*-----------------------------------------------------------------*/
8796 gen51Code (iCode * lic)
8801 lineHead = lineCurr = NULL;
8803 /* print the allocation information */
8805 printAllocInfo (currFunc, codeOutFile);
8806 /* if debug information required */
8807 if (options.debug && currFunc)
8809 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8811 if (IS_STATIC (currFunc->etype))
8812 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8814 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8817 /* stack pointer name */
8818 if (options.useXstack)
8824 for (ic = lic; ic; ic = ic->next)
8827 if (ic->lineno && cln != ic->lineno)
8832 emitcode ("", "C$%s$%d$%d$%d ==.",
8833 FileBaseName (ic->filename), ic->lineno,
8834 ic->level, ic->block);
8837 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
8838 printCLine(ic->filename, ic->lineno));
8841 /* if the result is marked as
8842 spilt and rematerializable or code for
8843 this has already been generated then
8845 if (resultRemat (ic) || ic->generated)
8848 /* depending on the operation */
8868 /* IPOP happens only when trying to restore a
8869 spilt live range, if there is an ifx statement
8870 following this pop then the if statement might
8871 be using some of the registers being popped which
8872 would destory the contents of the register so
8873 we need to check for this condition and handle it */
8875 ic->next->op == IFX &&
8876 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8877 genIfx (ic->next, ic);
8895 genEndFunction (ic);
8915 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8932 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8936 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8943 /* note these two are xlated by algebraic equivalence
8944 during parsing SDCC.y */
8945 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8946 "got '>=' or '<=' shouldn't have come here");
8950 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8962 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8966 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8970 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8997 case GET_VALUE_AT_ADDRESS:
8998 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9002 if (POINTER_SET (ic))
9003 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9029 addSet (&_G.sendSet, ic);
9038 /* now we are ready to call the
9039 peep hole optimizer */
9040 if (!options.nopeep)
9041 peepHole (&lineHead);
9043 /* now do the actual printing */
9044 printLine (lineHead, codeOutFile);