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 (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 (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;
2176 /* create the function header */
2177 emitcode (";", "-----------------------------------------");
2178 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2179 emitcode (";", "-----------------------------------------");
2181 emitcode ("", "%s:", sym->rname);
2182 ftype = operandType (IC_LEFT (ic));
2184 if (IFFUNC_ISNAKED(ftype))
2186 emitcode(";", "naked function: no prologue.");
2190 /* if critical function then turn interrupts off */
2191 if (IFFUNC_ISCRITICAL (ftype))
2192 emitcode ("clr", "ea");
2194 /* here we need to generate the equates for the
2195 register bank if required */
2196 if (FUNC_REGBANK (ftype) != rbank)
2200 rbank = FUNC_REGBANK (ftype);
2201 for (i = 0; i < mcs51_nRegs; i++)
2203 if (strcmp (regs8051[i].base, "0") == 0)
2204 emitcode ("", "%s = 0x%02x",
2206 8 * rbank + regs8051[i].offset);
2208 emitcode ("", "%s = %s + 0x%02x",
2211 8 * rbank + regs8051[i].offset);
2215 /* if this is an interrupt service routine then
2216 save acc, b, dpl, dph */
2217 if (IFFUNC_ISISR (sym->type))
2220 if (!inExcludeList ("acc"))
2221 emitcode ("push", "acc");
2222 if (!inExcludeList ("b"))
2223 emitcode ("push", "b");
2224 if (!inExcludeList ("dpl"))
2225 emitcode ("push", "dpl");
2226 if (!inExcludeList ("dph"))
2227 emitcode ("push", "dph");
2228 /* if this isr has no bank i.e. is going to
2229 run with bank 0 , then we need to save more
2231 if (!FUNC_REGBANK (sym->type))
2234 /* if this function does not call any other
2235 function then we can be economical and
2236 save only those registers that are used */
2237 if (!IFFUNC_HASFCALL(sym->type))
2241 /* if any registers used */
2244 /* save the registers used */
2245 for (i = 0; i < sym->regsUsed->size; i++)
2247 if (bitVectBitValue (sym->regsUsed, i) ||
2248 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2249 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2256 /* this function has a function call cannot
2257 determines register usage so we will have to push the
2259 saveRBank (0, ic, FALSE);
2264 /* This ISR uses a non-zero bank.
2266 * We assume that the bank is available for our
2269 * However, if this ISR calls a function which uses some
2270 * other bank, we must save that bank entirely.
2272 unsigned long banksToSave = 0;
2274 if (IFFUNC_HASFCALL(sym->type))
2277 #define MAX_REGISTER_BANKS 4
2282 for (i = ic; i; i = i->next)
2284 if (i->op == ENDFUNCTION)
2286 /* we got to the end OK. */
2294 dtype = operandType (IC_LEFT(i));
2296 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2298 /* Mark this bank for saving. */
2299 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2301 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2305 banksToSave |= (1 << FUNC_REGBANK(dtype));
2308 /* And note that we don't need to do it in
2316 /* This is a mess; we have no idea what
2317 * register bank the called function might
2320 * The only thing I can think of to do is
2321 * throw a warning and hope.
2323 werror(W_FUNCPTR_IN_USING_ISR);
2327 if (banksToSave && options.useXstack)
2329 /* Since we aren't passing it an ic,
2330 * saveRBank will assume r0 is available to abuse.
2332 * So switch to our (trashable) bank now, so
2333 * the caller's R0 isn't trashed.
2335 emitcode ("push", "psw");
2336 emitcode ("mov", "psw,#0x%02x",
2337 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2341 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2343 if (banksToSave & (1 << ix))
2345 saveRBank(ix, NULL, FALSE);
2349 // jwk: this needs a closer look
2350 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2355 /* if callee-save to be used for this function
2356 then save the registers being used in this function */
2357 if (IFFUNC_CALLEESAVES(sym->type))
2361 /* if any registers used */
2364 /* save the registers used */
2365 for (i = 0; i < sym->regsUsed->size; i++)
2367 if (bitVectBitValue (sym->regsUsed, i) ||
2368 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2370 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2378 /* set the register bank to the desired value */
2379 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2382 emitcode ("push", "psw");
2383 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2386 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2389 if (options.useXstack)
2391 emitcode ("mov", "r0,%s", spname);
2392 emitcode ("mov", "a,_bp");
2393 emitcode ("movx", "@r0,a");
2394 emitcode ("inc", "%s", spname);
2398 /* set up the stack */
2399 emitcode ("push", "_bp"); /* save the callers stack */
2401 emitcode ("mov", "_bp,%s", spname);
2404 /* adjust the stack for the function */
2410 werror (W_STACK_OVERFLOW, sym->name);
2412 if (i > 3 && sym->recvSize < 4)
2415 emitcode ("mov", "a,sp");
2416 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2417 emitcode ("mov", "sp,a");
2422 emitcode ("inc", "sp");
2428 emitcode ("mov", "a,_spx");
2429 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2430 emitcode ("mov", "_spx,a");
2435 /*-----------------------------------------------------------------*/
2436 /* genEndFunction - generates epilogue for functions */
2437 /*-----------------------------------------------------------------*/
2439 genEndFunction (iCode * ic)
2441 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2443 if (IFFUNC_ISNAKED(sym->type))
2445 emitcode(";", "naked function: no epilogue.");
2449 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2451 emitcode ("mov", "%s,_bp", spname);
2454 /* if use external stack but some variables were
2455 added to the local stack then decrement the
2457 if (options.useXstack && sym->stack)
2459 emitcode ("mov", "a,sp");
2460 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2461 emitcode ("mov", "sp,a");
2465 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2467 if (options.useXstack)
2469 emitcode ("mov", "r0,%s", spname);
2470 emitcode ("movx", "a,@r0");
2471 emitcode ("mov", "_bp,a");
2472 emitcode ("dec", "%s", spname);
2476 emitcode ("pop", "_bp");
2480 /* restore the register bank */
2481 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2483 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2484 || !options.useXstack)
2486 /* Special case of ISR using non-zero bank with useXstack
2489 emitcode ("pop", "psw");
2493 if (IFFUNC_ISISR (sym->type))
2496 /* now we need to restore the registers */
2497 /* if this isr has no bank i.e. is going to
2498 run with bank 0 , then we need to save more
2500 if (!FUNC_REGBANK (sym->type))
2502 /* if this function does not call any other
2503 function then we can be economical and
2504 save only those registers that are used */
2505 if (!IFFUNC_HASFCALL(sym->type))
2509 /* if any registers used */
2512 /* save the registers used */
2513 for (i = sym->regsUsed->size; i >= 0; i--)
2515 if (bitVectBitValue (sym->regsUsed, i) ||
2516 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2517 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2524 /* this function has a function call cannot
2525 determines register usage so we will have to pop the
2527 unsaveRBank (0, ic, FALSE);
2532 /* This ISR uses a non-zero bank.
2534 * Restore any register banks saved by genFunction
2537 // jwk: this needs a closer look
2538 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2541 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2543 if (savedBanks & (1 << ix))
2545 unsaveRBank(ix, NULL, FALSE);
2549 if (options.useXstack)
2551 /* Restore bank AFTER calling unsaveRBank,
2552 * since it can trash r0.
2554 emitcode ("pop", "psw");
2558 if (!inExcludeList ("dph"))
2559 emitcode ("pop", "dph");
2560 if (!inExcludeList ("dpl"))
2561 emitcode ("pop", "dpl");
2562 if (!inExcludeList ("b"))
2563 emitcode ("pop", "b");
2564 if (!inExcludeList ("acc"))
2565 emitcode ("pop", "acc");
2567 if (IFFUNC_ISCRITICAL (sym->type))
2568 emitcode ("setb", "ea");
2570 /* if debug then send end of function */
2571 /* if (options.debug && currFunc) */
2572 if (options.debug && currFunc)
2575 emitcode ("", "C$%s$%d$%d$%d ==.",
2576 FileBaseName (ic->filename), currFunc->lastLine,
2577 ic->level, ic->block);
2578 if (IS_STATIC (currFunc->etype))
2579 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2581 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2585 emitcode ("reti", "");
2589 if (IFFUNC_ISCRITICAL (sym->type))
2590 emitcode ("setb", "ea");
2592 if (IFFUNC_CALLEESAVES(sym->type))
2596 /* if any registers used */
2599 /* save the registers used */
2600 for (i = sym->regsUsed->size; i >= 0; i--)
2602 if (bitVectBitValue (sym->regsUsed, i) ||
2603 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2604 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2610 /* if debug then send end of function */
2611 if (options.debug && currFunc)
2614 emitcode ("", "C$%s$%d$%d$%d ==.",
2615 FileBaseName (ic->filename), currFunc->lastLine,
2616 ic->level, ic->block);
2617 if (IS_STATIC (currFunc->etype))
2618 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2620 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2624 emitcode ("ret", "");
2629 /*-----------------------------------------------------------------*/
2630 /* genRet - generate code for return statement */
2631 /*-----------------------------------------------------------------*/
2635 int size, offset = 0, pushed = 0;
2637 D(emitcode (";", "genRet"));
2639 /* if we have no return value then
2640 just generate the "ret" */
2644 /* we have something to return then
2645 move the return value into place */
2646 aopOp (IC_LEFT (ic), ic, FALSE);
2647 size = AOP_SIZE (IC_LEFT (ic));
2652 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2655 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2657 emitcode ("push", "%s", l);
2662 l = aopGet (AOP (IC_LEFT (ic)), offset,
2664 if (strcmp (fReturn[offset], l))
2665 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2674 if (strcmp (fReturn[pushed], "a"))
2675 emitcode ("pop", fReturn[pushed]);
2677 emitcode ("pop", "acc");
2680 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2683 /* generate a jump to the return label
2684 if the next is not the return statement */
2685 if (!(ic->next && ic->next->op == LABEL &&
2686 IC_LABEL (ic->next) == returnLabel))
2688 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2692 /*-----------------------------------------------------------------*/
2693 /* genLabel - generates a label */
2694 /*-----------------------------------------------------------------*/
2696 genLabel (iCode * ic)
2698 /* special case never generate */
2699 if (IC_LABEL (ic) == entryLabel)
2702 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2705 /*-----------------------------------------------------------------*/
2706 /* genGoto - generates a ljmp */
2707 /*-----------------------------------------------------------------*/
2709 genGoto (iCode * ic)
2711 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2714 /*-----------------------------------------------------------------*/
2715 /* findLabelBackwards: walks back through the iCode chain looking */
2716 /* for the given label. Returns number of iCode instructions */
2717 /* between that label and given ic. */
2718 /* Returns zero if label not found. */
2719 /*-----------------------------------------------------------------*/
2721 findLabelBackwards (iCode * ic, int key)
2730 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2732 /* printf("findLabelBackwards = %d\n", count); */
2740 /*-----------------------------------------------------------------*/
2741 /* genPlusIncr :- does addition with increment if possible */
2742 /*-----------------------------------------------------------------*/
2744 genPlusIncr (iCode * ic)
2746 unsigned int icount;
2747 unsigned int size = getDataSize (IC_RESULT (ic));
2749 /* will try to generate an increment */
2750 /* if the right side is not a literal
2752 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2755 /* if the literal value of the right hand side
2756 is greater than 4 then it is not worth it */
2757 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2760 D(emitcode (";", "genPlusIncr"));
2762 /* if increment 16 bits in register */
2763 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2771 /* If the next instruction is a goto and the goto target
2772 * is < 10 instructions previous to this, we can generate
2773 * jumps straight to that target.
2775 if (ic->next && ic->next->op == GOTO
2776 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2777 && labelRange <= 10)
2779 emitcode (";", "tail increment optimized");
2780 tlbl = IC_LABEL (ic->next);
2785 tlbl = newiTempLabel (NULL);
2788 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2789 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2790 IS_AOP_PREG (IC_RESULT (ic)))
2791 emitcode ("cjne", "%s,#0x00,%05d$"
2792 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2796 emitcode ("clr", "a");
2797 emitcode ("cjne", "a,%s,%05d$"
2798 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2802 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2805 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2806 IS_AOP_PREG (IC_RESULT (ic)))
2807 emitcode ("cjne", "%s,#0x00,%05d$"
2808 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2811 emitcode ("cjne", "a,%s,%05d$"
2812 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2815 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2819 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2820 IS_AOP_PREG (IC_RESULT (ic)))
2821 emitcode ("cjne", "%s,#0x00,%05d$"
2822 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2826 emitcode ("cjne", "a,%s,%05d$"
2827 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2830 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2835 emitcode ("", "%05d$:", tlbl->key + 100);
2840 /* if the sizes are greater than 1 then we cannot */
2841 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2842 AOP_SIZE (IC_LEFT (ic)) > 1)
2845 /* we can if the aops of the left & result match or
2846 if they are in registers and the registers are the
2848 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2853 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2854 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2855 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2861 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2870 /*-----------------------------------------------------------------*/
2871 /* outBitAcc - output a bit in acc */
2872 /*-----------------------------------------------------------------*/
2874 outBitAcc (operand * result)
2876 symbol *tlbl = newiTempLabel (NULL);
2877 /* if the result is a bit */
2878 if (AOP_TYPE (result) == AOP_CRY)
2880 aopPut (AOP (result), "a", 0);
2884 emitcode ("jz", "%05d$", tlbl->key + 100);
2885 emitcode ("mov", "a,%s", one);
2886 emitcode ("", "%05d$:", tlbl->key + 100);
2891 /*-----------------------------------------------------------------*/
2892 /* genPlusBits - generates code for addition of two bits */
2893 /*-----------------------------------------------------------------*/
2895 genPlusBits (iCode * ic)
2897 D(emitcode (";", "genPlusBits"));
2899 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2901 symbol *lbl = newiTempLabel (NULL);
2902 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2903 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2904 emitcode ("cpl", "c");
2905 emitcode ("", "%05d$:", (lbl->key + 100));
2906 outBitC (IC_RESULT (ic));
2910 emitcode ("clr", "a");
2911 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2912 emitcode ("rlc", "a");
2913 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2914 emitcode ("addc", "a,#0x00");
2915 outAcc (IC_RESULT (ic));
2920 /* This is the original version of this code.
2922 * This is being kept around for reference,
2923 * because I am not entirely sure I got it right...
2926 adjustArithmeticResult (iCode * ic)
2928 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2929 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2930 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2931 aopPut (AOP (IC_RESULT (ic)),
2932 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2935 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2936 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2937 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2938 aopPut (AOP (IC_RESULT (ic)),
2939 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2942 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2943 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2944 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2945 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2946 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2949 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2950 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2954 /* This is the pure and virtuous version of this code.
2955 * I'm pretty certain it's right, but not enough to toss the old
2959 adjustArithmeticResult (iCode * ic)
2961 if (opIsGptr (IC_RESULT (ic)) &&
2962 opIsGptr (IC_LEFT (ic)) &&
2963 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2965 aopPut (AOP (IC_RESULT (ic)),
2966 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2970 if (opIsGptr (IC_RESULT (ic)) &&
2971 opIsGptr (IC_RIGHT (ic)) &&
2972 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2974 aopPut (AOP (IC_RESULT (ic)),
2975 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2979 if (opIsGptr (IC_RESULT (ic)) &&
2980 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2981 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2982 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2983 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2986 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2987 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2992 /*-----------------------------------------------------------------*/
2993 /* genPlus - generates code for addition */
2994 /*-----------------------------------------------------------------*/
2996 genPlus (iCode * ic)
2998 int size, offset = 0;
3000 /* special cases :- */
3002 D(emitcode (";", "genPlus"));
3004 aopOp (IC_LEFT (ic), ic, FALSE);
3005 aopOp (IC_RIGHT (ic), ic, FALSE);
3006 aopOp (IC_RESULT (ic), ic, TRUE);
3008 /* if literal, literal on the right or
3009 if left requires ACC or right is already
3011 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3012 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3013 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3015 operand *t = IC_RIGHT (ic);
3016 IC_RIGHT (ic) = IC_LEFT (ic);
3020 /* if both left & right are in bit
3022 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3023 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3029 /* if left in bit space & right literal */
3030 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3031 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3033 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3034 /* if result in bit space */
3035 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3037 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3038 emitcode ("cpl", "c");
3039 outBitC (IC_RESULT (ic));
3043 size = getDataSize (IC_RESULT (ic));
3046 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3047 emitcode ("addc", "a,#00");
3048 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3054 /* if I can do an increment instead
3055 of add then GOOD for ME */
3056 if (genPlusIncr (ic) == TRUE)
3059 size = getDataSize (IC_RESULT (ic));
3063 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3065 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3067 emitcode ("add", "a,%s",
3068 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3070 emitcode ("addc", "a,%s",
3071 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3075 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3077 emitcode ("add", "a,%s",
3078 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3080 emitcode ("addc", "a,%s",
3081 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3083 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3086 adjustArithmeticResult (ic);
3089 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3090 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3091 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3094 /*-----------------------------------------------------------------*/
3095 /* genMinusDec :- does subtraction with deccrement if possible */
3096 /*-----------------------------------------------------------------*/
3098 genMinusDec (iCode * ic)
3100 unsigned int icount;
3101 unsigned int size = getDataSize (IC_RESULT (ic));
3103 /* will try to generate an increment */
3104 /* if the right side is not a literal
3106 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3109 /* if the literal value of the right hand side
3110 is greater than 4 then it is not worth it */
3111 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3114 D(emitcode (";", "genMinusDec"));
3116 /* if decrement 16 bits in register */
3117 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3125 /* If the next instruction is a goto and the goto target
3126 * is <= 10 instructions previous to this, we can generate
3127 * jumps straight to that target.
3129 if (ic->next && ic->next->op == GOTO
3130 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3131 && labelRange <= 10)
3133 emitcode (";", "tail decrement optimized");
3134 tlbl = IC_LABEL (ic->next);
3139 tlbl = newiTempLabel (NULL);
3143 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3144 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3145 IS_AOP_PREG (IC_RESULT (ic)))
3146 emitcode ("cjne", "%s,#0xff,%05d$"
3147 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3151 emitcode ("mov", "a,#0xff");
3152 emitcode ("cjne", "a,%s,%05d$"
3153 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3156 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3159 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3160 IS_AOP_PREG (IC_RESULT (ic)))
3161 emitcode ("cjne", "%s,#0xff,%05d$"
3162 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3166 emitcode ("cjne", "a,%s,%05d$"
3167 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3170 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3174 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3175 IS_AOP_PREG (IC_RESULT (ic)))
3176 emitcode ("cjne", "%s,#0xff,%05d$"
3177 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3181 emitcode ("cjne", "a,%s,%05d$"
3182 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3185 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3189 emitcode ("", "%05d$:", tlbl->key + 100);
3194 /* if the sizes are greater than 1 then we cannot */
3195 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3196 AOP_SIZE (IC_LEFT (ic)) > 1)
3199 /* we can if the aops of the left & result match or
3200 if they are in registers and the registers are the
3202 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3206 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3214 /*-----------------------------------------------------------------*/
3215 /* addSign - complete with sign */
3216 /*-----------------------------------------------------------------*/
3218 addSign (operand * result, int offset, int sign)
3220 int size = (getDataSize (result) - offset);
3225 emitcode ("rlc", "a");
3226 emitcode ("subb", "a,acc");
3228 aopPut (AOP (result), "a", offset++);
3232 aopPut (AOP (result), zero, offset++);
3236 /*-----------------------------------------------------------------*/
3237 /* genMinusBits - generates code for subtraction of two bits */
3238 /*-----------------------------------------------------------------*/
3240 genMinusBits (iCode * ic)
3242 symbol *lbl = newiTempLabel (NULL);
3244 D(emitcode (";", "genMinusBits"));
3246 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3248 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3249 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3250 emitcode ("cpl", "c");
3251 emitcode ("", "%05d$:", (lbl->key + 100));
3252 outBitC (IC_RESULT (ic));
3256 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3257 emitcode ("subb", "a,acc");
3258 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3259 emitcode ("inc", "a");
3260 emitcode ("", "%05d$:", (lbl->key + 100));
3261 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3262 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3266 /*-----------------------------------------------------------------*/
3267 /* genMinus - generates code for subtraction */
3268 /*-----------------------------------------------------------------*/
3270 genMinus (iCode * ic)
3272 int size, offset = 0;
3273 unsigned long lit = 0L;
3275 D(emitcode (";", "genMinus"));
3277 aopOp (IC_LEFT (ic), ic, FALSE);
3278 aopOp (IC_RIGHT (ic), ic, FALSE);
3279 aopOp (IC_RESULT (ic), ic, TRUE);
3281 /* special cases :- */
3282 /* if both left & right are in bit space */
3283 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3284 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3290 /* if I can do an decrement instead
3291 of subtract then GOOD for ME */
3292 if (genMinusDec (ic) == TRUE)
3295 size = getDataSize (IC_RESULT (ic));
3297 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3303 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3307 /* if literal, add a,#-lit, else normal subb */
3310 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3311 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3312 emitcode ("subb", "a,%s",
3313 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3316 /* first add without previous c */
3318 if (!size && lit==-1) {
3319 emitcode ("dec", "a");
3321 emitcode ("add", "a,#0x%02x",
3322 (unsigned int) (lit & 0x0FFL));
3325 emitcode ("addc", "a,#0x%02x",
3326 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3329 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3332 adjustArithmeticResult (ic);
3335 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3336 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3337 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3341 /*-----------------------------------------------------------------*/
3342 /* genMultbits :- multiplication of bits */
3343 /*-----------------------------------------------------------------*/
3345 genMultbits (operand * left,
3349 D(emitcode (";", "genMultbits"));
3351 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3352 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3357 /*-----------------------------------------------------------------*/
3358 /* genMultOneByte : 8*8=8/16 bit multiplication */
3359 /*-----------------------------------------------------------------*/
3361 genMultOneByte (operand * left,
3365 sym_link *opetype = operandType (result);
3367 int size=AOP_SIZE(result);
3369 D(emitcode (";", "genMultOneByte"));
3371 if (size<1 || size>2) {
3372 // this should never happen
3373 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3374 AOP_SIZE(result), __FILE__, lineno);
3378 /* (if two literals: the value is computed before) */
3379 /* if one literal, literal on the right */
3380 if (AOP_TYPE (left) == AOP_LIT)
3385 //emitcode (";", "swapped left and right");
3388 if (SPEC_USIGN(opetype)
3389 // ignore the sign of left and right, what else can we do?
3390 || (SPEC_USIGN(operandType(left)) &&
3391 SPEC_USIGN(operandType(right)))) {
3392 // just an unsigned 8*8=8/16 multiply
3393 //emitcode (";","unsigned");
3394 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3395 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3396 emitcode ("mul", "ab");
3397 aopPut (AOP (result), "a", 0);
3399 aopPut (AOP (result), "b", 1);
3404 // we have to do a signed multiply
3406 //emitcode (";", "signed");
3407 emitcode ("clr", "F0"); // reset sign flag
3408 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3410 lbl=newiTempLabel(NULL);
3411 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3412 // left side is negative, 8-bit two's complement, this fails for -128
3413 emitcode ("setb", "F0"); // set sign flag
3414 emitcode ("cpl", "a");
3415 emitcode ("inc", "a");
3417 emitcode ("", "%05d$:", lbl->key+100);
3420 if (AOP_TYPE(right)==AOP_LIT) {
3421 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3422 /* AND literal negative */
3424 emitcode ("cpl", "F0"); // complement sign flag
3425 emitcode ("mov", "b,#0x%02x", -val);
3427 emitcode ("mov", "b,#0x%02x", val);
3430 lbl=newiTempLabel(NULL);
3431 emitcode ("mov", "b,a");
3432 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3433 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3434 // right side is negative, 8-bit two's complement
3435 emitcode ("cpl", "F0"); // complement sign flag
3436 emitcode ("cpl", "a");
3437 emitcode ("inc", "a");
3438 emitcode ("", "%05d$:", lbl->key+100);
3440 emitcode ("mul", "ab");
3442 lbl=newiTempLabel(NULL);
3443 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3444 // only ONE op was negative, we have to do a 8/16-bit two's complement
3445 emitcode ("cpl", "a"); // lsb
3447 emitcode ("inc", "a");
3449 emitcode ("add", "a,#1");
3450 emitcode ("xch", "a,b");
3451 emitcode ("cpl", "a"); // msb
3452 emitcode ("addc", "a,#0");
3453 emitcode ("xch", "a,b");
3456 emitcode ("", "%05d$:", lbl->key+100);
3457 aopPut (AOP (result), "a", 0);
3459 aopPut (AOP (result), "b", 1);
3463 /*-----------------------------------------------------------------*/
3464 /* genMult - generates code for multiplication */
3465 /*-----------------------------------------------------------------*/
3467 genMult (iCode * ic)
3469 operand *left = IC_LEFT (ic);
3470 operand *right = IC_RIGHT (ic);
3471 operand *result = IC_RESULT (ic);
3473 D(emitcode (";", "genMult"));
3475 /* assign the amsops */
3476 aopOp (left, ic, FALSE);
3477 aopOp (right, ic, FALSE);
3478 aopOp (result, ic, TRUE);
3480 /* special cases first */
3482 if (AOP_TYPE (left) == AOP_CRY &&
3483 AOP_TYPE (right) == AOP_CRY)
3485 genMultbits (left, right, result);
3489 /* if both are of size == 1 */
3490 #if 0 // one of them can be a sloc shared with the result
3491 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3493 if (getSize(operandType(left)) == 1 &&
3494 getSize(operandType(right)) == 1)
3497 genMultOneByte (left, right, result);
3501 /* should have been converted to function call */
3502 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3503 getSize(OP_SYMBOL(right)->type));
3507 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3508 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3509 freeAsmop (result, NULL, ic, TRUE);
3512 /*-----------------------------------------------------------------*/
3513 /* genDivbits :- division of bits */
3514 /*-----------------------------------------------------------------*/
3516 genDivbits (operand * left,
3523 D(emitcode (";", "genDivbits"));
3525 /* the result must be bit */
3526 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3527 l = aopGet (AOP (left), 0, FALSE, FALSE);
3531 emitcode ("div", "ab");
3532 emitcode ("rrc", "a");
3533 aopPut (AOP (result), "c", 0);
3536 /*-----------------------------------------------------------------*/
3537 /* genDivOneByte : 8 bit division */
3538 /*-----------------------------------------------------------------*/
3540 genDivOneByte (operand * left,
3544 sym_link *opetype = operandType (result);
3549 D(emitcode (";", "genDivOneByte"));
3551 size = AOP_SIZE (result) - 1;
3553 /* signed or unsigned */
3554 if (SPEC_USIGN (opetype))
3556 /* unsigned is easy */
3557 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3558 l = aopGet (AOP (left), 0, FALSE, FALSE);
3560 emitcode ("div", "ab");
3561 aopPut (AOP (result), "a", 0);
3563 aopPut (AOP (result), zero, offset++);
3567 /* signed is a little bit more difficult */
3569 /* save the signs of the operands */
3570 l = aopGet (AOP (left), 0, FALSE, FALSE);
3572 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3573 emitcode ("push", "acc"); /* save it on the stack */
3575 /* now sign adjust for both left & right */
3576 l = aopGet (AOP (right), 0, FALSE, FALSE);
3578 lbl = newiTempLabel (NULL);
3579 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3580 emitcode ("cpl", "a");
3581 emitcode ("inc", "a");
3582 emitcode ("", "%05d$:", (lbl->key + 100));
3583 emitcode ("mov", "b,a");
3585 /* sign adjust left side */
3586 l = aopGet (AOP (left), 0, FALSE, FALSE);
3589 lbl = newiTempLabel (NULL);
3590 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3591 emitcode ("cpl", "a");
3592 emitcode ("inc", "a");
3593 emitcode ("", "%05d$:", (lbl->key + 100));
3595 /* now the division */
3596 emitcode ("div", "ab");
3597 /* we are interested in the lower order
3599 emitcode ("mov", "b,a");
3600 lbl = newiTempLabel (NULL);
3601 emitcode ("pop", "acc");
3602 /* if there was an over flow we don't
3603 adjust the sign of the result */
3604 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3605 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3607 emitcode ("clr", "a");
3608 emitcode ("subb", "a,b");
3609 emitcode ("mov", "b,a");
3610 emitcode ("", "%05d$:", (lbl->key + 100));
3612 /* now we are done */
3613 aopPut (AOP (result), "b", 0);
3616 emitcode ("mov", "c,b.7");
3617 emitcode ("subb", "a,acc");
3620 aopPut (AOP (result), "a", offset++);
3624 /*-----------------------------------------------------------------*/
3625 /* genDiv - generates code for division */
3626 /*-----------------------------------------------------------------*/
3630 operand *left = IC_LEFT (ic);
3631 operand *right = IC_RIGHT (ic);
3632 operand *result = IC_RESULT (ic);
3634 D(emitcode (";", "genDiv"));
3636 /* assign the amsops */
3637 aopOp (left, ic, FALSE);
3638 aopOp (right, ic, FALSE);
3639 aopOp (result, ic, TRUE);
3641 /* special cases first */
3643 if (AOP_TYPE (left) == AOP_CRY &&
3644 AOP_TYPE (right) == AOP_CRY)
3646 genDivbits (left, right, result);
3650 /* if both are of size == 1 */
3651 if (AOP_SIZE (left) == 1 &&
3652 AOP_SIZE (right) == 1)
3654 genDivOneByte (left, right, result);
3658 /* should have been converted to function call */
3661 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3662 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3663 freeAsmop (result, NULL, ic, TRUE);
3666 /*-----------------------------------------------------------------*/
3667 /* genModbits :- modulus of bits */
3668 /*-----------------------------------------------------------------*/
3670 genModbits (operand * left,
3677 D(emitcode (";", "genModbits"));
3679 /* the result must be bit */
3680 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3681 l = aopGet (AOP (left), 0, FALSE, FALSE);
3685 emitcode ("div", "ab");
3686 emitcode ("mov", "a,b");
3687 emitcode ("rrc", "a");
3688 aopPut (AOP (result), "c", 0);
3691 /*-----------------------------------------------------------------*/
3692 /* genModOneByte : 8 bit modulus */
3693 /*-----------------------------------------------------------------*/
3695 genModOneByte (operand * left,
3699 sym_link *opetype = operandType (result);
3703 D(emitcode (";", "genModOneByte"));
3705 /* signed or unsigned */
3706 if (SPEC_USIGN (opetype))
3708 /* unsigned is easy */
3709 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3710 l = aopGet (AOP (left), 0, FALSE, FALSE);
3712 emitcode ("div", "ab");
3713 aopPut (AOP (result), "b", 0);
3717 /* signed is a little bit more difficult */
3719 /* save the signs of the operands */
3720 l = aopGet (AOP (left), 0, FALSE, FALSE);
3723 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3724 emitcode ("push", "acc"); /* save it on the stack */
3726 /* now sign adjust for both left & right */
3727 l = aopGet (AOP (right), 0, FALSE, FALSE);
3730 lbl = newiTempLabel (NULL);
3731 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3732 emitcode ("cpl", "a");
3733 emitcode ("inc", "a");
3734 emitcode ("", "%05d$:", (lbl->key + 100));
3735 emitcode ("mov", "b,a");
3737 /* sign adjust left side */
3738 l = aopGet (AOP (left), 0, FALSE, FALSE);
3741 lbl = newiTempLabel (NULL);
3742 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3743 emitcode ("cpl", "a");
3744 emitcode ("inc", "a");
3745 emitcode ("", "%05d$:", (lbl->key + 100));
3747 /* now the multiplication */
3748 emitcode ("div", "ab");
3749 /* we are interested in the lower order
3751 lbl = newiTempLabel (NULL);
3752 emitcode ("pop", "acc");
3753 /* if there was an over flow we don't
3754 adjust the sign of the result */
3755 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3756 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3758 emitcode ("clr", "a");
3759 emitcode ("subb", "a,b");
3760 emitcode ("mov", "b,a");
3761 emitcode ("", "%05d$:", (lbl->key + 100));
3763 /* now we are done */
3764 aopPut (AOP (result), "b", 0);
3768 /*-----------------------------------------------------------------*/
3769 /* genMod - generates code for division */
3770 /*-----------------------------------------------------------------*/
3774 operand *left = IC_LEFT (ic);
3775 operand *right = IC_RIGHT (ic);
3776 operand *result = IC_RESULT (ic);
3778 D(emitcode (";", "genMod"));
3780 /* assign the amsops */
3781 aopOp (left, ic, FALSE);
3782 aopOp (right, ic, FALSE);
3783 aopOp (result, ic, TRUE);
3785 /* special cases first */
3787 if (AOP_TYPE (left) == AOP_CRY &&
3788 AOP_TYPE (right) == AOP_CRY)
3790 genModbits (left, right, result);
3794 /* if both are of size == 1 */
3795 if (AOP_SIZE (left) == 1 &&
3796 AOP_SIZE (right) == 1)
3798 genModOneByte (left, right, result);
3802 /* should have been converted to function call */
3806 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3807 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3808 freeAsmop (result, NULL, ic, TRUE);
3811 /*-----------------------------------------------------------------*/
3812 /* genIfxJump :- will create a jump depending on the ifx */
3813 /*-----------------------------------------------------------------*/
3815 genIfxJump (iCode * ic, char *jval)
3818 symbol *tlbl = newiTempLabel (NULL);
3821 D(emitcode (";", "genIfxJump"));
3823 /* if true label then we jump if condition
3827 jlbl = IC_TRUE (ic);
3828 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3829 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3833 /* false label is present */
3834 jlbl = IC_FALSE (ic);
3835 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3836 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3838 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3839 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3841 emitcode (inst, "%05d$", tlbl->key + 100);
3842 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3843 emitcode ("", "%05d$:", tlbl->key + 100);
3845 /* mark the icode as generated */
3849 /*-----------------------------------------------------------------*/
3850 /* genCmp :- greater or less than comparison */
3851 /*-----------------------------------------------------------------*/
3853 genCmp (operand * left, operand * right,
3854 operand * result, iCode * ifx, int sign, iCode *ic)
3856 int size, offset = 0;
3857 unsigned long lit = 0L;
3859 D(emitcode (";", "genCmp"));
3861 /* if left & right are bit variables */
3862 if (AOP_TYPE (left) == AOP_CRY &&
3863 AOP_TYPE (right) == AOP_CRY)
3865 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3866 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3870 /* subtract right from left if at the
3871 end the carry flag is set then we know that
3872 left is greater than right */
3873 size = max (AOP_SIZE (left), AOP_SIZE (right));
3875 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3876 if ((size == 1) && !sign &&
3877 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3879 symbol *lbl = newiTempLabel (NULL);
3880 emitcode ("cjne", "%s,%s,%05d$",
3881 aopGet (AOP (left), offset, FALSE, FALSE),
3882 aopGet (AOP (right), offset, FALSE, FALSE),
3884 emitcode ("", "%05d$:", lbl->key + 100);
3888 if (AOP_TYPE (right) == AOP_LIT)
3890 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3891 /* optimize if(x < 0) or if(x >= 0) */
3900 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3901 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3903 genIfxJump (ifx, "acc.7");
3907 emitcode ("rlc", "a");
3915 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3916 if (sign && size == 0)
3918 emitcode ("xrl", "a,#0x80");
3919 if (AOP_TYPE (right) == AOP_LIT)
3921 unsigned long lit = (unsigned long)
3922 floatFromVal (AOP (right)->aopu.aop_lit);
3923 emitcode ("subb", "a,#0x%02x",
3924 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3928 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3929 emitcode ("xrl", "b,#0x80");
3930 emitcode ("subb", "a,b");
3934 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3940 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3942 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3948 /* if the result is used in the next
3949 ifx conditional branch then generate
3950 code a little differently */
3952 genIfxJump (ifx, "c");
3955 /* leave the result in acc */
3959 /*-----------------------------------------------------------------*/
3960 /* genCmpGt :- greater than comparison */
3961 /*-----------------------------------------------------------------*/
3963 genCmpGt (iCode * ic, iCode * ifx)
3965 operand *left, *right, *result;
3966 sym_link *letype, *retype;
3969 D(emitcode (";", "genCmpGt"));
3971 left = IC_LEFT (ic);
3972 right = IC_RIGHT (ic);
3973 result = IC_RESULT (ic);
3975 letype = getSpec (operandType (left));
3976 retype = getSpec (operandType (right));
3977 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3978 /* assign the amsops */
3979 aopOp (left, ic, FALSE);
3980 aopOp (right, ic, FALSE);
3981 aopOp (result, ic, TRUE);
3983 genCmp (right, left, result, ifx, sign,ic);
3985 freeAsmop (result, NULL, ic, TRUE);
3988 /*-----------------------------------------------------------------*/
3989 /* genCmpLt - less than comparisons */
3990 /*-----------------------------------------------------------------*/
3992 genCmpLt (iCode * ic, iCode * ifx)
3994 operand *left, *right, *result;
3995 sym_link *letype, *retype;
3998 D(emitcode (";", "genCmpLt"));
4000 left = IC_LEFT (ic);
4001 right = IC_RIGHT (ic);
4002 result = IC_RESULT (ic);
4004 letype = getSpec (operandType (left));
4005 retype = getSpec (operandType (right));
4006 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4008 /* assign the amsops */
4009 aopOp (left, ic, FALSE);
4010 aopOp (right, ic, FALSE);
4011 aopOp (result, ic, TRUE);
4013 genCmp (left, right, result, ifx, sign,ic);
4015 freeAsmop (result, NULL, ic, TRUE);
4018 /*-----------------------------------------------------------------*/
4019 /* gencjneshort - compare and jump if not equal */
4020 /*-----------------------------------------------------------------*/
4022 gencjneshort (operand * left, operand * right, symbol * lbl)
4024 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4026 unsigned long lit = 0L;
4028 /* if the left side is a literal or
4029 if the right is in a pointer register and left
4031 if ((AOP_TYPE (left) == AOP_LIT) ||
4032 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4038 if (AOP_TYPE (right) == AOP_LIT)
4039 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4041 /* if the right side is a literal then anything goes */
4042 if (AOP_TYPE (right) == AOP_LIT &&
4043 AOP_TYPE (left) != AOP_DIR)
4047 emitcode ("cjne", "%s,%s,%05d$",
4048 aopGet (AOP (left), offset, FALSE, FALSE),
4049 aopGet (AOP (right), offset, FALSE, FALSE),
4055 /* if the right side is in a register or in direct space or
4056 if the left is a pointer register & right is not */
4057 else if (AOP_TYPE (right) == AOP_REG ||
4058 AOP_TYPE (right) == AOP_DIR ||
4059 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4060 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4064 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4065 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4066 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4067 emitcode ("jnz", "%05d$", lbl->key + 100);
4069 emitcode ("cjne", "a,%s,%05d$",
4070 aopGet (AOP (right), offset, FALSE, TRUE),
4077 /* right is a pointer reg need both a & b */
4080 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4081 if (strcmp (l, "b"))
4082 emitcode ("mov", "b,%s", l);
4083 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4084 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4090 /*-----------------------------------------------------------------*/
4091 /* gencjne - compare and jump if not equal */
4092 /*-----------------------------------------------------------------*/
4094 gencjne (operand * left, operand * right, symbol * lbl)
4096 symbol *tlbl = newiTempLabel (NULL);
4098 gencjneshort (left, right, lbl);
4100 emitcode ("mov", "a,%s", one);
4101 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4102 emitcode ("", "%05d$:", lbl->key + 100);
4103 emitcode ("clr", "a");
4104 emitcode ("", "%05d$:", tlbl->key + 100);
4107 /*-----------------------------------------------------------------*/
4108 /* genCmpEq - generates code for equal to */
4109 /*-----------------------------------------------------------------*/
4111 genCmpEq (iCode * ic, iCode * ifx)
4113 operand *left, *right, *result;
4115 D(emitcode (";", "genCmpEq"));
4117 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4118 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4119 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4121 /* if literal, literal on the right or
4122 if the right is in a pointer register and left
4124 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4125 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4127 operand *t = IC_RIGHT (ic);
4128 IC_RIGHT (ic) = IC_LEFT (ic);
4132 if (ifx && !AOP_SIZE (result))
4135 /* if they are both bit variables */
4136 if (AOP_TYPE (left) == AOP_CRY &&
4137 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4139 if (AOP_TYPE (right) == AOP_LIT)
4141 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4144 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4145 emitcode ("cpl", "c");
4149 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4153 emitcode ("clr", "c");
4155 /* AOP_TYPE(right) == AOP_CRY */
4159 symbol *lbl = newiTempLabel (NULL);
4160 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4161 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4162 emitcode ("cpl", "c");
4163 emitcode ("", "%05d$:", (lbl->key + 100));
4165 /* if true label then we jump if condition
4167 tlbl = newiTempLabel (NULL);
4170 emitcode ("jnc", "%05d$", tlbl->key + 100);
4171 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4175 emitcode ("jc", "%05d$", tlbl->key + 100);
4176 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4178 emitcode ("", "%05d$:", tlbl->key + 100);
4182 tlbl = newiTempLabel (NULL);
4183 gencjneshort (left, right, tlbl);
4186 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4187 emitcode ("", "%05d$:", tlbl->key + 100);
4191 symbol *lbl = newiTempLabel (NULL);
4192 emitcode ("sjmp", "%05d$", lbl->key + 100);
4193 emitcode ("", "%05d$:", tlbl->key + 100);
4194 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4195 emitcode ("", "%05d$:", lbl->key + 100);
4198 /* mark the icode as generated */
4203 /* if they are both bit variables */
4204 if (AOP_TYPE (left) == AOP_CRY &&
4205 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4207 if (AOP_TYPE (right) == AOP_LIT)
4209 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4212 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4213 emitcode ("cpl", "c");
4217 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4221 emitcode ("clr", "c");
4223 /* AOP_TYPE(right) == AOP_CRY */
4227 symbol *lbl = newiTempLabel (NULL);
4228 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4229 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4230 emitcode ("cpl", "c");
4231 emitcode ("", "%05d$:", (lbl->key + 100));
4234 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4241 genIfxJump (ifx, "c");
4244 /* if the result is used in an arithmetic operation
4245 then put the result in place */
4250 gencjne (left, right, newiTempLabel (NULL));
4251 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4253 aopPut (AOP (result), "a", 0);
4258 genIfxJump (ifx, "a");
4261 /* if the result is used in an arithmetic operation
4262 then put the result in place */
4263 if (AOP_TYPE (result) != AOP_CRY)
4265 /* leave the result in acc */
4269 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4270 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4271 freeAsmop (result, NULL, ic, TRUE);
4274 /*-----------------------------------------------------------------*/
4275 /* ifxForOp - returns the icode containing the ifx for operand */
4276 /*-----------------------------------------------------------------*/
4278 ifxForOp (operand * op, iCode * ic)
4280 /* if true symbol then needs to be assigned */
4281 if (IS_TRUE_SYMOP (op))
4284 /* if this has register type condition and
4285 the next instruction is ifx with the same operand
4286 and live to of the operand is upto the ifx only then */
4288 ic->next->op == IFX &&
4289 IC_COND (ic->next)->key == op->key &&
4290 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4296 /*-----------------------------------------------------------------*/
4297 /* hasInc - operand is incremented before any other use */
4298 /*-----------------------------------------------------------------*/
4300 hasInc (operand *op, iCode *ic)
4302 sym_link *type = operandType(op);
4303 sym_link *retype = getSpec (type);
4304 iCode *lic = ic->next;
4307 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4308 if (!IS_SYMOP(op)) return NULL;
4310 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4311 isize = getSize(type->next);
4313 /* if operand of the form op = op + <sizeof *op> */
4314 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4315 isOperandEqual(IC_RESULT(lic),op) &&
4316 isOperandLiteral(IC_RIGHT(lic)) &&
4317 operandLitValue(IC_RIGHT(lic)) == isize) {
4320 /* if the operand used or deffed */
4321 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4324 /* if GOTO or IFX */
4325 if (lic->op == IFX || lic->op == GOTO) break;
4331 /*-----------------------------------------------------------------*/
4332 /* genAndOp - for && operation */
4333 /*-----------------------------------------------------------------*/
4335 genAndOp (iCode * ic)
4337 operand *left, *right, *result;
4340 D(emitcode (";", "genAndOp"));
4342 /* note here that && operations that are in an
4343 if statement are taken away by backPatchLabels
4344 only those used in arthmetic operations remain */
4345 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4346 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4347 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4349 /* if both are bit variables */
4350 if (AOP_TYPE (left) == AOP_CRY &&
4351 AOP_TYPE (right) == AOP_CRY)
4353 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4354 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4359 tlbl = newiTempLabel (NULL);
4361 emitcode ("jz", "%05d$", tlbl->key + 100);
4363 emitcode ("", "%05d$:", tlbl->key + 100);
4367 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4368 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4369 freeAsmop (result, NULL, ic, TRUE);
4373 /*-----------------------------------------------------------------*/
4374 /* genOrOp - for || operation */
4375 /*-----------------------------------------------------------------*/
4377 genOrOp (iCode * ic)
4379 operand *left, *right, *result;
4382 D(emitcode (";", "genOrOp"));
4384 /* note here that || operations that are in an
4385 if statement are taken away by backPatchLabels
4386 only those used in arthmetic operations remain */
4387 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4388 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4389 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4391 /* if both are bit variables */
4392 if (AOP_TYPE (left) == AOP_CRY &&
4393 AOP_TYPE (right) == AOP_CRY)
4395 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4396 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4401 tlbl = newiTempLabel (NULL);
4403 emitcode ("jnz", "%05d$", tlbl->key + 100);
4405 emitcode ("", "%05d$:", tlbl->key + 100);
4409 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4410 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4411 freeAsmop (result, NULL, ic, TRUE);
4414 /*-----------------------------------------------------------------*/
4415 /* isLiteralBit - test if lit == 2^n */
4416 /*-----------------------------------------------------------------*/
4418 isLiteralBit (unsigned long lit)
4420 unsigned long pw[32] =
4421 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4422 0x100L, 0x200L, 0x400L, 0x800L,
4423 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4424 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4425 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4426 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4427 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4430 for (idx = 0; idx < 32; idx++)
4436 /*-----------------------------------------------------------------*/
4437 /* continueIfTrue - */
4438 /*-----------------------------------------------------------------*/
4440 continueIfTrue (iCode * ic)
4443 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4447 /*-----------------------------------------------------------------*/
4449 /*-----------------------------------------------------------------*/
4451 jumpIfTrue (iCode * ic)
4454 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4458 /*-----------------------------------------------------------------*/
4459 /* jmpTrueOrFalse - */
4460 /*-----------------------------------------------------------------*/
4462 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4464 // ugly but optimized by peephole
4467 symbol *nlbl = newiTempLabel (NULL);
4468 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4469 emitcode ("", "%05d$:", tlbl->key + 100);
4470 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4471 emitcode ("", "%05d$:", nlbl->key + 100);
4475 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4476 emitcode ("", "%05d$:", tlbl->key + 100);
4481 /*-----------------------------------------------------------------*/
4482 /* genAnd - code for and */
4483 /*-----------------------------------------------------------------*/
4485 genAnd (iCode * ic, iCode * ifx)
4487 operand *left, *right, *result;
4488 int size, offset = 0;
4489 unsigned long lit = 0L;
4493 D(emitcode (";", "genAnd"));
4495 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4496 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4497 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4500 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4502 AOP_TYPE (left), AOP_TYPE (right));
4503 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4505 AOP_SIZE (left), AOP_SIZE (right));
4508 /* if left is a literal & right is not then exchange them */
4509 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4510 AOP_NEEDSACC (left))
4512 operand *tmp = right;
4517 /* if result = right then exchange them */
4518 if (sameRegs (AOP (result), AOP (right)))
4520 operand *tmp = right;
4525 /* if right is bit then exchange them */
4526 if (AOP_TYPE (right) == AOP_CRY &&
4527 AOP_TYPE (left) != AOP_CRY)
4529 operand *tmp = right;
4533 if (AOP_TYPE (right) == AOP_LIT)
4534 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4536 size = AOP_SIZE (result);
4539 // result = bit & yy;
4540 if (AOP_TYPE (left) == AOP_CRY)
4542 // c = bit & literal;
4543 if (AOP_TYPE (right) == AOP_LIT)
4547 if (size && sameRegs (AOP (result), AOP (left)))
4550 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4555 if (size && (AOP_TYPE (result) == AOP_CRY))
4557 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4560 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4565 emitcode ("clr", "c");
4570 if (AOP_TYPE (right) == AOP_CRY)
4573 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4574 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4579 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4581 emitcode ("rrc", "a");
4582 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4590 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4591 genIfxJump (ifx, "c");
4595 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4596 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4597 if ((AOP_TYPE (right) == AOP_LIT) &&
4598 (AOP_TYPE (result) == AOP_CRY) &&
4599 (AOP_TYPE (left) != AOP_CRY))
4601 int posbit = isLiteralBit (lit);
4606 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4609 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4615 sprintf (buffer, "acc.%d", posbit & 0x07);
4616 genIfxJump (ifx, buffer);
4623 symbol *tlbl = newiTempLabel (NULL);
4624 int sizel = AOP_SIZE (left);
4626 emitcode ("setb", "c");
4629 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4631 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4633 if ((posbit = isLiteralBit (bytelit)) != 0)
4634 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4637 if (bytelit != 0x0FFL)
4638 emitcode ("anl", "a,%s",
4639 aopGet (AOP (right), offset, FALSE, TRUE));
4640 emitcode ("jnz", "%05d$", tlbl->key + 100);
4645 // bit = left & literal
4648 emitcode ("clr", "c");
4649 emitcode ("", "%05d$:", tlbl->key + 100);
4651 // if(left & literal)
4655 jmpTrueOrFalse (ifx, tlbl);
4663 /* if left is same as result */
4664 if (sameRegs (AOP (result), AOP (left)))
4666 for (; size--; offset++)
4668 if (AOP_TYPE (right) == AOP_LIT)
4670 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4672 else if (bytelit == 0)
4673 aopPut (AOP (result), zero, offset);
4674 else if (IS_AOP_PREG (result))
4676 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4677 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4678 aopPut (AOP (result), "a", offset);
4681 emitcode ("anl", "%s,%s",
4682 aopGet (AOP (left), offset, FALSE, TRUE),
4683 aopGet (AOP (right), offset, FALSE, FALSE));
4687 if (AOP_TYPE (left) == AOP_ACC)
4688 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4691 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4692 if (IS_AOP_PREG (result))
4694 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4695 aopPut (AOP (result), "a", offset);
4699 emitcode ("anl", "%s,a",
4700 aopGet (AOP (left), offset, FALSE, TRUE));
4707 // left & result in different registers
4708 if (AOP_TYPE (result) == AOP_CRY)
4711 // if(size), result in bit
4712 // if(!size && ifx), conditional oper: if(left & right)
4713 symbol *tlbl = newiTempLabel (NULL);
4714 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4716 emitcode ("setb", "c");
4719 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4720 emitcode ("anl", "a,%s",
4721 aopGet (AOP (right), offset, FALSE, FALSE));
4723 if (AOP_TYPE(left)==AOP_ACC) {
4724 emitcode("mov", "b,a");
4725 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4726 emitcode("anl", "a,b");
4728 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4729 emitcode ("anl", "a,%s",
4730 aopGet (AOP (left), offset, FALSE, FALSE));
4733 emitcode ("jnz", "%05d$", tlbl->key + 100);
4739 emitcode ("", "%05d$:", tlbl->key + 100);
4743 jmpTrueOrFalse (ifx, tlbl);
4747 for (; (size--); offset++)
4750 // result = left & right
4751 if (AOP_TYPE (right) == AOP_LIT)
4753 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4755 aopPut (AOP (result),
4756 aopGet (AOP (left), offset, FALSE, FALSE),
4760 else if (bytelit == 0)
4762 aopPut (AOP (result), zero, offset);
4766 // faster than result <- left, anl result,right
4767 // and better if result is SFR
4768 if (AOP_TYPE (left) == AOP_ACC)
4769 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4772 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4773 emitcode ("anl", "a,%s",
4774 aopGet (AOP (left), offset, FALSE, FALSE));
4776 aopPut (AOP (result), "a", offset);
4782 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4783 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4784 freeAsmop (result, NULL, ic, TRUE);
4787 /*-----------------------------------------------------------------*/
4788 /* genOr - code for or */
4789 /*-----------------------------------------------------------------*/
4791 genOr (iCode * ic, iCode * ifx)
4793 operand *left, *right, *result;
4794 int size, offset = 0;
4795 unsigned long lit = 0L;
4797 D(emitcode (";", "genOr"));
4799 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4800 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4801 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4804 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4806 AOP_TYPE (left), AOP_TYPE (right));
4807 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4809 AOP_SIZE (left), AOP_SIZE (right));
4812 /* if left is a literal & right is not then exchange them */
4813 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4814 AOP_NEEDSACC (left))
4816 operand *tmp = right;
4821 /* if result = right then exchange them */
4822 if (sameRegs (AOP (result), AOP (right)))
4824 operand *tmp = right;
4829 /* if right is bit then exchange them */
4830 if (AOP_TYPE (right) == AOP_CRY &&
4831 AOP_TYPE (left) != AOP_CRY)
4833 operand *tmp = right;
4837 if (AOP_TYPE (right) == AOP_LIT)
4838 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4840 size = AOP_SIZE (result);
4844 if (AOP_TYPE (left) == AOP_CRY)
4846 if (AOP_TYPE (right) == AOP_LIT)
4848 // c = bit & literal;
4851 // lit != 0 => result = 1
4852 if (AOP_TYPE (result) == AOP_CRY)
4855 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4857 continueIfTrue (ifx);
4860 emitcode ("setb", "c");
4864 // lit == 0 => result = left
4865 if (size && sameRegs (AOP (result), AOP (left)))
4867 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4872 if (AOP_TYPE (right) == AOP_CRY)
4875 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4876 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4881 symbol *tlbl = newiTempLabel (NULL);
4882 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4883 emitcode ("setb", "c");
4884 emitcode ("jb", "%s,%05d$",
4885 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4887 emitcode ("jnz", "%05d$", tlbl->key + 100);
4888 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4890 jmpTrueOrFalse (ifx, tlbl);
4896 emitcode ("", "%05d$:", tlbl->key + 100);
4905 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4906 genIfxJump (ifx, "c");
4910 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4911 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4912 if ((AOP_TYPE (right) == AOP_LIT) &&
4913 (AOP_TYPE (result) == AOP_CRY) &&
4914 (AOP_TYPE (left) != AOP_CRY))
4920 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4922 continueIfTrue (ifx);
4927 // lit = 0, result = boolean(left)
4929 emitcode ("setb", "c");
4933 symbol *tlbl = newiTempLabel (NULL);
4934 emitcode ("jnz", "%05d$", tlbl->key + 100);
4936 emitcode ("", "%05d$:", tlbl->key + 100);
4940 genIfxJump (ifx, "a");
4948 /* if left is same as result */
4949 if (sameRegs (AOP (result), AOP (left)))
4951 for (; size--; offset++)
4953 if (AOP_TYPE (right) == AOP_LIT)
4955 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4957 else if (IS_AOP_PREG (left))
4959 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4960 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4961 aopPut (AOP (result), "a", offset);
4964 emitcode ("orl", "%s,%s",
4965 aopGet (AOP (left), offset, FALSE, TRUE),
4966 aopGet (AOP (right), offset, FALSE, FALSE));
4970 if (AOP_TYPE (left) == AOP_ACC)
4971 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4974 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4975 if (IS_AOP_PREG (left))
4977 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4978 aopPut (AOP (result), "a", offset);
4981 emitcode ("orl", "%s,a",
4982 aopGet (AOP (left), offset, FALSE, TRUE));
4989 // left & result in different registers
4990 if (AOP_TYPE (result) == AOP_CRY)
4993 // if(size), result in bit
4994 // if(!size && ifx), conditional oper: if(left | right)
4995 symbol *tlbl = newiTempLabel (NULL);
4996 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4998 emitcode ("setb", "c");
5001 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5002 emitcode ("orl", "a,%s",
5003 aopGet (AOP (right), offset, FALSE, FALSE));
5005 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5006 emitcode ("orl", "a,%s",
5007 aopGet (AOP (left), offset, FALSE, FALSE));
5009 emitcode ("jnz", "%05d$", tlbl->key + 100);
5015 emitcode ("", "%05d$:", tlbl->key + 100);
5019 jmpTrueOrFalse (ifx, tlbl);
5022 for (; (size--); offset++)
5025 // result = left & right
5026 if (AOP_TYPE (right) == AOP_LIT)
5028 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5030 aopPut (AOP (result),
5031 aopGet (AOP (left), offset, FALSE, FALSE),
5036 // faster than result <- left, anl result,right
5037 // and better if result is SFR
5038 if (AOP_TYPE (left) == AOP_ACC)
5039 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5042 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5043 emitcode ("orl", "a,%s",
5044 aopGet (AOP (left), offset, FALSE, FALSE));
5046 aopPut (AOP (result), "a", offset);
5051 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5052 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5053 freeAsmop (result, NULL, ic, TRUE);
5056 /*-----------------------------------------------------------------*/
5057 /* genXor - code for xclusive or */
5058 /*-----------------------------------------------------------------*/
5060 genXor (iCode * ic, iCode * ifx)
5062 operand *left, *right, *result;
5063 int size, offset = 0;
5064 unsigned long lit = 0L;
5066 D(emitcode (";", "genXor"));
5068 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5069 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5070 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5073 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5075 AOP_TYPE (left), AOP_TYPE (right));
5076 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5078 AOP_SIZE (left), AOP_SIZE (right));
5081 /* if left is a literal & right is not ||
5082 if left needs acc & right does not */
5083 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5084 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5086 operand *tmp = right;
5091 /* if result = right then exchange them */
5092 if (sameRegs (AOP (result), AOP (right)))
5094 operand *tmp = right;
5099 /* if right is bit then exchange them */
5100 if (AOP_TYPE (right) == AOP_CRY &&
5101 AOP_TYPE (left) != AOP_CRY)
5103 operand *tmp = right;
5107 if (AOP_TYPE (right) == AOP_LIT)
5108 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5110 size = AOP_SIZE (result);
5114 if (AOP_TYPE (left) == AOP_CRY)
5116 if (AOP_TYPE (right) == AOP_LIT)
5118 // c = bit & literal;
5121 // lit>>1 != 0 => result = 1
5122 if (AOP_TYPE (result) == AOP_CRY)
5125 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5127 continueIfTrue (ifx);
5130 emitcode ("setb", "c");
5137 // lit == 0, result = left
5138 if (size && sameRegs (AOP (result), AOP (left)))
5140 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5144 // lit == 1, result = not(left)
5145 if (size && sameRegs (AOP (result), AOP (left)))
5147 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5152 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5153 emitcode ("cpl", "c");
5162 symbol *tlbl = newiTempLabel (NULL);
5163 if (AOP_TYPE (right) == AOP_CRY)
5166 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5170 int sizer = AOP_SIZE (right);
5172 // if val>>1 != 0, result = 1
5173 emitcode ("setb", "c");
5176 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5178 // test the msb of the lsb
5179 emitcode ("anl", "a,#0xfe");
5180 emitcode ("jnz", "%05d$", tlbl->key + 100);
5184 emitcode ("rrc", "a");
5186 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5187 emitcode ("cpl", "c");
5188 emitcode ("", "%05d$:", (tlbl->key + 100));
5195 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5196 genIfxJump (ifx, "c");
5200 if (sameRegs (AOP (result), AOP (left)))
5202 /* if left is same as result */
5203 for (; size--; offset++)
5205 if (AOP_TYPE (right) == AOP_LIT)
5207 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5209 else if (IS_AOP_PREG (left))
5211 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5212 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5213 aopPut (AOP (result), "a", offset);
5216 emitcode ("xrl", "%s,%s",
5217 aopGet (AOP (left), offset, FALSE, TRUE),
5218 aopGet (AOP (right), offset, FALSE, FALSE));
5222 if (AOP_TYPE (left) == AOP_ACC)
5223 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5226 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5227 if (IS_AOP_PREG (left))
5229 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5230 aopPut (AOP (result), "a", offset);
5233 emitcode ("xrl", "%s,a",
5234 aopGet (AOP (left), offset, FALSE, TRUE));
5241 // left & result in different registers
5242 if (AOP_TYPE (result) == AOP_CRY)
5245 // if(size), result in bit
5246 // if(!size && ifx), conditional oper: if(left ^ right)
5247 symbol *tlbl = newiTempLabel (NULL);
5248 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5250 emitcode ("setb", "c");
5253 if ((AOP_TYPE (right) == AOP_LIT) &&
5254 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5256 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5260 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5261 emitcode ("xrl", "a,%s",
5262 aopGet (AOP (right), offset, FALSE, FALSE));
5264 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5265 emitcode ("xrl", "a,%s",
5266 aopGet (AOP (left), offset, FALSE, FALSE));
5269 emitcode ("jnz", "%05d$", tlbl->key + 100);
5275 emitcode ("", "%05d$:", tlbl->key + 100);
5279 jmpTrueOrFalse (ifx, tlbl);
5282 for (; (size--); offset++)
5285 // result = left & right
5286 if (AOP_TYPE (right) == AOP_LIT)
5288 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5290 aopPut (AOP (result),
5291 aopGet (AOP (left), offset, FALSE, FALSE),
5296 // faster than result <- left, anl result,right
5297 // and better if result is SFR
5298 if (AOP_TYPE (left) == AOP_ACC)
5299 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5302 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5303 emitcode ("xrl", "a,%s",
5304 aopGet (AOP (left), offset, FALSE, TRUE));
5306 aopPut (AOP (result), "a", offset);
5311 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5312 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313 freeAsmop (result, NULL, ic, TRUE);
5316 /*-----------------------------------------------------------------*/
5317 /* genInline - write the inline code out */
5318 /*-----------------------------------------------------------------*/
5320 genInline (iCode * ic)
5322 char *buffer, *bp, *bp1;
5324 D(emitcode (";", "genInline"));
5326 _G.inLine += (!options.asmpeep);
5328 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5329 strcpy (buffer, IC_INLINE (ic));
5331 /* emit each line as a code */
5356 /* emitcode("",buffer); */
5357 _G.inLine -= (!options.asmpeep);
5360 /*-----------------------------------------------------------------*/
5361 /* genRRC - rotate right with carry */
5362 /*-----------------------------------------------------------------*/
5366 operand *left, *result;
5367 int size, offset = 0;
5370 D(emitcode (";", "genRRC"));
5372 /* rotate right with carry */
5373 left = IC_LEFT (ic);
5374 result = IC_RESULT (ic);
5375 aopOp (left, ic, FALSE);
5376 aopOp (result, ic, FALSE);
5378 /* move it to the result */
5379 size = AOP_SIZE (result);
5381 if (size == 1) { /* special case for 1 byte */
5382 l = aopGet (AOP (left), offset, FALSE, FALSE);
5384 emitcode ("rr", "a");
5390 l = aopGet (AOP (left), offset, FALSE, FALSE);
5392 emitcode ("rrc", "a");
5393 if (AOP_SIZE (result) > 1)
5394 aopPut (AOP (result), "a", offset--);
5396 /* now we need to put the carry into the
5397 highest order byte of the result */
5398 if (AOP_SIZE (result) > 1)
5400 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5403 emitcode ("mov", "acc.7,c");
5405 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5406 freeAsmop (left, NULL, ic, TRUE);
5407 freeAsmop (result, NULL, ic, TRUE);
5410 /*-----------------------------------------------------------------*/
5411 /* genRLC - generate code for rotate left with carry */
5412 /*-----------------------------------------------------------------*/
5416 operand *left, *result;
5417 int size, offset = 0;
5420 D(emitcode (";", "genRLC"));
5422 /* rotate right with carry */
5423 left = IC_LEFT (ic);
5424 result = IC_RESULT (ic);
5425 aopOp (left, ic, FALSE);
5426 aopOp (result, ic, FALSE);
5428 /* move it to the result */
5429 size = AOP_SIZE (result);
5433 l = aopGet (AOP (left), offset, FALSE, FALSE);
5435 if (size == 0) { /* special case for 1 byte */
5439 emitcode ("add", "a,acc");
5440 if (AOP_SIZE (result) > 1)
5441 aopPut (AOP (result), "a", offset++);
5444 l = aopGet (AOP (left), offset, FALSE, FALSE);
5446 emitcode ("rlc", "a");
5447 if (AOP_SIZE (result) > 1)
5448 aopPut (AOP (result), "a", offset++);
5451 /* now we need to put the carry into the
5452 highest order byte of the result */
5453 if (AOP_SIZE (result) > 1)
5455 l = aopGet (AOP (result), 0, FALSE, FALSE);
5458 emitcode ("mov", "acc.0,c");
5460 aopPut (AOP (result), "a", 0);
5461 freeAsmop (left, NULL, ic, TRUE);
5462 freeAsmop (result, NULL, ic, TRUE);
5465 /*-----------------------------------------------------------------*/
5466 /* genGetHbit - generates code get highest order bit */
5467 /*-----------------------------------------------------------------*/
5469 genGetHbit (iCode * ic)
5471 operand *left, *result;
5473 D(emitcode (";", "genGetHbit"));
5475 left = IC_LEFT (ic);
5476 result = IC_RESULT (ic);
5477 aopOp (left, ic, FALSE);
5478 aopOp (result, ic, FALSE);
5480 /* get the highest order byte into a */
5481 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5482 if (AOP_TYPE (result) == AOP_CRY)
5484 emitcode ("rlc", "a");
5489 emitcode ("rl", "a");
5490 emitcode ("anl", "a,#0x01");
5495 freeAsmop (left, NULL, ic, TRUE);
5496 freeAsmop (result, NULL, ic, TRUE);
5499 /*-----------------------------------------------------------------*/
5500 /* AccRol - rotate left accumulator by known count */
5501 /*-----------------------------------------------------------------*/
5503 AccRol (int shCount)
5505 shCount &= 0x0007; // shCount : 0..7
5512 emitcode ("rl", "a");
5515 emitcode ("rl", "a");
5516 emitcode ("rl", "a");
5519 emitcode ("swap", "a");
5520 emitcode ("rr", "a");
5523 emitcode ("swap", "a");
5526 emitcode ("swap", "a");
5527 emitcode ("rl", "a");
5530 emitcode ("rr", "a");
5531 emitcode ("rr", "a");
5534 emitcode ("rr", "a");
5539 /*-----------------------------------------------------------------*/
5540 /* AccLsh - left shift accumulator by known count */
5541 /*-----------------------------------------------------------------*/
5543 AccLsh (int shCount)
5548 emitcode ("add", "a,acc");
5549 else if (shCount == 2)
5551 emitcode ("add", "a,acc");
5552 emitcode ("add", "a,acc");
5556 /* rotate left accumulator */
5558 /* and kill the lower order bits */
5559 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5564 /*-----------------------------------------------------------------*/
5565 /* AccRsh - right shift accumulator by known count */
5566 /*-----------------------------------------------------------------*/
5568 AccRsh (int shCount)
5575 emitcode ("rrc", "a");
5579 /* rotate right accumulator */
5580 AccRol (8 - shCount);
5581 /* and kill the higher order bits */
5582 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5587 /*-----------------------------------------------------------------*/
5588 /* AccSRsh - signed right shift accumulator by known count */
5589 /*-----------------------------------------------------------------*/
5591 AccSRsh (int shCount)
5598 emitcode ("mov", "c,acc.7");
5599 emitcode ("rrc", "a");
5601 else if (shCount == 2)
5603 emitcode ("mov", "c,acc.7");
5604 emitcode ("rrc", "a");
5605 emitcode ("mov", "c,acc.7");
5606 emitcode ("rrc", "a");
5610 tlbl = newiTempLabel (NULL);
5611 /* rotate right accumulator */
5612 AccRol (8 - shCount);
5613 /* and kill the higher order bits */
5614 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5615 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5616 emitcode ("orl", "a,#0x%02x",
5617 (unsigned char) ~SRMask[shCount]);
5618 emitcode ("", "%05d$:", tlbl->key + 100);
5623 /*-----------------------------------------------------------------*/
5624 /* shiftR1Left2Result - shift right one byte from left to result */
5625 /*-----------------------------------------------------------------*/
5627 shiftR1Left2Result (operand * left, int offl,
5628 operand * result, int offr,
5629 int shCount, int sign)
5631 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5632 /* shift right accumulator */
5637 aopPut (AOP (result), "a", offr);
5640 /*-----------------------------------------------------------------*/
5641 /* shiftL1Left2Result - shift left one byte from left to result */
5642 /*-----------------------------------------------------------------*/
5644 shiftL1Left2Result (operand * left, int offl,
5645 operand * result, int offr, int shCount)
5648 l = aopGet (AOP (left), offl, FALSE, FALSE);
5650 /* shift left accumulator */
5652 aopPut (AOP (result), "a", offr);
5655 /*-----------------------------------------------------------------*/
5656 /* movLeft2Result - move byte from left to result */
5657 /*-----------------------------------------------------------------*/
5659 movLeft2Result (operand * left, int offl,
5660 operand * result, int offr, int sign)
5663 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5665 l = aopGet (AOP (left), offl, FALSE, FALSE);
5667 if (*l == '@' && (IS_AOP_PREG (result)))
5669 emitcode ("mov", "a,%s", l);
5670 aopPut (AOP (result), "a", offr);
5675 aopPut (AOP (result), l, offr);
5678 /* MSB sign in acc.7 ! */
5679 if (getDataSize (left) == offl + 1)
5681 emitcode ("mov", "a,%s", l);
5682 aopPut (AOP (result), "a", offr);
5689 /*-----------------------------------------------------------------*/
5690 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5691 /*-----------------------------------------------------------------*/
5695 emitcode ("rrc", "a");
5696 emitcode ("xch", "a,%s", x);
5697 emitcode ("rrc", "a");
5698 emitcode ("xch", "a,%s", x);
5701 /*-----------------------------------------------------------------*/
5702 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5703 /*-----------------------------------------------------------------*/
5707 emitcode ("xch", "a,%s", x);
5708 emitcode ("rlc", "a");
5709 emitcode ("xch", "a,%s", x);
5710 emitcode ("rlc", "a");
5713 /*-----------------------------------------------------------------*/
5714 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5715 /*-----------------------------------------------------------------*/
5719 emitcode ("xch", "a,%s", x);
5720 emitcode ("add", "a,acc");
5721 emitcode ("xch", "a,%s", x);
5722 emitcode ("rlc", "a");
5725 /*-----------------------------------------------------------------*/
5726 /* AccAXLsh - left shift a:x by known count (0..7) */
5727 /*-----------------------------------------------------------------*/
5729 AccAXLsh (char *x, int shCount)
5744 case 5: // AAAAABBB:CCCCCDDD
5746 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5748 emitcode ("anl", "a,#0x%02x",
5749 SLMask[shCount]); // BBB00000:CCCCCDDD
5751 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5753 AccRol (shCount); // DDDCCCCC:BBB00000
5755 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5757 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5759 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5761 emitcode ("anl", "a,#0x%02x",
5762 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5764 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5766 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5769 case 6: // AAAAAABB:CCCCCCDD
5770 emitcode ("anl", "a,#0x%02x",
5771 SRMask[shCount]); // 000000BB:CCCCCCDD
5772 emitcode ("mov", "c,acc.0"); // c = B
5773 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5775 AccAXRrl1 (x); // BCCCCCCD:D000000B
5776 AccAXRrl1 (x); // BBCCCCCC:DD000000
5778 emitcode("rrc","a");
5779 emitcode("xch","a,%s", x);
5780 emitcode("rrc","a");
5781 emitcode("mov","c,acc.0"); //<< get correct bit
5782 emitcode("xch","a,%s", x);
5784 emitcode("rrc","a");
5785 emitcode("xch","a,%s", x);
5786 emitcode("rrc","a");
5787 emitcode("xch","a,%s", x);
5790 case 7: // a:x <<= 7
5792 emitcode ("anl", "a,#0x%02x",
5793 SRMask[shCount]); // 0000000B:CCCCCCCD
5795 emitcode ("mov", "c,acc.0"); // c = B
5797 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5799 AccAXRrl1 (x); // BCCCCCCC:D0000000
5807 /*-----------------------------------------------------------------*/
5808 /* AccAXRsh - right shift a:x known count (0..7) */
5809 /*-----------------------------------------------------------------*/
5811 AccAXRsh (char *x, int shCount)
5819 AccAXRrl1 (x); // 0->a:x
5824 AccAXRrl1 (x); // 0->a:x
5827 AccAXRrl1 (x); // 0->a:x
5832 case 5: // AAAAABBB:CCCCCDDD = a:x
5834 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5836 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5838 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5840 emitcode ("anl", "a,#0x%02x",
5841 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5843 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5845 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5847 emitcode ("anl", "a,#0x%02x",
5848 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5850 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5852 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5854 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5857 case 6: // AABBBBBB:CCDDDDDD
5859 emitcode ("mov", "c,acc.7");
5860 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5862 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5864 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5866 emitcode ("anl", "a,#0x%02x",
5867 SRMask[shCount]); // 000000AA:BBBBBBCC
5870 case 7: // ABBBBBBB:CDDDDDDD
5872 emitcode ("mov", "c,acc.7"); // c = A
5874 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5876 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5878 emitcode ("anl", "a,#0x%02x",
5879 SRMask[shCount]); // 0000000A:BBBBBBBC
5887 /*-----------------------------------------------------------------*/
5888 /* AccAXRshS - right shift signed a:x known count (0..7) */
5889 /*-----------------------------------------------------------------*/
5891 AccAXRshS (char *x, int shCount)
5899 emitcode ("mov", "c,acc.7");
5900 AccAXRrl1 (x); // s->a:x
5904 emitcode ("mov", "c,acc.7");
5905 AccAXRrl1 (x); // s->a:x
5907 emitcode ("mov", "c,acc.7");
5908 AccAXRrl1 (x); // s->a:x
5913 case 5: // AAAAABBB:CCCCCDDD = a:x
5915 tlbl = newiTempLabel (NULL);
5916 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5918 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5920 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5922 emitcode ("anl", "a,#0x%02x",
5923 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5925 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5927 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5929 emitcode ("anl", "a,#0x%02x",
5930 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5932 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5934 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5936 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5938 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5939 emitcode ("orl", "a,#0x%02x",
5940 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5942 emitcode ("", "%05d$:", tlbl->key + 100);
5943 break; // SSSSAAAA:BBBCCCCC
5945 case 6: // AABBBBBB:CCDDDDDD
5947 tlbl = newiTempLabel (NULL);
5948 emitcode ("mov", "c,acc.7");
5949 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5951 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5953 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5955 emitcode ("anl", "a,#0x%02x",
5956 SRMask[shCount]); // 000000AA:BBBBBBCC
5958 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5959 emitcode ("orl", "a,#0x%02x",
5960 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5962 emitcode ("", "%05d$:", tlbl->key + 100);
5964 case 7: // ABBBBBBB:CDDDDDDD
5966 tlbl = newiTempLabel (NULL);
5967 emitcode ("mov", "c,acc.7"); // c = A
5969 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5971 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5973 emitcode ("anl", "a,#0x%02x",
5974 SRMask[shCount]); // 0000000A:BBBBBBBC
5976 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5977 emitcode ("orl", "a,#0x%02x",
5978 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5980 emitcode ("", "%05d$:", tlbl->key + 100);
5987 /*-----------------------------------------------------------------*/
5988 /* shiftL2Left2Result - shift left two bytes from left to result */
5989 /*-----------------------------------------------------------------*/
5991 shiftL2Left2Result (operand * left, int offl,
5992 operand * result, int offr, int shCount)
5994 if (sameRegs (AOP (result), AOP (left)) &&
5995 ((offl + MSB16) == offr))
5997 /* don't crash result[offr] */
5998 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5999 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6003 movLeft2Result (left, offl, result, offr, 0);
6004 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6006 /* ax << shCount (x = lsb(result)) */
6007 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6008 aopPut (AOP (result), "a", offr + MSB16);
6012 /*-----------------------------------------------------------------*/
6013 /* shiftR2Left2Result - shift right two bytes from left to result */
6014 /*-----------------------------------------------------------------*/
6016 shiftR2Left2Result (operand * left, int offl,
6017 operand * result, int offr,
6018 int shCount, int sign)
6020 if (sameRegs (AOP (result), AOP (left)) &&
6021 ((offl + MSB16) == offr))
6023 /* don't crash result[offr] */
6024 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6025 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6029 movLeft2Result (left, offl, result, offr, 0);
6030 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6032 /* a:x >> shCount (x = lsb(result)) */
6034 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6036 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6037 if (getDataSize (result) > 1)
6038 aopPut (AOP (result), "a", offr + MSB16);
6041 /*-----------------------------------------------------------------*/
6042 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6043 /*-----------------------------------------------------------------*/
6045 shiftLLeftOrResult (operand * left, int offl,
6046 operand * result, int offr, int shCount)
6048 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6049 /* shift left accumulator */
6051 /* or with result */
6052 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6053 /* back to result */
6054 aopPut (AOP (result), "a", offr);
6057 /*-----------------------------------------------------------------*/
6058 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6059 /*-----------------------------------------------------------------*/
6061 shiftRLeftOrResult (operand * left, int offl,
6062 operand * result, int offr, int shCount)
6064 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6065 /* shift right accumulator */
6067 /* or with result */
6068 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6069 /* back to result */
6070 aopPut (AOP (result), "a", offr);
6073 /*-----------------------------------------------------------------*/
6074 /* genlshOne - left shift a one byte quantity by known count */
6075 /*-----------------------------------------------------------------*/
6077 genlshOne (operand * result, operand * left, int shCount)
6079 D(emitcode (";", "genlshOne"));
6081 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6084 /*-----------------------------------------------------------------*/
6085 /* genlshTwo - left shift two bytes by known amount != 0 */
6086 /*-----------------------------------------------------------------*/
6088 genlshTwo (operand * result, operand * left, int shCount)
6092 D(emitcode (";", "genlshTwo"));
6094 size = getDataSize (result);
6096 /* if shCount >= 8 */
6104 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6106 movLeft2Result (left, LSB, result, MSB16, 0);
6108 aopPut (AOP (result), zero, LSB);
6111 /* 1 <= shCount <= 7 */
6115 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6117 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6121 /*-----------------------------------------------------------------*/
6122 /* shiftLLong - shift left one long from left to result */
6123 /* offl = LSB or MSB16 */
6124 /*-----------------------------------------------------------------*/
6126 shiftLLong (operand * left, operand * result, int offr)
6129 int size = AOP_SIZE (result);
6131 if (size >= LSB + offr)
6133 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6135 emitcode ("add", "a,acc");
6136 if (sameRegs (AOP (left), AOP (result)) &&
6137 size >= MSB16 + offr && offr != LSB)
6138 emitcode ("xch", "a,%s",
6139 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6141 aopPut (AOP (result), "a", LSB + offr);
6144 if (size >= MSB16 + offr)
6146 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6148 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6151 emitcode ("rlc", "a");
6152 if (sameRegs (AOP (left), AOP (result)) &&
6153 size >= MSB24 + offr && offr != LSB)
6154 emitcode ("xch", "a,%s",
6155 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6157 aopPut (AOP (result), "a", MSB16 + offr);
6160 if (size >= MSB24 + offr)
6162 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6164 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6167 emitcode ("rlc", "a");
6168 if (sameRegs (AOP (left), AOP (result)) &&
6169 size >= MSB32 + offr && offr != LSB)
6170 emitcode ("xch", "a,%s",
6171 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6173 aopPut (AOP (result), "a", MSB24 + offr);
6176 if (size > MSB32 + offr)
6178 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6180 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6183 emitcode ("rlc", "a");
6184 aopPut (AOP (result), "a", MSB32 + offr);
6187 aopPut (AOP (result), zero, LSB);
6190 /*-----------------------------------------------------------------*/
6191 /* genlshFour - shift four byte by a known amount != 0 */
6192 /*-----------------------------------------------------------------*/
6194 genlshFour (operand * result, operand * left, int shCount)
6198 D(emitcode (";", "genlshFour"));
6200 size = AOP_SIZE (result);
6202 /* if shifting more that 3 bytes */
6207 /* lowest order of left goes to the highest
6208 order of the destination */
6209 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6211 movLeft2Result (left, LSB, result, MSB32, 0);
6212 aopPut (AOP (result), zero, LSB);
6213 aopPut (AOP (result), zero, MSB16);
6214 aopPut (AOP (result), zero, MSB24);
6218 /* more than two bytes */
6219 else if (shCount >= 16)
6221 /* lower order two bytes goes to higher order two bytes */
6223 /* if some more remaining */
6225 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6228 movLeft2Result (left, MSB16, result, MSB32, 0);
6229 movLeft2Result (left, LSB, result, MSB24, 0);
6231 aopPut (AOP (result), zero, MSB16);
6232 aopPut (AOP (result), zero, LSB);
6236 /* if more than 1 byte */
6237 else if (shCount >= 8)
6239 /* lower order three bytes goes to higher order three bytes */
6244 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6246 movLeft2Result (left, LSB, result, MSB16, 0);
6252 movLeft2Result (left, MSB24, result, MSB32, 0);
6253 movLeft2Result (left, MSB16, result, MSB24, 0);
6254 movLeft2Result (left, LSB, result, MSB16, 0);
6255 aopPut (AOP (result), zero, LSB);
6257 else if (shCount == 1)
6258 shiftLLong (left, result, MSB16);
6261 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6262 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6263 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6264 aopPut (AOP (result), zero, LSB);
6269 /* 1 <= shCount <= 7 */
6270 else if (shCount <= 2)
6272 shiftLLong (left, result, LSB);
6274 shiftLLong (result, result, LSB);
6276 /* 3 <= shCount <= 7, optimize */
6279 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6280 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6281 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6285 /*-----------------------------------------------------------------*/
6286 /* genLeftShiftLiteral - left shifting by known count */
6287 /*-----------------------------------------------------------------*/
6289 genLeftShiftLiteral (operand * left,
6294 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6297 D(emitcode (";", "genLeftShiftLiteral"));
6299 freeAsmop (right, NULL, ic, TRUE);
6301 aopOp (left, ic, FALSE);
6302 aopOp (result, ic, FALSE);
6304 size = getSize (operandType (result));
6307 emitcode ("; shift left ", "result %d, left %d", size,
6311 /* I suppose that the left size >= result size */
6316 movLeft2Result (left, size, result, size, 0);
6320 else if (shCount >= (size * 8))
6322 aopPut (AOP (result), zero, size);
6328 genlshOne (result, left, shCount);
6332 genlshTwo (result, left, shCount);
6336 genlshFour (result, left, shCount);
6339 fprintf(stderr, "*** ack! mystery literal shift!\n");
6343 freeAsmop (left, NULL, ic, TRUE);
6344 freeAsmop (result, NULL, ic, TRUE);
6347 /*-----------------------------------------------------------------*/
6348 /* genLeftShift - generates code for left shifting */
6349 /*-----------------------------------------------------------------*/
6351 genLeftShift (iCode * ic)
6353 operand *left, *right, *result;
6356 symbol *tlbl, *tlbl1;
6358 D(emitcode (";", "genLeftShift"));
6360 right = IC_RIGHT (ic);
6361 left = IC_LEFT (ic);
6362 result = IC_RESULT (ic);
6364 aopOp (right, ic, FALSE);
6366 /* if the shift count is known then do it
6367 as efficiently as possible */
6368 if (AOP_TYPE (right) == AOP_LIT)
6370 genLeftShiftLiteral (left, right, result, ic);
6374 /* shift count is unknown then we have to form
6375 a loop get the loop count in B : Note: we take
6376 only the lower order byte since shifting
6377 more that 32 bits make no sense anyway, ( the
6378 largest size of an object can be only 32 bits ) */
6380 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6381 emitcode ("inc", "b");
6382 freeAsmop (right, NULL, ic, TRUE);
6383 aopOp (left, ic, FALSE);
6384 aopOp (result, ic, FALSE);
6386 /* now move the left to the result if they are not the
6388 if (!sameRegs (AOP (left), AOP (result)) &&
6389 AOP_SIZE (result) > 1)
6392 size = AOP_SIZE (result);
6396 l = aopGet (AOP (left), offset, FALSE, TRUE);
6397 if (*l == '@' && (IS_AOP_PREG (result)))
6400 emitcode ("mov", "a,%s", l);
6401 aopPut (AOP (result), "a", offset);
6404 aopPut (AOP (result), l, offset);
6409 tlbl = newiTempLabel (NULL);
6410 size = AOP_SIZE (result);
6412 tlbl1 = newiTempLabel (NULL);
6414 /* if it is only one byte then */
6417 symbol *tlbl1 = newiTempLabel (NULL);
6419 l = aopGet (AOP (left), 0, FALSE, FALSE);
6421 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6422 emitcode ("", "%05d$:", tlbl->key + 100);
6423 emitcode ("add", "a,acc");
6424 emitcode ("", "%05d$:", tlbl1->key + 100);
6425 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6426 aopPut (AOP (result), "a", 0);
6430 reAdjustPreg (AOP (result));
6432 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6433 emitcode ("", "%05d$:", tlbl->key + 100);
6434 l = aopGet (AOP (result), offset, FALSE, FALSE);
6436 emitcode ("add", "a,acc");
6437 aopPut (AOP (result), "a", offset++);
6440 l = aopGet (AOP (result), offset, FALSE, FALSE);
6442 emitcode ("rlc", "a");
6443 aopPut (AOP (result), "a", offset++);
6445 reAdjustPreg (AOP (result));
6447 emitcode ("", "%05d$:", tlbl1->key + 100);
6448 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6450 freeAsmop (left, NULL, ic, TRUE);
6451 freeAsmop (result, NULL, ic, TRUE);
6454 /*-----------------------------------------------------------------*/
6455 /* genrshOne - right shift a one byte quantity by known count */
6456 /*-----------------------------------------------------------------*/
6458 genrshOne (operand * result, operand * left,
6459 int shCount, int sign)
6461 D(emitcode (";", "genrshOne"));
6463 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6466 /*-----------------------------------------------------------------*/
6467 /* genrshTwo - right shift two bytes by known amount != 0 */
6468 /*-----------------------------------------------------------------*/
6470 genrshTwo (operand * result, operand * left,
6471 int shCount, int sign)
6473 D(emitcode (";", "genrshTwo"));
6475 /* if shCount >= 8 */
6480 shiftR1Left2Result (left, MSB16, result, LSB,
6483 movLeft2Result (left, MSB16, result, LSB, sign);
6484 addSign (result, MSB16, sign);
6487 /* 1 <= shCount <= 7 */
6489 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6492 /*-----------------------------------------------------------------*/
6493 /* shiftRLong - shift right one long from left to result */
6494 /* offl = LSB or MSB16 */
6495 /*-----------------------------------------------------------------*/
6497 shiftRLong (operand * left, int offl,
6498 operand * result, int sign)
6500 int isSameRegs=sameRegs(AOP(left),AOP(result));
6502 if (isSameRegs && offl>1) {
6503 // we are in big trouble, but this shouldn't happen
6504 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6507 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6512 emitcode ("rlc", "a");
6513 emitcode ("subb", "a,acc");
6514 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6516 aopPut (AOP(result), zero, MSB32);
6521 emitcode ("clr", "c");
6523 emitcode ("mov", "c,acc.7");
6526 emitcode ("rrc", "a");
6528 if (isSameRegs && offl==MSB16) {
6529 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6531 aopPut (AOP (result), "a", MSB32);
6532 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6535 emitcode ("rrc", "a");
6536 if (isSameRegs && offl==1) {
6537 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6539 aopPut (AOP (result), "a", MSB24);
6540 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6542 emitcode ("rrc", "a");
6543 aopPut (AOP (result), "a", MSB16 - offl);
6547 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6548 emitcode ("rrc", "a");
6549 aopPut (AOP (result), "a", LSB);
6553 /*-----------------------------------------------------------------*/
6554 /* genrshFour - shift four byte by a known amount != 0 */
6555 /*-----------------------------------------------------------------*/
6557 genrshFour (operand * result, operand * left,
6558 int shCount, int sign)
6560 D(emitcode (";", "genrshFour"));
6562 /* if shifting more that 3 bytes */
6567 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6569 movLeft2Result (left, MSB32, result, LSB, sign);
6570 addSign (result, MSB16, sign);
6572 else if (shCount >= 16)
6576 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6579 movLeft2Result (left, MSB24, result, LSB, 0);
6580 movLeft2Result (left, MSB32, result, MSB16, sign);
6582 addSign (result, MSB24, sign);
6584 else if (shCount >= 8)
6588 shiftRLong (left, MSB16, result, sign);
6589 else if (shCount == 0)
6591 movLeft2Result (left, MSB16, result, LSB, 0);
6592 movLeft2Result (left, MSB24, result, MSB16, 0);
6593 movLeft2Result (left, MSB32, result, MSB24, sign);
6594 addSign (result, MSB32, sign);
6598 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6599 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6600 /* the last shift is signed */
6601 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6602 addSign (result, MSB32, sign);
6606 { /* 1 <= shCount <= 7 */
6609 shiftRLong (left, LSB, result, sign);
6611 shiftRLong (result, LSB, result, sign);
6615 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6616 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6617 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6622 /*-----------------------------------------------------------------*/
6623 /* genRightShiftLiteral - right shifting by known count */
6624 /*-----------------------------------------------------------------*/
6626 genRightShiftLiteral (operand * left,
6632 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6635 D(emitcode (";", "genRightShiftLiteral"));
6637 freeAsmop (right, NULL, ic, TRUE);
6639 aopOp (left, ic, FALSE);
6640 aopOp (result, ic, FALSE);
6643 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6647 size = getDataSize (left);
6648 /* test the LEFT size !!! */
6650 /* I suppose that the left size >= result size */
6653 size = getDataSize (result);
6655 movLeft2Result (left, size, result, size, 0);
6658 else if (shCount >= (size * 8))
6661 /* get sign in acc.7 */
6662 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6663 addSign (result, LSB, sign);
6670 genrshOne (result, left, shCount, sign);
6674 genrshTwo (result, left, shCount, sign);
6678 genrshFour (result, left, shCount, sign);
6684 freeAsmop (left, NULL, ic, TRUE);
6685 freeAsmop (result, NULL, ic, TRUE);
6689 /*-----------------------------------------------------------------*/
6690 /* genSignedRightShift - right shift of signed number */
6691 /*-----------------------------------------------------------------*/
6693 genSignedRightShift (iCode * ic)
6695 operand *right, *left, *result;
6698 symbol *tlbl, *tlbl1;
6700 D(emitcode (";", "genSignedRightShift"));
6702 /* we do it the hard way put the shift count in b
6703 and loop thru preserving the sign */
6705 right = IC_RIGHT (ic);
6706 left = IC_LEFT (ic);
6707 result = IC_RESULT (ic);
6709 aopOp (right, ic, FALSE);
6712 if (AOP_TYPE (right) == AOP_LIT)
6714 genRightShiftLiteral (left, right, result, ic, 1);
6717 /* shift count is unknown then we have to form
6718 a loop get the loop count in B : Note: we take
6719 only the lower order byte since shifting
6720 more that 32 bits make no sense anyway, ( the
6721 largest size of an object can be only 32 bits ) */
6723 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6724 emitcode ("inc", "b");
6725 freeAsmop (right, NULL, ic, TRUE);
6726 aopOp (left, ic, FALSE);
6727 aopOp (result, ic, FALSE);
6729 /* now move the left to the result if they are not the
6731 if (!sameRegs (AOP (left), AOP (result)) &&
6732 AOP_SIZE (result) > 1)
6735 size = AOP_SIZE (result);
6739 l = aopGet (AOP (left), offset, FALSE, TRUE);
6740 if (*l == '@' && IS_AOP_PREG (result))
6743 emitcode ("mov", "a,%s", l);
6744 aopPut (AOP (result), "a", offset);
6747 aopPut (AOP (result), l, offset);
6752 /* mov the highest order bit to OVR */
6753 tlbl = newiTempLabel (NULL);
6754 tlbl1 = newiTempLabel (NULL);
6756 size = AOP_SIZE (result);
6758 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6759 emitcode ("rlc", "a");
6760 emitcode ("mov", "ov,c");
6761 /* if it is only one byte then */
6764 l = aopGet (AOP (left), 0, FALSE, FALSE);
6766 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6767 emitcode ("", "%05d$:", tlbl->key + 100);
6768 emitcode ("mov", "c,ov");
6769 emitcode ("rrc", "a");
6770 emitcode ("", "%05d$:", tlbl1->key + 100);
6771 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6772 aopPut (AOP (result), "a", 0);
6776 reAdjustPreg (AOP (result));
6777 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6778 emitcode ("", "%05d$:", tlbl->key + 100);
6779 emitcode ("mov", "c,ov");
6782 l = aopGet (AOP (result), offset, FALSE, FALSE);
6784 emitcode ("rrc", "a");
6785 aopPut (AOP (result), "a", offset--);
6787 reAdjustPreg (AOP (result));
6788 emitcode ("", "%05d$:", tlbl1->key + 100);
6789 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6792 freeAsmop (left, NULL, ic, TRUE);
6793 freeAsmop (result, NULL, ic, TRUE);
6796 /*-----------------------------------------------------------------*/
6797 /* genRightShift - generate code for right shifting */
6798 /*-----------------------------------------------------------------*/
6800 genRightShift (iCode * ic)
6802 operand *right, *left, *result;
6806 symbol *tlbl, *tlbl1;
6808 D(emitcode (";", "genRightShift"));
6810 /* if signed then we do it the hard way preserve the
6811 sign bit moving it inwards */
6812 retype = getSpec (operandType (IC_RESULT (ic)));
6814 if (!SPEC_USIGN (retype))
6816 genSignedRightShift (ic);
6820 /* signed & unsigned types are treated the same : i.e. the
6821 signed is NOT propagated inwards : quoting from the
6822 ANSI - standard : "for E1 >> E2, is equivalent to division
6823 by 2**E2 if unsigned or if it has a non-negative value,
6824 otherwise the result is implementation defined ", MY definition
6825 is that the sign does not get propagated */
6827 right = IC_RIGHT (ic);
6828 left = IC_LEFT (ic);
6829 result = IC_RESULT (ic);
6831 aopOp (right, ic, FALSE);
6833 /* if the shift count is known then do it
6834 as efficiently as possible */
6835 if (AOP_TYPE (right) == AOP_LIT)
6837 genRightShiftLiteral (left, right, result, ic, 0);
6841 /* shift count is unknown then we have to form
6842 a loop get the loop count in B : Note: we take
6843 only the lower order byte since shifting
6844 more that 32 bits make no sense anyway, ( the
6845 largest size of an object can be only 32 bits ) */
6847 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6848 emitcode ("inc", "b");
6849 freeAsmop (right, NULL, ic, TRUE);
6850 aopOp (left, ic, FALSE);
6851 aopOp (result, ic, FALSE);
6853 /* now move the left to the result if they are not the
6855 if (!sameRegs (AOP (left), AOP (result)) &&
6856 AOP_SIZE (result) > 1)
6859 size = AOP_SIZE (result);
6863 l = aopGet (AOP (left), offset, FALSE, TRUE);
6864 if (*l == '@' && IS_AOP_PREG (result))
6867 emitcode ("mov", "a,%s", l);
6868 aopPut (AOP (result), "a", offset);
6871 aopPut (AOP (result), l, offset);
6876 tlbl = newiTempLabel (NULL);
6877 tlbl1 = newiTempLabel (NULL);
6878 size = AOP_SIZE (result);
6881 /* if it is only one byte then */
6884 l = aopGet (AOP (left), 0, FALSE, FALSE);
6886 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6887 emitcode ("", "%05d$:", tlbl->key + 100);
6889 emitcode ("rrc", "a");
6890 emitcode ("", "%05d$:", tlbl1->key + 100);
6891 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6892 aopPut (AOP (result), "a", 0);
6896 reAdjustPreg (AOP (result));
6897 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6898 emitcode ("", "%05d$:", tlbl->key + 100);
6902 l = aopGet (AOP (result), offset, FALSE, FALSE);
6904 emitcode ("rrc", "a");
6905 aopPut (AOP (result), "a", offset--);
6907 reAdjustPreg (AOP (result));
6909 emitcode ("", "%05d$:", tlbl1->key + 100);
6910 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6913 freeAsmop (left, NULL, ic, TRUE);
6914 freeAsmop (result, NULL, ic, TRUE);
6917 /*-----------------------------------------------------------------*/
6918 /* genUnpackBits - generates code for unpacking bits */
6919 /*-----------------------------------------------------------------*/
6921 genUnpackBits (operand * result, char *rname, int ptype)
6929 D(emitcode (";", "genUnpackBits"));
6931 etype = getSpec (operandType (result));
6932 rsize = getSize (operandType (result));
6933 /* read the first byte */
6939 emitcode ("mov", "a,@%s", rname);
6943 emitcode ("movx", "a,@%s", rname);
6947 emitcode ("movx", "a,@dptr");
6951 emitcode ("clr", "a");
6952 emitcode ("movc", "a,@a+dptr");
6956 emitcode ("lcall", "__gptrget");
6960 rlen = SPEC_BLEN (etype);
6962 /* if we have bitdisplacement then it fits */
6963 /* into this byte completely or if length is */
6964 /* less than a byte */
6965 if ((shCnt = SPEC_BSTR (etype)) ||
6966 (SPEC_BLEN (etype) <= 8))
6969 /* shift right acc */
6972 emitcode ("anl", "a,#0x%02x",
6973 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6974 aopPut (AOP (result), "a", offset++);
6978 /* bit field did not fit in a byte */
6979 aopPut (AOP (result), "a", offset++);
6988 emitcode ("inc", "%s", rname);
6989 emitcode ("mov", "a,@%s", rname);
6993 emitcode ("inc", "%s", rname);
6994 emitcode ("movx", "a,@%s", rname);
6998 emitcode ("inc", "dptr");
6999 emitcode ("movx", "a,@dptr");
7003 emitcode ("clr", "a");
7004 emitcode ("inc", "dptr");
7005 emitcode ("movc", "a,@a+dptr");
7009 emitcode ("inc", "dptr");
7010 emitcode ("lcall", "__gptrget");
7015 /* if we are done */
7019 aopPut (AOP (result), "a", offset++);
7025 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7027 aopPut (AOP (result), "a", offset++);
7035 aopPut (AOP (result), zero, offset++);
7041 /*-----------------------------------------------------------------*/
7042 /* genDataPointerGet - generates code when ptr offset is known */
7043 /*-----------------------------------------------------------------*/
7045 genDataPointerGet (operand * left,
7051 int size, offset = 0;
7053 D(emitcode (";", "genDataPointerGet"));
7055 aopOp (result, ic, TRUE);
7057 /* get the string representation of the name */
7058 l = aopGet (AOP (left), 0, FALSE, TRUE);
7059 size = AOP_SIZE (result);
7063 sprintf (buffer, "(%s + %d)", l + 1, offset);
7065 sprintf (buffer, "%s", l + 1);
7066 aopPut (AOP (result), buffer, offset++);
7069 freeAsmop (left, NULL, ic, TRUE);
7070 freeAsmop (result, NULL, ic, TRUE);
7073 /*-----------------------------------------------------------------*/
7074 /* genNearPointerGet - emitcode for near pointer fetch */
7075 /*-----------------------------------------------------------------*/
7077 genNearPointerGet (operand * left,
7085 sym_link *rtype, *retype;
7086 sym_link *ltype = operandType (left);
7089 D(emitcode (";", "genNearPointerGet"));
7091 rtype = operandType (result);
7092 retype = getSpec (rtype);
7094 aopOp (left, ic, FALSE);
7096 /* if left is rematerialisable and
7097 result is not bit variable type and
7098 the left is pointer to data space i.e
7099 lower 128 bytes of space */
7100 if (AOP_TYPE (left) == AOP_IMMD &&
7101 !IS_BITVAR (retype) &&
7102 DCL_TYPE (ltype) == POINTER)
7104 genDataPointerGet (left, result, ic);
7108 /* if the value is already in a pointer register
7109 then don't need anything more */
7110 if (!AOP_INPREG (AOP (left)))
7112 /* otherwise get a free pointer register */
7114 preg = getFreePtr (ic, &aop, FALSE);
7115 emitcode ("mov", "%s,%s",
7117 aopGet (AOP (left), 0, FALSE, TRUE));
7121 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7123 //aopOp (result, ic, FALSE);
7124 aopOp (result, ic, result?TRUE:FALSE);
7126 /* if bitfield then unpack the bits */
7127 if (IS_BITVAR (retype))
7128 genUnpackBits (result, rname, POINTER);
7131 /* we have can just get the values */
7132 int size = AOP_SIZE (result);
7137 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7140 emitcode ("mov", "a,@%s", rname);
7141 aopPut (AOP (result), "a", offset);
7145 sprintf (buffer, "@%s", rname);
7146 aopPut (AOP (result), buffer, offset);
7150 emitcode ("inc", "%s", rname);
7154 /* now some housekeeping stuff */
7155 if (aop) /* we had to allocate for this iCode */
7157 if (pi) { /* post increment present */
7158 aopPut(AOP ( left ),rname,0);
7160 freeAsmop (NULL, aop, ic, TRUE);
7164 /* we did not allocate which means left
7165 already in a pointer register, then
7166 if size > 0 && this could be used again
7167 we have to point it back to where it
7169 if ((AOP_SIZE (result) > 1 &&
7170 !OP_SYMBOL (left)->remat &&
7171 (OP_SYMBOL (left)->liveTo > ic->seq ||
7175 int size = AOP_SIZE (result) - 1;
7177 emitcode ("dec", "%s", rname);
7182 freeAsmop (left, NULL, ic, TRUE);
7183 freeAsmop (result, NULL, ic, TRUE);
7184 if (pi) pi->generated = 1;
7187 /*-----------------------------------------------------------------*/
7188 /* genPagedPointerGet - emitcode for paged pointer fetch */
7189 /*-----------------------------------------------------------------*/
7191 genPagedPointerGet (operand * left,
7199 sym_link *rtype, *retype;
7201 D(emitcode (";", "genPagedPointerGet"));
7203 rtype = operandType (result);
7204 retype = getSpec (rtype);
7206 aopOp (left, ic, FALSE);
7208 /* if the value is already in a pointer register
7209 then don't need anything more */
7210 if (!AOP_INPREG (AOP (left)))
7212 /* otherwise get a free pointer register */
7214 preg = getFreePtr (ic, &aop, FALSE);
7215 emitcode ("mov", "%s,%s",
7217 aopGet (AOP (left), 0, FALSE, TRUE));
7221 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7223 aopOp (result, ic, FALSE);
7225 /* if bitfield then unpack the bits */
7226 if (IS_BITVAR (retype))
7227 genUnpackBits (result, rname, PPOINTER);
7230 /* we have can just get the values */
7231 int size = AOP_SIZE (result);
7237 emitcode ("movx", "a,@%s", rname);
7238 aopPut (AOP (result), "a", offset);
7243 emitcode ("inc", "%s", rname);
7247 /* now some housekeeping stuff */
7248 if (aop) /* we had to allocate for this iCode */
7250 if (pi) aopPut ( AOP (left), rname, 0);
7251 freeAsmop (NULL, aop, ic, TRUE);
7255 /* we did not allocate which means left
7256 already in a pointer register, then
7257 if size > 0 && this could be used again
7258 we have to point it back to where it
7260 if ((AOP_SIZE (result) > 1 &&
7261 !OP_SYMBOL (left)->remat &&
7262 (OP_SYMBOL (left)->liveTo > ic->seq ||
7266 int size = AOP_SIZE (result) - 1;
7268 emitcode ("dec", "%s", rname);
7273 freeAsmop (left, NULL, ic, TRUE);
7274 freeAsmop (result, NULL, ic, TRUE);
7275 if (pi) pi->generated = 1;
7279 /*-----------------------------------------------------------------*/
7280 /* genFarPointerGet - gget value from far space */
7281 /*-----------------------------------------------------------------*/
7283 genFarPointerGet (operand * left,
7284 operand * result, iCode * ic, iCode * pi)
7287 sym_link *retype = getSpec (operandType (result));
7289 D(emitcode (";", "genFarPointerGet"));
7291 aopOp (left, ic, FALSE);
7293 /* if the operand is already in dptr
7294 then we do nothing else we move the value to dptr */
7295 if (AOP_TYPE (left) != AOP_STR)
7297 /* if this is remateriazable */
7298 if (AOP_TYPE (left) == AOP_IMMD)
7299 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7301 { /* we need to get it byte by byte */
7302 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7303 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7306 /* so dptr know contains the address */
7307 aopOp (result, ic, FALSE);
7309 /* if bit then unpack */
7310 if (IS_BITVAR (retype))
7311 genUnpackBits (result, "dptr", FPOINTER);
7314 size = AOP_SIZE (result);
7319 emitcode ("movx", "a,@dptr");
7320 aopPut (AOP (result), "a", offset++);
7322 emitcode ("inc", "dptr");
7326 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7327 aopPut ( AOP (left), "dpl", 0);
7328 aopPut ( AOP (left), "dph", 1);
7331 freeAsmop (left, NULL, ic, TRUE);
7332 freeAsmop (result, NULL, ic, TRUE);
7335 /*-----------------------------------------------------------------*/
7336 /* genCodePointerGet - gget value from code space */
7337 /*-----------------------------------------------------------------*/
7339 genCodePointerGet (operand * left,
7340 operand * result, iCode * ic, iCode *pi)
7343 sym_link *retype = getSpec (operandType (result));
7345 D(emitcode (";", "genCodePointerGet"));
7347 aopOp (left, ic, FALSE);
7349 /* if the operand is already in dptr
7350 then we do nothing else we move the value to dptr */
7351 if (AOP_TYPE (left) != AOP_STR)
7353 /* if this is remateriazable */
7354 if (AOP_TYPE (left) == AOP_IMMD)
7355 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7357 { /* we need to get it byte by byte */
7358 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7359 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7362 /* so dptr know contains the address */
7363 aopOp (result, ic, FALSE);
7365 /* if bit then unpack */
7366 if (IS_BITVAR (retype))
7367 genUnpackBits (result, "dptr", CPOINTER);
7370 size = AOP_SIZE (result);
7375 emitcode ("clr", "a");
7376 emitcode ("movc", "a,@a+dptr");
7377 aopPut (AOP (result), "a", offset++);
7379 emitcode ("inc", "dptr");
7383 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7384 aopPut ( AOP (left), "dpl", 0);
7385 aopPut ( AOP (left), "dph", 1);
7388 freeAsmop (left, NULL, ic, TRUE);
7389 freeAsmop (result, NULL, ic, TRUE);
7392 /*-----------------------------------------------------------------*/
7393 /* genGenPointerGet - gget value from generic pointer space */
7394 /*-----------------------------------------------------------------*/
7396 genGenPointerGet (operand * left,
7397 operand * result, iCode * ic, iCode *pi)
7400 sym_link *retype = getSpec (operandType (result));
7402 D(emitcode (";", "genGenPointerGet"));
7404 aopOp (left, ic, FALSE);
7406 /* if the operand is already in dptr
7407 then we do nothing else we move the value to dptr */
7408 if (AOP_TYPE (left) != AOP_STR)
7410 /* if this is remateriazable */
7411 if (AOP_TYPE (left) == AOP_IMMD)
7413 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7414 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7415 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7417 emitcode ("mov", "b,#%d", pointerCode (retype));
7420 { /* we need to get it byte by byte */
7421 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7422 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7423 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7426 /* so dptr know contains the address */
7427 aopOp (result, ic, FALSE);
7429 /* if bit then unpack */
7430 if (IS_BITVAR (retype))
7431 genUnpackBits (result, "dptr", GPOINTER);
7434 size = AOP_SIZE (result);
7439 emitcode ("lcall", "__gptrget");
7440 aopPut (AOP (result), "a", offset++);
7442 emitcode ("inc", "dptr");
7446 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7447 aopPut ( AOP (left), "dpl", 0);
7448 aopPut ( AOP (left), "dph", 1);
7449 aopPut ( AOP (left), "b", 2);
7452 freeAsmop (left, NULL, ic, TRUE);
7453 freeAsmop (result, NULL, ic, TRUE);
7456 /*-----------------------------------------------------------------*/
7457 /* genPointerGet - generate code for pointer get */
7458 /*-----------------------------------------------------------------*/
7460 genPointerGet (iCode * ic, iCode *pi)
7462 operand *left, *result;
7463 sym_link *type, *etype;
7466 D(emitcode (";", "genPointerGet"));
7468 left = IC_LEFT (ic);
7469 result = IC_RESULT (ic);
7471 /* depending on the type of pointer we need to
7472 move it to the correct pointer register */
7473 type = operandType (left);
7474 etype = getSpec (type);
7475 /* if left is of type of pointer then it is simple */
7476 if (IS_PTR (type) && !IS_FUNC (type->next))
7477 p_type = DCL_TYPE (type);
7480 /* we have to go by the storage class */
7481 p_type = PTR_TYPE (SPEC_OCLS (etype));
7484 /* special case when cast remat */
7485 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7486 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7487 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7488 type = type = operandType (left);
7489 p_type = DCL_TYPE (type);
7491 /* now that we have the pointer type we assign
7492 the pointer values */
7498 genNearPointerGet (left, result, ic, pi);
7502 genPagedPointerGet (left, result, ic, pi);
7506 genFarPointerGet (left, result, ic, pi);
7510 genCodePointerGet (left, result, ic, pi);
7514 genGenPointerGet (left, result, ic, pi);
7520 /*-----------------------------------------------------------------*/
7521 /* genPackBits - generates code for packed bit storage */
7522 /*-----------------------------------------------------------------*/
7524 genPackBits (sym_link * etype,
7526 char *rname, int p_type)
7534 D(emitcode (";", "genPackBits"));
7536 blen = SPEC_BLEN (etype);
7537 bstr = SPEC_BSTR (etype);
7539 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7542 /* if the bit lenth is less than or */
7543 /* it exactly fits a byte then */
7544 if (SPEC_BLEN (etype) <= 8)
7546 shCount = SPEC_BSTR (etype);
7548 /* shift left acc */
7551 if (SPEC_BLEN (etype) < 8)
7552 { /* if smaller than a byte */
7558 emitcode ("mov", "b,a");
7559 emitcode ("mov", "a,@%s", rname);
7563 emitcode ("mov", "b,a");
7564 emitcode ("movx", "a,@dptr");
7568 emitcode ("push", "b");
7569 emitcode ("push", "acc");
7570 emitcode ("lcall", "__gptrget");
7571 emitcode ("pop", "b");
7575 emitcode ("anl", "a,#0x%02x", (unsigned char)
7576 ((unsigned char) (0xFF << (blen + bstr)) |
7577 (unsigned char) (0xFF >> (8 - bstr))));
7578 emitcode ("orl", "a,b");
7579 if (p_type == GPOINTER)
7580 emitcode ("pop", "b");
7587 emitcode ("mov", "@%s,a", rname);
7591 emitcode ("movx", "@dptr,a");
7595 emitcode ("lcall", "__gptrput");
7600 if (SPEC_BLEN (etype) <= 8)
7603 emitcode ("inc", "%s", rname);
7604 rLen = SPEC_BLEN (etype);
7606 /* now generate for lengths greater than one byte */
7610 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7622 emitcode ("mov", "@%s,a", rname);
7625 emitcode ("mov", "@%s,%s", rname, l);
7630 emitcode ("movx", "@dptr,a");
7635 emitcode ("lcall", "__gptrput");
7638 emitcode ("inc", "%s", rname);
7643 /* last last was not complete */
7646 /* save the byte & read byte */
7650 emitcode ("mov", "b,a");
7651 emitcode ("mov", "a,@%s", rname);
7655 emitcode ("mov", "b,a");
7656 emitcode ("movx", "a,@dptr");
7660 emitcode ("push", "b");
7661 emitcode ("push", "acc");
7662 emitcode ("lcall", "__gptrget");
7663 emitcode ("pop", "b");
7667 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7668 emitcode ("orl", "a,b");
7671 if (p_type == GPOINTER)
7672 emitcode ("pop", "b");
7678 emitcode ("mov", "@%s,a", rname);
7682 emitcode ("movx", "@dptr,a");
7686 emitcode ("lcall", "__gptrput");
7690 /*-----------------------------------------------------------------*/
7691 /* genDataPointerSet - remat pointer to data space */
7692 /*-----------------------------------------------------------------*/
7694 genDataPointerSet (operand * right,
7698 int size, offset = 0;
7699 char *l, buffer[256];
7701 D(emitcode (";", "genDataPointerSet"));
7703 aopOp (right, ic, FALSE);
7705 l = aopGet (AOP (result), 0, FALSE, TRUE);
7706 size = AOP_SIZE (right);
7710 sprintf (buffer, "(%s + %d)", l + 1, offset);
7712 sprintf (buffer, "%s", l + 1);
7713 emitcode ("mov", "%s,%s", buffer,
7714 aopGet (AOP (right), offset++, FALSE, FALSE));
7717 freeAsmop (right, NULL, ic, TRUE);
7718 freeAsmop (result, NULL, ic, TRUE);
7721 /*-----------------------------------------------------------------*/
7722 /* genNearPointerSet - emitcode for near pointer put */
7723 /*-----------------------------------------------------------------*/
7725 genNearPointerSet (operand * right,
7733 sym_link *retype, *letype;
7734 sym_link *ptype = operandType (result);
7736 D(emitcode (";", "genNearPointerSet"));
7738 retype = getSpec (operandType (right));
7739 letype = getSpec (ptype);
7740 aopOp (result, ic, FALSE);
7742 /* if the result is rematerializable &
7743 in data space & not a bit variable */
7744 if (AOP_TYPE (result) == AOP_IMMD &&
7745 DCL_TYPE (ptype) == POINTER &&
7746 !IS_BITVAR (retype) &&
7747 !IS_BITVAR (letype))
7749 genDataPointerSet (right, result, ic);
7753 /* if the value is already in a pointer register
7754 then don't need anything more */
7755 if (!AOP_INPREG (AOP (result)))
7758 //AOP_TYPE (result) == AOP_STK
7762 // Aha, it is a pointer, just in disguise.
7763 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7766 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7767 __FILE__, __LINE__);
7772 rname++; // skip the '@'.
7777 /* otherwise get a free pointer register */
7779 preg = getFreePtr (ic, &aop, FALSE);
7780 emitcode ("mov", "%s,%s",
7782 aopGet (AOP (result), 0, FALSE, TRUE));
7788 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7791 aopOp (right, ic, FALSE);
7793 /* if bitfield then unpack the bits */
7794 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7795 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7798 /* we have can just get the values */
7799 int size = AOP_SIZE (right);
7804 l = aopGet (AOP (right), offset, FALSE, TRUE);
7808 emitcode ("mov", "@%s,a", rname);
7811 emitcode ("mov", "@%s,%s", rname, l);
7813 emitcode ("inc", "%s", rname);
7818 /* now some housekeeping stuff */
7819 if (aop) /* we had to allocate for this iCode */
7821 if (pi) aopPut (AOP (result),rname,0);
7822 freeAsmop (NULL, aop, ic, TRUE);
7826 /* we did not allocate which means left
7827 already in a pointer register, then
7828 if size > 0 && this could be used again
7829 we have to point it back to where it
7831 if ((AOP_SIZE (right) > 1 &&
7832 !OP_SYMBOL (result)->remat &&
7833 (OP_SYMBOL (result)->liveTo > ic->seq ||
7837 int size = AOP_SIZE (right) - 1;
7839 emitcode ("dec", "%s", rname);
7844 if (pi) pi->generated = 1;
7845 freeAsmop (result, NULL, ic, TRUE);
7846 freeAsmop (right, NULL, ic, TRUE);
7849 /*-----------------------------------------------------------------*/
7850 /* genPagedPointerSet - emitcode for Paged pointer put */
7851 /*-----------------------------------------------------------------*/
7853 genPagedPointerSet (operand * right,
7861 sym_link *retype, *letype;
7863 D(emitcode (";", "genPagedPointerSet"));
7865 retype = getSpec (operandType (right));
7866 letype = getSpec (operandType (result));
7868 aopOp (result, ic, FALSE);
7870 /* if the value is already in a pointer register
7871 then don't need anything more */
7872 if (!AOP_INPREG (AOP (result)))
7874 /* otherwise get a free pointer register */
7876 preg = getFreePtr (ic, &aop, FALSE);
7877 emitcode ("mov", "%s,%s",
7879 aopGet (AOP (result), 0, FALSE, TRUE));
7883 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7885 aopOp (right, ic, FALSE);
7887 /* if bitfield then unpack the bits */
7888 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7889 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7892 /* we have can just get the values */
7893 int size = AOP_SIZE (right);
7898 l = aopGet (AOP (right), offset, FALSE, TRUE);
7901 emitcode ("movx", "@%s,a", rname);
7904 emitcode ("inc", "%s", rname);
7910 /* now some housekeeping stuff */
7911 if (aop) /* we had to allocate for this iCode */
7913 if (pi) aopPut (AOP (result),rname,0);
7914 freeAsmop (NULL, aop, ic, TRUE);
7918 /* we did not allocate which means left
7919 already in a pointer register, then
7920 if size > 0 && this could be used again
7921 we have to point it back to where it
7923 if (AOP_SIZE (right) > 1 &&
7924 !OP_SYMBOL (result)->remat &&
7925 (OP_SYMBOL (result)->liveTo > ic->seq ||
7928 int size = AOP_SIZE (right) - 1;
7930 emitcode ("dec", "%s", rname);
7935 if (pi) pi->generated = 1;
7936 freeAsmop (result, NULL, ic, TRUE);
7937 freeAsmop (right, NULL, ic, TRUE);
7942 /*-----------------------------------------------------------------*/
7943 /* genFarPointerSet - set value from far space */
7944 /*-----------------------------------------------------------------*/
7946 genFarPointerSet (operand * right,
7947 operand * result, iCode * ic, iCode * pi)
7950 sym_link *retype = getSpec (operandType (right));
7951 sym_link *letype = getSpec (operandType (result));
7953 D(emitcode (";", "genFarPointerSet"));
7955 aopOp (result, ic, FALSE);
7957 /* if the operand is already in dptr
7958 then we do nothing else we move the value to dptr */
7959 if (AOP_TYPE (result) != AOP_STR)
7961 /* if this is remateriazable */
7962 if (AOP_TYPE (result) == AOP_IMMD)
7963 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7965 { /* we need to get it byte by byte */
7966 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7967 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7970 /* so dptr know contains the address */
7971 aopOp (right, ic, FALSE);
7973 /* if bit then unpack */
7974 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7975 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7978 size = AOP_SIZE (right);
7983 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7985 emitcode ("movx", "@dptr,a");
7987 emitcode ("inc", "dptr");
7990 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7991 aopPut (AOP(result),"dpl",0);
7992 aopPut (AOP(result),"dph",1);
7995 freeAsmop (result, NULL, ic, TRUE);
7996 freeAsmop (right, NULL, ic, TRUE);
7999 /*-----------------------------------------------------------------*/
8000 /* genGenPointerSet - set value from generic pointer space */
8001 /*-----------------------------------------------------------------*/
8003 genGenPointerSet (operand * right,
8004 operand * result, iCode * ic, iCode * pi)
8007 sym_link *retype = getSpec (operandType (right));
8008 sym_link *letype = getSpec (operandType (result));
8010 D(emitcode (";", "genGenPointerSet"));
8012 aopOp (result, ic, FALSE);
8014 /* if the operand is already in dptr
8015 then we do nothing else we move the value to dptr */
8016 if (AOP_TYPE (result) != AOP_STR)
8018 /* if this is remateriazable */
8019 if (AOP_TYPE (result) == AOP_IMMD)
8021 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8022 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8023 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8025 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8028 { /* we need to get it byte by byte */
8029 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8030 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8031 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8034 /* so dptr know contains the address */
8035 aopOp (right, ic, FALSE);
8037 /* if bit then unpack */
8038 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8039 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8042 size = AOP_SIZE (right);
8047 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8049 emitcode ("lcall", "__gptrput");
8051 emitcode ("inc", "dptr");
8055 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8056 aopPut (AOP(result),"dpl",0);
8057 aopPut (AOP(result),"dph",1);
8058 aopPut (AOP(result),"b",2);
8061 freeAsmop (result, NULL, ic, TRUE);
8062 freeAsmop (right, NULL, ic, TRUE);
8065 /*-----------------------------------------------------------------*/
8066 /* genPointerSet - stores the value into a pointer location */
8067 /*-----------------------------------------------------------------*/
8069 genPointerSet (iCode * ic, iCode *pi)
8071 operand *right, *result;
8072 sym_link *type, *etype;
8075 D(emitcode (";", "genPointerSet"));
8077 right = IC_RIGHT (ic);
8078 result = IC_RESULT (ic);
8080 /* depending on the type of pointer we need to
8081 move it to the correct pointer register */
8082 type = operandType (result);
8083 etype = getSpec (type);
8084 /* if left is of type of pointer then it is simple */
8085 if (IS_PTR (type) && !IS_FUNC (type->next))
8087 p_type = DCL_TYPE (type);
8091 /* we have to go by the storage class */
8092 p_type = PTR_TYPE (SPEC_OCLS (etype));
8095 /* special case when cast remat */
8096 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8097 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8098 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8099 type = type = operandType (result);
8100 p_type = DCL_TYPE (type);
8102 /* now that we have the pointer type we assign
8103 the pointer values */
8109 genNearPointerSet (right, result, ic, pi);
8113 genPagedPointerSet (right, result, ic, pi);
8117 genFarPointerSet (right, result, ic, pi);
8121 genGenPointerSet (right, result, ic, pi);
8127 /*-----------------------------------------------------------------*/
8128 /* genIfx - generate code for Ifx statement */
8129 /*-----------------------------------------------------------------*/
8131 genIfx (iCode * ic, iCode * popIc)
8133 operand *cond = IC_COND (ic);
8136 D(emitcode (";", "genIfx"));
8138 aopOp (cond, ic, FALSE);
8140 /* get the value into acc */
8141 if (AOP_TYPE (cond) != AOP_CRY)
8145 /* the result is now in the accumulator */
8146 freeAsmop (cond, NULL, ic, TRUE);
8148 /* if there was something to be popped then do it */
8152 /* if the condition is a bit variable */
8153 if (isbit && IS_ITEMP (cond) &&
8155 genIfxJump (ic, SPIL_LOC (cond)->rname);
8156 else if (isbit && !IS_ITEMP (cond))
8157 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8159 genIfxJump (ic, "a");
8164 /*-----------------------------------------------------------------*/
8165 /* genAddrOf - generates code for address of */
8166 /*-----------------------------------------------------------------*/
8168 genAddrOf (iCode * ic)
8170 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8173 D(emitcode (";", "genAddrOf"));
8175 aopOp (IC_RESULT (ic), ic, FALSE);
8177 /* if the operand is on the stack then we
8178 need to get the stack offset of this
8182 /* if it has an offset then we need to compute
8186 emitcode ("mov", "a,_bp");
8187 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8188 ((char) (sym->stack - _G.nRegsSaved)) :
8189 ((char) sym->stack)) & 0xff);
8190 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8194 /* we can just move _bp */
8195 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8197 /* fill the result with zero */
8198 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8203 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8209 /* object not on stack then we need the name */
8210 size = AOP_SIZE (IC_RESULT (ic));
8215 char s[SDCC_NAME_MAX];
8217 sprintf (s, "#(%s >> %d)",
8221 sprintf (s, "#%s", sym->rname);
8222 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8226 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8230 /*-----------------------------------------------------------------*/
8231 /* genFarFarAssign - assignment when both are in far space */
8232 /*-----------------------------------------------------------------*/
8234 genFarFarAssign (operand * result, operand * right, iCode * ic)
8236 int size = AOP_SIZE (right);
8240 D(emitcode (";", "genFarFarAssign"));
8242 /* first push the right side on to the stack */
8245 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8247 emitcode ("push", "acc");
8250 freeAsmop (right, NULL, ic, FALSE);
8251 /* now assign DPTR to result */
8252 aopOp (result, ic, FALSE);
8253 size = AOP_SIZE (result);
8256 emitcode ("pop", "acc");
8257 aopPut (AOP (result), "a", --offset);
8259 freeAsmop (result, NULL, ic, FALSE);
8263 /*-----------------------------------------------------------------*/
8264 /* genAssign - generate code for assignment */
8265 /*-----------------------------------------------------------------*/
8267 genAssign (iCode * ic)
8269 operand *result, *right;
8271 unsigned long lit = 0L;
8273 D(emitcode(";","genAssign"));
8275 result = IC_RESULT (ic);
8276 right = IC_RIGHT (ic);
8278 /* if they are the same */
8279 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8282 aopOp (right, ic, FALSE);
8284 /* special case both in far space */
8285 if (AOP_TYPE (right) == AOP_DPTR &&
8286 IS_TRUE_SYMOP (result) &&
8287 isOperandInFarSpace (result))
8290 genFarFarAssign (result, right, ic);
8294 aopOp (result, ic, TRUE);
8296 /* if they are the same registers */
8297 if (sameRegs (AOP (right), AOP (result)))
8300 /* if the result is a bit */
8301 if (AOP_TYPE (result) == AOP_CRY)
8304 /* if the right size is a literal then
8305 we know what the value is */
8306 if (AOP_TYPE (right) == AOP_LIT)
8308 if (((int) operandLitValue (right)))
8309 aopPut (AOP (result), one, 0);
8311 aopPut (AOP (result), zero, 0);
8315 /* the right is also a bit variable */
8316 if (AOP_TYPE (right) == AOP_CRY)
8318 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8319 aopPut (AOP (result), "c", 0);
8325 aopPut (AOP (result), "a", 0);
8329 /* bit variables done */
8331 size = AOP_SIZE (result);
8333 if (AOP_TYPE (right) == AOP_LIT)
8334 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8336 (AOP_TYPE (result) != AOP_REG) &&
8337 (AOP_TYPE (right) == AOP_LIT) &&
8338 !IS_FLOAT (operandType (right)) &&
8341 emitcode ("clr", "a");
8344 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8345 aopPut (AOP (result), "a", size);
8347 aopPut (AOP (result),
8348 aopGet (AOP (right), size, FALSE, FALSE),
8356 aopPut (AOP (result),
8357 aopGet (AOP (right), offset, FALSE, FALSE),
8364 freeAsmop (right, NULL, ic, TRUE);
8365 freeAsmop (result, NULL, ic, TRUE);
8368 /*-----------------------------------------------------------------*/
8369 /* genJumpTab - genrates code for jump table */
8370 /*-----------------------------------------------------------------*/
8372 genJumpTab (iCode * ic)
8377 D(emitcode (";", "genJumpTab"));
8379 aopOp (IC_JTCOND (ic), ic, FALSE);
8380 /* get the condition into accumulator */
8381 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8383 /* multiply by three */
8384 emitcode ("add", "a,acc");
8385 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8386 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8388 jtab = newiTempLabel (NULL);
8389 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8390 emitcode ("jmp", "@a+dptr");
8391 emitcode ("", "%05d$:", jtab->key + 100);
8392 /* now generate the jump labels */
8393 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8394 jtab = setNextItem (IC_JTLABELS (ic)))
8395 emitcode ("ljmp", "%05d$", jtab->key + 100);
8399 /*-----------------------------------------------------------------*/
8400 /* genCast - gen code for casting */
8401 /*-----------------------------------------------------------------*/
8403 genCast (iCode * ic)
8405 operand *result = IC_RESULT (ic);
8406 sym_link *ctype = operandType (IC_LEFT (ic));
8407 sym_link *rtype = operandType (IC_RIGHT (ic));
8408 operand *right = IC_RIGHT (ic);
8411 D(emitcode(";", "genCast"));
8413 /* if they are equivalent then do nothing */
8414 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8417 aopOp (right, ic, FALSE);
8418 aopOp (result, ic, FALSE);
8420 /* if the result is a bit */
8421 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8422 if (IS_BITVAR(OP_SYMBOL(result)->type))
8424 /* if the right size is a literal then
8425 we know what the value is */
8426 if (AOP_TYPE (right) == AOP_LIT)
8428 if (((int) operandLitValue (right)))
8429 aopPut (AOP (result), one, 0);
8431 aopPut (AOP (result), zero, 0);
8436 /* the right is also a bit variable */
8437 if (AOP_TYPE (right) == AOP_CRY)
8439 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8440 aopPut (AOP (result), "c", 0);
8446 aopPut (AOP (result), "a", 0);
8450 /* if they are the same size : or less */
8451 if (AOP_SIZE (result) <= AOP_SIZE (right))
8454 /* if they are in the same place */
8455 if (sameRegs (AOP (right), AOP (result)))
8458 /* if they in different places then copy */
8459 size = AOP_SIZE (result);
8463 aopPut (AOP (result),
8464 aopGet (AOP (right), offset, FALSE, FALSE),
8472 /* if the result is of type pointer */
8477 sym_link *type = operandType (right);
8478 sym_link *etype = getSpec (type);
8480 /* pointer to generic pointer */
8481 if (IS_GENPTR (ctype))
8486 p_type = DCL_TYPE (type);
8489 if (SPEC_SCLS(etype)==S_REGISTER) {
8490 // let's assume it is a generic pointer
8493 /* we have to go by the storage class */
8494 p_type = PTR_TYPE (SPEC_OCLS (etype));
8498 /* the first two bytes are known */
8499 size = GPTRSIZE - 1;
8503 aopPut (AOP (result),
8504 aopGet (AOP (right), offset, FALSE, FALSE),
8508 /* the last byte depending on type */
8524 case PPOINTER: // what the fck is this?
8529 /* this should never happen */
8530 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8531 "got unknown pointer type");
8534 aopPut (AOP (result), l, GPTRSIZE - 1);
8538 /* just copy the pointers */
8539 size = AOP_SIZE (result);
8543 aopPut (AOP (result),
8544 aopGet (AOP (right), offset, FALSE, FALSE),
8551 /* so we now know that the size of destination is greater
8552 than the size of the source */
8553 /* we move to result for the size of source */
8554 size = AOP_SIZE (right);
8558 aopPut (AOP (result),
8559 aopGet (AOP (right), offset, FALSE, FALSE),
8564 /* now depending on the sign of the source && destination */
8565 size = AOP_SIZE (result) - AOP_SIZE (right);
8566 /* if unsigned or not an integral type */
8567 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8570 aopPut (AOP (result), zero, offset++);
8574 /* we need to extend the sign :{ */
8575 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8578 emitcode ("rlc", "a");
8579 emitcode ("subb", "a,acc");
8581 aopPut (AOP (result), "a", offset++);
8584 /* we are done hurray !!!! */
8587 freeAsmop (right, NULL, ic, TRUE);
8588 freeAsmop (result, NULL, ic, TRUE);
8592 /*-----------------------------------------------------------------*/
8593 /* genDjnz - generate decrement & jump if not zero instrucion */
8594 /*-----------------------------------------------------------------*/
8596 genDjnz (iCode * ic, iCode * ifx)
8602 D(emitcode (";", "genDjnz"));
8604 /* if the if condition has a false label
8605 then we cannot save */
8609 /* if the minus is not of the form
8611 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8612 !IS_OP_LITERAL (IC_RIGHT (ic)))
8615 if (operandLitValue (IC_RIGHT (ic)) != 1)
8618 /* if the size of this greater than one then no
8620 if (getSize (operandType (IC_RESULT (ic))) > 1)
8623 /* otherwise we can save BIG */
8624 lbl = newiTempLabel (NULL);
8625 lbl1 = newiTempLabel (NULL);
8627 aopOp (IC_RESULT (ic), ic, FALSE);
8629 if (AOP_NEEDSACC(IC_RESULT(ic)))
8631 /* If the result is accessed indirectly via
8632 * the accumulator, we must explicitly write
8633 * it back after the decrement.
8635 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8637 if (strcmp(rByte, "a"))
8639 /* Something is hopelessly wrong */
8640 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8641 __FILE__, __LINE__);
8642 /* We can just give up; the generated code will be inefficient,
8645 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8648 emitcode ("dec", "%s", rByte);
8649 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8650 emitcode ("jnz", "%05d$", lbl->key + 100);
8652 else if (IS_AOP_PREG (IC_RESULT (ic)))
8654 emitcode ("dec", "%s",
8655 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8656 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8657 emitcode ("jnz", "%05d$", lbl->key + 100);
8661 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8664 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8665 emitcode ("", "%05d$:", lbl->key + 100);
8666 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8667 emitcode ("", "%05d$:", lbl1->key + 100);
8669 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8674 /*-----------------------------------------------------------------*/
8675 /* genReceive - generate code for a receive iCode */
8676 /*-----------------------------------------------------------------*/
8678 genReceive (iCode * ic)
8680 D(emitcode (";", "genReceive"));
8682 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8683 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8684 IS_TRUE_SYMOP (IC_RESULT (ic))))
8687 int size = getSize (operandType (IC_RESULT (ic)));
8688 int offset = fReturnSizeMCS51 - size;
8691 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8692 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8695 aopOp (IC_RESULT (ic), ic, FALSE);
8696 size = AOP_SIZE (IC_RESULT (ic));
8700 emitcode ("pop", "acc");
8701 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8708 aopOp (IC_RESULT (ic), ic, FALSE);
8710 assignResultValue (IC_RESULT (ic));
8713 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8716 /*-----------------------------------------------------------------*/
8717 /* gen51AggregateAssign - copy complete array's or structures */
8718 /*-----------------------------------------------------------------*/
8719 void gen51AggregateAssign(iCode *ic) {
8720 operand *left=IC_LEFT(ic);
8721 operand *right=IC_RIGHT(ic);
8722 char *fromName=OP_SYMBOL(right)->rname;
8723 char *toName=OP_SYMBOL(left)->rname;
8724 int fromSize=getSize(OP_SYMBOL(right)->type);
8725 int toSize=getSize(OP_SYMBOL(left)->type);
8728 D(emitcode (";", "gen51AggregateAssign"));
8730 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8731 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8732 // well, this code isn't used yet from anywhere else as for initialising
8733 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8737 if (fromSize!=toSize) {
8738 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8739 ic->filename, ic->lineno);
8744 // use the generic memcpy() for now
8745 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8746 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8747 emitcode ("mov", "a,#%s", fromName);
8748 emitcode ("movx", "@dptr,a");
8749 emitcode ("inc", "dptr");
8750 emitcode ("mov", "a,#(%s>>8)", fromName);
8751 emitcode ("movx", "@dptr,a");
8752 emitcode ("inc", "dptr");
8753 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8754 emitcode ("movx", "@dptr,a");
8755 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8756 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8757 emitcode ("movx", "@dptr,a");
8758 emitcode ("inc", "dptr");
8759 emitcode ("mov", "a,#(%d>>8)", count);
8760 emitcode ("movx", "@dptr,a");
8761 emitcode ("mov", "dptr,#%s", toName);
8762 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8763 emitcode ("lcall", "_memcpy");
8765 // more efficient, but will require the native_memcpy_cs2xs
8766 emitcode ("mov", "r0,#%s", fromName);
8767 emitcode ("mov", "r1,#(%s>>8)", fromName);
8768 emitcode ("mov", "r2,#%s", toName);
8769 emitcode ("mov", "r3,#(%s>>8)", toName);
8770 emitcode ("mov", "r4,#%d", count);
8771 emitcode ("mov", "r5,#(%d>>8)", count);
8772 emitcode ("lcall", "_native_memcpy_cs2xs");
8776 /*-----------------------------------------------------------------*/
8777 /* gen51Code - generate code for 8051 based controllers */
8778 /*-----------------------------------------------------------------*/
8780 gen51Code (iCode * lic)
8785 lineHead = lineCurr = NULL;
8787 /* print the allocation information */
8789 printAllocInfo (currFunc, codeOutFile);
8790 /* if debug information required */
8791 /* if (options.debug && currFunc) { */
8792 if (options.debug && currFunc)
8794 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8796 if (IS_STATIC (currFunc->etype))
8797 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8799 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8802 /* stack pointer name */
8803 if (options.useXstack)
8809 for (ic = lic; ic; ic = ic->next)
8812 if (cln != ic->lineno)
8817 emitcode ("", "C$%s$%d$%d$%d ==.",
8818 FileBaseName (ic->filename), ic->lineno,
8819 ic->level, ic->block);
8822 emitcode (";", "%s %d", ic->filename, ic->lineno);
8825 /* if the result is marked as
8826 spilt and rematerializable or code for
8827 this has already been generated then
8829 if (resultRemat (ic) || ic->generated)
8832 /* depending on the operation */
8852 /* IPOP happens only when trying to restore a
8853 spilt live range, if there is an ifx statement
8854 following this pop then the if statement might
8855 be using some of the registers being popped which
8856 would destory the contents of the register so
8857 we need to check for this condition and handle it */
8859 ic->next->op == IFX &&
8860 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8861 genIfx (ic->next, ic);
8879 genEndFunction (ic);
8899 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8916 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8920 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8927 /* note these two are xlated by algebraic equivalence
8928 during parsing SDCC.y */
8929 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8930 "got '>=' or '<=' shouldn't have come here");
8934 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8946 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8950 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8954 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8981 case GET_VALUE_AT_ADDRESS:
8982 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8986 if (POINTER_SET (ic))
8987 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
9013 addSet (&_G.sendSet, ic);
9017 gen51AggregateAssign(ic);
9026 /* now we are ready to call the
9027 peep hole optimizer */
9028 if (!options.nopeep)
9029 peepHole (&lineHead);
9031 /* now do the actual printing */
9032 printLine (lineHead, codeOutFile);