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");
2423 /* ISRs will be handled by the code above, because they
2424 can't have parameters. Therefore it's save to use r0 */
2425 emitcode ("mov", "r0,a");
2426 emitcode ("mov", "a,sp");
2427 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2428 emitcode ("mov", "sp,a");
2429 emitcode ("mov", "a,r0");
2434 emitcode ("inc", "sp");
2440 emitcode ("mov", "a,_spx");
2441 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2442 emitcode ("mov", "_spx,a");
2447 /*-----------------------------------------------------------------*/
2448 /* genEndFunction - generates epilogue for functions */
2449 /*-----------------------------------------------------------------*/
2451 genEndFunction (iCode * ic)
2453 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2455 if (IFFUNC_ISNAKED(sym->type))
2457 emitcode(";", "naked function: no epilogue.");
2461 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2463 emitcode ("mov", "%s,_bp", spname);
2466 /* if use external stack but some variables were
2467 added to the local stack then decrement the
2469 if (options.useXstack && sym->stack)
2471 emitcode ("mov", "a,sp");
2472 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2473 emitcode ("mov", "sp,a");
2477 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2479 if (options.useXstack)
2481 emitcode ("mov", "r0,%s", spname);
2482 emitcode ("movx", "a,@r0");
2483 emitcode ("mov", "_bp,a");
2484 emitcode ("dec", "%s", spname);
2488 emitcode ("pop", "_bp");
2492 /* restore the register bank */
2493 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2495 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2496 || !options.useXstack)
2498 /* Special case of ISR using non-zero bank with useXstack
2501 emitcode ("pop", "psw");
2505 if (IFFUNC_ISISR (sym->type))
2508 /* now we need to restore the registers */
2509 /* if this isr has no bank i.e. is going to
2510 run with bank 0 , then we need to save more
2512 if (!FUNC_REGBANK (sym->type))
2514 /* if this function does not call any other
2515 function then we can be economical and
2516 save only those registers that are used */
2517 if (!IFFUNC_HASFCALL(sym->type))
2521 /* if any registers used */
2524 /* save the registers used */
2525 for (i = sym->regsUsed->size; i >= 0; i--)
2527 if (bitVectBitValue (sym->regsUsed, i) ||
2528 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2529 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2536 /* this function has a function call cannot
2537 determines register usage so we will have to pop the
2539 unsaveRBank (0, ic, FALSE);
2544 /* This ISR uses a non-zero bank.
2546 * Restore any register banks saved by genFunction
2549 // jwk: this needs a closer look
2550 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2553 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2555 if (savedBanks & (1 << ix))
2557 unsaveRBank(ix, NULL, FALSE);
2561 if (options.useXstack)
2563 /* Restore bank AFTER calling unsaveRBank,
2564 * since it can trash r0.
2566 emitcode ("pop", "psw");
2570 if (!inExcludeList ("dph"))
2571 emitcode ("pop", "dph");
2572 if (!inExcludeList ("dpl"))
2573 emitcode ("pop", "dpl");
2574 if (!inExcludeList ("b"))
2575 emitcode ("pop", "b");
2576 if (!inExcludeList ("acc"))
2577 emitcode ("pop", "acc");
2579 if (IFFUNC_ISCRITICAL (sym->type))
2580 emitcode ("setb", "ea");
2582 /* if debug then send end of function */
2583 if (options.debug && currFunc)
2586 emitcode ("", "C$%s$%d$%d$%d ==.",
2587 FileBaseName (ic->filename), currFunc->lastLine,
2588 ic->level, ic->block);
2589 if (IS_STATIC (currFunc->etype))
2590 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2592 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2596 emitcode ("reti", "");
2600 if (IFFUNC_ISCRITICAL (sym->type))
2601 emitcode ("setb", "ea");
2603 if (IFFUNC_CALLEESAVES(sym->type))
2607 /* if any registers used */
2610 /* save the registers used */
2611 for (i = sym->regsUsed->size; i >= 0; i--)
2613 if (bitVectBitValue (sym->regsUsed, i) ||
2614 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2615 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2621 /* if debug then send end of function */
2622 if (options.debug && currFunc)
2625 emitcode ("", "C$%s$%d$%d$%d ==.",
2626 FileBaseName (ic->filename), currFunc->lastLine,
2627 ic->level, ic->block);
2628 if (IS_STATIC (currFunc->etype))
2629 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2631 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2635 emitcode ("ret", "");
2640 /*-----------------------------------------------------------------*/
2641 /* genRet - generate code for return statement */
2642 /*-----------------------------------------------------------------*/
2646 int size, offset = 0, pushed = 0;
2648 D(emitcode (";", "genRet"));
2650 /* if we have no return value then
2651 just generate the "ret" */
2655 /* we have something to return then
2656 move the return value into place */
2657 aopOp (IC_LEFT (ic), ic, FALSE);
2658 size = AOP_SIZE (IC_LEFT (ic));
2663 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2666 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2668 emitcode ("push", "%s", l);
2673 l = aopGet (AOP (IC_LEFT (ic)), offset,
2675 if (strcmp (fReturn[offset], l))
2676 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2685 if (strcmp (fReturn[pushed], "a"))
2686 emitcode ("pop", fReturn[pushed]);
2688 emitcode ("pop", "acc");
2691 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2694 /* generate a jump to the return label
2695 if the next is not the return statement */
2696 if (!(ic->next && ic->next->op == LABEL &&
2697 IC_LABEL (ic->next) == returnLabel))
2699 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2703 /*-----------------------------------------------------------------*/
2704 /* genLabel - generates a label */
2705 /*-----------------------------------------------------------------*/
2707 genLabel (iCode * ic)
2709 /* special case never generate */
2710 if (IC_LABEL (ic) == entryLabel)
2713 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2716 /*-----------------------------------------------------------------*/
2717 /* genGoto - generates a ljmp */
2718 /*-----------------------------------------------------------------*/
2720 genGoto (iCode * ic)
2722 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2725 /*-----------------------------------------------------------------*/
2726 /* findLabelBackwards: walks back through the iCode chain looking */
2727 /* for the given label. Returns number of iCode instructions */
2728 /* between that label and given ic. */
2729 /* Returns zero if label not found. */
2730 /*-----------------------------------------------------------------*/
2732 findLabelBackwards (iCode * ic, int key)
2741 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2743 /* printf("findLabelBackwards = %d\n", count); */
2751 /*-----------------------------------------------------------------*/
2752 /* genPlusIncr :- does addition with increment if possible */
2753 /*-----------------------------------------------------------------*/
2755 genPlusIncr (iCode * ic)
2757 unsigned int icount;
2758 unsigned int size = getDataSize (IC_RESULT (ic));
2760 /* will try to generate an increment */
2761 /* if the right side is not a literal
2763 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2766 /* if the literal value of the right hand side
2767 is greater than 4 then it is not worth it */
2768 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2771 D(emitcode (";", "genPlusIncr"));
2773 /* if increment 16 bits in register */
2774 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2782 /* If the next instruction is a goto and the goto target
2783 * is < 10 instructions previous to this, we can generate
2784 * jumps straight to that target.
2786 if (ic->next && ic->next->op == GOTO
2787 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2788 && labelRange <= 10)
2790 emitcode (";", "tail increment optimized");
2791 tlbl = IC_LABEL (ic->next);
2796 tlbl = newiTempLabel (NULL);
2799 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2800 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2801 IS_AOP_PREG (IC_RESULT (ic)))
2802 emitcode ("cjne", "%s,#0x00,%05d$"
2803 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2807 emitcode ("clr", "a");
2808 emitcode ("cjne", "a,%s,%05d$"
2809 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2813 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2816 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2817 IS_AOP_PREG (IC_RESULT (ic)))
2818 emitcode ("cjne", "%s,#0x00,%05d$"
2819 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2822 emitcode ("cjne", "a,%s,%05d$"
2823 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2826 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2830 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2831 IS_AOP_PREG (IC_RESULT (ic)))
2832 emitcode ("cjne", "%s,#0x00,%05d$"
2833 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2837 emitcode ("cjne", "a,%s,%05d$"
2838 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2841 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2846 emitcode ("", "%05d$:", tlbl->key + 100);
2851 /* if the sizes are greater than 1 then we cannot */
2852 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2853 AOP_SIZE (IC_LEFT (ic)) > 1)
2856 /* we can if the aops of the left & result match or
2857 if they are in registers and the registers are the
2859 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2864 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2865 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2866 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2872 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2881 /*-----------------------------------------------------------------*/
2882 /* outBitAcc - output a bit in acc */
2883 /*-----------------------------------------------------------------*/
2885 outBitAcc (operand * result)
2887 symbol *tlbl = newiTempLabel (NULL);
2888 /* if the result is a bit */
2889 if (AOP_TYPE (result) == AOP_CRY)
2891 aopPut (AOP (result), "a", 0);
2895 emitcode ("jz", "%05d$", tlbl->key + 100);
2896 emitcode ("mov", "a,%s", one);
2897 emitcode ("", "%05d$:", tlbl->key + 100);
2902 /*-----------------------------------------------------------------*/
2903 /* genPlusBits - generates code for addition of two bits */
2904 /*-----------------------------------------------------------------*/
2906 genPlusBits (iCode * ic)
2908 D(emitcode (";", "genPlusBits"));
2910 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2912 symbol *lbl = newiTempLabel (NULL);
2913 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2914 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2915 emitcode ("cpl", "c");
2916 emitcode ("", "%05d$:", (lbl->key + 100));
2917 outBitC (IC_RESULT (ic));
2921 emitcode ("clr", "a");
2922 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2923 emitcode ("rlc", "a");
2924 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2925 emitcode ("addc", "a,#0x00");
2926 outAcc (IC_RESULT (ic));
2931 /* This is the original version of this code.
2933 * This is being kept around for reference,
2934 * because I am not entirely sure I got it right...
2937 adjustArithmeticResult (iCode * ic)
2939 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2940 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2941 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2942 aopPut (AOP (IC_RESULT (ic)),
2943 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2946 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2947 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2948 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2949 aopPut (AOP (IC_RESULT (ic)),
2950 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2953 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2954 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2955 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2956 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2957 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2960 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2961 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2965 /* This is the pure and virtuous version of this code.
2966 * I'm pretty certain it's right, but not enough to toss the old
2970 adjustArithmeticResult (iCode * ic)
2972 if (opIsGptr (IC_RESULT (ic)) &&
2973 opIsGptr (IC_LEFT (ic)) &&
2974 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2976 aopPut (AOP (IC_RESULT (ic)),
2977 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2981 if (opIsGptr (IC_RESULT (ic)) &&
2982 opIsGptr (IC_RIGHT (ic)) &&
2983 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2985 aopPut (AOP (IC_RESULT (ic)),
2986 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2990 if (opIsGptr (IC_RESULT (ic)) &&
2991 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2992 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2993 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2994 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2997 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2998 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3003 /*-----------------------------------------------------------------*/
3004 /* genPlus - generates code for addition */
3005 /*-----------------------------------------------------------------*/
3007 genPlus (iCode * ic)
3009 int size, offset = 0;
3011 /* special cases :- */
3013 D(emitcode (";", "genPlus"));
3015 aopOp (IC_LEFT (ic), ic, FALSE);
3016 aopOp (IC_RIGHT (ic), ic, FALSE);
3017 aopOp (IC_RESULT (ic), ic, TRUE);
3019 /* if literal, literal on the right or
3020 if left requires ACC or right is already
3022 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3023 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3024 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3026 operand *t = IC_RIGHT (ic);
3027 IC_RIGHT (ic) = IC_LEFT (ic);
3031 /* if both left & right are in bit
3033 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3034 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3040 /* if left in bit space & right literal */
3041 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3042 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3044 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3045 /* if result in bit space */
3046 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3048 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3049 emitcode ("cpl", "c");
3050 outBitC (IC_RESULT (ic));
3054 size = getDataSize (IC_RESULT (ic));
3057 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3058 emitcode ("addc", "a,#00");
3059 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3065 /* if I can do an increment instead
3066 of add then GOOD for ME */
3067 if (genPlusIncr (ic) == TRUE)
3070 size = getDataSize (IC_RESULT (ic));
3074 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3076 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3078 emitcode ("add", "a,%s",
3079 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3081 emitcode ("addc", "a,%s",
3082 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3086 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3088 emitcode ("add", "a,%s",
3089 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3091 emitcode ("addc", "a,%s",
3092 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3094 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3097 adjustArithmeticResult (ic);
3100 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3101 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3102 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3105 /*-----------------------------------------------------------------*/
3106 /* genMinusDec :- does subtraction with deccrement if possible */
3107 /*-----------------------------------------------------------------*/
3109 genMinusDec (iCode * ic)
3111 unsigned int icount;
3112 unsigned int size = getDataSize (IC_RESULT (ic));
3114 /* will try to generate an increment */
3115 /* if the right side is not a literal
3117 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3120 /* if the literal value of the right hand side
3121 is greater than 4 then it is not worth it */
3122 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3125 D(emitcode (";", "genMinusDec"));
3127 /* if decrement 16 bits in register */
3128 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3136 /* If the next instruction is a goto and the goto target
3137 * is <= 10 instructions previous to this, we can generate
3138 * jumps straight to that target.
3140 if (ic->next && ic->next->op == GOTO
3141 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3142 && labelRange <= 10)
3144 emitcode (";", "tail decrement optimized");
3145 tlbl = IC_LABEL (ic->next);
3150 tlbl = newiTempLabel (NULL);
3154 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3155 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3156 IS_AOP_PREG (IC_RESULT (ic)))
3157 emitcode ("cjne", "%s,#0xff,%05d$"
3158 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3162 emitcode ("mov", "a,#0xff");
3163 emitcode ("cjne", "a,%s,%05d$"
3164 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3167 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3170 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3171 IS_AOP_PREG (IC_RESULT (ic)))
3172 emitcode ("cjne", "%s,#0xff,%05d$"
3173 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3177 emitcode ("cjne", "a,%s,%05d$"
3178 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3181 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3185 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3186 IS_AOP_PREG (IC_RESULT (ic)))
3187 emitcode ("cjne", "%s,#0xff,%05d$"
3188 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3192 emitcode ("cjne", "a,%s,%05d$"
3193 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3196 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3200 emitcode ("", "%05d$:", tlbl->key + 100);
3205 /* if the sizes are greater than 1 then we cannot */
3206 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3207 AOP_SIZE (IC_LEFT (ic)) > 1)
3210 /* we can if the aops of the left & result match or
3211 if they are in registers and the registers are the
3213 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3217 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3225 /*-----------------------------------------------------------------*/
3226 /* addSign - complete with sign */
3227 /*-----------------------------------------------------------------*/
3229 addSign (operand * result, int offset, int sign)
3231 int size = (getDataSize (result) - offset);
3236 emitcode ("rlc", "a");
3237 emitcode ("subb", "a,acc");
3239 aopPut (AOP (result), "a", offset++);
3243 aopPut (AOP (result), zero, offset++);
3247 /*-----------------------------------------------------------------*/
3248 /* genMinusBits - generates code for subtraction of two bits */
3249 /*-----------------------------------------------------------------*/
3251 genMinusBits (iCode * ic)
3253 symbol *lbl = newiTempLabel (NULL);
3255 D(emitcode (";", "genMinusBits"));
3257 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3259 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3260 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3261 emitcode ("cpl", "c");
3262 emitcode ("", "%05d$:", (lbl->key + 100));
3263 outBitC (IC_RESULT (ic));
3267 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3268 emitcode ("subb", "a,acc");
3269 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3270 emitcode ("inc", "a");
3271 emitcode ("", "%05d$:", (lbl->key + 100));
3272 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3273 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3277 /*-----------------------------------------------------------------*/
3278 /* genMinus - generates code for subtraction */
3279 /*-----------------------------------------------------------------*/
3281 genMinus (iCode * ic)
3283 int size, offset = 0;
3284 unsigned long lit = 0L;
3286 D(emitcode (";", "genMinus"));
3288 aopOp (IC_LEFT (ic), ic, FALSE);
3289 aopOp (IC_RIGHT (ic), ic, FALSE);
3290 aopOp (IC_RESULT (ic), ic, TRUE);
3292 /* special cases :- */
3293 /* if both left & right are in bit space */
3294 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3295 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3301 /* if I can do an decrement instead
3302 of subtract then GOOD for ME */
3303 if (genMinusDec (ic) == TRUE)
3306 size = getDataSize (IC_RESULT (ic));
3308 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3314 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3318 /* if literal, add a,#-lit, else normal subb */
3321 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3322 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3323 emitcode ("subb", "a,%s",
3324 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3327 /* first add without previous c */
3329 if (!size && lit==-1) {
3330 emitcode ("dec", "a");
3332 emitcode ("add", "a,#0x%02x",
3333 (unsigned int) (lit & 0x0FFL));
3336 emitcode ("addc", "a,#0x%02x",
3337 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3340 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3343 adjustArithmeticResult (ic);
3346 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3347 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3348 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3352 /*-----------------------------------------------------------------*/
3353 /* genMultbits :- multiplication of bits */
3354 /*-----------------------------------------------------------------*/
3356 genMultbits (operand * left,
3360 D(emitcode (";", "genMultbits"));
3362 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3363 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3368 /*-----------------------------------------------------------------*/
3369 /* genMultOneByte : 8*8=8/16 bit multiplication */
3370 /*-----------------------------------------------------------------*/
3372 genMultOneByte (operand * left,
3376 sym_link *opetype = operandType (result);
3378 int size=AOP_SIZE(result);
3380 D(emitcode (";", "genMultOneByte"));
3382 if (size<1 || size>2) {
3383 // this should never happen
3384 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3385 AOP_SIZE(result), __FILE__, lineno);
3389 /* (if two literals: the value is computed before) */
3390 /* if one literal, literal on the right */
3391 if (AOP_TYPE (left) == AOP_LIT)
3396 //emitcode (";", "swapped left and right");
3399 if (SPEC_USIGN(opetype)
3400 // ignore the sign of left and right, what else can we do?
3401 || (SPEC_USIGN(operandType(left)) &&
3402 SPEC_USIGN(operandType(right)))) {
3403 // just an unsigned 8*8=8/16 multiply
3404 //emitcode (";","unsigned");
3405 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3406 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3407 emitcode ("mul", "ab");
3408 aopPut (AOP (result), "a", 0);
3410 aopPut (AOP (result), "b", 1);
3415 // we have to do a signed multiply
3417 //emitcode (";", "signed");
3418 emitcode ("clr", "F0"); // reset sign flag
3419 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3421 lbl=newiTempLabel(NULL);
3422 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3423 // left side is negative, 8-bit two's complement, this fails for -128
3424 emitcode ("setb", "F0"); // set sign flag
3425 emitcode ("cpl", "a");
3426 emitcode ("inc", "a");
3428 emitcode ("", "%05d$:", lbl->key+100);
3431 if (AOP_TYPE(right)==AOP_LIT) {
3432 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3433 /* AND literal negative */
3435 emitcode ("cpl", "F0"); // complement sign flag
3436 emitcode ("mov", "b,#0x%02x", -val);
3438 emitcode ("mov", "b,#0x%02x", val);
3441 lbl=newiTempLabel(NULL);
3442 emitcode ("mov", "b,a");
3443 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3444 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3445 // right side is negative, 8-bit two's complement
3446 emitcode ("cpl", "F0"); // complement sign flag
3447 emitcode ("cpl", "a");
3448 emitcode ("inc", "a");
3449 emitcode ("", "%05d$:", lbl->key+100);
3451 emitcode ("mul", "ab");
3453 lbl=newiTempLabel(NULL);
3454 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3455 // only ONE op was negative, we have to do a 8/16-bit two's complement
3456 emitcode ("cpl", "a"); // lsb
3458 emitcode ("inc", "a");
3460 emitcode ("add", "a,#1");
3461 emitcode ("xch", "a,b");
3462 emitcode ("cpl", "a"); // msb
3463 emitcode ("addc", "a,#0");
3464 emitcode ("xch", "a,b");
3467 emitcode ("", "%05d$:", lbl->key+100);
3468 aopPut (AOP (result), "a", 0);
3470 aopPut (AOP (result), "b", 1);
3474 /*-----------------------------------------------------------------*/
3475 /* genMult - generates code for multiplication */
3476 /*-----------------------------------------------------------------*/
3478 genMult (iCode * ic)
3480 operand *left = IC_LEFT (ic);
3481 operand *right = IC_RIGHT (ic);
3482 operand *result = IC_RESULT (ic);
3484 D(emitcode (";", "genMult"));
3486 /* assign the amsops */
3487 aopOp (left, ic, FALSE);
3488 aopOp (right, ic, FALSE);
3489 aopOp (result, ic, TRUE);
3491 /* special cases first */
3493 if (AOP_TYPE (left) == AOP_CRY &&
3494 AOP_TYPE (right) == AOP_CRY)
3496 genMultbits (left, right, result);
3500 /* if both are of size == 1 */
3501 #if 0 // one of them can be a sloc shared with the result
3502 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3504 if (getSize(operandType(left)) == 1 &&
3505 getSize(operandType(right)) == 1)
3508 genMultOneByte (left, right, result);
3512 /* should have been converted to function call */
3513 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3514 getSize(OP_SYMBOL(right)->type));
3518 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3519 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3520 freeAsmop (result, NULL, ic, TRUE);
3523 /*-----------------------------------------------------------------*/
3524 /* genDivbits :- division of bits */
3525 /*-----------------------------------------------------------------*/
3527 genDivbits (operand * left,
3534 D(emitcode (";", "genDivbits"));
3536 /* the result must be bit */
3537 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3538 l = aopGet (AOP (left), 0, FALSE, FALSE);
3542 emitcode ("div", "ab");
3543 emitcode ("rrc", "a");
3544 aopPut (AOP (result), "c", 0);
3547 /*-----------------------------------------------------------------*/
3548 /* genDivOneByte : 8 bit division */
3549 /*-----------------------------------------------------------------*/
3551 genDivOneByte (operand * left,
3555 sym_link *opetype = operandType (result);
3560 D(emitcode (";", "genDivOneByte"));
3562 size = AOP_SIZE (result) - 1;
3564 /* signed or unsigned */
3565 if (SPEC_USIGN (opetype))
3567 /* unsigned is easy */
3568 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3569 l = aopGet (AOP (left), 0, FALSE, FALSE);
3571 emitcode ("div", "ab");
3572 aopPut (AOP (result), "a", 0);
3574 aopPut (AOP (result), zero, offset++);
3578 /* signed is a little bit more difficult */
3580 /* save the signs of the operands */
3581 l = aopGet (AOP (left), 0, FALSE, FALSE);
3583 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3584 emitcode ("push", "acc"); /* save it on the stack */
3586 /* now sign adjust for both left & right */
3587 l = aopGet (AOP (right), 0, FALSE, FALSE);
3589 lbl = newiTempLabel (NULL);
3590 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3591 emitcode ("cpl", "a");
3592 emitcode ("inc", "a");
3593 emitcode ("", "%05d$:", (lbl->key + 100));
3594 emitcode ("mov", "b,a");
3596 /* sign adjust left side */
3597 l = aopGet (AOP (left), 0, FALSE, FALSE);
3600 lbl = newiTempLabel (NULL);
3601 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3602 emitcode ("cpl", "a");
3603 emitcode ("inc", "a");
3604 emitcode ("", "%05d$:", (lbl->key + 100));
3606 /* now the division */
3607 emitcode ("div", "ab");
3608 /* we are interested in the lower order
3610 emitcode ("mov", "b,a");
3611 lbl = newiTempLabel (NULL);
3612 emitcode ("pop", "acc");
3613 /* if there was an over flow we don't
3614 adjust the sign of the result */
3615 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3616 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3618 emitcode ("clr", "a");
3619 emitcode ("subb", "a,b");
3620 emitcode ("mov", "b,a");
3621 emitcode ("", "%05d$:", (lbl->key + 100));
3623 /* now we are done */
3624 aopPut (AOP (result), "b", 0);
3627 emitcode ("mov", "c,b.7");
3628 emitcode ("subb", "a,acc");
3631 aopPut (AOP (result), "a", offset++);
3635 /*-----------------------------------------------------------------*/
3636 /* genDiv - generates code for division */
3637 /*-----------------------------------------------------------------*/
3641 operand *left = IC_LEFT (ic);
3642 operand *right = IC_RIGHT (ic);
3643 operand *result = IC_RESULT (ic);
3645 D(emitcode (";", "genDiv"));
3647 /* assign the amsops */
3648 aopOp (left, ic, FALSE);
3649 aopOp (right, ic, FALSE);
3650 aopOp (result, ic, TRUE);
3652 /* special cases first */
3654 if (AOP_TYPE (left) == AOP_CRY &&
3655 AOP_TYPE (right) == AOP_CRY)
3657 genDivbits (left, right, result);
3661 /* if both are of size == 1 */
3662 if (AOP_SIZE (left) == 1 &&
3663 AOP_SIZE (right) == 1)
3665 genDivOneByte (left, right, result);
3669 /* should have been converted to function call */
3672 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3673 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3674 freeAsmop (result, NULL, ic, TRUE);
3677 /*-----------------------------------------------------------------*/
3678 /* genModbits :- modulus of bits */
3679 /*-----------------------------------------------------------------*/
3681 genModbits (operand * left,
3688 D(emitcode (";", "genModbits"));
3690 /* the result must be bit */
3691 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3692 l = aopGet (AOP (left), 0, FALSE, FALSE);
3696 emitcode ("div", "ab");
3697 emitcode ("mov", "a,b");
3698 emitcode ("rrc", "a");
3699 aopPut (AOP (result), "c", 0);
3702 /*-----------------------------------------------------------------*/
3703 /* genModOneByte : 8 bit modulus */
3704 /*-----------------------------------------------------------------*/
3706 genModOneByte (operand * left,
3710 sym_link *opetype = operandType (result);
3714 D(emitcode (";", "genModOneByte"));
3716 /* signed or unsigned */
3717 if (SPEC_USIGN (opetype))
3719 /* unsigned is easy */
3720 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3721 l = aopGet (AOP (left), 0, FALSE, FALSE);
3723 emitcode ("div", "ab");
3724 aopPut (AOP (result), "b", 0);
3728 /* signed is a little bit more difficult */
3730 /* save the signs of the operands */
3731 l = aopGet (AOP (left), 0, FALSE, FALSE);
3734 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3735 emitcode ("push", "acc"); /* save it on the stack */
3737 /* now sign adjust for both left & right */
3738 l = aopGet (AOP (right), 0, FALSE, FALSE);
3741 lbl = newiTempLabel (NULL);
3742 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3743 emitcode ("cpl", "a");
3744 emitcode ("inc", "a");
3745 emitcode ("", "%05d$:", (lbl->key + 100));
3746 emitcode ("mov", "b,a");
3748 /* sign adjust left side */
3749 l = aopGet (AOP (left), 0, FALSE, FALSE);
3752 lbl = newiTempLabel (NULL);
3753 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3754 emitcode ("cpl", "a");
3755 emitcode ("inc", "a");
3756 emitcode ("", "%05d$:", (lbl->key + 100));
3758 /* now the multiplication */
3759 emitcode ("div", "ab");
3760 /* we are interested in the lower order
3762 lbl = newiTempLabel (NULL);
3763 emitcode ("pop", "acc");
3764 /* if there was an over flow we don't
3765 adjust the sign of the result */
3766 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3767 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3769 emitcode ("clr", "a");
3770 emitcode ("subb", "a,b");
3771 emitcode ("mov", "b,a");
3772 emitcode ("", "%05d$:", (lbl->key + 100));
3774 /* now we are done */
3775 aopPut (AOP (result), "b", 0);
3779 /*-----------------------------------------------------------------*/
3780 /* genMod - generates code for division */
3781 /*-----------------------------------------------------------------*/
3785 operand *left = IC_LEFT (ic);
3786 operand *right = IC_RIGHT (ic);
3787 operand *result = IC_RESULT (ic);
3789 D(emitcode (";", "genMod"));
3791 /* assign the amsops */
3792 aopOp (left, ic, FALSE);
3793 aopOp (right, ic, FALSE);
3794 aopOp (result, ic, TRUE);
3796 /* special cases first */
3798 if (AOP_TYPE (left) == AOP_CRY &&
3799 AOP_TYPE (right) == AOP_CRY)
3801 genModbits (left, right, result);
3805 /* if both are of size == 1 */
3806 if (AOP_SIZE (left) == 1 &&
3807 AOP_SIZE (right) == 1)
3809 genModOneByte (left, right, result);
3813 /* should have been converted to function call */
3817 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3818 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3819 freeAsmop (result, NULL, ic, TRUE);
3822 /*-----------------------------------------------------------------*/
3823 /* genIfxJump :- will create a jump depending on the ifx */
3824 /*-----------------------------------------------------------------*/
3826 genIfxJump (iCode * ic, char *jval)
3829 symbol *tlbl = newiTempLabel (NULL);
3832 D(emitcode (";", "genIfxJump"));
3834 /* if true label then we jump if condition
3838 jlbl = IC_TRUE (ic);
3839 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3840 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3844 /* false label is present */
3845 jlbl = IC_FALSE (ic);
3846 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3847 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3849 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3850 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3852 emitcode (inst, "%05d$", tlbl->key + 100);
3853 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3854 emitcode ("", "%05d$:", tlbl->key + 100);
3856 /* mark the icode as generated */
3860 /*-----------------------------------------------------------------*/
3861 /* genCmp :- greater or less than comparison */
3862 /*-----------------------------------------------------------------*/
3864 genCmp (operand * left, operand * right,
3865 operand * result, iCode * ifx, int sign, iCode *ic)
3867 int size, offset = 0;
3868 unsigned long lit = 0L;
3870 D(emitcode (";", "genCmp"));
3872 /* if left & right are bit variables */
3873 if (AOP_TYPE (left) == AOP_CRY &&
3874 AOP_TYPE (right) == AOP_CRY)
3876 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3877 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3881 /* subtract right from left if at the
3882 end the carry flag is set then we know that
3883 left is greater than right */
3884 size = max (AOP_SIZE (left), AOP_SIZE (right));
3886 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3887 if ((size == 1) && !sign &&
3888 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3890 symbol *lbl = newiTempLabel (NULL);
3891 emitcode ("cjne", "%s,%s,%05d$",
3892 aopGet (AOP (left), offset, FALSE, FALSE),
3893 aopGet (AOP (right), offset, FALSE, FALSE),
3895 emitcode ("", "%05d$:", lbl->key + 100);
3899 if (AOP_TYPE (right) == AOP_LIT)
3901 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3902 /* optimize if(x < 0) or if(x >= 0) */
3911 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3912 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3914 genIfxJump (ifx, "acc.7");
3918 emitcode ("rlc", "a");
3926 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3927 if (sign && size == 0)
3929 emitcode ("xrl", "a,#0x80");
3930 if (AOP_TYPE (right) == AOP_LIT)
3932 unsigned long lit = (unsigned long)
3933 floatFromVal (AOP (right)->aopu.aop_lit);
3934 emitcode ("subb", "a,#0x%02x",
3935 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3939 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3940 emitcode ("xrl", "b,#0x80");
3941 emitcode ("subb", "a,b");
3945 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3951 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3952 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3953 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3959 /* if the result is used in the next
3960 ifx conditional branch then generate
3961 code a little differently */
3963 genIfxJump (ifx, "c");
3966 /* leave the result in acc */
3970 /*-----------------------------------------------------------------*/
3971 /* genCmpGt :- greater than comparison */
3972 /*-----------------------------------------------------------------*/
3974 genCmpGt (iCode * ic, iCode * ifx)
3976 operand *left, *right, *result;
3977 sym_link *letype, *retype;
3980 D(emitcode (";", "genCmpGt"));
3982 left = IC_LEFT (ic);
3983 right = IC_RIGHT (ic);
3984 result = IC_RESULT (ic);
3986 letype = getSpec (operandType (left));
3987 retype = getSpec (operandType (right));
3988 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3989 /* assign the amsops */
3990 aopOp (left, ic, FALSE);
3991 aopOp (right, ic, FALSE);
3992 aopOp (result, ic, TRUE);
3994 genCmp (right, left, result, ifx, sign,ic);
3996 freeAsmop (result, NULL, ic, TRUE);
3999 /*-----------------------------------------------------------------*/
4000 /* genCmpLt - less than comparisons */
4001 /*-----------------------------------------------------------------*/
4003 genCmpLt (iCode * ic, iCode * ifx)
4005 operand *left, *right, *result;
4006 sym_link *letype, *retype;
4009 D(emitcode (";", "genCmpLt"));
4011 left = IC_LEFT (ic);
4012 right = IC_RIGHT (ic);
4013 result = IC_RESULT (ic);
4015 letype = getSpec (operandType (left));
4016 retype = getSpec (operandType (right));
4017 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4019 /* assign the amsops */
4020 aopOp (left, ic, FALSE);
4021 aopOp (right, ic, FALSE);
4022 aopOp (result, ic, TRUE);
4024 genCmp (left, right, result, ifx, sign,ic);
4026 freeAsmop (result, NULL, ic, TRUE);
4029 /*-----------------------------------------------------------------*/
4030 /* gencjneshort - compare and jump if not equal */
4031 /*-----------------------------------------------------------------*/
4033 gencjneshort (operand * left, operand * right, symbol * lbl)
4035 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4037 unsigned long lit = 0L;
4039 /* if the left side is a literal or
4040 if the right is in a pointer register and left
4042 if ((AOP_TYPE (left) == AOP_LIT) ||
4043 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4049 if (AOP_TYPE (right) == AOP_LIT)
4050 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4052 /* if the right side is a literal then anything goes */
4053 if (AOP_TYPE (right) == AOP_LIT &&
4054 AOP_TYPE (left) != AOP_DIR)
4058 emitcode ("cjne", "%s,%s,%05d$",
4059 aopGet (AOP (left), offset, FALSE, FALSE),
4060 aopGet (AOP (right), offset, FALSE, FALSE),
4066 /* if the right side is in a register or in direct space or
4067 if the left is a pointer register & right is not */
4068 else if (AOP_TYPE (right) == AOP_REG ||
4069 AOP_TYPE (right) == AOP_DIR ||
4070 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4071 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4075 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4076 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4077 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4078 emitcode ("jnz", "%05d$", lbl->key + 100);
4080 emitcode ("cjne", "a,%s,%05d$",
4081 aopGet (AOP (right), offset, FALSE, TRUE),
4088 /* right is a pointer reg need both a & b */
4091 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4092 if (strcmp (l, "b"))
4093 emitcode ("mov", "b,%s", l);
4094 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4095 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4101 /*-----------------------------------------------------------------*/
4102 /* gencjne - compare and jump if not equal */
4103 /*-----------------------------------------------------------------*/
4105 gencjne (operand * left, operand * right, symbol * lbl)
4107 symbol *tlbl = newiTempLabel (NULL);
4109 gencjneshort (left, right, lbl);
4111 emitcode ("mov", "a,%s", one);
4112 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4113 emitcode ("", "%05d$:", lbl->key + 100);
4114 emitcode ("clr", "a");
4115 emitcode ("", "%05d$:", tlbl->key + 100);
4118 /*-----------------------------------------------------------------*/
4119 /* genCmpEq - generates code for equal to */
4120 /*-----------------------------------------------------------------*/
4122 genCmpEq (iCode * ic, iCode * ifx)
4124 operand *left, *right, *result;
4126 D(emitcode (";", "genCmpEq"));
4128 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4129 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4130 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4132 /* if literal, literal on the right or
4133 if the right is in a pointer register and left
4135 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4136 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4138 operand *t = IC_RIGHT (ic);
4139 IC_RIGHT (ic) = IC_LEFT (ic);
4143 if (ifx && !AOP_SIZE (result))
4146 /* if they are both bit variables */
4147 if (AOP_TYPE (left) == AOP_CRY &&
4148 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4150 if (AOP_TYPE (right) == AOP_LIT)
4152 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4155 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4156 emitcode ("cpl", "c");
4160 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4164 emitcode ("clr", "c");
4166 /* AOP_TYPE(right) == AOP_CRY */
4170 symbol *lbl = newiTempLabel (NULL);
4171 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4172 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4173 emitcode ("cpl", "c");
4174 emitcode ("", "%05d$:", (lbl->key + 100));
4176 /* if true label then we jump if condition
4178 tlbl = newiTempLabel (NULL);
4181 emitcode ("jnc", "%05d$", tlbl->key + 100);
4182 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4186 emitcode ("jc", "%05d$", tlbl->key + 100);
4187 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4189 emitcode ("", "%05d$:", tlbl->key + 100);
4193 tlbl = newiTempLabel (NULL);
4194 gencjneshort (left, right, tlbl);
4197 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4198 emitcode ("", "%05d$:", tlbl->key + 100);
4202 symbol *lbl = newiTempLabel (NULL);
4203 emitcode ("sjmp", "%05d$", lbl->key + 100);
4204 emitcode ("", "%05d$:", tlbl->key + 100);
4205 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4206 emitcode ("", "%05d$:", lbl->key + 100);
4209 /* mark the icode as generated */
4214 /* if they are both bit variables */
4215 if (AOP_TYPE (left) == AOP_CRY &&
4216 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4218 if (AOP_TYPE (right) == AOP_LIT)
4220 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4223 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4224 emitcode ("cpl", "c");
4228 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4232 emitcode ("clr", "c");
4234 /* AOP_TYPE(right) == AOP_CRY */
4238 symbol *lbl = newiTempLabel (NULL);
4239 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4240 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4241 emitcode ("cpl", "c");
4242 emitcode ("", "%05d$:", (lbl->key + 100));
4245 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4252 genIfxJump (ifx, "c");
4255 /* if the result is used in an arithmetic operation
4256 then put the result in place */
4261 gencjne (left, right, newiTempLabel (NULL));
4262 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4264 aopPut (AOP (result), "a", 0);
4269 genIfxJump (ifx, "a");
4272 /* if the result is used in an arithmetic operation
4273 then put the result in place */
4274 if (AOP_TYPE (result) != AOP_CRY)
4276 /* leave the result in acc */
4280 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4281 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4282 freeAsmop (result, NULL, ic, TRUE);
4285 /*-----------------------------------------------------------------*/
4286 /* ifxForOp - returns the icode containing the ifx for operand */
4287 /*-----------------------------------------------------------------*/
4289 ifxForOp (operand * op, iCode * ic)
4291 /* if true symbol then needs to be assigned */
4292 if (IS_TRUE_SYMOP (op))
4295 /* if this has register type condition and
4296 the next instruction is ifx with the same operand
4297 and live to of the operand is upto the ifx only then */
4299 ic->next->op == IFX &&
4300 IC_COND (ic->next)->key == op->key &&
4301 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4307 /*-----------------------------------------------------------------*/
4308 /* hasInc - operand is incremented before any other use */
4309 /*-----------------------------------------------------------------*/
4311 hasInc (operand *op, iCode *ic)
4313 sym_link *type = operandType(op);
4314 sym_link *retype = getSpec (type);
4315 iCode *lic = ic->next;
4318 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4319 if (!IS_SYMOP(op)) return NULL;
4321 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4322 isize = getSize(type->next);
4324 /* if operand of the form op = op + <sizeof *op> */
4325 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4326 isOperandEqual(IC_RESULT(lic),op) &&
4327 isOperandLiteral(IC_RIGHT(lic)) &&
4328 operandLitValue(IC_RIGHT(lic)) == isize) {
4331 /* if the operand used or deffed */
4332 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4335 /* if GOTO or IFX */
4336 if (lic->op == IFX || lic->op == GOTO) break;
4342 /*-----------------------------------------------------------------*/
4343 /* genAndOp - for && operation */
4344 /*-----------------------------------------------------------------*/
4346 genAndOp (iCode * ic)
4348 operand *left, *right, *result;
4351 D(emitcode (";", "genAndOp"));
4353 /* note here that && operations that are in an
4354 if statement are taken away by backPatchLabels
4355 only those used in arthmetic operations remain */
4356 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4357 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4358 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4360 /* if both are bit variables */
4361 if (AOP_TYPE (left) == AOP_CRY &&
4362 AOP_TYPE (right) == AOP_CRY)
4364 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4365 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4370 tlbl = newiTempLabel (NULL);
4372 emitcode ("jz", "%05d$", tlbl->key + 100);
4374 emitcode ("", "%05d$:", tlbl->key + 100);
4378 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4379 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4380 freeAsmop (result, NULL, ic, TRUE);
4384 /*-----------------------------------------------------------------*/
4385 /* genOrOp - for || operation */
4386 /*-----------------------------------------------------------------*/
4388 genOrOp (iCode * ic)
4390 operand *left, *right, *result;
4393 D(emitcode (";", "genOrOp"));
4395 /* note here that || operations that are in an
4396 if statement are taken away by backPatchLabels
4397 only those used in arthmetic operations remain */
4398 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4399 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4400 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4402 /* if both are bit variables */
4403 if (AOP_TYPE (left) == AOP_CRY &&
4404 AOP_TYPE (right) == AOP_CRY)
4406 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4407 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4412 tlbl = newiTempLabel (NULL);
4414 emitcode ("jnz", "%05d$", tlbl->key + 100);
4416 emitcode ("", "%05d$:", tlbl->key + 100);
4420 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4421 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4422 freeAsmop (result, NULL, ic, TRUE);
4425 /*-----------------------------------------------------------------*/
4426 /* isLiteralBit - test if lit == 2^n */
4427 /*-----------------------------------------------------------------*/
4429 isLiteralBit (unsigned long lit)
4431 unsigned long pw[32] =
4432 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4433 0x100L, 0x200L, 0x400L, 0x800L,
4434 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4435 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4436 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4437 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4438 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4441 for (idx = 0; idx < 32; idx++)
4447 /*-----------------------------------------------------------------*/
4448 /* continueIfTrue - */
4449 /*-----------------------------------------------------------------*/
4451 continueIfTrue (iCode * ic)
4454 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4458 /*-----------------------------------------------------------------*/
4460 /*-----------------------------------------------------------------*/
4462 jumpIfTrue (iCode * ic)
4465 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4469 /*-----------------------------------------------------------------*/
4470 /* jmpTrueOrFalse - */
4471 /*-----------------------------------------------------------------*/
4473 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4475 // ugly but optimized by peephole
4478 symbol *nlbl = newiTempLabel (NULL);
4479 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4480 emitcode ("", "%05d$:", tlbl->key + 100);
4481 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4482 emitcode ("", "%05d$:", nlbl->key + 100);
4486 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4487 emitcode ("", "%05d$:", tlbl->key + 100);
4492 /*-----------------------------------------------------------------*/
4493 /* genAnd - code for and */
4494 /*-----------------------------------------------------------------*/
4496 genAnd (iCode * ic, iCode * ifx)
4498 operand *left, *right, *result;
4499 int size, offset = 0;
4500 unsigned long lit = 0L;
4504 D(emitcode (";", "genAnd"));
4506 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4507 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4508 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4511 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4513 AOP_TYPE (left), AOP_TYPE (right));
4514 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4516 AOP_SIZE (left), AOP_SIZE (right));
4519 /* if left is a literal & right is not then exchange them */
4520 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4521 AOP_NEEDSACC (left))
4523 operand *tmp = right;
4528 /* if result = right then exchange them */
4529 if (sameRegs (AOP (result), AOP (right)))
4531 operand *tmp = right;
4536 /* if right is bit then exchange them */
4537 if (AOP_TYPE (right) == AOP_CRY &&
4538 AOP_TYPE (left) != AOP_CRY)
4540 operand *tmp = right;
4544 if (AOP_TYPE (right) == AOP_LIT)
4545 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4547 size = AOP_SIZE (result);
4550 // result = bit & yy;
4551 if (AOP_TYPE (left) == AOP_CRY)
4553 // c = bit & literal;
4554 if (AOP_TYPE (right) == AOP_LIT)
4558 if (size && sameRegs (AOP (result), AOP (left)))
4561 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4566 if (size && (AOP_TYPE (result) == AOP_CRY))
4568 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4571 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4576 emitcode ("clr", "c");
4581 if (AOP_TYPE (right) == AOP_CRY)
4584 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4585 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4590 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4592 emitcode ("rrc", "a");
4593 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4601 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4602 genIfxJump (ifx, "c");
4606 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4607 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4608 if ((AOP_TYPE (right) == AOP_LIT) &&
4609 (AOP_TYPE (result) == AOP_CRY) &&
4610 (AOP_TYPE (left) != AOP_CRY))
4612 int posbit = isLiteralBit (lit);
4617 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4620 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4626 sprintf (buffer, "acc.%d", posbit & 0x07);
4627 genIfxJump (ifx, buffer);
4634 symbol *tlbl = newiTempLabel (NULL);
4635 int sizel = AOP_SIZE (left);
4637 emitcode ("setb", "c");
4640 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4642 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4644 if ((posbit = isLiteralBit (bytelit)) != 0)
4645 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4648 if (bytelit != 0x0FFL)
4649 emitcode ("anl", "a,%s",
4650 aopGet (AOP (right), offset, FALSE, TRUE));
4651 emitcode ("jnz", "%05d$", tlbl->key + 100);
4656 // bit = left & literal
4659 emitcode ("clr", "c");
4660 emitcode ("", "%05d$:", tlbl->key + 100);
4662 // if(left & literal)
4666 jmpTrueOrFalse (ifx, tlbl);
4674 /* if left is same as result */
4675 if (sameRegs (AOP (result), AOP (left)))
4677 for (; size--; offset++)
4679 if (AOP_TYPE (right) == AOP_LIT)
4681 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4683 else if (bytelit == 0)
4684 aopPut (AOP (result), zero, offset);
4685 else if (IS_AOP_PREG (result))
4687 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4688 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4689 aopPut (AOP (result), "a", offset);
4692 emitcode ("anl", "%s,%s",
4693 aopGet (AOP (left), offset, FALSE, TRUE),
4694 aopGet (AOP (right), offset, FALSE, FALSE));
4698 if (AOP_TYPE (left) == AOP_ACC)
4699 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4702 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4703 if (IS_AOP_PREG (result))
4705 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4706 aopPut (AOP (result), "a", offset);
4710 emitcode ("anl", "%s,a",
4711 aopGet (AOP (left), offset, FALSE, TRUE));
4718 // left & result in different registers
4719 if (AOP_TYPE (result) == AOP_CRY)
4722 // if(size), result in bit
4723 // if(!size && ifx), conditional oper: if(left & right)
4724 symbol *tlbl = newiTempLabel (NULL);
4725 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4727 emitcode ("setb", "c");
4730 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4731 emitcode ("anl", "a,%s",
4732 aopGet (AOP (right), offset, FALSE, FALSE));
4734 if (AOP_TYPE(left)==AOP_ACC) {
4735 emitcode("mov", "b,a");
4736 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4737 emitcode("anl", "a,b");
4739 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4740 emitcode ("anl", "a,%s",
4741 aopGet (AOP (left), offset, FALSE, FALSE));
4744 emitcode ("jnz", "%05d$", tlbl->key + 100);
4750 emitcode ("", "%05d$:", tlbl->key + 100);
4754 jmpTrueOrFalse (ifx, tlbl);
4758 for (; (size--); offset++)
4761 // result = left & right
4762 if (AOP_TYPE (right) == AOP_LIT)
4764 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4766 aopPut (AOP (result),
4767 aopGet (AOP (left), offset, FALSE, FALSE),
4771 else if (bytelit == 0)
4773 aopPut (AOP (result), zero, offset);
4777 // faster than result <- left, anl result,right
4778 // and better if result is SFR
4779 if (AOP_TYPE (left) == AOP_ACC)
4780 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4783 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4784 emitcode ("anl", "a,%s",
4785 aopGet (AOP (left), offset, FALSE, FALSE));
4787 aopPut (AOP (result), "a", offset);
4793 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4794 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795 freeAsmop (result, NULL, ic, TRUE);
4798 /*-----------------------------------------------------------------*/
4799 /* genOr - code for or */
4800 /*-----------------------------------------------------------------*/
4802 genOr (iCode * ic, iCode * ifx)
4804 operand *left, *right, *result;
4805 int size, offset = 0;
4806 unsigned long lit = 0L;
4808 D(emitcode (";", "genOr"));
4810 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4811 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4812 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4815 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4817 AOP_TYPE (left), AOP_TYPE (right));
4818 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4820 AOP_SIZE (left), AOP_SIZE (right));
4823 /* if left is a literal & right is not then exchange them */
4824 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4825 AOP_NEEDSACC (left))
4827 operand *tmp = right;
4832 /* if result = right then exchange them */
4833 if (sameRegs (AOP (result), AOP (right)))
4835 operand *tmp = right;
4840 /* if right is bit then exchange them */
4841 if (AOP_TYPE (right) == AOP_CRY &&
4842 AOP_TYPE (left) != AOP_CRY)
4844 operand *tmp = right;
4848 if (AOP_TYPE (right) == AOP_LIT)
4849 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4851 size = AOP_SIZE (result);
4855 if (AOP_TYPE (left) == AOP_CRY)
4857 if (AOP_TYPE (right) == AOP_LIT)
4859 // c = bit & literal;
4862 // lit != 0 => result = 1
4863 if (AOP_TYPE (result) == AOP_CRY)
4866 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4868 continueIfTrue (ifx);
4871 emitcode ("setb", "c");
4875 // lit == 0 => result = left
4876 if (size && sameRegs (AOP (result), AOP (left)))
4878 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4883 if (AOP_TYPE (right) == AOP_CRY)
4886 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4887 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4892 symbol *tlbl = newiTempLabel (NULL);
4893 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4894 emitcode ("setb", "c");
4895 emitcode ("jb", "%s,%05d$",
4896 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4898 emitcode ("jnz", "%05d$", tlbl->key + 100);
4899 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4901 jmpTrueOrFalse (ifx, tlbl);
4907 emitcode ("", "%05d$:", tlbl->key + 100);
4916 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4917 genIfxJump (ifx, "c");
4921 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4922 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4923 if ((AOP_TYPE (right) == AOP_LIT) &&
4924 (AOP_TYPE (result) == AOP_CRY) &&
4925 (AOP_TYPE (left) != AOP_CRY))
4931 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4933 continueIfTrue (ifx);
4938 // lit = 0, result = boolean(left)
4940 emitcode ("setb", "c");
4944 symbol *tlbl = newiTempLabel (NULL);
4945 emitcode ("jnz", "%05d$", tlbl->key + 100);
4947 emitcode ("", "%05d$:", tlbl->key + 100);
4951 genIfxJump (ifx, "a");
4959 /* if left is same as result */
4960 if (sameRegs (AOP (result), AOP (left)))
4962 for (; size--; offset++)
4964 if (AOP_TYPE (right) == AOP_LIT)
4966 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4968 else if (IS_AOP_PREG (left))
4970 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4971 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4972 aopPut (AOP (result), "a", offset);
4975 emitcode ("orl", "%s,%s",
4976 aopGet (AOP (left), offset, FALSE, TRUE),
4977 aopGet (AOP (right), offset, FALSE, FALSE));
4981 if (AOP_TYPE (left) == AOP_ACC)
4982 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4985 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4986 if (IS_AOP_PREG (left))
4988 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4989 aopPut (AOP (result), "a", offset);
4992 emitcode ("orl", "%s,a",
4993 aopGet (AOP (left), offset, FALSE, TRUE));
5000 // left & result in different registers
5001 if (AOP_TYPE (result) == AOP_CRY)
5004 // if(size), result in bit
5005 // if(!size && ifx), conditional oper: if(left | right)
5006 symbol *tlbl = newiTempLabel (NULL);
5007 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5009 emitcode ("setb", "c");
5012 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5013 emitcode ("orl", "a,%s",
5014 aopGet (AOP (right), offset, FALSE, FALSE));
5016 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5017 emitcode ("orl", "a,%s",
5018 aopGet (AOP (left), offset, FALSE, FALSE));
5020 emitcode ("jnz", "%05d$", tlbl->key + 100);
5026 emitcode ("", "%05d$:", tlbl->key + 100);
5030 jmpTrueOrFalse (ifx, tlbl);
5033 for (; (size--); offset++)
5036 // result = left & right
5037 if (AOP_TYPE (right) == AOP_LIT)
5039 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5041 aopPut (AOP (result),
5042 aopGet (AOP (left), offset, FALSE, FALSE),
5047 // faster than result <- left, anl result,right
5048 // and better if result is SFR
5049 if (AOP_TYPE (left) == AOP_ACC)
5050 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5053 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5054 emitcode ("orl", "a,%s",
5055 aopGet (AOP (left), offset, FALSE, FALSE));
5057 aopPut (AOP (result), "a", offset);
5062 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5063 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5064 freeAsmop (result, NULL, ic, TRUE);
5067 /*-----------------------------------------------------------------*/
5068 /* genXor - code for xclusive or */
5069 /*-----------------------------------------------------------------*/
5071 genXor (iCode * ic, iCode * ifx)
5073 operand *left, *right, *result;
5074 int size, offset = 0;
5075 unsigned long lit = 0L;
5077 D(emitcode (";", "genXor"));
5079 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5080 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5081 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5084 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5086 AOP_TYPE (left), AOP_TYPE (right));
5087 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5089 AOP_SIZE (left), AOP_SIZE (right));
5092 /* if left is a literal & right is not ||
5093 if left needs acc & right does not */
5094 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5095 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5097 operand *tmp = right;
5102 /* if result = right then exchange them */
5103 if (sameRegs (AOP (result), AOP (right)))
5105 operand *tmp = right;
5110 /* if right is bit then exchange them */
5111 if (AOP_TYPE (right) == AOP_CRY &&
5112 AOP_TYPE (left) != AOP_CRY)
5114 operand *tmp = right;
5118 if (AOP_TYPE (right) == AOP_LIT)
5119 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5121 size = AOP_SIZE (result);
5125 if (AOP_TYPE (left) == AOP_CRY)
5127 if (AOP_TYPE (right) == AOP_LIT)
5129 // c = bit & literal;
5132 // lit>>1 != 0 => result = 1
5133 if (AOP_TYPE (result) == AOP_CRY)
5136 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5138 continueIfTrue (ifx);
5141 emitcode ("setb", "c");
5148 // lit == 0, result = left
5149 if (size && sameRegs (AOP (result), AOP (left)))
5151 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5155 // lit == 1, result = not(left)
5156 if (size && sameRegs (AOP (result), AOP (left)))
5158 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5163 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5164 emitcode ("cpl", "c");
5173 symbol *tlbl = newiTempLabel (NULL);
5174 if (AOP_TYPE (right) == AOP_CRY)
5177 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5181 int sizer = AOP_SIZE (right);
5183 // if val>>1 != 0, result = 1
5184 emitcode ("setb", "c");
5187 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5189 // test the msb of the lsb
5190 emitcode ("anl", "a,#0xfe");
5191 emitcode ("jnz", "%05d$", tlbl->key + 100);
5195 emitcode ("rrc", "a");
5197 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5198 emitcode ("cpl", "c");
5199 emitcode ("", "%05d$:", (tlbl->key + 100));
5206 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5207 genIfxJump (ifx, "c");
5211 if (sameRegs (AOP (result), AOP (left)))
5213 /* if left is same as result */
5214 for (; size--; offset++)
5216 if (AOP_TYPE (right) == AOP_LIT)
5218 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5220 else if (IS_AOP_PREG (left))
5222 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5223 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5224 aopPut (AOP (result), "a", offset);
5227 emitcode ("xrl", "%s,%s",
5228 aopGet (AOP (left), offset, FALSE, TRUE),
5229 aopGet (AOP (right), offset, FALSE, FALSE));
5233 if (AOP_TYPE (left) == AOP_ACC)
5234 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5237 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5238 if (IS_AOP_PREG (left))
5240 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5241 aopPut (AOP (result), "a", offset);
5244 emitcode ("xrl", "%s,a",
5245 aopGet (AOP (left), offset, FALSE, TRUE));
5252 // left & result in different registers
5253 if (AOP_TYPE (result) == AOP_CRY)
5256 // if(size), result in bit
5257 // if(!size && ifx), conditional oper: if(left ^ right)
5258 symbol *tlbl = newiTempLabel (NULL);
5259 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5261 emitcode ("setb", "c");
5264 if ((AOP_TYPE (right) == AOP_LIT) &&
5265 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5267 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5271 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5272 emitcode ("xrl", "a,%s",
5273 aopGet (AOP (right), offset, FALSE, FALSE));
5275 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5276 emitcode ("xrl", "a,%s",
5277 aopGet (AOP (left), offset, FALSE, FALSE));
5280 emitcode ("jnz", "%05d$", tlbl->key + 100);
5286 emitcode ("", "%05d$:", tlbl->key + 100);
5290 jmpTrueOrFalse (ifx, tlbl);
5293 for (; (size--); offset++)
5296 // result = left & right
5297 if (AOP_TYPE (right) == AOP_LIT)
5299 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5301 aopPut (AOP (result),
5302 aopGet (AOP (left), offset, FALSE, FALSE),
5307 // faster than result <- left, anl result,right
5308 // and better if result is SFR
5309 if (AOP_TYPE (left) == AOP_ACC)
5310 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5313 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5314 emitcode ("xrl", "a,%s",
5315 aopGet (AOP (left), offset, FALSE, TRUE));
5317 aopPut (AOP (result), "a", offset);
5322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5323 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5324 freeAsmop (result, NULL, ic, TRUE);
5327 /*-----------------------------------------------------------------*/
5328 /* genInline - write the inline code out */
5329 /*-----------------------------------------------------------------*/
5331 genInline (iCode * ic)
5333 char *buffer, *bp, *bp1;
5335 D(emitcode (";", "genInline"));
5337 _G.inLine += (!options.asmpeep);
5339 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5340 strcpy (buffer, IC_INLINE (ic));
5342 /* emit each line as a code */
5367 /* emitcode("",buffer); */
5368 _G.inLine -= (!options.asmpeep);
5371 /*-----------------------------------------------------------------*/
5372 /* genRRC - rotate right with carry */
5373 /*-----------------------------------------------------------------*/
5377 operand *left, *result;
5378 int size, offset = 0;
5381 D(emitcode (";", "genRRC"));
5383 /* rotate right with carry */
5384 left = IC_LEFT (ic);
5385 result = IC_RESULT (ic);
5386 aopOp (left, ic, FALSE);
5387 aopOp (result, ic, FALSE);
5389 /* move it to the result */
5390 size = AOP_SIZE (result);
5392 if (size == 1) { /* special case for 1 byte */
5393 l = aopGet (AOP (left), offset, FALSE, FALSE);
5395 emitcode ("rr", "a");
5401 l = aopGet (AOP (left), offset, FALSE, FALSE);
5403 emitcode ("rrc", "a");
5404 if (AOP_SIZE (result) > 1)
5405 aopPut (AOP (result), "a", offset--);
5407 /* now we need to put the carry into the
5408 highest order byte of the result */
5409 if (AOP_SIZE (result) > 1)
5411 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5414 emitcode ("mov", "acc.7,c");
5416 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5417 freeAsmop (left, NULL, ic, TRUE);
5418 freeAsmop (result, NULL, ic, TRUE);
5421 /*-----------------------------------------------------------------*/
5422 /* genRLC - generate code for rotate left with carry */
5423 /*-----------------------------------------------------------------*/
5427 operand *left, *result;
5428 int size, offset = 0;
5431 D(emitcode (";", "genRLC"));
5433 /* rotate right with carry */
5434 left = IC_LEFT (ic);
5435 result = IC_RESULT (ic);
5436 aopOp (left, ic, FALSE);
5437 aopOp (result, ic, FALSE);
5439 /* move it to the result */
5440 size = AOP_SIZE (result);
5444 l = aopGet (AOP (left), offset, FALSE, FALSE);
5446 if (size == 0) { /* special case for 1 byte */
5450 emitcode ("add", "a,acc");
5451 if (AOP_SIZE (result) > 1)
5452 aopPut (AOP (result), "a", offset++);
5455 l = aopGet (AOP (left), offset, FALSE, FALSE);
5457 emitcode ("rlc", "a");
5458 if (AOP_SIZE (result) > 1)
5459 aopPut (AOP (result), "a", offset++);
5462 /* now we need to put the carry into the
5463 highest order byte of the result */
5464 if (AOP_SIZE (result) > 1)
5466 l = aopGet (AOP (result), 0, FALSE, FALSE);
5469 emitcode ("mov", "acc.0,c");
5471 aopPut (AOP (result), "a", 0);
5472 freeAsmop (left, NULL, ic, TRUE);
5473 freeAsmop (result, NULL, ic, TRUE);
5476 /*-----------------------------------------------------------------*/
5477 /* genGetHbit - generates code get highest order bit */
5478 /*-----------------------------------------------------------------*/
5480 genGetHbit (iCode * ic)
5482 operand *left, *result;
5484 D(emitcode (";", "genGetHbit"));
5486 left = IC_LEFT (ic);
5487 result = IC_RESULT (ic);
5488 aopOp (left, ic, FALSE);
5489 aopOp (result, ic, FALSE);
5491 /* get the highest order byte into a */
5492 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5493 if (AOP_TYPE (result) == AOP_CRY)
5495 emitcode ("rlc", "a");
5500 emitcode ("rl", "a");
5501 emitcode ("anl", "a,#0x01");
5506 freeAsmop (left, NULL, ic, TRUE);
5507 freeAsmop (result, NULL, ic, TRUE);
5510 /*-----------------------------------------------------------------*/
5511 /* AccRol - rotate left accumulator by known count */
5512 /*-----------------------------------------------------------------*/
5514 AccRol (int shCount)
5516 shCount &= 0x0007; // shCount : 0..7
5523 emitcode ("rl", "a");
5526 emitcode ("rl", "a");
5527 emitcode ("rl", "a");
5530 emitcode ("swap", "a");
5531 emitcode ("rr", "a");
5534 emitcode ("swap", "a");
5537 emitcode ("swap", "a");
5538 emitcode ("rl", "a");
5541 emitcode ("rr", "a");
5542 emitcode ("rr", "a");
5545 emitcode ("rr", "a");
5550 /*-----------------------------------------------------------------*/
5551 /* AccLsh - left shift accumulator by known count */
5552 /*-----------------------------------------------------------------*/
5554 AccLsh (int shCount)
5559 emitcode ("add", "a,acc");
5560 else if (shCount == 2)
5562 emitcode ("add", "a,acc");
5563 emitcode ("add", "a,acc");
5567 /* rotate left accumulator */
5569 /* and kill the lower order bits */
5570 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5575 /*-----------------------------------------------------------------*/
5576 /* AccRsh - right shift accumulator by known count */
5577 /*-----------------------------------------------------------------*/
5579 AccRsh (int shCount)
5586 emitcode ("rrc", "a");
5590 /* rotate right accumulator */
5591 AccRol (8 - shCount);
5592 /* and kill the higher order bits */
5593 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5598 /*-----------------------------------------------------------------*/
5599 /* AccSRsh - signed right shift accumulator by known count */
5600 /*-----------------------------------------------------------------*/
5602 AccSRsh (int shCount)
5609 emitcode ("mov", "c,acc.7");
5610 emitcode ("rrc", "a");
5612 else if (shCount == 2)
5614 emitcode ("mov", "c,acc.7");
5615 emitcode ("rrc", "a");
5616 emitcode ("mov", "c,acc.7");
5617 emitcode ("rrc", "a");
5621 tlbl = newiTempLabel (NULL);
5622 /* rotate right accumulator */
5623 AccRol (8 - shCount);
5624 /* and kill the higher order bits */
5625 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5626 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5627 emitcode ("orl", "a,#0x%02x",
5628 (unsigned char) ~SRMask[shCount]);
5629 emitcode ("", "%05d$:", tlbl->key + 100);
5634 /*-----------------------------------------------------------------*/
5635 /* shiftR1Left2Result - shift right one byte from left to result */
5636 /*-----------------------------------------------------------------*/
5638 shiftR1Left2Result (operand * left, int offl,
5639 operand * result, int offr,
5640 int shCount, int sign)
5642 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5643 /* shift right accumulator */
5648 aopPut (AOP (result), "a", offr);
5651 /*-----------------------------------------------------------------*/
5652 /* shiftL1Left2Result - shift left one byte from left to result */
5653 /*-----------------------------------------------------------------*/
5655 shiftL1Left2Result (operand * left, int offl,
5656 operand * result, int offr, int shCount)
5659 l = aopGet (AOP (left), offl, FALSE, FALSE);
5661 /* shift left accumulator */
5663 aopPut (AOP (result), "a", offr);
5666 /*-----------------------------------------------------------------*/
5667 /* movLeft2Result - move byte from left to result */
5668 /*-----------------------------------------------------------------*/
5670 movLeft2Result (operand * left, int offl,
5671 operand * result, int offr, int sign)
5674 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5676 l = aopGet (AOP (left), offl, FALSE, FALSE);
5678 if (*l == '@' && (IS_AOP_PREG (result)))
5680 emitcode ("mov", "a,%s", l);
5681 aopPut (AOP (result), "a", offr);
5686 aopPut (AOP (result), l, offr);
5689 /* MSB sign in acc.7 ! */
5690 if (getDataSize (left) == offl + 1)
5692 emitcode ("mov", "a,%s", l);
5693 aopPut (AOP (result), "a", offr);
5700 /*-----------------------------------------------------------------*/
5701 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5702 /*-----------------------------------------------------------------*/
5706 emitcode ("rrc", "a");
5707 emitcode ("xch", "a,%s", x);
5708 emitcode ("rrc", "a");
5709 emitcode ("xch", "a,%s", x);
5712 /*-----------------------------------------------------------------*/
5713 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5714 /*-----------------------------------------------------------------*/
5718 emitcode ("xch", "a,%s", x);
5719 emitcode ("rlc", "a");
5720 emitcode ("xch", "a,%s", x);
5721 emitcode ("rlc", "a");
5724 /*-----------------------------------------------------------------*/
5725 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5726 /*-----------------------------------------------------------------*/
5730 emitcode ("xch", "a,%s", x);
5731 emitcode ("add", "a,acc");
5732 emitcode ("xch", "a,%s", x);
5733 emitcode ("rlc", "a");
5736 /*-----------------------------------------------------------------*/
5737 /* AccAXLsh - left shift a:x by known count (0..7) */
5738 /*-----------------------------------------------------------------*/
5740 AccAXLsh (char *x, int shCount)
5755 case 5: // AAAAABBB:CCCCCDDD
5757 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5759 emitcode ("anl", "a,#0x%02x",
5760 SLMask[shCount]); // BBB00000:CCCCCDDD
5762 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5764 AccRol (shCount); // DDDCCCCC:BBB00000
5766 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5768 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5770 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5772 emitcode ("anl", "a,#0x%02x",
5773 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5775 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5777 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5780 case 6: // AAAAAABB:CCCCCCDD
5781 emitcode ("anl", "a,#0x%02x",
5782 SRMask[shCount]); // 000000BB:CCCCCCDD
5783 emitcode ("mov", "c,acc.0"); // c = B
5784 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5786 AccAXRrl1 (x); // BCCCCCCD:D000000B
5787 AccAXRrl1 (x); // BBCCCCCC:DD000000
5789 emitcode("rrc","a");
5790 emitcode("xch","a,%s", x);
5791 emitcode("rrc","a");
5792 emitcode("mov","c,acc.0"); //<< get correct bit
5793 emitcode("xch","a,%s", x);
5795 emitcode("rrc","a");
5796 emitcode("xch","a,%s", x);
5797 emitcode("rrc","a");
5798 emitcode("xch","a,%s", x);
5801 case 7: // a:x <<= 7
5803 emitcode ("anl", "a,#0x%02x",
5804 SRMask[shCount]); // 0000000B:CCCCCCCD
5806 emitcode ("mov", "c,acc.0"); // c = B
5808 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5810 AccAXRrl1 (x); // BCCCCCCC:D0000000
5818 /*-----------------------------------------------------------------*/
5819 /* AccAXRsh - right shift a:x known count (0..7) */
5820 /*-----------------------------------------------------------------*/
5822 AccAXRsh (char *x, int shCount)
5830 AccAXRrl1 (x); // 0->a:x
5835 AccAXRrl1 (x); // 0->a:x
5838 AccAXRrl1 (x); // 0->a:x
5843 case 5: // AAAAABBB:CCCCCDDD = a:x
5845 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5847 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5849 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5851 emitcode ("anl", "a,#0x%02x",
5852 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5854 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5856 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5858 emitcode ("anl", "a,#0x%02x",
5859 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5861 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5863 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5865 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5868 case 6: // AABBBBBB:CCDDDDDD
5870 emitcode ("mov", "c,acc.7");
5871 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5873 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5875 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5877 emitcode ("anl", "a,#0x%02x",
5878 SRMask[shCount]); // 000000AA:BBBBBBCC
5881 case 7: // ABBBBBBB:CDDDDDDD
5883 emitcode ("mov", "c,acc.7"); // c = A
5885 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5887 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5889 emitcode ("anl", "a,#0x%02x",
5890 SRMask[shCount]); // 0000000A:BBBBBBBC
5898 /*-----------------------------------------------------------------*/
5899 /* AccAXRshS - right shift signed a:x known count (0..7) */
5900 /*-----------------------------------------------------------------*/
5902 AccAXRshS (char *x, int shCount)
5910 emitcode ("mov", "c,acc.7");
5911 AccAXRrl1 (x); // s->a:x
5915 emitcode ("mov", "c,acc.7");
5916 AccAXRrl1 (x); // s->a:x
5918 emitcode ("mov", "c,acc.7");
5919 AccAXRrl1 (x); // s->a:x
5924 case 5: // AAAAABBB:CCCCCDDD = a:x
5926 tlbl = newiTempLabel (NULL);
5927 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5929 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5931 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5933 emitcode ("anl", "a,#0x%02x",
5934 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5936 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5938 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5940 emitcode ("anl", "a,#0x%02x",
5941 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5943 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5945 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5947 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5949 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5950 emitcode ("orl", "a,#0x%02x",
5951 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5953 emitcode ("", "%05d$:", tlbl->key + 100);
5954 break; // SSSSAAAA:BBBCCCCC
5956 case 6: // AABBBBBB:CCDDDDDD
5958 tlbl = newiTempLabel (NULL);
5959 emitcode ("mov", "c,acc.7");
5960 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5962 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5964 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5966 emitcode ("anl", "a,#0x%02x",
5967 SRMask[shCount]); // 000000AA:BBBBBBCC
5969 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5970 emitcode ("orl", "a,#0x%02x",
5971 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5973 emitcode ("", "%05d$:", tlbl->key + 100);
5975 case 7: // ABBBBBBB:CDDDDDDD
5977 tlbl = newiTempLabel (NULL);
5978 emitcode ("mov", "c,acc.7"); // c = A
5980 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5982 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5984 emitcode ("anl", "a,#0x%02x",
5985 SRMask[shCount]); // 0000000A:BBBBBBBC
5987 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5988 emitcode ("orl", "a,#0x%02x",
5989 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5991 emitcode ("", "%05d$:", tlbl->key + 100);
5998 /*-----------------------------------------------------------------*/
5999 /* shiftL2Left2Result - shift left two bytes from left to result */
6000 /*-----------------------------------------------------------------*/
6002 shiftL2Left2Result (operand * left, int offl,
6003 operand * result, int offr, int shCount)
6005 if (sameRegs (AOP (result), AOP (left)) &&
6006 ((offl + MSB16) == offr))
6008 /* don't crash result[offr] */
6009 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6010 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6014 movLeft2Result (left, offl, result, offr, 0);
6015 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6017 /* ax << shCount (x = lsb(result)) */
6018 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6019 aopPut (AOP (result), "a", offr + MSB16);
6023 /*-----------------------------------------------------------------*/
6024 /* shiftR2Left2Result - shift right two bytes from left to result */
6025 /*-----------------------------------------------------------------*/
6027 shiftR2Left2Result (operand * left, int offl,
6028 operand * result, int offr,
6029 int shCount, int sign)
6031 if (sameRegs (AOP (result), AOP (left)) &&
6032 ((offl + MSB16) == offr))
6034 /* don't crash result[offr] */
6035 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6036 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6040 movLeft2Result (left, offl, result, offr, 0);
6041 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6043 /* a:x >> shCount (x = lsb(result)) */
6045 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6047 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6048 if (getDataSize (result) > 1)
6049 aopPut (AOP (result), "a", offr + MSB16);
6052 /*-----------------------------------------------------------------*/
6053 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6054 /*-----------------------------------------------------------------*/
6056 shiftLLeftOrResult (operand * left, int offl,
6057 operand * result, int offr, int shCount)
6059 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6060 /* shift left accumulator */
6062 /* or with result */
6063 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6064 /* back to result */
6065 aopPut (AOP (result), "a", offr);
6068 /*-----------------------------------------------------------------*/
6069 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6070 /*-----------------------------------------------------------------*/
6072 shiftRLeftOrResult (operand * left, int offl,
6073 operand * result, int offr, int shCount)
6075 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6076 /* shift right accumulator */
6078 /* or with result */
6079 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6080 /* back to result */
6081 aopPut (AOP (result), "a", offr);
6084 /*-----------------------------------------------------------------*/
6085 /* genlshOne - left shift a one byte quantity by known count */
6086 /*-----------------------------------------------------------------*/
6088 genlshOne (operand * result, operand * left, int shCount)
6090 D(emitcode (";", "genlshOne"));
6092 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6095 /*-----------------------------------------------------------------*/
6096 /* genlshTwo - left shift two bytes by known amount != 0 */
6097 /*-----------------------------------------------------------------*/
6099 genlshTwo (operand * result, operand * left, int shCount)
6103 D(emitcode (";", "genlshTwo"));
6105 size = getDataSize (result);
6107 /* if shCount >= 8 */
6115 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6117 movLeft2Result (left, LSB, result, MSB16, 0);
6119 aopPut (AOP (result), zero, LSB);
6122 /* 1 <= shCount <= 7 */
6126 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6128 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6132 /*-----------------------------------------------------------------*/
6133 /* shiftLLong - shift left one long from left to result */
6134 /* offl = LSB or MSB16 */
6135 /*-----------------------------------------------------------------*/
6137 shiftLLong (operand * left, operand * result, int offr)
6140 int size = AOP_SIZE (result);
6142 if (size >= LSB + offr)
6144 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6146 emitcode ("add", "a,acc");
6147 if (sameRegs (AOP (left), AOP (result)) &&
6148 size >= MSB16 + offr && offr != LSB)
6149 emitcode ("xch", "a,%s",
6150 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6152 aopPut (AOP (result), "a", LSB + offr);
6155 if (size >= MSB16 + offr)
6157 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6159 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6162 emitcode ("rlc", "a");
6163 if (sameRegs (AOP (left), AOP (result)) &&
6164 size >= MSB24 + offr && offr != LSB)
6165 emitcode ("xch", "a,%s",
6166 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6168 aopPut (AOP (result), "a", MSB16 + offr);
6171 if (size >= MSB24 + offr)
6173 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6175 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6178 emitcode ("rlc", "a");
6179 if (sameRegs (AOP (left), AOP (result)) &&
6180 size >= MSB32 + offr && offr != LSB)
6181 emitcode ("xch", "a,%s",
6182 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6184 aopPut (AOP (result), "a", MSB24 + offr);
6187 if (size > MSB32 + offr)
6189 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6191 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6194 emitcode ("rlc", "a");
6195 aopPut (AOP (result), "a", MSB32 + offr);
6198 aopPut (AOP (result), zero, LSB);
6201 /*-----------------------------------------------------------------*/
6202 /* genlshFour - shift four byte by a known amount != 0 */
6203 /*-----------------------------------------------------------------*/
6205 genlshFour (operand * result, operand * left, int shCount)
6209 D(emitcode (";", "genlshFour"));
6211 size = AOP_SIZE (result);
6213 /* if shifting more that 3 bytes */
6218 /* lowest order of left goes to the highest
6219 order of the destination */
6220 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6222 movLeft2Result (left, LSB, result, MSB32, 0);
6223 aopPut (AOP (result), zero, LSB);
6224 aopPut (AOP (result), zero, MSB16);
6225 aopPut (AOP (result), zero, MSB24);
6229 /* more than two bytes */
6230 else if (shCount >= 16)
6232 /* lower order two bytes goes to higher order two bytes */
6234 /* if some more remaining */
6236 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6239 movLeft2Result (left, MSB16, result, MSB32, 0);
6240 movLeft2Result (left, LSB, result, MSB24, 0);
6242 aopPut (AOP (result), zero, MSB16);
6243 aopPut (AOP (result), zero, LSB);
6247 /* if more than 1 byte */
6248 else if (shCount >= 8)
6250 /* lower order three bytes goes to higher order three bytes */
6255 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6257 movLeft2Result (left, LSB, result, MSB16, 0);
6263 movLeft2Result (left, MSB24, result, MSB32, 0);
6264 movLeft2Result (left, MSB16, result, MSB24, 0);
6265 movLeft2Result (left, LSB, result, MSB16, 0);
6266 aopPut (AOP (result), zero, LSB);
6268 else if (shCount == 1)
6269 shiftLLong (left, result, MSB16);
6272 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6273 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6274 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6275 aopPut (AOP (result), zero, LSB);
6280 /* 1 <= shCount <= 7 */
6281 else if (shCount <= 2)
6283 shiftLLong (left, result, LSB);
6285 shiftLLong (result, result, LSB);
6287 /* 3 <= shCount <= 7, optimize */
6290 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6291 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6292 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6296 /*-----------------------------------------------------------------*/
6297 /* genLeftShiftLiteral - left shifting by known count */
6298 /*-----------------------------------------------------------------*/
6300 genLeftShiftLiteral (operand * left,
6305 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6308 D(emitcode (";", "genLeftShiftLiteral"));
6310 freeAsmop (right, NULL, ic, TRUE);
6312 aopOp (left, ic, FALSE);
6313 aopOp (result, ic, FALSE);
6315 size = getSize (operandType (result));
6318 emitcode ("; shift left ", "result %d, left %d", size,
6322 /* I suppose that the left size >= result size */
6327 movLeft2Result (left, size, result, size, 0);
6331 else if (shCount >= (size * 8))
6333 aopPut (AOP (result), zero, size);
6339 genlshOne (result, left, shCount);
6343 genlshTwo (result, left, shCount);
6347 genlshFour (result, left, shCount);
6350 fprintf(stderr, "*** ack! mystery literal shift!\n");
6354 freeAsmop (left, NULL, ic, TRUE);
6355 freeAsmop (result, NULL, ic, TRUE);
6358 /*-----------------------------------------------------------------*/
6359 /* genLeftShift - generates code for left shifting */
6360 /*-----------------------------------------------------------------*/
6362 genLeftShift (iCode * ic)
6364 operand *left, *right, *result;
6367 symbol *tlbl, *tlbl1;
6369 D(emitcode (";", "genLeftShift"));
6371 right = IC_RIGHT (ic);
6372 left = IC_LEFT (ic);
6373 result = IC_RESULT (ic);
6375 aopOp (right, ic, FALSE);
6377 /* if the shift count is known then do it
6378 as efficiently as possible */
6379 if (AOP_TYPE (right) == AOP_LIT)
6381 genLeftShiftLiteral (left, right, result, ic);
6385 /* shift count is unknown then we have to form
6386 a loop get the loop count in B : Note: we take
6387 only the lower order byte since shifting
6388 more that 32 bits make no sense anyway, ( the
6389 largest size of an object can be only 32 bits ) */
6391 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6392 emitcode ("inc", "b");
6393 freeAsmop (right, NULL, ic, TRUE);
6394 aopOp (left, ic, FALSE);
6395 aopOp (result, ic, FALSE);
6397 /* now move the left to the result if they are not the
6399 if (!sameRegs (AOP (left), AOP (result)) &&
6400 AOP_SIZE (result) > 1)
6403 size = AOP_SIZE (result);
6407 l = aopGet (AOP (left), offset, FALSE, TRUE);
6408 if (*l == '@' && (IS_AOP_PREG (result)))
6411 emitcode ("mov", "a,%s", l);
6412 aopPut (AOP (result), "a", offset);
6415 aopPut (AOP (result), l, offset);
6420 tlbl = newiTempLabel (NULL);
6421 size = AOP_SIZE (result);
6423 tlbl1 = newiTempLabel (NULL);
6425 /* if it is only one byte then */
6428 symbol *tlbl1 = newiTempLabel (NULL);
6430 l = aopGet (AOP (left), 0, FALSE, FALSE);
6432 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6433 emitcode ("", "%05d$:", tlbl->key + 100);
6434 emitcode ("add", "a,acc");
6435 emitcode ("", "%05d$:", tlbl1->key + 100);
6436 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6437 aopPut (AOP (result), "a", 0);
6441 reAdjustPreg (AOP (result));
6443 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6444 emitcode ("", "%05d$:", tlbl->key + 100);
6445 l = aopGet (AOP (result), offset, FALSE, FALSE);
6447 emitcode ("add", "a,acc");
6448 aopPut (AOP (result), "a", offset++);
6451 l = aopGet (AOP (result), offset, FALSE, FALSE);
6453 emitcode ("rlc", "a");
6454 aopPut (AOP (result), "a", offset++);
6456 reAdjustPreg (AOP (result));
6458 emitcode ("", "%05d$:", tlbl1->key + 100);
6459 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6461 freeAsmop (left, NULL, ic, TRUE);
6462 freeAsmop (result, NULL, ic, TRUE);
6465 /*-----------------------------------------------------------------*/
6466 /* genrshOne - right shift a one byte quantity by known count */
6467 /*-----------------------------------------------------------------*/
6469 genrshOne (operand * result, operand * left,
6470 int shCount, int sign)
6472 D(emitcode (";", "genrshOne"));
6474 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6477 /*-----------------------------------------------------------------*/
6478 /* genrshTwo - right shift two bytes by known amount != 0 */
6479 /*-----------------------------------------------------------------*/
6481 genrshTwo (operand * result, operand * left,
6482 int shCount, int sign)
6484 D(emitcode (";", "genrshTwo"));
6486 /* if shCount >= 8 */
6491 shiftR1Left2Result (left, MSB16, result, LSB,
6494 movLeft2Result (left, MSB16, result, LSB, sign);
6495 addSign (result, MSB16, sign);
6498 /* 1 <= shCount <= 7 */
6500 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6503 /*-----------------------------------------------------------------*/
6504 /* shiftRLong - shift right one long from left to result */
6505 /* offl = LSB or MSB16 */
6506 /*-----------------------------------------------------------------*/
6508 shiftRLong (operand * left, int offl,
6509 operand * result, int sign)
6511 int isSameRegs=sameRegs(AOP(left),AOP(result));
6513 if (isSameRegs && offl>1) {
6514 // we are in big trouble, but this shouldn't happen
6515 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6518 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6523 emitcode ("rlc", "a");
6524 emitcode ("subb", "a,acc");
6525 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6527 aopPut (AOP(result), zero, MSB32);
6532 emitcode ("clr", "c");
6534 emitcode ("mov", "c,acc.7");
6537 emitcode ("rrc", "a");
6539 if (isSameRegs && offl==MSB16) {
6540 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6542 aopPut (AOP (result), "a", MSB32);
6543 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6546 emitcode ("rrc", "a");
6547 if (isSameRegs && offl==1) {
6548 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6550 aopPut (AOP (result), "a", MSB24);
6551 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6553 emitcode ("rrc", "a");
6554 aopPut (AOP (result), "a", MSB16 - offl);
6558 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6559 emitcode ("rrc", "a");
6560 aopPut (AOP (result), "a", LSB);
6564 /*-----------------------------------------------------------------*/
6565 /* genrshFour - shift four byte by a known amount != 0 */
6566 /*-----------------------------------------------------------------*/
6568 genrshFour (operand * result, operand * left,
6569 int shCount, int sign)
6571 D(emitcode (";", "genrshFour"));
6573 /* if shifting more that 3 bytes */
6578 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6580 movLeft2Result (left, MSB32, result, LSB, sign);
6581 addSign (result, MSB16, sign);
6583 else if (shCount >= 16)
6587 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6590 movLeft2Result (left, MSB24, result, LSB, 0);
6591 movLeft2Result (left, MSB32, result, MSB16, sign);
6593 addSign (result, MSB24, sign);
6595 else if (shCount >= 8)
6599 shiftRLong (left, MSB16, result, sign);
6600 else if (shCount == 0)
6602 movLeft2Result (left, MSB16, result, LSB, 0);
6603 movLeft2Result (left, MSB24, result, MSB16, 0);
6604 movLeft2Result (left, MSB32, result, MSB24, sign);
6605 addSign (result, MSB32, sign);
6609 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6610 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6611 /* the last shift is signed */
6612 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6613 addSign (result, MSB32, sign);
6617 { /* 1 <= shCount <= 7 */
6620 shiftRLong (left, LSB, result, sign);
6622 shiftRLong (result, LSB, result, sign);
6626 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6627 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6628 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6633 /*-----------------------------------------------------------------*/
6634 /* genRightShiftLiteral - right shifting by known count */
6635 /*-----------------------------------------------------------------*/
6637 genRightShiftLiteral (operand * left,
6643 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6646 D(emitcode (";", "genRightShiftLiteral"));
6648 freeAsmop (right, NULL, ic, TRUE);
6650 aopOp (left, ic, FALSE);
6651 aopOp (result, ic, FALSE);
6654 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6658 size = getDataSize (left);
6659 /* test the LEFT size !!! */
6661 /* I suppose that the left size >= result size */
6664 size = getDataSize (result);
6666 movLeft2Result (left, size, result, size, 0);
6669 else if (shCount >= (size * 8))
6672 /* get sign in acc.7 */
6673 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6674 addSign (result, LSB, sign);
6681 genrshOne (result, left, shCount, sign);
6685 genrshTwo (result, left, shCount, sign);
6689 genrshFour (result, left, shCount, sign);
6695 freeAsmop (left, NULL, ic, TRUE);
6696 freeAsmop (result, NULL, ic, TRUE);
6700 /*-----------------------------------------------------------------*/
6701 /* genSignedRightShift - right shift of signed number */
6702 /*-----------------------------------------------------------------*/
6704 genSignedRightShift (iCode * ic)
6706 operand *right, *left, *result;
6709 symbol *tlbl, *tlbl1;
6711 D(emitcode (";", "genSignedRightShift"));
6713 /* we do it the hard way put the shift count in b
6714 and loop thru preserving the sign */
6716 right = IC_RIGHT (ic);
6717 left = IC_LEFT (ic);
6718 result = IC_RESULT (ic);
6720 aopOp (right, ic, FALSE);
6723 if (AOP_TYPE (right) == AOP_LIT)
6725 genRightShiftLiteral (left, right, result, ic, 1);
6728 /* shift count is unknown then we have to form
6729 a loop get the loop count in B : Note: we take
6730 only the lower order byte since shifting
6731 more that 32 bits make no sense anyway, ( the
6732 largest size of an object can be only 32 bits ) */
6734 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6735 emitcode ("inc", "b");
6736 freeAsmop (right, NULL, ic, TRUE);
6737 aopOp (left, ic, FALSE);
6738 aopOp (result, ic, FALSE);
6740 /* now move the left to the result if they are not the
6742 if (!sameRegs (AOP (left), AOP (result)) &&
6743 AOP_SIZE (result) > 1)
6746 size = AOP_SIZE (result);
6750 l = aopGet (AOP (left), offset, FALSE, TRUE);
6751 if (*l == '@' && IS_AOP_PREG (result))
6754 emitcode ("mov", "a,%s", l);
6755 aopPut (AOP (result), "a", offset);
6758 aopPut (AOP (result), l, offset);
6763 /* mov the highest order bit to OVR */
6764 tlbl = newiTempLabel (NULL);
6765 tlbl1 = newiTempLabel (NULL);
6767 size = AOP_SIZE (result);
6769 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6770 emitcode ("rlc", "a");
6771 emitcode ("mov", "ov,c");
6772 /* if it is only one byte then */
6775 l = aopGet (AOP (left), 0, FALSE, FALSE);
6777 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6778 emitcode ("", "%05d$:", tlbl->key + 100);
6779 emitcode ("mov", "c,ov");
6780 emitcode ("rrc", "a");
6781 emitcode ("", "%05d$:", tlbl1->key + 100);
6782 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6783 aopPut (AOP (result), "a", 0);
6787 reAdjustPreg (AOP (result));
6788 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6789 emitcode ("", "%05d$:", tlbl->key + 100);
6790 emitcode ("mov", "c,ov");
6793 l = aopGet (AOP (result), offset, FALSE, FALSE);
6795 emitcode ("rrc", "a");
6796 aopPut (AOP (result), "a", offset--);
6798 reAdjustPreg (AOP (result));
6799 emitcode ("", "%05d$:", tlbl1->key + 100);
6800 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6803 freeAsmop (left, NULL, ic, TRUE);
6804 freeAsmop (result, NULL, ic, TRUE);
6807 /*-----------------------------------------------------------------*/
6808 /* genRightShift - generate code for right shifting */
6809 /*-----------------------------------------------------------------*/
6811 genRightShift (iCode * ic)
6813 operand *right, *left, *result;
6817 symbol *tlbl, *tlbl1;
6819 D(emitcode (";", "genRightShift"));
6821 /* if signed then we do it the hard way preserve the
6822 sign bit moving it inwards */
6823 retype = getSpec (operandType (IC_RESULT (ic)));
6825 if (!SPEC_USIGN (retype))
6827 genSignedRightShift (ic);
6831 /* signed & unsigned types are treated the same : i.e. the
6832 signed is NOT propagated inwards : quoting from the
6833 ANSI - standard : "for E1 >> E2, is equivalent to division
6834 by 2**E2 if unsigned or if it has a non-negative value,
6835 otherwise the result is implementation defined ", MY definition
6836 is that the sign does not get propagated */
6838 right = IC_RIGHT (ic);
6839 left = IC_LEFT (ic);
6840 result = IC_RESULT (ic);
6842 aopOp (right, ic, FALSE);
6844 /* if the shift count is known then do it
6845 as efficiently as possible */
6846 if (AOP_TYPE (right) == AOP_LIT)
6848 genRightShiftLiteral (left, right, result, ic, 0);
6852 /* shift count is unknown then we have to form
6853 a loop get the loop count in B : Note: we take
6854 only the lower order byte since shifting
6855 more that 32 bits make no sense anyway, ( the
6856 largest size of an object can be only 32 bits ) */
6858 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6859 emitcode ("inc", "b");
6860 freeAsmop (right, NULL, ic, TRUE);
6861 aopOp (left, ic, FALSE);
6862 aopOp (result, ic, FALSE);
6864 /* now move the left to the result if they are not the
6866 if (!sameRegs (AOP (left), AOP (result)) &&
6867 AOP_SIZE (result) > 1)
6870 size = AOP_SIZE (result);
6874 l = aopGet (AOP (left), offset, FALSE, TRUE);
6875 if (*l == '@' && IS_AOP_PREG (result))
6878 emitcode ("mov", "a,%s", l);
6879 aopPut (AOP (result), "a", offset);
6882 aopPut (AOP (result), l, offset);
6887 tlbl = newiTempLabel (NULL);
6888 tlbl1 = newiTempLabel (NULL);
6889 size = AOP_SIZE (result);
6892 /* if it is only one byte then */
6895 l = aopGet (AOP (left), 0, FALSE, FALSE);
6897 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6898 emitcode ("", "%05d$:", tlbl->key + 100);
6900 emitcode ("rrc", "a");
6901 emitcode ("", "%05d$:", tlbl1->key + 100);
6902 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6903 aopPut (AOP (result), "a", 0);
6907 reAdjustPreg (AOP (result));
6908 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6909 emitcode ("", "%05d$:", tlbl->key + 100);
6913 l = aopGet (AOP (result), offset, FALSE, FALSE);
6915 emitcode ("rrc", "a");
6916 aopPut (AOP (result), "a", offset--);
6918 reAdjustPreg (AOP (result));
6920 emitcode ("", "%05d$:", tlbl1->key + 100);
6921 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6924 freeAsmop (left, NULL, ic, TRUE);
6925 freeAsmop (result, NULL, ic, TRUE);
6928 /*-----------------------------------------------------------------*/
6929 /* genUnpackBits - generates code for unpacking bits */
6930 /*-----------------------------------------------------------------*/
6932 genUnpackBits (operand * result, char *rname, int ptype)
6940 D(emitcode (";", "genUnpackBits"));
6942 etype = getSpec (operandType (result));
6943 rsize = getSize (operandType (result));
6944 /* read the first byte */
6950 emitcode ("mov", "a,@%s", rname);
6954 emitcode ("movx", "a,@%s", rname);
6958 emitcode ("movx", "a,@dptr");
6962 emitcode ("clr", "a");
6963 emitcode ("movc", "a,@a+dptr");
6967 emitcode ("lcall", "__gptrget");
6971 rlen = SPEC_BLEN (etype);
6973 /* if we have bitdisplacement then it fits */
6974 /* into this byte completely or if length is */
6975 /* less than a byte */
6976 if ((shCnt = SPEC_BSTR (etype)) ||
6977 (SPEC_BLEN (etype) <= 8))
6980 /* shift right acc */
6983 emitcode ("anl", "a,#0x%02x",
6984 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6985 aopPut (AOP (result), "a", offset++);
6989 /* bit field did not fit in a byte */
6990 aopPut (AOP (result), "a", offset++);
6999 emitcode ("inc", "%s", rname);
7000 emitcode ("mov", "a,@%s", rname);
7004 emitcode ("inc", "%s", rname);
7005 emitcode ("movx", "a,@%s", rname);
7009 emitcode ("inc", "dptr");
7010 emitcode ("movx", "a,@dptr");
7014 emitcode ("clr", "a");
7015 emitcode ("inc", "dptr");
7016 emitcode ("movc", "a,@a+dptr");
7020 emitcode ("inc", "dptr");
7021 emitcode ("lcall", "__gptrget");
7026 /* if we are done */
7030 aopPut (AOP (result), "a", offset++);
7036 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7038 aopPut (AOP (result), "a", offset++);
7046 aopPut (AOP (result), zero, offset++);
7052 /*-----------------------------------------------------------------*/
7053 /* genDataPointerGet - generates code when ptr offset is known */
7054 /*-----------------------------------------------------------------*/
7056 genDataPointerGet (operand * left,
7062 int size, offset = 0;
7064 D(emitcode (";", "genDataPointerGet"));
7066 aopOp (result, ic, TRUE);
7068 /* get the string representation of the name */
7069 l = aopGet (AOP (left), 0, FALSE, TRUE);
7070 size = AOP_SIZE (result);
7074 sprintf (buffer, "(%s + %d)", l + 1, offset);
7076 sprintf (buffer, "%s", l + 1);
7077 aopPut (AOP (result), buffer, offset++);
7080 freeAsmop (left, NULL, ic, TRUE);
7081 freeAsmop (result, NULL, ic, TRUE);
7084 /*-----------------------------------------------------------------*/
7085 /* genNearPointerGet - emitcode for near pointer fetch */
7086 /*-----------------------------------------------------------------*/
7088 genNearPointerGet (operand * left,
7096 sym_link *rtype, *retype;
7097 sym_link *ltype = operandType (left);
7100 D(emitcode (";", "genNearPointerGet"));
7102 rtype = operandType (result);
7103 retype = getSpec (rtype);
7105 aopOp (left, ic, FALSE);
7107 /* if left is rematerialisable and
7108 result is not bit variable type and
7109 the left is pointer to data space i.e
7110 lower 128 bytes of space */
7111 if (AOP_TYPE (left) == AOP_IMMD &&
7112 !IS_BITVAR (retype) &&
7113 DCL_TYPE (ltype) == POINTER)
7115 genDataPointerGet (left, result, ic);
7119 /* if the value is already in a pointer register
7120 then don't need anything more */
7121 if (!AOP_INPREG (AOP (left)))
7123 /* otherwise get a free pointer register */
7125 preg = getFreePtr (ic, &aop, FALSE);
7126 emitcode ("mov", "%s,%s",
7128 aopGet (AOP (left), 0, FALSE, TRUE));
7132 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7134 //aopOp (result, ic, FALSE);
7135 aopOp (result, ic, result?TRUE:FALSE);
7137 /* if bitfield then unpack the bits */
7138 if (IS_BITVAR (retype))
7139 genUnpackBits (result, rname, POINTER);
7142 /* we have can just get the values */
7143 int size = AOP_SIZE (result);
7148 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7151 emitcode ("mov", "a,@%s", rname);
7152 aopPut (AOP (result), "a", offset);
7156 sprintf (buffer, "@%s", rname);
7157 aopPut (AOP (result), buffer, offset);
7161 emitcode ("inc", "%s", rname);
7165 /* now some housekeeping stuff */
7166 if (aop) /* we had to allocate for this iCode */
7168 if (pi) { /* post increment present */
7169 aopPut(AOP ( left ),rname,0);
7171 freeAsmop (NULL, aop, ic, TRUE);
7175 /* we did not allocate which means left
7176 already in a pointer register, then
7177 if size > 0 && this could be used again
7178 we have to point it back to where it
7180 if ((AOP_SIZE (result) > 1 &&
7181 !OP_SYMBOL (left)->remat &&
7182 (OP_SYMBOL (left)->liveTo > ic->seq ||
7186 int size = AOP_SIZE (result) - 1;
7188 emitcode ("dec", "%s", rname);
7193 freeAsmop (left, NULL, ic, TRUE);
7194 freeAsmop (result, NULL, ic, TRUE);
7195 if (pi) pi->generated = 1;
7198 /*-----------------------------------------------------------------*/
7199 /* genPagedPointerGet - emitcode for paged pointer fetch */
7200 /*-----------------------------------------------------------------*/
7202 genPagedPointerGet (operand * left,
7210 sym_link *rtype, *retype;
7212 D(emitcode (";", "genPagedPointerGet"));
7214 rtype = operandType (result);
7215 retype = getSpec (rtype);
7217 aopOp (left, ic, FALSE);
7219 /* if the value is already in a pointer register
7220 then don't need anything more */
7221 if (!AOP_INPREG (AOP (left)))
7223 /* otherwise get a free pointer register */
7225 preg = getFreePtr (ic, &aop, FALSE);
7226 emitcode ("mov", "%s,%s",
7228 aopGet (AOP (left), 0, FALSE, TRUE));
7232 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7234 aopOp (result, ic, FALSE);
7236 /* if bitfield then unpack the bits */
7237 if (IS_BITVAR (retype))
7238 genUnpackBits (result, rname, PPOINTER);
7241 /* we have can just get the values */
7242 int size = AOP_SIZE (result);
7248 emitcode ("movx", "a,@%s", rname);
7249 aopPut (AOP (result), "a", offset);
7254 emitcode ("inc", "%s", rname);
7258 /* now some housekeeping stuff */
7259 if (aop) /* we had to allocate for this iCode */
7261 if (pi) aopPut ( AOP (left), rname, 0);
7262 freeAsmop (NULL, aop, ic, TRUE);
7266 /* we did not allocate which means left
7267 already in a pointer register, then
7268 if size > 0 && this could be used again
7269 we have to point it back to where it
7271 if ((AOP_SIZE (result) > 1 &&
7272 !OP_SYMBOL (left)->remat &&
7273 (OP_SYMBOL (left)->liveTo > ic->seq ||
7277 int size = AOP_SIZE (result) - 1;
7279 emitcode ("dec", "%s", rname);
7284 freeAsmop (left, NULL, ic, TRUE);
7285 freeAsmop (result, NULL, ic, TRUE);
7286 if (pi) pi->generated = 1;
7290 /*-----------------------------------------------------------------*/
7291 /* genFarPointerGet - gget value from far space */
7292 /*-----------------------------------------------------------------*/
7294 genFarPointerGet (operand * left,
7295 operand * result, iCode * ic, iCode * pi)
7298 sym_link *retype = getSpec (operandType (result));
7300 D(emitcode (";", "genFarPointerGet"));
7302 aopOp (left, ic, FALSE);
7304 /* if the operand is already in dptr
7305 then we do nothing else we move the value to dptr */
7306 if (AOP_TYPE (left) != AOP_STR)
7308 /* if this is remateriazable */
7309 if (AOP_TYPE (left) == AOP_IMMD)
7310 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7312 { /* we need to get it byte by byte */
7313 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7314 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7317 /* so dptr know contains the address */
7318 aopOp (result, ic, FALSE);
7320 /* if bit then unpack */
7321 if (IS_BITVAR (retype))
7322 genUnpackBits (result, "dptr", FPOINTER);
7325 size = AOP_SIZE (result);
7330 emitcode ("movx", "a,@dptr");
7331 aopPut (AOP (result), "a", offset++);
7333 emitcode ("inc", "dptr");
7337 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7338 aopPut ( AOP (left), "dpl", 0);
7339 aopPut ( AOP (left), "dph", 1);
7342 freeAsmop (left, NULL, ic, TRUE);
7343 freeAsmop (result, NULL, ic, TRUE);
7346 /*-----------------------------------------------------------------*/
7347 /* genCodePointerGet - gget value from code space */
7348 /*-----------------------------------------------------------------*/
7350 genCodePointerGet (operand * left,
7351 operand * result, iCode * ic, iCode *pi)
7354 sym_link *retype = getSpec (operandType (result));
7356 D(emitcode (";", "genCodePointerGet"));
7358 aopOp (left, ic, FALSE);
7360 /* if the operand is already in dptr
7361 then we do nothing else we move the value to dptr */
7362 if (AOP_TYPE (left) != AOP_STR)
7364 /* if this is remateriazable */
7365 if (AOP_TYPE (left) == AOP_IMMD)
7366 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7368 { /* we need to get it byte by byte */
7369 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7370 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7373 /* so dptr know contains the address */
7374 aopOp (result, ic, FALSE);
7376 /* if bit then unpack */
7377 if (IS_BITVAR (retype))
7378 genUnpackBits (result, "dptr", CPOINTER);
7381 size = AOP_SIZE (result);
7386 emitcode ("clr", "a");
7387 emitcode ("movc", "a,@a+dptr");
7388 aopPut (AOP (result), "a", offset++);
7390 emitcode ("inc", "dptr");
7394 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7395 aopPut ( AOP (left), "dpl", 0);
7396 aopPut ( AOP (left), "dph", 1);
7399 freeAsmop (left, NULL, ic, TRUE);
7400 freeAsmop (result, NULL, ic, TRUE);
7403 /*-----------------------------------------------------------------*/
7404 /* genGenPointerGet - gget value from generic pointer space */
7405 /*-----------------------------------------------------------------*/
7407 genGenPointerGet (operand * left,
7408 operand * result, iCode * ic, iCode *pi)
7411 sym_link *retype = getSpec (operandType (result));
7413 D(emitcode (";", "genGenPointerGet"));
7415 aopOp (left, ic, FALSE);
7417 /* if the operand is already in dptr
7418 then we do nothing else we move the value to dptr */
7419 if (AOP_TYPE (left) != AOP_STR)
7421 /* if this is remateriazable */
7422 if (AOP_TYPE (left) == AOP_IMMD)
7424 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7425 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7426 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7428 emitcode ("mov", "b,#%d", pointerCode (retype));
7431 { /* we need to get it byte by byte */
7432 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7433 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7434 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7437 /* so dptr know contains the address */
7438 aopOp (result, ic, FALSE);
7440 /* if bit then unpack */
7441 if (IS_BITVAR (retype))
7442 genUnpackBits (result, "dptr", GPOINTER);
7445 size = AOP_SIZE (result);
7450 emitcode ("lcall", "__gptrget");
7451 aopPut (AOP (result), "a", offset++);
7453 emitcode ("inc", "dptr");
7457 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7458 aopPut ( AOP (left), "dpl", 0);
7459 aopPut ( AOP (left), "dph", 1);
7460 aopPut ( AOP (left), "b", 2);
7463 freeAsmop (left, NULL, ic, TRUE);
7464 freeAsmop (result, NULL, ic, TRUE);
7467 /*-----------------------------------------------------------------*/
7468 /* genPointerGet - generate code for pointer get */
7469 /*-----------------------------------------------------------------*/
7471 genPointerGet (iCode * ic, iCode *pi)
7473 operand *left, *result;
7474 sym_link *type, *etype;
7477 D(emitcode (";", "genPointerGet"));
7479 left = IC_LEFT (ic);
7480 result = IC_RESULT (ic);
7482 /* depending on the type of pointer we need to
7483 move it to the correct pointer register */
7484 type = operandType (left);
7485 etype = getSpec (type);
7486 /* if left is of type of pointer then it is simple */
7487 if (IS_PTR (type) && !IS_FUNC (type->next))
7488 p_type = DCL_TYPE (type);
7491 /* we have to go by the storage class */
7492 p_type = PTR_TYPE (SPEC_OCLS (etype));
7495 /* special case when cast remat */
7496 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7497 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7498 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7499 type = type = operandType (left);
7500 p_type = DCL_TYPE (type);
7502 /* now that we have the pointer type we assign
7503 the pointer values */
7509 genNearPointerGet (left, result, ic, pi);
7513 genPagedPointerGet (left, result, ic, pi);
7517 genFarPointerGet (left, result, ic, pi);
7521 genCodePointerGet (left, result, ic, pi);
7525 genGenPointerGet (left, result, ic, pi);
7531 /*-----------------------------------------------------------------*/
7532 /* genPackBits - generates code for packed bit storage */
7533 /*-----------------------------------------------------------------*/
7535 genPackBits (sym_link * etype,
7537 char *rname, int p_type)
7545 D(emitcode (";", "genPackBits"));
7547 blen = SPEC_BLEN (etype);
7548 bstr = SPEC_BSTR (etype);
7550 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7553 /* if the bit lenth is less than or */
7554 /* it exactly fits a byte then */
7555 if (SPEC_BLEN (etype) <= 8)
7557 shCount = SPEC_BSTR (etype);
7559 /* shift left acc */
7562 if (SPEC_BLEN (etype) < 8)
7563 { /* if smaller than a byte */
7569 emitcode ("mov", "b,a");
7570 emitcode ("mov", "a,@%s", rname);
7574 emitcode ("mov", "b,a");
7575 emitcode ("movx", "a,@dptr");
7579 emitcode ("push", "b");
7580 emitcode ("push", "acc");
7581 emitcode ("lcall", "__gptrget");
7582 emitcode ("pop", "b");
7586 emitcode ("anl", "a,#0x%02x", (unsigned char)
7587 ((unsigned char) (0xFF << (blen + bstr)) |
7588 (unsigned char) (0xFF >> (8 - bstr))));
7589 emitcode ("orl", "a,b");
7590 if (p_type == GPOINTER)
7591 emitcode ("pop", "b");
7598 emitcode ("mov", "@%s,a", rname);
7602 emitcode ("movx", "@dptr,a");
7606 emitcode ("lcall", "__gptrput");
7611 if (SPEC_BLEN (etype) <= 8)
7614 emitcode ("inc", "%s", rname);
7615 rLen = SPEC_BLEN (etype);
7617 /* now generate for lengths greater than one byte */
7621 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7633 emitcode ("mov", "@%s,a", rname);
7636 emitcode ("mov", "@%s,%s", rname, l);
7641 emitcode ("movx", "@dptr,a");
7646 emitcode ("lcall", "__gptrput");
7649 emitcode ("inc", "%s", rname);
7654 /* last last was not complete */
7657 /* save the byte & read byte */
7661 emitcode ("mov", "b,a");
7662 emitcode ("mov", "a,@%s", rname);
7666 emitcode ("mov", "b,a");
7667 emitcode ("movx", "a,@dptr");
7671 emitcode ("push", "b");
7672 emitcode ("push", "acc");
7673 emitcode ("lcall", "__gptrget");
7674 emitcode ("pop", "b");
7678 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7679 emitcode ("orl", "a,b");
7682 if (p_type == GPOINTER)
7683 emitcode ("pop", "b");
7689 emitcode ("mov", "@%s,a", rname);
7693 emitcode ("movx", "@dptr,a");
7697 emitcode ("lcall", "__gptrput");
7701 /*-----------------------------------------------------------------*/
7702 /* genDataPointerSet - remat pointer to data space */
7703 /*-----------------------------------------------------------------*/
7705 genDataPointerSet (operand * right,
7709 int size, offset = 0;
7710 char *l, buffer[256];
7712 D(emitcode (";", "genDataPointerSet"));
7714 aopOp (right, ic, FALSE);
7716 l = aopGet (AOP (result), 0, FALSE, TRUE);
7717 size = AOP_SIZE (right);
7721 sprintf (buffer, "(%s + %d)", l + 1, offset);
7723 sprintf (buffer, "%s", l + 1);
7724 emitcode ("mov", "%s,%s", buffer,
7725 aopGet (AOP (right), offset++, FALSE, FALSE));
7728 freeAsmop (right, NULL, ic, TRUE);
7729 freeAsmop (result, NULL, ic, TRUE);
7732 /*-----------------------------------------------------------------*/
7733 /* genNearPointerSet - emitcode for near pointer put */
7734 /*-----------------------------------------------------------------*/
7736 genNearPointerSet (operand * right,
7744 sym_link *retype, *letype;
7745 sym_link *ptype = operandType (result);
7747 D(emitcode (";", "genNearPointerSet"));
7749 retype = getSpec (operandType (right));
7750 letype = getSpec (ptype);
7751 aopOp (result, ic, FALSE);
7753 /* if the result is rematerializable &
7754 in data space & not a bit variable */
7755 if (AOP_TYPE (result) == AOP_IMMD &&
7756 DCL_TYPE (ptype) == POINTER &&
7757 !IS_BITVAR (retype) &&
7758 !IS_BITVAR (letype))
7760 genDataPointerSet (right, result, ic);
7764 /* if the value is already in a pointer register
7765 then don't need anything more */
7766 if (!AOP_INPREG (AOP (result)))
7769 //AOP_TYPE (result) == AOP_STK
7773 // Aha, it is a pointer, just in disguise.
7774 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7777 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7778 __FILE__, __LINE__);
7783 rname++; // skip the '@'.
7788 /* otherwise get a free pointer register */
7790 preg = getFreePtr (ic, &aop, FALSE);
7791 emitcode ("mov", "%s,%s",
7793 aopGet (AOP (result), 0, FALSE, TRUE));
7799 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7802 aopOp (right, ic, FALSE);
7804 /* if bitfield then unpack the bits */
7805 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7806 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7809 /* we have can just get the values */
7810 int size = AOP_SIZE (right);
7815 l = aopGet (AOP (right), offset, FALSE, TRUE);
7819 emitcode ("mov", "@%s,a", rname);
7822 emitcode ("mov", "@%s,%s", rname, l);
7824 emitcode ("inc", "%s", rname);
7829 /* now some housekeeping stuff */
7830 if (aop) /* we had to allocate for this iCode */
7832 if (pi) aopPut (AOP (result),rname,0);
7833 freeAsmop (NULL, aop, ic, TRUE);
7837 /* we did not allocate which means left
7838 already in a pointer register, then
7839 if size > 0 && this could be used again
7840 we have to point it back to where it
7842 if ((AOP_SIZE (right) > 1 &&
7843 !OP_SYMBOL (result)->remat &&
7844 (OP_SYMBOL (result)->liveTo > ic->seq ||
7848 int size = AOP_SIZE (right) - 1;
7850 emitcode ("dec", "%s", rname);
7855 if (pi) pi->generated = 1;
7856 freeAsmop (result, NULL, ic, TRUE);
7857 freeAsmop (right, NULL, ic, TRUE);
7860 /*-----------------------------------------------------------------*/
7861 /* genPagedPointerSet - emitcode for Paged pointer put */
7862 /*-----------------------------------------------------------------*/
7864 genPagedPointerSet (operand * right,
7872 sym_link *retype, *letype;
7874 D(emitcode (";", "genPagedPointerSet"));
7876 retype = getSpec (operandType (right));
7877 letype = getSpec (operandType (result));
7879 aopOp (result, ic, FALSE);
7881 /* if the value is already in a pointer register
7882 then don't need anything more */
7883 if (!AOP_INPREG (AOP (result)))
7885 /* otherwise get a free pointer register */
7887 preg = getFreePtr (ic, &aop, FALSE);
7888 emitcode ("mov", "%s,%s",
7890 aopGet (AOP (result), 0, FALSE, TRUE));
7894 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7896 aopOp (right, ic, FALSE);
7898 /* if bitfield then unpack the bits */
7899 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7900 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7903 /* we have can just get the values */
7904 int size = AOP_SIZE (right);
7909 l = aopGet (AOP (right), offset, FALSE, TRUE);
7912 emitcode ("movx", "@%s,a", rname);
7915 emitcode ("inc", "%s", rname);
7921 /* now some housekeeping stuff */
7922 if (aop) /* we had to allocate for this iCode */
7924 if (pi) aopPut (AOP (result),rname,0);
7925 freeAsmop (NULL, aop, ic, TRUE);
7929 /* we did not allocate which means left
7930 already in a pointer register, then
7931 if size > 0 && this could be used again
7932 we have to point it back to where it
7934 if (AOP_SIZE (right) > 1 &&
7935 !OP_SYMBOL (result)->remat &&
7936 (OP_SYMBOL (result)->liveTo > ic->seq ||
7939 int size = AOP_SIZE (right) - 1;
7941 emitcode ("dec", "%s", rname);
7946 if (pi) pi->generated = 1;
7947 freeAsmop (result, NULL, ic, TRUE);
7948 freeAsmop (right, NULL, ic, TRUE);
7953 /*-----------------------------------------------------------------*/
7954 /* genFarPointerSet - set value from far space */
7955 /*-----------------------------------------------------------------*/
7957 genFarPointerSet (operand * right,
7958 operand * result, iCode * ic, iCode * pi)
7961 sym_link *retype = getSpec (operandType (right));
7962 sym_link *letype = getSpec (operandType (result));
7964 D(emitcode (";", "genFarPointerSet"));
7966 aopOp (result, ic, FALSE);
7968 /* if the operand is already in dptr
7969 then we do nothing else we move the value to dptr */
7970 if (AOP_TYPE (result) != AOP_STR)
7972 /* if this is remateriazable */
7973 if (AOP_TYPE (result) == AOP_IMMD)
7974 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7976 { /* we need to get it byte by byte */
7977 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7978 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7981 /* so dptr know contains the address */
7982 aopOp (right, ic, FALSE);
7984 /* if bit then unpack */
7985 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7986 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7989 size = AOP_SIZE (right);
7994 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7996 emitcode ("movx", "@dptr,a");
7998 emitcode ("inc", "dptr");
8001 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8002 aopPut (AOP(result),"dpl",0);
8003 aopPut (AOP(result),"dph",1);
8006 freeAsmop (result, NULL, ic, TRUE);
8007 freeAsmop (right, NULL, ic, TRUE);
8010 /*-----------------------------------------------------------------*/
8011 /* genGenPointerSet - set value from generic pointer space */
8012 /*-----------------------------------------------------------------*/
8014 genGenPointerSet (operand * right,
8015 operand * result, iCode * ic, iCode * pi)
8018 sym_link *retype = getSpec (operandType (right));
8019 sym_link *letype = getSpec (operandType (result));
8021 D(emitcode (";", "genGenPointerSet"));
8023 aopOp (result, ic, FALSE);
8025 /* if the operand is already in dptr
8026 then we do nothing else we move the value to dptr */
8027 if (AOP_TYPE (result) != AOP_STR)
8029 /* if this is remateriazable */
8030 if (AOP_TYPE (result) == AOP_IMMD)
8032 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8033 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8034 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8036 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8039 { /* we need to get it byte by byte */
8040 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8041 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8042 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8045 /* so dptr know contains the address */
8046 aopOp (right, ic, FALSE);
8048 /* if bit then unpack */
8049 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8050 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8053 size = AOP_SIZE (right);
8058 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8060 emitcode ("lcall", "__gptrput");
8062 emitcode ("inc", "dptr");
8066 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8067 aopPut (AOP(result),"dpl",0);
8068 aopPut (AOP(result),"dph",1);
8069 aopPut (AOP(result),"b",2);
8072 freeAsmop (result, NULL, ic, TRUE);
8073 freeAsmop (right, NULL, ic, TRUE);
8076 /*-----------------------------------------------------------------*/
8077 /* genPointerSet - stores the value into a pointer location */
8078 /*-----------------------------------------------------------------*/
8080 genPointerSet (iCode * ic, iCode *pi)
8082 operand *right, *result;
8083 sym_link *type, *etype;
8086 D(emitcode (";", "genPointerSet"));
8088 right = IC_RIGHT (ic);
8089 result = IC_RESULT (ic);
8091 /* depending on the type of pointer we need to
8092 move it to the correct pointer register */
8093 type = operandType (result);
8094 etype = getSpec (type);
8095 /* if left is of type of pointer then it is simple */
8096 if (IS_PTR (type) && !IS_FUNC (type->next))
8098 p_type = DCL_TYPE (type);
8102 /* we have to go by the storage class */
8103 p_type = PTR_TYPE (SPEC_OCLS (etype));
8106 /* special case when cast remat */
8107 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8108 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8109 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8110 type = type = operandType (result);
8111 p_type = DCL_TYPE (type);
8113 /* now that we have the pointer type we assign
8114 the pointer values */
8120 genNearPointerSet (right, result, ic, pi);
8124 genPagedPointerSet (right, result, ic, pi);
8128 genFarPointerSet (right, result, ic, pi);
8132 genGenPointerSet (right, result, ic, pi);
8138 /*-----------------------------------------------------------------*/
8139 /* genIfx - generate code for Ifx statement */
8140 /*-----------------------------------------------------------------*/
8142 genIfx (iCode * ic, iCode * popIc)
8144 operand *cond = IC_COND (ic);
8147 D(emitcode (";", "genIfx"));
8149 aopOp (cond, ic, FALSE);
8151 /* get the value into acc */
8152 if (AOP_TYPE (cond) != AOP_CRY)
8156 /* the result is now in the accumulator */
8157 freeAsmop (cond, NULL, ic, TRUE);
8159 /* if there was something to be popped then do it */
8163 /* if the condition is a bit variable */
8164 if (isbit && IS_ITEMP (cond) &&
8166 genIfxJump (ic, SPIL_LOC (cond)->rname);
8167 else if (isbit && !IS_ITEMP (cond))
8168 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8170 genIfxJump (ic, "a");
8175 /*-----------------------------------------------------------------*/
8176 /* genAddrOf - generates code for address of */
8177 /*-----------------------------------------------------------------*/
8179 genAddrOf (iCode * ic)
8181 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8184 D(emitcode (";", "genAddrOf"));
8186 aopOp (IC_RESULT (ic), ic, FALSE);
8188 /* if the operand is on the stack then we
8189 need to get the stack offset of this
8193 /* if it has an offset then we need to compute
8197 emitcode ("mov", "a,_bp");
8198 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8199 ((char) (sym->stack - _G.nRegsSaved)) :
8200 ((char) sym->stack)) & 0xff);
8201 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8205 /* we can just move _bp */
8206 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8208 /* fill the result with zero */
8209 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8214 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8220 /* object not on stack then we need the name */
8221 size = AOP_SIZE (IC_RESULT (ic));
8226 char s[SDCC_NAME_MAX];
8228 sprintf (s, "#(%s >> %d)",
8232 sprintf (s, "#%s", sym->rname);
8233 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8237 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8241 /*-----------------------------------------------------------------*/
8242 /* genFarFarAssign - assignment when both are in far space */
8243 /*-----------------------------------------------------------------*/
8245 genFarFarAssign (operand * result, operand * right, iCode * ic)
8247 int size = AOP_SIZE (right);
8251 D(emitcode (";", "genFarFarAssign"));
8253 /* first push the right side on to the stack */
8256 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8258 emitcode ("push", "acc");
8261 freeAsmop (right, NULL, ic, FALSE);
8262 /* now assign DPTR to result */
8263 aopOp (result, ic, FALSE);
8264 size = AOP_SIZE (result);
8267 emitcode ("pop", "acc");
8268 aopPut (AOP (result), "a", --offset);
8270 freeAsmop (result, NULL, ic, FALSE);
8274 /*-----------------------------------------------------------------*/
8275 /* genAssign - generate code for assignment */
8276 /*-----------------------------------------------------------------*/
8278 genAssign (iCode * ic)
8280 operand *result, *right;
8282 unsigned long lit = 0L;
8284 D(emitcode(";","genAssign"));
8286 result = IC_RESULT (ic);
8287 right = IC_RIGHT (ic);
8289 /* if they are the same */
8290 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8293 aopOp (right, ic, FALSE);
8295 /* special case both in far space */
8296 if (AOP_TYPE (right) == AOP_DPTR &&
8297 IS_TRUE_SYMOP (result) &&
8298 isOperandInFarSpace (result))
8301 genFarFarAssign (result, right, ic);
8305 aopOp (result, ic, TRUE);
8307 /* if they are the same registers */
8308 if (sameRegs (AOP (right), AOP (result)))
8311 /* if the result is a bit */
8312 if (AOP_TYPE (result) == AOP_CRY)
8315 /* if the right size is a literal then
8316 we know what the value is */
8317 if (AOP_TYPE (right) == AOP_LIT)
8319 if (((int) operandLitValue (right)))
8320 aopPut (AOP (result), one, 0);
8322 aopPut (AOP (result), zero, 0);
8326 /* the right is also a bit variable */
8327 if (AOP_TYPE (right) == AOP_CRY)
8329 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8330 aopPut (AOP (result), "c", 0);
8336 aopPut (AOP (result), "a", 0);
8340 /* bit variables done */
8342 size = AOP_SIZE (result);
8344 if (AOP_TYPE (right) == AOP_LIT)
8345 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8347 (AOP_TYPE (result) != AOP_REG) &&
8348 (AOP_TYPE (right) == AOP_LIT) &&
8349 !IS_FLOAT (operandType (right)) &&
8352 emitcode ("clr", "a");
8355 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8356 aopPut (AOP (result), "a", size);
8358 aopPut (AOP (result),
8359 aopGet (AOP (right), size, FALSE, FALSE),
8367 aopPut (AOP (result),
8368 aopGet (AOP (right), offset, FALSE, FALSE),
8375 freeAsmop (right, NULL, ic, TRUE);
8376 freeAsmop (result, NULL, ic, TRUE);
8379 /*-----------------------------------------------------------------*/
8380 /* genJumpTab - genrates code for jump table */
8381 /*-----------------------------------------------------------------*/
8383 genJumpTab (iCode * ic)
8388 D(emitcode (";", "genJumpTab"));
8390 aopOp (IC_JTCOND (ic), ic, FALSE);
8391 /* get the condition into accumulator */
8392 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8394 /* multiply by three */
8395 emitcode ("add", "a,acc");
8396 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8397 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8399 jtab = newiTempLabel (NULL);
8400 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8401 emitcode ("jmp", "@a+dptr");
8402 emitcode ("", "%05d$:", jtab->key + 100);
8403 /* now generate the jump labels */
8404 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8405 jtab = setNextItem (IC_JTLABELS (ic)))
8406 emitcode ("ljmp", "%05d$", jtab->key + 100);
8410 /*-----------------------------------------------------------------*/
8411 /* genCast - gen code for casting */
8412 /*-----------------------------------------------------------------*/
8414 genCast (iCode * ic)
8416 operand *result = IC_RESULT (ic);
8417 sym_link *ctype = operandType (IC_LEFT (ic));
8418 sym_link *rtype = operandType (IC_RIGHT (ic));
8419 operand *right = IC_RIGHT (ic);
8422 D(emitcode(";", "genCast"));
8424 /* if they are equivalent then do nothing */
8425 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8428 aopOp (right, ic, FALSE);
8429 aopOp (result, ic, FALSE);
8431 /* if the result is a bit */
8432 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8433 if (IS_BITVAR(OP_SYMBOL(result)->type))
8435 /* if the right size is a literal then
8436 we know what the value is */
8437 if (AOP_TYPE (right) == AOP_LIT)
8439 if (((int) operandLitValue (right)))
8440 aopPut (AOP (result), one, 0);
8442 aopPut (AOP (result), zero, 0);
8447 /* the right is also a bit variable */
8448 if (AOP_TYPE (right) == AOP_CRY)
8450 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8451 aopPut (AOP (result), "c", 0);
8457 aopPut (AOP (result), "a", 0);
8461 /* if they are the same size : or less */
8462 if (AOP_SIZE (result) <= AOP_SIZE (right))
8465 /* if they are in the same place */
8466 if (sameRegs (AOP (right), AOP (result)))
8469 /* if they in different places then copy */
8470 size = AOP_SIZE (result);
8474 aopPut (AOP (result),
8475 aopGet (AOP (right), offset, FALSE, FALSE),
8483 /* if the result is of type pointer */
8488 sym_link *type = operandType (right);
8489 sym_link *etype = getSpec (type);
8491 /* pointer to generic pointer */
8492 if (IS_GENPTR (ctype))
8497 p_type = DCL_TYPE (type);
8500 if (SPEC_SCLS(etype)==S_REGISTER) {
8501 // let's assume it is a generic pointer
8504 /* we have to go by the storage class */
8505 p_type = PTR_TYPE (SPEC_OCLS (etype));
8509 /* the first two bytes are known */
8510 size = GPTRSIZE - 1;
8514 aopPut (AOP (result),
8515 aopGet (AOP (right), offset, FALSE, FALSE),
8519 /* the last byte depending on type */
8535 case PPOINTER: // what the fck is this?
8540 /* this should never happen */
8541 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8542 "got unknown pointer type");
8545 aopPut (AOP (result), l, GPTRSIZE - 1);
8549 /* just copy the pointers */
8550 size = AOP_SIZE (result);
8554 aopPut (AOP (result),
8555 aopGet (AOP (right), offset, FALSE, FALSE),
8562 /* so we now know that the size of destination is greater
8563 than the size of the source */
8564 /* we move to result for the size of source */
8565 size = AOP_SIZE (right);
8569 aopPut (AOP (result),
8570 aopGet (AOP (right), offset, FALSE, FALSE),
8575 /* now depending on the sign of the source && destination */
8576 size = AOP_SIZE (result) - AOP_SIZE (right);
8577 /* if unsigned or not an integral type */
8578 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8581 aopPut (AOP (result), zero, offset++);
8585 /* we need to extend the sign :{ */
8586 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8589 emitcode ("rlc", "a");
8590 emitcode ("subb", "a,acc");
8592 aopPut (AOP (result), "a", offset++);
8595 /* we are done hurray !!!! */
8598 freeAsmop (right, NULL, ic, TRUE);
8599 freeAsmop (result, NULL, ic, TRUE);
8603 /*-----------------------------------------------------------------*/
8604 /* genDjnz - generate decrement & jump if not zero instrucion */
8605 /*-----------------------------------------------------------------*/
8607 genDjnz (iCode * ic, iCode * ifx)
8613 D(emitcode (";", "genDjnz"));
8615 /* if the if condition has a false label
8616 then we cannot save */
8620 /* if the minus is not of the form
8622 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8623 !IS_OP_LITERAL (IC_RIGHT (ic)))
8626 if (operandLitValue (IC_RIGHT (ic)) != 1)
8629 /* if the size of this greater than one then no
8631 if (getSize (operandType (IC_RESULT (ic))) > 1)
8634 /* otherwise we can save BIG */
8635 lbl = newiTempLabel (NULL);
8636 lbl1 = newiTempLabel (NULL);
8638 aopOp (IC_RESULT (ic), ic, FALSE);
8640 if (AOP_NEEDSACC(IC_RESULT(ic)))
8642 /* If the result is accessed indirectly via
8643 * the accumulator, we must explicitly write
8644 * it back after the decrement.
8646 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8648 if (strcmp(rByte, "a"))
8650 /* Something is hopelessly wrong */
8651 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8652 __FILE__, __LINE__);
8653 /* We can just give up; the generated code will be inefficient,
8656 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8659 emitcode ("dec", "%s", rByte);
8660 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8661 emitcode ("jnz", "%05d$", lbl->key + 100);
8663 else if (IS_AOP_PREG (IC_RESULT (ic)))
8665 emitcode ("dec", "%s",
8666 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8667 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8668 emitcode ("jnz", "%05d$", lbl->key + 100);
8672 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8675 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8676 emitcode ("", "%05d$:", lbl->key + 100);
8677 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8678 emitcode ("", "%05d$:", lbl1->key + 100);
8680 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8685 /*-----------------------------------------------------------------*/
8686 /* genReceive - generate code for a receive iCode */
8687 /*-----------------------------------------------------------------*/
8689 genReceive (iCode * ic)
8691 D(emitcode (";", "genReceive"));
8693 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8694 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8695 IS_TRUE_SYMOP (IC_RESULT (ic))))
8698 int size = getSize (operandType (IC_RESULT (ic)));
8699 int offset = fReturnSizeMCS51 - size;
8702 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8703 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8706 aopOp (IC_RESULT (ic), ic, FALSE);
8707 size = AOP_SIZE (IC_RESULT (ic));
8711 emitcode ("pop", "acc");
8712 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8719 aopOp (IC_RESULT (ic), ic, FALSE);
8721 assignResultValue (IC_RESULT (ic));
8724 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8727 /*-----------------------------------------------------------------*/
8728 /* gen51AggregateAssign - copy complete array's or structures */
8729 /*-----------------------------------------------------------------*/
8730 void gen51AggregateAssign(iCode *ic) {
8731 operand *left=IC_LEFT(ic);
8732 operand *right=IC_RIGHT(ic);
8733 char *fromName=OP_SYMBOL(right)->rname;
8734 char *toName=OP_SYMBOL(left)->rname;
8735 int fromSize=getSize(OP_SYMBOL(right)->type);
8736 int toSize=getSize(OP_SYMBOL(left)->type);
8739 D(emitcode (";", "gen51AggregateAssign"));
8741 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8742 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8743 // well, this code isn't used yet from anywhere else as for initialising
8744 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8748 if (fromSize!=toSize) {
8749 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8750 ic->filename, ic->lineno);
8755 // use the generic memcpy() for now
8756 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8757 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8758 emitcode ("mov", "a,#%s", fromName);
8759 emitcode ("movx", "@dptr,a");
8760 emitcode ("inc", "dptr");
8761 emitcode ("mov", "a,#(%s>>8)", fromName);
8762 emitcode ("movx", "@dptr,a");
8763 emitcode ("inc", "dptr");
8764 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8765 emitcode ("movx", "@dptr,a");
8766 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8767 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8768 emitcode ("movx", "@dptr,a");
8769 emitcode ("inc", "dptr");
8770 emitcode ("mov", "a,#(%d>>8)", count);
8771 emitcode ("movx", "@dptr,a");
8772 emitcode ("mov", "dptr,#%s", toName);
8773 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8774 emitcode ("lcall", "_memcpy");
8776 // more efficient, but will require the native_memcpy_cs2xs
8777 emitcode ("mov", "r0,#%s", fromName);
8778 emitcode ("mov", "r1,#(%s>>8)", fromName);
8779 emitcode ("mov", "r2,#%s", toName);
8780 emitcode ("mov", "r3,#(%s>>8)", toName);
8781 emitcode ("mov", "r4,#%d", count);
8782 emitcode ("mov", "r5,#(%d>>8)", count);
8783 emitcode ("lcall", "_native_memcpy_cs2xs");
8787 /*-----------------------------------------------------------------*/
8788 /* gen51Code - generate code for 8051 based controllers */
8789 /*-----------------------------------------------------------------*/
8791 gen51Code (iCode * lic)
8796 lineHead = lineCurr = NULL;
8798 /* print the allocation information */
8800 printAllocInfo (currFunc, codeOutFile);
8801 /* if debug information required */
8802 if (options.debug && currFunc)
8804 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8806 if (IS_STATIC (currFunc->etype))
8807 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8809 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8812 /* stack pointer name */
8813 if (options.useXstack)
8819 for (ic = lic; ic; ic = ic->next)
8822 if (cln != ic->lineno)
8827 emitcode ("", "C$%s$%d$%d$%d ==.",
8828 FileBaseName (ic->filename), ic->lineno,
8829 ic->level, ic->block);
8832 emitcode (";", "%s %d", ic->filename, ic->lineno);
8835 /* if the result is marked as
8836 spilt and rematerializable or code for
8837 this has already been generated then
8839 if (resultRemat (ic) || ic->generated)
8842 /* depending on the operation */
8862 /* IPOP happens only when trying to restore a
8863 spilt live range, if there is an ifx statement
8864 following this pop then the if statement might
8865 be using some of the registers being popped which
8866 would destory the contents of the register so
8867 we need to check for this condition and handle it */
8869 ic->next->op == IFX &&
8870 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8871 genIfx (ic->next, ic);
8889 genEndFunction (ic);
8909 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8926 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8930 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8937 /* note these two are xlated by algebraic equivalence
8938 during parsing SDCC.y */
8939 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8940 "got '>=' or '<=' shouldn't have come here");
8944 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8956 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8960 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8964 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8991 case GET_VALUE_AT_ADDRESS:
8992 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8996 if (POINTER_SET (ic))
8997 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
9023 addSet (&_G.sendSet, ic);
9027 gen51AggregateAssign(ic);
9036 /* now we are ready to call the
9037 peep hole optimizer */
9038 if (!options.nopeep)
9039 peepHole (&lineHead);
9041 /* now do the actual printing */
9042 printLine (lineHead, codeOutFile);