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 /* if both are in bit space then
1341 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1342 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1345 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1346 emitcode ("cpl", "c");
1347 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1351 size = AOP_SIZE (IC_RESULT (ic));
1354 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1356 emitcode ("cpl", "a");
1357 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1362 /* release the aops */
1363 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1364 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1367 /*-----------------------------------------------------------------*/
1368 /* genUminusFloat - unary minus for floating points */
1369 /*-----------------------------------------------------------------*/
1371 genUminusFloat (operand * op, operand * result)
1373 int size, offset = 0;
1376 D(emitcode (";", "genUminusFloat"));
1378 /* for this we just need to flip the
1379 first it then copy the rest in place */
1380 size = AOP_SIZE (op) - 1;
1381 l = aopGet (AOP (op), 3, FALSE, FALSE);
1385 emitcode ("cpl", "acc.7");
1386 aopPut (AOP (result), "a", 3);
1390 aopPut (AOP (result),
1391 aopGet (AOP (op), offset, FALSE, FALSE),
1397 /*-----------------------------------------------------------------*/
1398 /* genUminus - unary minus code generation */
1399 /*-----------------------------------------------------------------*/
1401 genUminus (iCode * ic)
1404 sym_link *optype, *rtype;
1407 D(emitcode (";", "genUminus"));
1410 aopOp (IC_LEFT (ic), ic, FALSE);
1411 aopOp (IC_RESULT (ic), ic, TRUE);
1413 /* if both in bit space then special
1415 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1416 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1419 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1420 emitcode ("cpl", "c");
1421 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1425 optype = operandType (IC_LEFT (ic));
1426 rtype = operandType (IC_RESULT (ic));
1428 /* if float then do float stuff */
1429 if (IS_FLOAT (optype))
1431 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1435 /* otherwise subtract from zero */
1436 size = AOP_SIZE (IC_LEFT (ic));
1441 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1442 if (!strcmp (l, "a"))
1446 emitcode ("cpl", "a");
1447 emitcode ("addc", "a,#0");
1453 emitcode ("clr", "a");
1454 emitcode ("subb", "a,%s", l);
1456 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1459 /* if any remaining bytes in the result */
1460 /* we just need to propagate the sign */
1461 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1463 emitcode ("rlc", "a");
1464 emitcode ("subb", "a,acc");
1466 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1470 /* release the aops */
1471 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1472 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1475 /*-----------------------------------------------------------------*/
1476 /* saveRegisters - will look for a call and save the registers */
1477 /*-----------------------------------------------------------------*/
1479 saveRegisters (iCode * lic)
1486 for (ic = lic; ic; ic = ic->next)
1487 if (ic->op == CALL || ic->op == PCALL)
1492 fprintf (stderr, "found parameter push with no function call\n");
1496 /* if the registers have been saved already or don't need to be then
1498 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1499 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1502 /* safe the registers in use at this time but skip the
1503 ones for the result */
1504 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1505 mcs51_rUmaskForOp (IC_RESULT(ic)));
1508 if (options.useXstack)
1510 if (bitVectBitValue (rsave, R0_IDX))
1511 emitcode ("mov", "b,r0");
1512 emitcode ("mov", "r0,%s", spname);
1513 for (i = 0; i < mcs51_nRegs; i++)
1515 if (bitVectBitValue (rsave, i))
1518 emitcode ("mov", "a,b");
1520 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1521 emitcode ("movx", "@r0,a");
1522 emitcode ("inc", "r0");
1525 emitcode ("mov", "%s,r0", spname);
1526 if (bitVectBitValue (rsave, R0_IDX))
1527 emitcode ("mov", "r0,b");
1530 for (i = 0; i < mcs51_nRegs; i++)
1532 if (bitVectBitValue (rsave, i))
1533 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1537 /*-----------------------------------------------------------------*/
1538 /* unsaveRegisters - pop the pushed registers */
1539 /*-----------------------------------------------------------------*/
1541 unsaveRegisters (iCode * ic)
1546 /* restore the registers in use at this time but skip the
1547 ones for the result */
1548 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1549 mcs51_rUmaskForOp (IC_RESULT(ic)));
1551 if (options.useXstack)
1553 emitcode ("mov", "r0,%s", spname);
1554 for (i = mcs51_nRegs; i >= 0; i--)
1556 if (bitVectBitValue (rsave, i))
1558 emitcode ("dec", "r0");
1559 emitcode ("movx", "a,@r0");
1561 emitcode ("mov", "b,a");
1563 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1567 emitcode ("mov", "%s,r0", spname);
1568 if (bitVectBitValue (rsave, R0_IDX))
1569 emitcode ("mov", "r0,b");
1572 for (i = mcs51_nRegs; i >= 0; i--)
1574 if (bitVectBitValue (rsave, i))
1575 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1581 /*-----------------------------------------------------------------*/
1583 /*-----------------------------------------------------------------*/
1585 pushSide (operand * oper, int size)
1590 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1591 if (AOP_TYPE (oper) != AOP_REG &&
1592 AOP_TYPE (oper) != AOP_DIR &&
1595 emitcode ("mov", "a,%s", l);
1596 emitcode ("push", "acc");
1599 emitcode ("push", "%s", l);
1603 /*-----------------------------------------------------------------*/
1604 /* assignResultValue - */
1605 /*-----------------------------------------------------------------*/
1607 assignResultValue (operand * oper)
1610 int size = AOP_SIZE (oper);
1613 aopPut (AOP (oper), fReturn[offset], offset);
1619 /*-----------------------------------------------------------------*/
1620 /* genXpush - pushes onto the external stack */
1621 /*-----------------------------------------------------------------*/
1623 genXpush (iCode * ic)
1625 asmop *aop = newAsmop (0);
1627 int size, offset = 0;
1629 D(emitcode (";", "genXpush"));
1631 aopOp (IC_LEFT (ic), ic, FALSE);
1632 r = getFreePtr (ic, &aop, FALSE);
1635 emitcode ("mov", "%s,_spx", r->name);
1637 size = AOP_SIZE (IC_LEFT (ic));
1641 char *l = aopGet (AOP (IC_LEFT (ic)),
1642 offset++, FALSE, FALSE);
1644 emitcode ("movx", "@%s,a", r->name);
1645 emitcode ("inc", "%s", r->name);
1650 emitcode ("mov", "_spx,%s", r->name);
1652 freeAsmop (NULL, aop, ic, TRUE);
1653 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1656 /*-----------------------------------------------------------------*/
1657 /* genIpush - genrate code for pushing this gets a little complex */
1658 /*-----------------------------------------------------------------*/
1660 genIpush (iCode * ic)
1662 int size, offset = 0;
1665 D(emitcode (";", "genIpush"));
1667 /* if this is not a parm push : ie. it is spill push
1668 and spill push is always done on the local stack */
1672 /* and the item is spilt then do nothing */
1673 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1676 aopOp (IC_LEFT (ic), ic, FALSE);
1677 size = AOP_SIZE (IC_LEFT (ic));
1678 /* push it on the stack */
1681 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1687 emitcode ("push", "%s", l);
1692 /* this is a paramter push: in this case we call
1693 the routine to find the call and save those
1694 registers that need to be saved */
1697 /* if use external stack then call the external
1698 stack pushing routine */
1699 if (options.useXstack)
1705 /* then do the push */
1706 aopOp (IC_LEFT (ic), ic, FALSE);
1709 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1710 size = AOP_SIZE (IC_LEFT (ic));
1714 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1715 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1716 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1719 emitcode ("mov", "a,%s", l);
1720 emitcode ("push", "acc");
1723 emitcode ("push", "%s", l);
1726 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1729 /*-----------------------------------------------------------------*/
1730 /* genIpop - recover the registers: can happen only for spilling */
1731 /*-----------------------------------------------------------------*/
1733 genIpop (iCode * ic)
1737 D(emitcode (";", "genIpop"));
1739 /* if the temp was not pushed then */
1740 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1743 aopOp (IC_LEFT (ic), ic, FALSE);
1744 size = AOP_SIZE (IC_LEFT (ic));
1745 offset = (size - 1);
1747 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1750 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1753 /*-----------------------------------------------------------------*/
1754 /* unsaveRBank - restores the resgister bank from stack */
1755 /*-----------------------------------------------------------------*/
1757 unsaveRBank (int bank, iCode * ic, bool popPsw)
1763 if (options.useXstack)
1767 /* Assume r0 is available for use. */
1768 r = mcs51_regWithIdx (R0_IDX);;
1773 r = getFreePtr (ic, &aop, FALSE);
1775 emitcode ("mov", "%s,_spx", r->name);
1780 if (options.useXstack)
1782 emitcode ("movx", "a,@%s", r->name);
1783 emitcode ("mov", "psw,a");
1784 emitcode ("dec", "%s", r->name);
1788 emitcode ("pop", "psw");
1792 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1794 if (options.useXstack)
1796 emitcode ("movx", "a,@%s", r->name);
1797 emitcode ("mov", "(%s+%d),a",
1798 regs8051[i].base, 8 * bank + regs8051[i].offset);
1799 emitcode ("dec", "%s", r->name);
1803 emitcode ("pop", "(%s+%d)",
1804 regs8051[i].base, 8 * bank + regs8051[i].offset);
1807 if (options.useXstack)
1809 emitcode ("mov", "_spx,%s", r->name);
1814 freeAsmop (NULL, aop, ic, TRUE);
1818 /*-----------------------------------------------------------------*/
1819 /* saveRBank - saves an entire register bank on the stack */
1820 /*-----------------------------------------------------------------*/
1822 saveRBank (int bank, iCode * ic, bool pushPsw)
1828 if (options.useXstack)
1832 /* Assume r0 is available for use. */
1833 r = mcs51_regWithIdx (R0_IDX);;
1838 r = getFreePtr (ic, &aop, FALSE);
1840 emitcode ("mov", "%s,_spx", r->name);
1843 for (i = 0; i < mcs51_nRegs; i++)
1845 if (options.useXstack)
1847 emitcode ("inc", "%s", r->name);
1848 emitcode ("mov", "a,(%s+%d)",
1849 regs8051[i].base, 8 * bank + regs8051[i].offset);
1850 emitcode ("movx", "@%s,a", r->name);
1853 emitcode ("push", "(%s+%d)",
1854 regs8051[i].base, 8 * bank + regs8051[i].offset);
1859 if (options.useXstack)
1861 emitcode ("mov", "a,psw");
1862 emitcode ("movx", "@%s,a", r->name);
1863 emitcode ("inc", "%s", r->name);
1864 emitcode ("mov", "_spx,%s", r->name);
1869 emitcode ("push", "psw");
1872 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1877 freeAsmop (NULL, aop, ic, TRUE);
1886 /*-----------------------------------------------------------------*/
1887 /* genCall - generates a call statement */
1888 /*-----------------------------------------------------------------*/
1890 genCall (iCode * ic)
1893 bool restoreBank = FALSE;
1894 bool swapBanks = FALSE;
1896 D(emitcode(";", "genCall"));
1898 /* if send set is not empty the assign */
1903 for (sic = setFirstItem (_G.sendSet); sic;
1904 sic = setNextItem (_G.sendSet))
1906 int size, offset = 0;
1907 aopOp (IC_LEFT (sic), sic, FALSE);
1908 size = AOP_SIZE (IC_LEFT (sic));
1911 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1913 if (strcmp (l, fReturn[offset]))
1914 emitcode ("mov", "%s,%s",
1919 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1924 /* if we are calling a not _naked function that is not using
1925 the same register bank then we need to save the
1926 destination registers on the stack */
1927 dtype = operandType (IC_LEFT (ic));
1928 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1929 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1930 IFFUNC_ISISR (currFunc->type))
1934 /* This is unexpected; the bank should have been saved in
1937 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1943 /* if caller saves & we have not saved then */
1949 emitcode ("mov", "psw,#0x%02x",
1950 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1954 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1955 OP_SYMBOL (IC_LEFT (ic))->rname :
1956 OP_SYMBOL (IC_LEFT (ic))->name));
1960 emitcode ("mov", "psw,#0x%02x",
1961 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1964 /* if we need assign a result value */
1965 if ((IS_ITEMP (IC_RESULT (ic)) &&
1966 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1967 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1968 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1969 IS_TRUE_SYMOP (IC_RESULT (ic)))
1973 aopOp (IC_RESULT (ic), ic, FALSE);
1976 assignResultValue (IC_RESULT (ic));
1978 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1981 /* adjust the stack for parameters if
1986 if (ic->parmBytes > 3)
1988 emitcode ("mov", "a,%s", spname);
1989 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1990 emitcode ("mov", "%s,a", spname);
1993 for (i = 0; i < ic->parmBytes; i++)
1994 emitcode ("dec", "%s", spname);
1997 /* if we hade saved some registers then unsave them */
1998 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1999 unsaveRegisters (ic);
2001 /* if register bank was saved then pop them */
2003 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2006 /*-----------------------------------------------------------------*/
2007 /* genPcall - generates a call by pointer statement */
2008 /*-----------------------------------------------------------------*/
2010 genPcall (iCode * ic)
2013 symbol *rlbl = newiTempLabel (NULL);
2014 bool restoreBank=FALSE;
2016 D(emitcode(";", "genPCall"));
2018 /* if caller saves & we have not saved then */
2022 /* if we are calling a function that is not using
2023 the same register bank then we need to save the
2024 destination registers on the stack */
2025 dtype = operandType (IC_LEFT (ic));
2026 if (currFunc && dtype && !FUNC_ISNAKED(dtype) &&
2027 IFFUNC_ISISR (currFunc->type) &&
2028 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2029 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2033 /* push the return address on to the stack */
2034 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2035 emitcode ("push", "acc");
2036 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2037 emitcode ("push", "acc");
2039 /* now push the calling address */
2040 aopOp (IC_LEFT (ic), ic, FALSE);
2042 pushSide (IC_LEFT (ic), FPTRSIZE);
2044 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2046 /* if send set is not empty the assign */
2051 for (sic = setFirstItem (_G.sendSet); sic;
2052 sic = setNextItem (_G.sendSet))
2054 int size, offset = 0;
2055 aopOp (IC_LEFT (sic), sic, FALSE);
2056 size = AOP_SIZE (IC_LEFT (sic));
2059 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2061 if (strcmp (l, fReturn[offset]))
2062 emitcode ("mov", "%s,%s",
2067 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2072 emitcode ("ret", "");
2073 emitcode ("", "%05d$:", (rlbl->key + 100));
2076 /* if we need assign a result value */
2077 if ((IS_ITEMP (IC_RESULT (ic)) &&
2078 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2079 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2080 IS_TRUE_SYMOP (IC_RESULT (ic)))
2084 aopOp (IC_RESULT (ic), ic, FALSE);
2087 assignResultValue (IC_RESULT (ic));
2089 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2092 /* adjust the stack for parameters if
2097 if (ic->parmBytes > 3)
2099 emitcode ("mov", "a,%s", spname);
2100 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2101 emitcode ("mov", "%s,a", spname);
2104 for (i = 0; i < ic->parmBytes; i++)
2105 emitcode ("dec", "%s", spname);
2109 /* if register bank was saved then unsave them */
2111 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2113 /* if we hade saved some registers then
2115 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2116 unsaveRegisters (ic);
2119 /*-----------------------------------------------------------------*/
2120 /* resultRemat - result is rematerializable */
2121 /*-----------------------------------------------------------------*/
2123 resultRemat (iCode * ic)
2125 if (SKIP_IC (ic) || ic->op == IFX)
2128 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2130 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2131 if (sym->remat && !POINTER_SET (ic))
2138 #if defined(__BORLANDC__) || defined(_MSC_VER)
2139 #define STRCASECMP stricmp
2141 #define STRCASECMP strcasecmp
2144 /*-----------------------------------------------------------------*/
2145 /* inExcludeList - return 1 if the string is in exclude Reg list */
2146 /*-----------------------------------------------------------------*/
2148 inExcludeList (char *s)
2152 if (options.excludeRegs[i] &&
2153 STRCASECMP (options.excludeRegs[i], "none") == 0)
2156 for (i = 0; options.excludeRegs[i]; i++)
2158 if (options.excludeRegs[i] &&
2159 STRCASECMP (s, options.excludeRegs[i]) == 0)
2165 /*-----------------------------------------------------------------*/
2166 /* genFunction - generated code for function entry */
2167 /*-----------------------------------------------------------------*/
2169 genFunction (iCode * ic)
2173 bool switchedPSW = FALSE;
2174 int calleesaves_saved_register = -1;
2177 /* create the function header */
2178 emitcode (";", "-----------------------------------------");
2179 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2180 emitcode (";", "-----------------------------------------");
2182 emitcode ("", "%s:", sym->rname);
2183 ftype = operandType (IC_LEFT (ic));
2185 if (IFFUNC_ISNAKED(ftype))
2187 emitcode(";", "naked function: no prologue.");
2191 /* if critical function then turn interrupts off */
2192 if (IFFUNC_ISCRITICAL (ftype))
2193 emitcode ("clr", "ea");
2195 /* here we need to generate the equates for the
2196 register bank if required */
2197 if (FUNC_REGBANK (ftype) != rbank)
2201 rbank = FUNC_REGBANK (ftype);
2202 for (i = 0; i < mcs51_nRegs; i++)
2204 if (strcmp (regs8051[i].base, "0") == 0)
2205 emitcode ("", "%s = 0x%02x",
2207 8 * rbank + regs8051[i].offset);
2209 emitcode ("", "%s = %s + 0x%02x",
2212 8 * rbank + regs8051[i].offset);
2216 /* if this is an interrupt service routine then
2217 save acc, b, dpl, dph */
2218 if (IFFUNC_ISISR (sym->type))
2221 if (!inExcludeList ("acc"))
2222 emitcode ("push", "acc");
2223 if (!inExcludeList ("b"))
2224 emitcode ("push", "b");
2225 if (!inExcludeList ("dpl"))
2226 emitcode ("push", "dpl");
2227 if (!inExcludeList ("dph"))
2228 emitcode ("push", "dph");
2229 /* if this isr has no bank i.e. is going to
2230 run with bank 0 , then we need to save more
2232 if (!FUNC_REGBANK (sym->type))
2235 /* if this function does not call any other
2236 function then we can be economical and
2237 save only those registers that are used */
2238 if (!IFFUNC_HASFCALL(sym->type))
2242 /* if any registers used */
2245 /* save the registers used */
2246 for (i = 0; i < sym->regsUsed->size; i++)
2248 if (bitVectBitValue (sym->regsUsed, i) ||
2249 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2250 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2257 /* this function has a function call cannot
2258 determines register usage so we will have to push the
2260 saveRBank (0, ic, FALSE);
2265 /* This ISR uses a non-zero bank.
2267 * We assume that the bank is available for our
2270 * However, if this ISR calls a function which uses some
2271 * other bank, we must save that bank entirely.
2273 unsigned long banksToSave = 0;
2275 if (IFFUNC_HASFCALL(sym->type))
2278 #define MAX_REGISTER_BANKS 4
2283 for (i = ic; i; i = i->next)
2285 if (i->op == ENDFUNCTION)
2287 /* we got to the end OK. */
2295 dtype = operandType (IC_LEFT(i));
2297 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2299 /* Mark this bank for saving. */
2300 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2302 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2306 banksToSave |= (1 << FUNC_REGBANK(dtype));
2309 /* And note that we don't need to do it in
2317 /* This is a mess; we have no idea what
2318 * register bank the called function might
2321 * The only thing I can think of to do is
2322 * throw a warning and hope.
2324 werror(W_FUNCPTR_IN_USING_ISR);
2328 if (banksToSave && options.useXstack)
2330 /* Since we aren't passing it an ic,
2331 * saveRBank will assume r0 is available to abuse.
2333 * So switch to our (trashable) bank now, so
2334 * the caller's R0 isn't trashed.
2336 emitcode ("push", "psw");
2337 emitcode ("mov", "psw,#0x%02x",
2338 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2342 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2344 if (banksToSave & (1 << ix))
2346 saveRBank(ix, NULL, FALSE);
2350 // jwk: this needs a closer look
2351 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2356 /* if callee-save to be used for this function
2357 then save the registers being used in this function */
2358 if (IFFUNC_CALLEESAVES(sym->type))
2362 /* if any registers used */
2365 /* save the registers used */
2366 for (i = 0; i < sym->regsUsed->size; i++)
2368 if (bitVectBitValue (sym->regsUsed, i) ||
2369 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2371 /* remember one saved register for later usage */
2372 if (calleesaves_saved_register < 0)
2373 calleesaves_saved_register = i;
2374 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2382 /* set the register bank to the desired value */
2383 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2386 emitcode ("push", "psw");
2387 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2390 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2393 if (options.useXstack)
2395 emitcode ("mov", "r0,%s", spname);
2396 emitcode ("mov", "a,_bp");
2397 emitcode ("movx", "@r0,a");
2398 emitcode ("inc", "%s", spname);
2402 /* set up the stack */
2403 emitcode ("push", "_bp"); /* save the callers stack */
2405 emitcode ("mov", "_bp,%s", spname);
2408 /* adjust the stack for the function */
2414 werror (W_STACK_OVERFLOW, sym->name);
2416 if (i > 3 && sym->recvSize < 4)
2419 emitcode ("mov", "a,sp");
2420 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2421 emitcode ("mov", "sp,a");
2426 if (IFFUNC_CALLEESAVES(sym->type))
2428 /* if it's a callee-saves function we need a saved register */
2429 if (calleesaves_saved_register >= 0)
2431 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2432 emitcode ("mov", "a,sp");
2433 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2434 emitcode ("mov", "sp,a");
2435 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2438 /* do it the hard way */
2440 emitcode ("inc", "sp");
2444 /* not callee-saves, we can clobber ar0 */
2445 emitcode ("mov", "ar0,a");
2446 emitcode ("mov", "a,sp");
2447 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2448 emitcode ("mov", "sp,a");
2449 emitcode ("mov", "a,ar0");
2454 emitcode ("inc", "sp");
2460 emitcode ("mov", "a,_spx");
2461 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2462 emitcode ("mov", "_spx,a");
2467 /*-----------------------------------------------------------------*/
2468 /* genEndFunction - generates epilogue for functions */
2469 /*-----------------------------------------------------------------*/
2471 genEndFunction (iCode * ic)
2473 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2475 if (IFFUNC_ISNAKED(sym->type))
2477 emitcode(";", "naked function: no epilogue.");
2481 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2483 emitcode ("mov", "%s,_bp", spname);
2486 /* if use external stack but some variables were
2487 added to the local stack then decrement the
2489 if (options.useXstack && sym->stack)
2491 emitcode ("mov", "a,sp");
2492 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2493 emitcode ("mov", "sp,a");
2497 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2499 if (options.useXstack)
2501 emitcode ("mov", "r0,%s", spname);
2502 emitcode ("movx", "a,@r0");
2503 emitcode ("mov", "_bp,a");
2504 emitcode ("dec", "%s", spname);
2508 emitcode ("pop", "_bp");
2512 /* restore the register bank */
2513 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2515 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2516 || !options.useXstack)
2518 /* Special case of ISR using non-zero bank with useXstack
2521 emitcode ("pop", "psw");
2525 if (IFFUNC_ISISR (sym->type))
2528 /* now we need to restore the registers */
2529 /* if this isr has no bank i.e. is going to
2530 run with bank 0 , then we need to save more
2532 if (!FUNC_REGBANK (sym->type))
2534 /* if this function does not call any other
2535 function then we can be economical and
2536 save only those registers that are used */
2537 if (!IFFUNC_HASFCALL(sym->type))
2541 /* if any registers used */
2544 /* save the registers used */
2545 for (i = sym->regsUsed->size; i >= 0; i--)
2547 if (bitVectBitValue (sym->regsUsed, i) ||
2548 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2549 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2556 /* this function has a function call cannot
2557 determines register usage so we will have to pop the
2559 unsaveRBank (0, ic, FALSE);
2564 /* This ISR uses a non-zero bank.
2566 * Restore any register banks saved by genFunction
2569 // jwk: this needs a closer look
2570 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2573 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2575 if (savedBanks & (1 << ix))
2577 unsaveRBank(ix, NULL, FALSE);
2581 if (options.useXstack)
2583 /* Restore bank AFTER calling unsaveRBank,
2584 * since it can trash r0.
2586 emitcode ("pop", "psw");
2590 if (!inExcludeList ("dph"))
2591 emitcode ("pop", "dph");
2592 if (!inExcludeList ("dpl"))
2593 emitcode ("pop", "dpl");
2594 if (!inExcludeList ("b"))
2595 emitcode ("pop", "b");
2596 if (!inExcludeList ("acc"))
2597 emitcode ("pop", "acc");
2599 if (IFFUNC_ISCRITICAL (sym->type))
2600 emitcode ("setb", "ea");
2602 /* if debug then send end of function */
2603 if (options.debug && currFunc)
2606 emitcode ("", "C$%s$%d$%d$%d ==.",
2607 FileBaseName (ic->filename), currFunc->lastLine,
2608 ic->level, ic->block);
2609 if (IS_STATIC (currFunc->etype))
2610 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2612 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2616 emitcode ("reti", "");
2620 if (IFFUNC_ISCRITICAL (sym->type))
2621 emitcode ("setb", "ea");
2623 if (IFFUNC_CALLEESAVES(sym->type))
2627 /* if any registers used */
2630 /* save the registers used */
2631 for (i = sym->regsUsed->size; i >= 0; i--)
2633 if (bitVectBitValue (sym->regsUsed, i) ||
2634 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2635 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2641 /* if debug then send end of function */
2642 if (options.debug && currFunc)
2645 emitcode ("", "C$%s$%d$%d$%d ==.",
2646 FileBaseName (ic->filename), currFunc->lastLine,
2647 ic->level, ic->block);
2648 if (IS_STATIC (currFunc->etype))
2649 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2651 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2655 emitcode ("ret", "");
2660 /*-----------------------------------------------------------------*/
2661 /* genRet - generate code for return statement */
2662 /*-----------------------------------------------------------------*/
2666 int size, offset = 0, pushed = 0;
2668 D(emitcode (";", "genRet"));
2670 /* if we have no return value then
2671 just generate the "ret" */
2675 /* we have something to return then
2676 move the return value into place */
2677 aopOp (IC_LEFT (ic), ic, FALSE);
2678 size = AOP_SIZE (IC_LEFT (ic));
2683 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2686 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2688 emitcode ("push", "%s", l);
2693 l = aopGet (AOP (IC_LEFT (ic)), offset,
2695 if (strcmp (fReturn[offset], l))
2696 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2705 if (strcmp (fReturn[pushed], "a"))
2706 emitcode ("pop", fReturn[pushed]);
2708 emitcode ("pop", "acc");
2711 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2714 /* generate a jump to the return label
2715 if the next is not the return statement */
2716 if (!(ic->next && ic->next->op == LABEL &&
2717 IC_LABEL (ic->next) == returnLabel))
2719 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2723 /*-----------------------------------------------------------------*/
2724 /* genLabel - generates a label */
2725 /*-----------------------------------------------------------------*/
2727 genLabel (iCode * ic)
2729 /* special case never generate */
2730 if (IC_LABEL (ic) == entryLabel)
2733 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2736 /*-----------------------------------------------------------------*/
2737 /* genGoto - generates a ljmp */
2738 /*-----------------------------------------------------------------*/
2740 genGoto (iCode * ic)
2742 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2745 /*-----------------------------------------------------------------*/
2746 /* findLabelBackwards: walks back through the iCode chain looking */
2747 /* for the given label. Returns number of iCode instructions */
2748 /* between that label and given ic. */
2749 /* Returns zero if label not found. */
2750 /*-----------------------------------------------------------------*/
2752 findLabelBackwards (iCode * ic, int key)
2761 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2763 /* printf("findLabelBackwards = %d\n", count); */
2771 /*-----------------------------------------------------------------*/
2772 /* genPlusIncr :- does addition with increment if possible */
2773 /*-----------------------------------------------------------------*/
2775 genPlusIncr (iCode * ic)
2777 unsigned int icount;
2778 unsigned int size = getDataSize (IC_RESULT (ic));
2780 /* will try to generate an increment */
2781 /* if the right side is not a literal
2783 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2786 /* if the literal value of the right hand side
2787 is greater than 4 then it is not worth it */
2788 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2791 D(emitcode (";", "genPlusIncr"));
2793 /* if increment 16 bits in register */
2794 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2802 /* If the next instruction is a goto and the goto target
2803 * is < 10 instructions previous to this, we can generate
2804 * jumps straight to that target.
2806 if (ic->next && ic->next->op == GOTO
2807 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2808 && labelRange <= 10)
2810 emitcode (";", "tail increment optimized");
2811 tlbl = IC_LABEL (ic->next);
2816 tlbl = newiTempLabel (NULL);
2819 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2820 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2821 IS_AOP_PREG (IC_RESULT (ic)))
2822 emitcode ("cjne", "%s,#0x00,%05d$"
2823 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2827 emitcode ("clr", "a");
2828 emitcode ("cjne", "a,%s,%05d$"
2829 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2833 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2836 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2837 IS_AOP_PREG (IC_RESULT (ic)))
2838 emitcode ("cjne", "%s,#0x00,%05d$"
2839 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2842 emitcode ("cjne", "a,%s,%05d$"
2843 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2846 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2850 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2851 IS_AOP_PREG (IC_RESULT (ic)))
2852 emitcode ("cjne", "%s,#0x00,%05d$"
2853 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2857 emitcode ("cjne", "a,%s,%05d$"
2858 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2861 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2866 emitcode ("", "%05d$:", tlbl->key + 100);
2871 /* if the sizes are greater than 1 then we cannot */
2872 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2873 AOP_SIZE (IC_LEFT (ic)) > 1)
2876 /* we can if the aops of the left & result match or
2877 if they are in registers and the registers are the
2879 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2884 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2885 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2886 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2892 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2901 /*-----------------------------------------------------------------*/
2902 /* outBitAcc - output a bit in acc */
2903 /*-----------------------------------------------------------------*/
2905 outBitAcc (operand * result)
2907 symbol *tlbl = newiTempLabel (NULL);
2908 /* if the result is a bit */
2909 if (AOP_TYPE (result) == AOP_CRY)
2911 aopPut (AOP (result), "a", 0);
2915 emitcode ("jz", "%05d$", tlbl->key + 100);
2916 emitcode ("mov", "a,%s", one);
2917 emitcode ("", "%05d$:", tlbl->key + 100);
2922 /*-----------------------------------------------------------------*/
2923 /* genPlusBits - generates code for addition of two bits */
2924 /*-----------------------------------------------------------------*/
2926 genPlusBits (iCode * ic)
2928 D(emitcode (";", "genPlusBits"));
2930 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2932 symbol *lbl = newiTempLabel (NULL);
2933 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2934 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2935 emitcode ("cpl", "c");
2936 emitcode ("", "%05d$:", (lbl->key + 100));
2937 outBitC (IC_RESULT (ic));
2941 emitcode ("clr", "a");
2942 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2943 emitcode ("rlc", "a");
2944 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2945 emitcode ("addc", "a,#0x00");
2946 outAcc (IC_RESULT (ic));
2951 /* This is the original version of this code.
2953 * This is being kept around for reference,
2954 * because I am not entirely sure I got it right...
2957 adjustArithmeticResult (iCode * ic)
2959 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2960 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2961 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2962 aopPut (AOP (IC_RESULT (ic)),
2963 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2966 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2967 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2968 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2969 aopPut (AOP (IC_RESULT (ic)),
2970 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2973 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2974 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2975 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2976 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2977 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2980 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2981 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2985 /* This is the pure and virtuous version of this code.
2986 * I'm pretty certain it's right, but not enough to toss the old
2990 adjustArithmeticResult (iCode * ic)
2992 if (opIsGptr (IC_RESULT (ic)) &&
2993 opIsGptr (IC_LEFT (ic)) &&
2994 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2996 aopPut (AOP (IC_RESULT (ic)),
2997 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3001 if (opIsGptr (IC_RESULT (ic)) &&
3002 opIsGptr (IC_RIGHT (ic)) &&
3003 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3005 aopPut (AOP (IC_RESULT (ic)),
3006 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3010 if (opIsGptr (IC_RESULT (ic)) &&
3011 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3012 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3013 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3014 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3017 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3018 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3023 /*-----------------------------------------------------------------*/
3024 /* genPlus - generates code for addition */
3025 /*-----------------------------------------------------------------*/
3027 genPlus (iCode * ic)
3029 int size, offset = 0;
3031 /* special cases :- */
3033 D(emitcode (";", "genPlus"));
3035 aopOp (IC_LEFT (ic), ic, FALSE);
3036 aopOp (IC_RIGHT (ic), ic, FALSE);
3037 aopOp (IC_RESULT (ic), ic, TRUE);
3039 /* if literal, literal on the right or
3040 if left requires ACC or right is already
3042 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3043 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3044 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3046 operand *t = IC_RIGHT (ic);
3047 IC_RIGHT (ic) = IC_LEFT (ic);
3051 /* if both left & right are in bit
3053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3054 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3060 /* if left in bit space & right literal */
3061 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3062 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3064 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3065 /* if result in bit space */
3066 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3068 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3069 emitcode ("cpl", "c");
3070 outBitC (IC_RESULT (ic));
3074 size = getDataSize (IC_RESULT (ic));
3077 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3078 emitcode ("addc", "a,#00");
3079 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3085 /* if I can do an increment instead
3086 of add then GOOD for ME */
3087 if (genPlusIncr (ic) == TRUE)
3090 size = getDataSize (IC_RESULT (ic));
3094 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3096 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3098 emitcode ("add", "a,%s",
3099 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3101 emitcode ("addc", "a,%s",
3102 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3106 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3108 emitcode ("add", "a,%s",
3109 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3111 emitcode ("addc", "a,%s",
3112 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3114 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3117 adjustArithmeticResult (ic);
3120 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3121 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3122 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3125 /*-----------------------------------------------------------------*/
3126 /* genMinusDec :- does subtraction with deccrement if possible */
3127 /*-----------------------------------------------------------------*/
3129 genMinusDec (iCode * ic)
3131 unsigned int icount;
3132 unsigned int size = getDataSize (IC_RESULT (ic));
3134 /* will try to generate an increment */
3135 /* if the right side is not a literal
3137 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3140 /* if the literal value of the right hand side
3141 is greater than 4 then it is not worth it */
3142 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3145 D(emitcode (";", "genMinusDec"));
3147 /* if decrement 16 bits in register */
3148 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3156 /* If the next instruction is a goto and the goto target
3157 * is <= 10 instructions previous to this, we can generate
3158 * jumps straight to that target.
3160 if (ic->next && ic->next->op == GOTO
3161 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3162 && labelRange <= 10)
3164 emitcode (";", "tail decrement optimized");
3165 tlbl = IC_LABEL (ic->next);
3170 tlbl = newiTempLabel (NULL);
3174 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3175 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3176 IS_AOP_PREG (IC_RESULT (ic)))
3177 emitcode ("cjne", "%s,#0xff,%05d$"
3178 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3182 emitcode ("mov", "a,#0xff");
3183 emitcode ("cjne", "a,%s,%05d$"
3184 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3187 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3190 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3191 IS_AOP_PREG (IC_RESULT (ic)))
3192 emitcode ("cjne", "%s,#0xff,%05d$"
3193 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3197 emitcode ("cjne", "a,%s,%05d$"
3198 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3201 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3205 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3206 IS_AOP_PREG (IC_RESULT (ic)))
3207 emitcode ("cjne", "%s,#0xff,%05d$"
3208 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3212 emitcode ("cjne", "a,%s,%05d$"
3213 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3216 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3220 emitcode ("", "%05d$:", tlbl->key + 100);
3225 /* if the sizes are greater than 1 then we cannot */
3226 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3227 AOP_SIZE (IC_LEFT (ic)) > 1)
3230 /* we can if the aops of the left & result match or
3231 if they are in registers and the registers are the
3233 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3237 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3245 /*-----------------------------------------------------------------*/
3246 /* addSign - complete with sign */
3247 /*-----------------------------------------------------------------*/
3249 addSign (operand * result, int offset, int sign)
3251 int size = (getDataSize (result) - offset);
3256 emitcode ("rlc", "a");
3257 emitcode ("subb", "a,acc");
3259 aopPut (AOP (result), "a", offset++);
3263 aopPut (AOP (result), zero, offset++);
3267 /*-----------------------------------------------------------------*/
3268 /* genMinusBits - generates code for subtraction of two bits */
3269 /*-----------------------------------------------------------------*/
3271 genMinusBits (iCode * ic)
3273 symbol *lbl = newiTempLabel (NULL);
3275 D(emitcode (";", "genMinusBits"));
3277 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3279 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3280 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3281 emitcode ("cpl", "c");
3282 emitcode ("", "%05d$:", (lbl->key + 100));
3283 outBitC (IC_RESULT (ic));
3287 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3288 emitcode ("subb", "a,acc");
3289 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3290 emitcode ("inc", "a");
3291 emitcode ("", "%05d$:", (lbl->key + 100));
3292 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3293 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3297 /*-----------------------------------------------------------------*/
3298 /* genMinus - generates code for subtraction */
3299 /*-----------------------------------------------------------------*/
3301 genMinus (iCode * ic)
3303 int size, offset = 0;
3304 unsigned long lit = 0L;
3306 D(emitcode (";", "genMinus"));
3308 aopOp (IC_LEFT (ic), ic, FALSE);
3309 aopOp (IC_RIGHT (ic), ic, FALSE);
3310 aopOp (IC_RESULT (ic), ic, TRUE);
3312 /* special cases :- */
3313 /* if both left & right are in bit space */
3314 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3315 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3321 /* if I can do an decrement instead
3322 of subtract then GOOD for ME */
3323 if (genMinusDec (ic) == TRUE)
3326 size = getDataSize (IC_RESULT (ic));
3328 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3334 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3338 /* if literal, add a,#-lit, else normal subb */
3341 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3342 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3343 emitcode ("subb", "a,%s",
3344 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3347 /* first add without previous c */
3349 if (!size && lit==-1) {
3350 emitcode ("dec", "a");
3352 emitcode ("add", "a,#0x%02x",
3353 (unsigned int) (lit & 0x0FFL));
3356 emitcode ("addc", "a,#0x%02x",
3357 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3360 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3363 adjustArithmeticResult (ic);
3366 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3367 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3368 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3372 /*-----------------------------------------------------------------*/
3373 /* genMultbits :- multiplication of bits */
3374 /*-----------------------------------------------------------------*/
3376 genMultbits (operand * left,
3380 D(emitcode (";", "genMultbits"));
3382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3383 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3388 /*-----------------------------------------------------------------*/
3389 /* genMultOneByte : 8*8=8/16 bit multiplication */
3390 /*-----------------------------------------------------------------*/
3392 genMultOneByte (operand * left,
3396 sym_link *opetype = operandType (result);
3398 int size=AOP_SIZE(result);
3400 D(emitcode (";", "genMultOneByte"));
3402 if (size<1 || size>2) {
3403 // this should never happen
3404 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3405 AOP_SIZE(result), __FILE__, lineno);
3409 /* (if two literals: the value is computed before) */
3410 /* if one literal, literal on the right */
3411 if (AOP_TYPE (left) == AOP_LIT)
3416 //emitcode (";", "swapped left and right");
3419 if (SPEC_USIGN(opetype)
3420 // ignore the sign of left and right, what else can we do?
3421 || (SPEC_USIGN(operandType(left)) &&
3422 SPEC_USIGN(operandType(right)))) {
3423 // just an unsigned 8*8=8/16 multiply
3424 //emitcode (";","unsigned");
3425 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3426 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3427 emitcode ("mul", "ab");
3428 aopPut (AOP (result), "a", 0);
3430 aopPut (AOP (result), "b", 1);
3435 // we have to do a signed multiply
3437 //emitcode (";", "signed");
3438 emitcode ("clr", "F0"); // reset sign flag
3439 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3441 lbl=newiTempLabel(NULL);
3442 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3443 // left side is negative, 8-bit two's complement, this fails for -128
3444 emitcode ("setb", "F0"); // set sign flag
3445 emitcode ("cpl", "a");
3446 emitcode ("inc", "a");
3448 emitcode ("", "%05d$:", lbl->key+100);
3451 if (AOP_TYPE(right)==AOP_LIT) {
3452 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3453 /* AND literal negative */
3455 emitcode ("cpl", "F0"); // complement sign flag
3456 emitcode ("mov", "b,#0x%02x", -val);
3458 emitcode ("mov", "b,#0x%02x", val);
3461 lbl=newiTempLabel(NULL);
3462 emitcode ("mov", "b,a");
3463 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3464 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3465 // right side is negative, 8-bit two's complement
3466 emitcode ("cpl", "F0"); // complement sign flag
3467 emitcode ("cpl", "a");
3468 emitcode ("inc", "a");
3469 emitcode ("", "%05d$:", lbl->key+100);
3471 emitcode ("mul", "ab");
3473 lbl=newiTempLabel(NULL);
3474 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3475 // only ONE op was negative, we have to do a 8/16-bit two's complement
3476 emitcode ("cpl", "a"); // lsb
3478 emitcode ("inc", "a");
3480 emitcode ("add", "a,#1");
3481 emitcode ("xch", "a,b");
3482 emitcode ("cpl", "a"); // msb
3483 emitcode ("addc", "a,#0");
3484 emitcode ("xch", "a,b");
3487 emitcode ("", "%05d$:", lbl->key+100);
3488 aopPut (AOP (result), "a", 0);
3490 aopPut (AOP (result), "b", 1);
3494 /*-----------------------------------------------------------------*/
3495 /* genMult - generates code for multiplication */
3496 /*-----------------------------------------------------------------*/
3498 genMult (iCode * ic)
3500 operand *left = IC_LEFT (ic);
3501 operand *right = IC_RIGHT (ic);
3502 operand *result = IC_RESULT (ic);
3504 D(emitcode (";", "genMult"));
3506 /* assign the amsops */
3507 aopOp (left, ic, FALSE);
3508 aopOp (right, ic, FALSE);
3509 aopOp (result, ic, TRUE);
3511 /* special cases first */
3513 if (AOP_TYPE (left) == AOP_CRY &&
3514 AOP_TYPE (right) == AOP_CRY)
3516 genMultbits (left, right, result);
3520 /* if both are of size == 1 */
3521 #if 0 // one of them can be a sloc shared with the result
3522 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3524 if (getSize(operandType(left)) == 1 &&
3525 getSize(operandType(right)) == 1)
3528 genMultOneByte (left, right, result);
3532 /* should have been converted to function call */
3533 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3534 getSize(OP_SYMBOL(right)->type));
3538 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3539 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3540 freeAsmop (result, NULL, ic, TRUE);
3543 /*-----------------------------------------------------------------*/
3544 /* genDivbits :- division of bits */
3545 /*-----------------------------------------------------------------*/
3547 genDivbits (operand * left,
3554 D(emitcode (";", "genDivbits"));
3556 /* the result must be bit */
3557 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3558 l = aopGet (AOP (left), 0, FALSE, FALSE);
3562 emitcode ("div", "ab");
3563 emitcode ("rrc", "a");
3564 aopPut (AOP (result), "c", 0);
3567 /*-----------------------------------------------------------------*/
3568 /* genDivOneByte : 8 bit division */
3569 /*-----------------------------------------------------------------*/
3571 genDivOneByte (operand * left,
3575 sym_link *opetype = operandType (result);
3580 D(emitcode (";", "genDivOneByte"));
3582 size = AOP_SIZE (result) - 1;
3584 /* signed or unsigned */
3585 if (SPEC_USIGN (opetype))
3587 /* unsigned is easy */
3588 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3589 l = aopGet (AOP (left), 0, FALSE, FALSE);
3591 emitcode ("div", "ab");
3592 aopPut (AOP (result), "a", 0);
3594 aopPut (AOP (result), zero, offset++);
3598 /* signed is a little bit more difficult */
3600 /* save the signs of the operands */
3601 l = aopGet (AOP (left), 0, FALSE, FALSE);
3603 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3604 emitcode ("push", "acc"); /* save it on the stack */
3606 /* now sign adjust for both left & right */
3607 l = aopGet (AOP (right), 0, FALSE, FALSE);
3609 lbl = newiTempLabel (NULL);
3610 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3611 emitcode ("cpl", "a");
3612 emitcode ("inc", "a");
3613 emitcode ("", "%05d$:", (lbl->key + 100));
3614 emitcode ("mov", "b,a");
3616 /* sign adjust left side */
3617 l = aopGet (AOP (left), 0, FALSE, FALSE);
3620 lbl = newiTempLabel (NULL);
3621 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3622 emitcode ("cpl", "a");
3623 emitcode ("inc", "a");
3624 emitcode ("", "%05d$:", (lbl->key + 100));
3626 /* now the division */
3627 emitcode ("div", "ab");
3628 /* we are interested in the lower order
3630 emitcode ("mov", "b,a");
3631 lbl = newiTempLabel (NULL);
3632 emitcode ("pop", "acc");
3633 /* if there was an over flow we don't
3634 adjust the sign of the result */
3635 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3636 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3638 emitcode ("clr", "a");
3639 emitcode ("subb", "a,b");
3640 emitcode ("mov", "b,a");
3641 emitcode ("", "%05d$:", (lbl->key + 100));
3643 /* now we are done */
3644 aopPut (AOP (result), "b", 0);
3647 emitcode ("mov", "c,b.7");
3648 emitcode ("subb", "a,acc");
3651 aopPut (AOP (result), "a", offset++);
3655 /*-----------------------------------------------------------------*/
3656 /* genDiv - generates code for division */
3657 /*-----------------------------------------------------------------*/
3661 operand *left = IC_LEFT (ic);
3662 operand *right = IC_RIGHT (ic);
3663 operand *result = IC_RESULT (ic);
3665 D(emitcode (";", "genDiv"));
3667 /* assign the amsops */
3668 aopOp (left, ic, FALSE);
3669 aopOp (right, ic, FALSE);
3670 aopOp (result, ic, TRUE);
3672 /* special cases first */
3674 if (AOP_TYPE (left) == AOP_CRY &&
3675 AOP_TYPE (right) == AOP_CRY)
3677 genDivbits (left, right, result);
3681 /* if both are of size == 1 */
3682 if (AOP_SIZE (left) == 1 &&
3683 AOP_SIZE (right) == 1)
3685 genDivOneByte (left, right, result);
3689 /* should have been converted to function call */
3692 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3693 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3694 freeAsmop (result, NULL, ic, TRUE);
3697 /*-----------------------------------------------------------------*/
3698 /* genModbits :- modulus of bits */
3699 /*-----------------------------------------------------------------*/
3701 genModbits (operand * left,
3708 D(emitcode (";", "genModbits"));
3710 /* the result must be bit */
3711 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3712 l = aopGet (AOP (left), 0, FALSE, FALSE);
3716 emitcode ("div", "ab");
3717 emitcode ("mov", "a,b");
3718 emitcode ("rrc", "a");
3719 aopPut (AOP (result), "c", 0);
3722 /*-----------------------------------------------------------------*/
3723 /* genModOneByte : 8 bit modulus */
3724 /*-----------------------------------------------------------------*/
3726 genModOneByte (operand * left,
3730 sym_link *opetype = operandType (result);
3734 D(emitcode (";", "genModOneByte"));
3736 /* signed or unsigned */
3737 if (SPEC_USIGN (opetype))
3739 /* unsigned is easy */
3740 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3741 l = aopGet (AOP (left), 0, FALSE, FALSE);
3743 emitcode ("div", "ab");
3744 aopPut (AOP (result), "b", 0);
3748 /* signed is a little bit more difficult */
3750 /* save the signs of the operands */
3751 l = aopGet (AOP (left), 0, FALSE, FALSE);
3754 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3755 emitcode ("push", "acc"); /* save it on the stack */
3757 /* now sign adjust for both left & right */
3758 l = aopGet (AOP (right), 0, FALSE, FALSE);
3761 lbl = newiTempLabel (NULL);
3762 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3763 emitcode ("cpl", "a");
3764 emitcode ("inc", "a");
3765 emitcode ("", "%05d$:", (lbl->key + 100));
3766 emitcode ("mov", "b,a");
3768 /* sign adjust left side */
3769 l = aopGet (AOP (left), 0, FALSE, FALSE);
3772 lbl = newiTempLabel (NULL);
3773 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3774 emitcode ("cpl", "a");
3775 emitcode ("inc", "a");
3776 emitcode ("", "%05d$:", (lbl->key + 100));
3778 /* now the multiplication */
3779 emitcode ("div", "ab");
3780 /* we are interested in the lower order
3782 lbl = newiTempLabel (NULL);
3783 emitcode ("pop", "acc");
3784 /* if there was an over flow we don't
3785 adjust the sign of the result */
3786 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3787 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3789 emitcode ("clr", "a");
3790 emitcode ("subb", "a,b");
3791 emitcode ("mov", "b,a");
3792 emitcode ("", "%05d$:", (lbl->key + 100));
3794 /* now we are done */
3795 aopPut (AOP (result), "b", 0);
3799 /*-----------------------------------------------------------------*/
3800 /* genMod - generates code for division */
3801 /*-----------------------------------------------------------------*/
3805 operand *left = IC_LEFT (ic);
3806 operand *right = IC_RIGHT (ic);
3807 operand *result = IC_RESULT (ic);
3809 D(emitcode (";", "genMod"));
3811 /* assign the amsops */
3812 aopOp (left, ic, FALSE);
3813 aopOp (right, ic, FALSE);
3814 aopOp (result, ic, TRUE);
3816 /* special cases first */
3818 if (AOP_TYPE (left) == AOP_CRY &&
3819 AOP_TYPE (right) == AOP_CRY)
3821 genModbits (left, right, result);
3825 /* if both are of size == 1 */
3826 if (AOP_SIZE (left) == 1 &&
3827 AOP_SIZE (right) == 1)
3829 genModOneByte (left, right, result);
3833 /* should have been converted to function call */
3837 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3838 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3839 freeAsmop (result, NULL, ic, TRUE);
3842 /*-----------------------------------------------------------------*/
3843 /* genIfxJump :- will create a jump depending on the ifx */
3844 /*-----------------------------------------------------------------*/
3846 genIfxJump (iCode * ic, char *jval)
3849 symbol *tlbl = newiTempLabel (NULL);
3852 D(emitcode (";", "genIfxJump"));
3854 /* if true label then we jump if condition
3858 jlbl = IC_TRUE (ic);
3859 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3860 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3864 /* false label is present */
3865 jlbl = IC_FALSE (ic);
3866 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3867 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3869 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3870 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3872 emitcode (inst, "%05d$", tlbl->key + 100);
3873 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3874 emitcode ("", "%05d$:", tlbl->key + 100);
3876 /* mark the icode as generated */
3880 /*-----------------------------------------------------------------*/
3881 /* genCmp :- greater or less than comparison */
3882 /*-----------------------------------------------------------------*/
3884 genCmp (operand * left, operand * right,
3885 operand * result, iCode * ifx, int sign, iCode *ic)
3887 int size, offset = 0;
3888 unsigned long lit = 0L;
3890 D(emitcode (";", "genCmp"));
3892 /* if left & right are bit variables */
3893 if (AOP_TYPE (left) == AOP_CRY &&
3894 AOP_TYPE (right) == AOP_CRY)
3896 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3897 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3901 /* subtract right from left if at the
3902 end the carry flag is set then we know that
3903 left is greater than right */
3904 size = max (AOP_SIZE (left), AOP_SIZE (right));
3906 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3907 if ((size == 1) && !sign &&
3908 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3910 symbol *lbl = newiTempLabel (NULL);
3911 emitcode ("cjne", "%s,%s,%05d$",
3912 aopGet (AOP (left), offset, FALSE, FALSE),
3913 aopGet (AOP (right), offset, FALSE, FALSE),
3915 emitcode ("", "%05d$:", lbl->key + 100);
3919 if (AOP_TYPE (right) == AOP_LIT)
3921 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3922 /* optimize if(x < 0) or if(x >= 0) */
3931 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3932 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3934 genIfxJump (ifx, "acc.7");
3938 emitcode ("rlc", "a");
3946 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3947 if (sign && size == 0)
3949 emitcode ("xrl", "a,#0x80");
3950 if (AOP_TYPE (right) == AOP_LIT)
3952 unsigned long lit = (unsigned long)
3953 floatFromVal (AOP (right)->aopu.aop_lit);
3954 emitcode ("subb", "a,#0x%02x",
3955 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3959 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3960 emitcode ("xrl", "b,#0x80");
3961 emitcode ("subb", "a,b");
3965 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3971 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3972 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3973 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3979 /* if the result is used in the next
3980 ifx conditional branch then generate
3981 code a little differently */
3983 genIfxJump (ifx, "c");
3986 /* leave the result in acc */
3990 /*-----------------------------------------------------------------*/
3991 /* genCmpGt :- greater than comparison */
3992 /*-----------------------------------------------------------------*/
3994 genCmpGt (iCode * ic, iCode * ifx)
3996 operand *left, *right, *result;
3997 sym_link *letype, *retype;
4000 D(emitcode (";", "genCmpGt"));
4002 left = IC_LEFT (ic);
4003 right = IC_RIGHT (ic);
4004 result = IC_RESULT (ic);
4006 letype = getSpec (operandType (left));
4007 retype = getSpec (operandType (right));
4008 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4009 /* assign the amsops */
4010 aopOp (left, ic, FALSE);
4011 aopOp (right, ic, FALSE);
4012 aopOp (result, ic, TRUE);
4014 genCmp (right, left, result, ifx, sign,ic);
4016 freeAsmop (result, NULL, ic, TRUE);
4019 /*-----------------------------------------------------------------*/
4020 /* genCmpLt - less than comparisons */
4021 /*-----------------------------------------------------------------*/
4023 genCmpLt (iCode * ic, iCode * ifx)
4025 operand *left, *right, *result;
4026 sym_link *letype, *retype;
4029 D(emitcode (";", "genCmpLt"));
4031 left = IC_LEFT (ic);
4032 right = IC_RIGHT (ic);
4033 result = IC_RESULT (ic);
4035 letype = getSpec (operandType (left));
4036 retype = getSpec (operandType (right));
4037 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4039 /* assign the amsops */
4040 aopOp (left, ic, FALSE);
4041 aopOp (right, ic, FALSE);
4042 aopOp (result, ic, TRUE);
4044 genCmp (left, right, result, ifx, sign,ic);
4046 freeAsmop (result, NULL, ic, TRUE);
4049 /*-----------------------------------------------------------------*/
4050 /* gencjneshort - compare and jump if not equal */
4051 /*-----------------------------------------------------------------*/
4053 gencjneshort (operand * left, operand * right, symbol * lbl)
4055 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4057 unsigned long lit = 0L;
4059 /* if the left side is a literal or
4060 if the right is in a pointer register and left
4062 if ((AOP_TYPE (left) == AOP_LIT) ||
4063 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4069 if (AOP_TYPE (right) == AOP_LIT)
4070 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4072 /* if the right side is a literal then anything goes */
4073 if (AOP_TYPE (right) == AOP_LIT &&
4074 AOP_TYPE (left) != AOP_DIR)
4078 emitcode ("cjne", "%s,%s,%05d$",
4079 aopGet (AOP (left), offset, FALSE, FALSE),
4080 aopGet (AOP (right), offset, FALSE, FALSE),
4086 /* if the right side is in a register or in direct space or
4087 if the left is a pointer register & right is not */
4088 else if (AOP_TYPE (right) == AOP_REG ||
4089 AOP_TYPE (right) == AOP_DIR ||
4090 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4091 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4095 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4096 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4097 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4098 emitcode ("jnz", "%05d$", lbl->key + 100);
4100 emitcode ("cjne", "a,%s,%05d$",
4101 aopGet (AOP (right), offset, FALSE, TRUE),
4108 /* right is a pointer reg need both a & b */
4111 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4112 if (strcmp (l, "b"))
4113 emitcode ("mov", "b,%s", l);
4114 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4115 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4121 /*-----------------------------------------------------------------*/
4122 /* gencjne - compare and jump if not equal */
4123 /*-----------------------------------------------------------------*/
4125 gencjne (operand * left, operand * right, symbol * lbl)
4127 symbol *tlbl = newiTempLabel (NULL);
4129 gencjneshort (left, right, lbl);
4131 emitcode ("mov", "a,%s", one);
4132 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4133 emitcode ("", "%05d$:", lbl->key + 100);
4134 emitcode ("clr", "a");
4135 emitcode ("", "%05d$:", tlbl->key + 100);
4138 /*-----------------------------------------------------------------*/
4139 /* genCmpEq - generates code for equal to */
4140 /*-----------------------------------------------------------------*/
4142 genCmpEq (iCode * ic, iCode * ifx)
4144 operand *left, *right, *result;
4146 D(emitcode (";", "genCmpEq"));
4148 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4149 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4150 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4152 /* if literal, literal on the right or
4153 if the right is in a pointer register and left
4155 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4156 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4158 operand *t = IC_RIGHT (ic);
4159 IC_RIGHT (ic) = IC_LEFT (ic);
4163 if (ifx && !AOP_SIZE (result))
4166 /* if they are both bit variables */
4167 if (AOP_TYPE (left) == AOP_CRY &&
4168 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4170 if (AOP_TYPE (right) == AOP_LIT)
4172 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4175 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4176 emitcode ("cpl", "c");
4180 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4184 emitcode ("clr", "c");
4186 /* AOP_TYPE(right) == AOP_CRY */
4190 symbol *lbl = newiTempLabel (NULL);
4191 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4192 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4193 emitcode ("cpl", "c");
4194 emitcode ("", "%05d$:", (lbl->key + 100));
4196 /* if true label then we jump if condition
4198 tlbl = newiTempLabel (NULL);
4201 emitcode ("jnc", "%05d$", tlbl->key + 100);
4202 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4206 emitcode ("jc", "%05d$", tlbl->key + 100);
4207 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4209 emitcode ("", "%05d$:", tlbl->key + 100);
4213 tlbl = newiTempLabel (NULL);
4214 gencjneshort (left, right, tlbl);
4217 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4218 emitcode ("", "%05d$:", tlbl->key + 100);
4222 symbol *lbl = newiTempLabel (NULL);
4223 emitcode ("sjmp", "%05d$", lbl->key + 100);
4224 emitcode ("", "%05d$:", tlbl->key + 100);
4225 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4226 emitcode ("", "%05d$:", lbl->key + 100);
4229 /* mark the icode as generated */
4234 /* if they are both bit variables */
4235 if (AOP_TYPE (left) == AOP_CRY &&
4236 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4238 if (AOP_TYPE (right) == AOP_LIT)
4240 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4243 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4244 emitcode ("cpl", "c");
4248 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4252 emitcode ("clr", "c");
4254 /* AOP_TYPE(right) == AOP_CRY */
4258 symbol *lbl = newiTempLabel (NULL);
4259 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4260 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4261 emitcode ("cpl", "c");
4262 emitcode ("", "%05d$:", (lbl->key + 100));
4265 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4272 genIfxJump (ifx, "c");
4275 /* if the result is used in an arithmetic operation
4276 then put the result in place */
4281 gencjne (left, right, newiTempLabel (NULL));
4282 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4284 aopPut (AOP (result), "a", 0);
4289 genIfxJump (ifx, "a");
4292 /* if the result is used in an arithmetic operation
4293 then put the result in place */
4294 if (AOP_TYPE (result) != AOP_CRY)
4296 /* leave the result in acc */
4300 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4301 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4302 freeAsmop (result, NULL, ic, TRUE);
4305 /*-----------------------------------------------------------------*/
4306 /* ifxForOp - returns the icode containing the ifx for operand */
4307 /*-----------------------------------------------------------------*/
4309 ifxForOp (operand * op, iCode * ic)
4311 /* if true symbol then needs to be assigned */
4312 if (IS_TRUE_SYMOP (op))
4315 /* if this has register type condition and
4316 the next instruction is ifx with the same operand
4317 and live to of the operand is upto the ifx only then */
4319 ic->next->op == IFX &&
4320 IC_COND (ic->next)->key == op->key &&
4321 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4327 /*-----------------------------------------------------------------*/
4328 /* hasInc - operand is incremented before any other use */
4329 /*-----------------------------------------------------------------*/
4331 hasInc (operand *op, iCode *ic,int osize)
4333 sym_link *type = operandType(op);
4334 sym_link *retype = getSpec (type);
4335 iCode *lic = ic->next;
4338 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4339 if (!IS_SYMOP(op)) return NULL;
4341 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4342 if (osize != (isize = getSize(type->next))) return NULL;
4344 /* if operand of the form op = op + <sizeof *op> */
4345 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4346 isOperandEqual(IC_RESULT(lic),op) &&
4347 isOperandLiteral(IC_RIGHT(lic)) &&
4348 operandLitValue(IC_RIGHT(lic)) == isize) {
4351 /* if the operand used or deffed */
4352 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4355 /* if GOTO or IFX */
4356 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4362 /*-----------------------------------------------------------------*/
4363 /* genAndOp - for && operation */
4364 /*-----------------------------------------------------------------*/
4366 genAndOp (iCode * ic)
4368 operand *left, *right, *result;
4371 D(emitcode (";", "genAndOp"));
4373 /* note here that && operations that are in an
4374 if statement are taken away by backPatchLabels
4375 only those used in arthmetic operations remain */
4376 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4377 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4378 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4380 /* if both are bit variables */
4381 if (AOP_TYPE (left) == AOP_CRY &&
4382 AOP_TYPE (right) == AOP_CRY)
4384 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4385 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4390 tlbl = newiTempLabel (NULL);
4392 emitcode ("jz", "%05d$", tlbl->key + 100);
4394 emitcode ("", "%05d$:", tlbl->key + 100);
4398 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4399 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4400 freeAsmop (result, NULL, ic, TRUE);
4404 /*-----------------------------------------------------------------*/
4405 /* genOrOp - for || operation */
4406 /*-----------------------------------------------------------------*/
4408 genOrOp (iCode * ic)
4410 operand *left, *right, *result;
4413 D(emitcode (";", "genOrOp"));
4415 /* note here that || operations that are in an
4416 if statement are taken away by backPatchLabels
4417 only those used in arthmetic operations remain */
4418 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4419 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4420 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4422 /* if both are bit variables */
4423 if (AOP_TYPE (left) == AOP_CRY &&
4424 AOP_TYPE (right) == AOP_CRY)
4426 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4427 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4432 tlbl = newiTempLabel (NULL);
4434 emitcode ("jnz", "%05d$", tlbl->key + 100);
4436 emitcode ("", "%05d$:", tlbl->key + 100);
4440 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4441 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4442 freeAsmop (result, NULL, ic, TRUE);
4445 /*-----------------------------------------------------------------*/
4446 /* isLiteralBit - test if lit == 2^n */
4447 /*-----------------------------------------------------------------*/
4449 isLiteralBit (unsigned long lit)
4451 unsigned long pw[32] =
4452 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4453 0x100L, 0x200L, 0x400L, 0x800L,
4454 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4455 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4456 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4457 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4458 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4461 for (idx = 0; idx < 32; idx++)
4467 /*-----------------------------------------------------------------*/
4468 /* continueIfTrue - */
4469 /*-----------------------------------------------------------------*/
4471 continueIfTrue (iCode * ic)
4474 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4478 /*-----------------------------------------------------------------*/
4480 /*-----------------------------------------------------------------*/
4482 jumpIfTrue (iCode * ic)
4485 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4489 /*-----------------------------------------------------------------*/
4490 /* jmpTrueOrFalse - */
4491 /*-----------------------------------------------------------------*/
4493 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4495 // ugly but optimized by peephole
4498 symbol *nlbl = newiTempLabel (NULL);
4499 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4500 emitcode ("", "%05d$:", tlbl->key + 100);
4501 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4502 emitcode ("", "%05d$:", nlbl->key + 100);
4506 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4507 emitcode ("", "%05d$:", tlbl->key + 100);
4512 /*-----------------------------------------------------------------*/
4513 /* genAnd - code for and */
4514 /*-----------------------------------------------------------------*/
4516 genAnd (iCode * ic, iCode * ifx)
4518 operand *left, *right, *result;
4519 int size, offset = 0;
4520 unsigned long lit = 0L;
4524 D(emitcode (";", "genAnd"));
4526 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4527 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4528 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4531 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4533 AOP_TYPE (left), AOP_TYPE (right));
4534 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4536 AOP_SIZE (left), AOP_SIZE (right));
4539 /* if left is a literal & right is not then exchange them */
4540 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4541 AOP_NEEDSACC (left))
4543 operand *tmp = right;
4548 /* if result = right then exchange them */
4549 if (sameRegs (AOP (result), AOP (right)))
4551 operand *tmp = right;
4556 /* if right is bit then exchange them */
4557 if (AOP_TYPE (right) == AOP_CRY &&
4558 AOP_TYPE (left) != AOP_CRY)
4560 operand *tmp = right;
4564 if (AOP_TYPE (right) == AOP_LIT)
4565 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4567 size = AOP_SIZE (result);
4570 // result = bit & yy;
4571 if (AOP_TYPE (left) == AOP_CRY)
4573 // c = bit & literal;
4574 if (AOP_TYPE (right) == AOP_LIT)
4578 if (size && sameRegs (AOP (result), AOP (left)))
4581 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4586 if (size && (AOP_TYPE (result) == AOP_CRY))
4588 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4591 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4596 emitcode ("clr", "c");
4601 if (AOP_TYPE (right) == AOP_CRY)
4604 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4605 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4610 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4612 emitcode ("rrc", "a");
4613 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4621 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4622 genIfxJump (ifx, "c");
4626 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4627 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4628 if ((AOP_TYPE (right) == AOP_LIT) &&
4629 (AOP_TYPE (result) == AOP_CRY) &&
4630 (AOP_TYPE (left) != AOP_CRY))
4632 int posbit = isLiteralBit (lit);
4637 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4640 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4646 sprintf (buffer, "acc.%d", posbit & 0x07);
4647 genIfxJump (ifx, buffer);
4654 symbol *tlbl = newiTempLabel (NULL);
4655 int sizel = AOP_SIZE (left);
4657 emitcode ("setb", "c");
4660 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4662 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4664 if ((posbit = isLiteralBit (bytelit)) != 0)
4665 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4668 if (bytelit != 0x0FFL)
4669 emitcode ("anl", "a,%s",
4670 aopGet (AOP (right), offset, FALSE, TRUE));
4671 emitcode ("jnz", "%05d$", tlbl->key + 100);
4676 // bit = left & literal
4679 emitcode ("clr", "c");
4680 emitcode ("", "%05d$:", tlbl->key + 100);
4682 // if(left & literal)
4686 jmpTrueOrFalse (ifx, tlbl);
4694 /* if left is same as result */
4695 if (sameRegs (AOP (result), AOP (left)))
4697 for (; size--; offset++)
4699 if (AOP_TYPE (right) == AOP_LIT)
4701 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4703 else if (bytelit == 0)
4704 aopPut (AOP (result), zero, offset);
4705 else if (IS_AOP_PREG (result))
4707 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4708 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4709 aopPut (AOP (result), "a", offset);
4712 emitcode ("anl", "%s,%s",
4713 aopGet (AOP (left), offset, FALSE, TRUE),
4714 aopGet (AOP (right), offset, FALSE, FALSE));
4718 if (AOP_TYPE (left) == AOP_ACC)
4719 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4722 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4723 if (IS_AOP_PREG (result))
4725 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4726 aopPut (AOP (result), "a", offset);
4730 emitcode ("anl", "%s,a",
4731 aopGet (AOP (left), offset, FALSE, TRUE));
4738 // left & result in different registers
4739 if (AOP_TYPE (result) == AOP_CRY)
4742 // if(size), result in bit
4743 // if(!size && ifx), conditional oper: if(left & right)
4744 symbol *tlbl = newiTempLabel (NULL);
4745 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4747 emitcode ("setb", "c");
4750 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4751 emitcode ("anl", "a,%s",
4752 aopGet (AOP (right), offset, FALSE, FALSE));
4754 if (AOP_TYPE(left)==AOP_ACC) {
4755 emitcode("mov", "b,a");
4756 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4757 emitcode("anl", "a,b");
4759 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4760 emitcode ("anl", "a,%s",
4761 aopGet (AOP (left), offset, FALSE, FALSE));
4764 emitcode ("jnz", "%05d$", tlbl->key + 100);
4770 emitcode ("", "%05d$:", tlbl->key + 100);
4774 jmpTrueOrFalse (ifx, tlbl);
4778 for (; (size--); offset++)
4781 // result = left & right
4782 if (AOP_TYPE (right) == AOP_LIT)
4784 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4786 aopPut (AOP (result),
4787 aopGet (AOP (left), offset, FALSE, FALSE),
4791 else if (bytelit == 0)
4793 aopPut (AOP (result), zero, offset);
4797 // faster than result <- left, anl result,right
4798 // and better if result is SFR
4799 if (AOP_TYPE (left) == AOP_ACC)
4800 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4803 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4804 emitcode ("anl", "a,%s",
4805 aopGet (AOP (left), offset, FALSE, FALSE));
4807 aopPut (AOP (result), "a", offset);
4813 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4814 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4815 freeAsmop (result, NULL, ic, TRUE);
4818 /*-----------------------------------------------------------------*/
4819 /* genOr - code for or */
4820 /*-----------------------------------------------------------------*/
4822 genOr (iCode * ic, iCode * ifx)
4824 operand *left, *right, *result;
4825 int size, offset = 0;
4826 unsigned long lit = 0L;
4828 D(emitcode (";", "genOr"));
4830 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4831 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4832 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4835 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4837 AOP_TYPE (left), AOP_TYPE (right));
4838 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4840 AOP_SIZE (left), AOP_SIZE (right));
4843 /* if left is a literal & right is not then exchange them */
4844 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4845 AOP_NEEDSACC (left))
4847 operand *tmp = right;
4852 /* if result = right then exchange them */
4853 if (sameRegs (AOP (result), AOP (right)))
4855 operand *tmp = right;
4860 /* if right is bit then exchange them */
4861 if (AOP_TYPE (right) == AOP_CRY &&
4862 AOP_TYPE (left) != AOP_CRY)
4864 operand *tmp = right;
4868 if (AOP_TYPE (right) == AOP_LIT)
4869 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4871 size = AOP_SIZE (result);
4875 if (AOP_TYPE (left) == AOP_CRY)
4877 if (AOP_TYPE (right) == AOP_LIT)
4879 // c = bit & literal;
4882 // lit != 0 => result = 1
4883 if (AOP_TYPE (result) == AOP_CRY)
4886 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4888 continueIfTrue (ifx);
4891 emitcode ("setb", "c");
4895 // lit == 0 => result = left
4896 if (size && sameRegs (AOP (result), AOP (left)))
4898 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4903 if (AOP_TYPE (right) == AOP_CRY)
4906 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4907 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4912 symbol *tlbl = newiTempLabel (NULL);
4913 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4914 emitcode ("setb", "c");
4915 emitcode ("jb", "%s,%05d$",
4916 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4918 emitcode ("jnz", "%05d$", tlbl->key + 100);
4919 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4921 jmpTrueOrFalse (ifx, tlbl);
4927 emitcode ("", "%05d$:", tlbl->key + 100);
4936 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4937 genIfxJump (ifx, "c");
4941 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4942 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4943 if ((AOP_TYPE (right) == AOP_LIT) &&
4944 (AOP_TYPE (result) == AOP_CRY) &&
4945 (AOP_TYPE (left) != AOP_CRY))
4951 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4953 continueIfTrue (ifx);
4958 // lit = 0, result = boolean(left)
4960 emitcode ("setb", "c");
4964 symbol *tlbl = newiTempLabel (NULL);
4965 emitcode ("jnz", "%05d$", tlbl->key + 100);
4967 emitcode ("", "%05d$:", tlbl->key + 100);
4971 genIfxJump (ifx, "a");
4979 /* if left is same as result */
4980 if (sameRegs (AOP (result), AOP (left)))
4982 for (; size--; offset++)
4984 if (AOP_TYPE (right) == AOP_LIT)
4986 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4988 else if (IS_AOP_PREG (left))
4990 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4991 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4992 aopPut (AOP (result), "a", offset);
4995 emitcode ("orl", "%s,%s",
4996 aopGet (AOP (left), offset, FALSE, TRUE),
4997 aopGet (AOP (right), offset, FALSE, FALSE));
5001 if (AOP_TYPE (left) == AOP_ACC)
5002 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5005 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5006 if (IS_AOP_PREG (left))
5008 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5009 aopPut (AOP (result), "a", offset);
5012 emitcode ("orl", "%s,a",
5013 aopGet (AOP (left), offset, FALSE, TRUE));
5020 // left & result in different registers
5021 if (AOP_TYPE (result) == AOP_CRY)
5024 // if(size), result in bit
5025 // if(!size && ifx), conditional oper: if(left | right)
5026 symbol *tlbl = newiTempLabel (NULL);
5027 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5029 emitcode ("setb", "c");
5032 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5033 emitcode ("orl", "a,%s",
5034 aopGet (AOP (right), offset, FALSE, FALSE));
5036 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5037 emitcode ("orl", "a,%s",
5038 aopGet (AOP (left), offset, FALSE, FALSE));
5040 emitcode ("jnz", "%05d$", tlbl->key + 100);
5046 emitcode ("", "%05d$:", tlbl->key + 100);
5050 jmpTrueOrFalse (ifx, tlbl);
5053 for (; (size--); offset++)
5056 // result = left & right
5057 if (AOP_TYPE (right) == AOP_LIT)
5059 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5061 aopPut (AOP (result),
5062 aopGet (AOP (left), offset, FALSE, FALSE),
5067 // faster than result <- left, anl result,right
5068 // and better if result is SFR
5069 if (AOP_TYPE (left) == AOP_ACC)
5070 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5073 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5074 emitcode ("orl", "a,%s",
5075 aopGet (AOP (left), offset, FALSE, FALSE));
5077 aopPut (AOP (result), "a", offset);
5082 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5083 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5084 freeAsmop (result, NULL, ic, TRUE);
5087 /*-----------------------------------------------------------------*/
5088 /* genXor - code for xclusive or */
5089 /*-----------------------------------------------------------------*/
5091 genXor (iCode * ic, iCode * ifx)
5093 operand *left, *right, *result;
5094 int size, offset = 0;
5095 unsigned long lit = 0L;
5097 D(emitcode (";", "genXor"));
5099 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5100 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5101 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5104 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5106 AOP_TYPE (left), AOP_TYPE (right));
5107 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5109 AOP_SIZE (left), AOP_SIZE (right));
5112 /* if left is a literal & right is not ||
5113 if left needs acc & right does not */
5114 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5115 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5117 operand *tmp = right;
5122 /* if result = right then exchange them */
5123 if (sameRegs (AOP (result), AOP (right)))
5125 operand *tmp = right;
5130 /* if right is bit then exchange them */
5131 if (AOP_TYPE (right) == AOP_CRY &&
5132 AOP_TYPE (left) != AOP_CRY)
5134 operand *tmp = right;
5138 if (AOP_TYPE (right) == AOP_LIT)
5139 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5141 size = AOP_SIZE (result);
5145 if (AOP_TYPE (left) == AOP_CRY)
5147 if (AOP_TYPE (right) == AOP_LIT)
5149 // c = bit & literal;
5152 // lit>>1 != 0 => result = 1
5153 if (AOP_TYPE (result) == AOP_CRY)
5156 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5158 continueIfTrue (ifx);
5161 emitcode ("setb", "c");
5168 // lit == 0, result = left
5169 if (size && sameRegs (AOP (result), AOP (left)))
5171 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5175 // lit == 1, result = not(left)
5176 if (size && sameRegs (AOP (result), AOP (left)))
5178 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5183 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5184 emitcode ("cpl", "c");
5193 symbol *tlbl = newiTempLabel (NULL);
5194 if (AOP_TYPE (right) == AOP_CRY)
5197 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5201 int sizer = AOP_SIZE (right);
5203 // if val>>1 != 0, result = 1
5204 emitcode ("setb", "c");
5207 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5209 // test the msb of the lsb
5210 emitcode ("anl", "a,#0xfe");
5211 emitcode ("jnz", "%05d$", tlbl->key + 100);
5215 emitcode ("rrc", "a");
5217 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5218 emitcode ("cpl", "c");
5219 emitcode ("", "%05d$:", (tlbl->key + 100));
5226 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5227 genIfxJump (ifx, "c");
5231 if (sameRegs (AOP (result), AOP (left)))
5233 /* if left is same as result */
5234 for (; size--; offset++)
5236 if (AOP_TYPE (right) == AOP_LIT)
5238 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5240 else if (IS_AOP_PREG (left))
5242 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5243 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5244 aopPut (AOP (result), "a", offset);
5247 emitcode ("xrl", "%s,%s",
5248 aopGet (AOP (left), offset, FALSE, TRUE),
5249 aopGet (AOP (right), offset, FALSE, FALSE));
5253 if (AOP_TYPE (left) == AOP_ACC)
5254 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5257 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5258 if (IS_AOP_PREG (left))
5260 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5261 aopPut (AOP (result), "a", offset);
5264 emitcode ("xrl", "%s,a",
5265 aopGet (AOP (left), offset, FALSE, TRUE));
5272 // left & result in different registers
5273 if (AOP_TYPE (result) == AOP_CRY)
5276 // if(size), result in bit
5277 // if(!size && ifx), conditional oper: if(left ^ right)
5278 symbol *tlbl = newiTempLabel (NULL);
5279 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5281 emitcode ("setb", "c");
5284 if ((AOP_TYPE (right) == AOP_LIT) &&
5285 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5287 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5291 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5292 emitcode ("xrl", "a,%s",
5293 aopGet (AOP (right), offset, FALSE, FALSE));
5295 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5296 emitcode ("xrl", "a,%s",
5297 aopGet (AOP (left), offset, FALSE, FALSE));
5300 emitcode ("jnz", "%05d$", tlbl->key + 100);
5306 emitcode ("", "%05d$:", tlbl->key + 100);
5310 jmpTrueOrFalse (ifx, tlbl);
5313 for (; (size--); offset++)
5316 // result = left & right
5317 if (AOP_TYPE (right) == AOP_LIT)
5319 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5321 aopPut (AOP (result),
5322 aopGet (AOP (left), offset, FALSE, FALSE),
5327 // faster than result <- left, anl result,right
5328 // and better if result is SFR
5329 if (AOP_TYPE (left) == AOP_ACC)
5330 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5334 emitcode ("xrl", "a,%s",
5335 aopGet (AOP (left), offset, FALSE, TRUE));
5337 aopPut (AOP (result), "a", offset);
5342 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5343 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5344 freeAsmop (result, NULL, ic, TRUE);
5347 /*-----------------------------------------------------------------*/
5348 /* genInline - write the inline code out */
5349 /*-----------------------------------------------------------------*/
5351 genInline (iCode * ic)
5353 char *buffer, *bp, *bp1;
5355 D(emitcode (";", "genInline"));
5357 _G.inLine += (!options.asmpeep);
5359 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5360 strcpy (buffer, IC_INLINE (ic));
5362 /* emit each line as a code */
5387 /* emitcode("",buffer); */
5388 _G.inLine -= (!options.asmpeep);
5391 /*-----------------------------------------------------------------*/
5392 /* genRRC - rotate right with carry */
5393 /*-----------------------------------------------------------------*/
5397 operand *left, *result;
5398 int size, offset = 0;
5401 D(emitcode (";", "genRRC"));
5403 /* rotate right with carry */
5404 left = IC_LEFT (ic);
5405 result = IC_RESULT (ic);
5406 aopOp (left, ic, FALSE);
5407 aopOp (result, ic, FALSE);
5409 /* move it to the result */
5410 size = AOP_SIZE (result);
5412 if (size == 1) { /* special case for 1 byte */
5413 l = aopGet (AOP (left), offset, FALSE, FALSE);
5415 emitcode ("rr", "a");
5421 l = aopGet (AOP (left), offset, FALSE, FALSE);
5423 emitcode ("rrc", "a");
5424 if (AOP_SIZE (result) > 1)
5425 aopPut (AOP (result), "a", offset--);
5427 /* now we need to put the carry into the
5428 highest order byte of the result */
5429 if (AOP_SIZE (result) > 1)
5431 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5434 emitcode ("mov", "acc.7,c");
5436 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5437 freeAsmop (left, NULL, ic, TRUE);
5438 freeAsmop (result, NULL, ic, TRUE);
5441 /*-----------------------------------------------------------------*/
5442 /* genRLC - generate code for rotate left with carry */
5443 /*-----------------------------------------------------------------*/
5447 operand *left, *result;
5448 int size, offset = 0;
5451 D(emitcode (";", "genRLC"));
5453 /* rotate right with carry */
5454 left = IC_LEFT (ic);
5455 result = IC_RESULT (ic);
5456 aopOp (left, ic, FALSE);
5457 aopOp (result, ic, FALSE);
5459 /* move it to the result */
5460 size = AOP_SIZE (result);
5464 l = aopGet (AOP (left), offset, FALSE, FALSE);
5466 if (size == 0) { /* special case for 1 byte */
5470 emitcode ("add", "a,acc");
5471 if (AOP_SIZE (result) > 1)
5472 aopPut (AOP (result), "a", offset++);
5475 l = aopGet (AOP (left), offset, FALSE, FALSE);
5477 emitcode ("rlc", "a");
5478 if (AOP_SIZE (result) > 1)
5479 aopPut (AOP (result), "a", offset++);
5482 /* now we need to put the carry into the
5483 highest order byte of the result */
5484 if (AOP_SIZE (result) > 1)
5486 l = aopGet (AOP (result), 0, FALSE, FALSE);
5489 emitcode ("mov", "acc.0,c");
5491 aopPut (AOP (result), "a", 0);
5492 freeAsmop (left, NULL, ic, TRUE);
5493 freeAsmop (result, NULL, ic, TRUE);
5496 /*-----------------------------------------------------------------*/
5497 /* genGetHbit - generates code get highest order bit */
5498 /*-----------------------------------------------------------------*/
5500 genGetHbit (iCode * ic)
5502 operand *left, *result;
5504 D(emitcode (";", "genGetHbit"));
5506 left = IC_LEFT (ic);
5507 result = IC_RESULT (ic);
5508 aopOp (left, ic, FALSE);
5509 aopOp (result, ic, FALSE);
5511 /* get the highest order byte into a */
5512 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5513 if (AOP_TYPE (result) == AOP_CRY)
5515 emitcode ("rlc", "a");
5520 emitcode ("rl", "a");
5521 emitcode ("anl", "a,#0x01");
5526 freeAsmop (left, NULL, ic, TRUE);
5527 freeAsmop (result, NULL, ic, TRUE);
5530 /*-----------------------------------------------------------------*/
5531 /* AccRol - rotate left accumulator by known count */
5532 /*-----------------------------------------------------------------*/
5534 AccRol (int shCount)
5536 shCount &= 0x0007; // shCount : 0..7
5543 emitcode ("rl", "a");
5546 emitcode ("rl", "a");
5547 emitcode ("rl", "a");
5550 emitcode ("swap", "a");
5551 emitcode ("rr", "a");
5554 emitcode ("swap", "a");
5557 emitcode ("swap", "a");
5558 emitcode ("rl", "a");
5561 emitcode ("rr", "a");
5562 emitcode ("rr", "a");
5565 emitcode ("rr", "a");
5570 /*-----------------------------------------------------------------*/
5571 /* AccLsh - left shift accumulator by known count */
5572 /*-----------------------------------------------------------------*/
5574 AccLsh (int shCount)
5579 emitcode ("add", "a,acc");
5580 else if (shCount == 2)
5582 emitcode ("add", "a,acc");
5583 emitcode ("add", "a,acc");
5587 /* rotate left accumulator */
5589 /* and kill the lower order bits */
5590 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5595 /*-----------------------------------------------------------------*/
5596 /* AccRsh - right shift accumulator by known count */
5597 /*-----------------------------------------------------------------*/
5599 AccRsh (int shCount)
5606 emitcode ("rrc", "a");
5610 /* rotate right accumulator */
5611 AccRol (8 - shCount);
5612 /* and kill the higher order bits */
5613 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5618 /*-----------------------------------------------------------------*/
5619 /* AccSRsh - signed right shift accumulator by known count */
5620 /*-----------------------------------------------------------------*/
5622 AccSRsh (int shCount)
5629 emitcode ("mov", "c,acc.7");
5630 emitcode ("rrc", "a");
5632 else if (shCount == 2)
5634 emitcode ("mov", "c,acc.7");
5635 emitcode ("rrc", "a");
5636 emitcode ("mov", "c,acc.7");
5637 emitcode ("rrc", "a");
5641 tlbl = newiTempLabel (NULL);
5642 /* rotate right accumulator */
5643 AccRol (8 - shCount);
5644 /* and kill the higher order bits */
5645 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5646 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5647 emitcode ("orl", "a,#0x%02x",
5648 (unsigned char) ~SRMask[shCount]);
5649 emitcode ("", "%05d$:", tlbl->key + 100);
5654 /*-----------------------------------------------------------------*/
5655 /* shiftR1Left2Result - shift right one byte from left to result */
5656 /*-----------------------------------------------------------------*/
5658 shiftR1Left2Result (operand * left, int offl,
5659 operand * result, int offr,
5660 int shCount, int sign)
5662 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5663 /* shift right accumulator */
5668 aopPut (AOP (result), "a", offr);
5671 /*-----------------------------------------------------------------*/
5672 /* shiftL1Left2Result - shift left one byte from left to result */
5673 /*-----------------------------------------------------------------*/
5675 shiftL1Left2Result (operand * left, int offl,
5676 operand * result, int offr, int shCount)
5679 l = aopGet (AOP (left), offl, FALSE, FALSE);
5681 /* shift left accumulator */
5683 aopPut (AOP (result), "a", offr);
5686 /*-----------------------------------------------------------------*/
5687 /* movLeft2Result - move byte from left to result */
5688 /*-----------------------------------------------------------------*/
5690 movLeft2Result (operand * left, int offl,
5691 operand * result, int offr, int sign)
5694 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5696 l = aopGet (AOP (left), offl, FALSE, FALSE);
5698 if (*l == '@' && (IS_AOP_PREG (result)))
5700 emitcode ("mov", "a,%s", l);
5701 aopPut (AOP (result), "a", offr);
5706 aopPut (AOP (result), l, offr);
5709 /* MSB sign in acc.7 ! */
5710 if (getDataSize (left) == offl + 1)
5712 emitcode ("mov", "a,%s", l);
5713 aopPut (AOP (result), "a", offr);
5720 /*-----------------------------------------------------------------*/
5721 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5722 /*-----------------------------------------------------------------*/
5726 emitcode ("rrc", "a");
5727 emitcode ("xch", "a,%s", x);
5728 emitcode ("rrc", "a");
5729 emitcode ("xch", "a,%s", x);
5732 /*-----------------------------------------------------------------*/
5733 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5734 /*-----------------------------------------------------------------*/
5738 emitcode ("xch", "a,%s", x);
5739 emitcode ("rlc", "a");
5740 emitcode ("xch", "a,%s", x);
5741 emitcode ("rlc", "a");
5744 /*-----------------------------------------------------------------*/
5745 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5746 /*-----------------------------------------------------------------*/
5750 emitcode ("xch", "a,%s", x);
5751 emitcode ("add", "a,acc");
5752 emitcode ("xch", "a,%s", x);
5753 emitcode ("rlc", "a");
5756 /*-----------------------------------------------------------------*/
5757 /* AccAXLsh - left shift a:x by known count (0..7) */
5758 /*-----------------------------------------------------------------*/
5760 AccAXLsh (char *x, int shCount)
5775 case 5: // AAAAABBB:CCCCCDDD
5777 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5779 emitcode ("anl", "a,#0x%02x",
5780 SLMask[shCount]); // BBB00000:CCCCCDDD
5782 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5784 AccRol (shCount); // DDDCCCCC:BBB00000
5786 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5788 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5790 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5792 emitcode ("anl", "a,#0x%02x",
5793 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5795 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5797 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5800 case 6: // AAAAAABB:CCCCCCDD
5801 emitcode ("anl", "a,#0x%02x",
5802 SRMask[shCount]); // 000000BB:CCCCCCDD
5803 emitcode ("mov", "c,acc.0"); // c = B
5804 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5806 AccAXRrl1 (x); // BCCCCCCD:D000000B
5807 AccAXRrl1 (x); // BBCCCCCC:DD000000
5809 emitcode("rrc","a");
5810 emitcode("xch","a,%s", x);
5811 emitcode("rrc","a");
5812 emitcode("mov","c,acc.0"); //<< get correct bit
5813 emitcode("xch","a,%s", x);
5815 emitcode("rrc","a");
5816 emitcode("xch","a,%s", x);
5817 emitcode("rrc","a");
5818 emitcode("xch","a,%s", x);
5821 case 7: // a:x <<= 7
5823 emitcode ("anl", "a,#0x%02x",
5824 SRMask[shCount]); // 0000000B:CCCCCCCD
5826 emitcode ("mov", "c,acc.0"); // c = B
5828 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5830 AccAXRrl1 (x); // BCCCCCCC:D0000000
5838 /*-----------------------------------------------------------------*/
5839 /* AccAXRsh - right shift a:x known count (0..7) */
5840 /*-----------------------------------------------------------------*/
5842 AccAXRsh (char *x, int shCount)
5850 AccAXRrl1 (x); // 0->a:x
5855 AccAXRrl1 (x); // 0->a:x
5858 AccAXRrl1 (x); // 0->a:x
5863 case 5: // AAAAABBB:CCCCCDDD = a:x
5865 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5867 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5869 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5871 emitcode ("anl", "a,#0x%02x",
5872 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5874 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5876 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5878 emitcode ("anl", "a,#0x%02x",
5879 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5881 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5883 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5885 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5888 case 6: // AABBBBBB:CCDDDDDD
5890 emitcode ("mov", "c,acc.7");
5891 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5893 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5895 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5897 emitcode ("anl", "a,#0x%02x",
5898 SRMask[shCount]); // 000000AA:BBBBBBCC
5901 case 7: // ABBBBBBB:CDDDDDDD
5903 emitcode ("mov", "c,acc.7"); // c = A
5905 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5907 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5909 emitcode ("anl", "a,#0x%02x",
5910 SRMask[shCount]); // 0000000A:BBBBBBBC
5918 /*-----------------------------------------------------------------*/
5919 /* AccAXRshS - right shift signed a:x known count (0..7) */
5920 /*-----------------------------------------------------------------*/
5922 AccAXRshS (char *x, int shCount)
5930 emitcode ("mov", "c,acc.7");
5931 AccAXRrl1 (x); // s->a:x
5935 emitcode ("mov", "c,acc.7");
5936 AccAXRrl1 (x); // s->a:x
5938 emitcode ("mov", "c,acc.7");
5939 AccAXRrl1 (x); // s->a:x
5944 case 5: // AAAAABBB:CCCCCDDD = a:x
5946 tlbl = newiTempLabel (NULL);
5947 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5949 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5951 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5953 emitcode ("anl", "a,#0x%02x",
5954 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5956 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5958 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5960 emitcode ("anl", "a,#0x%02x",
5961 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5963 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5965 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5967 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5969 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5970 emitcode ("orl", "a,#0x%02x",
5971 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5973 emitcode ("", "%05d$:", tlbl->key + 100);
5974 break; // SSSSAAAA:BBBCCCCC
5976 case 6: // AABBBBBB:CCDDDDDD
5978 tlbl = newiTempLabel (NULL);
5979 emitcode ("mov", "c,acc.7");
5980 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5982 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5984 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5986 emitcode ("anl", "a,#0x%02x",
5987 SRMask[shCount]); // 000000AA:BBBBBBCC
5989 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5990 emitcode ("orl", "a,#0x%02x",
5991 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5993 emitcode ("", "%05d$:", tlbl->key + 100);
5995 case 7: // ABBBBBBB:CDDDDDDD
5997 tlbl = newiTempLabel (NULL);
5998 emitcode ("mov", "c,acc.7"); // c = A
6000 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6002 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6004 emitcode ("anl", "a,#0x%02x",
6005 SRMask[shCount]); // 0000000A:BBBBBBBC
6007 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6008 emitcode ("orl", "a,#0x%02x",
6009 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6011 emitcode ("", "%05d$:", tlbl->key + 100);
6018 /*-----------------------------------------------------------------*/
6019 /* shiftL2Left2Result - shift left two bytes from left to result */
6020 /*-----------------------------------------------------------------*/
6022 shiftL2Left2Result (operand * left, int offl,
6023 operand * result, int offr, int shCount)
6025 if (sameRegs (AOP (result), AOP (left)) &&
6026 ((offl + MSB16) == offr))
6028 /* don't crash result[offr] */
6029 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6030 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6034 movLeft2Result (left, offl, result, offr, 0);
6035 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6037 /* ax << shCount (x = lsb(result)) */
6038 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6039 aopPut (AOP (result), "a", offr + MSB16);
6043 /*-----------------------------------------------------------------*/
6044 /* shiftR2Left2Result - shift right two bytes from left to result */
6045 /*-----------------------------------------------------------------*/
6047 shiftR2Left2Result (operand * left, int offl,
6048 operand * result, int offr,
6049 int shCount, int sign)
6051 if (sameRegs (AOP (result), AOP (left)) &&
6052 ((offl + MSB16) == offr))
6054 /* don't crash result[offr] */
6055 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6056 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6060 movLeft2Result (left, offl, result, offr, 0);
6061 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6063 /* a:x >> shCount (x = lsb(result)) */
6065 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6067 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6068 if (getDataSize (result) > 1)
6069 aopPut (AOP (result), "a", offr + MSB16);
6072 /*-----------------------------------------------------------------*/
6073 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6074 /*-----------------------------------------------------------------*/
6076 shiftLLeftOrResult (operand * left, int offl,
6077 operand * result, int offr, int shCount)
6079 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6080 /* shift left accumulator */
6082 /* or with result */
6083 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6084 /* back to result */
6085 aopPut (AOP (result), "a", offr);
6088 /*-----------------------------------------------------------------*/
6089 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6090 /*-----------------------------------------------------------------*/
6092 shiftRLeftOrResult (operand * left, int offl,
6093 operand * result, int offr, int shCount)
6095 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6096 /* shift right accumulator */
6098 /* or with result */
6099 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6100 /* back to result */
6101 aopPut (AOP (result), "a", offr);
6104 /*-----------------------------------------------------------------*/
6105 /* genlshOne - left shift a one byte quantity by known count */
6106 /*-----------------------------------------------------------------*/
6108 genlshOne (operand * result, operand * left, int shCount)
6110 D(emitcode (";", "genlshOne"));
6112 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6115 /*-----------------------------------------------------------------*/
6116 /* genlshTwo - left shift two bytes by known amount != 0 */
6117 /*-----------------------------------------------------------------*/
6119 genlshTwo (operand * result, operand * left, int shCount)
6123 D(emitcode (";", "genlshTwo"));
6125 size = getDataSize (result);
6127 /* if shCount >= 8 */
6135 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6137 movLeft2Result (left, LSB, result, MSB16, 0);
6139 aopPut (AOP (result), zero, LSB);
6142 /* 1 <= shCount <= 7 */
6146 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6148 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6152 /*-----------------------------------------------------------------*/
6153 /* shiftLLong - shift left one long from left to result */
6154 /* offl = LSB or MSB16 */
6155 /*-----------------------------------------------------------------*/
6157 shiftLLong (operand * left, operand * result, int offr)
6160 int size = AOP_SIZE (result);
6162 if (size >= LSB + offr)
6164 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6166 emitcode ("add", "a,acc");
6167 if (sameRegs (AOP (left), AOP (result)) &&
6168 size >= MSB16 + offr && offr != LSB)
6169 emitcode ("xch", "a,%s",
6170 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6172 aopPut (AOP (result), "a", LSB + offr);
6175 if (size >= MSB16 + offr)
6177 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6179 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6182 emitcode ("rlc", "a");
6183 if (sameRegs (AOP (left), AOP (result)) &&
6184 size >= MSB24 + offr && offr != LSB)
6185 emitcode ("xch", "a,%s",
6186 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6188 aopPut (AOP (result), "a", MSB16 + offr);
6191 if (size >= MSB24 + offr)
6193 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6195 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6198 emitcode ("rlc", "a");
6199 if (sameRegs (AOP (left), AOP (result)) &&
6200 size >= MSB32 + offr && offr != LSB)
6201 emitcode ("xch", "a,%s",
6202 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6204 aopPut (AOP (result), "a", MSB24 + offr);
6207 if (size > MSB32 + offr)
6209 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6211 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6214 emitcode ("rlc", "a");
6215 aopPut (AOP (result), "a", MSB32 + offr);
6218 aopPut (AOP (result), zero, LSB);
6221 /*-----------------------------------------------------------------*/
6222 /* genlshFour - shift four byte by a known amount != 0 */
6223 /*-----------------------------------------------------------------*/
6225 genlshFour (operand * result, operand * left, int shCount)
6229 D(emitcode (";", "genlshFour"));
6231 size = AOP_SIZE (result);
6233 /* if shifting more that 3 bytes */
6238 /* lowest order of left goes to the highest
6239 order of the destination */
6240 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6242 movLeft2Result (left, LSB, result, MSB32, 0);
6243 aopPut (AOP (result), zero, LSB);
6244 aopPut (AOP (result), zero, MSB16);
6245 aopPut (AOP (result), zero, MSB24);
6249 /* more than two bytes */
6250 else if (shCount >= 16)
6252 /* lower order two bytes goes to higher order two bytes */
6254 /* if some more remaining */
6256 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6259 movLeft2Result (left, MSB16, result, MSB32, 0);
6260 movLeft2Result (left, LSB, result, MSB24, 0);
6262 aopPut (AOP (result), zero, MSB16);
6263 aopPut (AOP (result), zero, LSB);
6267 /* if more than 1 byte */
6268 else if (shCount >= 8)
6270 /* lower order three bytes goes to higher order three bytes */
6275 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6277 movLeft2Result (left, LSB, result, MSB16, 0);
6283 movLeft2Result (left, MSB24, result, MSB32, 0);
6284 movLeft2Result (left, MSB16, result, MSB24, 0);
6285 movLeft2Result (left, LSB, result, MSB16, 0);
6286 aopPut (AOP (result), zero, LSB);
6288 else if (shCount == 1)
6289 shiftLLong (left, result, MSB16);
6292 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6293 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6294 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6295 aopPut (AOP (result), zero, LSB);
6300 /* 1 <= shCount <= 7 */
6301 else if (shCount <= 2)
6303 shiftLLong (left, result, LSB);
6305 shiftLLong (result, result, LSB);
6307 /* 3 <= shCount <= 7, optimize */
6310 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6311 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6312 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6316 /*-----------------------------------------------------------------*/
6317 /* genLeftShiftLiteral - left shifting by known count */
6318 /*-----------------------------------------------------------------*/
6320 genLeftShiftLiteral (operand * left,
6325 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6328 D(emitcode (";", "genLeftShiftLiteral"));
6330 freeAsmop (right, NULL, ic, TRUE);
6332 aopOp (left, ic, FALSE);
6333 aopOp (result, ic, FALSE);
6335 size = getSize (operandType (result));
6338 emitcode ("; shift left ", "result %d, left %d", size,
6342 /* I suppose that the left size >= result size */
6347 movLeft2Result (left, size, result, size, 0);
6351 else if (shCount >= (size * 8))
6353 aopPut (AOP (result), zero, size);
6359 genlshOne (result, left, shCount);
6363 genlshTwo (result, left, shCount);
6367 genlshFour (result, left, shCount);
6370 fprintf(stderr, "*** ack! mystery literal shift!\n");
6374 freeAsmop (left, NULL, ic, TRUE);
6375 freeAsmop (result, NULL, ic, TRUE);
6378 /*-----------------------------------------------------------------*/
6379 /* genLeftShift - generates code for left shifting */
6380 /*-----------------------------------------------------------------*/
6382 genLeftShift (iCode * ic)
6384 operand *left, *right, *result;
6387 symbol *tlbl, *tlbl1;
6389 D(emitcode (";", "genLeftShift"));
6391 right = IC_RIGHT (ic);
6392 left = IC_LEFT (ic);
6393 result = IC_RESULT (ic);
6395 aopOp (right, ic, FALSE);
6397 /* if the shift count is known then do it
6398 as efficiently as possible */
6399 if (AOP_TYPE (right) == AOP_LIT)
6401 genLeftShiftLiteral (left, right, result, ic);
6405 /* shift count is unknown then we have to form
6406 a loop get the loop count in B : Note: we take
6407 only the lower order byte since shifting
6408 more that 32 bits make no sense anyway, ( the
6409 largest size of an object can be only 32 bits ) */
6411 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6412 emitcode ("inc", "b");
6413 freeAsmop (right, NULL, ic, TRUE);
6414 aopOp (left, ic, FALSE);
6415 aopOp (result, ic, FALSE);
6417 /* now move the left to the result if they are not the
6419 if (!sameRegs (AOP (left), AOP (result)) &&
6420 AOP_SIZE (result) > 1)
6423 size = AOP_SIZE (result);
6427 l = aopGet (AOP (left), offset, FALSE, TRUE);
6428 if (*l == '@' && (IS_AOP_PREG (result)))
6431 emitcode ("mov", "a,%s", l);
6432 aopPut (AOP (result), "a", offset);
6435 aopPut (AOP (result), l, offset);
6440 tlbl = newiTempLabel (NULL);
6441 size = AOP_SIZE (result);
6443 tlbl1 = newiTempLabel (NULL);
6445 /* if it is only one byte then */
6448 symbol *tlbl1 = newiTempLabel (NULL);
6450 l = aopGet (AOP (left), 0, FALSE, FALSE);
6452 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6453 emitcode ("", "%05d$:", tlbl->key + 100);
6454 emitcode ("add", "a,acc");
6455 emitcode ("", "%05d$:", tlbl1->key + 100);
6456 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6457 aopPut (AOP (result), "a", 0);
6461 reAdjustPreg (AOP (result));
6463 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6464 emitcode ("", "%05d$:", tlbl->key + 100);
6465 l = aopGet (AOP (result), offset, FALSE, FALSE);
6467 emitcode ("add", "a,acc");
6468 aopPut (AOP (result), "a", offset++);
6471 l = aopGet (AOP (result), offset, FALSE, FALSE);
6473 emitcode ("rlc", "a");
6474 aopPut (AOP (result), "a", offset++);
6476 reAdjustPreg (AOP (result));
6478 emitcode ("", "%05d$:", tlbl1->key + 100);
6479 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6481 freeAsmop (left, NULL, ic, TRUE);
6482 freeAsmop (result, NULL, ic, TRUE);
6485 /*-----------------------------------------------------------------*/
6486 /* genrshOne - right shift a one byte quantity by known count */
6487 /*-----------------------------------------------------------------*/
6489 genrshOne (operand * result, operand * left,
6490 int shCount, int sign)
6492 D(emitcode (";", "genrshOne"));
6494 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6497 /*-----------------------------------------------------------------*/
6498 /* genrshTwo - right shift two bytes by known amount != 0 */
6499 /*-----------------------------------------------------------------*/
6501 genrshTwo (operand * result, operand * left,
6502 int shCount, int sign)
6504 D(emitcode (";", "genrshTwo"));
6506 /* if shCount >= 8 */
6511 shiftR1Left2Result (left, MSB16, result, LSB,
6514 movLeft2Result (left, MSB16, result, LSB, sign);
6515 addSign (result, MSB16, sign);
6518 /* 1 <= shCount <= 7 */
6520 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6523 /*-----------------------------------------------------------------*/
6524 /* shiftRLong - shift right one long from left to result */
6525 /* offl = LSB or MSB16 */
6526 /*-----------------------------------------------------------------*/
6528 shiftRLong (operand * left, int offl,
6529 operand * result, int sign)
6531 int isSameRegs=sameRegs(AOP(left),AOP(result));
6533 if (isSameRegs && offl>1) {
6534 // we are in big trouble, but this shouldn't happen
6535 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6538 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6543 emitcode ("rlc", "a");
6544 emitcode ("subb", "a,acc");
6545 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6547 aopPut (AOP(result), zero, MSB32);
6552 emitcode ("clr", "c");
6554 emitcode ("mov", "c,acc.7");
6557 emitcode ("rrc", "a");
6559 if (isSameRegs && offl==MSB16) {
6560 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6562 aopPut (AOP (result), "a", MSB32);
6563 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6566 emitcode ("rrc", "a");
6567 if (isSameRegs && offl==1) {
6568 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6570 aopPut (AOP (result), "a", MSB24);
6571 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6573 emitcode ("rrc", "a");
6574 aopPut (AOP (result), "a", MSB16 - offl);
6578 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6579 emitcode ("rrc", "a");
6580 aopPut (AOP (result), "a", LSB);
6584 /*-----------------------------------------------------------------*/
6585 /* genrshFour - shift four byte by a known amount != 0 */
6586 /*-----------------------------------------------------------------*/
6588 genrshFour (operand * result, operand * left,
6589 int shCount, int sign)
6591 D(emitcode (";", "genrshFour"));
6593 /* if shifting more that 3 bytes */
6598 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6600 movLeft2Result (left, MSB32, result, LSB, sign);
6601 addSign (result, MSB16, sign);
6603 else if (shCount >= 16)
6607 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6610 movLeft2Result (left, MSB24, result, LSB, 0);
6611 movLeft2Result (left, MSB32, result, MSB16, sign);
6613 addSign (result, MSB24, sign);
6615 else if (shCount >= 8)
6619 shiftRLong (left, MSB16, result, sign);
6620 else if (shCount == 0)
6622 movLeft2Result (left, MSB16, result, LSB, 0);
6623 movLeft2Result (left, MSB24, result, MSB16, 0);
6624 movLeft2Result (left, MSB32, result, MSB24, sign);
6625 addSign (result, MSB32, sign);
6629 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6630 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6631 /* the last shift is signed */
6632 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6633 addSign (result, MSB32, sign);
6637 { /* 1 <= shCount <= 7 */
6640 shiftRLong (left, LSB, result, sign);
6642 shiftRLong (result, LSB, result, sign);
6646 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6647 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6648 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6653 /*-----------------------------------------------------------------*/
6654 /* genRightShiftLiteral - right shifting by known count */
6655 /*-----------------------------------------------------------------*/
6657 genRightShiftLiteral (operand * left,
6663 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6666 D(emitcode (";", "genRightShiftLiteral"));
6668 freeAsmop (right, NULL, ic, TRUE);
6670 aopOp (left, ic, FALSE);
6671 aopOp (result, ic, FALSE);
6674 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6678 size = getDataSize (left);
6679 /* test the LEFT size !!! */
6681 /* I suppose that the left size >= result size */
6684 size = getDataSize (result);
6686 movLeft2Result (left, size, result, size, 0);
6689 else if (shCount >= (size * 8))
6692 /* get sign in acc.7 */
6693 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6694 addSign (result, LSB, sign);
6701 genrshOne (result, left, shCount, sign);
6705 genrshTwo (result, left, shCount, sign);
6709 genrshFour (result, left, shCount, sign);
6715 freeAsmop (left, NULL, ic, TRUE);
6716 freeAsmop (result, NULL, ic, TRUE);
6720 /*-----------------------------------------------------------------*/
6721 /* genSignedRightShift - right shift of signed number */
6722 /*-----------------------------------------------------------------*/
6724 genSignedRightShift (iCode * ic)
6726 operand *right, *left, *result;
6729 symbol *tlbl, *tlbl1;
6731 D(emitcode (";", "genSignedRightShift"));
6733 /* we do it the hard way put the shift count in b
6734 and loop thru preserving the sign */
6736 right = IC_RIGHT (ic);
6737 left = IC_LEFT (ic);
6738 result = IC_RESULT (ic);
6740 aopOp (right, ic, FALSE);
6743 if (AOP_TYPE (right) == AOP_LIT)
6745 genRightShiftLiteral (left, right, result, ic, 1);
6748 /* shift count is unknown then we have to form
6749 a loop get the loop count in B : Note: we take
6750 only the lower order byte since shifting
6751 more that 32 bits make no sense anyway, ( the
6752 largest size of an object can be only 32 bits ) */
6754 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6755 emitcode ("inc", "b");
6756 freeAsmop (right, NULL, ic, TRUE);
6757 aopOp (left, ic, FALSE);
6758 aopOp (result, ic, FALSE);
6760 /* now move the left to the result if they are not the
6762 if (!sameRegs (AOP (left), AOP (result)) &&
6763 AOP_SIZE (result) > 1)
6766 size = AOP_SIZE (result);
6770 l = aopGet (AOP (left), offset, FALSE, TRUE);
6771 if (*l == '@' && IS_AOP_PREG (result))
6774 emitcode ("mov", "a,%s", l);
6775 aopPut (AOP (result), "a", offset);
6778 aopPut (AOP (result), l, offset);
6783 /* mov the highest order bit to OVR */
6784 tlbl = newiTempLabel (NULL);
6785 tlbl1 = newiTempLabel (NULL);
6787 size = AOP_SIZE (result);
6789 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6790 emitcode ("rlc", "a");
6791 emitcode ("mov", "ov,c");
6792 /* if it is only one byte then */
6795 l = aopGet (AOP (left), 0, FALSE, FALSE);
6797 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6798 emitcode ("", "%05d$:", tlbl->key + 100);
6799 emitcode ("mov", "c,ov");
6800 emitcode ("rrc", "a");
6801 emitcode ("", "%05d$:", tlbl1->key + 100);
6802 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6803 aopPut (AOP (result), "a", 0);
6807 reAdjustPreg (AOP (result));
6808 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6809 emitcode ("", "%05d$:", tlbl->key + 100);
6810 emitcode ("mov", "c,ov");
6813 l = aopGet (AOP (result), offset, FALSE, FALSE);
6815 emitcode ("rrc", "a");
6816 aopPut (AOP (result), "a", offset--);
6818 reAdjustPreg (AOP (result));
6819 emitcode ("", "%05d$:", tlbl1->key + 100);
6820 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6823 freeAsmop (left, NULL, ic, TRUE);
6824 freeAsmop (result, NULL, ic, TRUE);
6827 /*-----------------------------------------------------------------*/
6828 /* genRightShift - generate code for right shifting */
6829 /*-----------------------------------------------------------------*/
6831 genRightShift (iCode * ic)
6833 operand *right, *left, *result;
6837 symbol *tlbl, *tlbl1;
6839 D(emitcode (";", "genRightShift"));
6841 /* if signed then we do it the hard way preserve the
6842 sign bit moving it inwards */
6843 retype = getSpec (operandType (IC_RESULT (ic)));
6845 if (!SPEC_USIGN (retype))
6847 genSignedRightShift (ic);
6851 /* signed & unsigned types are treated the same : i.e. the
6852 signed is NOT propagated inwards : quoting from the
6853 ANSI - standard : "for E1 >> E2, is equivalent to division
6854 by 2**E2 if unsigned or if it has a non-negative value,
6855 otherwise the result is implementation defined ", MY definition
6856 is that the sign does not get propagated */
6858 right = IC_RIGHT (ic);
6859 left = IC_LEFT (ic);
6860 result = IC_RESULT (ic);
6862 aopOp (right, ic, FALSE);
6864 /* if the shift count is known then do it
6865 as efficiently as possible */
6866 if (AOP_TYPE (right) == AOP_LIT)
6868 genRightShiftLiteral (left, right, result, ic, 0);
6872 /* shift count is unknown then we have to form
6873 a loop get the loop count in B : Note: we take
6874 only the lower order byte since shifting
6875 more that 32 bits make no sense anyway, ( the
6876 largest size of an object can be only 32 bits ) */
6878 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6879 emitcode ("inc", "b");
6880 freeAsmop (right, NULL, ic, TRUE);
6881 aopOp (left, ic, FALSE);
6882 aopOp (result, ic, FALSE);
6884 /* now move the left to the result if they are not the
6886 if (!sameRegs (AOP (left), AOP (result)) &&
6887 AOP_SIZE (result) > 1)
6890 size = AOP_SIZE (result);
6894 l = aopGet (AOP (left), offset, FALSE, TRUE);
6895 if (*l == '@' && IS_AOP_PREG (result))
6898 emitcode ("mov", "a,%s", l);
6899 aopPut (AOP (result), "a", offset);
6902 aopPut (AOP (result), l, offset);
6907 tlbl = newiTempLabel (NULL);
6908 tlbl1 = newiTempLabel (NULL);
6909 size = AOP_SIZE (result);
6912 /* if it is only one byte then */
6915 l = aopGet (AOP (left), 0, FALSE, FALSE);
6917 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6918 emitcode ("", "%05d$:", tlbl->key + 100);
6920 emitcode ("rrc", "a");
6921 emitcode ("", "%05d$:", tlbl1->key + 100);
6922 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6923 aopPut (AOP (result), "a", 0);
6927 reAdjustPreg (AOP (result));
6928 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6929 emitcode ("", "%05d$:", tlbl->key + 100);
6933 l = aopGet (AOP (result), offset, FALSE, FALSE);
6935 emitcode ("rrc", "a");
6936 aopPut (AOP (result), "a", offset--);
6938 reAdjustPreg (AOP (result));
6940 emitcode ("", "%05d$:", tlbl1->key + 100);
6941 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6944 freeAsmop (left, NULL, ic, TRUE);
6945 freeAsmop (result, NULL, ic, TRUE);
6948 /*-----------------------------------------------------------------*/
6949 /* genUnpackBits - generates code for unpacking bits */
6950 /*-----------------------------------------------------------------*/
6952 genUnpackBits (operand * result, char *rname, int ptype)
6960 D(emitcode (";", "genUnpackBits"));
6962 etype = getSpec (operandType (result));
6963 rsize = getSize (operandType (result));
6964 /* read the first byte */
6970 emitcode ("mov", "a,@%s", rname);
6974 emitcode ("movx", "a,@%s", rname);
6978 emitcode ("movx", "a,@dptr");
6982 emitcode ("clr", "a");
6983 emitcode ("movc", "a,@a+dptr");
6987 emitcode ("lcall", "__gptrget");
6991 rlen = SPEC_BLEN (etype);
6993 /* if we have bitdisplacement then it fits */
6994 /* into this byte completely or if length is */
6995 /* less than a byte */
6996 if ((shCnt = SPEC_BSTR (etype)) ||
6997 (SPEC_BLEN (etype) <= 8))
7000 /* shift right acc */
7003 emitcode ("anl", "a,#0x%02x",
7004 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7005 aopPut (AOP (result), "a", offset++);
7009 /* bit field did not fit in a byte */
7010 aopPut (AOP (result), "a", offset++);
7019 emitcode ("inc", "%s", rname);
7020 emitcode ("mov", "a,@%s", rname);
7024 emitcode ("inc", "%s", rname);
7025 emitcode ("movx", "a,@%s", rname);
7029 emitcode ("inc", "dptr");
7030 emitcode ("movx", "a,@dptr");
7034 emitcode ("clr", "a");
7035 emitcode ("inc", "dptr");
7036 emitcode ("movc", "a,@a+dptr");
7040 emitcode ("inc", "dptr");
7041 emitcode ("lcall", "__gptrget");
7046 /* if we are done */
7050 aopPut (AOP (result), "a", offset++);
7056 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7058 aopPut (AOP (result), "a", offset++);
7066 aopPut (AOP (result), zero, offset++);
7072 /*-----------------------------------------------------------------*/
7073 /* genDataPointerGet - generates code when ptr offset is known */
7074 /*-----------------------------------------------------------------*/
7076 genDataPointerGet (operand * left,
7082 int size, offset = 0;
7084 D(emitcode (";", "genDataPointerGet"));
7086 aopOp (result, ic, TRUE);
7088 /* get the string representation of the name */
7089 l = aopGet (AOP (left), 0, FALSE, TRUE);
7090 size = AOP_SIZE (result);
7094 sprintf (buffer, "(%s + %d)", l + 1, offset);
7096 sprintf (buffer, "%s", l + 1);
7097 aopPut (AOP (result), buffer, offset++);
7100 freeAsmop (left, NULL, ic, TRUE);
7101 freeAsmop (result, NULL, ic, TRUE);
7104 /*-----------------------------------------------------------------*/
7105 /* genNearPointerGet - emitcode for near pointer fetch */
7106 /*-----------------------------------------------------------------*/
7108 genNearPointerGet (operand * left,
7116 sym_link *rtype, *retype;
7117 sym_link *ltype = operandType (left);
7120 D(emitcode (";", "genNearPointerGet"));
7122 rtype = operandType (result);
7123 retype = getSpec (rtype);
7125 aopOp (left, ic, FALSE);
7127 /* if left is rematerialisable and
7128 result is not bit variable type and
7129 the left is pointer to data space i.e
7130 lower 128 bytes of space */
7131 if (AOP_TYPE (left) == AOP_IMMD &&
7132 !IS_BITVAR (retype) &&
7133 DCL_TYPE (ltype) == POINTER)
7135 genDataPointerGet (left, result, ic);
7139 /* if the value is already in a pointer register
7140 then don't need anything more */
7141 if (!AOP_INPREG (AOP (left)))
7143 /* otherwise get a free pointer register */
7145 preg = getFreePtr (ic, &aop, FALSE);
7146 emitcode ("mov", "%s,%s",
7148 aopGet (AOP (left), 0, FALSE, TRUE));
7152 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7154 //aopOp (result, ic, FALSE);
7155 aopOp (result, ic, result?TRUE:FALSE);
7157 /* if bitfield then unpack the bits */
7158 if (IS_BITVAR (retype))
7159 genUnpackBits (result, rname, POINTER);
7162 /* we have can just get the values */
7163 int size = AOP_SIZE (result);
7168 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7171 emitcode ("mov", "a,@%s", rname);
7172 aopPut (AOP (result), "a", offset);
7176 sprintf (buffer, "@%s", rname);
7177 aopPut (AOP (result), buffer, offset);
7181 emitcode ("inc", "%s", rname);
7185 /* now some housekeeping stuff */
7186 if (aop) /* we had to allocate for this iCode */
7188 if (pi) { /* post increment present */
7189 aopPut(AOP ( left ),rname,0);
7191 freeAsmop (NULL, aop, ic, TRUE);
7195 /* we did not allocate which means left
7196 already in a pointer register, then
7197 if size > 0 && this could be used again
7198 we have to point it back to where it
7200 if ((AOP_SIZE (result) > 1 &&
7201 !OP_SYMBOL (left)->remat &&
7202 (OP_SYMBOL (left)->liveTo > ic->seq ||
7206 int size = AOP_SIZE (result) - 1;
7208 emitcode ("dec", "%s", rname);
7213 freeAsmop (left, NULL, ic, TRUE);
7214 freeAsmop (result, NULL, ic, TRUE);
7215 if (pi) pi->generated = 1;
7218 /*-----------------------------------------------------------------*/
7219 /* genPagedPointerGet - emitcode for paged pointer fetch */
7220 /*-----------------------------------------------------------------*/
7222 genPagedPointerGet (operand * left,
7230 sym_link *rtype, *retype;
7232 D(emitcode (";", "genPagedPointerGet"));
7234 rtype = operandType (result);
7235 retype = getSpec (rtype);
7237 aopOp (left, ic, FALSE);
7239 /* if the value is already in a pointer register
7240 then don't need anything more */
7241 if (!AOP_INPREG (AOP (left)))
7243 /* otherwise get a free pointer register */
7245 preg = getFreePtr (ic, &aop, FALSE);
7246 emitcode ("mov", "%s,%s",
7248 aopGet (AOP (left), 0, FALSE, TRUE));
7252 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7254 aopOp (result, ic, FALSE);
7256 /* if bitfield then unpack the bits */
7257 if (IS_BITVAR (retype))
7258 genUnpackBits (result, rname, PPOINTER);
7261 /* we have can just get the values */
7262 int size = AOP_SIZE (result);
7268 emitcode ("movx", "a,@%s", rname);
7269 aopPut (AOP (result), "a", offset);
7274 emitcode ("inc", "%s", rname);
7278 /* now some housekeeping stuff */
7279 if (aop) /* we had to allocate for this iCode */
7281 if (pi) aopPut ( AOP (left), rname, 0);
7282 freeAsmop (NULL, aop, ic, TRUE);
7286 /* we did not allocate which means left
7287 already in a pointer register, then
7288 if size > 0 && this could be used again
7289 we have to point it back to where it
7291 if ((AOP_SIZE (result) > 1 &&
7292 !OP_SYMBOL (left)->remat &&
7293 (OP_SYMBOL (left)->liveTo > ic->seq ||
7297 int size = AOP_SIZE (result) - 1;
7299 emitcode ("dec", "%s", rname);
7304 freeAsmop (left, NULL, ic, TRUE);
7305 freeAsmop (result, NULL, ic, TRUE);
7306 if (pi) pi->generated = 1;
7310 /*-----------------------------------------------------------------*/
7311 /* genFarPointerGet - gget value from far space */
7312 /*-----------------------------------------------------------------*/
7314 genFarPointerGet (operand * left,
7315 operand * result, iCode * ic, iCode * pi)
7318 sym_link *retype = getSpec (operandType (result));
7320 D(emitcode (";", "genFarPointerGet"));
7322 aopOp (left, ic, FALSE);
7324 /* if the operand is already in dptr
7325 then we do nothing else we move the value to dptr */
7326 if (AOP_TYPE (left) != AOP_STR)
7328 /* if this is remateriazable */
7329 if (AOP_TYPE (left) == AOP_IMMD)
7330 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7332 { /* we need to get it byte by byte */
7333 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7334 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7337 /* so dptr know contains the address */
7338 aopOp (result, ic, FALSE);
7340 /* if bit then unpack */
7341 if (IS_BITVAR (retype))
7342 genUnpackBits (result, "dptr", FPOINTER);
7345 size = AOP_SIZE (result);
7350 emitcode ("movx", "a,@dptr");
7351 aopPut (AOP (result), "a", offset++);
7353 emitcode ("inc", "dptr");
7357 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7358 aopPut ( AOP (left), "dpl", 0);
7359 aopPut ( AOP (left), "dph", 1);
7362 freeAsmop (left, NULL, ic, TRUE);
7363 freeAsmop (result, NULL, ic, TRUE);
7366 /*-----------------------------------------------------------------*/
7367 /* genCodePointerGet - gget value from code space */
7368 /*-----------------------------------------------------------------*/
7370 genCodePointerGet (operand * left,
7371 operand * result, iCode * ic, iCode *pi)
7374 sym_link *retype = getSpec (operandType (result));
7376 D(emitcode (";", "genCodePointerGet"));
7378 aopOp (left, ic, FALSE);
7380 /* if the operand is already in dptr
7381 then we do nothing else we move the value to dptr */
7382 if (AOP_TYPE (left) != AOP_STR)
7384 /* if this is remateriazable */
7385 if (AOP_TYPE (left) == AOP_IMMD)
7386 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7388 { /* we need to get it byte by byte */
7389 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7390 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7393 /* so dptr know contains the address */
7394 aopOp (result, ic, FALSE);
7396 /* if bit then unpack */
7397 if (IS_BITVAR (retype))
7398 genUnpackBits (result, "dptr", CPOINTER);
7401 size = AOP_SIZE (result);
7406 emitcode ("clr", "a");
7407 emitcode ("movc", "a,@a+dptr");
7408 aopPut (AOP (result), "a", offset++);
7410 emitcode ("inc", "dptr");
7414 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7415 aopPut ( AOP (left), "dpl", 0);
7416 aopPut ( AOP (left), "dph", 1);
7419 freeAsmop (left, NULL, ic, TRUE);
7420 freeAsmop (result, NULL, ic, TRUE);
7423 /*-----------------------------------------------------------------*/
7424 /* genGenPointerGet - gget value from generic pointer space */
7425 /*-----------------------------------------------------------------*/
7427 genGenPointerGet (operand * left,
7428 operand * result, iCode * ic, iCode *pi)
7431 sym_link *retype = getSpec (operandType (result));
7433 D(emitcode (";", "genGenPointerGet"));
7435 aopOp (left, ic, FALSE);
7437 /* if the operand is already in dptr
7438 then we do nothing else we move the value to dptr */
7439 if (AOP_TYPE (left) != AOP_STR)
7441 /* if this is remateriazable */
7442 if (AOP_TYPE (left) == AOP_IMMD)
7444 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7445 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7446 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7448 emitcode ("mov", "b,#%d", pointerCode (retype));
7451 { /* we need to get it byte by byte */
7452 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7453 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7454 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7457 /* so dptr know contains the address */
7458 aopOp (result, ic, FALSE);
7460 /* if bit then unpack */
7461 if (IS_BITVAR (retype))
7462 genUnpackBits (result, "dptr", GPOINTER);
7465 size = AOP_SIZE (result);
7470 emitcode ("lcall", "__gptrget");
7471 aopPut (AOP (result), "a", offset++);
7473 emitcode ("inc", "dptr");
7477 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7478 aopPut ( AOP (left), "dpl", 0);
7479 aopPut ( AOP (left), "dph", 1);
7480 aopPut ( AOP (left), "b", 2);
7483 freeAsmop (left, NULL, ic, TRUE);
7484 freeAsmop (result, NULL, ic, TRUE);
7487 /*-----------------------------------------------------------------*/
7488 /* genPointerGet - generate code for pointer get */
7489 /*-----------------------------------------------------------------*/
7491 genPointerGet (iCode * ic, iCode *pi)
7493 operand *left, *result;
7494 sym_link *type, *etype;
7497 D(emitcode (";", "genPointerGet"));
7499 left = IC_LEFT (ic);
7500 result = IC_RESULT (ic);
7502 /* depending on the type of pointer we need to
7503 move it to the correct pointer register */
7504 type = operandType (left);
7505 etype = getSpec (type);
7506 /* if left is of type of pointer then it is simple */
7507 if (IS_PTR (type) && !IS_FUNC (type->next))
7508 p_type = DCL_TYPE (type);
7511 /* we have to go by the storage class */
7512 p_type = PTR_TYPE (SPEC_OCLS (etype));
7515 /* special case when cast remat */
7516 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7517 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7518 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7519 type = type = operandType (left);
7520 p_type = DCL_TYPE (type);
7522 /* now that we have the pointer type we assign
7523 the pointer values */
7529 genNearPointerGet (left, result, ic, pi);
7533 genPagedPointerGet (left, result, ic, pi);
7537 genFarPointerGet (left, result, ic, pi);
7541 genCodePointerGet (left, result, ic, pi);
7545 genGenPointerGet (left, result, ic, pi);
7551 /*-----------------------------------------------------------------*/
7552 /* genPackBits - generates code for packed bit storage */
7553 /*-----------------------------------------------------------------*/
7555 genPackBits (sym_link * etype,
7557 char *rname, int p_type)
7565 D(emitcode (";", "genPackBits"));
7567 blen = SPEC_BLEN (etype);
7568 bstr = SPEC_BSTR (etype);
7570 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7573 /* if the bit lenth is less than or */
7574 /* it exactly fits a byte then */
7575 if (SPEC_BLEN (etype) <= 8)
7577 shCount = SPEC_BSTR (etype);
7579 /* shift left acc */
7582 if (SPEC_BLEN (etype) < 8)
7583 { /* if smaller than a byte */
7589 emitcode ("mov", "b,a");
7590 emitcode ("mov", "a,@%s", rname);
7594 emitcode ("mov", "b,a");
7595 emitcode ("movx", "a,@dptr");
7599 emitcode ("push", "b");
7600 emitcode ("push", "acc");
7601 emitcode ("lcall", "__gptrget");
7602 emitcode ("pop", "b");
7606 emitcode ("anl", "a,#0x%02x", (unsigned char)
7607 ((unsigned char) (0xFF << (blen + bstr)) |
7608 (unsigned char) (0xFF >> (8 - bstr))));
7609 emitcode ("orl", "a,b");
7610 if (p_type == GPOINTER)
7611 emitcode ("pop", "b");
7618 emitcode ("mov", "@%s,a", rname);
7622 emitcode ("movx", "@dptr,a");
7626 emitcode ("lcall", "__gptrput");
7631 if (SPEC_BLEN (etype) <= 8)
7634 emitcode ("inc", "%s", rname);
7635 rLen = SPEC_BLEN (etype);
7637 /* now generate for lengths greater than one byte */
7641 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7653 emitcode ("mov", "@%s,a", rname);
7656 emitcode ("mov", "@%s,%s", rname, l);
7661 emitcode ("movx", "@dptr,a");
7666 emitcode ("lcall", "__gptrput");
7669 emitcode ("inc", "%s", rname);
7674 /* last last was not complete */
7677 /* save the byte & read byte */
7681 emitcode ("mov", "b,a");
7682 emitcode ("mov", "a,@%s", rname);
7686 emitcode ("mov", "b,a");
7687 emitcode ("movx", "a,@dptr");
7691 emitcode ("push", "b");
7692 emitcode ("push", "acc");
7693 emitcode ("lcall", "__gptrget");
7694 emitcode ("pop", "b");
7698 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7699 emitcode ("orl", "a,b");
7702 if (p_type == GPOINTER)
7703 emitcode ("pop", "b");
7709 emitcode ("mov", "@%s,a", rname);
7713 emitcode ("movx", "@dptr,a");
7717 emitcode ("lcall", "__gptrput");
7721 /*-----------------------------------------------------------------*/
7722 /* genDataPointerSet - remat pointer to data space */
7723 /*-----------------------------------------------------------------*/
7725 genDataPointerSet (operand * right,
7729 int size, offset = 0;
7730 char *l, buffer[256];
7732 D(emitcode (";", "genDataPointerSet"));
7734 aopOp (right, ic, FALSE);
7736 l = aopGet (AOP (result), 0, FALSE, TRUE);
7737 size = AOP_SIZE (right);
7741 sprintf (buffer, "(%s + %d)", l + 1, offset);
7743 sprintf (buffer, "%s", l + 1);
7744 emitcode ("mov", "%s,%s", buffer,
7745 aopGet (AOP (right), offset++, FALSE, FALSE));
7748 freeAsmop (right, NULL, ic, TRUE);
7749 freeAsmop (result, NULL, ic, TRUE);
7752 /*-----------------------------------------------------------------*/
7753 /* genNearPointerSet - emitcode for near pointer put */
7754 /*-----------------------------------------------------------------*/
7756 genNearPointerSet (operand * right,
7764 sym_link *retype, *letype;
7765 sym_link *ptype = operandType (result);
7767 D(emitcode (";", "genNearPointerSet"));
7769 retype = getSpec (operandType (right));
7770 letype = getSpec (ptype);
7771 aopOp (result, ic, FALSE);
7773 /* if the result is rematerializable &
7774 in data space & not a bit variable */
7775 if (AOP_TYPE (result) == AOP_IMMD &&
7776 DCL_TYPE (ptype) == POINTER &&
7777 !IS_BITVAR (retype) &&
7778 !IS_BITVAR (letype))
7780 genDataPointerSet (right, result, ic);
7784 /* if the value is already in a pointer register
7785 then don't need anything more */
7786 if (!AOP_INPREG (AOP (result)))
7789 //AOP_TYPE (result) == AOP_STK
7793 // Aha, it is a pointer, just in disguise.
7794 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7797 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7798 __FILE__, __LINE__);
7803 rname++; // skip the '@'.
7808 /* otherwise get a free pointer register */
7810 preg = getFreePtr (ic, &aop, FALSE);
7811 emitcode ("mov", "%s,%s",
7813 aopGet (AOP (result), 0, FALSE, TRUE));
7819 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7822 aopOp (right, ic, FALSE);
7824 /* if bitfield then unpack the bits */
7825 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7826 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7829 /* we have can just get the values */
7830 int size = AOP_SIZE (right);
7835 l = aopGet (AOP (right), offset, FALSE, TRUE);
7839 emitcode ("mov", "@%s,a", rname);
7842 emitcode ("mov", "@%s,%s", rname, l);
7844 emitcode ("inc", "%s", rname);
7849 /* now some housekeeping stuff */
7850 if (aop) /* we had to allocate for this iCode */
7852 if (pi) aopPut (AOP (result),rname,0);
7853 freeAsmop (NULL, aop, ic, TRUE);
7857 /* we did not allocate which means left
7858 already in a pointer register, then
7859 if size > 0 && this could be used again
7860 we have to point it back to where it
7862 if ((AOP_SIZE (right) > 1 &&
7863 !OP_SYMBOL (result)->remat &&
7864 (OP_SYMBOL (result)->liveTo > ic->seq ||
7868 int size = AOP_SIZE (right) - 1;
7870 emitcode ("dec", "%s", rname);
7875 if (pi) pi->generated = 1;
7876 freeAsmop (result, NULL, ic, TRUE);
7877 freeAsmop (right, NULL, ic, TRUE);
7880 /*-----------------------------------------------------------------*/
7881 /* genPagedPointerSet - emitcode for Paged pointer put */
7882 /*-----------------------------------------------------------------*/
7884 genPagedPointerSet (operand * right,
7892 sym_link *retype, *letype;
7894 D(emitcode (";", "genPagedPointerSet"));
7896 retype = getSpec (operandType (right));
7897 letype = getSpec (operandType (result));
7899 aopOp (result, ic, FALSE);
7901 /* if the value is already in a pointer register
7902 then don't need anything more */
7903 if (!AOP_INPREG (AOP (result)))
7905 /* otherwise get a free pointer register */
7907 preg = getFreePtr (ic, &aop, FALSE);
7908 emitcode ("mov", "%s,%s",
7910 aopGet (AOP (result), 0, FALSE, TRUE));
7914 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7916 aopOp (right, ic, FALSE);
7918 /* if bitfield then unpack the bits */
7919 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7920 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7923 /* we have can just get the values */
7924 int size = AOP_SIZE (right);
7929 l = aopGet (AOP (right), offset, FALSE, TRUE);
7932 emitcode ("movx", "@%s,a", rname);
7935 emitcode ("inc", "%s", rname);
7941 /* now some housekeeping stuff */
7942 if (aop) /* we had to allocate for this iCode */
7944 if (pi) aopPut (AOP (result),rname,0);
7945 freeAsmop (NULL, aop, ic, TRUE);
7949 /* we did not allocate which means left
7950 already in a pointer register, then
7951 if size > 0 && this could be used again
7952 we have to point it back to where it
7954 if (AOP_SIZE (right) > 1 &&
7955 !OP_SYMBOL (result)->remat &&
7956 (OP_SYMBOL (result)->liveTo > ic->seq ||
7959 int size = AOP_SIZE (right) - 1;
7961 emitcode ("dec", "%s", rname);
7966 if (pi) pi->generated = 1;
7967 freeAsmop (result, NULL, ic, TRUE);
7968 freeAsmop (right, NULL, ic, TRUE);
7973 /*-----------------------------------------------------------------*/
7974 /* genFarPointerSet - set value from far space */
7975 /*-----------------------------------------------------------------*/
7977 genFarPointerSet (operand * right,
7978 operand * result, iCode * ic, iCode * pi)
7981 sym_link *retype = getSpec (operandType (right));
7982 sym_link *letype = getSpec (operandType (result));
7984 D(emitcode (";", "genFarPointerSet"));
7986 aopOp (result, ic, FALSE);
7988 /* if the operand is already in dptr
7989 then we do nothing else we move the value to dptr */
7990 if (AOP_TYPE (result) != AOP_STR)
7992 /* if this is remateriazable */
7993 if (AOP_TYPE (result) == AOP_IMMD)
7994 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7996 { /* we need to get it byte by byte */
7997 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7998 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8001 /* so dptr know contains the address */
8002 aopOp (right, ic, FALSE);
8004 /* if bit then unpack */
8005 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8006 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8009 size = AOP_SIZE (right);
8014 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8016 emitcode ("movx", "@dptr,a");
8018 emitcode ("inc", "dptr");
8021 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8022 aopPut (AOP(result),"dpl",0);
8023 aopPut (AOP(result),"dph",1);
8026 freeAsmop (result, NULL, ic, TRUE);
8027 freeAsmop (right, NULL, ic, TRUE);
8030 /*-----------------------------------------------------------------*/
8031 /* genGenPointerSet - set value from generic pointer space */
8032 /*-----------------------------------------------------------------*/
8034 genGenPointerSet (operand * right,
8035 operand * result, iCode * ic, iCode * pi)
8038 sym_link *retype = getSpec (operandType (right));
8039 sym_link *letype = getSpec (operandType (result));
8041 D(emitcode (";", "genGenPointerSet"));
8043 aopOp (result, ic, FALSE);
8045 /* if the operand is already in dptr
8046 then we do nothing else we move the value to dptr */
8047 if (AOP_TYPE (result) != AOP_STR)
8049 /* if this is remateriazable */
8050 if (AOP_TYPE (result) == AOP_IMMD)
8052 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8053 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8054 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8056 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8059 { /* we need to get it byte by byte */
8060 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8061 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8062 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8065 /* so dptr know contains the address */
8066 aopOp (right, ic, FALSE);
8068 /* if bit then unpack */
8069 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8070 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8073 size = AOP_SIZE (right);
8078 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8080 emitcode ("lcall", "__gptrput");
8082 emitcode ("inc", "dptr");
8086 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8087 aopPut (AOP(result),"dpl",0);
8088 aopPut (AOP(result),"dph",1);
8089 aopPut (AOP(result),"b",2);
8092 freeAsmop (result, NULL, ic, TRUE);
8093 freeAsmop (right, NULL, ic, TRUE);
8096 /*-----------------------------------------------------------------*/
8097 /* genPointerSet - stores the value into a pointer location */
8098 /*-----------------------------------------------------------------*/
8100 genPointerSet (iCode * ic, iCode *pi)
8102 operand *right, *result;
8103 sym_link *type, *etype;
8106 D(emitcode (";", "genPointerSet"));
8108 right = IC_RIGHT (ic);
8109 result = IC_RESULT (ic);
8111 /* depending on the type of pointer we need to
8112 move it to the correct pointer register */
8113 type = operandType (result);
8114 etype = getSpec (type);
8115 /* if left is of type of pointer then it is simple */
8116 if (IS_PTR (type) && !IS_FUNC (type->next))
8118 p_type = DCL_TYPE (type);
8122 /* we have to go by the storage class */
8123 p_type = PTR_TYPE (SPEC_OCLS (etype));
8126 /* special case when cast remat */
8127 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8128 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8129 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8130 type = type = operandType (result);
8131 p_type = DCL_TYPE (type);
8133 /* now that we have the pointer type we assign
8134 the pointer values */
8140 genNearPointerSet (right, result, ic, pi);
8144 genPagedPointerSet (right, result, ic, pi);
8148 genFarPointerSet (right, result, ic, pi);
8152 genGenPointerSet (right, result, ic, pi);
8158 /*-----------------------------------------------------------------*/
8159 /* genIfx - generate code for Ifx statement */
8160 /*-----------------------------------------------------------------*/
8162 genIfx (iCode * ic, iCode * popIc)
8164 operand *cond = IC_COND (ic);
8167 D(emitcode (";", "genIfx"));
8169 aopOp (cond, ic, FALSE);
8171 /* get the value into acc */
8172 if (AOP_TYPE (cond) != AOP_CRY)
8176 /* the result is now in the accumulator */
8177 freeAsmop (cond, NULL, ic, TRUE);
8179 /* if there was something to be popped then do it */
8183 /* if the condition is a bit variable */
8184 if (isbit && IS_ITEMP (cond) &&
8186 genIfxJump (ic, SPIL_LOC (cond)->rname);
8187 else if (isbit && !IS_ITEMP (cond))
8188 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8190 genIfxJump (ic, "a");
8195 /*-----------------------------------------------------------------*/
8196 /* genAddrOf - generates code for address of */
8197 /*-----------------------------------------------------------------*/
8199 genAddrOf (iCode * ic)
8201 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8204 D(emitcode (";", "genAddrOf"));
8206 aopOp (IC_RESULT (ic), ic, FALSE);
8208 /* if the operand is on the stack then we
8209 need to get the stack offset of this
8213 /* if it has an offset then we need to compute
8217 emitcode ("mov", "a,_bp");
8218 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8219 ((char) (sym->stack - _G.nRegsSaved)) :
8220 ((char) sym->stack)) & 0xff);
8221 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8225 /* we can just move _bp */
8226 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8228 /* fill the result with zero */
8229 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8234 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8240 /* object not on stack then we need the name */
8241 size = AOP_SIZE (IC_RESULT (ic));
8246 char s[SDCC_NAME_MAX];
8248 sprintf (s, "#(%s >> %d)",
8252 sprintf (s, "#%s", sym->rname);
8253 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8257 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8261 /*-----------------------------------------------------------------*/
8262 /* genFarFarAssign - assignment when both are in far space */
8263 /*-----------------------------------------------------------------*/
8265 genFarFarAssign (operand * result, operand * right, iCode * ic)
8267 int size = AOP_SIZE (right);
8271 D(emitcode (";", "genFarFarAssign"));
8273 /* first push the right side on to the stack */
8276 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8278 emitcode ("push", "acc");
8281 freeAsmop (right, NULL, ic, FALSE);
8282 /* now assign DPTR to result */
8283 aopOp (result, ic, FALSE);
8284 size = AOP_SIZE (result);
8287 emitcode ("pop", "acc");
8288 aopPut (AOP (result), "a", --offset);
8290 freeAsmop (result, NULL, ic, FALSE);
8294 /*-----------------------------------------------------------------*/
8295 /* genAssign - generate code for assignment */
8296 /*-----------------------------------------------------------------*/
8298 genAssign (iCode * ic)
8300 operand *result, *right;
8302 unsigned long lit = 0L;
8304 D(emitcode(";","genAssign"));
8306 result = IC_RESULT (ic);
8307 right = IC_RIGHT (ic);
8309 /* if they are the same */
8310 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8313 aopOp (right, ic, FALSE);
8315 /* special case both in far space */
8316 if (AOP_TYPE (right) == AOP_DPTR &&
8317 IS_TRUE_SYMOP (result) &&
8318 isOperandInFarSpace (result))
8321 genFarFarAssign (result, right, ic);
8325 aopOp (result, ic, TRUE);
8327 /* if they are the same registers */
8328 if (sameRegs (AOP (right), AOP (result)))
8331 /* if the result is a bit */
8332 if (AOP_TYPE (result) == AOP_CRY)
8335 /* if the right size is a literal then
8336 we know what the value is */
8337 if (AOP_TYPE (right) == AOP_LIT)
8339 if (((int) operandLitValue (right)))
8340 aopPut (AOP (result), one, 0);
8342 aopPut (AOP (result), zero, 0);
8346 /* the right is also a bit variable */
8347 if (AOP_TYPE (right) == AOP_CRY)
8349 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8350 aopPut (AOP (result), "c", 0);
8356 aopPut (AOP (result), "a", 0);
8360 /* bit variables done */
8362 size = AOP_SIZE (result);
8364 if (AOP_TYPE (right) == AOP_LIT)
8365 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8367 (AOP_TYPE (result) != AOP_REG) &&
8368 (AOP_TYPE (right) == AOP_LIT) &&
8369 !IS_FLOAT (operandType (right)) &&
8372 emitcode ("clr", "a");
8375 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8376 aopPut (AOP (result), "a", size);
8378 aopPut (AOP (result),
8379 aopGet (AOP (right), size, FALSE, FALSE),
8387 aopPut (AOP (result),
8388 aopGet (AOP (right), offset, FALSE, FALSE),
8395 freeAsmop (right, NULL, ic, TRUE);
8396 freeAsmop (result, NULL, ic, TRUE);
8399 /*-----------------------------------------------------------------*/
8400 /* genJumpTab - genrates code for jump table */
8401 /*-----------------------------------------------------------------*/
8403 genJumpTab (iCode * ic)
8408 D(emitcode (";", "genJumpTab"));
8410 aopOp (IC_JTCOND (ic), ic, FALSE);
8411 /* get the condition into accumulator */
8412 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8414 /* multiply by three */
8415 emitcode ("add", "a,acc");
8416 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8417 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8419 jtab = newiTempLabel (NULL);
8420 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8421 emitcode ("jmp", "@a+dptr");
8422 emitcode ("", "%05d$:", jtab->key + 100);
8423 /* now generate the jump labels */
8424 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8425 jtab = setNextItem (IC_JTLABELS (ic)))
8426 emitcode ("ljmp", "%05d$", jtab->key + 100);
8430 /*-----------------------------------------------------------------*/
8431 /* genCast - gen code for casting */
8432 /*-----------------------------------------------------------------*/
8434 genCast (iCode * ic)
8436 operand *result = IC_RESULT (ic);
8437 sym_link *ctype = operandType (IC_LEFT (ic));
8438 sym_link *rtype = operandType (IC_RIGHT (ic));
8439 operand *right = IC_RIGHT (ic);
8442 D(emitcode(";", "genCast"));
8444 /* if they are equivalent then do nothing */
8445 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8448 aopOp (right, ic, FALSE);
8449 aopOp (result, ic, FALSE);
8451 /* if the result is a bit */
8452 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8453 if (IS_BITVAR(OP_SYMBOL(result)->type))
8455 /* if the right size is a literal then
8456 we know what the value is */
8457 if (AOP_TYPE (right) == AOP_LIT)
8459 if (((int) operandLitValue (right)))
8460 aopPut (AOP (result), one, 0);
8462 aopPut (AOP (result), zero, 0);
8467 /* the right is also a bit variable */
8468 if (AOP_TYPE (right) == AOP_CRY)
8470 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8471 aopPut (AOP (result), "c", 0);
8477 aopPut (AOP (result), "a", 0);
8481 /* if they are the same size : or less */
8482 if (AOP_SIZE (result) <= AOP_SIZE (right))
8485 /* if they are in the same place */
8486 if (sameRegs (AOP (right), AOP (result)))
8489 /* if they in different places then copy */
8490 size = AOP_SIZE (result);
8494 aopPut (AOP (result),
8495 aopGet (AOP (right), offset, FALSE, FALSE),
8503 /* if the result is of type pointer */
8508 sym_link *type = operandType (right);
8509 sym_link *etype = getSpec (type);
8511 /* pointer to generic pointer */
8512 if (IS_GENPTR (ctype))
8517 p_type = DCL_TYPE (type);
8520 if (SPEC_SCLS(etype)==S_REGISTER) {
8521 // let's assume it is a generic pointer
8524 /* we have to go by the storage class */
8525 p_type = PTR_TYPE (SPEC_OCLS (etype));
8529 /* the first two bytes are known */
8530 size = GPTRSIZE - 1;
8534 aopPut (AOP (result),
8535 aopGet (AOP (right), offset, FALSE, FALSE),
8539 /* the last byte depending on type */
8555 case PPOINTER: // what the fck is this?
8560 /* this should never happen */
8561 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8562 "got unknown pointer type");
8565 aopPut (AOP (result), l, GPTRSIZE - 1);
8569 /* just copy the pointers */
8570 size = AOP_SIZE (result);
8574 aopPut (AOP (result),
8575 aopGet (AOP (right), offset, FALSE, FALSE),
8582 /* so we now know that the size of destination is greater
8583 than the size of the source */
8584 /* we move to result for the size of source */
8585 size = AOP_SIZE (right);
8589 aopPut (AOP (result),
8590 aopGet (AOP (right), offset, FALSE, FALSE),
8595 /* now depending on the sign of the source && destination */
8596 size = AOP_SIZE (result) - AOP_SIZE (right);
8597 /* if unsigned or not an integral type */
8598 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8601 aopPut (AOP (result), zero, offset++);
8605 /* we need to extend the sign :{ */
8606 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8609 emitcode ("rlc", "a");
8610 emitcode ("subb", "a,acc");
8612 aopPut (AOP (result), "a", offset++);
8615 /* we are done hurray !!!! */
8618 freeAsmop (right, NULL, ic, TRUE);
8619 freeAsmop (result, NULL, ic, TRUE);
8623 /*-----------------------------------------------------------------*/
8624 /* genDjnz - generate decrement & jump if not zero instrucion */
8625 /*-----------------------------------------------------------------*/
8627 genDjnz (iCode * ic, iCode * ifx)
8633 D(emitcode (";", "genDjnz"));
8635 /* if the if condition has a false label
8636 then we cannot save */
8640 /* if the minus is not of the form
8642 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8643 !IS_OP_LITERAL (IC_RIGHT (ic)))
8646 if (operandLitValue (IC_RIGHT (ic)) != 1)
8649 /* if the size of this greater than one then no
8651 if (getSize (operandType (IC_RESULT (ic))) > 1)
8654 /* otherwise we can save BIG */
8655 lbl = newiTempLabel (NULL);
8656 lbl1 = newiTempLabel (NULL);
8658 aopOp (IC_RESULT (ic), ic, FALSE);
8660 if (AOP_NEEDSACC(IC_RESULT(ic)))
8662 /* If the result is accessed indirectly via
8663 * the accumulator, we must explicitly write
8664 * it back after the decrement.
8666 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8668 if (strcmp(rByte, "a"))
8670 /* Something is hopelessly wrong */
8671 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8672 __FILE__, __LINE__);
8673 /* We can just give up; the generated code will be inefficient,
8676 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8679 emitcode ("dec", "%s", rByte);
8680 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8681 emitcode ("jnz", "%05d$", lbl->key + 100);
8683 else if (IS_AOP_PREG (IC_RESULT (ic)))
8685 emitcode ("dec", "%s",
8686 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8687 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8688 emitcode ("jnz", "%05d$", lbl->key + 100);
8692 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8695 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8696 emitcode ("", "%05d$:", lbl->key + 100);
8697 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8698 emitcode ("", "%05d$:", lbl1->key + 100);
8700 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8705 /*-----------------------------------------------------------------*/
8706 /* genReceive - generate code for a receive iCode */
8707 /*-----------------------------------------------------------------*/
8709 genReceive (iCode * ic)
8711 D(emitcode (";", "genReceive"));
8713 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8714 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8715 IS_TRUE_SYMOP (IC_RESULT (ic))))
8718 int size = getSize (operandType (IC_RESULT (ic)));
8719 int offset = fReturnSizeMCS51 - size;
8722 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8723 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8726 aopOp (IC_RESULT (ic), ic, FALSE);
8727 size = AOP_SIZE (IC_RESULT (ic));
8731 emitcode ("pop", "acc");
8732 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8739 aopOp (IC_RESULT (ic), ic, FALSE);
8741 assignResultValue (IC_RESULT (ic));
8744 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8747 /*-----------------------------------------------------------------*/
8748 /* gen51Code - generate code for 8051 based controllers */
8749 /*-----------------------------------------------------------------*/
8751 gen51Code (iCode * lic)
8756 lineHead = lineCurr = NULL;
8758 /* print the allocation information */
8760 printAllocInfo (currFunc, codeOutFile);
8761 /* if debug information required */
8762 if (options.debug && currFunc)
8764 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8766 if (IS_STATIC (currFunc->etype))
8767 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8769 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8772 /* stack pointer name */
8773 if (options.useXstack)
8779 for (ic = lic; ic; ic = ic->next)
8782 if (cln != ic->lineno)
8787 emitcode ("", "C$%s$%d$%d$%d ==.",
8788 FileBaseName (ic->filename), ic->lineno,
8789 ic->level, ic->block);
8792 emitcode (";", "%s %d", ic->filename, ic->lineno);
8795 /* if the result is marked as
8796 spilt and rematerializable or code for
8797 this has already been generated then
8799 if (resultRemat (ic) || ic->generated)
8802 /* depending on the operation */
8822 /* IPOP happens only when trying to restore a
8823 spilt live range, if there is an ifx statement
8824 following this pop then the if statement might
8825 be using some of the registers being popped which
8826 would destory the contents of the register so
8827 we need to check for this condition and handle it */
8829 ic->next->op == IFX &&
8830 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8831 genIfx (ic->next, ic);
8849 genEndFunction (ic);
8869 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8886 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8890 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8897 /* note these two are xlated by algebraic equivalence
8898 during parsing SDCC.y */
8899 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8900 "got '>=' or '<=' shouldn't have come here");
8904 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8916 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8920 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8924 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8951 case GET_VALUE_AT_ADDRESS:
8952 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_LEFT(ic)))));
8956 if (POINTER_SET (ic))
8957 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8983 addSet (&_G.sendSet, ic);
8992 /* now we are ready to call the
8993 peep hole optimizer */
8994 if (!options.nopeep)
8995 peepHole (&lineHead);
8997 /* now do the actual printing */
8998 printLine (lineHead, codeOutFile);