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 extern int mcs51_ptrRegReq;
97 extern int mcs51_nRegs;
98 extern FILE *codeOutFile;
99 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 sprintf (lb, "%s\t", inst);
140 sprintf (lb, "%s", inst);
141 vsprintf (lb + (strlen (lb)), fmt, ap);
144 vsprintf (lb, fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
386 val += (int) operandLitValue (IC_RIGHT (ic));
387 else if (ic->op == '-')
388 val -= (int) operandLitValue (IC_RIGHT (ic));
389 else if (IS_CAST_ICODE(ic)) {
390 sym_link *from_type = operandType(IC_RIGHT(ic));
391 aop->aopu.aop_immd.from_cast_remat = 1;
392 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
393 ptr_type = DCL_TYPE(from_type);
394 if (ptr_type == IPOINTER) {
401 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
405 sprintf (buffer, "(%s %c 0x%04x)",
406 OP_SYMBOL (IC_LEFT (ic))->rname,
407 val >= 0 ? '+' : '-',
410 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
413 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
414 /* set immd2 field if required */
415 if (aop->aopu.aop_immd.from_cast_remat) {
416 sprintf(buffer,"#0x%02x",ptr_type);
417 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
418 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
424 /*-----------------------------------------------------------------*/
425 /* regsInCommon - two operands have some registers in common */
426 /*-----------------------------------------------------------------*/
428 regsInCommon (operand * op1, operand * op2)
433 /* if they have registers in common */
434 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
437 sym1 = OP_SYMBOL (op1);
438 sym2 = OP_SYMBOL (op2);
440 if (sym1->nRegs == 0 || sym2->nRegs == 0)
443 for (i = 0; i < sym1->nRegs; i++)
449 for (j = 0; j < sym2->nRegs; j++)
454 if (sym2->regs[j] == sym1->regs[i])
462 /*-----------------------------------------------------------------*/
463 /* operandsEqu - equivalent */
464 /*-----------------------------------------------------------------*/
466 operandsEqu (operand * op1, operand * op2)
470 /* if they not symbols */
471 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
474 sym1 = OP_SYMBOL (op1);
475 sym2 = OP_SYMBOL (op2);
477 /* if both are itemps & one is spilt
478 and the other is not then false */
479 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
480 sym1->isspilt != sym2->isspilt)
483 /* if they are the same */
487 if (strcmp (sym1->rname, sym2->rname) == 0)
491 /* if left is a tmp & right is not */
492 if (IS_ITEMP (op1) &&
495 (sym1->usl.spillLoc == sym2))
498 if (IS_ITEMP (op2) &&
502 (sym2->usl.spillLoc == sym1))
508 /*-----------------------------------------------------------------*/
509 /* sameRegs - two asmops have the same registers */
510 /*-----------------------------------------------------------------*/
512 sameRegs (asmop * aop1, asmop * aop2)
519 if (aop1->type != AOP_REG ||
520 aop2->type != AOP_REG)
523 if (aop1->size != aop2->size)
526 for (i = 0; i < aop1->size; i++)
527 if (aop1->aopu.aop_reg[i] !=
528 aop2->aopu.aop_reg[i])
534 /*-----------------------------------------------------------------*/
535 /* aopOp - allocates an asmop for an operand : */
536 /*-----------------------------------------------------------------*/
538 aopOp (operand * op, iCode * ic, bool result)
547 /* if this a literal */
548 if (IS_OP_LITERAL (op))
550 op->aop = aop = newAsmop (AOP_LIT);
551 aop->aopu.aop_lit = op->operand.valOperand;
552 aop->size = getSize (operandType (op));
556 /* if already has a asmop then continue */
560 /* if the underlying symbol has a aop */
561 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
563 op->aop = OP_SYMBOL (op)->aop;
567 /* if this is a true symbol */
568 if (IS_TRUE_SYMOP (op))
570 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
574 /* this is a temporary : this has
580 e) can be a return use only */
582 sym = OP_SYMBOL (op);
584 /* if the type is a conditional */
585 if (sym->regType == REG_CND)
587 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
592 /* if it is spilt then two situations
594 b) has a spill location */
595 if (sym->isspilt || sym->nRegs == 0)
598 /* rematerialize it NOW */
601 sym->aop = op->aop = aop =
603 aop->size = getSize (sym->type);
610 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
611 aop->size = getSize (sym->type);
612 for (i = 0; i < 2; i++)
613 aop->aopu.aop_str[i] = accUse[i];
621 aop = op->aop = sym->aop = newAsmop (AOP_STR);
622 aop->size = getSize (sym->type);
623 for (i = 0; i < fReturnSizeMCS51; i++)
624 aop->aopu.aop_str[i] = fReturn[i];
628 /* else spill location */
629 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
630 /* force a new aop if sizes differ */
631 sym->usl.spillLoc->aop = NULL;
633 sym->aop = op->aop = aop =
634 aopForSym (ic, sym->usl.spillLoc, result);
635 aop->size = getSize (sym->type);
639 /* must be in a register */
640 sym->aop = op->aop = aop = newAsmop (AOP_REG);
641 aop->size = sym->nRegs;
642 for (i = 0; i < sym->nRegs; i++)
643 aop->aopu.aop_reg[i] = sym->regs[i];
646 /*-----------------------------------------------------------------*/
647 /* freeAsmop - free up the asmop given to an operand */
648 /*----------------------------------------------------------------*/
650 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
667 /* depending on the asmop type only three cases need work AOP_RO
668 , AOP_R1 && AOP_STK */
676 emitcode ("pop", "ar0");
680 bitVectUnSetBit (ic->rUsed, R0_IDX);
688 emitcode ("pop", "ar1");
692 bitVectUnSetBit (ic->rUsed, R1_IDX);
698 int stk = aop->aopu.aop_stk + aop->size;
699 bitVectUnSetBit (ic->rUsed, R0_IDX);
700 bitVectUnSetBit (ic->rUsed, R1_IDX);
702 getFreePtr (ic, &aop, FALSE);
706 emitcode ("mov", "a,_bp");
707 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
708 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
712 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
717 emitcode ("pop", "acc");
718 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
721 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
724 freeAsmop (op, NULL, ic, TRUE);
727 emitcode ("pop", "ar0");
733 emitcode ("pop", "ar1");
740 /* all other cases just dealloc */
746 OP_SYMBOL (op)->aop = NULL;
747 /* if the symbol has a spill */
749 SPIL_LOC (op)->aop = NULL;
754 /*-----------------------------------------------------------------*/
755 /* aopGet - for fetching value of the aop */
756 /*-----------------------------------------------------------------*/
758 aopGet (asmop * aop, int offset, bool bit16, bool dname)
763 /* offset is greater than
765 if (offset > (aop->size - 1) &&
766 aop->type != AOP_LIT)
769 /* depending on type */
775 /* if we need to increment it */
776 while (offset > aop->coff)
778 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
782 while (offset < aop->coff)
784 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
791 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
792 return (dname ? "acc" : "a");
794 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
795 rs = Safe_calloc (1, strlen (s) + 1);
800 while (offset > aop->coff)
802 emitcode ("inc", "dptr");
806 while (offset < aop->coff)
808 emitcode ("lcall", "__decdptr");
815 emitcode ("clr", "a");
816 emitcode ("movc", "a,@a+dptr");
820 emitcode ("movx", "a,@dptr");
822 return (dname ? "acc" : "a");
826 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
827 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
829 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
831 sprintf (s, "#(%s >> %d)",
832 aop->aopu.aop_immd.aop_immd1,
836 aop->aopu.aop_immd.aop_immd1);
837 rs = Safe_calloc (1, strlen (s) + 1);
843 sprintf (s, "(%s + %d)",
847 sprintf (s, "%s", aop->aopu.aop_dir);
848 rs = Safe_calloc (1, strlen (s) + 1);
854 return aop->aopu.aop_reg[offset]->dname;
856 return aop->aopu.aop_reg[offset]->name;
859 emitcode ("clr", "a");
860 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
861 emitcode ("rlc", "a");
862 return (dname ? "acc" : "a");
865 if (!offset && dname)
867 return aop->aopu.aop_str[offset];
870 return aopLiteral (aop->aopu.aop_lit, offset);
874 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
878 return aop->aopu.aop_str[offset];
882 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
883 "aopget got unsupported aop->type");
886 /*-----------------------------------------------------------------*/
887 /* aopPut - puts a string for a aop */
888 /*-----------------------------------------------------------------*/
890 aopPut (asmop * aop, char *s, int offset)
894 if (aop->size && offset > (aop->size - 1))
896 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
897 "aopPut got offset > aop->size");
901 /* will assign value to value */
902 /* depending on where it is ofcourse */
907 sprintf (d, "(%s + %d)",
908 aop->aopu.aop_dir, offset);
910 sprintf (d, "%s", aop->aopu.aop_dir);
913 emitcode ("mov", "%s,%s", d, s);
918 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
919 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
922 strcmp (s, "r0") == 0 ||
923 strcmp (s, "r1") == 0 ||
924 strcmp (s, "r2") == 0 ||
925 strcmp (s, "r3") == 0 ||
926 strcmp (s, "r4") == 0 ||
927 strcmp (s, "r5") == 0 ||
928 strcmp (s, "r6") == 0 ||
929 strcmp (s, "r7") == 0)
930 emitcode ("mov", "%s,%s",
931 aop->aopu.aop_reg[offset]->dname, s);
933 emitcode ("mov", "%s,%s",
934 aop->aopu.aop_reg[offset]->name, s);
941 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
942 "aopPut writting to code space");
946 while (offset > aop->coff)
949 emitcode ("inc", "dptr");
952 while (offset < aop->coff)
955 emitcode ("lcall", "__decdptr");
960 /* if not in accumulater */
963 emitcode ("movx", "@dptr,a");
968 while (offset > aop->coff)
971 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
973 while (offset < aop->coff)
976 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
983 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
989 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
991 else if (strcmp (s, "r0") == 0 ||
992 strcmp (s, "r1") == 0 ||
993 strcmp (s, "r2") == 0 ||
994 strcmp (s, "r3") == 0 ||
995 strcmp (s, "r4") == 0 ||
996 strcmp (s, "r5") == 0 ||
997 strcmp (s, "r6") == 0 ||
998 strcmp (s, "r7") == 0)
1001 sprintf (buffer, "a%s", s);
1002 emitcode ("mov", "@%s,%s",
1003 aop->aopu.aop_ptr->name, buffer);
1006 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1011 if (strcmp (s, "a") == 0)
1012 emitcode ("push", "acc");
1016 emitcode ("push", "acc");
1018 emitcode ("push", s);
1024 /* if bit variable */
1025 if (!aop->aopu.aop_dir)
1027 emitcode ("clr", "a");
1028 emitcode ("rlc", "a");
1033 emitcode ("clr", "%s", aop->aopu.aop_dir);
1035 emitcode ("setb", "%s", aop->aopu.aop_dir);
1036 else if (!strcmp (s, "c"))
1037 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1040 if (strcmp (s, "a"))
1045 symbol *lbl = newiTempLabel (NULL);
1046 emitcode ("clr", "c");
1047 emitcode ("jz", "%05d$", lbl->key + 100);
1048 emitcode ("cpl", "c");
1049 emitcode ("", "%05d$:", lbl->key + 100);
1050 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1058 if (strcmp (aop->aopu.aop_str[offset], s))
1059 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1064 if (!offset && (strcmp (s, "acc") == 0))
1067 if (strcmp (aop->aopu.aop_str[offset], s))
1068 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1072 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1073 "aopPut got unsupported aop->type");
1081 /*-----------------------------------------------------------------*/
1082 /* pointToEnd :- points to the last byte of the operand */
1083 /*-----------------------------------------------------------------*/
1085 pointToEnd (asmop * aop)
1091 aop->coff = count = (aop->size - 1);
1097 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1101 emitcode ("inc", "dptr");
1108 /*-----------------------------------------------------------------*/
1109 /* reAdjustPreg - points a register back to where it should */
1110 /*-----------------------------------------------------------------*/
1112 reAdjustPreg (asmop * aop)
1114 if ((aop->coff==0) || aop->size <= 1)
1122 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1127 emitcode ("lcall", "__decdptr");
1134 #define AOP(op) op->aop
1135 #define AOP_TYPE(op) AOP(op)->type
1136 #define AOP_SIZE(op) AOP(op)->size
1137 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1138 AOP_TYPE(x) == AOP_R0))
1140 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1141 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1143 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1144 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1145 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1147 /*-----------------------------------------------------------------*/
1148 /* genNotFloat - generates not for float operations */
1149 /*-----------------------------------------------------------------*/
1151 genNotFloat (operand * op, operand * res)
1157 D(emitcode (";", "genNotFloat"));
1159 /* we will put 127 in the first byte of
1161 aopPut (AOP (res), "#127", 0);
1162 size = AOP_SIZE (op) - 1;
1165 l = aopGet (op->aop, offset++, FALSE, FALSE);
1170 emitcode ("orl", "a,%s",
1172 offset++, FALSE, FALSE));
1175 tlbl = newiTempLabel (NULL);
1176 aopPut (res->aop, one, 1);
1177 emitcode ("jz", "%05d$", (tlbl->key + 100));
1178 aopPut (res->aop, zero, 1);
1179 emitcode ("", "%05d$:", (tlbl->key + 100));
1181 size = res->aop->size - 2;
1183 /* put zeros in the rest */
1185 aopPut (res->aop, zero, offset++);
1188 /*-----------------------------------------------------------------*/
1189 /* opIsGptr: returns non-zero if the passed operand is */
1190 /* a generic pointer type. */
1191 /*-----------------------------------------------------------------*/
1193 opIsGptr (operand * op)
1195 sym_link *type = operandType (op);
1197 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1204 /*-----------------------------------------------------------------*/
1205 /* getDataSize - get the operand data size */
1206 /*-----------------------------------------------------------------*/
1208 getDataSize (operand * op)
1211 size = AOP_SIZE (op);
1212 if (size == GPTRSIZE)
1214 sym_link *type = operandType (op);
1215 if (IS_GENPTR (type))
1217 /* generic pointer; arithmetic operations
1218 * should ignore the high byte (pointer type).
1226 /*-----------------------------------------------------------------*/
1227 /* outAcc - output Acc */
1228 /*-----------------------------------------------------------------*/
1230 outAcc (operand * result)
1233 size = getDataSize (result);
1236 aopPut (AOP (result), "a", 0);
1239 /* unsigned or positive */
1242 aopPut (AOP (result), zero, offset++);
1247 /*-----------------------------------------------------------------*/
1248 /* outBitC - output a bit C */
1249 /*-----------------------------------------------------------------*/
1251 outBitC (operand * result)
1253 /* if the result is bit */
1254 if (AOP_TYPE (result) == AOP_CRY)
1255 aopPut (AOP (result), "c", 0);
1258 emitcode ("clr", "a");
1259 emitcode ("rlc", "a");
1264 /*-----------------------------------------------------------------*/
1265 /* toBoolean - emit code for orl a,operator(sizeop) */
1266 /*-----------------------------------------------------------------*/
1268 toBoolean (operand * oper)
1270 int size = AOP_SIZE (oper) - 1;
1272 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1274 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1278 /*-----------------------------------------------------------------*/
1279 /* genNot - generate code for ! operation */
1280 /*-----------------------------------------------------------------*/
1285 sym_link *optype = operandType (IC_LEFT (ic));
1287 D(emitcode (";", "genNot"));
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if in bit space then a special case */
1294 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1296 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1297 emitcode ("cpl", "c");
1298 outBitC (IC_RESULT (ic));
1302 /* if type float then do float */
1303 if (IS_FLOAT (optype))
1305 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1309 toBoolean (IC_LEFT (ic));
1311 tlbl = newiTempLabel (NULL);
1312 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1313 emitcode ("", "%05d$:", tlbl->key + 100);
1314 outBitC (IC_RESULT (ic));
1317 /* release the aops */
1318 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1319 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1323 /*-----------------------------------------------------------------*/
1324 /* genCpl - generate code for complement */
1325 /*-----------------------------------------------------------------*/
1333 D(emitcode (";", "genCpl"));
1335 /* assign asmOps to operand & result */
1336 aopOp (IC_LEFT (ic), ic, FALSE);
1337 aopOp (IC_RESULT (ic), ic, TRUE);
1339 /* special case if in bit space */
1340 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1341 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1342 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1343 emitcode ("cpl", "c");
1344 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1347 tlbl=newiTempLabel(NULL);
1348 emitcode ("cjne", "%s,#0x01,%05d$",
1349 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1350 emitcode ("", "%05d$:", tlbl->key+100);
1351 outBitC (IC_RESULT(ic));
1355 size = AOP_SIZE (IC_RESULT (ic));
1358 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1360 emitcode ("cpl", "a");
1361 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1366 /* release the aops */
1367 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1368 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1371 /*-----------------------------------------------------------------*/
1372 /* genUminusFloat - unary minus for floating points */
1373 /*-----------------------------------------------------------------*/
1375 genUminusFloat (operand * op, operand * result)
1377 int size, offset = 0;
1380 D(emitcode (";", "genUminusFloat"));
1382 /* for this we just need to flip the
1383 first it then copy the rest in place */
1384 size = AOP_SIZE (op) - 1;
1385 l = aopGet (AOP (op), 3, FALSE, FALSE);
1389 emitcode ("cpl", "acc.7");
1390 aopPut (AOP (result), "a", 3);
1394 aopPut (AOP (result),
1395 aopGet (AOP (op), offset, FALSE, FALSE),
1401 /*-----------------------------------------------------------------*/
1402 /* genUminus - unary minus code generation */
1403 /*-----------------------------------------------------------------*/
1405 genUminus (iCode * ic)
1408 sym_link *optype, *rtype;
1411 D(emitcode (";", "genUminus"));
1414 aopOp (IC_LEFT (ic), ic, FALSE);
1415 aopOp (IC_RESULT (ic), ic, TRUE);
1417 /* if both in bit space then special
1419 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1420 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1423 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1424 emitcode ("cpl", "c");
1425 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1429 optype = operandType (IC_LEFT (ic));
1430 rtype = operandType (IC_RESULT (ic));
1432 /* if float then do float stuff */
1433 if (IS_FLOAT (optype))
1435 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1439 /* otherwise subtract from zero */
1440 size = AOP_SIZE (IC_LEFT (ic));
1445 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1446 if (!strcmp (l, "a"))
1450 emitcode ("cpl", "a");
1451 emitcode ("addc", "a,#0");
1457 emitcode ("clr", "a");
1458 emitcode ("subb", "a,%s", l);
1460 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1463 /* if any remaining bytes in the result */
1464 /* we just need to propagate the sign */
1465 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1467 emitcode ("rlc", "a");
1468 emitcode ("subb", "a,acc");
1470 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1474 /* release the aops */
1475 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1479 /*-----------------------------------------------------------------*/
1480 /* saveRegisters - will look for a call and save the registers */
1481 /*-----------------------------------------------------------------*/
1483 saveRegisters (iCode * lic)
1490 for (ic = lic; ic; ic = ic->next)
1491 if (ic->op == CALL || ic->op == PCALL)
1496 fprintf (stderr, "found parameter push with no function call\n");
1500 /* if the registers have been saved already or don't need to be then
1502 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1503 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1506 /* safe the registers in use at this time but skip the
1507 ones for the result */
1508 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1509 mcs51_rUmaskForOp (IC_RESULT(ic)));
1512 if (options.useXstack)
1514 if (bitVectBitValue (rsave, R0_IDX))
1515 emitcode ("mov", "b,r0");
1516 emitcode ("mov", "r0,%s", spname);
1517 for (i = 0; i < mcs51_nRegs; i++)
1519 if (bitVectBitValue (rsave, i))
1522 emitcode ("mov", "a,b");
1524 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1525 emitcode ("movx", "@r0,a");
1526 emitcode ("inc", "r0");
1529 emitcode ("mov", "%s,r0", spname);
1530 if (bitVectBitValue (rsave, R0_IDX))
1531 emitcode ("mov", "r0,b");
1534 for (i = 0; i < mcs51_nRegs; i++)
1536 if (bitVectBitValue (rsave, i))
1537 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1541 /*-----------------------------------------------------------------*/
1542 /* unsaveRegisters - pop the pushed registers */
1543 /*-----------------------------------------------------------------*/
1545 unsaveRegisters (iCode * ic)
1550 /* restore the registers in use at this time but skip the
1551 ones for the result */
1552 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1553 mcs51_rUmaskForOp (IC_RESULT(ic)));
1555 if (options.useXstack)
1557 emitcode ("mov", "r0,%s", spname);
1558 for (i = mcs51_nRegs; i >= 0; i--)
1560 if (bitVectBitValue (rsave, i))
1562 emitcode ("dec", "r0");
1563 emitcode ("movx", "a,@r0");
1565 emitcode ("mov", "b,a");
1567 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1571 emitcode ("mov", "%s,r0", spname);
1572 if (bitVectBitValue (rsave, R0_IDX))
1573 emitcode ("mov", "r0,b");
1576 for (i = mcs51_nRegs; i >= 0; i--)
1578 if (bitVectBitValue (rsave, i))
1579 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1585 /*-----------------------------------------------------------------*/
1587 /*-----------------------------------------------------------------*/
1589 pushSide (operand * oper, int size)
1594 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1595 if (AOP_TYPE (oper) != AOP_REG &&
1596 AOP_TYPE (oper) != AOP_DIR &&
1599 emitcode ("mov", "a,%s", l);
1600 emitcode ("push", "acc");
1603 emitcode ("push", "%s", l);
1607 /*-----------------------------------------------------------------*/
1608 /* assignResultValue - */
1609 /*-----------------------------------------------------------------*/
1611 assignResultValue (operand * oper)
1614 int size = AOP_SIZE (oper);
1617 aopPut (AOP (oper), fReturn[offset], offset);
1623 /*-----------------------------------------------------------------*/
1624 /* genXpush - pushes onto the external stack */
1625 /*-----------------------------------------------------------------*/
1627 genXpush (iCode * ic)
1629 asmop *aop = newAsmop (0);
1631 int size, offset = 0;
1633 D(emitcode (";", "genXpush"));
1635 aopOp (IC_LEFT (ic), ic, FALSE);
1636 r = getFreePtr (ic, &aop, FALSE);
1639 emitcode ("mov", "%s,_spx", r->name);
1641 size = AOP_SIZE (IC_LEFT (ic));
1645 char *l = aopGet (AOP (IC_LEFT (ic)),
1646 offset++, FALSE, FALSE);
1648 emitcode ("movx", "@%s,a", r->name);
1649 emitcode ("inc", "%s", r->name);
1654 emitcode ("mov", "_spx,%s", r->name);
1656 freeAsmop (NULL, aop, ic, TRUE);
1657 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1660 /*-----------------------------------------------------------------*/
1661 /* genIpush - genrate code for pushing this gets a little complex */
1662 /*-----------------------------------------------------------------*/
1664 genIpush (iCode * ic)
1666 int size, offset = 0;
1669 D(emitcode (";", "genIpush"));
1671 /* if this is not a parm push : ie. it is spill push
1672 and spill push is always done on the local stack */
1676 /* and the item is spilt then do nothing */
1677 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1680 aopOp (IC_LEFT (ic), ic, FALSE);
1681 size = AOP_SIZE (IC_LEFT (ic));
1682 /* push it on the stack */
1685 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1691 emitcode ("push", "%s", l);
1696 /* this is a paramter push: in this case we call
1697 the routine to find the call and save those
1698 registers that need to be saved */
1701 /* if use external stack then call the external
1702 stack pushing routine */
1703 if (options.useXstack)
1709 /* then do the push */
1710 aopOp (IC_LEFT (ic), ic, FALSE);
1713 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1714 size = AOP_SIZE (IC_LEFT (ic));
1718 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1719 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1720 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1723 emitcode ("mov", "a,%s", l);
1724 emitcode ("push", "acc");
1727 emitcode ("push", "%s", l);
1730 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1733 /*-----------------------------------------------------------------*/
1734 /* genIpop - recover the registers: can happen only for spilling */
1735 /*-----------------------------------------------------------------*/
1737 genIpop (iCode * ic)
1741 D(emitcode (";", "genIpop"));
1743 /* if the temp was not pushed then */
1744 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1747 aopOp (IC_LEFT (ic), ic, FALSE);
1748 size = AOP_SIZE (IC_LEFT (ic));
1749 offset = (size - 1);
1751 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1754 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1757 /*-----------------------------------------------------------------*/
1758 /* unsaveRBank - restores the resgister bank from stack */
1759 /*-----------------------------------------------------------------*/
1761 unsaveRBank (int bank, iCode * ic, bool popPsw)
1767 if (options.useXstack)
1771 /* Assume r0 is available for use. */
1772 r = mcs51_regWithIdx (R0_IDX);;
1777 r = getFreePtr (ic, &aop, FALSE);
1779 emitcode ("mov", "%s,_spx", r->name);
1784 if (options.useXstack)
1786 emitcode ("movx", "a,@%s", r->name);
1787 emitcode ("mov", "psw,a");
1788 emitcode ("dec", "%s", r->name);
1792 emitcode ("pop", "psw");
1796 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1798 if (options.useXstack)
1800 emitcode ("movx", "a,@%s", r->name);
1801 emitcode ("mov", "(%s+%d),a",
1802 regs8051[i].base, 8 * bank + regs8051[i].offset);
1803 emitcode ("dec", "%s", r->name);
1807 emitcode ("pop", "(%s+%d)",
1808 regs8051[i].base, 8 * bank + regs8051[i].offset);
1811 if (options.useXstack)
1813 emitcode ("mov", "_spx,%s", r->name);
1818 freeAsmop (NULL, aop, ic, TRUE);
1822 /*-----------------------------------------------------------------*/
1823 /* saveRBank - saves an entire register bank on the stack */
1824 /*-----------------------------------------------------------------*/
1826 saveRBank (int bank, iCode * ic, bool pushPsw)
1832 if (options.useXstack)
1836 /* Assume r0 is available for use. */
1837 r = mcs51_regWithIdx (R0_IDX);;
1842 r = getFreePtr (ic, &aop, FALSE);
1844 emitcode ("mov", "%s,_spx", r->name);
1847 for (i = 0; i < mcs51_nRegs; i++)
1849 if (options.useXstack)
1851 emitcode ("inc", "%s", r->name);
1852 emitcode ("mov", "a,(%s+%d)",
1853 regs8051[i].base, 8 * bank + regs8051[i].offset);
1854 emitcode ("movx", "@%s,a", r->name);
1857 emitcode ("push", "(%s+%d)",
1858 regs8051[i].base, 8 * bank + regs8051[i].offset);
1863 if (options.useXstack)
1865 emitcode ("mov", "a,psw");
1866 emitcode ("movx", "@%s,a", r->name);
1867 emitcode ("inc", "%s", r->name);
1868 emitcode ("mov", "_spx,%s", r->name);
1873 emitcode ("push", "psw");
1876 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1881 freeAsmop (NULL, aop, ic, TRUE);
1890 /*-----------------------------------------------------------------*/
1891 /* genCall - generates a call statement */
1892 /*-----------------------------------------------------------------*/
1894 genCall (iCode * ic)
1897 // bool restoreBank = FALSE;
1898 bool swapBanks = FALSE;
1900 D(emitcode(";", "genCall"));
1902 /* if send set is not empty the assign */
1907 for (sic = setFirstItem (_G.sendSet); sic;
1908 sic = setNextItem (_G.sendSet))
1910 int size, offset = 0;
1911 aopOp (IC_LEFT (sic), sic, FALSE);
1912 size = AOP_SIZE (IC_LEFT (sic));
1915 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1917 if (strcmp (l, fReturn[offset]))
1918 emitcode ("mov", "%s,%s",
1923 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1928 /* if we are calling a not _naked function that is not using
1929 the same register bank then we need to save the
1930 destination registers on the stack */
1931 dtype = operandType (IC_LEFT (ic));
1932 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1933 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1934 !IFFUNC_ISISR (dtype))
1936 // if (!ic->bankSaved)
1938 // /* This is unexpected; the bank should have been saved in
1941 // saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1942 // restoreBank = TRUE;
1944 // need caution message to user here
1948 /* if caller saves & we have not saved then */
1954 emitcode ("mov", "psw,#0x%02x",
1955 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1959 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1960 OP_SYMBOL (IC_LEFT (ic))->rname :
1961 OP_SYMBOL (IC_LEFT (ic))->name));
1965 emitcode ("mov", "psw,#0x%02x",
1966 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1969 /* if we need assign a result value */
1970 if ((IS_ITEMP (IC_RESULT (ic)) &&
1971 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1972 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1973 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1974 IS_TRUE_SYMOP (IC_RESULT (ic)))
1978 aopOp (IC_RESULT (ic), ic, FALSE);
1981 assignResultValue (IC_RESULT (ic));
1983 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1986 /* adjust the stack for parameters if
1991 if (ic->parmBytes > 3)
1993 emitcode ("mov", "a,%s", spname);
1994 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1995 emitcode ("mov", "%s,a", spname);
1998 for (i = 0; i < ic->parmBytes; i++)
1999 emitcode ("dec", "%s", spname);
2002 /* if we hade saved some registers then unsave them */
2003 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2004 unsaveRegisters (ic);
2006 // /* if register bank was saved then pop them */
2008 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2011 /*-----------------------------------------------------------------*/
2012 /* -10l - generates a call by pointer statement */
2013 /*-----------------------------------------------------------------*/
2015 genPcall (iCode * ic)
2018 symbol *rlbl = newiTempLabel (NULL);
2019 // bool restoreBank=FALSE;
2020 bool swapBanks = FALSE;
2022 D(emitcode(";", "genPCall"));
2024 /* if caller saves & we have not saved then */
2028 /* if we are calling a not _naked function that is not using
2029 the same register bank then we need to save the
2030 destination registers on the stack */
2031 dtype = operandType (IC_LEFT (ic))->next;
2032 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2033 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2034 !IFFUNC_ISISR (dtype))
2036 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2037 // restoreBank=TRUE;
2039 // need caution message to user here
2042 /* push the return address on to the stack */
2043 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2044 emitcode ("push", "acc");
2045 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2046 emitcode ("push", "acc");
2048 /* now push the calling address */
2049 aopOp (IC_LEFT (ic), ic, FALSE);
2051 pushSide (IC_LEFT (ic), FPTRSIZE);
2053 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2055 /* if send set is not empty the assign */
2060 for (sic = setFirstItem (_G.sendSet); sic;
2061 sic = setNextItem (_G.sendSet))
2063 int size, offset = 0;
2064 aopOp (IC_LEFT (sic), sic, FALSE);
2065 size = AOP_SIZE (IC_LEFT (sic));
2068 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2070 if (strcmp (l, fReturn[offset]))
2071 emitcode ("mov", "%s,%s",
2076 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2083 emitcode ("mov", "psw,#0x%02x",
2084 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2088 emitcode ("ret", "");
2089 emitcode ("", "%05d$:", (rlbl->key + 100));
2094 emitcode ("mov", "psw,#0x%02x",
2095 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2098 /* if we need assign a result value */
2099 if ((IS_ITEMP (IC_RESULT (ic)) &&
2100 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2101 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2102 IS_TRUE_SYMOP (IC_RESULT (ic)))
2106 aopOp (IC_RESULT (ic), ic, FALSE);
2109 assignResultValue (IC_RESULT (ic));
2111 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2114 /* adjust the stack for parameters if
2119 if (ic->parmBytes > 3)
2121 emitcode ("mov", "a,%s", spname);
2122 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2123 emitcode ("mov", "%s,a", spname);
2126 for (i = 0; i < ic->parmBytes; i++)
2127 emitcode ("dec", "%s", spname);
2131 // /* if register bank was saved then unsave them */
2133 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2135 /* if we hade saved some registers then
2137 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2138 unsaveRegisters (ic);
2141 /*-----------------------------------------------------------------*/
2142 /* resultRemat - result is rematerializable */
2143 /*-----------------------------------------------------------------*/
2145 resultRemat (iCode * ic)
2147 if (SKIP_IC (ic) || ic->op == IFX)
2150 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2152 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2153 if (sym->remat && !POINTER_SET (ic))
2160 #if defined(__BORLANDC__) || defined(_MSC_VER)
2161 #define STRCASECMP stricmp
2163 #define STRCASECMP strcasecmp
2166 /*-----------------------------------------------------------------*/
2167 /* inExcludeList - return 1 if the string is in exclude Reg list */
2168 /*-----------------------------------------------------------------*/
2170 inExcludeList (char *s)
2174 if (options.excludeRegs[i] &&
2175 STRCASECMP (options.excludeRegs[i], "none") == 0)
2178 for (i = 0; options.excludeRegs[i]; i++)
2180 if (options.excludeRegs[i] &&
2181 STRCASECMP (s, options.excludeRegs[i]) == 0)
2187 /*-----------------------------------------------------------------*/
2188 /* genFunction - generated code for function entry */
2189 /*-----------------------------------------------------------------*/
2191 genFunction (iCode * ic)
2195 bool switchedPSW = FALSE;
2196 int calleesaves_saved_register = -1;
2199 /* create the function header */
2200 emitcode (";", "-----------------------------------------");
2201 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2202 emitcode (";", "-----------------------------------------");
2204 emitcode ("", "%s:", sym->rname);
2205 ftype = operandType (IC_LEFT (ic));
2207 if (IFFUNC_ISNAKED(ftype))
2209 emitcode(";", "naked function: no prologue.");
2213 /* if critical function then turn interrupts off */
2214 if (IFFUNC_ISCRITICAL (ftype))
2215 emitcode ("clr", "ea");
2217 /* here we need to generate the equates for the
2218 register bank if required */
2219 if (FUNC_REGBANK (ftype) != rbank)
2223 rbank = FUNC_REGBANK (ftype);
2224 for (i = 0; i < mcs51_nRegs; i++)
2226 if (strcmp (regs8051[i].base, "0") == 0)
2227 emitcode ("", "%s = 0x%02x",
2229 8 * rbank + regs8051[i].offset);
2231 emitcode ("", "%s = %s + 0x%02x",
2234 8 * rbank + regs8051[i].offset);
2238 /* if this is an interrupt service routine then
2239 save acc, b, dpl, dph */
2240 if (IFFUNC_ISISR (sym->type))
2243 if (!inExcludeList ("acc"))
2244 emitcode ("push", "acc");
2245 if (!inExcludeList ("b"))
2246 emitcode ("push", "b");
2247 if (!inExcludeList ("dpl"))
2248 emitcode ("push", "dpl");
2249 if (!inExcludeList ("dph"))
2250 emitcode ("push", "dph");
2251 /* if this isr has no bank i.e. is going to
2252 run with bank 0 , then we need to save more
2254 if (!FUNC_REGBANK (sym->type))
2257 /* if this function does not call any other
2258 function then we can be economical and
2259 save only those registers that are used */
2260 if (!IFFUNC_HASFCALL(sym->type))
2264 /* if any registers used */
2267 /* save the registers used */
2268 for (i = 0; i < sym->regsUsed->size; i++)
2270 if (bitVectBitValue (sym->regsUsed, i) ||
2271 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2272 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2279 /* this function has a function call cannot
2280 determines register usage so we will have to push the
2282 saveRBank (0, ic, FALSE);
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 /* this function has a function call cannot
2579 determines register usage so we will have to pop the
2581 unsaveRBank (0, ic, FALSE);
2586 /* This ISR uses a non-zero bank.
2588 * Restore any register banks saved by genFunction
2591 // jwk: this needs a closer look
2592 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2595 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2597 if (savedBanks & (1 << ix))
2599 unsaveRBank(ix, NULL, FALSE);
2603 if (options.useXstack)
2605 /* Restore bank AFTER calling unsaveRBank,
2606 * since it can trash r0.
2608 emitcode ("pop", "psw");
2612 if (!inExcludeList ("dph"))
2613 emitcode ("pop", "dph");
2614 if (!inExcludeList ("dpl"))
2615 emitcode ("pop", "dpl");
2616 if (!inExcludeList ("b"))
2617 emitcode ("pop", "b");
2618 if (!inExcludeList ("acc"))
2619 emitcode ("pop", "acc");
2621 if (IFFUNC_ISCRITICAL (sym->type))
2622 emitcode ("setb", "ea");
2624 /* if debug then send end of function */
2625 if (options.debug && currFunc)
2628 emitcode ("", "C$%s$%d$%d$%d ==.",
2629 FileBaseName (ic->filename), currFunc->lastLine,
2630 ic->level, ic->block);
2631 if (IS_STATIC (currFunc->etype))
2632 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2634 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2638 emitcode ("reti", "");
2642 if (IFFUNC_ISCRITICAL (sym->type))
2643 emitcode ("setb", "ea");
2645 if (IFFUNC_CALLEESAVES(sym->type))
2649 /* if any registers used */
2652 /* save the registers used */
2653 for (i = sym->regsUsed->size; i >= 0; i--)
2655 if (bitVectBitValue (sym->regsUsed, i) ||
2656 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2657 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2663 /* if debug then send end of function */
2664 if (options.debug && currFunc)
2667 emitcode ("", "C$%s$%d$%d$%d ==.",
2668 FileBaseName (ic->filename), currFunc->lastLine,
2669 ic->level, ic->block);
2670 if (IS_STATIC (currFunc->etype))
2671 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2673 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2677 emitcode ("ret", "");
2682 /*-----------------------------------------------------------------*/
2683 /* genRet - generate code for return statement */
2684 /*-----------------------------------------------------------------*/
2688 int size, offset = 0, pushed = 0;
2690 D(emitcode (";", "genRet"));
2692 /* if we have no return value then
2693 just generate the "ret" */
2697 /* we have something to return then
2698 move the return value into place */
2699 aopOp (IC_LEFT (ic), ic, FALSE);
2700 size = AOP_SIZE (IC_LEFT (ic));
2705 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2708 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2710 emitcode ("push", "%s", l);
2715 l = aopGet (AOP (IC_LEFT (ic)), offset,
2717 if (strcmp (fReturn[offset], l))
2718 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2727 if (strcmp (fReturn[pushed], "a"))
2728 emitcode ("pop", fReturn[pushed]);
2730 emitcode ("pop", "acc");
2733 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2736 /* generate a jump to the return label
2737 if the next is not the return statement */
2738 if (!(ic->next && ic->next->op == LABEL &&
2739 IC_LABEL (ic->next) == returnLabel))
2741 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2745 /*-----------------------------------------------------------------*/
2746 /* genLabel - generates a label */
2747 /*-----------------------------------------------------------------*/
2749 genLabel (iCode * ic)
2751 /* special case never generate */
2752 if (IC_LABEL (ic) == entryLabel)
2755 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2758 /*-----------------------------------------------------------------*/
2759 /* genGoto - generates a ljmp */
2760 /*-----------------------------------------------------------------*/
2762 genGoto (iCode * ic)
2764 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2767 /*-----------------------------------------------------------------*/
2768 /* findLabelBackwards: walks back through the iCode chain looking */
2769 /* for the given label. Returns number of iCode instructions */
2770 /* between that label and given ic. */
2771 /* Returns zero if label not found. */
2772 /*-----------------------------------------------------------------*/
2774 findLabelBackwards (iCode * ic, int key)
2783 /* If we have any pushes or pops, we cannot predict the distance.
2784 I don't like this at all, this should be dealt with in the
2786 if (ic->op == IPUSH || ic->op == IPOP) {
2790 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2799 /*-----------------------------------------------------------------*/
2800 /* genPlusIncr :- does addition with increment if possible */
2801 /*-----------------------------------------------------------------*/
2803 genPlusIncr (iCode * ic)
2805 unsigned int icount;
2806 unsigned int size = getDataSize (IC_RESULT (ic));
2808 /* will try to generate an increment */
2809 /* if the right side is not a literal
2811 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2814 /* if the literal value of the right hand side
2815 is greater than 4 then it is not worth it */
2816 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2819 D(emitcode (";", "genPlusIncr"));
2821 /* if increment 16 bits in register */
2822 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2830 /* If the next instruction is a goto and the goto target
2831 * is < 10 instructions previous to this, we can generate
2832 * jumps straight to that target.
2834 if (ic->next && ic->next->op == GOTO
2835 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2836 && labelRange <= 10)
2838 emitcode (";", "tail increment optimized");
2839 tlbl = IC_LABEL (ic->next);
2844 tlbl = newiTempLabel (NULL);
2847 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2848 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2849 IS_AOP_PREG (IC_RESULT (ic)))
2850 emitcode ("cjne", "%s,#0x00,%05d$",
2851 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2855 emitcode ("clr", "a");
2856 emitcode ("cjne", "a,%s,%05d$",
2857 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2861 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2864 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2865 IS_AOP_PREG (IC_RESULT (ic)))
2866 emitcode ("cjne", "%s,#0x00,%05d$",
2867 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2870 emitcode ("cjne", "a,%s,%05d$",
2871 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2874 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2878 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2879 IS_AOP_PREG (IC_RESULT (ic)))
2880 emitcode ("cjne", "%s,#0x00,%05d$",
2881 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2885 emitcode ("cjne", "a,%s,%05d$",
2886 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2889 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2894 emitcode ("", "%05d$:", tlbl->key + 100);
2899 /* if the sizes are greater than 1 then we cannot */
2900 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2901 AOP_SIZE (IC_LEFT (ic)) > 1)
2904 /* we can if the aops of the left & result match or
2905 if they are in registers and the registers are the
2907 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2912 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2913 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2914 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2920 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2929 /*-----------------------------------------------------------------*/
2930 /* outBitAcc - output a bit in acc */
2931 /*-----------------------------------------------------------------*/
2933 outBitAcc (operand * result)
2935 symbol *tlbl = newiTempLabel (NULL);
2936 /* if the result is a bit */
2937 if (AOP_TYPE (result) == AOP_CRY)
2939 aopPut (AOP (result), "a", 0);
2943 emitcode ("jz", "%05d$", tlbl->key + 100);
2944 emitcode ("mov", "a,%s", one);
2945 emitcode ("", "%05d$:", tlbl->key + 100);
2950 /*-----------------------------------------------------------------*/
2951 /* genPlusBits - generates code for addition of two bits */
2952 /*-----------------------------------------------------------------*/
2954 genPlusBits (iCode * ic)
2956 D(emitcode (";", "genPlusBits"));
2958 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2960 symbol *lbl = newiTempLabel (NULL);
2961 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2962 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2963 emitcode ("cpl", "c");
2964 emitcode ("", "%05d$:", (lbl->key + 100));
2965 outBitC (IC_RESULT (ic));
2969 emitcode ("clr", "a");
2970 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2971 emitcode ("rlc", "a");
2972 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2973 emitcode ("addc", "a,#0x00");
2974 outAcc (IC_RESULT (ic));
2979 /* This is the original version of this code.
2981 * This is being kept around for reference,
2982 * because I am not entirely sure I got it right...
2985 adjustArithmeticResult (iCode * ic)
2987 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2988 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2989 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2990 aopPut (AOP (IC_RESULT (ic)),
2991 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2994 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2995 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2996 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2997 aopPut (AOP (IC_RESULT (ic)),
2998 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3001 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3002 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3003 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3004 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3005 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3008 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3009 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3013 /* This is the pure and virtuous version of this code.
3014 * I'm pretty certain it's right, but not enough to toss the old
3018 adjustArithmeticResult (iCode * ic)
3020 if (opIsGptr (IC_RESULT (ic)) &&
3021 opIsGptr (IC_LEFT (ic)) &&
3022 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3024 aopPut (AOP (IC_RESULT (ic)),
3025 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3029 if (opIsGptr (IC_RESULT (ic)) &&
3030 opIsGptr (IC_RIGHT (ic)) &&
3031 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3033 aopPut (AOP (IC_RESULT (ic)),
3034 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3038 if (opIsGptr (IC_RESULT (ic)) &&
3039 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3040 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3041 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3042 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3045 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3046 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3051 /*-----------------------------------------------------------------*/
3052 /* genPlus - generates code for addition */
3053 /*-----------------------------------------------------------------*/
3055 genPlus (iCode * ic)
3057 int size, offset = 0;
3059 /* special cases :- */
3061 D(emitcode (";", "genPlus"));
3063 aopOp (IC_LEFT (ic), ic, FALSE);
3064 aopOp (IC_RIGHT (ic), ic, FALSE);
3065 aopOp (IC_RESULT (ic), ic, TRUE);
3067 /* if literal, literal on the right or
3068 if left requires ACC or right is already
3070 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3071 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3072 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3074 operand *t = IC_RIGHT (ic);
3075 IC_RIGHT (ic) = IC_LEFT (ic);
3079 /* if both left & right are in bit
3081 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3082 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3088 /* if left in bit space & right literal */
3089 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3090 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3092 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3093 /* if result in bit space */
3094 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3096 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3097 emitcode ("cpl", "c");
3098 outBitC (IC_RESULT (ic));
3102 size = getDataSize (IC_RESULT (ic));
3105 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3106 emitcode ("addc", "a,#00");
3107 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3113 /* if I can do an increment instead
3114 of add then GOOD for ME */
3115 if (genPlusIncr (ic) == TRUE)
3118 size = getDataSize (IC_RESULT (ic));
3122 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3124 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3126 emitcode ("add", "a,%s",
3127 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3129 emitcode ("addc", "a,%s",
3130 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3134 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3136 emitcode ("add", "a,%s",
3137 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3139 emitcode ("addc", "a,%s",
3140 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3142 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3145 adjustArithmeticResult (ic);
3148 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3149 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3150 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3153 /*-----------------------------------------------------------------*/
3154 /* genMinusDec :- does subtraction with deccrement if possible */
3155 /*-----------------------------------------------------------------*/
3157 genMinusDec (iCode * ic)
3159 unsigned int icount;
3160 unsigned int size = getDataSize (IC_RESULT (ic));
3162 /* will try to generate an increment */
3163 /* if the right side is not a literal
3165 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3168 /* if the literal value of the right hand side
3169 is greater than 4 then it is not worth it */
3170 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3173 D(emitcode (";", "genMinusDec"));
3175 /* if decrement 16 bits in register */
3176 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3184 /* If the next instruction is a goto and the goto target
3185 * is <= 10 instructions previous to this, we can generate
3186 * jumps straight to that target.
3188 if (ic->next && ic->next->op == GOTO
3189 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3190 && labelRange <= 10)
3192 emitcode (";", "tail decrement optimized");
3193 tlbl = IC_LABEL (ic->next);
3198 tlbl = newiTempLabel (NULL);
3202 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3203 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3204 IS_AOP_PREG (IC_RESULT (ic)))
3205 emitcode ("cjne", "%s,#0xff,%05d$"
3206 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3210 emitcode ("mov", "a,#0xff");
3211 emitcode ("cjne", "a,%s,%05d$"
3212 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3215 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3218 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3219 IS_AOP_PREG (IC_RESULT (ic)))
3220 emitcode ("cjne", "%s,#0xff,%05d$"
3221 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3225 emitcode ("cjne", "a,%s,%05d$"
3226 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3229 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3233 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3234 IS_AOP_PREG (IC_RESULT (ic)))
3235 emitcode ("cjne", "%s,#0xff,%05d$"
3236 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3240 emitcode ("cjne", "a,%s,%05d$"
3241 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3244 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3248 emitcode ("", "%05d$:", tlbl->key + 100);
3253 /* if the sizes are greater than 1 then we cannot */
3254 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3255 AOP_SIZE (IC_LEFT (ic)) > 1)
3258 /* we can if the aops of the left & result match or
3259 if they are in registers and the registers are the
3261 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3265 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3273 /*-----------------------------------------------------------------*/
3274 /* addSign - complete with sign */
3275 /*-----------------------------------------------------------------*/
3277 addSign (operand * result, int offset, int sign)
3279 int size = (getDataSize (result) - offset);
3284 emitcode ("rlc", "a");
3285 emitcode ("subb", "a,acc");
3287 aopPut (AOP (result), "a", offset++);
3291 aopPut (AOP (result), zero, offset++);
3295 /*-----------------------------------------------------------------*/
3296 /* genMinusBits - generates code for subtraction of two bits */
3297 /*-----------------------------------------------------------------*/
3299 genMinusBits (iCode * ic)
3301 symbol *lbl = newiTempLabel (NULL);
3303 D(emitcode (";", "genMinusBits"));
3305 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3307 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3308 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3309 emitcode ("cpl", "c");
3310 emitcode ("", "%05d$:", (lbl->key + 100));
3311 outBitC (IC_RESULT (ic));
3315 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3316 emitcode ("subb", "a,acc");
3317 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3318 emitcode ("inc", "a");
3319 emitcode ("", "%05d$:", (lbl->key + 100));
3320 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3321 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3325 /*-----------------------------------------------------------------*/
3326 /* genMinus - generates code for subtraction */
3327 /*-----------------------------------------------------------------*/
3329 genMinus (iCode * ic)
3331 int size, offset = 0;
3332 unsigned long lit = 0L;
3334 D(emitcode (";", "genMinus"));
3336 aopOp (IC_LEFT (ic), ic, FALSE);
3337 aopOp (IC_RIGHT (ic), ic, FALSE);
3338 aopOp (IC_RESULT (ic), ic, TRUE);
3340 /* special cases :- */
3341 /* if both left & right are in bit space */
3342 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3343 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3349 /* if I can do an decrement instead
3350 of subtract then GOOD for ME */
3351 if (genMinusDec (ic) == TRUE)
3354 size = getDataSize (IC_RESULT (ic));
3356 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3362 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3366 /* if literal, add a,#-lit, else normal subb */
3369 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3370 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3371 emitcode ("subb", "a,%s",
3372 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3375 /* first add without previous c */
3377 if (!size && lit==-1) {
3378 emitcode ("dec", "a");
3380 emitcode ("add", "a,#0x%02x",
3381 (unsigned int) (lit & 0x0FFL));
3384 emitcode ("addc", "a,#0x%02x",
3385 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3388 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3391 adjustArithmeticResult (ic);
3394 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3395 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3396 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3400 /*-----------------------------------------------------------------*/
3401 /* genMultbits :- multiplication of bits */
3402 /*-----------------------------------------------------------------*/
3404 genMultbits (operand * left,
3408 D(emitcode (";", "genMultbits"));
3410 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3411 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3416 /*-----------------------------------------------------------------*/
3417 /* genMultOneByte : 8*8=8/16 bit multiplication */
3418 /*-----------------------------------------------------------------*/
3420 genMultOneByte (operand * left,
3424 sym_link *opetype = operandType (result);
3426 int size=AOP_SIZE(result);
3428 D(emitcode (";", "genMultOneByte"));
3430 if (size<1 || size>2) {
3431 // this should never happen
3432 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3433 AOP_SIZE(result), __FILE__, lineno);
3437 /* (if two literals: the value is computed before) */
3438 /* if one literal, literal on the right */
3439 if (AOP_TYPE (left) == AOP_LIT)
3444 //emitcode (";", "swapped left and right");
3447 if (SPEC_USIGN(opetype)
3448 // ignore the sign of left and right, what else can we do?
3449 || (SPEC_USIGN(operandType(left)) &&
3450 SPEC_USIGN(operandType(right)))) {
3451 // just an unsigned 8*8=8/16 multiply
3452 //emitcode (";","unsigned");
3453 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3454 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3455 emitcode ("mul", "ab");
3456 aopPut (AOP (result), "a", 0);
3458 aopPut (AOP (result), "b", 1);
3463 // we have to do a signed multiply
3465 //emitcode (";", "signed");
3466 emitcode ("clr", "F0"); // reset sign flag
3467 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3469 lbl=newiTempLabel(NULL);
3470 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3471 // left side is negative, 8-bit two's complement, this fails for -128
3472 emitcode ("setb", "F0"); // set sign flag
3473 emitcode ("cpl", "a");
3474 emitcode ("inc", "a");
3476 emitcode ("", "%05d$:", lbl->key+100);
3479 if (AOP_TYPE(right)==AOP_LIT) {
3480 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3481 /* AND literal negative */
3483 emitcode ("cpl", "F0"); // complement sign flag
3484 emitcode ("mov", "b,#0x%02x", -val);
3486 emitcode ("mov", "b,#0x%02x", val);
3489 lbl=newiTempLabel(NULL);
3490 emitcode ("mov", "b,a");
3491 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3492 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3493 // right side is negative, 8-bit two's complement
3494 emitcode ("cpl", "F0"); // complement sign flag
3495 emitcode ("cpl", "a");
3496 emitcode ("inc", "a");
3497 emitcode ("", "%05d$:", lbl->key+100);
3499 emitcode ("mul", "ab");
3501 lbl=newiTempLabel(NULL);
3502 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3503 // only ONE op was negative, we have to do a 8/16-bit two's complement
3504 emitcode ("cpl", "a"); // lsb
3506 emitcode ("inc", "a");
3508 emitcode ("add", "a,#1");
3509 emitcode ("xch", "a,b");
3510 emitcode ("cpl", "a"); // msb
3511 emitcode ("addc", "a,#0");
3512 emitcode ("xch", "a,b");
3515 emitcode ("", "%05d$:", lbl->key+100);
3516 aopPut (AOP (result), "a", 0);
3518 aopPut (AOP (result), "b", 1);
3522 /*-----------------------------------------------------------------*/
3523 /* genMult - generates code for multiplication */
3524 /*-----------------------------------------------------------------*/
3526 genMult (iCode * ic)
3528 operand *left = IC_LEFT (ic);
3529 operand *right = IC_RIGHT (ic);
3530 operand *result = IC_RESULT (ic);
3532 D(emitcode (";", "genMult"));
3534 /* assign the amsops */
3535 aopOp (left, ic, FALSE);
3536 aopOp (right, ic, FALSE);
3537 aopOp (result, ic, TRUE);
3539 /* special cases first */
3541 if (AOP_TYPE (left) == AOP_CRY &&
3542 AOP_TYPE (right) == AOP_CRY)
3544 genMultbits (left, right, result);
3548 /* if both are of size == 1 */
3549 #if 0 // one of them can be a sloc shared with the result
3550 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3552 if (getSize(operandType(left)) == 1 &&
3553 getSize(operandType(right)) == 1)
3556 genMultOneByte (left, right, result);
3560 /* should have been converted to function call */
3561 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3562 getSize(OP_SYMBOL(right)->type));
3566 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3567 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3568 freeAsmop (result, NULL, ic, TRUE);
3571 /*-----------------------------------------------------------------*/
3572 /* genDivbits :- division of bits */
3573 /*-----------------------------------------------------------------*/
3575 genDivbits (operand * left,
3582 D(emitcode (";", "genDivbits"));
3584 /* the result must be bit */
3585 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3586 l = aopGet (AOP (left), 0, FALSE, FALSE);
3590 emitcode ("div", "ab");
3591 emitcode ("rrc", "a");
3592 aopPut (AOP (result), "c", 0);
3595 /*-----------------------------------------------------------------*/
3596 /* genDivOneByte : 8 bit division */
3597 /*-----------------------------------------------------------------*/
3599 genDivOneByte (operand * left,
3603 sym_link *opetype = operandType (result);
3608 D(emitcode (";", "genDivOneByte"));
3610 size = AOP_SIZE (result) - 1;
3612 /* signed or unsigned */
3613 if (SPEC_USIGN (opetype))
3615 /* unsigned is easy */
3616 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3617 l = aopGet (AOP (left), 0, FALSE, FALSE);
3619 emitcode ("div", "ab");
3620 aopPut (AOP (result), "a", 0);
3622 aopPut (AOP (result), zero, offset++);
3626 /* signed is a little bit more difficult */
3628 /* save the signs of the operands */
3629 l = aopGet (AOP (left), 0, FALSE, FALSE);
3631 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3632 emitcode ("push", "acc"); /* save it on the stack */
3634 /* now sign adjust for both left & right */
3635 l = aopGet (AOP (right), 0, FALSE, FALSE);
3637 lbl = newiTempLabel (NULL);
3638 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3639 emitcode ("cpl", "a");
3640 emitcode ("inc", "a");
3641 emitcode ("", "%05d$:", (lbl->key + 100));
3642 emitcode ("mov", "b,a");
3644 /* sign adjust left side */
3645 l = aopGet (AOP (left), 0, FALSE, FALSE);
3648 lbl = newiTempLabel (NULL);
3649 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3650 emitcode ("cpl", "a");
3651 emitcode ("inc", "a");
3652 emitcode ("", "%05d$:", (lbl->key + 100));
3654 /* now the division */
3655 emitcode ("div", "ab");
3656 /* we are interested in the lower order
3658 emitcode ("mov", "b,a");
3659 lbl = newiTempLabel (NULL);
3660 emitcode ("pop", "acc");
3661 /* if there was an over flow we don't
3662 adjust the sign of the result */
3663 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3664 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3666 emitcode ("clr", "a");
3667 emitcode ("subb", "a,b");
3668 emitcode ("mov", "b,a");
3669 emitcode ("", "%05d$:", (lbl->key + 100));
3671 /* now we are done */
3672 aopPut (AOP (result), "b", 0);
3675 emitcode ("mov", "c,b.7");
3676 emitcode ("subb", "a,acc");
3679 aopPut (AOP (result), "a", offset++);
3683 /*-----------------------------------------------------------------*/
3684 /* genDiv - generates code for division */
3685 /*-----------------------------------------------------------------*/
3689 operand *left = IC_LEFT (ic);
3690 operand *right = IC_RIGHT (ic);
3691 operand *result = IC_RESULT (ic);
3693 D(emitcode (";", "genDiv"));
3695 /* assign the amsops */
3696 aopOp (left, ic, FALSE);
3697 aopOp (right, ic, FALSE);
3698 aopOp (result, ic, TRUE);
3700 /* special cases first */
3702 if (AOP_TYPE (left) == AOP_CRY &&
3703 AOP_TYPE (right) == AOP_CRY)
3705 genDivbits (left, right, result);
3709 /* if both are of size == 1 */
3710 if (AOP_SIZE (left) == 1 &&
3711 AOP_SIZE (right) == 1)
3713 genDivOneByte (left, right, result);
3717 /* should have been converted to function call */
3720 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3721 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3722 freeAsmop (result, NULL, ic, TRUE);
3725 /*-----------------------------------------------------------------*/
3726 /* genModbits :- modulus of bits */
3727 /*-----------------------------------------------------------------*/
3729 genModbits (operand * left,
3736 D(emitcode (";", "genModbits"));
3738 /* the result must be bit */
3739 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3740 l = aopGet (AOP (left), 0, FALSE, FALSE);
3744 emitcode ("div", "ab");
3745 emitcode ("mov", "a,b");
3746 emitcode ("rrc", "a");
3747 aopPut (AOP (result), "c", 0);
3750 /*-----------------------------------------------------------------*/
3751 /* genModOneByte : 8 bit modulus */
3752 /*-----------------------------------------------------------------*/
3754 genModOneByte (operand * left,
3758 sym_link *opetype = operandType (result);
3762 D(emitcode (";", "genModOneByte"));
3764 /* signed or unsigned */
3765 if (SPEC_USIGN (opetype))
3767 /* unsigned is easy */
3768 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3769 l = aopGet (AOP (left), 0, FALSE, FALSE);
3771 emitcode ("div", "ab");
3772 aopPut (AOP (result), "b", 0);
3776 /* signed is a little bit more difficult */
3778 /* save the signs of the operands */
3779 l = aopGet (AOP (left), 0, FALSE, FALSE);
3782 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3783 emitcode ("push", "acc"); /* save it on the stack */
3785 /* now sign adjust for both left & right */
3786 l = aopGet (AOP (right), 0, FALSE, FALSE);
3789 lbl = newiTempLabel (NULL);
3790 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3791 emitcode ("cpl", "a");
3792 emitcode ("inc", "a");
3793 emitcode ("", "%05d$:", (lbl->key + 100));
3794 emitcode ("mov", "b,a");
3796 /* sign adjust left side */
3797 l = aopGet (AOP (left), 0, FALSE, FALSE);
3800 lbl = newiTempLabel (NULL);
3801 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3802 emitcode ("cpl", "a");
3803 emitcode ("inc", "a");
3804 emitcode ("", "%05d$:", (lbl->key + 100));
3806 /* now the multiplication */
3807 emitcode ("div", "ab");
3808 /* we are interested in the lower order
3810 lbl = newiTempLabel (NULL);
3811 emitcode ("pop", "acc");
3812 /* if there was an over flow we don't
3813 adjust the sign of the result */
3814 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3815 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3817 emitcode ("clr", "a");
3818 emitcode ("subb", "a,b");
3819 emitcode ("mov", "b,a");
3820 emitcode ("", "%05d$:", (lbl->key + 100));
3822 /* now we are done */
3823 aopPut (AOP (result), "b", 0);
3827 /*-----------------------------------------------------------------*/
3828 /* genMod - generates code for division */
3829 /*-----------------------------------------------------------------*/
3833 operand *left = IC_LEFT (ic);
3834 operand *right = IC_RIGHT (ic);
3835 operand *result = IC_RESULT (ic);
3837 D(emitcode (";", "genMod"));
3839 /* assign the amsops */
3840 aopOp (left, ic, FALSE);
3841 aopOp (right, ic, FALSE);
3842 aopOp (result, ic, TRUE);
3844 /* special cases first */
3846 if (AOP_TYPE (left) == AOP_CRY &&
3847 AOP_TYPE (right) == AOP_CRY)
3849 genModbits (left, right, result);
3853 /* if both are of size == 1 */
3854 if (AOP_SIZE (left) == 1 &&
3855 AOP_SIZE (right) == 1)
3857 genModOneByte (left, right, result);
3861 /* should have been converted to function call */
3865 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3866 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3867 freeAsmop (result, NULL, ic, TRUE);
3870 /*-----------------------------------------------------------------*/
3871 /* genIfxJump :- will create a jump depending on the ifx */
3872 /*-----------------------------------------------------------------*/
3874 genIfxJump (iCode * ic, char *jval)
3877 symbol *tlbl = newiTempLabel (NULL);
3880 D(emitcode (";", "genIfxJump"));
3882 /* if true label then we jump if condition
3886 jlbl = IC_TRUE (ic);
3887 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3888 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3892 /* false label is present */
3893 jlbl = IC_FALSE (ic);
3894 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3895 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3897 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3898 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3900 emitcode (inst, "%05d$", tlbl->key + 100);
3901 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3902 emitcode ("", "%05d$:", tlbl->key + 100);
3904 /* mark the icode as generated */
3908 /*-----------------------------------------------------------------*/
3909 /* genCmp :- greater or less than comparison */
3910 /*-----------------------------------------------------------------*/
3912 genCmp (operand * left, operand * right,
3913 operand * result, iCode * ifx, int sign, iCode *ic)
3915 int size, offset = 0;
3916 unsigned long lit = 0L;
3918 D(emitcode (";", "genCmp"));
3920 /* if left & right are bit variables */
3921 if (AOP_TYPE (left) == AOP_CRY &&
3922 AOP_TYPE (right) == AOP_CRY)
3924 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3925 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3929 /* subtract right from left if at the
3930 end the carry flag is set then we know that
3931 left is greater than right */
3932 size = max (AOP_SIZE (left), AOP_SIZE (right));
3934 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3935 if ((size == 1) && !sign &&
3936 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3938 symbol *lbl = newiTempLabel (NULL);
3939 emitcode ("cjne", "%s,%s,%05d$",
3940 aopGet (AOP (left), offset, FALSE, FALSE),
3941 aopGet (AOP (right), offset, FALSE, FALSE),
3943 emitcode ("", "%05d$:", lbl->key + 100);
3947 if (AOP_TYPE (right) == AOP_LIT)
3949 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3950 /* optimize if(x < 0) or if(x >= 0) */
3959 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3960 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3962 genIfxJump (ifx, "acc.7");
3966 emitcode ("rlc", "a");
3974 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3975 if (sign && size == 0)
3977 emitcode ("xrl", "a,#0x80");
3978 if (AOP_TYPE (right) == AOP_LIT)
3980 unsigned long lit = (unsigned long)
3981 floatFromVal (AOP (right)->aopu.aop_lit);
3982 emitcode ("subb", "a,#0x%02x",
3983 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3987 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3988 emitcode ("xrl", "b,#0x80");
3989 emitcode ("subb", "a,b");
3993 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3999 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4000 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4001 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4007 /* if the result is used in the next
4008 ifx conditional branch then generate
4009 code a little differently */
4011 genIfxJump (ifx, "c");
4014 /* leave the result in acc */
4018 /*-----------------------------------------------------------------*/
4019 /* genCmpGt :- greater than comparison */
4020 /*-----------------------------------------------------------------*/
4022 genCmpGt (iCode * ic, iCode * ifx)
4024 operand *left, *right, *result;
4025 sym_link *letype, *retype;
4028 D(emitcode (";", "genCmpGt"));
4030 left = IC_LEFT (ic);
4031 right = IC_RIGHT (ic);
4032 result = IC_RESULT (ic);
4034 letype = getSpec (operandType (left));
4035 retype = getSpec (operandType (right));
4036 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4037 /* assign the amsops */
4038 aopOp (left, ic, FALSE);
4039 aopOp (right, ic, FALSE);
4040 aopOp (result, ic, TRUE);
4042 genCmp (right, left, result, ifx, sign,ic);
4044 freeAsmop (result, NULL, ic, TRUE);
4047 /*-----------------------------------------------------------------*/
4048 /* genCmpLt - less than comparisons */
4049 /*-----------------------------------------------------------------*/
4051 genCmpLt (iCode * ic, iCode * ifx)
4053 operand *left, *right, *result;
4054 sym_link *letype, *retype;
4057 D(emitcode (";", "genCmpLt"));
4059 left = IC_LEFT (ic);
4060 right = IC_RIGHT (ic);
4061 result = IC_RESULT (ic);
4063 letype = getSpec (operandType (left));
4064 retype = getSpec (operandType (right));
4065 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4067 /* assign the amsops */
4068 aopOp (left, ic, FALSE);
4069 aopOp (right, ic, FALSE);
4070 aopOp (result, ic, TRUE);
4072 genCmp (left, right, result, ifx, sign,ic);
4074 freeAsmop (result, NULL, ic, TRUE);
4077 /*-----------------------------------------------------------------*/
4078 /* gencjneshort - compare and jump if not equal */
4079 /*-----------------------------------------------------------------*/
4081 gencjneshort (operand * left, operand * right, symbol * lbl)
4083 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4085 unsigned long lit = 0L;
4087 /* if the left side is a literal or
4088 if the right is in a pointer register and left
4090 if ((AOP_TYPE (left) == AOP_LIT) ||
4091 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4097 if (AOP_TYPE (right) == AOP_LIT)
4098 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4100 /* if the right side is a literal then anything goes */
4101 if (AOP_TYPE (right) == AOP_LIT &&
4102 AOP_TYPE (left) != AOP_DIR)
4106 emitcode ("cjne", "%s,%s,%05d$",
4107 aopGet (AOP (left), offset, FALSE, FALSE),
4108 aopGet (AOP (right), offset, FALSE, FALSE),
4114 /* if the right side is in a register or in direct space or
4115 if the left is a pointer register & right is not */
4116 else if (AOP_TYPE (right) == AOP_REG ||
4117 AOP_TYPE (right) == AOP_DIR ||
4118 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4119 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4123 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4124 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4125 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4126 emitcode ("jnz", "%05d$", lbl->key + 100);
4128 emitcode ("cjne", "a,%s,%05d$",
4129 aopGet (AOP (right), offset, FALSE, TRUE),
4136 /* right is a pointer reg need both a & b */
4139 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4140 if (strcmp (l, "b"))
4141 emitcode ("mov", "b,%s", l);
4142 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4143 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4149 /*-----------------------------------------------------------------*/
4150 /* gencjne - compare and jump if not equal */
4151 /*-----------------------------------------------------------------*/
4153 gencjne (operand * left, operand * right, symbol * lbl)
4155 symbol *tlbl = newiTempLabel (NULL);
4157 gencjneshort (left, right, lbl);
4159 emitcode ("mov", "a,%s", one);
4160 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4161 emitcode ("", "%05d$:", lbl->key + 100);
4162 emitcode ("clr", "a");
4163 emitcode ("", "%05d$:", tlbl->key + 100);
4166 /*-----------------------------------------------------------------*/
4167 /* genCmpEq - generates code for equal to */
4168 /*-----------------------------------------------------------------*/
4170 genCmpEq (iCode * ic, iCode * ifx)
4172 operand *left, *right, *result;
4174 D(emitcode (";", "genCmpEq"));
4176 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4177 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4178 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4180 /* if literal, literal on the right or
4181 if the right is in a pointer register and left
4183 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4184 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4186 operand *t = IC_RIGHT (ic);
4187 IC_RIGHT (ic) = IC_LEFT (ic);
4191 if (ifx && !AOP_SIZE (result))
4194 /* if they are both bit variables */
4195 if (AOP_TYPE (left) == AOP_CRY &&
4196 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4198 if (AOP_TYPE (right) == AOP_LIT)
4200 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4203 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4204 emitcode ("cpl", "c");
4208 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4212 emitcode ("clr", "c");
4214 /* AOP_TYPE(right) == AOP_CRY */
4218 symbol *lbl = newiTempLabel (NULL);
4219 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4220 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4221 emitcode ("cpl", "c");
4222 emitcode ("", "%05d$:", (lbl->key + 100));
4224 /* if true label then we jump if condition
4226 tlbl = newiTempLabel (NULL);
4229 emitcode ("jnc", "%05d$", tlbl->key + 100);
4230 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4234 emitcode ("jc", "%05d$", tlbl->key + 100);
4235 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4237 emitcode ("", "%05d$:", tlbl->key + 100);
4241 tlbl = newiTempLabel (NULL);
4242 gencjneshort (left, right, tlbl);
4245 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4246 emitcode ("", "%05d$:", tlbl->key + 100);
4250 symbol *lbl = newiTempLabel (NULL);
4251 emitcode ("sjmp", "%05d$", lbl->key + 100);
4252 emitcode ("", "%05d$:", tlbl->key + 100);
4253 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4254 emitcode ("", "%05d$:", lbl->key + 100);
4257 /* mark the icode as generated */
4262 /* if they are both bit variables */
4263 if (AOP_TYPE (left) == AOP_CRY &&
4264 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4266 if (AOP_TYPE (right) == AOP_LIT)
4268 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4271 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4272 emitcode ("cpl", "c");
4276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4280 emitcode ("clr", "c");
4282 /* AOP_TYPE(right) == AOP_CRY */
4286 symbol *lbl = newiTempLabel (NULL);
4287 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4288 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4289 emitcode ("cpl", "c");
4290 emitcode ("", "%05d$:", (lbl->key + 100));
4293 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4300 genIfxJump (ifx, "c");
4303 /* if the result is used in an arithmetic operation
4304 then put the result in place */
4309 gencjne (left, right, newiTempLabel (NULL));
4310 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4312 aopPut (AOP (result), "a", 0);
4317 genIfxJump (ifx, "a");
4320 /* if the result is used in an arithmetic operation
4321 then put the result in place */
4322 if (AOP_TYPE (result) != AOP_CRY)
4324 /* leave the result in acc */
4328 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4329 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4330 freeAsmop (result, NULL, ic, TRUE);
4333 /*-----------------------------------------------------------------*/
4334 /* ifxForOp - returns the icode containing the ifx for operand */
4335 /*-----------------------------------------------------------------*/
4337 ifxForOp (operand * op, iCode * ic)
4339 /* if true symbol then needs to be assigned */
4340 if (IS_TRUE_SYMOP (op))
4343 /* if this has register type condition and
4344 the next instruction is ifx with the same operand
4345 and live to of the operand is upto the ifx only then */
4347 ic->next->op == IFX &&
4348 IC_COND (ic->next)->key == op->key &&
4349 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4355 /*-----------------------------------------------------------------*/
4356 /* hasInc - operand is incremented before any other use */
4357 /*-----------------------------------------------------------------*/
4359 hasInc (operand *op, iCode *ic,int osize)
4361 sym_link *type = operandType(op);
4362 sym_link *retype = getSpec (type);
4363 iCode *lic = ic->next;
4366 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4367 if (!IS_SYMOP(op)) return NULL;
4369 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4370 if (IS_AGGREGATE(type->next)) return NULL;
4371 if (osize != (isize = getSize(type->next))) return NULL;
4374 /* if operand of the form op = op + <sizeof *op> */
4375 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4376 isOperandEqual(IC_RESULT(lic),op) &&
4377 isOperandLiteral(IC_RIGHT(lic)) &&
4378 operandLitValue(IC_RIGHT(lic)) == isize) {
4381 /* if the operand used or deffed */
4382 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4385 /* if GOTO or IFX */
4386 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4392 /*-----------------------------------------------------------------*/
4393 /* genAndOp - for && operation */
4394 /*-----------------------------------------------------------------*/
4396 genAndOp (iCode * ic)
4398 operand *left, *right, *result;
4401 D(emitcode (";", "genAndOp"));
4403 /* note here that && operations that are in an
4404 if statement are taken away by backPatchLabels
4405 only those used in arthmetic operations remain */
4406 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4407 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4408 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4410 /* if both are bit variables */
4411 if (AOP_TYPE (left) == AOP_CRY &&
4412 AOP_TYPE (right) == AOP_CRY)
4414 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4415 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4420 tlbl = newiTempLabel (NULL);
4422 emitcode ("jz", "%05d$", tlbl->key + 100);
4424 emitcode ("", "%05d$:", tlbl->key + 100);
4428 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4429 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4430 freeAsmop (result, NULL, ic, TRUE);
4434 /*-----------------------------------------------------------------*/
4435 /* genOrOp - for || operation */
4436 /*-----------------------------------------------------------------*/
4438 genOrOp (iCode * ic)
4440 operand *left, *right, *result;
4443 D(emitcode (";", "genOrOp"));
4445 /* note here that || operations that are in an
4446 if statement are taken away by backPatchLabels
4447 only those used in arthmetic operations remain */
4448 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4449 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4450 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4452 /* if both are bit variables */
4453 if (AOP_TYPE (left) == AOP_CRY &&
4454 AOP_TYPE (right) == AOP_CRY)
4456 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4457 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4462 tlbl = newiTempLabel (NULL);
4464 emitcode ("jnz", "%05d$", tlbl->key + 100);
4466 emitcode ("", "%05d$:", tlbl->key + 100);
4470 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4471 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4472 freeAsmop (result, NULL, ic, TRUE);
4475 /*-----------------------------------------------------------------*/
4476 /* isLiteralBit - test if lit == 2^n */
4477 /*-----------------------------------------------------------------*/
4479 isLiteralBit (unsigned long lit)
4481 unsigned long pw[32] =
4482 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4483 0x100L, 0x200L, 0x400L, 0x800L,
4484 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4485 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4486 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4487 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4488 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4491 for (idx = 0; idx < 32; idx++)
4497 /*-----------------------------------------------------------------*/
4498 /* continueIfTrue - */
4499 /*-----------------------------------------------------------------*/
4501 continueIfTrue (iCode * ic)
4504 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4508 /*-----------------------------------------------------------------*/
4510 /*-----------------------------------------------------------------*/
4512 jumpIfTrue (iCode * ic)
4515 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4519 /*-----------------------------------------------------------------*/
4520 /* jmpTrueOrFalse - */
4521 /*-----------------------------------------------------------------*/
4523 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4525 // ugly but optimized by peephole
4528 symbol *nlbl = newiTempLabel (NULL);
4529 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4530 emitcode ("", "%05d$:", tlbl->key + 100);
4531 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4532 emitcode ("", "%05d$:", nlbl->key + 100);
4536 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4537 emitcode ("", "%05d$:", tlbl->key + 100);
4542 /*-----------------------------------------------------------------*/
4543 /* genAnd - code for and */
4544 /*-----------------------------------------------------------------*/
4546 genAnd (iCode * ic, iCode * ifx)
4548 operand *left, *right, *result;
4549 int size, offset = 0;
4550 unsigned long lit = 0L;
4554 D(emitcode (";", "genAnd"));
4556 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4557 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4558 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4561 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4563 AOP_TYPE (left), AOP_TYPE (right));
4564 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4566 AOP_SIZE (left), AOP_SIZE (right));
4569 /* if left is a literal & right is not then exchange them */
4570 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4571 AOP_NEEDSACC (left))
4573 operand *tmp = right;
4578 /* if result = right then exchange them */
4579 if (sameRegs (AOP (result), AOP (right)))
4581 operand *tmp = right;
4586 /* if right is bit then exchange them */
4587 if (AOP_TYPE (right) == AOP_CRY &&
4588 AOP_TYPE (left) != AOP_CRY)
4590 operand *tmp = right;
4594 if (AOP_TYPE (right) == AOP_LIT)
4595 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4597 size = AOP_SIZE (result);
4600 // result = bit & yy;
4601 if (AOP_TYPE (left) == AOP_CRY)
4603 // c = bit & literal;
4604 if (AOP_TYPE (right) == AOP_LIT)
4608 if (size && sameRegs (AOP (result), AOP (left)))
4611 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4616 if (size && (AOP_TYPE (result) == AOP_CRY))
4618 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4621 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4626 emitcode ("clr", "c");
4631 if (AOP_TYPE (right) == AOP_CRY)
4634 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4635 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4640 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4642 emitcode ("rrc", "a");
4643 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4651 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4652 genIfxJump (ifx, "c");
4656 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4657 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4658 if ((AOP_TYPE (right) == AOP_LIT) &&
4659 (AOP_TYPE (result) == AOP_CRY) &&
4660 (AOP_TYPE (left) != AOP_CRY))
4662 int posbit = isLiteralBit (lit);
4667 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4670 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4676 sprintf (buffer, "acc.%d", posbit & 0x07);
4677 genIfxJump (ifx, buffer);
4684 symbol *tlbl = newiTempLabel (NULL);
4685 int sizel = AOP_SIZE (left);
4687 emitcode ("setb", "c");
4690 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4692 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4694 if ((posbit = isLiteralBit (bytelit)) != 0)
4695 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4698 if (bytelit != 0x0FFL)
4699 emitcode ("anl", "a,%s",
4700 aopGet (AOP (right), offset, FALSE, TRUE));
4701 emitcode ("jnz", "%05d$", tlbl->key + 100);
4706 // bit = left & literal
4709 emitcode ("clr", "c");
4710 emitcode ("", "%05d$:", tlbl->key + 100);
4712 // if(left & literal)
4716 jmpTrueOrFalse (ifx, tlbl);
4724 /* if left is same as result */
4725 if (sameRegs (AOP (result), AOP (left)))
4727 for (; size--; offset++)
4729 if (AOP_TYPE (right) == AOP_LIT)
4731 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4733 else if (bytelit == 0)
4734 aopPut (AOP (result), zero, offset);
4735 else if (IS_AOP_PREG (result))
4737 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4738 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4739 aopPut (AOP (result), "a", offset);
4742 emitcode ("anl", "%s,%s",
4743 aopGet (AOP (left), offset, FALSE, TRUE),
4744 aopGet (AOP (right), offset, FALSE, FALSE));
4748 if (AOP_TYPE (left) == AOP_ACC)
4749 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4752 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4753 if (IS_AOP_PREG (result))
4755 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4756 aopPut (AOP (result), "a", offset);
4760 emitcode ("anl", "%s,a",
4761 aopGet (AOP (left), offset, FALSE, TRUE));
4768 // left & result in different registers
4769 if (AOP_TYPE (result) == AOP_CRY)
4772 // if(size), result in bit
4773 // if(!size && ifx), conditional oper: if(left & right)
4774 symbol *tlbl = newiTempLabel (NULL);
4775 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4777 emitcode ("setb", "c");
4780 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4781 emitcode ("anl", "a,%s",
4782 aopGet (AOP (right), offset, FALSE, FALSE));
4784 if (AOP_TYPE(left)==AOP_ACC) {
4785 emitcode("mov", "b,a");
4786 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4787 emitcode("anl", "a,b");
4789 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4790 emitcode ("anl", "a,%s",
4791 aopGet (AOP (left), offset, FALSE, FALSE));
4794 emitcode ("jnz", "%05d$", tlbl->key + 100);
4800 emitcode ("", "%05d$:", tlbl->key + 100);
4804 jmpTrueOrFalse (ifx, tlbl);
4808 for (; (size--); offset++)
4811 // result = left & right
4812 if (AOP_TYPE (right) == AOP_LIT)
4814 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4816 aopPut (AOP (result),
4817 aopGet (AOP (left), offset, FALSE, FALSE),
4821 else if (bytelit == 0)
4823 aopPut (AOP (result), zero, offset);
4827 // faster than result <- left, anl result,right
4828 // and better if result is SFR
4829 if (AOP_TYPE (left) == AOP_ACC)
4830 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4833 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4834 emitcode ("anl", "a,%s",
4835 aopGet (AOP (left), offset, FALSE, FALSE));
4837 aopPut (AOP (result), "a", offset);
4843 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4844 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 freeAsmop (result, NULL, ic, TRUE);
4848 /*-----------------------------------------------------------------*/
4849 /* genOr - code for or */
4850 /*-----------------------------------------------------------------*/
4852 genOr (iCode * ic, iCode * ifx)
4854 operand *left, *right, *result;
4855 int size, offset = 0;
4856 unsigned long lit = 0L;
4858 D(emitcode (";", "genOr"));
4860 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4861 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4862 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4865 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4867 AOP_TYPE (left), AOP_TYPE (right));
4868 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4870 AOP_SIZE (left), AOP_SIZE (right));
4873 /* if left is a literal & right is not then exchange them */
4874 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4875 AOP_NEEDSACC (left))
4877 operand *tmp = right;
4882 /* if result = right then exchange them */
4883 if (sameRegs (AOP (result), AOP (right)))
4885 operand *tmp = right;
4890 /* if right is bit then exchange them */
4891 if (AOP_TYPE (right) == AOP_CRY &&
4892 AOP_TYPE (left) != AOP_CRY)
4894 operand *tmp = right;
4898 if (AOP_TYPE (right) == AOP_LIT)
4899 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4901 size = AOP_SIZE (result);
4905 if (AOP_TYPE (left) == AOP_CRY)
4907 if (AOP_TYPE (right) == AOP_LIT)
4909 // c = bit & literal;
4912 // lit != 0 => result = 1
4913 if (AOP_TYPE (result) == AOP_CRY)
4916 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4918 continueIfTrue (ifx);
4921 emitcode ("setb", "c");
4925 // lit == 0 => result = left
4926 if (size && sameRegs (AOP (result), AOP (left)))
4928 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4933 if (AOP_TYPE (right) == AOP_CRY)
4936 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4937 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4942 symbol *tlbl = newiTempLabel (NULL);
4943 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4944 emitcode ("setb", "c");
4945 emitcode ("jb", "%s,%05d$",
4946 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4948 emitcode ("jnz", "%05d$", tlbl->key + 100);
4949 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4951 jmpTrueOrFalse (ifx, tlbl);
4957 emitcode ("", "%05d$:", tlbl->key + 100);
4966 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4967 genIfxJump (ifx, "c");
4971 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4972 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4973 if ((AOP_TYPE (right) == AOP_LIT) &&
4974 (AOP_TYPE (result) == AOP_CRY) &&
4975 (AOP_TYPE (left) != AOP_CRY))
4981 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4983 continueIfTrue (ifx);
4988 // lit = 0, result = boolean(left)
4990 emitcode ("setb", "c");
4994 symbol *tlbl = newiTempLabel (NULL);
4995 emitcode ("jnz", "%05d$", tlbl->key + 100);
4997 emitcode ("", "%05d$:", tlbl->key + 100);
5001 genIfxJump (ifx, "a");
5009 /* if left is same as result */
5010 if (sameRegs (AOP (result), AOP (left)))
5012 for (; size--; offset++)
5014 if (AOP_TYPE (right) == AOP_LIT)
5016 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5018 else if (IS_AOP_PREG (left))
5020 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5021 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5022 aopPut (AOP (result), "a", offset);
5025 emitcode ("orl", "%s,%s",
5026 aopGet (AOP (left), offset, FALSE, TRUE),
5027 aopGet (AOP (right), offset, FALSE, FALSE));
5031 if (AOP_TYPE (left) == AOP_ACC)
5032 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5035 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5036 if (IS_AOP_PREG (left))
5038 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5039 aopPut (AOP (result), "a", offset);
5042 emitcode ("orl", "%s,a",
5043 aopGet (AOP (left), offset, FALSE, TRUE));
5050 // left & result in different registers
5051 if (AOP_TYPE (result) == AOP_CRY)
5054 // if(size), result in bit
5055 // if(!size && ifx), conditional oper: if(left | right)
5056 symbol *tlbl = newiTempLabel (NULL);
5057 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5059 emitcode ("setb", "c");
5062 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5063 emitcode ("orl", "a,%s",
5064 aopGet (AOP (right), offset, FALSE, FALSE));
5066 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5067 emitcode ("orl", "a,%s",
5068 aopGet (AOP (left), offset, FALSE, FALSE));
5070 emitcode ("jnz", "%05d$", tlbl->key + 100);
5076 emitcode ("", "%05d$:", tlbl->key + 100);
5080 jmpTrueOrFalse (ifx, tlbl);
5083 for (; (size--); offset++)
5086 // result = left & right
5087 if (AOP_TYPE (right) == AOP_LIT)
5089 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5091 aopPut (AOP (result),
5092 aopGet (AOP (left), offset, FALSE, FALSE),
5097 // faster than result <- left, anl result,right
5098 // and better if result is SFR
5099 if (AOP_TYPE (left) == AOP_ACC)
5100 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5103 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5104 emitcode ("orl", "a,%s",
5105 aopGet (AOP (left), offset, FALSE, FALSE));
5107 aopPut (AOP (result), "a", offset);
5112 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5113 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5114 freeAsmop (result, NULL, ic, TRUE);
5117 /*-----------------------------------------------------------------*/
5118 /* genXor - code for xclusive or */
5119 /*-----------------------------------------------------------------*/
5121 genXor (iCode * ic, iCode * ifx)
5123 operand *left, *right, *result;
5124 int size, offset = 0;
5125 unsigned long lit = 0L;
5127 D(emitcode (";", "genXor"));
5129 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5130 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5131 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5134 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5136 AOP_TYPE (left), AOP_TYPE (right));
5137 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5139 AOP_SIZE (left), AOP_SIZE (right));
5142 /* if left is a literal & right is not ||
5143 if left needs acc & right does not */
5144 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5145 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5147 operand *tmp = right;
5152 /* if result = right then exchange them */
5153 if (sameRegs (AOP (result), AOP (right)))
5155 operand *tmp = right;
5160 /* if right is bit then exchange them */
5161 if (AOP_TYPE (right) == AOP_CRY &&
5162 AOP_TYPE (left) != AOP_CRY)
5164 operand *tmp = right;
5168 if (AOP_TYPE (right) == AOP_LIT)
5169 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5171 size = AOP_SIZE (result);
5175 if (AOP_TYPE (left) == AOP_CRY)
5177 if (AOP_TYPE (right) == AOP_LIT)
5179 // c = bit & literal;
5182 // lit>>1 != 0 => result = 1
5183 if (AOP_TYPE (result) == AOP_CRY)
5186 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5188 continueIfTrue (ifx);
5191 emitcode ("setb", "c");
5198 // lit == 0, result = left
5199 if (size && sameRegs (AOP (result), AOP (left)))
5201 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5205 // lit == 1, result = not(left)
5206 if (size && sameRegs (AOP (result), AOP (left)))
5208 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5213 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5214 emitcode ("cpl", "c");
5223 symbol *tlbl = newiTempLabel (NULL);
5224 if (AOP_TYPE (right) == AOP_CRY)
5227 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5231 int sizer = AOP_SIZE (right);
5233 // if val>>1 != 0, result = 1
5234 emitcode ("setb", "c");
5237 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5239 // test the msb of the lsb
5240 emitcode ("anl", "a,#0xfe");
5241 emitcode ("jnz", "%05d$", tlbl->key + 100);
5245 emitcode ("rrc", "a");
5247 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5248 emitcode ("cpl", "c");
5249 emitcode ("", "%05d$:", (tlbl->key + 100));
5256 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5257 genIfxJump (ifx, "c");
5261 if (sameRegs (AOP (result), AOP (left)))
5263 /* if left is same as result */
5264 for (; size--; offset++)
5266 if (AOP_TYPE (right) == AOP_LIT)
5268 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5270 else if (IS_AOP_PREG (left))
5272 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5273 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5274 aopPut (AOP (result), "a", offset);
5277 emitcode ("xrl", "%s,%s",
5278 aopGet (AOP (left), offset, FALSE, TRUE),
5279 aopGet (AOP (right), offset, FALSE, FALSE));
5283 if (AOP_TYPE (left) == AOP_ACC)
5284 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5287 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5288 if (IS_AOP_PREG (left))
5290 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5291 aopPut (AOP (result), "a", offset);
5294 emitcode ("xrl", "%s,a",
5295 aopGet (AOP (left), offset, FALSE, TRUE));
5302 // left & result in different registers
5303 if (AOP_TYPE (result) == AOP_CRY)
5306 // if(size), result in bit
5307 // if(!size && ifx), conditional oper: if(left ^ right)
5308 symbol *tlbl = newiTempLabel (NULL);
5309 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5311 emitcode ("setb", "c");
5314 if ((AOP_TYPE (right) == AOP_LIT) &&
5315 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5317 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5321 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5322 emitcode ("xrl", "a,%s",
5323 aopGet (AOP (right), offset, FALSE, FALSE));
5325 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5326 emitcode ("xrl", "a,%s",
5327 aopGet (AOP (left), offset, FALSE, FALSE));
5330 emitcode ("jnz", "%05d$", tlbl->key + 100);
5336 emitcode ("", "%05d$:", tlbl->key + 100);
5340 jmpTrueOrFalse (ifx, tlbl);
5343 for (; (size--); offset++)
5346 // result = left & right
5347 if (AOP_TYPE (right) == AOP_LIT)
5349 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5351 aopPut (AOP (result),
5352 aopGet (AOP (left), offset, FALSE, FALSE),
5357 // faster than result <- left, anl result,right
5358 // and better if result is SFR
5359 if (AOP_TYPE (left) == AOP_ACC)
5360 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5363 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5364 emitcode ("xrl", "a,%s",
5365 aopGet (AOP (left), offset, FALSE, TRUE));
5367 aopPut (AOP (result), "a", offset);
5372 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5373 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5374 freeAsmop (result, NULL, ic, TRUE);
5377 /*-----------------------------------------------------------------*/
5378 /* genInline - write the inline code out */
5379 /*-----------------------------------------------------------------*/
5381 genInline (iCode * ic)
5383 char *buffer, *bp, *bp1;
5385 D(emitcode (";", "genInline"));
5387 _G.inLine += (!options.asmpeep);
5389 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5390 strcpy (buffer, IC_INLINE (ic));
5392 /* emit each line as a code */
5417 /* emitcode("",buffer); */
5418 _G.inLine -= (!options.asmpeep);
5421 /*-----------------------------------------------------------------*/
5422 /* genRRC - rotate right with carry */
5423 /*-----------------------------------------------------------------*/
5427 operand *left, *result;
5428 int size, offset = 0;
5431 D(emitcode (";", "genRRC"));
5433 /* rotate right with carry */
5434 left = IC_LEFT (ic);
5435 result = IC_RESULT (ic);
5436 aopOp (left, ic, FALSE);
5437 aopOp (result, ic, FALSE);
5439 /* move it to the result */
5440 size = AOP_SIZE (result);
5442 if (size == 1) { /* special case for 1 byte */
5443 l = aopGet (AOP (left), offset, FALSE, FALSE);
5445 emitcode ("rr", "a");
5451 l = aopGet (AOP (left), offset, FALSE, FALSE);
5453 emitcode ("rrc", "a");
5454 if (AOP_SIZE (result) > 1)
5455 aopPut (AOP (result), "a", offset--);
5457 /* now we need to put the carry into the
5458 highest order byte of the result */
5459 if (AOP_SIZE (result) > 1)
5461 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5464 emitcode ("mov", "acc.7,c");
5466 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5467 freeAsmop (left, NULL, ic, TRUE);
5468 freeAsmop (result, NULL, ic, TRUE);
5471 /*-----------------------------------------------------------------*/
5472 /* genRLC - generate code for rotate left with carry */
5473 /*-----------------------------------------------------------------*/
5477 operand *left, *result;
5478 int size, offset = 0;
5481 D(emitcode (";", "genRLC"));
5483 /* rotate right with carry */
5484 left = IC_LEFT (ic);
5485 result = IC_RESULT (ic);
5486 aopOp (left, ic, FALSE);
5487 aopOp (result, ic, FALSE);
5489 /* move it to the result */
5490 size = AOP_SIZE (result);
5494 l = aopGet (AOP (left), offset, FALSE, FALSE);
5496 if (size == 0) { /* special case for 1 byte */
5500 emitcode ("add", "a,acc");
5501 if (AOP_SIZE (result) > 1)
5502 aopPut (AOP (result), "a", offset++);
5505 l = aopGet (AOP (left), offset, FALSE, FALSE);
5507 emitcode ("rlc", "a");
5508 if (AOP_SIZE (result) > 1)
5509 aopPut (AOP (result), "a", offset++);
5512 /* now we need to put the carry into the
5513 highest order byte of the result */
5514 if (AOP_SIZE (result) > 1)
5516 l = aopGet (AOP (result), 0, FALSE, FALSE);
5519 emitcode ("mov", "acc.0,c");
5521 aopPut (AOP (result), "a", 0);
5522 freeAsmop (left, NULL, ic, TRUE);
5523 freeAsmop (result, NULL, ic, TRUE);
5526 /*-----------------------------------------------------------------*/
5527 /* genGetHbit - generates code get highest order bit */
5528 /*-----------------------------------------------------------------*/
5530 genGetHbit (iCode * ic)
5532 operand *left, *result;
5534 D(emitcode (";", "genGetHbit"));
5536 left = IC_LEFT (ic);
5537 result = IC_RESULT (ic);
5538 aopOp (left, ic, FALSE);
5539 aopOp (result, ic, FALSE);
5541 /* get the highest order byte into a */
5542 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5543 if (AOP_TYPE (result) == AOP_CRY)
5545 emitcode ("rlc", "a");
5550 emitcode ("rl", "a");
5551 emitcode ("anl", "a,#0x01");
5556 freeAsmop (left, NULL, ic, TRUE);
5557 freeAsmop (result, NULL, ic, TRUE);
5560 /*-----------------------------------------------------------------*/
5561 /* AccRol - rotate left accumulator by known count */
5562 /*-----------------------------------------------------------------*/
5564 AccRol (int shCount)
5566 shCount &= 0x0007; // shCount : 0..7
5573 emitcode ("rl", "a");
5576 emitcode ("rl", "a");
5577 emitcode ("rl", "a");
5580 emitcode ("swap", "a");
5581 emitcode ("rr", "a");
5584 emitcode ("swap", "a");
5587 emitcode ("swap", "a");
5588 emitcode ("rl", "a");
5591 emitcode ("rr", "a");
5592 emitcode ("rr", "a");
5595 emitcode ("rr", "a");
5600 /*-----------------------------------------------------------------*/
5601 /* AccLsh - left shift accumulator by known count */
5602 /*-----------------------------------------------------------------*/
5604 AccLsh (int shCount)
5609 emitcode ("add", "a,acc");
5610 else if (shCount == 2)
5612 emitcode ("add", "a,acc");
5613 emitcode ("add", "a,acc");
5617 /* rotate left accumulator */
5619 /* and kill the lower order bits */
5620 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5625 /*-----------------------------------------------------------------*/
5626 /* AccRsh - right shift accumulator by known count */
5627 /*-----------------------------------------------------------------*/
5629 AccRsh (int shCount)
5636 emitcode ("rrc", "a");
5640 /* rotate right accumulator */
5641 AccRol (8 - shCount);
5642 /* and kill the higher order bits */
5643 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5648 /*-----------------------------------------------------------------*/
5649 /* AccSRsh - signed right shift accumulator by known count */
5650 /*-----------------------------------------------------------------*/
5652 AccSRsh (int shCount)
5659 emitcode ("mov", "c,acc.7");
5660 emitcode ("rrc", "a");
5662 else if (shCount == 2)
5664 emitcode ("mov", "c,acc.7");
5665 emitcode ("rrc", "a");
5666 emitcode ("mov", "c,acc.7");
5667 emitcode ("rrc", "a");
5671 tlbl = newiTempLabel (NULL);
5672 /* rotate right accumulator */
5673 AccRol (8 - shCount);
5674 /* and kill the higher order bits */
5675 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5676 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5677 emitcode ("orl", "a,#0x%02x",
5678 (unsigned char) ~SRMask[shCount]);
5679 emitcode ("", "%05d$:", tlbl->key + 100);
5684 /*-----------------------------------------------------------------*/
5685 /* shiftR1Left2Result - shift right one byte from left to result */
5686 /*-----------------------------------------------------------------*/
5688 shiftR1Left2Result (operand * left, int offl,
5689 operand * result, int offr,
5690 int shCount, int sign)
5692 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5693 /* shift right accumulator */
5698 aopPut (AOP (result), "a", offr);
5701 /*-----------------------------------------------------------------*/
5702 /* shiftL1Left2Result - shift left one byte from left to result */
5703 /*-----------------------------------------------------------------*/
5705 shiftL1Left2Result (operand * left, int offl,
5706 operand * result, int offr, int shCount)
5709 l = aopGet (AOP (left), offl, FALSE, FALSE);
5711 /* shift left accumulator */
5713 aopPut (AOP (result), "a", offr);
5716 /*-----------------------------------------------------------------*/
5717 /* movLeft2Result - move byte from left to result */
5718 /*-----------------------------------------------------------------*/
5720 movLeft2Result (operand * left, int offl,
5721 operand * result, int offr, int sign)
5724 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5726 l = aopGet (AOP (left), offl, FALSE, FALSE);
5728 if (*l == '@' && (IS_AOP_PREG (result)))
5730 emitcode ("mov", "a,%s", l);
5731 aopPut (AOP (result), "a", offr);
5736 aopPut (AOP (result), l, offr);
5739 /* MSB sign in acc.7 ! */
5740 if (getDataSize (left) == offl + 1)
5742 emitcode ("mov", "a,%s", l);
5743 aopPut (AOP (result), "a", offr);
5750 /*-----------------------------------------------------------------*/
5751 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5752 /*-----------------------------------------------------------------*/
5756 emitcode ("rrc", "a");
5757 emitcode ("xch", "a,%s", x);
5758 emitcode ("rrc", "a");
5759 emitcode ("xch", "a,%s", x);
5762 /*-----------------------------------------------------------------*/
5763 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5764 /*-----------------------------------------------------------------*/
5768 emitcode ("xch", "a,%s", x);
5769 emitcode ("rlc", "a");
5770 emitcode ("xch", "a,%s", x);
5771 emitcode ("rlc", "a");
5774 /*-----------------------------------------------------------------*/
5775 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5776 /*-----------------------------------------------------------------*/
5780 emitcode ("xch", "a,%s", x);
5781 emitcode ("add", "a,acc");
5782 emitcode ("xch", "a,%s", x);
5783 emitcode ("rlc", "a");
5786 /*-----------------------------------------------------------------*/
5787 /* AccAXLsh - left shift a:x by known count (0..7) */
5788 /*-----------------------------------------------------------------*/
5790 AccAXLsh (char *x, int shCount)
5805 case 5: // AAAAABBB:CCCCCDDD
5807 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5809 emitcode ("anl", "a,#0x%02x",
5810 SLMask[shCount]); // BBB00000:CCCCCDDD
5812 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5814 AccRol (shCount); // DDDCCCCC:BBB00000
5816 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5818 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5820 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5822 emitcode ("anl", "a,#0x%02x",
5823 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5825 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5827 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5830 case 6: // AAAAAABB:CCCCCCDD
5831 emitcode ("anl", "a,#0x%02x",
5832 SRMask[shCount]); // 000000BB:CCCCCCDD
5833 emitcode ("mov", "c,acc.0"); // c = B
5834 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5836 AccAXRrl1 (x); // BCCCCCCD:D000000B
5837 AccAXRrl1 (x); // BBCCCCCC:DD000000
5839 emitcode("rrc","a");
5840 emitcode("xch","a,%s", x);
5841 emitcode("rrc","a");
5842 emitcode("mov","c,acc.0"); //<< get correct bit
5843 emitcode("xch","a,%s", x);
5845 emitcode("rrc","a");
5846 emitcode("xch","a,%s", x);
5847 emitcode("rrc","a");
5848 emitcode("xch","a,%s", x);
5851 case 7: // a:x <<= 7
5853 emitcode ("anl", "a,#0x%02x",
5854 SRMask[shCount]); // 0000000B:CCCCCCCD
5856 emitcode ("mov", "c,acc.0"); // c = B
5858 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5860 AccAXRrl1 (x); // BCCCCCCC:D0000000
5868 /*-----------------------------------------------------------------*/
5869 /* AccAXRsh - right shift a:x known count (0..7) */
5870 /*-----------------------------------------------------------------*/
5872 AccAXRsh (char *x, int shCount)
5880 AccAXRrl1 (x); // 0->a:x
5885 AccAXRrl1 (x); // 0->a:x
5888 AccAXRrl1 (x); // 0->a:x
5893 case 5: // AAAAABBB:CCCCCDDD = a:x
5895 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5897 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5899 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5901 emitcode ("anl", "a,#0x%02x",
5902 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5904 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5906 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5908 emitcode ("anl", "a,#0x%02x",
5909 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5911 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5913 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5915 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5918 case 6: // AABBBBBB:CCDDDDDD
5920 emitcode ("mov", "c,acc.7");
5921 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5923 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5925 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5927 emitcode ("anl", "a,#0x%02x",
5928 SRMask[shCount]); // 000000AA:BBBBBBCC
5931 case 7: // ABBBBBBB:CDDDDDDD
5933 emitcode ("mov", "c,acc.7"); // c = A
5935 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5937 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5939 emitcode ("anl", "a,#0x%02x",
5940 SRMask[shCount]); // 0000000A:BBBBBBBC
5948 /*-----------------------------------------------------------------*/
5949 /* AccAXRshS - right shift signed a:x known count (0..7) */
5950 /*-----------------------------------------------------------------*/
5952 AccAXRshS (char *x, int shCount)
5960 emitcode ("mov", "c,acc.7");
5961 AccAXRrl1 (x); // s->a:x
5965 emitcode ("mov", "c,acc.7");
5966 AccAXRrl1 (x); // s->a:x
5968 emitcode ("mov", "c,acc.7");
5969 AccAXRrl1 (x); // s->a:x
5974 case 5: // AAAAABBB:CCCCCDDD = a:x
5976 tlbl = newiTempLabel (NULL);
5977 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5979 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5981 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5983 emitcode ("anl", "a,#0x%02x",
5984 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5986 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5988 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5990 emitcode ("anl", "a,#0x%02x",
5991 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5993 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5995 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5997 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5999 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6000 emitcode ("orl", "a,#0x%02x",
6001 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6003 emitcode ("", "%05d$:", tlbl->key + 100);
6004 break; // SSSSAAAA:BBBCCCCC
6006 case 6: // AABBBBBB:CCDDDDDD
6008 tlbl = newiTempLabel (NULL);
6009 emitcode ("mov", "c,acc.7");
6010 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6012 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6014 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6016 emitcode ("anl", "a,#0x%02x",
6017 SRMask[shCount]); // 000000AA:BBBBBBCC
6019 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6020 emitcode ("orl", "a,#0x%02x",
6021 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6023 emitcode ("", "%05d$:", tlbl->key + 100);
6025 case 7: // ABBBBBBB:CDDDDDDD
6027 tlbl = newiTempLabel (NULL);
6028 emitcode ("mov", "c,acc.7"); // c = A
6030 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6032 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6034 emitcode ("anl", "a,#0x%02x",
6035 SRMask[shCount]); // 0000000A:BBBBBBBC
6037 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6038 emitcode ("orl", "a,#0x%02x",
6039 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6041 emitcode ("", "%05d$:", tlbl->key + 100);
6048 /*-----------------------------------------------------------------*/
6049 /* shiftL2Left2Result - shift left two bytes from left to result */
6050 /*-----------------------------------------------------------------*/
6052 shiftL2Left2Result (operand * left, int offl,
6053 operand * result, int offr, int shCount)
6055 if (sameRegs (AOP (result), AOP (left)) &&
6056 ((offl + MSB16) == offr))
6058 /* don't crash result[offr] */
6059 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6060 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6064 movLeft2Result (left, offl, result, offr, 0);
6065 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6067 /* ax << shCount (x = lsb(result)) */
6068 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6069 aopPut (AOP (result), "a", offr + MSB16);
6073 /*-----------------------------------------------------------------*/
6074 /* shiftR2Left2Result - shift right two bytes from left to result */
6075 /*-----------------------------------------------------------------*/
6077 shiftR2Left2Result (operand * left, int offl,
6078 operand * result, int offr,
6079 int shCount, int sign)
6081 if (sameRegs (AOP (result), AOP (left)) &&
6082 ((offl + MSB16) == offr))
6084 /* don't crash result[offr] */
6085 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6086 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6090 movLeft2Result (left, offl, result, offr, 0);
6091 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6093 /* a:x >> shCount (x = lsb(result)) */
6095 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6097 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6098 if (getDataSize (result) > 1)
6099 aopPut (AOP (result), "a", offr + MSB16);
6102 /*-----------------------------------------------------------------*/
6103 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6104 /*-----------------------------------------------------------------*/
6106 shiftLLeftOrResult (operand * left, int offl,
6107 operand * result, int offr, int shCount)
6109 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6110 /* shift left accumulator */
6112 /* or with result */
6113 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6114 /* back to result */
6115 aopPut (AOP (result), "a", offr);
6118 /*-----------------------------------------------------------------*/
6119 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6120 /*-----------------------------------------------------------------*/
6122 shiftRLeftOrResult (operand * left, int offl,
6123 operand * result, int offr, int shCount)
6125 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6126 /* shift right accumulator */
6128 /* or with result */
6129 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6130 /* back to result */
6131 aopPut (AOP (result), "a", offr);
6134 /*-----------------------------------------------------------------*/
6135 /* genlshOne - left shift a one byte quantity by known count */
6136 /*-----------------------------------------------------------------*/
6138 genlshOne (operand * result, operand * left, int shCount)
6140 D(emitcode (";", "genlshOne"));
6142 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6145 /*-----------------------------------------------------------------*/
6146 /* genlshTwo - left shift two bytes by known amount != 0 */
6147 /*-----------------------------------------------------------------*/
6149 genlshTwo (operand * result, operand * left, int shCount)
6153 D(emitcode (";", "genlshTwo"));
6155 size = getDataSize (result);
6157 /* if shCount >= 8 */
6165 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6167 movLeft2Result (left, LSB, result, MSB16, 0);
6169 aopPut (AOP (result), zero, LSB);
6172 /* 1 <= shCount <= 7 */
6176 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6178 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6182 /*-----------------------------------------------------------------*/
6183 /* shiftLLong - shift left one long from left to result */
6184 /* offl = LSB or MSB16 */
6185 /*-----------------------------------------------------------------*/
6187 shiftLLong (operand * left, operand * result, int offr)
6190 int size = AOP_SIZE (result);
6192 if (size >= LSB + offr)
6194 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6196 emitcode ("add", "a,acc");
6197 if (sameRegs (AOP (left), AOP (result)) &&
6198 size >= MSB16 + offr && offr != LSB)
6199 emitcode ("xch", "a,%s",
6200 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6202 aopPut (AOP (result), "a", LSB + offr);
6205 if (size >= MSB16 + offr)
6207 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6209 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6212 emitcode ("rlc", "a");
6213 if (sameRegs (AOP (left), AOP (result)) &&
6214 size >= MSB24 + offr && offr != LSB)
6215 emitcode ("xch", "a,%s",
6216 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6218 aopPut (AOP (result), "a", MSB16 + offr);
6221 if (size >= MSB24 + offr)
6223 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6225 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6228 emitcode ("rlc", "a");
6229 if (sameRegs (AOP (left), AOP (result)) &&
6230 size >= MSB32 + offr && offr != LSB)
6231 emitcode ("xch", "a,%s",
6232 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6234 aopPut (AOP (result), "a", MSB24 + offr);
6237 if (size > MSB32 + offr)
6239 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6241 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6244 emitcode ("rlc", "a");
6245 aopPut (AOP (result), "a", MSB32 + offr);
6248 aopPut (AOP (result), zero, LSB);
6251 /*-----------------------------------------------------------------*/
6252 /* genlshFour - shift four byte by a known amount != 0 */
6253 /*-----------------------------------------------------------------*/
6255 genlshFour (operand * result, operand * left, int shCount)
6259 D(emitcode (";", "genlshFour"));
6261 size = AOP_SIZE (result);
6263 /* if shifting more that 3 bytes */
6268 /* lowest order of left goes to the highest
6269 order of the destination */
6270 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6272 movLeft2Result (left, LSB, result, MSB32, 0);
6273 aopPut (AOP (result), zero, LSB);
6274 aopPut (AOP (result), zero, MSB16);
6275 aopPut (AOP (result), zero, MSB24);
6279 /* more than two bytes */
6280 else if (shCount >= 16)
6282 /* lower order two bytes goes to higher order two bytes */
6284 /* if some more remaining */
6286 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6289 movLeft2Result (left, MSB16, result, MSB32, 0);
6290 movLeft2Result (left, LSB, result, MSB24, 0);
6292 aopPut (AOP (result), zero, MSB16);
6293 aopPut (AOP (result), zero, LSB);
6297 /* if more than 1 byte */
6298 else if (shCount >= 8)
6300 /* lower order three bytes goes to higher order three bytes */
6305 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6307 movLeft2Result (left, LSB, result, MSB16, 0);
6313 movLeft2Result (left, MSB24, result, MSB32, 0);
6314 movLeft2Result (left, MSB16, result, MSB24, 0);
6315 movLeft2Result (left, LSB, result, MSB16, 0);
6316 aopPut (AOP (result), zero, LSB);
6318 else if (shCount == 1)
6319 shiftLLong (left, result, MSB16);
6322 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6323 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6324 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6325 aopPut (AOP (result), zero, LSB);
6330 /* 1 <= shCount <= 7 */
6331 else if (shCount <= 2)
6333 shiftLLong (left, result, LSB);
6335 shiftLLong (result, result, LSB);
6337 /* 3 <= shCount <= 7, optimize */
6340 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6341 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6342 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6346 /*-----------------------------------------------------------------*/
6347 /* genLeftShiftLiteral - left shifting by known count */
6348 /*-----------------------------------------------------------------*/
6350 genLeftShiftLiteral (operand * left,
6355 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6358 D(emitcode (";", "genLeftShiftLiteral"));
6360 freeAsmop (right, NULL, ic, TRUE);
6362 aopOp (left, ic, FALSE);
6363 aopOp (result, ic, FALSE);
6365 size = getSize (operandType (result));
6368 emitcode ("; shift left ", "result %d, left %d", size,
6372 /* I suppose that the left size >= result size */
6377 movLeft2Result (left, size, result, size, 0);
6381 else if (shCount >= (size * 8))
6383 aopPut (AOP (result), zero, size);
6389 genlshOne (result, left, shCount);
6393 genlshTwo (result, left, shCount);
6397 genlshFour (result, left, shCount);
6400 fprintf(stderr, "*** ack! mystery literal shift!\n");
6404 freeAsmop (left, NULL, ic, TRUE);
6405 freeAsmop (result, NULL, ic, TRUE);
6408 /*-----------------------------------------------------------------*/
6409 /* genLeftShift - generates code for left shifting */
6410 /*-----------------------------------------------------------------*/
6412 genLeftShift (iCode * ic)
6414 operand *left, *right, *result;
6417 symbol *tlbl, *tlbl1;
6419 D(emitcode (";", "genLeftShift"));
6421 right = IC_RIGHT (ic);
6422 left = IC_LEFT (ic);
6423 result = IC_RESULT (ic);
6425 aopOp (right, ic, FALSE);
6427 /* if the shift count is known then do it
6428 as efficiently as possible */
6429 if (AOP_TYPE (right) == AOP_LIT)
6431 genLeftShiftLiteral (left, right, result, ic);
6435 /* shift count is unknown then we have to form
6436 a loop get the loop count in B : Note: we take
6437 only the lower order byte since shifting
6438 more that 32 bits make no sense anyway, ( the
6439 largest size of an object can be only 32 bits ) */
6441 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6442 emitcode ("inc", "b");
6443 freeAsmop (right, NULL, ic, TRUE);
6444 aopOp (left, ic, FALSE);
6445 aopOp (result, ic, FALSE);
6447 /* now move the left to the result if they are not the
6449 if (!sameRegs (AOP (left), AOP (result)) &&
6450 AOP_SIZE (result) > 1)
6453 size = AOP_SIZE (result);
6457 l = aopGet (AOP (left), offset, FALSE, TRUE);
6458 if (*l == '@' && (IS_AOP_PREG (result)))
6461 emitcode ("mov", "a,%s", l);
6462 aopPut (AOP (result), "a", offset);
6465 aopPut (AOP (result), l, offset);
6470 tlbl = newiTempLabel (NULL);
6471 size = AOP_SIZE (result);
6473 tlbl1 = newiTempLabel (NULL);
6475 /* if it is only one byte then */
6478 symbol *tlbl1 = newiTempLabel (NULL);
6480 l = aopGet (AOP (left), 0, FALSE, FALSE);
6482 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6483 emitcode ("", "%05d$:", tlbl->key + 100);
6484 emitcode ("add", "a,acc");
6485 emitcode ("", "%05d$:", tlbl1->key + 100);
6486 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6487 aopPut (AOP (result), "a", 0);
6491 reAdjustPreg (AOP (result));
6493 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6494 emitcode ("", "%05d$:", tlbl->key + 100);
6495 l = aopGet (AOP (result), offset, FALSE, FALSE);
6497 emitcode ("add", "a,acc");
6498 aopPut (AOP (result), "a", offset++);
6501 l = aopGet (AOP (result), offset, FALSE, FALSE);
6503 emitcode ("rlc", "a");
6504 aopPut (AOP (result), "a", offset++);
6506 reAdjustPreg (AOP (result));
6508 emitcode ("", "%05d$:", tlbl1->key + 100);
6509 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6511 freeAsmop (left, NULL, ic, TRUE);
6512 freeAsmop (result, NULL, ic, TRUE);
6515 /*-----------------------------------------------------------------*/
6516 /* genrshOne - right shift a one byte quantity by known count */
6517 /*-----------------------------------------------------------------*/
6519 genrshOne (operand * result, operand * left,
6520 int shCount, int sign)
6522 D(emitcode (";", "genrshOne"));
6524 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6527 /*-----------------------------------------------------------------*/
6528 /* genrshTwo - right shift two bytes by known amount != 0 */
6529 /*-----------------------------------------------------------------*/
6531 genrshTwo (operand * result, operand * left,
6532 int shCount, int sign)
6534 D(emitcode (";", "genrshTwo"));
6536 /* if shCount >= 8 */
6541 shiftR1Left2Result (left, MSB16, result, LSB,
6544 movLeft2Result (left, MSB16, result, LSB, sign);
6545 addSign (result, MSB16, sign);
6548 /* 1 <= shCount <= 7 */
6550 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6553 /*-----------------------------------------------------------------*/
6554 /* shiftRLong - shift right one long from left to result */
6555 /* offl = LSB or MSB16 */
6556 /*-----------------------------------------------------------------*/
6558 shiftRLong (operand * left, int offl,
6559 operand * result, int sign)
6561 int isSameRegs=sameRegs(AOP(left),AOP(result));
6563 if (isSameRegs && offl>1) {
6564 // we are in big trouble, but this shouldn't happen
6565 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6568 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6573 emitcode ("rlc", "a");
6574 emitcode ("subb", "a,acc");
6575 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6577 aopPut (AOP(result), zero, MSB32);
6582 emitcode ("clr", "c");
6584 emitcode ("mov", "c,acc.7");
6587 emitcode ("rrc", "a");
6589 if (isSameRegs && offl==MSB16) {
6590 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6592 aopPut (AOP (result), "a", MSB32);
6593 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6596 emitcode ("rrc", "a");
6597 if (isSameRegs && offl==1) {
6598 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6600 aopPut (AOP (result), "a", MSB24);
6601 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6603 emitcode ("rrc", "a");
6604 aopPut (AOP (result), "a", MSB16 - offl);
6608 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6609 emitcode ("rrc", "a");
6610 aopPut (AOP (result), "a", LSB);
6614 /*-----------------------------------------------------------------*/
6615 /* genrshFour - shift four byte by a known amount != 0 */
6616 /*-----------------------------------------------------------------*/
6618 genrshFour (operand * result, operand * left,
6619 int shCount, int sign)
6621 D(emitcode (";", "genrshFour"));
6623 /* if shifting more that 3 bytes */
6628 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6630 movLeft2Result (left, MSB32, result, LSB, sign);
6631 addSign (result, MSB16, sign);
6633 else if (shCount >= 16)
6637 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6640 movLeft2Result (left, MSB24, result, LSB, 0);
6641 movLeft2Result (left, MSB32, result, MSB16, sign);
6643 addSign (result, MSB24, sign);
6645 else if (shCount >= 8)
6649 shiftRLong (left, MSB16, result, sign);
6650 else if (shCount == 0)
6652 movLeft2Result (left, MSB16, result, LSB, 0);
6653 movLeft2Result (left, MSB24, result, MSB16, 0);
6654 movLeft2Result (left, MSB32, result, MSB24, sign);
6655 addSign (result, MSB32, sign);
6659 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6660 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6661 /* the last shift is signed */
6662 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6663 addSign (result, MSB32, sign);
6667 { /* 1 <= shCount <= 7 */
6670 shiftRLong (left, LSB, result, sign);
6672 shiftRLong (result, LSB, result, sign);
6676 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6677 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6678 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6683 /*-----------------------------------------------------------------*/
6684 /* genRightShiftLiteral - right shifting by known count */
6685 /*-----------------------------------------------------------------*/
6687 genRightShiftLiteral (operand * left,
6693 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6696 D(emitcode (";", "genRightShiftLiteral"));
6698 freeAsmop (right, NULL, ic, TRUE);
6700 aopOp (left, ic, FALSE);
6701 aopOp (result, ic, FALSE);
6704 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6708 size = getDataSize (left);
6709 /* test the LEFT size !!! */
6711 /* I suppose that the left size >= result size */
6714 size = getDataSize (result);
6716 movLeft2Result (left, size, result, size, 0);
6719 else if (shCount >= (size * 8))
6722 /* get sign in acc.7 */
6723 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6724 addSign (result, LSB, sign);
6731 genrshOne (result, left, shCount, sign);
6735 genrshTwo (result, left, shCount, sign);
6739 genrshFour (result, left, shCount, sign);
6745 freeAsmop (left, NULL, ic, TRUE);
6746 freeAsmop (result, NULL, ic, TRUE);
6750 /*-----------------------------------------------------------------*/
6751 /* genSignedRightShift - right shift of signed number */
6752 /*-----------------------------------------------------------------*/
6754 genSignedRightShift (iCode * ic)
6756 operand *right, *left, *result;
6759 symbol *tlbl, *tlbl1;
6761 D(emitcode (";", "genSignedRightShift"));
6763 /* we do it the hard way put the shift count in b
6764 and loop thru preserving the sign */
6766 right = IC_RIGHT (ic);
6767 left = IC_LEFT (ic);
6768 result = IC_RESULT (ic);
6770 aopOp (right, ic, FALSE);
6773 if (AOP_TYPE (right) == AOP_LIT)
6775 genRightShiftLiteral (left, right, result, ic, 1);
6778 /* shift count is unknown then we have to form
6779 a loop get the loop count in B : Note: we take
6780 only the lower order byte since shifting
6781 more that 32 bits make no sense anyway, ( the
6782 largest size of an object can be only 32 bits ) */
6784 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6785 emitcode ("inc", "b");
6786 freeAsmop (right, NULL, ic, TRUE);
6787 aopOp (left, ic, FALSE);
6788 aopOp (result, ic, FALSE);
6790 /* now move the left to the result if they are not the
6792 if (!sameRegs (AOP (left), AOP (result)) &&
6793 AOP_SIZE (result) > 1)
6796 size = AOP_SIZE (result);
6800 l = aopGet (AOP (left), offset, FALSE, TRUE);
6801 if (*l == '@' && IS_AOP_PREG (result))
6804 emitcode ("mov", "a,%s", l);
6805 aopPut (AOP (result), "a", offset);
6808 aopPut (AOP (result), l, offset);
6813 /* mov the highest order bit to OVR */
6814 tlbl = newiTempLabel (NULL);
6815 tlbl1 = newiTempLabel (NULL);
6817 size = AOP_SIZE (result);
6819 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6820 emitcode ("rlc", "a");
6821 emitcode ("mov", "ov,c");
6822 /* if it is only one byte then */
6825 l = aopGet (AOP (left), 0, FALSE, FALSE);
6827 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6828 emitcode ("", "%05d$:", tlbl->key + 100);
6829 emitcode ("mov", "c,ov");
6830 emitcode ("rrc", "a");
6831 emitcode ("", "%05d$:", tlbl1->key + 100);
6832 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6833 aopPut (AOP (result), "a", 0);
6837 reAdjustPreg (AOP (result));
6838 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6839 emitcode ("", "%05d$:", tlbl->key + 100);
6840 emitcode ("mov", "c,ov");
6843 l = aopGet (AOP (result), offset, FALSE, FALSE);
6845 emitcode ("rrc", "a");
6846 aopPut (AOP (result), "a", offset--);
6848 reAdjustPreg (AOP (result));
6849 emitcode ("", "%05d$:", tlbl1->key + 100);
6850 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6853 freeAsmop (left, NULL, ic, TRUE);
6854 freeAsmop (result, NULL, ic, TRUE);
6857 /*-----------------------------------------------------------------*/
6858 /* genRightShift - generate code for right shifting */
6859 /*-----------------------------------------------------------------*/
6861 genRightShift (iCode * ic)
6863 operand *right, *left, *result;
6867 symbol *tlbl, *tlbl1;
6869 D(emitcode (";", "genRightShift"));
6871 /* if signed then we do it the hard way preserve the
6872 sign bit moving it inwards */
6873 retype = getSpec (operandType (IC_RESULT (ic)));
6875 if (!SPEC_USIGN (retype))
6877 genSignedRightShift (ic);
6881 /* signed & unsigned types are treated the same : i.e. the
6882 signed is NOT propagated inwards : quoting from the
6883 ANSI - standard : "for E1 >> E2, is equivalent to division
6884 by 2**E2 if unsigned or if it has a non-negative value,
6885 otherwise the result is implementation defined ", MY definition
6886 is that the sign does not get propagated */
6888 right = IC_RIGHT (ic);
6889 left = IC_LEFT (ic);
6890 result = IC_RESULT (ic);
6892 aopOp (right, ic, FALSE);
6894 /* if the shift count is known then do it
6895 as efficiently as possible */
6896 if (AOP_TYPE (right) == AOP_LIT)
6898 genRightShiftLiteral (left, right, result, ic, 0);
6902 /* shift count is unknown then we have to form
6903 a loop get the loop count in B : Note: we take
6904 only the lower order byte since shifting
6905 more that 32 bits make no sense anyway, ( the
6906 largest size of an object can be only 32 bits ) */
6908 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6909 emitcode ("inc", "b");
6910 freeAsmop (right, NULL, ic, TRUE);
6911 aopOp (left, ic, FALSE);
6912 aopOp (result, ic, FALSE);
6914 /* now move the left to the result if they are not the
6916 if (!sameRegs (AOP (left), AOP (result)) &&
6917 AOP_SIZE (result) > 1)
6920 size = AOP_SIZE (result);
6924 l = aopGet (AOP (left), offset, FALSE, TRUE);
6925 if (*l == '@' && IS_AOP_PREG (result))
6928 emitcode ("mov", "a,%s", l);
6929 aopPut (AOP (result), "a", offset);
6932 aopPut (AOP (result), l, offset);
6937 tlbl = newiTempLabel (NULL);
6938 tlbl1 = newiTempLabel (NULL);
6939 size = AOP_SIZE (result);
6942 /* if it is only one byte then */
6945 l = aopGet (AOP (left), 0, FALSE, FALSE);
6947 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6948 emitcode ("", "%05d$:", tlbl->key + 100);
6950 emitcode ("rrc", "a");
6951 emitcode ("", "%05d$:", tlbl1->key + 100);
6952 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6953 aopPut (AOP (result), "a", 0);
6957 reAdjustPreg (AOP (result));
6958 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6959 emitcode ("", "%05d$:", tlbl->key + 100);
6963 l = aopGet (AOP (result), offset, FALSE, FALSE);
6965 emitcode ("rrc", "a");
6966 aopPut (AOP (result), "a", offset--);
6968 reAdjustPreg (AOP (result));
6970 emitcode ("", "%05d$:", tlbl1->key + 100);
6971 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6974 freeAsmop (left, NULL, ic, TRUE);
6975 freeAsmop (result, NULL, ic, TRUE);
6978 /*-----------------------------------------------------------------*/
6979 /* genUnpackBits - generates code for unpacking bits */
6980 /*-----------------------------------------------------------------*/
6982 genUnpackBits (operand * result, char *rname, int ptype)
6990 D(emitcode (";", "genUnpackBits"));
6992 etype = getSpec (operandType (result));
6993 rsize = getSize (operandType (result));
6994 /* read the first byte */
7000 emitcode ("mov", "a,@%s", rname);
7004 emitcode ("movx", "a,@%s", rname);
7008 emitcode ("movx", "a,@dptr");
7012 emitcode ("clr", "a");
7013 emitcode ("movc", "a,@a+dptr");
7017 emitcode ("lcall", "__gptrget");
7021 rlen = SPEC_BLEN (etype);
7023 /* if we have bitdisplacement then it fits */
7024 /* into this byte completely or if length is */
7025 /* less than a byte */
7026 if ((shCnt = SPEC_BSTR (etype)) ||
7027 (SPEC_BLEN (etype) <= 8))
7030 /* shift right acc */
7033 emitcode ("anl", "a,#0x%02x",
7034 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7035 aopPut (AOP (result), "a", offset++);
7039 /* bit field did not fit in a byte */
7040 aopPut (AOP (result), "a", offset++);
7049 emitcode ("inc", "%s", rname);
7050 emitcode ("mov", "a,@%s", rname);
7054 emitcode ("inc", "%s", rname);
7055 emitcode ("movx", "a,@%s", rname);
7059 emitcode ("inc", "dptr");
7060 emitcode ("movx", "a,@dptr");
7064 emitcode ("clr", "a");
7065 emitcode ("inc", "dptr");
7066 emitcode ("movc", "a,@a+dptr");
7070 emitcode ("inc", "dptr");
7071 emitcode ("lcall", "__gptrget");
7076 /* if we are done */
7080 aopPut (AOP (result), "a", offset++);
7086 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7088 aopPut (AOP (result), "a", offset++);
7096 aopPut (AOP (result), zero, offset++);
7102 /*-----------------------------------------------------------------*/
7103 /* genDataPointerGet - generates code when ptr offset is known */
7104 /*-----------------------------------------------------------------*/
7106 genDataPointerGet (operand * left,
7112 int size, offset = 0;
7114 D(emitcode (";", "genDataPointerGet"));
7116 aopOp (result, ic, TRUE);
7118 /* get the string representation of the name */
7119 l = aopGet (AOP (left), 0, FALSE, TRUE);
7120 size = AOP_SIZE (result);
7124 sprintf (buffer, "(%s + %d)", l + 1, offset);
7126 sprintf (buffer, "%s", l + 1);
7127 aopPut (AOP (result), buffer, offset++);
7130 freeAsmop (left, NULL, ic, TRUE);
7131 freeAsmop (result, NULL, ic, TRUE);
7134 /*-----------------------------------------------------------------*/
7135 /* genNearPointerGet - emitcode for near pointer fetch */
7136 /*-----------------------------------------------------------------*/
7138 genNearPointerGet (operand * left,
7146 sym_link *rtype, *retype;
7147 sym_link *ltype = operandType (left);
7150 D(emitcode (";", "genNearPointerGet"));
7152 rtype = operandType (result);
7153 retype = getSpec (rtype);
7155 aopOp (left, ic, FALSE);
7157 /* if left is rematerialisable and
7158 result is not bit variable type and
7159 the left is pointer to data space i.e
7160 lower 128 bytes of space */
7161 if (AOP_TYPE (left) == AOP_IMMD &&
7162 !IS_BITVAR (retype) &&
7163 DCL_TYPE (ltype) == POINTER)
7165 genDataPointerGet (left, result, ic);
7169 /* if the value is already in a pointer register
7170 then don't need anything more */
7171 if (!AOP_INPREG (AOP (left)))
7173 /* otherwise get a free pointer register */
7175 preg = getFreePtr (ic, &aop, FALSE);
7176 emitcode ("mov", "%s,%s",
7178 aopGet (AOP (left), 0, FALSE, TRUE));
7182 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7184 //aopOp (result, ic, FALSE);
7185 aopOp (result, ic, result?TRUE:FALSE);
7187 /* if bitfield then unpack the bits */
7188 if (IS_BITVAR (retype))
7189 genUnpackBits (result, rname, POINTER);
7192 /* we have can just get the values */
7193 int size = AOP_SIZE (result);
7198 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7201 emitcode ("mov", "a,@%s", rname);
7202 aopPut (AOP (result), "a", offset);
7206 sprintf (buffer, "@%s", rname);
7207 aopPut (AOP (result), buffer, offset);
7211 emitcode ("inc", "%s", rname);
7215 /* now some housekeeping stuff */
7216 if (aop) /* we had to allocate for this iCode */
7218 if (pi) { /* post increment present */
7219 aopPut(AOP ( left ),rname,0);
7221 freeAsmop (NULL, aop, ic, TRUE);
7225 /* we did not allocate which means left
7226 already in a pointer register, then
7227 if size > 0 && this could be used again
7228 we have to point it back to where it
7230 if ((AOP_SIZE (result) > 1 &&
7231 !OP_SYMBOL (left)->remat &&
7232 (OP_SYMBOL (left)->liveTo > ic->seq ||
7236 int size = AOP_SIZE (result) - 1;
7238 emitcode ("dec", "%s", rname);
7243 freeAsmop (left, NULL, ic, TRUE);
7244 freeAsmop (result, NULL, ic, TRUE);
7245 if (pi) pi->generated = 1;
7248 /*-----------------------------------------------------------------*/
7249 /* genPagedPointerGet - emitcode for paged pointer fetch */
7250 /*-----------------------------------------------------------------*/
7252 genPagedPointerGet (operand * left,
7260 sym_link *rtype, *retype;
7262 D(emitcode (";", "genPagedPointerGet"));
7264 rtype = operandType (result);
7265 retype = getSpec (rtype);
7267 aopOp (left, ic, FALSE);
7269 /* if the value is already in a pointer register
7270 then don't need anything more */
7271 if (!AOP_INPREG (AOP (left)))
7273 /* otherwise get a free pointer register */
7275 preg = getFreePtr (ic, &aop, FALSE);
7276 emitcode ("mov", "%s,%s",
7278 aopGet (AOP (left), 0, FALSE, TRUE));
7282 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7284 aopOp (result, ic, FALSE);
7286 /* if bitfield then unpack the bits */
7287 if (IS_BITVAR (retype))
7288 genUnpackBits (result, rname, PPOINTER);
7291 /* we have can just get the values */
7292 int size = AOP_SIZE (result);
7298 emitcode ("movx", "a,@%s", rname);
7299 aopPut (AOP (result), "a", offset);
7304 emitcode ("inc", "%s", rname);
7308 /* now some housekeeping stuff */
7309 if (aop) /* we had to allocate for this iCode */
7311 if (pi) aopPut ( AOP (left), rname, 0);
7312 freeAsmop (NULL, aop, ic, TRUE);
7316 /* we did not allocate which means left
7317 already in a pointer register, then
7318 if size > 0 && this could be used again
7319 we have to point it back to where it
7321 if ((AOP_SIZE (result) > 1 &&
7322 !OP_SYMBOL (left)->remat &&
7323 (OP_SYMBOL (left)->liveTo > ic->seq ||
7327 int size = AOP_SIZE (result) - 1;
7329 emitcode ("dec", "%s", rname);
7334 freeAsmop (left, NULL, ic, TRUE);
7335 freeAsmop (result, NULL, ic, TRUE);
7336 if (pi) pi->generated = 1;
7340 /*-----------------------------------------------------------------*/
7341 /* genFarPointerGet - gget value from far space */
7342 /*-----------------------------------------------------------------*/
7344 genFarPointerGet (operand * left,
7345 operand * result, iCode * ic, iCode * pi)
7348 sym_link *retype = getSpec (operandType (result));
7350 D(emitcode (";", "genFarPointerGet"));
7352 aopOp (left, ic, FALSE);
7354 /* if the operand is already in dptr
7355 then we do nothing else we move the value to dptr */
7356 if (AOP_TYPE (left) != AOP_STR)
7358 /* if this is remateriazable */
7359 if (AOP_TYPE (left) == AOP_IMMD)
7360 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7362 { /* we need to get it byte by byte */
7363 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7364 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7367 /* so dptr know contains the address */
7368 aopOp (result, ic, FALSE);
7370 /* if bit then unpack */
7371 if (IS_BITVAR (retype))
7372 genUnpackBits (result, "dptr", FPOINTER);
7375 size = AOP_SIZE (result);
7380 emitcode ("movx", "a,@dptr");
7381 aopPut (AOP (result), "a", offset++);
7383 emitcode ("inc", "dptr");
7387 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7388 aopPut ( AOP (left), "dpl", 0);
7389 aopPut ( AOP (left), "dph", 1);
7392 freeAsmop (left, NULL, ic, TRUE);
7393 freeAsmop (result, NULL, ic, TRUE);
7396 /*-----------------------------------------------------------------*/
7397 /* genCodePointerGet - gget value from code space */
7398 /*-----------------------------------------------------------------*/
7400 genCodePointerGet (operand * left,
7401 operand * result, iCode * ic, iCode *pi)
7404 sym_link *retype = getSpec (operandType (result));
7406 D(emitcode (";", "genCodePointerGet"));
7408 aopOp (left, ic, FALSE);
7410 /* if the operand is already in dptr
7411 then we do nothing else we move the value to dptr */
7412 if (AOP_TYPE (left) != AOP_STR)
7414 /* if this is remateriazable */
7415 if (AOP_TYPE (left) == AOP_IMMD)
7416 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7418 { /* we need to get it byte by byte */
7419 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7420 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7423 /* so dptr know contains the address */
7424 aopOp (result, ic, FALSE);
7426 /* if bit then unpack */
7427 if (IS_BITVAR (retype))
7428 genUnpackBits (result, "dptr", CPOINTER);
7431 size = AOP_SIZE (result);
7436 emitcode ("clr", "a");
7437 emitcode ("movc", "a,@a+dptr");
7438 aopPut (AOP (result), "a", offset++);
7440 emitcode ("inc", "dptr");
7444 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7445 aopPut ( AOP (left), "dpl", 0);
7446 aopPut ( AOP (left), "dph", 1);
7449 freeAsmop (left, NULL, ic, TRUE);
7450 freeAsmop (result, NULL, ic, TRUE);
7453 /*-----------------------------------------------------------------*/
7454 /* genGenPointerGet - gget value from generic pointer space */
7455 /*-----------------------------------------------------------------*/
7457 genGenPointerGet (operand * left,
7458 operand * result, iCode * ic, iCode *pi)
7461 sym_link *retype = getSpec (operandType (result));
7463 D(emitcode (";", "genGenPointerGet"));
7465 aopOp (left, ic, FALSE);
7467 /* if the operand is already in dptr
7468 then we do nothing else we move the value to dptr */
7469 if (AOP_TYPE (left) != AOP_STR)
7471 /* if this is remateriazable */
7472 if (AOP_TYPE (left) == AOP_IMMD)
7474 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7475 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7476 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7478 emitcode ("mov", "b,#%d", pointerCode (retype));
7481 { /* we need to get it byte by byte */
7482 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7483 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7484 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7487 /* so dptr know contains the address */
7488 aopOp (result, ic, FALSE);
7490 /* if bit then unpack */
7491 if (IS_BITVAR (retype))
7492 genUnpackBits (result, "dptr", GPOINTER);
7495 size = AOP_SIZE (result);
7500 emitcode ("lcall", "__gptrget");
7501 aopPut (AOP (result), "a", offset++);
7503 emitcode ("inc", "dptr");
7507 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7508 aopPut ( AOP (left), "dpl", 0);
7509 aopPut ( AOP (left), "dph", 1);
7510 aopPut ( AOP (left), "b", 2);
7513 freeAsmop (left, NULL, ic, TRUE);
7514 freeAsmop (result, NULL, ic, TRUE);
7517 /*-----------------------------------------------------------------*/
7518 /* genPointerGet - generate code for pointer get */
7519 /*-----------------------------------------------------------------*/
7521 genPointerGet (iCode * ic, iCode *pi)
7523 operand *left, *result;
7524 sym_link *type, *etype;
7527 D(emitcode (";", "genPointerGet"));
7529 left = IC_LEFT (ic);
7530 result = IC_RESULT (ic);
7532 /* depending on the type of pointer we need to
7533 move it to the correct pointer register */
7534 type = operandType (left);
7535 etype = getSpec (type);
7536 /* if left is of type of pointer then it is simple */
7537 if (IS_PTR (type) && !IS_FUNC (type->next))
7538 p_type = DCL_TYPE (type);
7541 /* we have to go by the storage class */
7542 p_type = PTR_TYPE (SPEC_OCLS (etype));
7545 /* special case when cast remat */
7546 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7547 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7548 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7549 type = type = operandType (left);
7550 p_type = DCL_TYPE (type);
7552 /* now that we have the pointer type we assign
7553 the pointer values */
7559 genNearPointerGet (left, result, ic, pi);
7563 genPagedPointerGet (left, result, ic, pi);
7567 genFarPointerGet (left, result, ic, pi);
7571 genCodePointerGet (left, result, ic, pi);
7575 genGenPointerGet (left, result, ic, pi);
7581 /*-----------------------------------------------------------------*/
7582 /* genPackBits - generates code for packed bit storage */
7583 /*-----------------------------------------------------------------*/
7585 genPackBits (sym_link * etype,
7587 char *rname, int p_type)
7595 D(emitcode (";", "genPackBits"));
7597 blen = SPEC_BLEN (etype);
7598 bstr = SPEC_BSTR (etype);
7600 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7603 /* if the bit lenth is less than or */
7604 /* it exactly fits a byte then */
7605 if (SPEC_BLEN (etype) <= 8)
7607 shCount = SPEC_BSTR (etype);
7609 /* shift left acc */
7612 if (SPEC_BLEN (etype) < 8)
7613 { /* if smaller than a byte */
7619 emitcode ("mov", "b,a");
7620 emitcode ("mov", "a,@%s", rname);
7624 emitcode ("mov", "b,a");
7625 emitcode ("movx", "a,@dptr");
7629 emitcode ("push", "b");
7630 emitcode ("push", "acc");
7631 emitcode ("lcall", "__gptrget");
7632 emitcode ("pop", "b");
7636 emitcode ("anl", "a,#0x%02x", (unsigned char)
7637 ((unsigned char) (0xFF << (blen + bstr)) |
7638 (unsigned char) (0xFF >> (8 - bstr))));
7639 emitcode ("orl", "a,b");
7640 if (p_type == GPOINTER)
7641 emitcode ("pop", "b");
7648 emitcode ("mov", "@%s,a", rname);
7652 emitcode ("movx", "@dptr,a");
7656 emitcode ("lcall", "__gptrput");
7661 if (SPEC_BLEN (etype) <= 8)
7664 emitcode ("inc", "%s", rname);
7665 rLen = SPEC_BLEN (etype);
7667 /* now generate for lengths greater than one byte */
7671 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7683 emitcode ("mov", "@%s,a", rname);
7686 emitcode ("mov", "@%s,%s", rname, l);
7691 emitcode ("movx", "@dptr,a");
7696 emitcode ("lcall", "__gptrput");
7699 emitcode ("inc", "%s", rname);
7704 /* last last was not complete */
7707 /* save the byte & read byte */
7711 emitcode ("mov", "b,a");
7712 emitcode ("mov", "a,@%s", rname);
7716 emitcode ("mov", "b,a");
7717 emitcode ("movx", "a,@dptr");
7721 emitcode ("push", "b");
7722 emitcode ("push", "acc");
7723 emitcode ("lcall", "__gptrget");
7724 emitcode ("pop", "b");
7728 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7729 emitcode ("orl", "a,b");
7732 if (p_type == GPOINTER)
7733 emitcode ("pop", "b");
7739 emitcode ("mov", "@%s,a", rname);
7743 emitcode ("movx", "@dptr,a");
7747 emitcode ("lcall", "__gptrput");
7751 /*-----------------------------------------------------------------*/
7752 /* genDataPointerSet - remat pointer to data space */
7753 /*-----------------------------------------------------------------*/
7755 genDataPointerSet (operand * right,
7759 int size, offset = 0;
7760 char *l, buffer[256];
7762 D(emitcode (";", "genDataPointerSet"));
7764 aopOp (right, ic, FALSE);
7766 l = aopGet (AOP (result), 0, FALSE, TRUE);
7767 size = AOP_SIZE (right);
7771 sprintf (buffer, "(%s + %d)", l + 1, offset);
7773 sprintf (buffer, "%s", l + 1);
7774 emitcode ("mov", "%s,%s", buffer,
7775 aopGet (AOP (right), offset++, FALSE, FALSE));
7778 freeAsmop (right, NULL, ic, TRUE);
7779 freeAsmop (result, NULL, ic, TRUE);
7782 /*-----------------------------------------------------------------*/
7783 /* genNearPointerSet - emitcode for near pointer put */
7784 /*-----------------------------------------------------------------*/
7786 genNearPointerSet (operand * right,
7794 sym_link *retype, *letype;
7795 sym_link *ptype = operandType (result);
7797 D(emitcode (";", "genNearPointerSet"));
7799 retype = getSpec (operandType (right));
7800 letype = getSpec (ptype);
7801 aopOp (result, ic, FALSE);
7803 /* if the result is rematerializable &
7804 in data space & not a bit variable */
7805 if (AOP_TYPE (result) == AOP_IMMD &&
7806 DCL_TYPE (ptype) == POINTER &&
7807 !IS_BITVAR (retype) &&
7808 !IS_BITVAR (letype))
7810 genDataPointerSet (right, result, ic);
7814 /* if the value is already in a pointer register
7815 then don't need anything more */
7816 if (!AOP_INPREG (AOP (result)))
7819 //AOP_TYPE (result) == AOP_STK
7823 // Aha, it is a pointer, just in disguise.
7824 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7827 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7828 __FILE__, __LINE__);
7833 rname++; // skip the '@'.
7838 /* otherwise get a free pointer register */
7840 preg = getFreePtr (ic, &aop, FALSE);
7841 emitcode ("mov", "%s,%s",
7843 aopGet (AOP (result), 0, FALSE, TRUE));
7849 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7852 aopOp (right, ic, FALSE);
7854 /* if bitfield then unpack the bits */
7855 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7856 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7859 /* we have can just get the values */
7860 int size = AOP_SIZE (right);
7865 l = aopGet (AOP (right), offset, FALSE, TRUE);
7869 emitcode ("mov", "@%s,a", rname);
7872 emitcode ("mov", "@%s,%s", rname, l);
7874 emitcode ("inc", "%s", rname);
7879 /* now some housekeeping stuff */
7880 if (aop) /* we had to allocate for this iCode */
7882 if (pi) aopPut (AOP (result),rname,0);
7883 freeAsmop (NULL, aop, ic, TRUE);
7887 /* we did not allocate which means left
7888 already in a pointer register, then
7889 if size > 0 && this could be used again
7890 we have to point it back to where it
7892 if ((AOP_SIZE (right) > 1 &&
7893 !OP_SYMBOL (result)->remat &&
7894 (OP_SYMBOL (result)->liveTo > ic->seq ||
7898 int size = AOP_SIZE (right) - 1;
7900 emitcode ("dec", "%s", rname);
7905 if (pi) pi->generated = 1;
7906 freeAsmop (result, NULL, ic, TRUE);
7907 freeAsmop (right, NULL, ic, TRUE);
7910 /*-----------------------------------------------------------------*/
7911 /* genPagedPointerSet - emitcode for Paged pointer put */
7912 /*-----------------------------------------------------------------*/
7914 genPagedPointerSet (operand * right,
7922 sym_link *retype, *letype;
7924 D(emitcode (";", "genPagedPointerSet"));
7926 retype = getSpec (operandType (right));
7927 letype = getSpec (operandType (result));
7929 aopOp (result, ic, FALSE);
7931 /* if the value is already in a pointer register
7932 then don't need anything more */
7933 if (!AOP_INPREG (AOP (result)))
7935 /* otherwise get a free pointer register */
7937 preg = getFreePtr (ic, &aop, FALSE);
7938 emitcode ("mov", "%s,%s",
7940 aopGet (AOP (result), 0, FALSE, TRUE));
7944 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7946 aopOp (right, ic, FALSE);
7948 /* if bitfield then unpack the bits */
7949 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7950 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7953 /* we have can just get the values */
7954 int size = AOP_SIZE (right);
7959 l = aopGet (AOP (right), offset, FALSE, TRUE);
7962 emitcode ("movx", "@%s,a", rname);
7965 emitcode ("inc", "%s", rname);
7971 /* now some housekeeping stuff */
7972 if (aop) /* we had to allocate for this iCode */
7974 if (pi) aopPut (AOP (result),rname,0);
7975 freeAsmop (NULL, aop, ic, TRUE);
7979 /* we did not allocate which means left
7980 already in a pointer register, then
7981 if size > 0 && this could be used again
7982 we have to point it back to where it
7984 if (AOP_SIZE (right) > 1 &&
7985 !OP_SYMBOL (result)->remat &&
7986 (OP_SYMBOL (result)->liveTo > ic->seq ||
7989 int size = AOP_SIZE (right) - 1;
7991 emitcode ("dec", "%s", rname);
7996 if (pi) pi->generated = 1;
7997 freeAsmop (result, NULL, ic, TRUE);
7998 freeAsmop (right, NULL, ic, TRUE);
8003 /*-----------------------------------------------------------------*/
8004 /* genFarPointerSet - set value from far space */
8005 /*-----------------------------------------------------------------*/
8007 genFarPointerSet (operand * right,
8008 operand * result, iCode * ic, iCode * pi)
8011 sym_link *retype = getSpec (operandType (right));
8012 sym_link *letype = getSpec (operandType (result));
8014 D(emitcode (";", "genFarPointerSet"));
8016 aopOp (result, ic, FALSE);
8018 /* if the operand is already in dptr
8019 then we do nothing else we move the value to dptr */
8020 if (AOP_TYPE (result) != AOP_STR)
8022 /* if this is remateriazable */
8023 if (AOP_TYPE (result) == AOP_IMMD)
8024 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8026 { /* we need to get it byte by byte */
8027 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8028 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8031 /* so dptr know contains the address */
8032 aopOp (right, ic, FALSE);
8034 /* if bit then unpack */
8035 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8036 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8039 size = AOP_SIZE (right);
8044 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8046 emitcode ("movx", "@dptr,a");
8048 emitcode ("inc", "dptr");
8051 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8052 aopPut (AOP(result),"dpl",0);
8053 aopPut (AOP(result),"dph",1);
8056 freeAsmop (result, NULL, ic, TRUE);
8057 freeAsmop (right, NULL, ic, TRUE);
8060 /*-----------------------------------------------------------------*/
8061 /* genGenPointerSet - set value from generic pointer space */
8062 /*-----------------------------------------------------------------*/
8064 genGenPointerSet (operand * right,
8065 operand * result, iCode * ic, iCode * pi)
8068 sym_link *retype = getSpec (operandType (right));
8069 sym_link *letype = getSpec (operandType (result));
8071 D(emitcode (";", "genGenPointerSet"));
8073 aopOp (result, ic, FALSE);
8075 /* if the operand is already in dptr
8076 then we do nothing else we move the value to dptr */
8077 if (AOP_TYPE (result) != AOP_STR)
8079 /* if this is remateriazable */
8080 if (AOP_TYPE (result) == AOP_IMMD)
8082 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8083 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8084 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8086 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8089 { /* we need to get it byte by byte */
8090 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8091 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8092 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8095 /* so dptr know contains the address */
8096 aopOp (right, ic, FALSE);
8098 /* if bit then unpack */
8099 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8100 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8103 size = AOP_SIZE (right);
8108 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8110 emitcode ("lcall", "__gptrput");
8112 emitcode ("inc", "dptr");
8116 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8117 aopPut (AOP(result),"dpl",0);
8118 aopPut (AOP(result),"dph",1);
8119 aopPut (AOP(result),"b",2);
8122 freeAsmop (result, NULL, ic, TRUE);
8123 freeAsmop (right, NULL, ic, TRUE);
8126 /*-----------------------------------------------------------------*/
8127 /* genPointerSet - stores the value into a pointer location */
8128 /*-----------------------------------------------------------------*/
8130 genPointerSet (iCode * ic, iCode *pi)
8132 operand *right, *result;
8133 sym_link *type, *etype;
8136 D(emitcode (";", "genPointerSet"));
8138 right = IC_RIGHT (ic);
8139 result = IC_RESULT (ic);
8141 /* depending on the type of pointer we need to
8142 move it to the correct pointer register */
8143 type = operandType (result);
8144 etype = getSpec (type);
8145 /* if left is of type of pointer then it is simple */
8146 if (IS_PTR (type) && !IS_FUNC (type->next))
8148 p_type = DCL_TYPE (type);
8152 /* we have to go by the storage class */
8153 p_type = PTR_TYPE (SPEC_OCLS (etype));
8156 /* special case when cast remat */
8157 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8158 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8159 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8160 type = type = operandType (result);
8161 p_type = DCL_TYPE (type);
8163 /* now that we have the pointer type we assign
8164 the pointer values */
8170 genNearPointerSet (right, result, ic, pi);
8174 genPagedPointerSet (right, result, ic, pi);
8178 genFarPointerSet (right, result, ic, pi);
8182 genGenPointerSet (right, result, ic, pi);
8188 /*-----------------------------------------------------------------*/
8189 /* genIfx - generate code for Ifx statement */
8190 /*-----------------------------------------------------------------*/
8192 genIfx (iCode * ic, iCode * popIc)
8194 operand *cond = IC_COND (ic);
8197 D(emitcode (";", "genIfx"));
8199 aopOp (cond, ic, FALSE);
8201 /* get the value into acc */
8202 if (AOP_TYPE (cond) != AOP_CRY)
8206 /* the result is now in the accumulator */
8207 freeAsmop (cond, NULL, ic, TRUE);
8209 /* if there was something to be popped then do it */
8213 /* if the condition is a bit variable */
8214 if (isbit && IS_ITEMP (cond) &&
8216 genIfxJump (ic, SPIL_LOC (cond)->rname);
8217 else if (isbit && !IS_ITEMP (cond))
8218 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8220 genIfxJump (ic, "a");
8225 /*-----------------------------------------------------------------*/
8226 /* genAddrOf - generates code for address of */
8227 /*-----------------------------------------------------------------*/
8229 genAddrOf (iCode * ic)
8231 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8234 D(emitcode (";", "genAddrOf"));
8236 aopOp (IC_RESULT (ic), ic, FALSE);
8238 /* if the operand is on the stack then we
8239 need to get the stack offset of this
8243 /* if it has an offset then we need to compute
8247 emitcode ("mov", "a,_bp");
8248 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8249 ((char) (sym->stack - _G.nRegsSaved)) :
8250 ((char) sym->stack)) & 0xff);
8251 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8255 /* we can just move _bp */
8256 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8258 /* fill the result with zero */
8259 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8264 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8270 /* object not on stack then we need the name */
8271 size = AOP_SIZE (IC_RESULT (ic));
8276 char s[SDCC_NAME_MAX];
8278 sprintf (s, "#(%s >> %d)",
8282 sprintf (s, "#%s", sym->rname);
8283 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8287 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8291 /*-----------------------------------------------------------------*/
8292 /* genFarFarAssign - assignment when both are in far space */
8293 /*-----------------------------------------------------------------*/
8295 genFarFarAssign (operand * result, operand * right, iCode * ic)
8297 int size = AOP_SIZE (right);
8301 D(emitcode (";", "genFarFarAssign"));
8303 /* first push the right side on to the stack */
8306 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8308 emitcode ("push", "acc");
8311 freeAsmop (right, NULL, ic, FALSE);
8312 /* now assign DPTR to result */
8313 aopOp (result, ic, FALSE);
8314 size = AOP_SIZE (result);
8317 emitcode ("pop", "acc");
8318 aopPut (AOP (result), "a", --offset);
8320 freeAsmop (result, NULL, ic, FALSE);
8324 /*-----------------------------------------------------------------*/
8325 /* genAssign - generate code for assignment */
8326 /*-----------------------------------------------------------------*/
8328 genAssign (iCode * ic)
8330 operand *result, *right;
8332 unsigned long lit = 0L;
8334 D(emitcode(";","genAssign"));
8336 result = IC_RESULT (ic);
8337 right = IC_RIGHT (ic);
8339 /* if they are the same */
8340 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8343 aopOp (right, ic, FALSE);
8345 /* special case both in far space */
8346 if (AOP_TYPE (right) == AOP_DPTR &&
8347 IS_TRUE_SYMOP (result) &&
8348 isOperandInFarSpace (result))
8351 genFarFarAssign (result, right, ic);
8355 aopOp (result, ic, TRUE);
8357 /* if they are the same registers */
8358 if (sameRegs (AOP (right), AOP (result)))
8361 /* if the result is a bit */
8362 if (AOP_TYPE (result) == AOP_CRY)
8365 /* if the right size is a literal then
8366 we know what the value is */
8367 if (AOP_TYPE (right) == AOP_LIT)
8369 if (((int) operandLitValue (right)))
8370 aopPut (AOP (result), one, 0);
8372 aopPut (AOP (result), zero, 0);
8376 /* the right is also a bit variable */
8377 if (AOP_TYPE (right) == AOP_CRY)
8379 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8380 aopPut (AOP (result), "c", 0);
8386 aopPut (AOP (result), "a", 0);
8390 /* bit variables done */
8392 size = AOP_SIZE (result);
8394 if (AOP_TYPE (right) == AOP_LIT)
8395 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8397 (AOP_TYPE (result) != AOP_REG) &&
8398 (AOP_TYPE (right) == AOP_LIT) &&
8399 !IS_FLOAT (operandType (right)) &&
8402 emitcode ("clr", "a");
8405 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8406 aopPut (AOP (result), "a", size);
8408 aopPut (AOP (result),
8409 aopGet (AOP (right), size, FALSE, FALSE),
8417 aopPut (AOP (result),
8418 aopGet (AOP (right), offset, FALSE, FALSE),
8425 freeAsmop (right, NULL, ic, TRUE);
8426 freeAsmop (result, NULL, ic, TRUE);
8429 /*-----------------------------------------------------------------*/
8430 /* genJumpTab - genrates code for jump table */
8431 /*-----------------------------------------------------------------*/
8433 genJumpTab (iCode * ic)
8438 D(emitcode (";", "genJumpTab"));
8440 aopOp (IC_JTCOND (ic), ic, FALSE);
8441 /* get the condition into accumulator */
8442 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8444 /* multiply by three */
8445 emitcode ("add", "a,acc");
8446 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8447 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8449 jtab = newiTempLabel (NULL);
8450 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8451 emitcode ("jmp", "@a+dptr");
8452 emitcode ("", "%05d$:", jtab->key + 100);
8453 /* now generate the jump labels */
8454 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8455 jtab = setNextItem (IC_JTLABELS (ic)))
8456 emitcode ("ljmp", "%05d$", jtab->key + 100);
8460 /*-----------------------------------------------------------------*/
8461 /* genCast - gen code for casting */
8462 /*-----------------------------------------------------------------*/
8464 genCast (iCode * ic)
8466 operand *result = IC_RESULT (ic);
8467 sym_link *ctype = operandType (IC_LEFT (ic));
8468 sym_link *rtype = operandType (IC_RIGHT (ic));
8469 operand *right = IC_RIGHT (ic);
8472 D(emitcode(";", "genCast"));
8474 /* if they are equivalent then do nothing */
8475 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8478 aopOp (right, ic, FALSE);
8479 aopOp (result, ic, FALSE);
8481 /* if the result is a bit */
8482 if (IS_BITVAR(OP_SYMBOL(result)->type))
8484 /* if the right size is a literal then
8485 we know what the value is */
8486 if (AOP_TYPE (right) == AOP_LIT)
8488 if (((int) operandLitValue (right)))
8489 aopPut (AOP (result), one, 0);
8491 aopPut (AOP (result), zero, 0);
8496 /* the right is also a bit variable */
8497 if (AOP_TYPE (right) == AOP_CRY)
8499 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8500 aopPut (AOP (result), "c", 0);
8506 aopPut (AOP (result), "a", 0);
8510 /* if they are the same size : or less */
8511 if (AOP_SIZE (result) <= AOP_SIZE (right))
8514 /* if they are in the same place */
8515 if (sameRegs (AOP (right), AOP (result)))
8518 /* if they in different places then copy */
8519 size = AOP_SIZE (result);
8523 aopPut (AOP (result),
8524 aopGet (AOP (right), offset, FALSE, FALSE),
8532 /* if the result is of type pointer */
8537 sym_link *type = operandType (right);
8538 sym_link *etype = getSpec (type);
8540 /* pointer to generic pointer */
8541 if (IS_GENPTR (ctype))
8546 p_type = DCL_TYPE (type);
8549 if (SPEC_SCLS(etype)==S_REGISTER) {
8550 // let's assume it is a generic pointer
8553 /* we have to go by the storage class */
8554 p_type = PTR_TYPE (SPEC_OCLS (etype));
8558 /* the first two bytes are known */
8559 size = GPTRSIZE - 1;
8563 aopPut (AOP (result),
8564 aopGet (AOP (right), offset, FALSE, FALSE),
8568 /* the last byte depending on type */
8584 case PPOINTER: // what the fck is this?
8589 /* this should never happen */
8590 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8591 "got unknown pointer type");
8594 aopPut (AOP (result), l, GPTRSIZE - 1);
8598 /* just copy the pointers */
8599 size = AOP_SIZE (result);
8603 aopPut (AOP (result),
8604 aopGet (AOP (right), offset, FALSE, FALSE),
8611 /* so we now know that the size of destination is greater
8612 than the size of the source */
8613 /* we move to result for the size of source */
8614 size = AOP_SIZE (right);
8618 aopPut (AOP (result),
8619 aopGet (AOP (right), offset, FALSE, FALSE),
8624 /* now depending on the sign of the source && destination */
8625 size = AOP_SIZE (result) - AOP_SIZE (right);
8626 /* if unsigned or not an integral type */
8627 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8630 aopPut (AOP (result), zero, offset++);
8634 /* we need to extend the sign :{ */
8635 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8638 emitcode ("rlc", "a");
8639 emitcode ("subb", "a,acc");
8641 aopPut (AOP (result), "a", offset++);
8644 /* we are done hurray !!!! */
8647 freeAsmop (right, NULL, ic, TRUE);
8648 freeAsmop (result, NULL, ic, TRUE);
8652 /*-----------------------------------------------------------------*/
8653 /* genDjnz - generate decrement & jump if not zero instrucion */
8654 /*-----------------------------------------------------------------*/
8656 genDjnz (iCode * ic, iCode * ifx)
8662 D(emitcode (";", "genDjnz"));
8664 /* if the if condition has a false label
8665 then we cannot save */
8669 /* if the minus is not of the form
8671 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8672 !IS_OP_LITERAL (IC_RIGHT (ic)))
8675 if (operandLitValue (IC_RIGHT (ic)) != 1)
8678 /* if the size of this greater than one then no
8680 if (getSize (operandType (IC_RESULT (ic))) > 1)
8683 /* otherwise we can save BIG */
8684 lbl = newiTempLabel (NULL);
8685 lbl1 = newiTempLabel (NULL);
8687 aopOp (IC_RESULT (ic), ic, FALSE);
8689 if (AOP_NEEDSACC(IC_RESULT(ic)))
8691 /* If the result is accessed indirectly via
8692 * the accumulator, we must explicitly write
8693 * it back after the decrement.
8695 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8697 if (strcmp(rByte, "a"))
8699 /* Something is hopelessly wrong */
8700 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8701 __FILE__, __LINE__);
8702 /* We can just give up; the generated code will be inefficient,
8705 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8708 emitcode ("dec", "%s", rByte);
8709 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8710 emitcode ("jnz", "%05d$", lbl->key + 100);
8712 else if (IS_AOP_PREG (IC_RESULT (ic)))
8714 emitcode ("dec", "%s",
8715 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8716 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8717 emitcode ("jnz", "%05d$", lbl->key + 100);
8721 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8724 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8725 emitcode ("", "%05d$:", lbl->key + 100);
8726 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8727 emitcode ("", "%05d$:", lbl1->key + 100);
8729 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8734 /*-----------------------------------------------------------------*/
8735 /* genReceive - generate code for a receive iCode */
8736 /*-----------------------------------------------------------------*/
8738 genReceive (iCode * ic)
8740 D(emitcode (";", "genReceive"));
8742 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8743 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8744 IS_TRUE_SYMOP (IC_RESULT (ic))))
8747 int size = getSize (operandType (IC_RESULT (ic)));
8748 int offset = fReturnSizeMCS51 - size;
8751 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8752 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8755 aopOp (IC_RESULT (ic), ic, FALSE);
8756 size = AOP_SIZE (IC_RESULT (ic));
8760 emitcode ("pop", "acc");
8761 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8768 aopOp (IC_RESULT (ic), ic, FALSE);
8770 assignResultValue (IC_RESULT (ic));
8773 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8776 /*-----------------------------------------------------------------*/
8777 /* gen51Code - generate code for 8051 based controllers */
8778 /*-----------------------------------------------------------------*/
8780 gen51Code (iCode * lic)
8785 lineHead = lineCurr = NULL;
8787 /* print the allocation information */
8789 printAllocInfo (currFunc, codeOutFile);
8790 /* if debug information required */
8791 if (options.debug && currFunc)
8793 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8795 if (IS_STATIC (currFunc->etype))
8796 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8798 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8801 /* stack pointer name */
8802 if (options.useXstack)
8808 for (ic = lic; ic; ic = ic->next)
8811 if (ic->lineno && cln != ic->lineno)
8816 emitcode ("", "C$%s$%d$%d$%d ==.",
8817 FileBaseName (ic->filename), ic->lineno,
8818 ic->level, ic->block);
8821 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
8822 printCLine(ic->filename, ic->lineno));
8825 /* if the result is marked as
8826 spilt and rematerializable or code for
8827 this has already been generated then
8829 if (resultRemat (ic) || ic->generated)
8832 /* depending on the operation */
8852 /* IPOP happens only when trying to restore a
8853 spilt live range, if there is an ifx statement
8854 following this pop then the if statement might
8855 be using some of the registers being popped which
8856 would destory the contents of the register so
8857 we need to check for this condition and handle it */
8859 ic->next->op == IFX &&
8860 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8861 genIfx (ic->next, ic);
8879 genEndFunction (ic);
8899 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8916 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8920 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8927 /* note these two are xlated by algebraic equivalence
8928 during parsing SDCC.y */
8929 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8930 "got '>=' or '<=' shouldn't have come here");
8934 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8946 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8950 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8954 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8981 case GET_VALUE_AT_ADDRESS:
8982 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_LEFT(ic)))));
8986 if (POINTER_SET (ic))
8987 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9013 addSet (&_G.sendSet, ic);
9022 /* now we are ready to call the
9023 peep hole optimizer */
9024 if (!options.nopeep)
9025 peepHole (&lineHead);
9027 /* now do the actual printing */
9028 printLine (lineHead, codeOutFile);