1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 extern int mcs51_ptrRegReq;
97 extern int mcs51_nRegs;
98 extern FILE *codeOutFile;
99 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 sprintf (lb, "%s\t", inst);
140 sprintf (lb, "%s", inst);
141 vsprintf (lb + (strlen (lb)), fmt, ap);
144 vsprintf (lb, fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
386 val += (int) operandLitValue (IC_RIGHT (ic));
387 else if (ic->op == '-')
388 val -= (int) operandLitValue (IC_RIGHT (ic));
389 else if (IS_CAST_ICODE(ic)) {
390 sym_link *from_type = operandType(IC_RIGHT(ic));
391 aop->aopu.aop_immd.from_cast_remat = 1;
392 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
393 ptr_type = DCL_TYPE(from_type);
394 if (ptr_type == IPOINTER) {
401 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
405 sprintf (buffer, "(%s %c 0x%04x)",
406 OP_SYMBOL (IC_LEFT (ic))->rname,
407 val >= 0 ? '+' : '-',
410 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
413 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
414 /* set immd2 field if required */
415 if (aop->aopu.aop_immd.from_cast_remat) {
416 sprintf(buffer,"#0x%02x",ptr_type);
417 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
418 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
424 /*-----------------------------------------------------------------*/
425 /* regsInCommon - two operands have some registers in common */
426 /*-----------------------------------------------------------------*/
428 regsInCommon (operand * op1, operand * op2)
433 /* if they have registers in common */
434 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
437 sym1 = OP_SYMBOL (op1);
438 sym2 = OP_SYMBOL (op2);
440 if (sym1->nRegs == 0 || sym2->nRegs == 0)
443 for (i = 0; i < sym1->nRegs; i++)
449 for (j = 0; j < sym2->nRegs; j++)
454 if (sym2->regs[j] == sym1->regs[i])
462 /*-----------------------------------------------------------------*/
463 /* operandsEqu - equivalent */
464 /*-----------------------------------------------------------------*/
466 operandsEqu (operand * op1, operand * op2)
470 /* if they not symbols */
471 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
474 sym1 = OP_SYMBOL (op1);
475 sym2 = OP_SYMBOL (op2);
477 /* if both are itemps & one is spilt
478 and the other is not then false */
479 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
480 sym1->isspilt != sym2->isspilt)
483 /* if they are the same */
487 if (strcmp (sym1->rname, sym2->rname) == 0)
491 /* if left is a tmp & right is not */
492 if (IS_ITEMP (op1) &&
495 (sym1->usl.spillLoc == sym2))
498 if (IS_ITEMP (op2) &&
502 (sym2->usl.spillLoc == sym1))
508 /*-----------------------------------------------------------------*/
509 /* sameRegs - two asmops have the same registers */
510 /*-----------------------------------------------------------------*/
512 sameRegs (asmop * aop1, asmop * aop2)
519 if (aop1->type != AOP_REG ||
520 aop2->type != AOP_REG)
523 if (aop1->size != aop2->size)
526 for (i = 0; i < aop1->size; i++)
527 if (aop1->aopu.aop_reg[i] !=
528 aop2->aopu.aop_reg[i])
534 /*-----------------------------------------------------------------*/
535 /* aopOp - allocates an asmop for an operand : */
536 /*-----------------------------------------------------------------*/
538 aopOp (operand * op, iCode * ic, bool result)
547 /* if this a literal */
548 if (IS_OP_LITERAL (op))
550 op->aop = aop = newAsmop (AOP_LIT);
551 aop->aopu.aop_lit = op->operand.valOperand;
552 aop->size = getSize (operandType (op));
556 /* if already has a asmop then continue */
560 /* if the underlying symbol has a aop */
561 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
563 op->aop = OP_SYMBOL (op)->aop;
567 /* if this is a true symbol */
568 if (IS_TRUE_SYMOP (op))
570 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
574 /* this is a temporary : this has
580 e) can be a return use only */
582 sym = OP_SYMBOL (op);
584 /* if the type is a conditional */
585 if (sym->regType == REG_CND)
587 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
592 /* if it is spilt then two situations
594 b) has a spill location */
595 if (sym->isspilt || sym->nRegs == 0)
598 /* rematerialize it NOW */
601 sym->aop = op->aop = aop =
603 aop->size = getSize (sym->type);
610 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
611 aop->size = getSize (sym->type);
612 for (i = 0; i < 2; i++)
613 aop->aopu.aop_str[i] = accUse[i];
621 aop = op->aop = sym->aop = newAsmop (AOP_STR);
622 aop->size = getSize (sym->type);
623 for (i = 0; i < fReturnSizeMCS51; i++)
624 aop->aopu.aop_str[i] = fReturn[i];
628 /* else spill location */
629 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
630 /* force a new aop if sizes differ */
631 sym->usl.spillLoc->aop = NULL;
633 sym->aop = op->aop = aop =
634 aopForSym (ic, sym->usl.spillLoc, result);
635 aop->size = getSize (sym->type);
639 /* must be in a register */
640 sym->aop = op->aop = aop = newAsmop (AOP_REG);
641 aop->size = sym->nRegs;
642 for (i = 0; i < sym->nRegs; i++)
643 aop->aopu.aop_reg[i] = sym->regs[i];
646 /*-----------------------------------------------------------------*/
647 /* freeAsmop - free up the asmop given to an operand */
648 /*----------------------------------------------------------------*/
650 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
667 /* depending on the asmop type only three cases need work AOP_RO
668 , AOP_R1 && AOP_STK */
676 emitcode ("pop", "ar0");
680 bitVectUnSetBit (ic->rUsed, R0_IDX);
688 emitcode ("pop", "ar1");
692 bitVectUnSetBit (ic->rUsed, R1_IDX);
698 int stk = aop->aopu.aop_stk + aop->size;
699 bitVectUnSetBit (ic->rUsed, R0_IDX);
700 bitVectUnSetBit (ic->rUsed, R1_IDX);
702 getFreePtr (ic, &aop, FALSE);
706 emitcode ("mov", "a,_bp");
707 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
708 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
712 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
717 emitcode ("pop", "acc");
718 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
721 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
724 freeAsmop (op, NULL, ic, TRUE);
727 emitcode ("pop", "ar0");
733 emitcode ("pop", "ar1");
740 /* all other cases just dealloc */
746 OP_SYMBOL (op)->aop = NULL;
747 /* if the symbol has a spill */
749 SPIL_LOC (op)->aop = NULL;
754 /*-----------------------------------------------------------------*/
755 /* aopGet - for fetching value of the aop */
756 /*-----------------------------------------------------------------*/
758 aopGet (asmop * aop, int offset, bool bit16, bool dname)
763 /* offset is greater than
765 if (offset > (aop->size - 1) &&
766 aop->type != AOP_LIT)
769 /* depending on type */
775 /* if we need to increment it */
776 while (offset > aop->coff)
778 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
782 while (offset < aop->coff)
784 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
791 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
792 return (dname ? "acc" : "a");
794 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
795 rs = Safe_calloc (1, strlen (s) + 1);
800 while (offset > aop->coff)
802 emitcode ("inc", "dptr");
806 while (offset < aop->coff)
808 emitcode ("lcall", "__decdptr");
815 emitcode ("clr", "a");
816 emitcode ("movc", "a,@a+dptr");
820 emitcode ("movx", "a,@dptr");
822 return (dname ? "acc" : "a");
826 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
827 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
829 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
831 sprintf (s, "#(%s >> %d)",
832 aop->aopu.aop_immd.aop_immd1,
836 aop->aopu.aop_immd.aop_immd1);
837 rs = Safe_calloc (1, strlen (s) + 1);
843 sprintf (s, "(%s + %d)",
847 sprintf (s, "%s", aop->aopu.aop_dir);
848 rs = Safe_calloc (1, strlen (s) + 1);
854 return aop->aopu.aop_reg[offset]->dname;
856 return aop->aopu.aop_reg[offset]->name;
859 emitcode ("clr", "a");
860 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
861 emitcode ("rlc", "a");
862 return (dname ? "acc" : "a");
865 if (!offset && dname)
867 return aop->aopu.aop_str[offset];
870 return aopLiteral (aop->aopu.aop_lit, offset);
874 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
878 return aop->aopu.aop_str[offset];
882 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
883 "aopget got unsupported aop->type");
886 /*-----------------------------------------------------------------*/
887 /* aopPut - puts a string for a aop */
888 /*-----------------------------------------------------------------*/
890 aopPut (asmop * aop, char *s, int offset)
894 if (aop->size && offset > (aop->size - 1))
896 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
897 "aopPut got offset > aop->size");
901 /* will assign value to value */
902 /* depending on where it is ofcourse */
907 sprintf (d, "(%s + %d)",
908 aop->aopu.aop_dir, offset);
910 sprintf (d, "%s", aop->aopu.aop_dir);
913 emitcode ("mov", "%s,%s", d, s);
918 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
919 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
922 strcmp (s, "r0") == 0 ||
923 strcmp (s, "r1") == 0 ||
924 strcmp (s, "r2") == 0 ||
925 strcmp (s, "r3") == 0 ||
926 strcmp (s, "r4") == 0 ||
927 strcmp (s, "r5") == 0 ||
928 strcmp (s, "r6") == 0 ||
929 strcmp (s, "r7") == 0)
930 emitcode ("mov", "%s,%s",
931 aop->aopu.aop_reg[offset]->dname, s);
933 emitcode ("mov", "%s,%s",
934 aop->aopu.aop_reg[offset]->name, s);
941 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
942 "aopPut writting to code space");
946 while (offset > aop->coff)
949 emitcode ("inc", "dptr");
952 while (offset < aop->coff)
955 emitcode ("lcall", "__decdptr");
960 /* if not in accumulater */
963 emitcode ("movx", "@dptr,a");
968 while (offset > aop->coff)
971 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
973 while (offset < aop->coff)
976 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
983 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
989 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
991 else if (strcmp (s, "r0") == 0 ||
992 strcmp (s, "r1") == 0 ||
993 strcmp (s, "r2") == 0 ||
994 strcmp (s, "r3") == 0 ||
995 strcmp (s, "r4") == 0 ||
996 strcmp (s, "r5") == 0 ||
997 strcmp (s, "r6") == 0 ||
998 strcmp (s, "r7") == 0)
1001 sprintf (buffer, "a%s", s);
1002 emitcode ("mov", "@%s,%s",
1003 aop->aopu.aop_ptr->name, buffer);
1006 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1011 if (strcmp (s, "a") == 0)
1012 emitcode ("push", "acc");
1016 emitcode ("push", "acc");
1018 emitcode ("push", s);
1024 /* if bit variable */
1025 if (!aop->aopu.aop_dir)
1027 emitcode ("clr", "a");
1028 emitcode ("rlc", "a");
1033 emitcode ("clr", "%s", aop->aopu.aop_dir);
1035 emitcode ("setb", "%s", aop->aopu.aop_dir);
1036 else if (!strcmp (s, "c"))
1037 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1040 if (strcmp (s, "a"))
1045 symbol *lbl = newiTempLabel (NULL);
1046 emitcode ("clr", "c");
1047 emitcode ("jz", "%05d$", lbl->key + 100);
1048 emitcode ("cpl", "c");
1049 emitcode ("", "%05d$:", lbl->key + 100);
1050 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1058 if (strcmp (aop->aopu.aop_str[offset], s))
1059 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1064 if (!offset && (strcmp (s, "acc") == 0))
1067 if (strcmp (aop->aopu.aop_str[offset], s))
1068 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1072 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1073 "aopPut got unsupported aop->type");
1081 /*-----------------------------------------------------------------*/
1082 /* pointToEnd :- points to the last byte of the operand */
1083 /*-----------------------------------------------------------------*/
1085 pointToEnd (asmop * aop)
1091 aop->coff = count = (aop->size - 1);
1097 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1101 emitcode ("inc", "dptr");
1108 /*-----------------------------------------------------------------*/
1109 /* reAdjustPreg - points a register back to where it should */
1110 /*-----------------------------------------------------------------*/
1112 reAdjustPreg (asmop * aop)
1114 if ((aop->coff==0) || aop->size <= 1)
1122 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1127 emitcode ("lcall", "__decdptr");
1134 #define AOP(op) op->aop
1135 #define AOP_TYPE(op) AOP(op)->type
1136 #define AOP_SIZE(op) AOP(op)->size
1137 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1138 AOP_TYPE(x) == AOP_R0))
1140 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1141 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1143 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1144 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1145 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1147 /*-----------------------------------------------------------------*/
1148 /* genNotFloat - generates not for float operations */
1149 /*-----------------------------------------------------------------*/
1151 genNotFloat (operand * op, operand * res)
1157 D(emitcode (";", "genNotFloat"));
1159 /* we will put 127 in the first byte of
1161 aopPut (AOP (res), "#127", 0);
1162 size = AOP_SIZE (op) - 1;
1165 l = aopGet (op->aop, offset++, FALSE, FALSE);
1170 emitcode ("orl", "a,%s",
1172 offset++, FALSE, FALSE));
1175 tlbl = newiTempLabel (NULL);
1176 aopPut (res->aop, one, 1);
1177 emitcode ("jz", "%05d$", (tlbl->key + 100));
1178 aopPut (res->aop, zero, 1);
1179 emitcode ("", "%05d$:", (tlbl->key + 100));
1181 size = res->aop->size - 2;
1183 /* put zeros in the rest */
1185 aopPut (res->aop, zero, offset++);
1188 /*-----------------------------------------------------------------*/
1189 /* opIsGptr: returns non-zero if the passed operand is */
1190 /* a generic pointer type. */
1191 /*-----------------------------------------------------------------*/
1193 opIsGptr (operand * op)
1195 sym_link *type = operandType (op);
1197 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1204 /*-----------------------------------------------------------------*/
1205 /* getDataSize - get the operand data size */
1206 /*-----------------------------------------------------------------*/
1208 getDataSize (operand * op)
1211 size = AOP_SIZE (op);
1212 if (size == GPTRSIZE)
1214 sym_link *type = operandType (op);
1215 if (IS_GENPTR (type))
1217 /* generic pointer; arithmetic operations
1218 * should ignore the high byte (pointer type).
1226 /*-----------------------------------------------------------------*/
1227 /* outAcc - output Acc */
1228 /*-----------------------------------------------------------------*/
1230 outAcc (operand * result)
1233 size = getDataSize (result);
1236 aopPut (AOP (result), "a", 0);
1239 /* unsigned or positive */
1242 aopPut (AOP (result), zero, offset++);
1247 /*-----------------------------------------------------------------*/
1248 /* outBitC - output a bit C */
1249 /*-----------------------------------------------------------------*/
1251 outBitC (operand * result)
1253 /* if the result is bit */
1254 if (AOP_TYPE (result) == AOP_CRY)
1255 aopPut (AOP (result), "c", 0);
1258 emitcode ("clr", "a");
1259 emitcode ("rlc", "a");
1264 /*-----------------------------------------------------------------*/
1265 /* toBoolean - emit code for orl a,operator(sizeop) */
1266 /*-----------------------------------------------------------------*/
1268 toBoolean (operand * oper)
1270 int size = AOP_SIZE (oper) - 1;
1272 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1274 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1278 /*-----------------------------------------------------------------*/
1279 /* genNot - generate code for ! operation */
1280 /*-----------------------------------------------------------------*/
1285 sym_link *optype = operandType (IC_LEFT (ic));
1287 D(emitcode (";", "genNot"));
1289 /* assign asmOps to operand & result */
1290 aopOp (IC_LEFT (ic), ic, FALSE);
1291 aopOp (IC_RESULT (ic), ic, TRUE);
1293 /* if in bit space then a special case */
1294 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1296 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1297 emitcode ("cpl", "c");
1298 outBitC (IC_RESULT (ic));
1302 /* if type float then do float */
1303 if (IS_FLOAT (optype))
1305 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1309 toBoolean (IC_LEFT (ic));
1311 tlbl = newiTempLabel (NULL);
1312 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1313 emitcode ("", "%05d$:", tlbl->key + 100);
1314 outBitC (IC_RESULT (ic));
1317 /* release the aops */
1318 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1319 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1323 /*-----------------------------------------------------------------*/
1324 /* genCpl - generate code for complement */
1325 /*-----------------------------------------------------------------*/
1333 D(emitcode (";", "genCpl"));
1335 /* assign asmOps to operand & result */
1336 aopOp (IC_LEFT (ic), ic, FALSE);
1337 aopOp (IC_RESULT (ic), ic, TRUE);
1339 /* if both are in bit space then
1341 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1342 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1345 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1346 emitcode ("cpl", "c");
1347 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1351 size = AOP_SIZE (IC_RESULT (ic));
1354 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1356 emitcode ("cpl", "a");
1357 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1362 /* release the aops */
1363 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1364 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1367 /*-----------------------------------------------------------------*/
1368 /* genUminusFloat - unary minus for floating points */
1369 /*-----------------------------------------------------------------*/
1371 genUminusFloat (operand * op, operand * result)
1373 int size, offset = 0;
1376 D(emitcode (";", "genUminusFloat"));
1378 /* for this we just need to flip the
1379 first it then copy the rest in place */
1380 size = AOP_SIZE (op) - 1;
1381 l = aopGet (AOP (op), 3, FALSE, FALSE);
1385 emitcode ("cpl", "acc.7");
1386 aopPut (AOP (result), "a", 3);
1390 aopPut (AOP (result),
1391 aopGet (AOP (op), offset, FALSE, FALSE),
1397 /*-----------------------------------------------------------------*/
1398 /* genUminus - unary minus code generation */
1399 /*-----------------------------------------------------------------*/
1401 genUminus (iCode * ic)
1404 sym_link *optype, *rtype;
1407 D(emitcode (";", "genUminus"));
1410 aopOp (IC_LEFT (ic), ic, FALSE);
1411 aopOp (IC_RESULT (ic), ic, TRUE);
1413 /* if both in bit space then special
1415 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1416 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1419 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1420 emitcode ("cpl", "c");
1421 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1425 optype = operandType (IC_LEFT (ic));
1426 rtype = operandType (IC_RESULT (ic));
1428 /* if float then do float stuff */
1429 if (IS_FLOAT (optype))
1431 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1435 /* otherwise subtract from zero */
1436 size = AOP_SIZE (IC_LEFT (ic));
1441 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1442 if (!strcmp (l, "a"))
1446 emitcode ("cpl", "a");
1447 emitcode ("addc", "a,#0");
1453 emitcode ("clr", "a");
1454 emitcode ("subb", "a,%s", l);
1456 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1459 /* if any remaining bytes in the result */
1460 /* we just need to propagate the sign */
1461 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1463 emitcode ("rlc", "a");
1464 emitcode ("subb", "a,acc");
1466 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1470 /* release the aops */
1471 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1472 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1475 /*-----------------------------------------------------------------*/
1476 /* saveRegisters - will look for a call and save the registers */
1477 /*-----------------------------------------------------------------*/
1479 saveRegisters (iCode * lic)
1486 for (ic = lic; ic; ic = ic->next)
1487 if (ic->op == CALL || ic->op == PCALL)
1492 fprintf (stderr, "found parameter push with no function call\n");
1496 /* if the registers have been saved already or don't need to be then
1498 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1499 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1502 /* safe the registers in use at this time but skip the
1503 ones for the result */
1504 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1505 mcs51_rUmaskForOp (IC_RESULT(ic)));
1508 if (options.useXstack)
1510 if (bitVectBitValue (rsave, R0_IDX))
1511 emitcode ("mov", "b,r0");
1512 emitcode ("mov", "r0,%s", spname);
1513 for (i = 0; i < mcs51_nRegs; i++)
1515 if (bitVectBitValue (rsave, i))
1518 emitcode ("mov", "a,b");
1520 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1521 emitcode ("movx", "@r0,a");
1522 emitcode ("inc", "r0");
1525 emitcode ("mov", "%s,r0", spname);
1526 if (bitVectBitValue (rsave, R0_IDX))
1527 emitcode ("mov", "r0,b");
1530 for (i = 0; i < mcs51_nRegs; i++)
1532 if (bitVectBitValue (rsave, i))
1533 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1537 /*-----------------------------------------------------------------*/
1538 /* unsaveRegisters - pop the pushed registers */
1539 /*-----------------------------------------------------------------*/
1541 unsaveRegisters (iCode * ic)
1546 /* restore the registers in use at this time but skip the
1547 ones for the result */
1548 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1549 mcs51_rUmaskForOp (IC_RESULT(ic)));
1551 if (options.useXstack)
1553 emitcode ("mov", "r0,%s", spname);
1554 for (i = mcs51_nRegs; i >= 0; i--)
1556 if (bitVectBitValue (rsave, i))
1558 emitcode ("dec", "r0");
1559 emitcode ("movx", "a,@r0");
1561 emitcode ("mov", "b,a");
1563 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1567 emitcode ("mov", "%s,r0", spname);
1568 if (bitVectBitValue (rsave, R0_IDX))
1569 emitcode ("mov", "r0,b");
1572 for (i = mcs51_nRegs; i >= 0; i--)
1574 if (bitVectBitValue (rsave, i))
1575 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1581 /*-----------------------------------------------------------------*/
1583 /*-----------------------------------------------------------------*/
1585 pushSide (operand * oper, int size)
1590 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1591 if (AOP_TYPE (oper) != AOP_REG &&
1592 AOP_TYPE (oper) != AOP_DIR &&
1595 emitcode ("mov", "a,%s", l);
1596 emitcode ("push", "acc");
1599 emitcode ("push", "%s", l);
1603 /*-----------------------------------------------------------------*/
1604 /* assignResultValue - */
1605 /*-----------------------------------------------------------------*/
1607 assignResultValue (operand * oper)
1610 int size = AOP_SIZE (oper);
1613 aopPut (AOP (oper), fReturn[offset], offset);
1619 /*-----------------------------------------------------------------*/
1620 /* genXpush - pushes onto the external stack */
1621 /*-----------------------------------------------------------------*/
1623 genXpush (iCode * ic)
1625 asmop *aop = newAsmop (0);
1627 int size, offset = 0;
1629 D(emitcode (";", "genXpush"));
1631 aopOp (IC_LEFT (ic), ic, FALSE);
1632 r = getFreePtr (ic, &aop, FALSE);
1635 emitcode ("mov", "%s,_spx", r->name);
1637 size = AOP_SIZE (IC_LEFT (ic));
1641 char *l = aopGet (AOP (IC_LEFT (ic)),
1642 offset++, FALSE, FALSE);
1644 emitcode ("movx", "@%s,a", r->name);
1645 emitcode ("inc", "%s", r->name);
1650 emitcode ("mov", "_spx,%s", r->name);
1652 freeAsmop (NULL, aop, ic, TRUE);
1653 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1656 /*-----------------------------------------------------------------*/
1657 /* genIpush - genrate code for pushing this gets a little complex */
1658 /*-----------------------------------------------------------------*/
1660 genIpush (iCode * ic)
1662 int size, offset = 0;
1665 D(emitcode (";", "genIpush"));
1667 /* if this is not a parm push : ie. it is spill push
1668 and spill push is always done on the local stack */
1672 /* and the item is spilt then do nothing */
1673 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1676 aopOp (IC_LEFT (ic), ic, FALSE);
1677 size = AOP_SIZE (IC_LEFT (ic));
1678 /* push it on the stack */
1681 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1687 emitcode ("push", "%s", l);
1692 /* this is a paramter push: in this case we call
1693 the routine to find the call and save those
1694 registers that need to be saved */
1697 /* if use external stack then call the external
1698 stack pushing routine */
1699 if (options.useXstack)
1705 /* then do the push */
1706 aopOp (IC_LEFT (ic), ic, FALSE);
1709 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1710 size = AOP_SIZE (IC_LEFT (ic));
1714 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1715 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1716 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1719 emitcode ("mov", "a,%s", l);
1720 emitcode ("push", "acc");
1723 emitcode ("push", "%s", l);
1726 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1729 /*-----------------------------------------------------------------*/
1730 /* genIpop - recover the registers: can happen only for spilling */
1731 /*-----------------------------------------------------------------*/
1733 genIpop (iCode * ic)
1737 D(emitcode (";", "genIpop"));
1739 /* if the temp was not pushed then */
1740 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1743 aopOp (IC_LEFT (ic), ic, FALSE);
1744 size = AOP_SIZE (IC_LEFT (ic));
1745 offset = (size - 1);
1747 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1750 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1753 /*-----------------------------------------------------------------*/
1754 /* unsaveRBank - restores the resgister bank from stack */
1755 /*-----------------------------------------------------------------*/
1757 unsaveRBank (int bank, iCode * ic, bool popPsw)
1763 if (options.useXstack)
1767 /* Assume r0 is available for use. */
1768 r = mcs51_regWithIdx (R0_IDX);;
1773 r = getFreePtr (ic, &aop, FALSE);
1775 emitcode ("mov", "%s,_spx", r->name);
1780 if (options.useXstack)
1782 emitcode ("movx", "a,@%s", r->name);
1783 emitcode ("mov", "psw,a");
1784 emitcode ("dec", "%s", r->name);
1788 emitcode ("pop", "psw");
1792 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1794 if (options.useXstack)
1796 emitcode ("movx", "a,@%s", r->name);
1797 emitcode ("mov", "(%s+%d),a",
1798 regs8051[i].base, 8 * bank + regs8051[i].offset);
1799 emitcode ("dec", "%s", r->name);
1803 emitcode ("pop", "(%s+%d)",
1804 regs8051[i].base, 8 * bank + regs8051[i].offset);
1807 if (options.useXstack)
1809 emitcode ("mov", "_spx,%s", r->name);
1814 freeAsmop (NULL, aop, ic, TRUE);
1818 /*-----------------------------------------------------------------*/
1819 /* saveRBank - saves an entire register bank on the stack */
1820 /*-----------------------------------------------------------------*/
1822 saveRBank (int bank, iCode * ic, bool pushPsw)
1828 if (options.useXstack)
1832 /* Assume r0 is available for use. */
1833 r = mcs51_regWithIdx (R0_IDX);;
1838 r = getFreePtr (ic, &aop, FALSE);
1840 emitcode ("mov", "%s,_spx", r->name);
1843 for (i = 0; i < mcs51_nRegs; i++)
1845 if (options.useXstack)
1847 emitcode ("inc", "%s", r->name);
1848 emitcode ("mov", "a,(%s+%d)",
1849 regs8051[i].base, 8 * bank + regs8051[i].offset);
1850 emitcode ("movx", "@%s,a", r->name);
1853 emitcode ("push", "(%s+%d)",
1854 regs8051[i].base, 8 * bank + regs8051[i].offset);
1859 if (options.useXstack)
1861 emitcode ("mov", "a,psw");
1862 emitcode ("movx", "@%s,a", r->name);
1863 emitcode ("inc", "%s", r->name);
1864 emitcode ("mov", "_spx,%s", r->name);
1869 emitcode ("push", "psw");
1872 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1877 freeAsmop (NULL, aop, ic, TRUE);
1886 /*-----------------------------------------------------------------*/
1887 /* genCall - generates a call statement */
1888 /*-----------------------------------------------------------------*/
1890 genCall (iCode * ic)
1893 bool restoreBank = FALSE;
1894 bool swapBanks = FALSE;
1896 D(emitcode(";", "genCall"));
1898 /* if send set is not empty the assign */
1903 for (sic = setFirstItem (_G.sendSet); sic;
1904 sic = setNextItem (_G.sendSet))
1906 int size, offset = 0;
1907 aopOp (IC_LEFT (sic), sic, FALSE);
1908 size = AOP_SIZE (IC_LEFT (sic));
1911 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1913 if (strcmp (l, fReturn[offset]))
1914 emitcode ("mov", "%s,%s",
1919 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1924 /* if we are calling a not _naked function that is not using
1925 the same register bank then we need to save the
1926 destination registers on the stack */
1927 dtype = operandType (IC_LEFT (ic));
1928 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1929 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1930 IFFUNC_ISISR (currFunc->type))
1934 /* This is unexpected; the bank should have been saved in
1937 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1943 /* if caller saves & we have not saved then */
1949 emitcode ("mov", "psw,#0x%02x",
1950 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1954 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1955 OP_SYMBOL (IC_LEFT (ic))->rname :
1956 OP_SYMBOL (IC_LEFT (ic))->name));
1960 emitcode ("mov", "psw,#0x%02x",
1961 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1964 /* if we need assign a result value */
1965 if ((IS_ITEMP (IC_RESULT (ic)) &&
1966 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1967 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1968 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1969 IS_TRUE_SYMOP (IC_RESULT (ic)))
1973 aopOp (IC_RESULT (ic), ic, FALSE);
1976 assignResultValue (IC_RESULT (ic));
1978 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1981 /* adjust the stack for parameters if
1986 if (ic->parmBytes > 3)
1988 emitcode ("mov", "a,%s", spname);
1989 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1990 emitcode ("mov", "%s,a", spname);
1993 for (i = 0; i < ic->parmBytes; i++)
1994 emitcode ("dec", "%s", spname);
1997 /* if we hade saved some registers then unsave them */
1998 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1999 unsaveRegisters (ic);
2001 /* if register bank was saved then pop them */
2003 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2006 /*-----------------------------------------------------------------*/
2007 /* genPcall - generates a call by pointer statement */
2008 /*-----------------------------------------------------------------*/
2010 genPcall (iCode * ic)
2013 symbol *rlbl = newiTempLabel (NULL);
2014 bool restoreBank=FALSE;
2016 D(emitcode(";", "genPCall"));
2018 /* if caller saves & we have not saved then */
2022 /* if we are calling a function that is not using
2023 the same register bank then we need to save the
2024 destination registers on the stack */
2025 dtype = operandType (IC_LEFT (ic));
2026 if (currFunc && dtype && !FUNC_ISNAKED(dtype) &&
2027 IFFUNC_ISISR (currFunc->type) &&
2028 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2029 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2033 /* push the return address on to the stack */
2034 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2035 emitcode ("push", "acc");
2036 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2037 emitcode ("push", "acc");
2039 /* now push the calling address */
2040 aopOp (IC_LEFT (ic), ic, FALSE);
2042 pushSide (IC_LEFT (ic), FPTRSIZE);
2044 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2046 /* if send set is not empty the assign */
2051 for (sic = setFirstItem (_G.sendSet); sic;
2052 sic = setNextItem (_G.sendSet))
2054 int size, offset = 0;
2055 aopOp (IC_LEFT (sic), sic, FALSE);
2056 size = AOP_SIZE (IC_LEFT (sic));
2059 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2061 if (strcmp (l, fReturn[offset]))
2062 emitcode ("mov", "%s,%s",
2067 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2072 emitcode ("ret", "");
2073 emitcode ("", "%05d$:", (rlbl->key + 100));
2076 /* if we need assign a result value */
2077 if ((IS_ITEMP (IC_RESULT (ic)) &&
2078 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2079 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2080 IS_TRUE_SYMOP (IC_RESULT (ic)))
2084 aopOp (IC_RESULT (ic), ic, FALSE);
2087 assignResultValue (IC_RESULT (ic));
2089 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2092 /* adjust the stack for parameters if
2097 if (ic->parmBytes > 3)
2099 emitcode ("mov", "a,%s", spname);
2100 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2101 emitcode ("mov", "%s,a", spname);
2104 for (i = 0; i < ic->parmBytes; i++)
2105 emitcode ("dec", "%s", spname);
2109 /* if register bank was saved then unsave them */
2111 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2113 /* if we hade saved some registers then
2115 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2116 unsaveRegisters (ic);
2119 /*-----------------------------------------------------------------*/
2120 /* resultRemat - result is rematerializable */
2121 /*-----------------------------------------------------------------*/
2123 resultRemat (iCode * ic)
2125 if (SKIP_IC (ic) || ic->op == IFX)
2128 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2130 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2131 if (sym->remat && !POINTER_SET (ic))
2138 #if defined(__BORLANDC__) || defined(_MSC_VER)
2139 #define STRCASECMP stricmp
2141 #define STRCASECMP strcasecmp
2144 /*-----------------------------------------------------------------*/
2145 /* inExcludeList - return 1 if the string is in exclude Reg list */
2146 /*-----------------------------------------------------------------*/
2148 inExcludeList (char *s)
2152 if (options.excludeRegs[i] &&
2153 STRCASECMP (options.excludeRegs[i], "none") == 0)
2156 for (i = 0; options.excludeRegs[i]; i++)
2158 if (options.excludeRegs[i] &&
2159 STRCASECMP (s, options.excludeRegs[i]) == 0)
2165 /*-----------------------------------------------------------------*/
2166 /* genFunction - generated code for function entry */
2167 /*-----------------------------------------------------------------*/
2169 genFunction (iCode * ic)
2173 bool switchedPSW = FALSE;
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)
2574 emitcode ("", "C$%s$%d$%d$%d ==.",
2575 FileBaseName (ic->filename), currFunc->lastLine,
2576 ic->level, ic->block);
2577 if (IS_STATIC (currFunc->etype))
2578 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2580 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2584 emitcode ("reti", "");
2588 if (IFFUNC_ISCRITICAL (sym->type))
2589 emitcode ("setb", "ea");
2591 if (IFFUNC_CALLEESAVES(sym->type))
2595 /* if any registers used */
2598 /* save the registers used */
2599 for (i = sym->regsUsed->size; i >= 0; i--)
2601 if (bitVectBitValue (sym->regsUsed, i) ||
2602 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2603 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2609 /* if debug then send end of function */
2610 if (options.debug && currFunc)
2613 emitcode ("", "C$%s$%d$%d$%d ==.",
2614 FileBaseName (ic->filename), currFunc->lastLine,
2615 ic->level, ic->block);
2616 if (IS_STATIC (currFunc->etype))
2617 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2619 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2623 emitcode ("ret", "");
2628 /*-----------------------------------------------------------------*/
2629 /* genRet - generate code for return statement */
2630 /*-----------------------------------------------------------------*/
2634 int size, offset = 0, pushed = 0;
2636 D(emitcode (";", "genRet"));
2638 /* if we have no return value then
2639 just generate the "ret" */
2643 /* we have something to return then
2644 move the return value into place */
2645 aopOp (IC_LEFT (ic), ic, FALSE);
2646 size = AOP_SIZE (IC_LEFT (ic));
2651 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2654 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2656 emitcode ("push", "%s", l);
2661 l = aopGet (AOP (IC_LEFT (ic)), offset,
2663 if (strcmp (fReturn[offset], l))
2664 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2673 if (strcmp (fReturn[pushed], "a"))
2674 emitcode ("pop", fReturn[pushed]);
2676 emitcode ("pop", "acc");
2679 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2682 /* generate a jump to the return label
2683 if the next is not the return statement */
2684 if (!(ic->next && ic->next->op == LABEL &&
2685 IC_LABEL (ic->next) == returnLabel))
2687 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2691 /*-----------------------------------------------------------------*/
2692 /* genLabel - generates a label */
2693 /*-----------------------------------------------------------------*/
2695 genLabel (iCode * ic)
2697 /* special case never generate */
2698 if (IC_LABEL (ic) == entryLabel)
2701 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2704 /*-----------------------------------------------------------------*/
2705 /* genGoto - generates a ljmp */
2706 /*-----------------------------------------------------------------*/
2708 genGoto (iCode * ic)
2710 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2713 /*-----------------------------------------------------------------*/
2714 /* findLabelBackwards: walks back through the iCode chain looking */
2715 /* for the given label. Returns number of iCode instructions */
2716 /* between that label and given ic. */
2717 /* Returns zero if label not found. */
2718 /*-----------------------------------------------------------------*/
2720 findLabelBackwards (iCode * ic, int key)
2729 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2731 /* printf("findLabelBackwards = %d\n", count); */
2739 /*-----------------------------------------------------------------*/
2740 /* genPlusIncr :- does addition with increment if possible */
2741 /*-----------------------------------------------------------------*/
2743 genPlusIncr (iCode * ic)
2745 unsigned int icount;
2746 unsigned int size = getDataSize (IC_RESULT (ic));
2748 /* will try to generate an increment */
2749 /* if the right side is not a literal
2751 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2754 /* if the literal value of the right hand side
2755 is greater than 4 then it is not worth it */
2756 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2759 D(emitcode (";", "genPlusIncr"));
2761 /* if increment 16 bits in register */
2762 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2770 /* If the next instruction is a goto and the goto target
2771 * is < 10 instructions previous to this, we can generate
2772 * jumps straight to that target.
2774 if (ic->next && ic->next->op == GOTO
2775 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2776 && labelRange <= 10)
2778 emitcode (";", "tail increment optimized");
2779 tlbl = IC_LABEL (ic->next);
2784 tlbl = newiTempLabel (NULL);
2787 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2788 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2789 IS_AOP_PREG (IC_RESULT (ic)))
2790 emitcode ("cjne", "%s,#0x00,%05d$"
2791 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2795 emitcode ("clr", "a");
2796 emitcode ("cjne", "a,%s,%05d$"
2797 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2801 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2804 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2805 IS_AOP_PREG (IC_RESULT (ic)))
2806 emitcode ("cjne", "%s,#0x00,%05d$"
2807 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2810 emitcode ("cjne", "a,%s,%05d$"
2811 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2814 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2818 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2819 IS_AOP_PREG (IC_RESULT (ic)))
2820 emitcode ("cjne", "%s,#0x00,%05d$"
2821 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2825 emitcode ("cjne", "a,%s,%05d$"
2826 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2829 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2834 emitcode ("", "%05d$:", tlbl->key + 100);
2839 /* if the sizes are greater than 1 then we cannot */
2840 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2841 AOP_SIZE (IC_LEFT (ic)) > 1)
2844 /* we can if the aops of the left & result match or
2845 if they are in registers and the registers are the
2847 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2852 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2853 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2854 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2860 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2869 /*-----------------------------------------------------------------*/
2870 /* outBitAcc - output a bit in acc */
2871 /*-----------------------------------------------------------------*/
2873 outBitAcc (operand * result)
2875 symbol *tlbl = newiTempLabel (NULL);
2876 /* if the result is a bit */
2877 if (AOP_TYPE (result) == AOP_CRY)
2879 aopPut (AOP (result), "a", 0);
2883 emitcode ("jz", "%05d$", tlbl->key + 100);
2884 emitcode ("mov", "a,%s", one);
2885 emitcode ("", "%05d$:", tlbl->key + 100);
2890 /*-----------------------------------------------------------------*/
2891 /* genPlusBits - generates code for addition of two bits */
2892 /*-----------------------------------------------------------------*/
2894 genPlusBits (iCode * ic)
2896 D(emitcode (";", "genPlusBits"));
2898 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2900 symbol *lbl = newiTempLabel (NULL);
2901 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2902 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2903 emitcode ("cpl", "c");
2904 emitcode ("", "%05d$:", (lbl->key + 100));
2905 outBitC (IC_RESULT (ic));
2909 emitcode ("clr", "a");
2910 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2911 emitcode ("rlc", "a");
2912 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2913 emitcode ("addc", "a,#0x00");
2914 outAcc (IC_RESULT (ic));
2919 /* This is the original version of this code.
2921 * This is being kept around for reference,
2922 * because I am not entirely sure I got it right...
2925 adjustArithmeticResult (iCode * ic)
2927 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2928 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2929 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2930 aopPut (AOP (IC_RESULT (ic)),
2931 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2934 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2935 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2936 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2937 aopPut (AOP (IC_RESULT (ic)),
2938 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2941 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2942 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2943 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2944 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2945 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2948 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2949 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2953 /* This is the pure and virtuous version of this code.
2954 * I'm pretty certain it's right, but not enough to toss the old
2958 adjustArithmeticResult (iCode * ic)
2960 if (opIsGptr (IC_RESULT (ic)) &&
2961 opIsGptr (IC_LEFT (ic)) &&
2962 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2964 aopPut (AOP (IC_RESULT (ic)),
2965 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2969 if (opIsGptr (IC_RESULT (ic)) &&
2970 opIsGptr (IC_RIGHT (ic)) &&
2971 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2973 aopPut (AOP (IC_RESULT (ic)),
2974 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2978 if (opIsGptr (IC_RESULT (ic)) &&
2979 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2980 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2981 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2982 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2985 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2986 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2991 /*-----------------------------------------------------------------*/
2992 /* genPlus - generates code for addition */
2993 /*-----------------------------------------------------------------*/
2995 genPlus (iCode * ic)
2997 int size, offset = 0;
2999 /* special cases :- */
3001 D(emitcode (";", "genPlus"));
3003 aopOp (IC_LEFT (ic), ic, FALSE);
3004 aopOp (IC_RIGHT (ic), ic, FALSE);
3005 aopOp (IC_RESULT (ic), ic, TRUE);
3007 /* if literal, literal on the right or
3008 if left requires ACC or right is already
3010 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3011 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3012 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3014 operand *t = IC_RIGHT (ic);
3015 IC_RIGHT (ic) = IC_LEFT (ic);
3019 /* if both left & right are in bit
3021 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3022 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3028 /* if left in bit space & right literal */
3029 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3030 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3032 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3033 /* if result in bit space */
3034 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3036 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3037 emitcode ("cpl", "c");
3038 outBitC (IC_RESULT (ic));
3042 size = getDataSize (IC_RESULT (ic));
3045 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3046 emitcode ("addc", "a,#00");
3047 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3053 /* if I can do an increment instead
3054 of add then GOOD for ME */
3055 if (genPlusIncr (ic) == TRUE)
3058 size = getDataSize (IC_RESULT (ic));
3062 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3064 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3066 emitcode ("add", "a,%s",
3067 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3069 emitcode ("addc", "a,%s",
3070 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3074 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3076 emitcode ("add", "a,%s",
3077 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3079 emitcode ("addc", "a,%s",
3080 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3082 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3085 adjustArithmeticResult (ic);
3088 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3089 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3090 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3093 /*-----------------------------------------------------------------*/
3094 /* genMinusDec :- does subtraction with deccrement if possible */
3095 /*-----------------------------------------------------------------*/
3097 genMinusDec (iCode * ic)
3099 unsigned int icount;
3100 unsigned int size = getDataSize (IC_RESULT (ic));
3102 /* will try to generate an increment */
3103 /* if the right side is not a literal
3105 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3108 /* if the literal value of the right hand side
3109 is greater than 4 then it is not worth it */
3110 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3113 D(emitcode (";", "genMinusDec"));
3115 /* if decrement 16 bits in register */
3116 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3124 /* If the next instruction is a goto and the goto target
3125 * is <= 10 instructions previous to this, we can generate
3126 * jumps straight to that target.
3128 if (ic->next && ic->next->op == GOTO
3129 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3130 && labelRange <= 10)
3132 emitcode (";", "tail decrement optimized");
3133 tlbl = IC_LABEL (ic->next);
3138 tlbl = newiTempLabel (NULL);
3142 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3143 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3144 IS_AOP_PREG (IC_RESULT (ic)))
3145 emitcode ("cjne", "%s,#0xff,%05d$"
3146 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3150 emitcode ("mov", "a,#0xff");
3151 emitcode ("cjne", "a,%s,%05d$"
3152 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3155 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3158 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3159 IS_AOP_PREG (IC_RESULT (ic)))
3160 emitcode ("cjne", "%s,#0xff,%05d$"
3161 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3165 emitcode ("cjne", "a,%s,%05d$"
3166 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3169 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3173 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3174 IS_AOP_PREG (IC_RESULT (ic)))
3175 emitcode ("cjne", "%s,#0xff,%05d$"
3176 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3180 emitcode ("cjne", "a,%s,%05d$"
3181 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3184 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3188 emitcode ("", "%05d$:", tlbl->key + 100);
3193 /* if the sizes are greater than 1 then we cannot */
3194 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3195 AOP_SIZE (IC_LEFT (ic)) > 1)
3198 /* we can if the aops of the left & result match or
3199 if they are in registers and the registers are the
3201 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3205 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3213 /*-----------------------------------------------------------------*/
3214 /* addSign - complete with sign */
3215 /*-----------------------------------------------------------------*/
3217 addSign (operand * result, int offset, int sign)
3219 int size = (getDataSize (result) - offset);
3224 emitcode ("rlc", "a");
3225 emitcode ("subb", "a,acc");
3227 aopPut (AOP (result), "a", offset++);
3231 aopPut (AOP (result), zero, offset++);
3235 /*-----------------------------------------------------------------*/
3236 /* genMinusBits - generates code for subtraction of two bits */
3237 /*-----------------------------------------------------------------*/
3239 genMinusBits (iCode * ic)
3241 symbol *lbl = newiTempLabel (NULL);
3243 D(emitcode (";", "genMinusBits"));
3245 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3247 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3248 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3249 emitcode ("cpl", "c");
3250 emitcode ("", "%05d$:", (lbl->key + 100));
3251 outBitC (IC_RESULT (ic));
3255 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3256 emitcode ("subb", "a,acc");
3257 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3258 emitcode ("inc", "a");
3259 emitcode ("", "%05d$:", (lbl->key + 100));
3260 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3261 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3265 /*-----------------------------------------------------------------*/
3266 /* genMinus - generates code for subtraction */
3267 /*-----------------------------------------------------------------*/
3269 genMinus (iCode * ic)
3271 int size, offset = 0;
3272 unsigned long lit = 0L;
3274 D(emitcode (";", "genMinus"));
3276 aopOp (IC_LEFT (ic), ic, FALSE);
3277 aopOp (IC_RIGHT (ic), ic, FALSE);
3278 aopOp (IC_RESULT (ic), ic, TRUE);
3280 /* special cases :- */
3281 /* if both left & right are in bit space */
3282 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3283 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3289 /* if I can do an decrement instead
3290 of subtract then GOOD for ME */
3291 if (genMinusDec (ic) == TRUE)
3294 size = getDataSize (IC_RESULT (ic));
3296 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3302 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3306 /* if literal, add a,#-lit, else normal subb */
3309 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3310 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3311 emitcode ("subb", "a,%s",
3312 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3315 /* first add without previous c */
3317 if (!size && lit==-1) {
3318 emitcode ("dec", "a");
3320 emitcode ("add", "a,#0x%02x",
3321 (unsigned int) (lit & 0x0FFL));
3324 emitcode ("addc", "a,#0x%02x",
3325 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3328 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3331 adjustArithmeticResult (ic);
3334 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3335 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3336 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3340 /*-----------------------------------------------------------------*/
3341 /* genMultbits :- multiplication of bits */
3342 /*-----------------------------------------------------------------*/
3344 genMultbits (operand * left,
3348 D(emitcode (";", "genMultbits"));
3350 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3351 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3356 /*-----------------------------------------------------------------*/
3357 /* genMultOneByte : 8*8=8/16 bit multiplication */
3358 /*-----------------------------------------------------------------*/
3360 genMultOneByte (operand * left,
3364 sym_link *opetype = operandType (result);
3366 int size=AOP_SIZE(result);
3368 D(emitcode (";", "genMultOneByte"));
3370 if (size<1 || size>2) {
3371 // this should never happen
3372 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3373 AOP_SIZE(result), __FILE__, lineno);
3377 /* (if two literals: the value is computed before) */
3378 /* if one literal, literal on the right */
3379 if (AOP_TYPE (left) == AOP_LIT)
3384 //emitcode (";", "swapped left and right");
3387 if (SPEC_USIGN(opetype)
3388 // ignore the sign of left and right, what else can we do?
3389 || (SPEC_USIGN(operandType(left)) &&
3390 SPEC_USIGN(operandType(right)))) {
3391 // just an unsigned 8*8=8/16 multiply
3392 //emitcode (";","unsigned");
3393 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3394 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3395 emitcode ("mul", "ab");
3396 aopPut (AOP (result), "a", 0);
3398 aopPut (AOP (result), "b", 1);
3403 // we have to do a signed multiply
3405 //emitcode (";", "signed");
3406 emitcode ("clr", "F0"); // reset sign flag
3407 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3409 lbl=newiTempLabel(NULL);
3410 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3411 // left side is negative, 8-bit two's complement, this fails for -128
3412 emitcode ("setb", "F0"); // set sign flag
3413 emitcode ("cpl", "a");
3414 emitcode ("inc", "a");
3416 emitcode ("", "%05d$:", lbl->key+100);
3419 if (AOP_TYPE(right)==AOP_LIT) {
3420 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3421 /* AND literal negative */
3423 emitcode ("cpl", "F0"); // complement sign flag
3424 emitcode ("mov", "b,#0x%02x", -val);
3426 emitcode ("mov", "b,#0x%02x", val);
3429 lbl=newiTempLabel(NULL);
3430 emitcode ("mov", "b,a");
3431 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3432 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3433 // right side is negative, 8-bit two's complement
3434 emitcode ("cpl", "F0"); // complement sign flag
3435 emitcode ("cpl", "a");
3436 emitcode ("inc", "a");
3437 emitcode ("", "%05d$:", lbl->key+100);
3439 emitcode ("mul", "ab");
3441 lbl=newiTempLabel(NULL);
3442 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3443 // only ONE op was negative, we have to do a 8/16-bit two's complement
3444 emitcode ("cpl", "a"); // lsb
3446 emitcode ("inc", "a");
3448 emitcode ("add", "a,#1");
3449 emitcode ("xch", "a,b");
3450 emitcode ("cpl", "a"); // msb
3451 emitcode ("addc", "a,#0");
3452 emitcode ("xch", "a,b");
3455 emitcode ("", "%05d$:", lbl->key+100);
3456 aopPut (AOP (result), "a", 0);
3458 aopPut (AOP (result), "b", 1);
3462 /*-----------------------------------------------------------------*/
3463 /* genMult - generates code for multiplication */
3464 /*-----------------------------------------------------------------*/
3466 genMult (iCode * ic)
3468 operand *left = IC_LEFT (ic);
3469 operand *right = IC_RIGHT (ic);
3470 operand *result = IC_RESULT (ic);
3472 D(emitcode (";", "genMult"));
3474 /* assign the amsops */
3475 aopOp (left, ic, FALSE);
3476 aopOp (right, ic, FALSE);
3477 aopOp (result, ic, TRUE);
3479 /* special cases first */
3481 if (AOP_TYPE (left) == AOP_CRY &&
3482 AOP_TYPE (right) == AOP_CRY)
3484 genMultbits (left, right, result);
3488 /* if both are of size == 1 */
3489 #if 0 // one of them can be a sloc shared with the result
3490 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3492 if (getSize(operandType(left)) == 1 &&
3493 getSize(operandType(right)) == 1)
3496 genMultOneByte (left, right, result);
3500 /* should have been converted to function call */
3501 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3502 getSize(OP_SYMBOL(right)->type));
3506 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3507 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3508 freeAsmop (result, NULL, ic, TRUE);
3511 /*-----------------------------------------------------------------*/
3512 /* genDivbits :- division of bits */
3513 /*-----------------------------------------------------------------*/
3515 genDivbits (operand * left,
3522 D(emitcode (";", "genDivbits"));
3524 /* the result must be bit */
3525 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3526 l = aopGet (AOP (left), 0, FALSE, FALSE);
3530 emitcode ("div", "ab");
3531 emitcode ("rrc", "a");
3532 aopPut (AOP (result), "c", 0);
3535 /*-----------------------------------------------------------------*/
3536 /* genDivOneByte : 8 bit division */
3537 /*-----------------------------------------------------------------*/
3539 genDivOneByte (operand * left,
3543 sym_link *opetype = operandType (result);
3548 D(emitcode (";", "genDivOneByte"));
3550 size = AOP_SIZE (result) - 1;
3552 /* signed or unsigned */
3553 if (SPEC_USIGN (opetype))
3555 /* unsigned is easy */
3556 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3557 l = aopGet (AOP (left), 0, FALSE, FALSE);
3559 emitcode ("div", "ab");
3560 aopPut (AOP (result), "a", 0);
3562 aopPut (AOP (result), zero, offset++);
3566 /* signed is a little bit more difficult */
3568 /* save the signs of the operands */
3569 l = aopGet (AOP (left), 0, FALSE, FALSE);
3571 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3572 emitcode ("push", "acc"); /* save it on the stack */
3574 /* now sign adjust for both left & right */
3575 l = aopGet (AOP (right), 0, FALSE, FALSE);
3577 lbl = newiTempLabel (NULL);
3578 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3579 emitcode ("cpl", "a");
3580 emitcode ("inc", "a");
3581 emitcode ("", "%05d$:", (lbl->key + 100));
3582 emitcode ("mov", "b,a");
3584 /* sign adjust left side */
3585 l = aopGet (AOP (left), 0, FALSE, FALSE);
3588 lbl = newiTempLabel (NULL);
3589 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3590 emitcode ("cpl", "a");
3591 emitcode ("inc", "a");
3592 emitcode ("", "%05d$:", (lbl->key + 100));
3594 /* now the division */
3595 emitcode ("div", "ab");
3596 /* we are interested in the lower order
3598 emitcode ("mov", "b,a");
3599 lbl = newiTempLabel (NULL);
3600 emitcode ("pop", "acc");
3601 /* if there was an over flow we don't
3602 adjust the sign of the result */
3603 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3604 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3606 emitcode ("clr", "a");
3607 emitcode ("subb", "a,b");
3608 emitcode ("mov", "b,a");
3609 emitcode ("", "%05d$:", (lbl->key + 100));
3611 /* now we are done */
3612 aopPut (AOP (result), "b", 0);
3615 emitcode ("mov", "c,b.7");
3616 emitcode ("subb", "a,acc");
3619 aopPut (AOP (result), "a", offset++);
3623 /*-----------------------------------------------------------------*/
3624 /* genDiv - generates code for division */
3625 /*-----------------------------------------------------------------*/
3629 operand *left = IC_LEFT (ic);
3630 operand *right = IC_RIGHT (ic);
3631 operand *result = IC_RESULT (ic);
3633 D(emitcode (";", "genDiv"));
3635 /* assign the amsops */
3636 aopOp (left, ic, FALSE);
3637 aopOp (right, ic, FALSE);
3638 aopOp (result, ic, TRUE);
3640 /* special cases first */
3642 if (AOP_TYPE (left) == AOP_CRY &&
3643 AOP_TYPE (right) == AOP_CRY)
3645 genDivbits (left, right, result);
3649 /* if both are of size == 1 */
3650 if (AOP_SIZE (left) == 1 &&
3651 AOP_SIZE (right) == 1)
3653 genDivOneByte (left, right, result);
3657 /* should have been converted to function call */
3660 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3661 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3662 freeAsmop (result, NULL, ic, TRUE);
3665 /*-----------------------------------------------------------------*/
3666 /* genModbits :- modulus of bits */
3667 /*-----------------------------------------------------------------*/
3669 genModbits (operand * left,
3676 D(emitcode (";", "genModbits"));
3678 /* the result must be bit */
3679 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3680 l = aopGet (AOP (left), 0, FALSE, FALSE);
3684 emitcode ("div", "ab");
3685 emitcode ("mov", "a,b");
3686 emitcode ("rrc", "a");
3687 aopPut (AOP (result), "c", 0);
3690 /*-----------------------------------------------------------------*/
3691 /* genModOneByte : 8 bit modulus */
3692 /*-----------------------------------------------------------------*/
3694 genModOneByte (operand * left,
3698 sym_link *opetype = operandType (result);
3702 D(emitcode (";", "genModOneByte"));
3704 /* signed or unsigned */
3705 if (SPEC_USIGN (opetype))
3707 /* unsigned is easy */
3708 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3709 l = aopGet (AOP (left), 0, FALSE, FALSE);
3711 emitcode ("div", "ab");
3712 aopPut (AOP (result), "b", 0);
3716 /* signed is a little bit more difficult */
3718 /* save the signs of the operands */
3719 l = aopGet (AOP (left), 0, FALSE, FALSE);
3722 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3723 emitcode ("push", "acc"); /* save it on the stack */
3725 /* now sign adjust for both left & right */
3726 l = aopGet (AOP (right), 0, FALSE, FALSE);
3729 lbl = newiTempLabel (NULL);
3730 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3731 emitcode ("cpl", "a");
3732 emitcode ("inc", "a");
3733 emitcode ("", "%05d$:", (lbl->key + 100));
3734 emitcode ("mov", "b,a");
3736 /* sign adjust left side */
3737 l = aopGet (AOP (left), 0, FALSE, FALSE);
3740 lbl = newiTempLabel (NULL);
3741 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3742 emitcode ("cpl", "a");
3743 emitcode ("inc", "a");
3744 emitcode ("", "%05d$:", (lbl->key + 100));
3746 /* now the multiplication */
3747 emitcode ("div", "ab");
3748 /* we are interested in the lower order
3750 lbl = newiTempLabel (NULL);
3751 emitcode ("pop", "acc");
3752 /* if there was an over flow we don't
3753 adjust the sign of the result */
3754 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3755 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3757 emitcode ("clr", "a");
3758 emitcode ("subb", "a,b");
3759 emitcode ("mov", "b,a");
3760 emitcode ("", "%05d$:", (lbl->key + 100));
3762 /* now we are done */
3763 aopPut (AOP (result), "b", 0);
3767 /*-----------------------------------------------------------------*/
3768 /* genMod - generates code for division */
3769 /*-----------------------------------------------------------------*/
3773 operand *left = IC_LEFT (ic);
3774 operand *right = IC_RIGHT (ic);
3775 operand *result = IC_RESULT (ic);
3777 D(emitcode (";", "genMod"));
3779 /* assign the amsops */
3780 aopOp (left, ic, FALSE);
3781 aopOp (right, ic, FALSE);
3782 aopOp (result, ic, TRUE);
3784 /* special cases first */
3786 if (AOP_TYPE (left) == AOP_CRY &&
3787 AOP_TYPE (right) == AOP_CRY)
3789 genModbits (left, right, result);
3793 /* if both are of size == 1 */
3794 if (AOP_SIZE (left) == 1 &&
3795 AOP_SIZE (right) == 1)
3797 genModOneByte (left, right, result);
3801 /* should have been converted to function call */
3805 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3806 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3807 freeAsmop (result, NULL, ic, TRUE);
3810 /*-----------------------------------------------------------------*/
3811 /* genIfxJump :- will create a jump depending on the ifx */
3812 /*-----------------------------------------------------------------*/
3814 genIfxJump (iCode * ic, char *jval)
3817 symbol *tlbl = newiTempLabel (NULL);
3820 D(emitcode (";", "genIfxJump"));
3822 /* if true label then we jump if condition
3826 jlbl = IC_TRUE (ic);
3827 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3828 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3832 /* false label is present */
3833 jlbl = IC_FALSE (ic);
3834 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3835 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3837 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3838 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3840 emitcode (inst, "%05d$", tlbl->key + 100);
3841 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3842 emitcode ("", "%05d$:", tlbl->key + 100);
3844 /* mark the icode as generated */
3848 /*-----------------------------------------------------------------*/
3849 /* genCmp :- greater or less than comparison */
3850 /*-----------------------------------------------------------------*/
3852 genCmp (operand * left, operand * right,
3853 operand * result, iCode * ifx, int sign, iCode *ic)
3855 int size, offset = 0;
3856 unsigned long lit = 0L;
3858 D(emitcode (";", "genCmp"));
3860 /* if left & right are bit variables */
3861 if (AOP_TYPE (left) == AOP_CRY &&
3862 AOP_TYPE (right) == AOP_CRY)
3864 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3865 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3869 /* subtract right from left if at the
3870 end the carry flag is set then we know that
3871 left is greater than right */
3872 size = max (AOP_SIZE (left), AOP_SIZE (right));
3874 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3875 if ((size == 1) && !sign &&
3876 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3878 symbol *lbl = newiTempLabel (NULL);
3879 emitcode ("cjne", "%s,%s,%05d$",
3880 aopGet (AOP (left), offset, FALSE, FALSE),
3881 aopGet (AOP (right), offset, FALSE, FALSE),
3883 emitcode ("", "%05d$:", lbl->key + 100);
3887 if (AOP_TYPE (right) == AOP_LIT)
3889 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3890 /* optimize if(x < 0) or if(x >= 0) */
3899 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3900 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3902 genIfxJump (ifx, "acc.7");
3906 emitcode ("rlc", "a");
3914 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3915 if (sign && size == 0)
3917 emitcode ("xrl", "a,#0x80");
3918 if (AOP_TYPE (right) == AOP_LIT)
3920 unsigned long lit = (unsigned long)
3921 floatFromVal (AOP (right)->aopu.aop_lit);
3922 emitcode ("subb", "a,#0x%02x",
3923 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3927 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3928 emitcode ("xrl", "b,#0x80");
3929 emitcode ("subb", "a,b");
3933 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3939 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3940 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3947 /* if the result is used in the next
3948 ifx conditional branch then generate
3949 code a little differently */
3951 genIfxJump (ifx, "c");
3954 /* leave the result in acc */
3958 /*-----------------------------------------------------------------*/
3959 /* genCmpGt :- greater than comparison */
3960 /*-----------------------------------------------------------------*/
3962 genCmpGt (iCode * ic, iCode * ifx)
3964 operand *left, *right, *result;
3965 sym_link *letype, *retype;
3968 D(emitcode (";", "genCmpGt"));
3970 left = IC_LEFT (ic);
3971 right = IC_RIGHT (ic);
3972 result = IC_RESULT (ic);
3974 letype = getSpec (operandType (left));
3975 retype = getSpec (operandType (right));
3976 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3977 /* assign the amsops */
3978 aopOp (left, ic, FALSE);
3979 aopOp (right, ic, FALSE);
3980 aopOp (result, ic, TRUE);
3982 genCmp (right, left, result, ifx, sign,ic);
3984 freeAsmop (result, NULL, ic, TRUE);
3987 /*-----------------------------------------------------------------*/
3988 /* genCmpLt - less than comparisons */
3989 /*-----------------------------------------------------------------*/
3991 genCmpLt (iCode * ic, iCode * ifx)
3993 operand *left, *right, *result;
3994 sym_link *letype, *retype;
3997 D(emitcode (";", "genCmpLt"));
3999 left = IC_LEFT (ic);
4000 right = IC_RIGHT (ic);
4001 result = IC_RESULT (ic);
4003 letype = getSpec (operandType (left));
4004 retype = getSpec (operandType (right));
4005 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4007 /* assign the amsops */
4008 aopOp (left, ic, FALSE);
4009 aopOp (right, ic, FALSE);
4010 aopOp (result, ic, TRUE);
4012 genCmp (left, right, result, ifx, sign,ic);
4014 freeAsmop (result, NULL, ic, TRUE);
4017 /*-----------------------------------------------------------------*/
4018 /* gencjneshort - compare and jump if not equal */
4019 /*-----------------------------------------------------------------*/
4021 gencjneshort (operand * left, operand * right, symbol * lbl)
4023 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4025 unsigned long lit = 0L;
4027 /* if the left side is a literal or
4028 if the right is in a pointer register and left
4030 if ((AOP_TYPE (left) == AOP_LIT) ||
4031 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4037 if (AOP_TYPE (right) == AOP_LIT)
4038 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4040 /* if the right side is a literal then anything goes */
4041 if (AOP_TYPE (right) == AOP_LIT &&
4042 AOP_TYPE (left) != AOP_DIR)
4046 emitcode ("cjne", "%s,%s,%05d$",
4047 aopGet (AOP (left), offset, FALSE, FALSE),
4048 aopGet (AOP (right), offset, FALSE, FALSE),
4054 /* if the right side is in a register or in direct space or
4055 if the left is a pointer register & right is not */
4056 else if (AOP_TYPE (right) == AOP_REG ||
4057 AOP_TYPE (right) == AOP_DIR ||
4058 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4059 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4063 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4064 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4065 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4066 emitcode ("jnz", "%05d$", lbl->key + 100);
4068 emitcode ("cjne", "a,%s,%05d$",
4069 aopGet (AOP (right), offset, FALSE, TRUE),
4076 /* right is a pointer reg need both a & b */
4079 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4080 if (strcmp (l, "b"))
4081 emitcode ("mov", "b,%s", l);
4082 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4083 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4089 /*-----------------------------------------------------------------*/
4090 /* gencjne - compare and jump if not equal */
4091 /*-----------------------------------------------------------------*/
4093 gencjne (operand * left, operand * right, symbol * lbl)
4095 symbol *tlbl = newiTempLabel (NULL);
4097 gencjneshort (left, right, lbl);
4099 emitcode ("mov", "a,%s", one);
4100 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4101 emitcode ("", "%05d$:", lbl->key + 100);
4102 emitcode ("clr", "a");
4103 emitcode ("", "%05d$:", tlbl->key + 100);
4106 /*-----------------------------------------------------------------*/
4107 /* genCmpEq - generates code for equal to */
4108 /*-----------------------------------------------------------------*/
4110 genCmpEq (iCode * ic, iCode * ifx)
4112 operand *left, *right, *result;
4114 D(emitcode (";", "genCmpEq"));
4116 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4117 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4118 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4120 /* if literal, literal on the right or
4121 if the right is in a pointer register and left
4123 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4124 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4126 operand *t = IC_RIGHT (ic);
4127 IC_RIGHT (ic) = IC_LEFT (ic);
4131 if (ifx && !AOP_SIZE (result))
4134 /* if they are both bit variables */
4135 if (AOP_TYPE (left) == AOP_CRY &&
4136 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4138 if (AOP_TYPE (right) == AOP_LIT)
4140 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4143 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4144 emitcode ("cpl", "c");
4148 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4152 emitcode ("clr", "c");
4154 /* AOP_TYPE(right) == AOP_CRY */
4158 symbol *lbl = newiTempLabel (NULL);
4159 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4160 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4161 emitcode ("cpl", "c");
4162 emitcode ("", "%05d$:", (lbl->key + 100));
4164 /* if true label then we jump if condition
4166 tlbl = newiTempLabel (NULL);
4169 emitcode ("jnc", "%05d$", tlbl->key + 100);
4170 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4174 emitcode ("jc", "%05d$", tlbl->key + 100);
4175 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4177 emitcode ("", "%05d$:", tlbl->key + 100);
4181 tlbl = newiTempLabel (NULL);
4182 gencjneshort (left, right, tlbl);
4185 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4186 emitcode ("", "%05d$:", tlbl->key + 100);
4190 symbol *lbl = newiTempLabel (NULL);
4191 emitcode ("sjmp", "%05d$", lbl->key + 100);
4192 emitcode ("", "%05d$:", tlbl->key + 100);
4193 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4194 emitcode ("", "%05d$:", lbl->key + 100);
4197 /* mark the icode as generated */
4202 /* if they are both bit variables */
4203 if (AOP_TYPE (left) == AOP_CRY &&
4204 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4206 if (AOP_TYPE (right) == AOP_LIT)
4208 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4211 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4212 emitcode ("cpl", "c");
4216 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4220 emitcode ("clr", "c");
4222 /* AOP_TYPE(right) == AOP_CRY */
4226 symbol *lbl = newiTempLabel (NULL);
4227 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4228 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4229 emitcode ("cpl", "c");
4230 emitcode ("", "%05d$:", (lbl->key + 100));
4233 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4240 genIfxJump (ifx, "c");
4243 /* if the result is used in an arithmetic operation
4244 then put the result in place */
4249 gencjne (left, right, newiTempLabel (NULL));
4250 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4252 aopPut (AOP (result), "a", 0);
4257 genIfxJump (ifx, "a");
4260 /* if the result is used in an arithmetic operation
4261 then put the result in place */
4262 if (AOP_TYPE (result) != AOP_CRY)
4264 /* leave the result in acc */
4268 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4270 freeAsmop (result, NULL, ic, TRUE);
4273 /*-----------------------------------------------------------------*/
4274 /* ifxForOp - returns the icode containing the ifx for operand */
4275 /*-----------------------------------------------------------------*/
4277 ifxForOp (operand * op, iCode * ic)
4279 /* if true symbol then needs to be assigned */
4280 if (IS_TRUE_SYMOP (op))
4283 /* if this has register type condition and
4284 the next instruction is ifx with the same operand
4285 and live to of the operand is upto the ifx only then */
4287 ic->next->op == IFX &&
4288 IC_COND (ic->next)->key == op->key &&
4289 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4295 /*-----------------------------------------------------------------*/
4296 /* hasInc - operand is incremented before any other use */
4297 /*-----------------------------------------------------------------*/
4299 hasInc (operand *op, iCode *ic)
4301 sym_link *type = operandType(op);
4302 sym_link *retype = getSpec (type);
4303 iCode *lic = ic->next;
4306 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4307 if (!IS_SYMOP(op)) return NULL;
4309 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4310 isize = getSize(type->next);
4312 /* if operand of the form op = op + <sizeof *op> */
4313 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4314 isOperandEqual(IC_RESULT(lic),op) &&
4315 isOperandLiteral(IC_RIGHT(lic)) &&
4316 operandLitValue(IC_RIGHT(lic)) == isize) {
4319 /* if the operand used or deffed */
4320 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4323 /* if GOTO or IFX */
4324 if (lic->op == IFX || lic->op == GOTO) break;
4330 /*-----------------------------------------------------------------*/
4331 /* genAndOp - for && operation */
4332 /*-----------------------------------------------------------------*/
4334 genAndOp (iCode * ic)
4336 operand *left, *right, *result;
4339 D(emitcode (";", "genAndOp"));
4341 /* note here that && operations that are in an
4342 if statement are taken away by backPatchLabels
4343 only those used in arthmetic operations remain */
4344 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4345 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4346 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4348 /* if both are bit variables */
4349 if (AOP_TYPE (left) == AOP_CRY &&
4350 AOP_TYPE (right) == AOP_CRY)
4352 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4353 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4358 tlbl = newiTempLabel (NULL);
4360 emitcode ("jz", "%05d$", tlbl->key + 100);
4362 emitcode ("", "%05d$:", tlbl->key + 100);
4366 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4367 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4368 freeAsmop (result, NULL, ic, TRUE);
4372 /*-----------------------------------------------------------------*/
4373 /* genOrOp - for || operation */
4374 /*-----------------------------------------------------------------*/
4376 genOrOp (iCode * ic)
4378 operand *left, *right, *result;
4381 D(emitcode (";", "genOrOp"));
4383 /* note here that || operations that are in an
4384 if statement are taken away by backPatchLabels
4385 only those used in arthmetic operations remain */
4386 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4387 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4388 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4390 /* if both are bit variables */
4391 if (AOP_TYPE (left) == AOP_CRY &&
4392 AOP_TYPE (right) == AOP_CRY)
4394 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4395 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4400 tlbl = newiTempLabel (NULL);
4402 emitcode ("jnz", "%05d$", tlbl->key + 100);
4404 emitcode ("", "%05d$:", tlbl->key + 100);
4408 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4409 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4410 freeAsmop (result, NULL, ic, TRUE);
4413 /*-----------------------------------------------------------------*/
4414 /* isLiteralBit - test if lit == 2^n */
4415 /*-----------------------------------------------------------------*/
4417 isLiteralBit (unsigned long lit)
4419 unsigned long pw[32] =
4420 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4421 0x100L, 0x200L, 0x400L, 0x800L,
4422 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4423 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4424 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4425 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4426 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4429 for (idx = 0; idx < 32; idx++)
4435 /*-----------------------------------------------------------------*/
4436 /* continueIfTrue - */
4437 /*-----------------------------------------------------------------*/
4439 continueIfTrue (iCode * ic)
4442 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4446 /*-----------------------------------------------------------------*/
4448 /*-----------------------------------------------------------------*/
4450 jumpIfTrue (iCode * ic)
4453 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4457 /*-----------------------------------------------------------------*/
4458 /* jmpTrueOrFalse - */
4459 /*-----------------------------------------------------------------*/
4461 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4463 // ugly but optimized by peephole
4466 symbol *nlbl = newiTempLabel (NULL);
4467 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4468 emitcode ("", "%05d$:", tlbl->key + 100);
4469 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4470 emitcode ("", "%05d$:", nlbl->key + 100);
4474 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4475 emitcode ("", "%05d$:", tlbl->key + 100);
4480 /*-----------------------------------------------------------------*/
4481 /* genAnd - code for and */
4482 /*-----------------------------------------------------------------*/
4484 genAnd (iCode * ic, iCode * ifx)
4486 operand *left, *right, *result;
4487 int size, offset = 0;
4488 unsigned long lit = 0L;
4492 D(emitcode (";", "genAnd"));
4494 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4495 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4496 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4499 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4501 AOP_TYPE (left), AOP_TYPE (right));
4502 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4504 AOP_SIZE (left), AOP_SIZE (right));
4507 /* if left is a literal & right is not then exchange them */
4508 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4509 AOP_NEEDSACC (left))
4511 operand *tmp = right;
4516 /* if result = right then exchange them */
4517 if (sameRegs (AOP (result), AOP (right)))
4519 operand *tmp = right;
4524 /* if right is bit then exchange them */
4525 if (AOP_TYPE (right) == AOP_CRY &&
4526 AOP_TYPE (left) != AOP_CRY)
4528 operand *tmp = right;
4532 if (AOP_TYPE (right) == AOP_LIT)
4533 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4535 size = AOP_SIZE (result);
4538 // result = bit & yy;
4539 if (AOP_TYPE (left) == AOP_CRY)
4541 // c = bit & literal;
4542 if (AOP_TYPE (right) == AOP_LIT)
4546 if (size && sameRegs (AOP (result), AOP (left)))
4549 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4554 if (size && (AOP_TYPE (result) == AOP_CRY))
4556 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4559 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4564 emitcode ("clr", "c");
4569 if (AOP_TYPE (right) == AOP_CRY)
4572 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4573 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4578 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4580 emitcode ("rrc", "a");
4581 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4589 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4590 genIfxJump (ifx, "c");
4594 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4595 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4596 if ((AOP_TYPE (right) == AOP_LIT) &&
4597 (AOP_TYPE (result) == AOP_CRY) &&
4598 (AOP_TYPE (left) != AOP_CRY))
4600 int posbit = isLiteralBit (lit);
4605 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4608 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4614 sprintf (buffer, "acc.%d", posbit & 0x07);
4615 genIfxJump (ifx, buffer);
4622 symbol *tlbl = newiTempLabel (NULL);
4623 int sizel = AOP_SIZE (left);
4625 emitcode ("setb", "c");
4628 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4630 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4632 if ((posbit = isLiteralBit (bytelit)) != 0)
4633 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4636 if (bytelit != 0x0FFL)
4637 emitcode ("anl", "a,%s",
4638 aopGet (AOP (right), offset, FALSE, TRUE));
4639 emitcode ("jnz", "%05d$", tlbl->key + 100);
4644 // bit = left & literal
4647 emitcode ("clr", "c");
4648 emitcode ("", "%05d$:", tlbl->key + 100);
4650 // if(left & literal)
4654 jmpTrueOrFalse (ifx, tlbl);
4662 /* if left is same as result */
4663 if (sameRegs (AOP (result), AOP (left)))
4665 for (; size--; offset++)
4667 if (AOP_TYPE (right) == AOP_LIT)
4669 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4671 else if (bytelit == 0)
4672 aopPut (AOP (result), zero, offset);
4673 else if (IS_AOP_PREG (result))
4675 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4676 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4677 aopPut (AOP (result), "a", offset);
4680 emitcode ("anl", "%s,%s",
4681 aopGet (AOP (left), offset, FALSE, TRUE),
4682 aopGet (AOP (right), offset, FALSE, FALSE));
4686 if (AOP_TYPE (left) == AOP_ACC)
4687 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4690 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4691 if (IS_AOP_PREG (result))
4693 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4694 aopPut (AOP (result), "a", offset);
4698 emitcode ("anl", "%s,a",
4699 aopGet (AOP (left), offset, FALSE, TRUE));
4706 // left & result in different registers
4707 if (AOP_TYPE (result) == AOP_CRY)
4710 // if(size), result in bit
4711 // if(!size && ifx), conditional oper: if(left & right)
4712 symbol *tlbl = newiTempLabel (NULL);
4713 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4715 emitcode ("setb", "c");
4718 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4719 emitcode ("anl", "a,%s",
4720 aopGet (AOP (right), offset, FALSE, FALSE));
4722 if (AOP_TYPE(left)==AOP_ACC) {
4723 emitcode("mov", "b,a");
4724 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4725 emitcode("anl", "a,b");
4727 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4728 emitcode ("anl", "a,%s",
4729 aopGet (AOP (left), offset, FALSE, FALSE));
4732 emitcode ("jnz", "%05d$", tlbl->key + 100);
4738 emitcode ("", "%05d$:", tlbl->key + 100);
4742 jmpTrueOrFalse (ifx, tlbl);
4746 for (; (size--); offset++)
4749 // result = left & right
4750 if (AOP_TYPE (right) == AOP_LIT)
4752 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4754 aopPut (AOP (result),
4755 aopGet (AOP (left), offset, FALSE, FALSE),
4759 else if (bytelit == 0)
4761 aopPut (AOP (result), zero, offset);
4765 // faster than result <- left, anl result,right
4766 // and better if result is SFR
4767 if (AOP_TYPE (left) == AOP_ACC)
4768 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4771 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4772 emitcode ("anl", "a,%s",
4773 aopGet (AOP (left), offset, FALSE, FALSE));
4775 aopPut (AOP (result), "a", offset);
4781 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4782 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4783 freeAsmop (result, NULL, ic, TRUE);
4786 /*-----------------------------------------------------------------*/
4787 /* genOr - code for or */
4788 /*-----------------------------------------------------------------*/
4790 genOr (iCode * ic, iCode * ifx)
4792 operand *left, *right, *result;
4793 int size, offset = 0;
4794 unsigned long lit = 0L;
4796 D(emitcode (";", "genOr"));
4798 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4799 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4800 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4803 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4805 AOP_TYPE (left), AOP_TYPE (right));
4806 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4808 AOP_SIZE (left), AOP_SIZE (right));
4811 /* if left is a literal & right is not then exchange them */
4812 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4813 AOP_NEEDSACC (left))
4815 operand *tmp = right;
4820 /* if result = right then exchange them */
4821 if (sameRegs (AOP (result), AOP (right)))
4823 operand *tmp = right;
4828 /* if right is bit then exchange them */
4829 if (AOP_TYPE (right) == AOP_CRY &&
4830 AOP_TYPE (left) != AOP_CRY)
4832 operand *tmp = right;
4836 if (AOP_TYPE (right) == AOP_LIT)
4837 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4839 size = AOP_SIZE (result);
4843 if (AOP_TYPE (left) == AOP_CRY)
4845 if (AOP_TYPE (right) == AOP_LIT)
4847 // c = bit & literal;
4850 // lit != 0 => result = 1
4851 if (AOP_TYPE (result) == AOP_CRY)
4854 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4856 continueIfTrue (ifx);
4859 emitcode ("setb", "c");
4863 // lit == 0 => result = left
4864 if (size && sameRegs (AOP (result), AOP (left)))
4866 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4871 if (AOP_TYPE (right) == AOP_CRY)
4874 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4875 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4880 symbol *tlbl = newiTempLabel (NULL);
4881 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4882 emitcode ("setb", "c");
4883 emitcode ("jb", "%s,%05d$",
4884 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4886 emitcode ("jnz", "%05d$", tlbl->key + 100);
4887 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4889 jmpTrueOrFalse (ifx, tlbl);
4895 emitcode ("", "%05d$:", tlbl->key + 100);
4904 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4905 genIfxJump (ifx, "c");
4909 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4910 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4911 if ((AOP_TYPE (right) == AOP_LIT) &&
4912 (AOP_TYPE (result) == AOP_CRY) &&
4913 (AOP_TYPE (left) != AOP_CRY))
4919 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4921 continueIfTrue (ifx);
4926 // lit = 0, result = boolean(left)
4928 emitcode ("setb", "c");
4932 symbol *tlbl = newiTempLabel (NULL);
4933 emitcode ("jnz", "%05d$", tlbl->key + 100);
4935 emitcode ("", "%05d$:", tlbl->key + 100);
4939 genIfxJump (ifx, "a");
4947 /* if left is same as result */
4948 if (sameRegs (AOP (result), AOP (left)))
4950 for (; size--; offset++)
4952 if (AOP_TYPE (right) == AOP_LIT)
4954 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4956 else if (IS_AOP_PREG (left))
4958 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4959 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4960 aopPut (AOP (result), "a", offset);
4963 emitcode ("orl", "%s,%s",
4964 aopGet (AOP (left), offset, FALSE, TRUE),
4965 aopGet (AOP (right), offset, FALSE, FALSE));
4969 if (AOP_TYPE (left) == AOP_ACC)
4970 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4973 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4974 if (IS_AOP_PREG (left))
4976 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4977 aopPut (AOP (result), "a", offset);
4980 emitcode ("orl", "%s,a",
4981 aopGet (AOP (left), offset, FALSE, TRUE));
4988 // left & result in different registers
4989 if (AOP_TYPE (result) == AOP_CRY)
4992 // if(size), result in bit
4993 // if(!size && ifx), conditional oper: if(left | right)
4994 symbol *tlbl = newiTempLabel (NULL);
4995 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4997 emitcode ("setb", "c");
5000 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5001 emitcode ("orl", "a,%s",
5002 aopGet (AOP (right), offset, FALSE, FALSE));
5004 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5005 emitcode ("orl", "a,%s",
5006 aopGet (AOP (left), offset, FALSE, FALSE));
5008 emitcode ("jnz", "%05d$", tlbl->key + 100);
5014 emitcode ("", "%05d$:", tlbl->key + 100);
5018 jmpTrueOrFalse (ifx, tlbl);
5021 for (; (size--); offset++)
5024 // result = left & right
5025 if (AOP_TYPE (right) == AOP_LIT)
5027 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5029 aopPut (AOP (result),
5030 aopGet (AOP (left), offset, FALSE, FALSE),
5035 // faster than result <- left, anl result,right
5036 // and better if result is SFR
5037 if (AOP_TYPE (left) == AOP_ACC)
5038 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5041 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5042 emitcode ("orl", "a,%s",
5043 aopGet (AOP (left), offset, FALSE, FALSE));
5045 aopPut (AOP (result), "a", offset);
5050 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5051 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5052 freeAsmop (result, NULL, ic, TRUE);
5055 /*-----------------------------------------------------------------*/
5056 /* genXor - code for xclusive or */
5057 /*-----------------------------------------------------------------*/
5059 genXor (iCode * ic, iCode * ifx)
5061 operand *left, *right, *result;
5062 int size, offset = 0;
5063 unsigned long lit = 0L;
5065 D(emitcode (";", "genXor"));
5067 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5068 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5069 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5072 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5074 AOP_TYPE (left), AOP_TYPE (right));
5075 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5077 AOP_SIZE (left), AOP_SIZE (right));
5080 /* if left is a literal & right is not ||
5081 if left needs acc & right does not */
5082 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5083 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5085 operand *tmp = right;
5090 /* if result = right then exchange them */
5091 if (sameRegs (AOP (result), AOP (right)))
5093 operand *tmp = right;
5098 /* if right is bit then exchange them */
5099 if (AOP_TYPE (right) == AOP_CRY &&
5100 AOP_TYPE (left) != AOP_CRY)
5102 operand *tmp = right;
5106 if (AOP_TYPE (right) == AOP_LIT)
5107 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5109 size = AOP_SIZE (result);
5113 if (AOP_TYPE (left) == AOP_CRY)
5115 if (AOP_TYPE (right) == AOP_LIT)
5117 // c = bit & literal;
5120 // lit>>1 != 0 => result = 1
5121 if (AOP_TYPE (result) == AOP_CRY)
5124 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5126 continueIfTrue (ifx);
5129 emitcode ("setb", "c");
5136 // lit == 0, result = left
5137 if (size && sameRegs (AOP (result), AOP (left)))
5139 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5143 // lit == 1, result = not(left)
5144 if (size && sameRegs (AOP (result), AOP (left)))
5146 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5151 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5152 emitcode ("cpl", "c");
5161 symbol *tlbl = newiTempLabel (NULL);
5162 if (AOP_TYPE (right) == AOP_CRY)
5165 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5169 int sizer = AOP_SIZE (right);
5171 // if val>>1 != 0, result = 1
5172 emitcode ("setb", "c");
5175 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5177 // test the msb of the lsb
5178 emitcode ("anl", "a,#0xfe");
5179 emitcode ("jnz", "%05d$", tlbl->key + 100);
5183 emitcode ("rrc", "a");
5185 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5186 emitcode ("cpl", "c");
5187 emitcode ("", "%05d$:", (tlbl->key + 100));
5194 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5195 genIfxJump (ifx, "c");
5199 if (sameRegs (AOP (result), AOP (left)))
5201 /* if left is same as result */
5202 for (; size--; offset++)
5204 if (AOP_TYPE (right) == AOP_LIT)
5206 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5208 else if (IS_AOP_PREG (left))
5210 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5211 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5212 aopPut (AOP (result), "a", offset);
5215 emitcode ("xrl", "%s,%s",
5216 aopGet (AOP (left), offset, FALSE, TRUE),
5217 aopGet (AOP (right), offset, FALSE, FALSE));
5221 if (AOP_TYPE (left) == AOP_ACC)
5222 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5225 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5226 if (IS_AOP_PREG (left))
5228 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5229 aopPut (AOP (result), "a", offset);
5232 emitcode ("xrl", "%s,a",
5233 aopGet (AOP (left), offset, FALSE, TRUE));
5240 // left & result in different registers
5241 if (AOP_TYPE (result) == AOP_CRY)
5244 // if(size), result in bit
5245 // if(!size && ifx), conditional oper: if(left ^ right)
5246 symbol *tlbl = newiTempLabel (NULL);
5247 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5249 emitcode ("setb", "c");
5252 if ((AOP_TYPE (right) == AOP_LIT) &&
5253 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5255 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5259 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5260 emitcode ("xrl", "a,%s",
5261 aopGet (AOP (right), offset, FALSE, FALSE));
5263 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5264 emitcode ("xrl", "a,%s",
5265 aopGet (AOP (left), offset, FALSE, FALSE));
5268 emitcode ("jnz", "%05d$", tlbl->key + 100);
5274 emitcode ("", "%05d$:", tlbl->key + 100);
5278 jmpTrueOrFalse (ifx, tlbl);
5281 for (; (size--); offset++)
5284 // result = left & right
5285 if (AOP_TYPE (right) == AOP_LIT)
5287 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5289 aopPut (AOP (result),
5290 aopGet (AOP (left), offset, FALSE, FALSE),
5295 // faster than result <- left, anl result,right
5296 // and better if result is SFR
5297 if (AOP_TYPE (left) == AOP_ACC)
5298 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5301 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5302 emitcode ("xrl", "a,%s",
5303 aopGet (AOP (left), offset, FALSE, TRUE));
5305 aopPut (AOP (result), "a", offset);
5310 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5311 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5312 freeAsmop (result, NULL, ic, TRUE);
5315 /*-----------------------------------------------------------------*/
5316 /* genInline - write the inline code out */
5317 /*-----------------------------------------------------------------*/
5319 genInline (iCode * ic)
5321 char *buffer, *bp, *bp1;
5323 D(emitcode (";", "genInline"));
5325 _G.inLine += (!options.asmpeep);
5327 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5328 strcpy (buffer, IC_INLINE (ic));
5330 /* emit each line as a code */
5355 /* emitcode("",buffer); */
5356 _G.inLine -= (!options.asmpeep);
5359 /*-----------------------------------------------------------------*/
5360 /* genRRC - rotate right with carry */
5361 /*-----------------------------------------------------------------*/
5365 operand *left, *result;
5366 int size, offset = 0;
5369 D(emitcode (";", "genRRC"));
5371 /* rotate right with carry */
5372 left = IC_LEFT (ic);
5373 result = IC_RESULT (ic);
5374 aopOp (left, ic, FALSE);
5375 aopOp (result, ic, FALSE);
5377 /* move it to the result */
5378 size = AOP_SIZE (result);
5380 if (size == 1) { /* special case for 1 byte */
5381 l = aopGet (AOP (left), offset, FALSE, FALSE);
5383 emitcode ("rr", "a");
5389 l = aopGet (AOP (left), offset, FALSE, FALSE);
5391 emitcode ("rrc", "a");
5392 if (AOP_SIZE (result) > 1)
5393 aopPut (AOP (result), "a", offset--);
5395 /* now we need to put the carry into the
5396 highest order byte of the result */
5397 if (AOP_SIZE (result) > 1)
5399 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5402 emitcode ("mov", "acc.7,c");
5404 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5405 freeAsmop (left, NULL, ic, TRUE);
5406 freeAsmop (result, NULL, ic, TRUE);
5409 /*-----------------------------------------------------------------*/
5410 /* genRLC - generate code for rotate left with carry */
5411 /*-----------------------------------------------------------------*/
5415 operand *left, *result;
5416 int size, offset = 0;
5419 D(emitcode (";", "genRLC"));
5421 /* rotate right with carry */
5422 left = IC_LEFT (ic);
5423 result = IC_RESULT (ic);
5424 aopOp (left, ic, FALSE);
5425 aopOp (result, ic, FALSE);
5427 /* move it to the result */
5428 size = AOP_SIZE (result);
5432 l = aopGet (AOP (left), offset, FALSE, FALSE);
5434 if (size == 0) { /* special case for 1 byte */
5438 emitcode ("add", "a,acc");
5439 if (AOP_SIZE (result) > 1)
5440 aopPut (AOP (result), "a", offset++);
5443 l = aopGet (AOP (left), offset, FALSE, FALSE);
5445 emitcode ("rlc", "a");
5446 if (AOP_SIZE (result) > 1)
5447 aopPut (AOP (result), "a", offset++);
5450 /* now we need to put the carry into the
5451 highest order byte of the result */
5452 if (AOP_SIZE (result) > 1)
5454 l = aopGet (AOP (result), 0, FALSE, FALSE);
5457 emitcode ("mov", "acc.0,c");
5459 aopPut (AOP (result), "a", 0);
5460 freeAsmop (left, NULL, ic, TRUE);
5461 freeAsmop (result, NULL, ic, TRUE);
5464 /*-----------------------------------------------------------------*/
5465 /* genGetHbit - generates code get highest order bit */
5466 /*-----------------------------------------------------------------*/
5468 genGetHbit (iCode * ic)
5470 operand *left, *result;
5472 D(emitcode (";", "genGetHbit"));
5474 left = IC_LEFT (ic);
5475 result = IC_RESULT (ic);
5476 aopOp (left, ic, FALSE);
5477 aopOp (result, ic, FALSE);
5479 /* get the highest order byte into a */
5480 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5481 if (AOP_TYPE (result) == AOP_CRY)
5483 emitcode ("rlc", "a");
5488 emitcode ("rl", "a");
5489 emitcode ("anl", "a,#0x01");
5494 freeAsmop (left, NULL, ic, TRUE);
5495 freeAsmop (result, NULL, ic, TRUE);
5498 /*-----------------------------------------------------------------*/
5499 /* AccRol - rotate left accumulator by known count */
5500 /*-----------------------------------------------------------------*/
5502 AccRol (int shCount)
5504 shCount &= 0x0007; // shCount : 0..7
5511 emitcode ("rl", "a");
5514 emitcode ("rl", "a");
5515 emitcode ("rl", "a");
5518 emitcode ("swap", "a");
5519 emitcode ("rr", "a");
5522 emitcode ("swap", "a");
5525 emitcode ("swap", "a");
5526 emitcode ("rl", "a");
5529 emitcode ("rr", "a");
5530 emitcode ("rr", "a");
5533 emitcode ("rr", "a");
5538 /*-----------------------------------------------------------------*/
5539 /* AccLsh - left shift accumulator by known count */
5540 /*-----------------------------------------------------------------*/
5542 AccLsh (int shCount)
5547 emitcode ("add", "a,acc");
5548 else if (shCount == 2)
5550 emitcode ("add", "a,acc");
5551 emitcode ("add", "a,acc");
5555 /* rotate left accumulator */
5557 /* and kill the lower order bits */
5558 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5563 /*-----------------------------------------------------------------*/
5564 /* AccRsh - right shift accumulator by known count */
5565 /*-----------------------------------------------------------------*/
5567 AccRsh (int shCount)
5574 emitcode ("rrc", "a");
5578 /* rotate right accumulator */
5579 AccRol (8 - shCount);
5580 /* and kill the higher order bits */
5581 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5586 /*-----------------------------------------------------------------*/
5587 /* AccSRsh - signed right shift accumulator by known count */
5588 /*-----------------------------------------------------------------*/
5590 AccSRsh (int shCount)
5597 emitcode ("mov", "c,acc.7");
5598 emitcode ("rrc", "a");
5600 else if (shCount == 2)
5602 emitcode ("mov", "c,acc.7");
5603 emitcode ("rrc", "a");
5604 emitcode ("mov", "c,acc.7");
5605 emitcode ("rrc", "a");
5609 tlbl = newiTempLabel (NULL);
5610 /* rotate right accumulator */
5611 AccRol (8 - shCount);
5612 /* and kill the higher order bits */
5613 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5614 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5615 emitcode ("orl", "a,#0x%02x",
5616 (unsigned char) ~SRMask[shCount]);
5617 emitcode ("", "%05d$:", tlbl->key + 100);
5622 /*-----------------------------------------------------------------*/
5623 /* shiftR1Left2Result - shift right one byte from left to result */
5624 /*-----------------------------------------------------------------*/
5626 shiftR1Left2Result (operand * left, int offl,
5627 operand * result, int offr,
5628 int shCount, int sign)
5630 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5631 /* shift right accumulator */
5636 aopPut (AOP (result), "a", offr);
5639 /*-----------------------------------------------------------------*/
5640 /* shiftL1Left2Result - shift left one byte from left to result */
5641 /*-----------------------------------------------------------------*/
5643 shiftL1Left2Result (operand * left, int offl,
5644 operand * result, int offr, int shCount)
5647 l = aopGet (AOP (left), offl, FALSE, FALSE);
5649 /* shift left accumulator */
5651 aopPut (AOP (result), "a", offr);
5654 /*-----------------------------------------------------------------*/
5655 /* movLeft2Result - move byte from left to result */
5656 /*-----------------------------------------------------------------*/
5658 movLeft2Result (operand * left, int offl,
5659 operand * result, int offr, int sign)
5662 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5664 l = aopGet (AOP (left), offl, FALSE, FALSE);
5666 if (*l == '@' && (IS_AOP_PREG (result)))
5668 emitcode ("mov", "a,%s", l);
5669 aopPut (AOP (result), "a", offr);
5674 aopPut (AOP (result), l, offr);
5677 /* MSB sign in acc.7 ! */
5678 if (getDataSize (left) == offl + 1)
5680 emitcode ("mov", "a,%s", l);
5681 aopPut (AOP (result), "a", offr);
5688 /*-----------------------------------------------------------------*/
5689 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5690 /*-----------------------------------------------------------------*/
5694 emitcode ("rrc", "a");
5695 emitcode ("xch", "a,%s", x);
5696 emitcode ("rrc", "a");
5697 emitcode ("xch", "a,%s", x);
5700 /*-----------------------------------------------------------------*/
5701 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5702 /*-----------------------------------------------------------------*/
5706 emitcode ("xch", "a,%s", x);
5707 emitcode ("rlc", "a");
5708 emitcode ("xch", "a,%s", x);
5709 emitcode ("rlc", "a");
5712 /*-----------------------------------------------------------------*/
5713 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5714 /*-----------------------------------------------------------------*/
5718 emitcode ("xch", "a,%s", x);
5719 emitcode ("add", "a,acc");
5720 emitcode ("xch", "a,%s", x);
5721 emitcode ("rlc", "a");
5724 /*-----------------------------------------------------------------*/
5725 /* AccAXLsh - left shift a:x by known count (0..7) */
5726 /*-----------------------------------------------------------------*/
5728 AccAXLsh (char *x, int shCount)
5743 case 5: // AAAAABBB:CCCCCDDD
5745 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5747 emitcode ("anl", "a,#0x%02x",
5748 SLMask[shCount]); // BBB00000:CCCCCDDD
5750 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5752 AccRol (shCount); // DDDCCCCC:BBB00000
5754 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5756 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5758 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5760 emitcode ("anl", "a,#0x%02x",
5761 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5763 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5765 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5768 case 6: // AAAAAABB:CCCCCCDD
5769 emitcode ("anl", "a,#0x%02x",
5770 SRMask[shCount]); // 000000BB:CCCCCCDD
5771 emitcode ("mov", "c,acc.0"); // c = B
5772 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5774 AccAXRrl1 (x); // BCCCCCCD:D000000B
5775 AccAXRrl1 (x); // BBCCCCCC:DD000000
5777 emitcode("rrc","a");
5778 emitcode("xch","a,%s", x);
5779 emitcode("rrc","a");
5780 emitcode("mov","c,acc.0"); //<< get correct bit
5781 emitcode("xch","a,%s", x);
5783 emitcode("rrc","a");
5784 emitcode("xch","a,%s", x);
5785 emitcode("rrc","a");
5786 emitcode("xch","a,%s", x);
5789 case 7: // a:x <<= 7
5791 emitcode ("anl", "a,#0x%02x",
5792 SRMask[shCount]); // 0000000B:CCCCCCCD
5794 emitcode ("mov", "c,acc.0"); // c = B
5796 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5798 AccAXRrl1 (x); // BCCCCCCC:D0000000
5806 /*-----------------------------------------------------------------*/
5807 /* AccAXRsh - right shift a:x known count (0..7) */
5808 /*-----------------------------------------------------------------*/
5810 AccAXRsh (char *x, int shCount)
5818 AccAXRrl1 (x); // 0->a:x
5823 AccAXRrl1 (x); // 0->a:x
5826 AccAXRrl1 (x); // 0->a:x
5831 case 5: // AAAAABBB:CCCCCDDD = a:x
5833 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5835 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5837 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5839 emitcode ("anl", "a,#0x%02x",
5840 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5842 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5844 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5846 emitcode ("anl", "a,#0x%02x",
5847 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5849 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5851 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5853 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5856 case 6: // AABBBBBB:CCDDDDDD
5858 emitcode ("mov", "c,acc.7");
5859 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5861 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5863 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5865 emitcode ("anl", "a,#0x%02x",
5866 SRMask[shCount]); // 000000AA:BBBBBBCC
5869 case 7: // ABBBBBBB:CDDDDDDD
5871 emitcode ("mov", "c,acc.7"); // c = A
5873 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5875 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5877 emitcode ("anl", "a,#0x%02x",
5878 SRMask[shCount]); // 0000000A:BBBBBBBC
5886 /*-----------------------------------------------------------------*/
5887 /* AccAXRshS - right shift signed a:x known count (0..7) */
5888 /*-----------------------------------------------------------------*/
5890 AccAXRshS (char *x, int shCount)
5898 emitcode ("mov", "c,acc.7");
5899 AccAXRrl1 (x); // s->a:x
5903 emitcode ("mov", "c,acc.7");
5904 AccAXRrl1 (x); // s->a:x
5906 emitcode ("mov", "c,acc.7");
5907 AccAXRrl1 (x); // s->a:x
5912 case 5: // AAAAABBB:CCCCCDDD = a:x
5914 tlbl = newiTempLabel (NULL);
5915 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5917 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5919 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5921 emitcode ("anl", "a,#0x%02x",
5922 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5924 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5926 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5928 emitcode ("anl", "a,#0x%02x",
5929 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5931 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5933 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5935 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5937 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5938 emitcode ("orl", "a,#0x%02x",
5939 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5941 emitcode ("", "%05d$:", tlbl->key + 100);
5942 break; // SSSSAAAA:BBBCCCCC
5944 case 6: // AABBBBBB:CCDDDDDD
5946 tlbl = newiTempLabel (NULL);
5947 emitcode ("mov", "c,acc.7");
5948 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5950 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5952 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5954 emitcode ("anl", "a,#0x%02x",
5955 SRMask[shCount]); // 000000AA:BBBBBBCC
5957 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5958 emitcode ("orl", "a,#0x%02x",
5959 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5961 emitcode ("", "%05d$:", tlbl->key + 100);
5963 case 7: // ABBBBBBB:CDDDDDDD
5965 tlbl = newiTempLabel (NULL);
5966 emitcode ("mov", "c,acc.7"); // c = A
5968 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5970 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5972 emitcode ("anl", "a,#0x%02x",
5973 SRMask[shCount]); // 0000000A:BBBBBBBC
5975 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5976 emitcode ("orl", "a,#0x%02x",
5977 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5979 emitcode ("", "%05d$:", tlbl->key + 100);
5986 /*-----------------------------------------------------------------*/
5987 /* shiftL2Left2Result - shift left two bytes from left to result */
5988 /*-----------------------------------------------------------------*/
5990 shiftL2Left2Result (operand * left, int offl,
5991 operand * result, int offr, int shCount)
5993 if (sameRegs (AOP (result), AOP (left)) &&
5994 ((offl + MSB16) == offr))
5996 /* don't crash result[offr] */
5997 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5998 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6002 movLeft2Result (left, offl, result, offr, 0);
6003 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6005 /* ax << shCount (x = lsb(result)) */
6006 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6007 aopPut (AOP (result), "a", offr + MSB16);
6011 /*-----------------------------------------------------------------*/
6012 /* shiftR2Left2Result - shift right two bytes from left to result */
6013 /*-----------------------------------------------------------------*/
6015 shiftR2Left2Result (operand * left, int offl,
6016 operand * result, int offr,
6017 int shCount, int sign)
6019 if (sameRegs (AOP (result), AOP (left)) &&
6020 ((offl + MSB16) == offr))
6022 /* don't crash result[offr] */
6023 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6024 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6028 movLeft2Result (left, offl, result, offr, 0);
6029 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6031 /* a:x >> shCount (x = lsb(result)) */
6033 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6035 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6036 if (getDataSize (result) > 1)
6037 aopPut (AOP (result), "a", offr + MSB16);
6040 /*-----------------------------------------------------------------*/
6041 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6042 /*-----------------------------------------------------------------*/
6044 shiftLLeftOrResult (operand * left, int offl,
6045 operand * result, int offr, int shCount)
6047 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6048 /* shift left accumulator */
6050 /* or with result */
6051 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6052 /* back to result */
6053 aopPut (AOP (result), "a", offr);
6056 /*-----------------------------------------------------------------*/
6057 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6058 /*-----------------------------------------------------------------*/
6060 shiftRLeftOrResult (operand * left, int offl,
6061 operand * result, int offr, int shCount)
6063 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6064 /* shift right accumulator */
6066 /* or with result */
6067 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6068 /* back to result */
6069 aopPut (AOP (result), "a", offr);
6072 /*-----------------------------------------------------------------*/
6073 /* genlshOne - left shift a one byte quantity by known count */
6074 /*-----------------------------------------------------------------*/
6076 genlshOne (operand * result, operand * left, int shCount)
6078 D(emitcode (";", "genlshOne"));
6080 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6083 /*-----------------------------------------------------------------*/
6084 /* genlshTwo - left shift two bytes by known amount != 0 */
6085 /*-----------------------------------------------------------------*/
6087 genlshTwo (operand * result, operand * left, int shCount)
6091 D(emitcode (";", "genlshTwo"));
6093 size = getDataSize (result);
6095 /* if shCount >= 8 */
6103 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6105 movLeft2Result (left, LSB, result, MSB16, 0);
6107 aopPut (AOP (result), zero, LSB);
6110 /* 1 <= shCount <= 7 */
6114 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6116 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6120 /*-----------------------------------------------------------------*/
6121 /* shiftLLong - shift left one long from left to result */
6122 /* offl = LSB or MSB16 */
6123 /*-----------------------------------------------------------------*/
6125 shiftLLong (operand * left, operand * result, int offr)
6128 int size = AOP_SIZE (result);
6130 if (size >= LSB + offr)
6132 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6134 emitcode ("add", "a,acc");
6135 if (sameRegs (AOP (left), AOP (result)) &&
6136 size >= MSB16 + offr && offr != LSB)
6137 emitcode ("xch", "a,%s",
6138 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6140 aopPut (AOP (result), "a", LSB + offr);
6143 if (size >= MSB16 + offr)
6145 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6147 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6150 emitcode ("rlc", "a");
6151 if (sameRegs (AOP (left), AOP (result)) &&
6152 size >= MSB24 + offr && offr != LSB)
6153 emitcode ("xch", "a,%s",
6154 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6156 aopPut (AOP (result), "a", MSB16 + offr);
6159 if (size >= MSB24 + offr)
6161 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6163 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6166 emitcode ("rlc", "a");
6167 if (sameRegs (AOP (left), AOP (result)) &&
6168 size >= MSB32 + offr && offr != LSB)
6169 emitcode ("xch", "a,%s",
6170 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6172 aopPut (AOP (result), "a", MSB24 + offr);
6175 if (size > MSB32 + offr)
6177 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6179 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6182 emitcode ("rlc", "a");
6183 aopPut (AOP (result), "a", MSB32 + offr);
6186 aopPut (AOP (result), zero, LSB);
6189 /*-----------------------------------------------------------------*/
6190 /* genlshFour - shift four byte by a known amount != 0 */
6191 /*-----------------------------------------------------------------*/
6193 genlshFour (operand * result, operand * left, int shCount)
6197 D(emitcode (";", "genlshFour"));
6199 size = AOP_SIZE (result);
6201 /* if shifting more that 3 bytes */
6206 /* lowest order of left goes to the highest
6207 order of the destination */
6208 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6210 movLeft2Result (left, LSB, result, MSB32, 0);
6211 aopPut (AOP (result), zero, LSB);
6212 aopPut (AOP (result), zero, MSB16);
6213 aopPut (AOP (result), zero, MSB24);
6217 /* more than two bytes */
6218 else if (shCount >= 16)
6220 /* lower order two bytes goes to higher order two bytes */
6222 /* if some more remaining */
6224 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6227 movLeft2Result (left, MSB16, result, MSB32, 0);
6228 movLeft2Result (left, LSB, result, MSB24, 0);
6230 aopPut (AOP (result), zero, MSB16);
6231 aopPut (AOP (result), zero, LSB);
6235 /* if more than 1 byte */
6236 else if (shCount >= 8)
6238 /* lower order three bytes goes to higher order three bytes */
6243 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6245 movLeft2Result (left, LSB, result, MSB16, 0);
6251 movLeft2Result (left, MSB24, result, MSB32, 0);
6252 movLeft2Result (left, MSB16, result, MSB24, 0);
6253 movLeft2Result (left, LSB, result, MSB16, 0);
6254 aopPut (AOP (result), zero, LSB);
6256 else if (shCount == 1)
6257 shiftLLong (left, result, MSB16);
6260 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6261 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6262 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6263 aopPut (AOP (result), zero, LSB);
6268 /* 1 <= shCount <= 7 */
6269 else if (shCount <= 2)
6271 shiftLLong (left, result, LSB);
6273 shiftLLong (result, result, LSB);
6275 /* 3 <= shCount <= 7, optimize */
6278 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6279 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6280 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6284 /*-----------------------------------------------------------------*/
6285 /* genLeftShiftLiteral - left shifting by known count */
6286 /*-----------------------------------------------------------------*/
6288 genLeftShiftLiteral (operand * left,
6293 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6296 D(emitcode (";", "genLeftShiftLiteral"));
6298 freeAsmop (right, NULL, ic, TRUE);
6300 aopOp (left, ic, FALSE);
6301 aopOp (result, ic, FALSE);
6303 size = getSize (operandType (result));
6306 emitcode ("; shift left ", "result %d, left %d", size,
6310 /* I suppose that the left size >= result size */
6315 movLeft2Result (left, size, result, size, 0);
6319 else if (shCount >= (size * 8))
6321 aopPut (AOP (result), zero, size);
6327 genlshOne (result, left, shCount);
6331 genlshTwo (result, left, shCount);
6335 genlshFour (result, left, shCount);
6338 fprintf(stderr, "*** ack! mystery literal shift!\n");
6342 freeAsmop (left, NULL, ic, TRUE);
6343 freeAsmop (result, NULL, ic, TRUE);
6346 /*-----------------------------------------------------------------*/
6347 /* genLeftShift - generates code for left shifting */
6348 /*-----------------------------------------------------------------*/
6350 genLeftShift (iCode * ic)
6352 operand *left, *right, *result;
6355 symbol *tlbl, *tlbl1;
6357 D(emitcode (";", "genLeftShift"));
6359 right = IC_RIGHT (ic);
6360 left = IC_LEFT (ic);
6361 result = IC_RESULT (ic);
6363 aopOp (right, ic, FALSE);
6365 /* if the shift count is known then do it
6366 as efficiently as possible */
6367 if (AOP_TYPE (right) == AOP_LIT)
6369 genLeftShiftLiteral (left, right, result, ic);
6373 /* shift count is unknown then we have to form
6374 a loop get the loop count in B : Note: we take
6375 only the lower order byte since shifting
6376 more that 32 bits make no sense anyway, ( the
6377 largest size of an object can be only 32 bits ) */
6379 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6380 emitcode ("inc", "b");
6381 freeAsmop (right, NULL, ic, TRUE);
6382 aopOp (left, ic, FALSE);
6383 aopOp (result, ic, FALSE);
6385 /* now move the left to the result if they are not the
6387 if (!sameRegs (AOP (left), AOP (result)) &&
6388 AOP_SIZE (result) > 1)
6391 size = AOP_SIZE (result);
6395 l = aopGet (AOP (left), offset, FALSE, TRUE);
6396 if (*l == '@' && (IS_AOP_PREG (result)))
6399 emitcode ("mov", "a,%s", l);
6400 aopPut (AOP (result), "a", offset);
6403 aopPut (AOP (result), l, offset);
6408 tlbl = newiTempLabel (NULL);
6409 size = AOP_SIZE (result);
6411 tlbl1 = newiTempLabel (NULL);
6413 /* if it is only one byte then */
6416 symbol *tlbl1 = newiTempLabel (NULL);
6418 l = aopGet (AOP (left), 0, FALSE, FALSE);
6420 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6421 emitcode ("", "%05d$:", tlbl->key + 100);
6422 emitcode ("add", "a,acc");
6423 emitcode ("", "%05d$:", tlbl1->key + 100);
6424 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6425 aopPut (AOP (result), "a", 0);
6429 reAdjustPreg (AOP (result));
6431 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6432 emitcode ("", "%05d$:", tlbl->key + 100);
6433 l = aopGet (AOP (result), offset, FALSE, FALSE);
6435 emitcode ("add", "a,acc");
6436 aopPut (AOP (result), "a", offset++);
6439 l = aopGet (AOP (result), offset, FALSE, FALSE);
6441 emitcode ("rlc", "a");
6442 aopPut (AOP (result), "a", offset++);
6444 reAdjustPreg (AOP (result));
6446 emitcode ("", "%05d$:", tlbl1->key + 100);
6447 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6449 freeAsmop (left, NULL, ic, TRUE);
6450 freeAsmop (result, NULL, ic, TRUE);
6453 /*-----------------------------------------------------------------*/
6454 /* genrshOne - right shift a one byte quantity by known count */
6455 /*-----------------------------------------------------------------*/
6457 genrshOne (operand * result, operand * left,
6458 int shCount, int sign)
6460 D(emitcode (";", "genrshOne"));
6462 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6465 /*-----------------------------------------------------------------*/
6466 /* genrshTwo - right shift two bytes by known amount != 0 */
6467 /*-----------------------------------------------------------------*/
6469 genrshTwo (operand * result, operand * left,
6470 int shCount, int sign)
6472 D(emitcode (";", "genrshTwo"));
6474 /* if shCount >= 8 */
6479 shiftR1Left2Result (left, MSB16, result, LSB,
6482 movLeft2Result (left, MSB16, result, LSB, sign);
6483 addSign (result, MSB16, sign);
6486 /* 1 <= shCount <= 7 */
6488 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6491 /*-----------------------------------------------------------------*/
6492 /* shiftRLong - shift right one long from left to result */
6493 /* offl = LSB or MSB16 */
6494 /*-----------------------------------------------------------------*/
6496 shiftRLong (operand * left, int offl,
6497 operand * result, int sign)
6499 int isSameRegs=sameRegs(AOP(left),AOP(result));
6501 if (isSameRegs && offl>1) {
6502 // we are in big trouble, but this shouldn't happen
6503 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6506 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6511 emitcode ("rlc", "a");
6512 emitcode ("subb", "a,acc");
6513 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6515 aopPut (AOP(result), zero, MSB32);
6520 emitcode ("clr", "c");
6522 emitcode ("mov", "c,acc.7");
6525 emitcode ("rrc", "a");
6527 if (isSameRegs && offl==MSB16) {
6528 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6530 aopPut (AOP (result), "a", MSB32);
6531 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6534 emitcode ("rrc", "a");
6535 if (isSameRegs && offl==1) {
6536 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6538 aopPut (AOP (result), "a", MSB24);
6539 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6541 emitcode ("rrc", "a");
6542 aopPut (AOP (result), "a", MSB16 - offl);
6546 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6547 emitcode ("rrc", "a");
6548 aopPut (AOP (result), "a", LSB);
6552 /*-----------------------------------------------------------------*/
6553 /* genrshFour - shift four byte by a known amount != 0 */
6554 /*-----------------------------------------------------------------*/
6556 genrshFour (operand * result, operand * left,
6557 int shCount, int sign)
6559 D(emitcode (";", "genrshFour"));
6561 /* if shifting more that 3 bytes */
6566 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6568 movLeft2Result (left, MSB32, result, LSB, sign);
6569 addSign (result, MSB16, sign);
6571 else if (shCount >= 16)
6575 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6578 movLeft2Result (left, MSB24, result, LSB, 0);
6579 movLeft2Result (left, MSB32, result, MSB16, sign);
6581 addSign (result, MSB24, sign);
6583 else if (shCount >= 8)
6587 shiftRLong (left, MSB16, result, sign);
6588 else if (shCount == 0)
6590 movLeft2Result (left, MSB16, result, LSB, 0);
6591 movLeft2Result (left, MSB24, result, MSB16, 0);
6592 movLeft2Result (left, MSB32, result, MSB24, sign);
6593 addSign (result, MSB32, sign);
6597 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6598 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6599 /* the last shift is signed */
6600 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6601 addSign (result, MSB32, sign);
6605 { /* 1 <= shCount <= 7 */
6608 shiftRLong (left, LSB, result, sign);
6610 shiftRLong (result, LSB, result, sign);
6614 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6615 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6616 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6621 /*-----------------------------------------------------------------*/
6622 /* genRightShiftLiteral - right shifting by known count */
6623 /*-----------------------------------------------------------------*/
6625 genRightShiftLiteral (operand * left,
6631 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6634 D(emitcode (";", "genRightShiftLiteral"));
6636 freeAsmop (right, NULL, ic, TRUE);
6638 aopOp (left, ic, FALSE);
6639 aopOp (result, ic, FALSE);
6642 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6646 size = getDataSize (left);
6647 /* test the LEFT size !!! */
6649 /* I suppose that the left size >= result size */
6652 size = getDataSize (result);
6654 movLeft2Result (left, size, result, size, 0);
6657 else if (shCount >= (size * 8))
6660 /* get sign in acc.7 */
6661 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6662 addSign (result, LSB, sign);
6669 genrshOne (result, left, shCount, sign);
6673 genrshTwo (result, left, shCount, sign);
6677 genrshFour (result, left, shCount, sign);
6683 freeAsmop (left, NULL, ic, TRUE);
6684 freeAsmop (result, NULL, ic, TRUE);
6688 /*-----------------------------------------------------------------*/
6689 /* genSignedRightShift - right shift of signed number */
6690 /*-----------------------------------------------------------------*/
6692 genSignedRightShift (iCode * ic)
6694 operand *right, *left, *result;
6697 symbol *tlbl, *tlbl1;
6699 D(emitcode (";", "genSignedRightShift"));
6701 /* we do it the hard way put the shift count in b
6702 and loop thru preserving the sign */
6704 right = IC_RIGHT (ic);
6705 left = IC_LEFT (ic);
6706 result = IC_RESULT (ic);
6708 aopOp (right, ic, FALSE);
6711 if (AOP_TYPE (right) == AOP_LIT)
6713 genRightShiftLiteral (left, right, result, ic, 1);
6716 /* shift count is unknown then we have to form
6717 a loop get the loop count in B : Note: we take
6718 only the lower order byte since shifting
6719 more that 32 bits make no sense anyway, ( the
6720 largest size of an object can be only 32 bits ) */
6722 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6723 emitcode ("inc", "b");
6724 freeAsmop (right, NULL, ic, TRUE);
6725 aopOp (left, ic, FALSE);
6726 aopOp (result, ic, FALSE);
6728 /* now move the left to the result if they are not the
6730 if (!sameRegs (AOP (left), AOP (result)) &&
6731 AOP_SIZE (result) > 1)
6734 size = AOP_SIZE (result);
6738 l = aopGet (AOP (left), offset, FALSE, TRUE);
6739 if (*l == '@' && IS_AOP_PREG (result))
6742 emitcode ("mov", "a,%s", l);
6743 aopPut (AOP (result), "a", offset);
6746 aopPut (AOP (result), l, offset);
6751 /* mov the highest order bit to OVR */
6752 tlbl = newiTempLabel (NULL);
6753 tlbl1 = newiTempLabel (NULL);
6755 size = AOP_SIZE (result);
6757 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6758 emitcode ("rlc", "a");
6759 emitcode ("mov", "ov,c");
6760 /* if it is only one byte then */
6763 l = aopGet (AOP (left), 0, FALSE, FALSE);
6765 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6766 emitcode ("", "%05d$:", tlbl->key + 100);
6767 emitcode ("mov", "c,ov");
6768 emitcode ("rrc", "a");
6769 emitcode ("", "%05d$:", tlbl1->key + 100);
6770 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6771 aopPut (AOP (result), "a", 0);
6775 reAdjustPreg (AOP (result));
6776 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6777 emitcode ("", "%05d$:", tlbl->key + 100);
6778 emitcode ("mov", "c,ov");
6781 l = aopGet (AOP (result), offset, FALSE, FALSE);
6783 emitcode ("rrc", "a");
6784 aopPut (AOP (result), "a", offset--);
6786 reAdjustPreg (AOP (result));
6787 emitcode ("", "%05d$:", tlbl1->key + 100);
6788 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6791 freeAsmop (left, NULL, ic, TRUE);
6792 freeAsmop (result, NULL, ic, TRUE);
6795 /*-----------------------------------------------------------------*/
6796 /* genRightShift - generate code for right shifting */
6797 /*-----------------------------------------------------------------*/
6799 genRightShift (iCode * ic)
6801 operand *right, *left, *result;
6805 symbol *tlbl, *tlbl1;
6807 D(emitcode (";", "genRightShift"));
6809 /* if signed then we do it the hard way preserve the
6810 sign bit moving it inwards */
6811 retype = getSpec (operandType (IC_RESULT (ic)));
6813 if (!SPEC_USIGN (retype))
6815 genSignedRightShift (ic);
6819 /* signed & unsigned types are treated the same : i.e. the
6820 signed is NOT propagated inwards : quoting from the
6821 ANSI - standard : "for E1 >> E2, is equivalent to division
6822 by 2**E2 if unsigned or if it has a non-negative value,
6823 otherwise the result is implementation defined ", MY definition
6824 is that the sign does not get propagated */
6826 right = IC_RIGHT (ic);
6827 left = IC_LEFT (ic);
6828 result = IC_RESULT (ic);
6830 aopOp (right, ic, FALSE);
6832 /* if the shift count is known then do it
6833 as efficiently as possible */
6834 if (AOP_TYPE (right) == AOP_LIT)
6836 genRightShiftLiteral (left, right, result, ic, 0);
6840 /* shift count is unknown then we have to form
6841 a loop get the loop count in B : Note: we take
6842 only the lower order byte since shifting
6843 more that 32 bits make no sense anyway, ( the
6844 largest size of an object can be only 32 bits ) */
6846 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6847 emitcode ("inc", "b");
6848 freeAsmop (right, NULL, ic, TRUE);
6849 aopOp (left, ic, FALSE);
6850 aopOp (result, ic, FALSE);
6852 /* now move the left to the result if they are not the
6854 if (!sameRegs (AOP (left), AOP (result)) &&
6855 AOP_SIZE (result) > 1)
6858 size = AOP_SIZE (result);
6862 l = aopGet (AOP (left), offset, FALSE, TRUE);
6863 if (*l == '@' && IS_AOP_PREG (result))
6866 emitcode ("mov", "a,%s", l);
6867 aopPut (AOP (result), "a", offset);
6870 aopPut (AOP (result), l, offset);
6875 tlbl = newiTempLabel (NULL);
6876 tlbl1 = newiTempLabel (NULL);
6877 size = AOP_SIZE (result);
6880 /* if it is only one byte then */
6883 l = aopGet (AOP (left), 0, FALSE, FALSE);
6885 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6886 emitcode ("", "%05d$:", tlbl->key + 100);
6888 emitcode ("rrc", "a");
6889 emitcode ("", "%05d$:", tlbl1->key + 100);
6890 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6891 aopPut (AOP (result), "a", 0);
6895 reAdjustPreg (AOP (result));
6896 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6897 emitcode ("", "%05d$:", tlbl->key + 100);
6901 l = aopGet (AOP (result), offset, FALSE, FALSE);
6903 emitcode ("rrc", "a");
6904 aopPut (AOP (result), "a", offset--);
6906 reAdjustPreg (AOP (result));
6908 emitcode ("", "%05d$:", tlbl1->key + 100);
6909 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6912 freeAsmop (left, NULL, ic, TRUE);
6913 freeAsmop (result, NULL, ic, TRUE);
6916 /*-----------------------------------------------------------------*/
6917 /* genUnpackBits - generates code for unpacking bits */
6918 /*-----------------------------------------------------------------*/
6920 genUnpackBits (operand * result, char *rname, int ptype)
6928 D(emitcode (";", "genUnpackBits"));
6930 etype = getSpec (operandType (result));
6931 rsize = getSize (operandType (result));
6932 /* read the first byte */
6938 emitcode ("mov", "a,@%s", rname);
6942 emitcode ("movx", "a,@%s", rname);
6946 emitcode ("movx", "a,@dptr");
6950 emitcode ("clr", "a");
6951 emitcode ("movc", "a,@a+dptr");
6955 emitcode ("lcall", "__gptrget");
6959 rlen = SPEC_BLEN (etype);
6961 /* if we have bitdisplacement then it fits */
6962 /* into this byte completely or if length is */
6963 /* less than a byte */
6964 if ((shCnt = SPEC_BSTR (etype)) ||
6965 (SPEC_BLEN (etype) <= 8))
6968 /* shift right acc */
6971 emitcode ("anl", "a,#0x%02x",
6972 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6973 aopPut (AOP (result), "a", offset++);
6977 /* bit field did not fit in a byte */
6978 aopPut (AOP (result), "a", offset++);
6987 emitcode ("inc", "%s", rname);
6988 emitcode ("mov", "a,@%s", rname);
6992 emitcode ("inc", "%s", rname);
6993 emitcode ("movx", "a,@%s", rname);
6997 emitcode ("inc", "dptr");
6998 emitcode ("movx", "a,@dptr");
7002 emitcode ("clr", "a");
7003 emitcode ("inc", "dptr");
7004 emitcode ("movc", "a,@a+dptr");
7008 emitcode ("inc", "dptr");
7009 emitcode ("lcall", "__gptrget");
7014 /* if we are done */
7018 aopPut (AOP (result), "a", offset++);
7024 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7026 aopPut (AOP (result), "a", offset++);
7034 aopPut (AOP (result), zero, offset++);
7040 /*-----------------------------------------------------------------*/
7041 /* genDataPointerGet - generates code when ptr offset is known */
7042 /*-----------------------------------------------------------------*/
7044 genDataPointerGet (operand * left,
7050 int size, offset = 0;
7052 D(emitcode (";", "genDataPointerGet"));
7054 aopOp (result, ic, TRUE);
7056 /* get the string representation of the name */
7057 l = aopGet (AOP (left), 0, FALSE, TRUE);
7058 size = AOP_SIZE (result);
7062 sprintf (buffer, "(%s + %d)", l + 1, offset);
7064 sprintf (buffer, "%s", l + 1);
7065 aopPut (AOP (result), buffer, offset++);
7068 freeAsmop (left, NULL, ic, TRUE);
7069 freeAsmop (result, NULL, ic, TRUE);
7072 /*-----------------------------------------------------------------*/
7073 /* genNearPointerGet - emitcode for near pointer fetch */
7074 /*-----------------------------------------------------------------*/
7076 genNearPointerGet (operand * left,
7084 sym_link *rtype, *retype;
7085 sym_link *ltype = operandType (left);
7088 D(emitcode (";", "genNearPointerGet"));
7090 rtype = operandType (result);
7091 retype = getSpec (rtype);
7093 aopOp (left, ic, FALSE);
7095 /* if left is rematerialisable and
7096 result is not bit variable type and
7097 the left is pointer to data space i.e
7098 lower 128 bytes of space */
7099 if (AOP_TYPE (left) == AOP_IMMD &&
7100 !IS_BITVAR (retype) &&
7101 DCL_TYPE (ltype) == POINTER)
7103 genDataPointerGet (left, result, ic);
7107 /* if the value is already in a pointer register
7108 then don't need anything more */
7109 if (!AOP_INPREG (AOP (left)))
7111 /* otherwise get a free pointer register */
7113 preg = getFreePtr (ic, &aop, FALSE);
7114 emitcode ("mov", "%s,%s",
7116 aopGet (AOP (left), 0, FALSE, TRUE));
7120 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7122 //aopOp (result, ic, FALSE);
7123 aopOp (result, ic, result?TRUE:FALSE);
7125 /* if bitfield then unpack the bits */
7126 if (IS_BITVAR (retype))
7127 genUnpackBits (result, rname, POINTER);
7130 /* we have can just get the values */
7131 int size = AOP_SIZE (result);
7136 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7139 emitcode ("mov", "a,@%s", rname);
7140 aopPut (AOP (result), "a", offset);
7144 sprintf (buffer, "@%s", rname);
7145 aopPut (AOP (result), buffer, offset);
7149 emitcode ("inc", "%s", rname);
7153 /* now some housekeeping stuff */
7154 if (aop) /* we had to allocate for this iCode */
7156 if (pi) { /* post increment present */
7157 aopPut(AOP ( left ),rname,0);
7159 freeAsmop (NULL, aop, ic, TRUE);
7163 /* we did not allocate which means left
7164 already in a pointer register, then
7165 if size > 0 && this could be used again
7166 we have to point it back to where it
7168 if ((AOP_SIZE (result) > 1 &&
7169 !OP_SYMBOL (left)->remat &&
7170 (OP_SYMBOL (left)->liveTo > ic->seq ||
7174 int size = AOP_SIZE (result) - 1;
7176 emitcode ("dec", "%s", rname);
7181 freeAsmop (left, NULL, ic, TRUE);
7182 freeAsmop (result, NULL, ic, TRUE);
7183 if (pi) pi->generated = 1;
7186 /*-----------------------------------------------------------------*/
7187 /* genPagedPointerGet - emitcode for paged pointer fetch */
7188 /*-----------------------------------------------------------------*/
7190 genPagedPointerGet (operand * left,
7198 sym_link *rtype, *retype;
7200 D(emitcode (";", "genPagedPointerGet"));
7202 rtype = operandType (result);
7203 retype = getSpec (rtype);
7205 aopOp (left, ic, FALSE);
7207 /* if the value is already in a pointer register
7208 then don't need anything more */
7209 if (!AOP_INPREG (AOP (left)))
7211 /* otherwise get a free pointer register */
7213 preg = getFreePtr (ic, &aop, FALSE);
7214 emitcode ("mov", "%s,%s",
7216 aopGet (AOP (left), 0, FALSE, TRUE));
7220 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7222 aopOp (result, ic, FALSE);
7224 /* if bitfield then unpack the bits */
7225 if (IS_BITVAR (retype))
7226 genUnpackBits (result, rname, PPOINTER);
7229 /* we have can just get the values */
7230 int size = AOP_SIZE (result);
7236 emitcode ("movx", "a,@%s", rname);
7237 aopPut (AOP (result), "a", offset);
7242 emitcode ("inc", "%s", rname);
7246 /* now some housekeeping stuff */
7247 if (aop) /* we had to allocate for this iCode */
7249 if (pi) aopPut ( AOP (left), rname, 0);
7250 freeAsmop (NULL, aop, ic, TRUE);
7254 /* we did not allocate which means left
7255 already in a pointer register, then
7256 if size > 0 && this could be used again
7257 we have to point it back to where it
7259 if ((AOP_SIZE (result) > 1 &&
7260 !OP_SYMBOL (left)->remat &&
7261 (OP_SYMBOL (left)->liveTo > ic->seq ||
7265 int size = AOP_SIZE (result) - 1;
7267 emitcode ("dec", "%s", rname);
7272 freeAsmop (left, NULL, ic, TRUE);
7273 freeAsmop (result, NULL, ic, TRUE);
7274 if (pi) pi->generated = 1;
7278 /*-----------------------------------------------------------------*/
7279 /* genFarPointerGet - gget value from far space */
7280 /*-----------------------------------------------------------------*/
7282 genFarPointerGet (operand * left,
7283 operand * result, iCode * ic, iCode * pi)
7286 sym_link *retype = getSpec (operandType (result));
7288 D(emitcode (";", "genFarPointerGet"));
7290 aopOp (left, ic, FALSE);
7292 /* if the operand is already in dptr
7293 then we do nothing else we move the value to dptr */
7294 if (AOP_TYPE (left) != AOP_STR)
7296 /* if this is remateriazable */
7297 if (AOP_TYPE (left) == AOP_IMMD)
7298 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7300 { /* we need to get it byte by byte */
7301 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7302 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7305 /* so dptr know contains the address */
7306 aopOp (result, ic, FALSE);
7308 /* if bit then unpack */
7309 if (IS_BITVAR (retype))
7310 genUnpackBits (result, "dptr", FPOINTER);
7313 size = AOP_SIZE (result);
7318 emitcode ("movx", "a,@dptr");
7319 aopPut (AOP (result), "a", offset++);
7321 emitcode ("inc", "dptr");
7325 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7326 aopPut ( AOP (left), "dpl", 0);
7327 aopPut ( AOP (left), "dph", 1);
7330 freeAsmop (left, NULL, ic, TRUE);
7331 freeAsmop (result, NULL, ic, TRUE);
7334 /*-----------------------------------------------------------------*/
7335 /* genCodePointerGet - gget value from code space */
7336 /*-----------------------------------------------------------------*/
7338 genCodePointerGet (operand * left,
7339 operand * result, iCode * ic, iCode *pi)
7342 sym_link *retype = getSpec (operandType (result));
7344 D(emitcode (";", "genCodePointerGet"));
7346 aopOp (left, ic, FALSE);
7348 /* if the operand is already in dptr
7349 then we do nothing else we move the value to dptr */
7350 if (AOP_TYPE (left) != AOP_STR)
7352 /* if this is remateriazable */
7353 if (AOP_TYPE (left) == AOP_IMMD)
7354 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7356 { /* we need to get it byte by byte */
7357 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7358 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7361 /* so dptr know contains the address */
7362 aopOp (result, ic, FALSE);
7364 /* if bit then unpack */
7365 if (IS_BITVAR (retype))
7366 genUnpackBits (result, "dptr", CPOINTER);
7369 size = AOP_SIZE (result);
7374 emitcode ("clr", "a");
7375 emitcode ("movc", "a,@a+dptr");
7376 aopPut (AOP (result), "a", offset++);
7378 emitcode ("inc", "dptr");
7382 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7383 aopPut ( AOP (left), "dpl", 0);
7384 aopPut ( AOP (left), "dph", 1);
7387 freeAsmop (left, NULL, ic, TRUE);
7388 freeAsmop (result, NULL, ic, TRUE);
7391 /*-----------------------------------------------------------------*/
7392 /* genGenPointerGet - gget value from generic pointer space */
7393 /*-----------------------------------------------------------------*/
7395 genGenPointerGet (operand * left,
7396 operand * result, iCode * ic, iCode *pi)
7399 sym_link *retype = getSpec (operandType (result));
7401 D(emitcode (";", "genGenPointerGet"));
7403 aopOp (left, ic, FALSE);
7405 /* if the operand is already in dptr
7406 then we do nothing else we move the value to dptr */
7407 if (AOP_TYPE (left) != AOP_STR)
7409 /* if this is remateriazable */
7410 if (AOP_TYPE (left) == AOP_IMMD)
7412 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7413 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7414 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7416 emitcode ("mov", "b,#%d", pointerCode (retype));
7419 { /* we need to get it byte by byte */
7420 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7421 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7422 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7425 /* so dptr know contains the address */
7426 aopOp (result, ic, FALSE);
7428 /* if bit then unpack */
7429 if (IS_BITVAR (retype))
7430 genUnpackBits (result, "dptr", GPOINTER);
7433 size = AOP_SIZE (result);
7438 emitcode ("lcall", "__gptrget");
7439 aopPut (AOP (result), "a", offset++);
7441 emitcode ("inc", "dptr");
7445 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7446 aopPut ( AOP (left), "dpl", 0);
7447 aopPut ( AOP (left), "dph", 1);
7448 aopPut ( AOP (left), "b", 2);
7451 freeAsmop (left, NULL, ic, TRUE);
7452 freeAsmop (result, NULL, ic, TRUE);
7455 /*-----------------------------------------------------------------*/
7456 /* genPointerGet - generate code for pointer get */
7457 /*-----------------------------------------------------------------*/
7459 genPointerGet (iCode * ic, iCode *pi)
7461 operand *left, *result;
7462 sym_link *type, *etype;
7465 D(emitcode (";", "genPointerGet"));
7467 left = IC_LEFT (ic);
7468 result = IC_RESULT (ic);
7470 /* depending on the type of pointer we need to
7471 move it to the correct pointer register */
7472 type = operandType (left);
7473 etype = getSpec (type);
7474 /* if left is of type of pointer then it is simple */
7475 if (IS_PTR (type) && !IS_FUNC (type->next))
7476 p_type = DCL_TYPE (type);
7479 /* we have to go by the storage class */
7480 p_type = PTR_TYPE (SPEC_OCLS (etype));
7483 /* special case when cast remat */
7484 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7485 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7486 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7487 type = type = operandType (left);
7488 p_type = DCL_TYPE (type);
7490 /* now that we have the pointer type we assign
7491 the pointer values */
7497 genNearPointerGet (left, result, ic, pi);
7501 genPagedPointerGet (left, result, ic, pi);
7505 genFarPointerGet (left, result, ic, pi);
7509 genCodePointerGet (left, result, ic, pi);
7513 genGenPointerGet (left, result, ic, pi);
7519 /*-----------------------------------------------------------------*/
7520 /* genPackBits - generates code for packed bit storage */
7521 /*-----------------------------------------------------------------*/
7523 genPackBits (sym_link * etype,
7525 char *rname, int p_type)
7533 D(emitcode (";", "genPackBits"));
7535 blen = SPEC_BLEN (etype);
7536 bstr = SPEC_BSTR (etype);
7538 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7541 /* if the bit lenth is less than or */
7542 /* it exactly fits a byte then */
7543 if (SPEC_BLEN (etype) <= 8)
7545 shCount = SPEC_BSTR (etype);
7547 /* shift left acc */
7550 if (SPEC_BLEN (etype) < 8)
7551 { /* if smaller than a byte */
7557 emitcode ("mov", "b,a");
7558 emitcode ("mov", "a,@%s", rname);
7562 emitcode ("mov", "b,a");
7563 emitcode ("movx", "a,@dptr");
7567 emitcode ("push", "b");
7568 emitcode ("push", "acc");
7569 emitcode ("lcall", "__gptrget");
7570 emitcode ("pop", "b");
7574 emitcode ("anl", "a,#0x%02x", (unsigned char)
7575 ((unsigned char) (0xFF << (blen + bstr)) |
7576 (unsigned char) (0xFF >> (8 - bstr))));
7577 emitcode ("orl", "a,b");
7578 if (p_type == GPOINTER)
7579 emitcode ("pop", "b");
7586 emitcode ("mov", "@%s,a", rname);
7590 emitcode ("movx", "@dptr,a");
7594 emitcode ("lcall", "__gptrput");
7599 if (SPEC_BLEN (etype) <= 8)
7602 emitcode ("inc", "%s", rname);
7603 rLen = SPEC_BLEN (etype);
7605 /* now generate for lengths greater than one byte */
7609 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7621 emitcode ("mov", "@%s,a", rname);
7624 emitcode ("mov", "@%s,%s", rname, l);
7629 emitcode ("movx", "@dptr,a");
7634 emitcode ("lcall", "__gptrput");
7637 emitcode ("inc", "%s", rname);
7642 /* last last was not complete */
7645 /* save the byte & read byte */
7649 emitcode ("mov", "b,a");
7650 emitcode ("mov", "a,@%s", rname);
7654 emitcode ("mov", "b,a");
7655 emitcode ("movx", "a,@dptr");
7659 emitcode ("push", "b");
7660 emitcode ("push", "acc");
7661 emitcode ("lcall", "__gptrget");
7662 emitcode ("pop", "b");
7666 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7667 emitcode ("orl", "a,b");
7670 if (p_type == GPOINTER)
7671 emitcode ("pop", "b");
7677 emitcode ("mov", "@%s,a", rname);
7681 emitcode ("movx", "@dptr,a");
7685 emitcode ("lcall", "__gptrput");
7689 /*-----------------------------------------------------------------*/
7690 /* genDataPointerSet - remat pointer to data space */
7691 /*-----------------------------------------------------------------*/
7693 genDataPointerSet (operand * right,
7697 int size, offset = 0;
7698 char *l, buffer[256];
7700 D(emitcode (";", "genDataPointerSet"));
7702 aopOp (right, ic, FALSE);
7704 l = aopGet (AOP (result), 0, FALSE, TRUE);
7705 size = AOP_SIZE (right);
7709 sprintf (buffer, "(%s + %d)", l + 1, offset);
7711 sprintf (buffer, "%s", l + 1);
7712 emitcode ("mov", "%s,%s", buffer,
7713 aopGet (AOP (right), offset++, FALSE, FALSE));
7716 freeAsmop (right, NULL, ic, TRUE);
7717 freeAsmop (result, NULL, ic, TRUE);
7720 /*-----------------------------------------------------------------*/
7721 /* genNearPointerSet - emitcode for near pointer put */
7722 /*-----------------------------------------------------------------*/
7724 genNearPointerSet (operand * right,
7732 sym_link *retype, *letype;
7733 sym_link *ptype = operandType (result);
7735 D(emitcode (";", "genNearPointerSet"));
7737 retype = getSpec (operandType (right));
7738 letype = getSpec (ptype);
7739 aopOp (result, ic, FALSE);
7741 /* if the result is rematerializable &
7742 in data space & not a bit variable */
7743 if (AOP_TYPE (result) == AOP_IMMD &&
7744 DCL_TYPE (ptype) == POINTER &&
7745 !IS_BITVAR (retype) &&
7746 !IS_BITVAR (letype))
7748 genDataPointerSet (right, result, ic);
7752 /* if the value is already in a pointer register
7753 then don't need anything more */
7754 if (!AOP_INPREG (AOP (result)))
7757 //AOP_TYPE (result) == AOP_STK
7761 // Aha, it is a pointer, just in disguise.
7762 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7765 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7766 __FILE__, __LINE__);
7771 rname++; // skip the '@'.
7776 /* otherwise get a free pointer register */
7778 preg = getFreePtr (ic, &aop, FALSE);
7779 emitcode ("mov", "%s,%s",
7781 aopGet (AOP (result), 0, FALSE, TRUE));
7787 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7790 aopOp (right, ic, FALSE);
7792 /* if bitfield then unpack the bits */
7793 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7794 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7797 /* we have can just get the values */
7798 int size = AOP_SIZE (right);
7803 l = aopGet (AOP (right), offset, FALSE, TRUE);
7807 emitcode ("mov", "@%s,a", rname);
7810 emitcode ("mov", "@%s,%s", rname, l);
7812 emitcode ("inc", "%s", rname);
7817 /* now some housekeeping stuff */
7818 if (aop) /* we had to allocate for this iCode */
7820 if (pi) aopPut (AOP (result),rname,0);
7821 freeAsmop (NULL, aop, ic, TRUE);
7825 /* we did not allocate which means left
7826 already in a pointer register, then
7827 if size > 0 && this could be used again
7828 we have to point it back to where it
7830 if ((AOP_SIZE (right) > 1 &&
7831 !OP_SYMBOL (result)->remat &&
7832 (OP_SYMBOL (result)->liveTo > ic->seq ||
7836 int size = AOP_SIZE (right) - 1;
7838 emitcode ("dec", "%s", rname);
7843 if (pi) pi->generated = 1;
7844 freeAsmop (result, NULL, ic, TRUE);
7845 freeAsmop (right, NULL, ic, TRUE);
7848 /*-----------------------------------------------------------------*/
7849 /* genPagedPointerSet - emitcode for Paged pointer put */
7850 /*-----------------------------------------------------------------*/
7852 genPagedPointerSet (operand * right,
7860 sym_link *retype, *letype;
7862 D(emitcode (";", "genPagedPointerSet"));
7864 retype = getSpec (operandType (right));
7865 letype = getSpec (operandType (result));
7867 aopOp (result, ic, FALSE);
7869 /* if the value is already in a pointer register
7870 then don't need anything more */
7871 if (!AOP_INPREG (AOP (result)))
7873 /* otherwise get a free pointer register */
7875 preg = getFreePtr (ic, &aop, FALSE);
7876 emitcode ("mov", "%s,%s",
7878 aopGet (AOP (result), 0, FALSE, TRUE));
7882 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7884 aopOp (right, ic, FALSE);
7886 /* if bitfield then unpack the bits */
7887 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7888 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7891 /* we have can just get the values */
7892 int size = AOP_SIZE (right);
7897 l = aopGet (AOP (right), offset, FALSE, TRUE);
7900 emitcode ("movx", "@%s,a", rname);
7903 emitcode ("inc", "%s", rname);
7909 /* now some housekeeping stuff */
7910 if (aop) /* we had to allocate for this iCode */
7912 if (pi) aopPut (AOP (result),rname,0);
7913 freeAsmop (NULL, aop, ic, TRUE);
7917 /* we did not allocate which means left
7918 already in a pointer register, then
7919 if size > 0 && this could be used again
7920 we have to point it back to where it
7922 if (AOP_SIZE (right) > 1 &&
7923 !OP_SYMBOL (result)->remat &&
7924 (OP_SYMBOL (result)->liveTo > ic->seq ||
7927 int size = AOP_SIZE (right) - 1;
7929 emitcode ("dec", "%s", rname);
7934 if (pi) pi->generated = 1;
7935 freeAsmop (result, NULL, ic, TRUE);
7936 freeAsmop (right, NULL, ic, TRUE);
7941 /*-----------------------------------------------------------------*/
7942 /* genFarPointerSet - set value from far space */
7943 /*-----------------------------------------------------------------*/
7945 genFarPointerSet (operand * right,
7946 operand * result, iCode * ic, iCode * pi)
7949 sym_link *retype = getSpec (operandType (right));
7950 sym_link *letype = getSpec (operandType (result));
7952 D(emitcode (";", "genFarPointerSet"));
7954 aopOp (result, ic, FALSE);
7956 /* if the operand is already in dptr
7957 then we do nothing else we move the value to dptr */
7958 if (AOP_TYPE (result) != AOP_STR)
7960 /* if this is remateriazable */
7961 if (AOP_TYPE (result) == AOP_IMMD)
7962 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7964 { /* we need to get it byte by byte */
7965 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7966 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7969 /* so dptr know contains the address */
7970 aopOp (right, ic, FALSE);
7972 /* if bit then unpack */
7973 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7974 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7977 size = AOP_SIZE (right);
7982 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7984 emitcode ("movx", "@dptr,a");
7986 emitcode ("inc", "dptr");
7989 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7990 aopPut (AOP(result),"dpl",0);
7991 aopPut (AOP(result),"dph",1);
7994 freeAsmop (result, NULL, ic, TRUE);
7995 freeAsmop (right, NULL, ic, TRUE);
7998 /*-----------------------------------------------------------------*/
7999 /* genGenPointerSet - set value from generic pointer space */
8000 /*-----------------------------------------------------------------*/
8002 genGenPointerSet (operand * right,
8003 operand * result, iCode * ic, iCode * pi)
8006 sym_link *retype = getSpec (operandType (right));
8007 sym_link *letype = getSpec (operandType (result));
8009 D(emitcode (";", "genGenPointerSet"));
8011 aopOp (result, ic, FALSE);
8013 /* if the operand is already in dptr
8014 then we do nothing else we move the value to dptr */
8015 if (AOP_TYPE (result) != AOP_STR)
8017 /* if this is remateriazable */
8018 if (AOP_TYPE (result) == AOP_IMMD)
8020 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8021 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8022 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8024 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8027 { /* we need to get it byte by byte */
8028 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8029 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8030 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8033 /* so dptr know contains the address */
8034 aopOp (right, ic, FALSE);
8036 /* if bit then unpack */
8037 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8038 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8041 size = AOP_SIZE (right);
8046 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8048 emitcode ("lcall", "__gptrput");
8050 emitcode ("inc", "dptr");
8054 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8055 aopPut (AOP(result),"dpl",0);
8056 aopPut (AOP(result),"dph",1);
8057 aopPut (AOP(result),"b",2);
8060 freeAsmop (result, NULL, ic, TRUE);
8061 freeAsmop (right, NULL, ic, TRUE);
8064 /*-----------------------------------------------------------------*/
8065 /* genPointerSet - stores the value into a pointer location */
8066 /*-----------------------------------------------------------------*/
8068 genPointerSet (iCode * ic, iCode *pi)
8070 operand *right, *result;
8071 sym_link *type, *etype;
8074 D(emitcode (";", "genPointerSet"));
8076 right = IC_RIGHT (ic);
8077 result = IC_RESULT (ic);
8079 /* depending on the type of pointer we need to
8080 move it to the correct pointer register */
8081 type = operandType (result);
8082 etype = getSpec (type);
8083 /* if left is of type of pointer then it is simple */
8084 if (IS_PTR (type) && !IS_FUNC (type->next))
8086 p_type = DCL_TYPE (type);
8090 /* we have to go by the storage class */
8091 p_type = PTR_TYPE (SPEC_OCLS (etype));
8094 /* special case when cast remat */
8095 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8096 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8097 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8098 type = type = operandType (result);
8099 p_type = DCL_TYPE (type);
8101 /* now that we have the pointer type we assign
8102 the pointer values */
8108 genNearPointerSet (right, result, ic, pi);
8112 genPagedPointerSet (right, result, ic, pi);
8116 genFarPointerSet (right, result, ic, pi);
8120 genGenPointerSet (right, result, ic, pi);
8126 /*-----------------------------------------------------------------*/
8127 /* genIfx - generate code for Ifx statement */
8128 /*-----------------------------------------------------------------*/
8130 genIfx (iCode * ic, iCode * popIc)
8132 operand *cond = IC_COND (ic);
8135 D(emitcode (";", "genIfx"));
8137 aopOp (cond, ic, FALSE);
8139 /* get the value into acc */
8140 if (AOP_TYPE (cond) != AOP_CRY)
8144 /* the result is now in the accumulator */
8145 freeAsmop (cond, NULL, ic, TRUE);
8147 /* if there was something to be popped then do it */
8151 /* if the condition is a bit variable */
8152 if (isbit && IS_ITEMP (cond) &&
8154 genIfxJump (ic, SPIL_LOC (cond)->rname);
8155 else if (isbit && !IS_ITEMP (cond))
8156 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8158 genIfxJump (ic, "a");
8163 /*-----------------------------------------------------------------*/
8164 /* genAddrOf - generates code for address of */
8165 /*-----------------------------------------------------------------*/
8167 genAddrOf (iCode * ic)
8169 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8172 D(emitcode (";", "genAddrOf"));
8174 aopOp (IC_RESULT (ic), ic, FALSE);
8176 /* if the operand is on the stack then we
8177 need to get the stack offset of this
8181 /* if it has an offset then we need to compute
8185 emitcode ("mov", "a,_bp");
8186 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8187 ((char) (sym->stack - _G.nRegsSaved)) :
8188 ((char) sym->stack)) & 0xff);
8189 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8193 /* we can just move _bp */
8194 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8196 /* fill the result with zero */
8197 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8202 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8208 /* object not on stack then we need the name */
8209 size = AOP_SIZE (IC_RESULT (ic));
8214 char s[SDCC_NAME_MAX];
8216 sprintf (s, "#(%s >> %d)",
8220 sprintf (s, "#%s", sym->rname);
8221 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8229 /*-----------------------------------------------------------------*/
8230 /* genFarFarAssign - assignment when both are in far space */
8231 /*-----------------------------------------------------------------*/
8233 genFarFarAssign (operand * result, operand * right, iCode * ic)
8235 int size = AOP_SIZE (right);
8239 D(emitcode (";", "genFarFarAssign"));
8241 /* first push the right side on to the stack */
8244 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8246 emitcode ("push", "acc");
8249 freeAsmop (right, NULL, ic, FALSE);
8250 /* now assign DPTR to result */
8251 aopOp (result, ic, FALSE);
8252 size = AOP_SIZE (result);
8255 emitcode ("pop", "acc");
8256 aopPut (AOP (result), "a", --offset);
8258 freeAsmop (result, NULL, ic, FALSE);
8262 /*-----------------------------------------------------------------*/
8263 /* genAssign - generate code for assignment */
8264 /*-----------------------------------------------------------------*/
8266 genAssign (iCode * ic)
8268 operand *result, *right;
8270 unsigned long lit = 0L;
8272 D(emitcode(";","genAssign"));
8274 result = IC_RESULT (ic);
8275 right = IC_RIGHT (ic);
8277 /* if they are the same */
8278 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8281 aopOp (right, ic, FALSE);
8283 /* special case both in far space */
8284 if (AOP_TYPE (right) == AOP_DPTR &&
8285 IS_TRUE_SYMOP (result) &&
8286 isOperandInFarSpace (result))
8289 genFarFarAssign (result, right, ic);
8293 aopOp (result, ic, TRUE);
8295 /* if they are the same registers */
8296 if (sameRegs (AOP (right), AOP (result)))
8299 /* if the result is a bit */
8300 if (AOP_TYPE (result) == AOP_CRY)
8303 /* if the right size is a literal then
8304 we know what the value is */
8305 if (AOP_TYPE (right) == AOP_LIT)
8307 if (((int) operandLitValue (right)))
8308 aopPut (AOP (result), one, 0);
8310 aopPut (AOP (result), zero, 0);
8314 /* the right is also a bit variable */
8315 if (AOP_TYPE (right) == AOP_CRY)
8317 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8318 aopPut (AOP (result), "c", 0);
8324 aopPut (AOP (result), "a", 0);
8328 /* bit variables done */
8330 size = AOP_SIZE (result);
8332 if (AOP_TYPE (right) == AOP_LIT)
8333 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8335 (AOP_TYPE (result) != AOP_REG) &&
8336 (AOP_TYPE (right) == AOP_LIT) &&
8337 !IS_FLOAT (operandType (right)) &&
8340 emitcode ("clr", "a");
8343 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8344 aopPut (AOP (result), "a", size);
8346 aopPut (AOP (result),
8347 aopGet (AOP (right), size, FALSE, FALSE),
8355 aopPut (AOP (result),
8356 aopGet (AOP (right), offset, FALSE, FALSE),
8363 freeAsmop (right, NULL, ic, TRUE);
8364 freeAsmop (result, NULL, ic, TRUE);
8367 /*-----------------------------------------------------------------*/
8368 /* genJumpTab - genrates code for jump table */
8369 /*-----------------------------------------------------------------*/
8371 genJumpTab (iCode * ic)
8376 D(emitcode (";", "genJumpTab"));
8378 aopOp (IC_JTCOND (ic), ic, FALSE);
8379 /* get the condition into accumulator */
8380 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8382 /* multiply by three */
8383 emitcode ("add", "a,acc");
8384 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8385 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8387 jtab = newiTempLabel (NULL);
8388 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8389 emitcode ("jmp", "@a+dptr");
8390 emitcode ("", "%05d$:", jtab->key + 100);
8391 /* now generate the jump labels */
8392 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8393 jtab = setNextItem (IC_JTLABELS (ic)))
8394 emitcode ("ljmp", "%05d$", jtab->key + 100);
8398 /*-----------------------------------------------------------------*/
8399 /* genCast - gen code for casting */
8400 /*-----------------------------------------------------------------*/
8402 genCast (iCode * ic)
8404 operand *result = IC_RESULT (ic);
8405 sym_link *ctype = operandType (IC_LEFT (ic));
8406 sym_link *rtype = operandType (IC_RIGHT (ic));
8407 operand *right = IC_RIGHT (ic);
8410 D(emitcode(";", "genCast"));
8412 /* if they are equivalent then do nothing */
8413 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8416 aopOp (right, ic, FALSE);
8417 aopOp (result, ic, FALSE);
8419 /* if the result is a bit */
8420 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8421 if (IS_BITVAR(OP_SYMBOL(result)->type))
8423 /* if the right size is a literal then
8424 we know what the value is */
8425 if (AOP_TYPE (right) == AOP_LIT)
8427 if (((int) operandLitValue (right)))
8428 aopPut (AOP (result), one, 0);
8430 aopPut (AOP (result), zero, 0);
8435 /* the right is also a bit variable */
8436 if (AOP_TYPE (right) == AOP_CRY)
8438 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8439 aopPut (AOP (result), "c", 0);
8445 aopPut (AOP (result), "a", 0);
8449 /* if they are the same size : or less */
8450 if (AOP_SIZE (result) <= AOP_SIZE (right))
8453 /* if they are in the same place */
8454 if (sameRegs (AOP (right), AOP (result)))
8457 /* if they in different places then copy */
8458 size = AOP_SIZE (result);
8462 aopPut (AOP (result),
8463 aopGet (AOP (right), offset, FALSE, FALSE),
8471 /* if the result is of type pointer */
8476 sym_link *type = operandType (right);
8477 sym_link *etype = getSpec (type);
8479 /* pointer to generic pointer */
8480 if (IS_GENPTR (ctype))
8485 p_type = DCL_TYPE (type);
8488 if (SPEC_SCLS(etype)==S_REGISTER) {
8489 // let's assume it is a generic pointer
8492 /* we have to go by the storage class */
8493 p_type = PTR_TYPE (SPEC_OCLS (etype));
8497 /* the first two bytes are known */
8498 size = GPTRSIZE - 1;
8502 aopPut (AOP (result),
8503 aopGet (AOP (right), offset, FALSE, FALSE),
8507 /* the last byte depending on type */
8523 case PPOINTER: // what the fck is this?
8528 /* this should never happen */
8529 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8530 "got unknown pointer type");
8533 aopPut (AOP (result), l, GPTRSIZE - 1);
8537 /* just copy the pointers */
8538 size = AOP_SIZE (result);
8542 aopPut (AOP (result),
8543 aopGet (AOP (right), offset, FALSE, FALSE),
8550 /* so we now know that the size of destination is greater
8551 than the size of the source */
8552 /* we move to result for the size of source */
8553 size = AOP_SIZE (right);
8557 aopPut (AOP (result),
8558 aopGet (AOP (right), offset, FALSE, FALSE),
8563 /* now depending on the sign of the source && destination */
8564 size = AOP_SIZE (result) - AOP_SIZE (right);
8565 /* if unsigned or not an integral type */
8566 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8569 aopPut (AOP (result), zero, offset++);
8573 /* we need to extend the sign :{ */
8574 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8577 emitcode ("rlc", "a");
8578 emitcode ("subb", "a,acc");
8580 aopPut (AOP (result), "a", offset++);
8583 /* we are done hurray !!!! */
8586 freeAsmop (right, NULL, ic, TRUE);
8587 freeAsmop (result, NULL, ic, TRUE);
8591 /*-----------------------------------------------------------------*/
8592 /* genDjnz - generate decrement & jump if not zero instrucion */
8593 /*-----------------------------------------------------------------*/
8595 genDjnz (iCode * ic, iCode * ifx)
8601 D(emitcode (";", "genDjnz"));
8603 /* if the if condition has a false label
8604 then we cannot save */
8608 /* if the minus is not of the form
8610 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8611 !IS_OP_LITERAL (IC_RIGHT (ic)))
8614 if (operandLitValue (IC_RIGHT (ic)) != 1)
8617 /* if the size of this greater than one then no
8619 if (getSize (operandType (IC_RESULT (ic))) > 1)
8622 /* otherwise we can save BIG */
8623 lbl = newiTempLabel (NULL);
8624 lbl1 = newiTempLabel (NULL);
8626 aopOp (IC_RESULT (ic), ic, FALSE);
8628 if (AOP_NEEDSACC(IC_RESULT(ic)))
8630 /* If the result is accessed indirectly via
8631 * the accumulator, we must explicitly write
8632 * it back after the decrement.
8634 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8636 if (strcmp(rByte, "a"))
8638 /* Something is hopelessly wrong */
8639 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8640 __FILE__, __LINE__);
8641 /* We can just give up; the generated code will be inefficient,
8644 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8647 emitcode ("dec", "%s", rByte);
8648 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8649 emitcode ("jnz", "%05d$", lbl->key + 100);
8651 else if (IS_AOP_PREG (IC_RESULT (ic)))
8653 emitcode ("dec", "%s",
8654 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8655 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8656 emitcode ("jnz", "%05d$", lbl->key + 100);
8660 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8663 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8664 emitcode ("", "%05d$:", lbl->key + 100);
8665 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8666 emitcode ("", "%05d$:", lbl1->key + 100);
8668 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8673 /*-----------------------------------------------------------------*/
8674 /* genReceive - generate code for a receive iCode */
8675 /*-----------------------------------------------------------------*/
8677 genReceive (iCode * ic)
8679 D(emitcode (";", "genReceive"));
8681 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8682 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8683 IS_TRUE_SYMOP (IC_RESULT (ic))))
8686 int size = getSize (operandType (IC_RESULT (ic)));
8687 int offset = fReturnSizeMCS51 - size;
8690 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8691 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8694 aopOp (IC_RESULT (ic), ic, FALSE);
8695 size = AOP_SIZE (IC_RESULT (ic));
8699 emitcode ("pop", "acc");
8700 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8707 aopOp (IC_RESULT (ic), ic, FALSE);
8709 assignResultValue (IC_RESULT (ic));
8712 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8715 /*-----------------------------------------------------------------*/
8716 /* gen51AggregateAssign - copy complete array's or structures */
8717 /*-----------------------------------------------------------------*/
8718 void gen51AggregateAssign(iCode *ic) {
8719 operand *left=IC_LEFT(ic);
8720 operand *right=IC_RIGHT(ic);
8721 char *fromName=OP_SYMBOL(right)->rname;
8722 char *toName=OP_SYMBOL(left)->rname;
8723 int fromSize=getSize(OP_SYMBOL(right)->type);
8724 int toSize=getSize(OP_SYMBOL(left)->type);
8727 D(emitcode (";", "gen51AggregateAssign"));
8729 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8730 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8731 // well, this code isn't used yet from anywhere else as for initialising
8732 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8736 if (fromSize!=toSize) {
8737 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8738 ic->filename, ic->lineno);
8743 // use the generic memcpy() for now
8744 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8745 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8746 emitcode ("mov", "a,#%s", fromName);
8747 emitcode ("movx", "@dptr,a");
8748 emitcode ("inc", "dptr");
8749 emitcode ("mov", "a,#(%s>>8)", fromName);
8750 emitcode ("movx", "@dptr,a");
8751 emitcode ("inc", "dptr");
8752 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8753 emitcode ("movx", "@dptr,a");
8754 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8755 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8756 emitcode ("movx", "@dptr,a");
8757 emitcode ("inc", "dptr");
8758 emitcode ("mov", "a,#(%d>>8)", count);
8759 emitcode ("movx", "@dptr,a");
8760 emitcode ("mov", "dptr,#%s", toName);
8761 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8762 emitcode ("lcall", "_memcpy");
8764 // more efficient, but will require the native_memcpy_cs2xs
8765 emitcode ("mov", "r0,#%s", fromName);
8766 emitcode ("mov", "r1,#(%s>>8)", fromName);
8767 emitcode ("mov", "r2,#%s", toName);
8768 emitcode ("mov", "r3,#(%s>>8)", toName);
8769 emitcode ("mov", "r4,#%d", count);
8770 emitcode ("mov", "r5,#(%d>>8)", count);
8771 emitcode ("lcall", "_native_memcpy_cs2xs");
8775 /*-----------------------------------------------------------------*/
8776 /* gen51Code - generate code for 8051 based controllers */
8777 /*-----------------------------------------------------------------*/
8779 gen51Code (iCode * lic)
8784 lineHead = lineCurr = NULL;
8786 /* print the allocation information */
8788 printAllocInfo (currFunc, codeOutFile);
8789 /* if debug information required */
8790 if (options.debug && currFunc)
8792 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8794 if (IS_STATIC (currFunc->etype))
8795 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8797 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8800 /* stack pointer name */
8801 if (options.useXstack)
8807 for (ic = lic; ic; ic = ic->next)
8810 if (cln != ic->lineno)
8815 emitcode ("", "C$%s$%d$%d$%d ==.",
8816 FileBaseName (ic->filename), ic->lineno,
8817 ic->level, ic->block);
8820 emitcode (";", "%s %d", ic->filename, ic->lineno);
8823 /* if the result is marked as
8824 spilt and rematerializable or code for
8825 this has already been generated then
8827 if (resultRemat (ic) || ic->generated)
8830 /* depending on the operation */
8850 /* IPOP happens only when trying to restore a
8851 spilt live range, if there is an ifx statement
8852 following this pop then the if statement might
8853 be using some of the registers being popped which
8854 would destory the contents of the register so
8855 we need to check for this condition and handle it */
8857 ic->next->op == IFX &&
8858 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8859 genIfx (ic->next, ic);
8877 genEndFunction (ic);
8897 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8914 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8918 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8925 /* note these two are xlated by algebraic equivalence
8926 during parsing SDCC.y */
8927 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8928 "got '>=' or '<=' shouldn't have come here");
8932 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8944 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8948 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8952 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8979 case GET_VALUE_AT_ADDRESS:
8980 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8984 if (POINTER_SET (ic))
8985 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
9011 addSet (&_G.sendSet, ic);
9015 gen51AggregateAssign(ic);
9024 /* now we are ready to call the
9025 peep hole optimizer */
9026 if (!options.nopeep)
9027 peepHole (&lineHead);
9029 /* now do the actual printing */
9030 printLine (lineHead, codeOutFile);