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 (dtype))
1932 // if (!ic->bankSaved)
1934 // /* This is unexpected; the bank should have been saved in
1937 // saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1938 // restoreBank = TRUE;
1940 // need caution message to user here
1944 /* if caller saves & we have not saved then */
1950 emitcode ("mov", "psw,#0x%02x",
1951 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1955 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1956 OP_SYMBOL (IC_LEFT (ic))->rname :
1957 OP_SYMBOL (IC_LEFT (ic))->name));
1961 emitcode ("mov", "psw,#0x%02x",
1962 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1965 /* if we need assign a result value */
1966 if ((IS_ITEMP (IC_RESULT (ic)) &&
1967 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1968 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1969 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1970 IS_TRUE_SYMOP (IC_RESULT (ic)))
1974 aopOp (IC_RESULT (ic), ic, FALSE);
1977 assignResultValue (IC_RESULT (ic));
1979 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1982 /* adjust the stack for parameters if
1987 if (ic->parmBytes > 3)
1989 emitcode ("mov", "a,%s", spname);
1990 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1991 emitcode ("mov", "%s,a", spname);
1994 for (i = 0; i < ic->parmBytes; i++)
1995 emitcode ("dec", "%s", spname);
1998 /* if we hade saved some registers then unsave them */
1999 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2000 unsaveRegisters (ic);
2002 // /* if register bank was saved then pop them */
2004 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2007 /*-----------------------------------------------------------------*/
2008 /* -10l - generates a call by pointer statement */
2009 /*-----------------------------------------------------------------*/
2011 genPcall (iCode * ic)
2014 symbol *rlbl = newiTempLabel (NULL);
2015 // bool restoreBank=FALSE;
2016 bool swapBanks = FALSE;
2018 D(emitcode(";", "genPCall"));
2020 /* if caller saves & we have not saved then */
2024 /* if we are calling a not _naked function that is not using
2025 the same register bank then we need to save the
2026 destination registers on the stack */
2027 dtype = operandType (IC_LEFT (ic))->next;
2028 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2029 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2030 !IFFUNC_ISISR (dtype))
2032 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2033 // restoreBank=TRUE;
2035 // need caution message to user here
2038 /* push the return address on to the stack */
2039 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2040 emitcode ("push", "acc");
2041 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2042 emitcode ("push", "acc");
2044 /* now push the calling address */
2045 aopOp (IC_LEFT (ic), ic, FALSE);
2047 pushSide (IC_LEFT (ic), FPTRSIZE);
2049 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2051 /* if send set is not empty the assign */
2056 for (sic = setFirstItem (_G.sendSet); sic;
2057 sic = setNextItem (_G.sendSet))
2059 int size, offset = 0;
2060 aopOp (IC_LEFT (sic), sic, FALSE);
2061 size = AOP_SIZE (IC_LEFT (sic));
2064 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2066 if (strcmp (l, fReturn[offset]))
2067 emitcode ("mov", "%s,%s",
2072 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2079 emitcode ("mov", "psw,#0x%02x",
2080 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2084 emitcode ("ret", "");
2085 emitcode ("", "%05d$:", (rlbl->key + 100));
2090 emitcode ("mov", "psw,#0x%02x",
2091 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2094 /* if we need assign a result value */
2095 if ((IS_ITEMP (IC_RESULT (ic)) &&
2096 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2097 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2098 IS_TRUE_SYMOP (IC_RESULT (ic)))
2102 aopOp (IC_RESULT (ic), ic, FALSE);
2105 assignResultValue (IC_RESULT (ic));
2107 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2110 /* adjust the stack for parameters if
2115 if (ic->parmBytes > 3)
2117 emitcode ("mov", "a,%s", spname);
2118 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2119 emitcode ("mov", "%s,a", spname);
2122 for (i = 0; i < ic->parmBytes; i++)
2123 emitcode ("dec", "%s", spname);
2127 // /* if register bank was saved then unsave them */
2129 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2131 /* if we hade saved some registers then
2133 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2134 unsaveRegisters (ic);
2137 /*-----------------------------------------------------------------*/
2138 /* resultRemat - result is rematerializable */
2139 /*-----------------------------------------------------------------*/
2141 resultRemat (iCode * ic)
2143 if (SKIP_IC (ic) || ic->op == IFX)
2146 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2148 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2149 if (sym->remat && !POINTER_SET (ic))
2156 #if defined(__BORLANDC__) || defined(_MSC_VER)
2157 #define STRCASECMP stricmp
2159 #define STRCASECMP strcasecmp
2162 /*-----------------------------------------------------------------*/
2163 /* inExcludeList - return 1 if the string is in exclude Reg list */
2164 /*-----------------------------------------------------------------*/
2166 inExcludeList (char *s)
2170 if (options.excludeRegs[i] &&
2171 STRCASECMP (options.excludeRegs[i], "none") == 0)
2174 for (i = 0; options.excludeRegs[i]; i++)
2176 if (options.excludeRegs[i] &&
2177 STRCASECMP (s, options.excludeRegs[i]) == 0)
2183 /*-----------------------------------------------------------------*/
2184 /* genFunction - generated code for function entry */
2185 /*-----------------------------------------------------------------*/
2187 genFunction (iCode * ic)
2191 bool switchedPSW = FALSE;
2192 int calleesaves_saved_register = -1;
2195 /* create the function header */
2196 emitcode (";", "-----------------------------------------");
2197 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2198 emitcode (";", "-----------------------------------------");
2200 emitcode ("", "%s:", sym->rname);
2201 ftype = operandType (IC_LEFT (ic));
2203 if (IFFUNC_ISNAKED(ftype))
2205 emitcode(";", "naked function: no prologue.");
2209 /* if critical function then turn interrupts off */
2210 if (IFFUNC_ISCRITICAL (ftype))
2211 emitcode ("clr", "ea");
2213 /* here we need to generate the equates for the
2214 register bank if required */
2215 if (FUNC_REGBANK (ftype) != rbank)
2219 rbank = FUNC_REGBANK (ftype);
2220 for (i = 0; i < mcs51_nRegs; i++)
2222 if (strcmp (regs8051[i].base, "0") == 0)
2223 emitcode ("", "%s = 0x%02x",
2225 8 * rbank + regs8051[i].offset);
2227 emitcode ("", "%s = %s + 0x%02x",
2230 8 * rbank + regs8051[i].offset);
2234 /* if this is an interrupt service routine then
2235 save acc, b, dpl, dph */
2236 if (IFFUNC_ISISR (sym->type))
2239 if (!inExcludeList ("acc"))
2240 emitcode ("push", "acc");
2241 if (!inExcludeList ("b"))
2242 emitcode ("push", "b");
2243 if (!inExcludeList ("dpl"))
2244 emitcode ("push", "dpl");
2245 if (!inExcludeList ("dph"))
2246 emitcode ("push", "dph");
2247 /* if this isr has no bank i.e. is going to
2248 run with bank 0 , then we need to save more
2250 if (!FUNC_REGBANK (sym->type))
2253 /* if this function does not call any other
2254 function then we can be economical and
2255 save only those registers that are used */
2256 if (!IFFUNC_HASFCALL(sym->type))
2260 /* if any registers used */
2263 /* save the registers used */
2264 for (i = 0; i < sym->regsUsed->size; i++)
2266 if (bitVectBitValue (sym->regsUsed, i) ||
2267 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2268 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2275 /* this function has a function call cannot
2276 determines register usage so we will have to push the
2278 saveRBank (0, ic, FALSE);
2283 /* This ISR uses a non-zero bank.
2285 * We assume that the bank is available for our
2288 * However, if this ISR calls a function which uses some
2289 * other bank, we must save that bank entirely.
2291 unsigned long banksToSave = 0;
2293 if (IFFUNC_HASFCALL(sym->type))
2296 #define MAX_REGISTER_BANKS 4
2301 for (i = ic; i; i = i->next)
2303 if (i->op == ENDFUNCTION)
2305 /* we got to the end OK. */
2313 dtype = operandType (IC_LEFT(i));
2315 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2317 /* Mark this bank for saving. */
2318 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2320 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2324 banksToSave |= (1 << FUNC_REGBANK(dtype));
2327 /* And note that we don't need to do it in
2335 /* This is a mess; we have no idea what
2336 * register bank the called function might
2339 * The only thing I can think of to do is
2340 * throw a warning and hope.
2342 werror(W_FUNCPTR_IN_USING_ISR);
2346 if (banksToSave && options.useXstack)
2348 /* Since we aren't passing it an ic,
2349 * saveRBank will assume r0 is available to abuse.
2351 * So switch to our (trashable) bank now, so
2352 * the caller's R0 isn't trashed.
2354 emitcode ("push", "psw");
2355 emitcode ("mov", "psw,#0x%02x",
2356 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2360 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2362 if (banksToSave & (1 << ix))
2364 saveRBank(ix, NULL, FALSE);
2368 // jwk: this needs a closer look
2369 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2374 /* if callee-save to be used for this function
2375 then save the registers being used in this function */
2376 if (IFFUNC_CALLEESAVES(sym->type))
2380 /* if any registers used */
2383 /* save the registers used */
2384 for (i = 0; i < sym->regsUsed->size; i++)
2386 if (bitVectBitValue (sym->regsUsed, i) ||
2387 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2389 /* remember one saved register for later usage */
2390 if (calleesaves_saved_register < 0)
2391 calleesaves_saved_register = i;
2392 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2400 /* set the register bank to the desired value */
2401 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2404 emitcode ("push", "psw");
2405 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2408 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2411 if (options.useXstack)
2413 emitcode ("mov", "r0,%s", spname);
2414 emitcode ("mov", "a,_bp");
2415 emitcode ("movx", "@r0,a");
2416 emitcode ("inc", "%s", spname);
2420 /* set up the stack */
2421 emitcode ("push", "_bp"); /* save the callers stack */
2423 emitcode ("mov", "_bp,%s", spname);
2426 /* adjust the stack for the function */
2432 werror (W_STACK_OVERFLOW, sym->name);
2434 if (i > 3 && sym->recvSize < 4)
2437 emitcode ("mov", "a,sp");
2438 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2439 emitcode ("mov", "sp,a");
2444 if (IFFUNC_CALLEESAVES(sym->type))
2446 /* if it's a callee-saves function we need a saved register */
2447 if (calleesaves_saved_register >= 0)
2449 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2450 emitcode ("mov", "a,sp");
2451 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2452 emitcode ("mov", "sp,a");
2453 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2456 /* do it the hard way */
2458 emitcode ("inc", "sp");
2462 /* not callee-saves, we can clobber ar0 */
2463 emitcode ("mov", "ar0,a");
2464 emitcode ("mov", "a,sp");
2465 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2466 emitcode ("mov", "sp,a");
2467 emitcode ("mov", "a,ar0");
2472 emitcode ("inc", "sp");
2478 emitcode ("mov", "a,_spx");
2479 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2480 emitcode ("mov", "_spx,a");
2485 /*-----------------------------------------------------------------*/
2486 /* genEndFunction - generates epilogue for functions */
2487 /*-----------------------------------------------------------------*/
2489 genEndFunction (iCode * ic)
2491 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2493 if (IFFUNC_ISNAKED(sym->type))
2495 emitcode(";", "naked function: no epilogue.");
2499 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2501 emitcode ("mov", "%s,_bp", spname);
2504 /* if use external stack but some variables were
2505 added to the local stack then decrement the
2507 if (options.useXstack && sym->stack)
2509 emitcode ("mov", "a,sp");
2510 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2511 emitcode ("mov", "sp,a");
2515 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2517 if (options.useXstack)
2519 emitcode ("mov", "r0,%s", spname);
2520 emitcode ("movx", "a,@r0");
2521 emitcode ("mov", "_bp,a");
2522 emitcode ("dec", "%s", spname);
2526 emitcode ("pop", "_bp");
2530 /* restore the register bank */
2531 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2533 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2534 || !options.useXstack)
2536 /* Special case of ISR using non-zero bank with useXstack
2539 emitcode ("pop", "psw");
2543 if (IFFUNC_ISISR (sym->type))
2546 /* now we need to restore the registers */
2547 /* if this isr has no bank i.e. is going to
2548 run with bank 0 , then we need to save more
2550 if (!FUNC_REGBANK (sym->type))
2552 /* if this function does not call any other
2553 function then we can be economical and
2554 save only those registers that are used */
2555 if (!IFFUNC_HASFCALL(sym->type))
2559 /* if any registers used */
2562 /* save the registers used */
2563 for (i = sym->regsUsed->size; i >= 0; i--)
2565 if (bitVectBitValue (sym->regsUsed, i) ||
2566 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2567 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2574 /* this function has a function call cannot
2575 determines register usage so we will have to pop the
2577 unsaveRBank (0, ic, FALSE);
2582 /* This ISR uses a non-zero bank.
2584 * Restore any register banks saved by genFunction
2587 // jwk: this needs a closer look
2588 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2591 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2593 if (savedBanks & (1 << ix))
2595 unsaveRBank(ix, NULL, FALSE);
2599 if (options.useXstack)
2601 /* Restore bank AFTER calling unsaveRBank,
2602 * since it can trash r0.
2604 emitcode ("pop", "psw");
2608 if (!inExcludeList ("dph"))
2609 emitcode ("pop", "dph");
2610 if (!inExcludeList ("dpl"))
2611 emitcode ("pop", "dpl");
2612 if (!inExcludeList ("b"))
2613 emitcode ("pop", "b");
2614 if (!inExcludeList ("acc"))
2615 emitcode ("pop", "acc");
2617 if (IFFUNC_ISCRITICAL (sym->type))
2618 emitcode ("setb", "ea");
2620 /* if debug then send end of function */
2621 if (options.debug && currFunc)
2624 emitcode ("", "C$%s$%d$%d$%d ==.",
2625 FileBaseName (ic->filename), currFunc->lastLine,
2626 ic->level, ic->block);
2627 if (IS_STATIC (currFunc->etype))
2628 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2630 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2634 emitcode ("reti", "");
2638 if (IFFUNC_ISCRITICAL (sym->type))
2639 emitcode ("setb", "ea");
2641 if (IFFUNC_CALLEESAVES(sym->type))
2645 /* if any registers used */
2648 /* save the registers used */
2649 for (i = sym->regsUsed->size; i >= 0; i--)
2651 if (bitVectBitValue (sym->regsUsed, i) ||
2652 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2653 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2659 /* if debug then send end of function */
2660 if (options.debug && currFunc)
2663 emitcode ("", "C$%s$%d$%d$%d ==.",
2664 FileBaseName (ic->filename), currFunc->lastLine,
2665 ic->level, ic->block);
2666 if (IS_STATIC (currFunc->etype))
2667 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2669 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2673 emitcode ("ret", "");
2678 /*-----------------------------------------------------------------*/
2679 /* genRet - generate code for return statement */
2680 /*-----------------------------------------------------------------*/
2684 int size, offset = 0, pushed = 0;
2686 D(emitcode (";", "genRet"));
2688 /* if we have no return value then
2689 just generate the "ret" */
2693 /* we have something to return then
2694 move the return value into place */
2695 aopOp (IC_LEFT (ic), ic, FALSE);
2696 size = AOP_SIZE (IC_LEFT (ic));
2701 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2704 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2706 emitcode ("push", "%s", l);
2711 l = aopGet (AOP (IC_LEFT (ic)), offset,
2713 if (strcmp (fReturn[offset], l))
2714 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2723 if (strcmp (fReturn[pushed], "a"))
2724 emitcode ("pop", fReturn[pushed]);
2726 emitcode ("pop", "acc");
2729 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2732 /* generate a jump to the return label
2733 if the next is not the return statement */
2734 if (!(ic->next && ic->next->op == LABEL &&
2735 IC_LABEL (ic->next) == returnLabel))
2737 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2741 /*-----------------------------------------------------------------*/
2742 /* genLabel - generates a label */
2743 /*-----------------------------------------------------------------*/
2745 genLabel (iCode * ic)
2747 /* special case never generate */
2748 if (IC_LABEL (ic) == entryLabel)
2751 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2754 /*-----------------------------------------------------------------*/
2755 /* genGoto - generates a ljmp */
2756 /*-----------------------------------------------------------------*/
2758 genGoto (iCode * ic)
2760 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2763 /*-----------------------------------------------------------------*/
2764 /* findLabelBackwards: walks back through the iCode chain looking */
2765 /* for the given label. Returns number of iCode instructions */
2766 /* between that label and given ic. */
2767 /* Returns zero if label not found. */
2768 /*-----------------------------------------------------------------*/
2770 findLabelBackwards (iCode * ic, int key)
2779 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2781 /* printf("findLabelBackwards = %d\n", count); */
2789 /*-----------------------------------------------------------------*/
2790 /* genPlusIncr :- does addition with increment if possible */
2791 /*-----------------------------------------------------------------*/
2793 genPlusIncr (iCode * ic)
2795 unsigned int icount;
2796 unsigned int size = getDataSize (IC_RESULT (ic));
2798 /* will try to generate an increment */
2799 /* if the right side is not a literal
2801 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2804 /* if the literal value of the right hand side
2805 is greater than 4 then it is not worth it */
2806 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2809 D(emitcode (";", "genPlusIncr"));
2811 /* if increment 16 bits in register */
2812 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2820 /* If the next instruction is a goto and the goto target
2821 * is < 10 instructions previous to this, we can generate
2822 * jumps straight to that target.
2824 if (ic->next && ic->next->op == GOTO
2825 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2826 && labelRange <= 10)
2828 emitcode (";", "tail increment optimized");
2829 tlbl = IC_LABEL (ic->next);
2834 tlbl = newiTempLabel (NULL);
2837 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2838 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2839 IS_AOP_PREG (IC_RESULT (ic)))
2840 emitcode ("cjne", "%s,#0x00,%05d$"
2841 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2845 emitcode ("clr", "a");
2846 emitcode ("cjne", "a,%s,%05d$"
2847 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2851 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2854 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2855 IS_AOP_PREG (IC_RESULT (ic)))
2856 emitcode ("cjne", "%s,#0x00,%05d$"
2857 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2860 emitcode ("cjne", "a,%s,%05d$"
2861 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2864 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2868 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2869 IS_AOP_PREG (IC_RESULT (ic)))
2870 emitcode ("cjne", "%s,#0x00,%05d$"
2871 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2875 emitcode ("cjne", "a,%s,%05d$"
2876 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2879 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2884 emitcode ("", "%05d$:", tlbl->key + 100);
2889 /* if the sizes are greater than 1 then we cannot */
2890 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2891 AOP_SIZE (IC_LEFT (ic)) > 1)
2894 /* we can if the aops of the left & result match or
2895 if they are in registers and the registers are the
2897 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2902 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2903 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2904 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2910 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2919 /*-----------------------------------------------------------------*/
2920 /* outBitAcc - output a bit in acc */
2921 /*-----------------------------------------------------------------*/
2923 outBitAcc (operand * result)
2925 symbol *tlbl = newiTempLabel (NULL);
2926 /* if the result is a bit */
2927 if (AOP_TYPE (result) == AOP_CRY)
2929 aopPut (AOP (result), "a", 0);
2933 emitcode ("jz", "%05d$", tlbl->key + 100);
2934 emitcode ("mov", "a,%s", one);
2935 emitcode ("", "%05d$:", tlbl->key + 100);
2940 /*-----------------------------------------------------------------*/
2941 /* genPlusBits - generates code for addition of two bits */
2942 /*-----------------------------------------------------------------*/
2944 genPlusBits (iCode * ic)
2946 D(emitcode (";", "genPlusBits"));
2948 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2950 symbol *lbl = newiTempLabel (NULL);
2951 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2952 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2953 emitcode ("cpl", "c");
2954 emitcode ("", "%05d$:", (lbl->key + 100));
2955 outBitC (IC_RESULT (ic));
2959 emitcode ("clr", "a");
2960 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2961 emitcode ("rlc", "a");
2962 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2963 emitcode ("addc", "a,#0x00");
2964 outAcc (IC_RESULT (ic));
2969 /* This is the original version of this code.
2971 * This is being kept around for reference,
2972 * because I am not entirely sure I got it right...
2975 adjustArithmeticResult (iCode * ic)
2977 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2978 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2979 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2980 aopPut (AOP (IC_RESULT (ic)),
2981 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2984 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2985 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2986 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2987 aopPut (AOP (IC_RESULT (ic)),
2988 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2991 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2992 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2993 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2994 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2995 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2998 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2999 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3003 /* This is the pure and virtuous version of this code.
3004 * I'm pretty certain it's right, but not enough to toss the old
3008 adjustArithmeticResult (iCode * ic)
3010 if (opIsGptr (IC_RESULT (ic)) &&
3011 opIsGptr (IC_LEFT (ic)) &&
3012 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3014 aopPut (AOP (IC_RESULT (ic)),
3015 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3019 if (opIsGptr (IC_RESULT (ic)) &&
3020 opIsGptr (IC_RIGHT (ic)) &&
3021 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3023 aopPut (AOP (IC_RESULT (ic)),
3024 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3028 if (opIsGptr (IC_RESULT (ic)) &&
3029 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3030 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3031 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3032 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3035 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3036 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3041 /*-----------------------------------------------------------------*/
3042 /* genPlus - generates code for addition */
3043 /*-----------------------------------------------------------------*/
3045 genPlus (iCode * ic)
3047 int size, offset = 0;
3049 /* special cases :- */
3051 D(emitcode (";", "genPlus"));
3053 aopOp (IC_LEFT (ic), ic, FALSE);
3054 aopOp (IC_RIGHT (ic), ic, FALSE);
3055 aopOp (IC_RESULT (ic), ic, TRUE);
3057 /* if literal, literal on the right or
3058 if left requires ACC or right is already
3060 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3061 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3062 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3064 operand *t = IC_RIGHT (ic);
3065 IC_RIGHT (ic) = IC_LEFT (ic);
3069 /* if both left & right are in bit
3071 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3072 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3078 /* if left in bit space & right literal */
3079 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3080 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3082 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3083 /* if result in bit space */
3084 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3086 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3087 emitcode ("cpl", "c");
3088 outBitC (IC_RESULT (ic));
3092 size = getDataSize (IC_RESULT (ic));
3095 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3096 emitcode ("addc", "a,#00");
3097 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3103 /* if I can do an increment instead
3104 of add then GOOD for ME */
3105 if (genPlusIncr (ic) == TRUE)
3108 size = getDataSize (IC_RESULT (ic));
3112 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3114 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3116 emitcode ("add", "a,%s",
3117 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3119 emitcode ("addc", "a,%s",
3120 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3124 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3126 emitcode ("add", "a,%s",
3127 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3129 emitcode ("addc", "a,%s",
3130 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3132 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3135 adjustArithmeticResult (ic);
3138 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3139 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3140 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3143 /*-----------------------------------------------------------------*/
3144 /* genMinusDec :- does subtraction with deccrement if possible */
3145 /*-----------------------------------------------------------------*/
3147 genMinusDec (iCode * ic)
3149 unsigned int icount;
3150 unsigned int size = getDataSize (IC_RESULT (ic));
3152 /* will try to generate an increment */
3153 /* if the right side is not a literal
3155 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3158 /* if the literal value of the right hand side
3159 is greater than 4 then it is not worth it */
3160 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3163 D(emitcode (";", "genMinusDec"));
3165 /* if decrement 16 bits in register */
3166 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3174 /* If the next instruction is a goto and the goto target
3175 * is <= 10 instructions previous to this, we can generate
3176 * jumps straight to that target.
3178 if (ic->next && ic->next->op == GOTO
3179 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3180 && labelRange <= 10)
3182 emitcode (";", "tail decrement optimized");
3183 tlbl = IC_LABEL (ic->next);
3188 tlbl = newiTempLabel (NULL);
3192 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3193 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3194 IS_AOP_PREG (IC_RESULT (ic)))
3195 emitcode ("cjne", "%s,#0xff,%05d$"
3196 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3200 emitcode ("mov", "a,#0xff");
3201 emitcode ("cjne", "a,%s,%05d$"
3202 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3205 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3208 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3209 IS_AOP_PREG (IC_RESULT (ic)))
3210 emitcode ("cjne", "%s,#0xff,%05d$"
3211 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3215 emitcode ("cjne", "a,%s,%05d$"
3216 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3219 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3223 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3224 IS_AOP_PREG (IC_RESULT (ic)))
3225 emitcode ("cjne", "%s,#0xff,%05d$"
3226 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3230 emitcode ("cjne", "a,%s,%05d$"
3231 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3234 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3238 emitcode ("", "%05d$:", tlbl->key + 100);
3243 /* if the sizes are greater than 1 then we cannot */
3244 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3245 AOP_SIZE (IC_LEFT (ic)) > 1)
3248 /* we can if the aops of the left & result match or
3249 if they are in registers and the registers are the
3251 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3255 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3263 /*-----------------------------------------------------------------*/
3264 /* addSign - complete with sign */
3265 /*-----------------------------------------------------------------*/
3267 addSign (operand * result, int offset, int sign)
3269 int size = (getDataSize (result) - offset);
3274 emitcode ("rlc", "a");
3275 emitcode ("subb", "a,acc");
3277 aopPut (AOP (result), "a", offset++);
3281 aopPut (AOP (result), zero, offset++);
3285 /*-----------------------------------------------------------------*/
3286 /* genMinusBits - generates code for subtraction of two bits */
3287 /*-----------------------------------------------------------------*/
3289 genMinusBits (iCode * ic)
3291 symbol *lbl = newiTempLabel (NULL);
3293 D(emitcode (";", "genMinusBits"));
3295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3297 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3298 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3299 emitcode ("cpl", "c");
3300 emitcode ("", "%05d$:", (lbl->key + 100));
3301 outBitC (IC_RESULT (ic));
3305 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3306 emitcode ("subb", "a,acc");
3307 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3308 emitcode ("inc", "a");
3309 emitcode ("", "%05d$:", (lbl->key + 100));
3310 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3311 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3315 /*-----------------------------------------------------------------*/
3316 /* genMinus - generates code for subtraction */
3317 /*-----------------------------------------------------------------*/
3319 genMinus (iCode * ic)
3321 int size, offset = 0;
3322 unsigned long lit = 0L;
3324 D(emitcode (";", "genMinus"));
3326 aopOp (IC_LEFT (ic), ic, FALSE);
3327 aopOp (IC_RIGHT (ic), ic, FALSE);
3328 aopOp (IC_RESULT (ic), ic, TRUE);
3330 /* special cases :- */
3331 /* if both left & right are in bit space */
3332 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3333 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3339 /* if I can do an decrement instead
3340 of subtract then GOOD for ME */
3341 if (genMinusDec (ic) == TRUE)
3344 size = getDataSize (IC_RESULT (ic));
3346 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3352 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3356 /* if literal, add a,#-lit, else normal subb */
3359 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3360 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3361 emitcode ("subb", "a,%s",
3362 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3365 /* first add without previous c */
3367 if (!size && lit==-1) {
3368 emitcode ("dec", "a");
3370 emitcode ("add", "a,#0x%02x",
3371 (unsigned int) (lit & 0x0FFL));
3374 emitcode ("addc", "a,#0x%02x",
3375 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3378 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3381 adjustArithmeticResult (ic);
3384 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3385 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3386 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3390 /*-----------------------------------------------------------------*/
3391 /* genMultbits :- multiplication of bits */
3392 /*-----------------------------------------------------------------*/
3394 genMultbits (operand * left,
3398 D(emitcode (";", "genMultbits"));
3400 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3401 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3406 /*-----------------------------------------------------------------*/
3407 /* genMultOneByte : 8*8=8/16 bit multiplication */
3408 /*-----------------------------------------------------------------*/
3410 genMultOneByte (operand * left,
3414 sym_link *opetype = operandType (result);
3416 int size=AOP_SIZE(result);
3418 D(emitcode (";", "genMultOneByte"));
3420 if (size<1 || size>2) {
3421 // this should never happen
3422 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3423 AOP_SIZE(result), __FILE__, lineno);
3427 /* (if two literals: the value is computed before) */
3428 /* if one literal, literal on the right */
3429 if (AOP_TYPE (left) == AOP_LIT)
3434 //emitcode (";", "swapped left and right");
3437 if (SPEC_USIGN(opetype)
3438 // ignore the sign of left and right, what else can we do?
3439 || (SPEC_USIGN(operandType(left)) &&
3440 SPEC_USIGN(operandType(right)))) {
3441 // just an unsigned 8*8=8/16 multiply
3442 //emitcode (";","unsigned");
3443 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3444 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3445 emitcode ("mul", "ab");
3446 aopPut (AOP (result), "a", 0);
3448 aopPut (AOP (result), "b", 1);
3453 // we have to do a signed multiply
3455 //emitcode (";", "signed");
3456 emitcode ("clr", "F0"); // reset sign flag
3457 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3459 lbl=newiTempLabel(NULL);
3460 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3461 // left side is negative, 8-bit two's complement, this fails for -128
3462 emitcode ("setb", "F0"); // set sign flag
3463 emitcode ("cpl", "a");
3464 emitcode ("inc", "a");
3466 emitcode ("", "%05d$:", lbl->key+100);
3469 if (AOP_TYPE(right)==AOP_LIT) {
3470 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3471 /* AND literal negative */
3473 emitcode ("cpl", "F0"); // complement sign flag
3474 emitcode ("mov", "b,#0x%02x", -val);
3476 emitcode ("mov", "b,#0x%02x", val);
3479 lbl=newiTempLabel(NULL);
3480 emitcode ("mov", "b,a");
3481 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3482 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3483 // right side is negative, 8-bit two's complement
3484 emitcode ("cpl", "F0"); // complement sign flag
3485 emitcode ("cpl", "a");
3486 emitcode ("inc", "a");
3487 emitcode ("", "%05d$:", lbl->key+100);
3489 emitcode ("mul", "ab");
3491 lbl=newiTempLabel(NULL);
3492 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3493 // only ONE op was negative, we have to do a 8/16-bit two's complement
3494 emitcode ("cpl", "a"); // lsb
3496 emitcode ("inc", "a");
3498 emitcode ("add", "a,#1");
3499 emitcode ("xch", "a,b");
3500 emitcode ("cpl", "a"); // msb
3501 emitcode ("addc", "a,#0");
3502 emitcode ("xch", "a,b");
3505 emitcode ("", "%05d$:", lbl->key+100);
3506 aopPut (AOP (result), "a", 0);
3508 aopPut (AOP (result), "b", 1);
3512 /*-----------------------------------------------------------------*/
3513 /* genMult - generates code for multiplication */
3514 /*-----------------------------------------------------------------*/
3516 genMult (iCode * ic)
3518 operand *left = IC_LEFT (ic);
3519 operand *right = IC_RIGHT (ic);
3520 operand *result = IC_RESULT (ic);
3522 D(emitcode (";", "genMult"));
3524 /* assign the amsops */
3525 aopOp (left, ic, FALSE);
3526 aopOp (right, ic, FALSE);
3527 aopOp (result, ic, TRUE);
3529 /* special cases first */
3531 if (AOP_TYPE (left) == AOP_CRY &&
3532 AOP_TYPE (right) == AOP_CRY)
3534 genMultbits (left, right, result);
3538 /* if both are of size == 1 */
3539 #if 0 // one of them can be a sloc shared with the result
3540 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3542 if (getSize(operandType(left)) == 1 &&
3543 getSize(operandType(right)) == 1)
3546 genMultOneByte (left, right, result);
3550 /* should have been converted to function call */
3551 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3552 getSize(OP_SYMBOL(right)->type));
3556 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3557 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3558 freeAsmop (result, NULL, ic, TRUE);
3561 /*-----------------------------------------------------------------*/
3562 /* genDivbits :- division of bits */
3563 /*-----------------------------------------------------------------*/
3565 genDivbits (operand * left,
3572 D(emitcode (";", "genDivbits"));
3574 /* the result must be bit */
3575 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3576 l = aopGet (AOP (left), 0, FALSE, FALSE);
3580 emitcode ("div", "ab");
3581 emitcode ("rrc", "a");
3582 aopPut (AOP (result), "c", 0);
3585 /*-----------------------------------------------------------------*/
3586 /* genDivOneByte : 8 bit division */
3587 /*-----------------------------------------------------------------*/
3589 genDivOneByte (operand * left,
3593 sym_link *opetype = operandType (result);
3598 D(emitcode (";", "genDivOneByte"));
3600 size = AOP_SIZE (result) - 1;
3602 /* signed or unsigned */
3603 if (SPEC_USIGN (opetype))
3605 /* unsigned is easy */
3606 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3607 l = aopGet (AOP (left), 0, FALSE, FALSE);
3609 emitcode ("div", "ab");
3610 aopPut (AOP (result), "a", 0);
3612 aopPut (AOP (result), zero, offset++);
3616 /* signed is a little bit more difficult */
3618 /* save the signs of the operands */
3619 l = aopGet (AOP (left), 0, FALSE, FALSE);
3621 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3622 emitcode ("push", "acc"); /* save it on the stack */
3624 /* now sign adjust for both left & right */
3625 l = aopGet (AOP (right), 0, FALSE, FALSE);
3627 lbl = newiTempLabel (NULL);
3628 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3629 emitcode ("cpl", "a");
3630 emitcode ("inc", "a");
3631 emitcode ("", "%05d$:", (lbl->key + 100));
3632 emitcode ("mov", "b,a");
3634 /* sign adjust left side */
3635 l = aopGet (AOP (left), 0, FALSE, FALSE);
3638 lbl = newiTempLabel (NULL);
3639 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3640 emitcode ("cpl", "a");
3641 emitcode ("inc", "a");
3642 emitcode ("", "%05d$:", (lbl->key + 100));
3644 /* now the division */
3645 emitcode ("div", "ab");
3646 /* we are interested in the lower order
3648 emitcode ("mov", "b,a");
3649 lbl = newiTempLabel (NULL);
3650 emitcode ("pop", "acc");
3651 /* if there was an over flow we don't
3652 adjust the sign of the result */
3653 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3654 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3656 emitcode ("clr", "a");
3657 emitcode ("subb", "a,b");
3658 emitcode ("mov", "b,a");
3659 emitcode ("", "%05d$:", (lbl->key + 100));
3661 /* now we are done */
3662 aopPut (AOP (result), "b", 0);
3665 emitcode ("mov", "c,b.7");
3666 emitcode ("subb", "a,acc");
3669 aopPut (AOP (result), "a", offset++);
3673 /*-----------------------------------------------------------------*/
3674 /* genDiv - generates code for division */
3675 /*-----------------------------------------------------------------*/
3679 operand *left = IC_LEFT (ic);
3680 operand *right = IC_RIGHT (ic);
3681 operand *result = IC_RESULT (ic);
3683 D(emitcode (";", "genDiv"));
3685 /* assign the amsops */
3686 aopOp (left, ic, FALSE);
3687 aopOp (right, ic, FALSE);
3688 aopOp (result, ic, TRUE);
3690 /* special cases first */
3692 if (AOP_TYPE (left) == AOP_CRY &&
3693 AOP_TYPE (right) == AOP_CRY)
3695 genDivbits (left, right, result);
3699 /* if both are of size == 1 */
3700 if (AOP_SIZE (left) == 1 &&
3701 AOP_SIZE (right) == 1)
3703 genDivOneByte (left, right, result);
3707 /* should have been converted to function call */
3710 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3711 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3712 freeAsmop (result, NULL, ic, TRUE);
3715 /*-----------------------------------------------------------------*/
3716 /* genModbits :- modulus of bits */
3717 /*-----------------------------------------------------------------*/
3719 genModbits (operand * left,
3726 D(emitcode (";", "genModbits"));
3728 /* the result must be bit */
3729 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3730 l = aopGet (AOP (left), 0, FALSE, FALSE);
3734 emitcode ("div", "ab");
3735 emitcode ("mov", "a,b");
3736 emitcode ("rrc", "a");
3737 aopPut (AOP (result), "c", 0);
3740 /*-----------------------------------------------------------------*/
3741 /* genModOneByte : 8 bit modulus */
3742 /*-----------------------------------------------------------------*/
3744 genModOneByte (operand * left,
3748 sym_link *opetype = operandType (result);
3752 D(emitcode (";", "genModOneByte"));
3754 /* signed or unsigned */
3755 if (SPEC_USIGN (opetype))
3757 /* unsigned is easy */
3758 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3759 l = aopGet (AOP (left), 0, FALSE, FALSE);
3761 emitcode ("div", "ab");
3762 aopPut (AOP (result), "b", 0);
3766 /* signed is a little bit more difficult */
3768 /* save the signs of the operands */
3769 l = aopGet (AOP (left), 0, FALSE, FALSE);
3772 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3773 emitcode ("push", "acc"); /* save it on the stack */
3775 /* now sign adjust for both left & right */
3776 l = aopGet (AOP (right), 0, FALSE, FALSE);
3779 lbl = newiTempLabel (NULL);
3780 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3781 emitcode ("cpl", "a");
3782 emitcode ("inc", "a");
3783 emitcode ("", "%05d$:", (lbl->key + 100));
3784 emitcode ("mov", "b,a");
3786 /* sign adjust left side */
3787 l = aopGet (AOP (left), 0, FALSE, FALSE);
3790 lbl = newiTempLabel (NULL);
3791 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3792 emitcode ("cpl", "a");
3793 emitcode ("inc", "a");
3794 emitcode ("", "%05d$:", (lbl->key + 100));
3796 /* now the multiplication */
3797 emitcode ("div", "ab");
3798 /* we are interested in the lower order
3800 lbl = newiTempLabel (NULL);
3801 emitcode ("pop", "acc");
3802 /* if there was an over flow we don't
3803 adjust the sign of the result */
3804 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3805 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3807 emitcode ("clr", "a");
3808 emitcode ("subb", "a,b");
3809 emitcode ("mov", "b,a");
3810 emitcode ("", "%05d$:", (lbl->key + 100));
3812 /* now we are done */
3813 aopPut (AOP (result), "b", 0);
3817 /*-----------------------------------------------------------------*/
3818 /* genMod - generates code for division */
3819 /*-----------------------------------------------------------------*/
3823 operand *left = IC_LEFT (ic);
3824 operand *right = IC_RIGHT (ic);
3825 operand *result = IC_RESULT (ic);
3827 D(emitcode (";", "genMod"));
3829 /* assign the amsops */
3830 aopOp (left, ic, FALSE);
3831 aopOp (right, ic, FALSE);
3832 aopOp (result, ic, TRUE);
3834 /* special cases first */
3836 if (AOP_TYPE (left) == AOP_CRY &&
3837 AOP_TYPE (right) == AOP_CRY)
3839 genModbits (left, right, result);
3843 /* if both are of size == 1 */
3844 if (AOP_SIZE (left) == 1 &&
3845 AOP_SIZE (right) == 1)
3847 genModOneByte (left, right, result);
3851 /* should have been converted to function call */
3855 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3856 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3857 freeAsmop (result, NULL, ic, TRUE);
3860 /*-----------------------------------------------------------------*/
3861 /* genIfxJump :- will create a jump depending on the ifx */
3862 /*-----------------------------------------------------------------*/
3864 genIfxJump (iCode * ic, char *jval)
3867 symbol *tlbl = newiTempLabel (NULL);
3870 D(emitcode (";", "genIfxJump"));
3872 /* if true label then we jump if condition
3876 jlbl = IC_TRUE (ic);
3877 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3878 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3882 /* false label is present */
3883 jlbl = IC_FALSE (ic);
3884 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3885 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3887 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3888 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3890 emitcode (inst, "%05d$", tlbl->key + 100);
3891 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3892 emitcode ("", "%05d$:", tlbl->key + 100);
3894 /* mark the icode as generated */
3898 /*-----------------------------------------------------------------*/
3899 /* genCmp :- greater or less than comparison */
3900 /*-----------------------------------------------------------------*/
3902 genCmp (operand * left, operand * right,
3903 operand * result, iCode * ifx, int sign, iCode *ic)
3905 int size, offset = 0;
3906 unsigned long lit = 0L;
3908 D(emitcode (";", "genCmp"));
3910 /* if left & right are bit variables */
3911 if (AOP_TYPE (left) == AOP_CRY &&
3912 AOP_TYPE (right) == AOP_CRY)
3914 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3915 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3919 /* subtract right from left if at the
3920 end the carry flag is set then we know that
3921 left is greater than right */
3922 size = max (AOP_SIZE (left), AOP_SIZE (right));
3924 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3925 if ((size == 1) && !sign &&
3926 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3928 symbol *lbl = newiTempLabel (NULL);
3929 emitcode ("cjne", "%s,%s,%05d$",
3930 aopGet (AOP (left), offset, FALSE, FALSE),
3931 aopGet (AOP (right), offset, FALSE, FALSE),
3933 emitcode ("", "%05d$:", lbl->key + 100);
3937 if (AOP_TYPE (right) == AOP_LIT)
3939 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3940 /* optimize if(x < 0) or if(x >= 0) */
3949 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3950 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3952 genIfxJump (ifx, "acc.7");
3956 emitcode ("rlc", "a");
3964 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3965 if (sign && size == 0)
3967 emitcode ("xrl", "a,#0x80");
3968 if (AOP_TYPE (right) == AOP_LIT)
3970 unsigned long lit = (unsigned long)
3971 floatFromVal (AOP (right)->aopu.aop_lit);
3972 emitcode ("subb", "a,#0x%02x",
3973 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3977 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3978 emitcode ("xrl", "b,#0x80");
3979 emitcode ("subb", "a,b");
3983 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3989 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3990 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3991 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3997 /* if the result is used in the next
3998 ifx conditional branch then generate
3999 code a little differently */
4001 genIfxJump (ifx, "c");
4004 /* leave the result in acc */
4008 /*-----------------------------------------------------------------*/
4009 /* genCmpGt :- greater than comparison */
4010 /*-----------------------------------------------------------------*/
4012 genCmpGt (iCode * ic, iCode * ifx)
4014 operand *left, *right, *result;
4015 sym_link *letype, *retype;
4018 D(emitcode (";", "genCmpGt"));
4020 left = IC_LEFT (ic);
4021 right = IC_RIGHT (ic);
4022 result = IC_RESULT (ic);
4024 letype = getSpec (operandType (left));
4025 retype = getSpec (operandType (right));
4026 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4027 /* assign the amsops */
4028 aopOp (left, ic, FALSE);
4029 aopOp (right, ic, FALSE);
4030 aopOp (result, ic, TRUE);
4032 genCmp (right, left, result, ifx, sign,ic);
4034 freeAsmop (result, NULL, ic, TRUE);
4037 /*-----------------------------------------------------------------*/
4038 /* genCmpLt - less than comparisons */
4039 /*-----------------------------------------------------------------*/
4041 genCmpLt (iCode * ic, iCode * ifx)
4043 operand *left, *right, *result;
4044 sym_link *letype, *retype;
4047 D(emitcode (";", "genCmpLt"));
4049 left = IC_LEFT (ic);
4050 right = IC_RIGHT (ic);
4051 result = IC_RESULT (ic);
4053 letype = getSpec (operandType (left));
4054 retype = getSpec (operandType (right));
4055 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4057 /* assign the amsops */
4058 aopOp (left, ic, FALSE);
4059 aopOp (right, ic, FALSE);
4060 aopOp (result, ic, TRUE);
4062 genCmp (left, right, result, ifx, sign,ic);
4064 freeAsmop (result, NULL, ic, TRUE);
4067 /*-----------------------------------------------------------------*/
4068 /* gencjneshort - compare and jump if not equal */
4069 /*-----------------------------------------------------------------*/
4071 gencjneshort (operand * left, operand * right, symbol * lbl)
4073 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4075 unsigned long lit = 0L;
4077 /* if the left side is a literal or
4078 if the right is in a pointer register and left
4080 if ((AOP_TYPE (left) == AOP_LIT) ||
4081 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4087 if (AOP_TYPE (right) == AOP_LIT)
4088 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4090 /* if the right side is a literal then anything goes */
4091 if (AOP_TYPE (right) == AOP_LIT &&
4092 AOP_TYPE (left) != AOP_DIR)
4096 emitcode ("cjne", "%s,%s,%05d$",
4097 aopGet (AOP (left), offset, FALSE, FALSE),
4098 aopGet (AOP (right), offset, FALSE, FALSE),
4104 /* if the right side is in a register or in direct space or
4105 if the left is a pointer register & right is not */
4106 else if (AOP_TYPE (right) == AOP_REG ||
4107 AOP_TYPE (right) == AOP_DIR ||
4108 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4109 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4113 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4114 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4115 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4116 emitcode ("jnz", "%05d$", lbl->key + 100);
4118 emitcode ("cjne", "a,%s,%05d$",
4119 aopGet (AOP (right), offset, FALSE, TRUE),
4126 /* right is a pointer reg need both a & b */
4129 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4130 if (strcmp (l, "b"))
4131 emitcode ("mov", "b,%s", l);
4132 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4133 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4139 /*-----------------------------------------------------------------*/
4140 /* gencjne - compare and jump if not equal */
4141 /*-----------------------------------------------------------------*/
4143 gencjne (operand * left, operand * right, symbol * lbl)
4145 symbol *tlbl = newiTempLabel (NULL);
4147 gencjneshort (left, right, lbl);
4149 emitcode ("mov", "a,%s", one);
4150 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4151 emitcode ("", "%05d$:", lbl->key + 100);
4152 emitcode ("clr", "a");
4153 emitcode ("", "%05d$:", tlbl->key + 100);
4156 /*-----------------------------------------------------------------*/
4157 /* genCmpEq - generates code for equal to */
4158 /*-----------------------------------------------------------------*/
4160 genCmpEq (iCode * ic, iCode * ifx)
4162 operand *left, *right, *result;
4164 D(emitcode (";", "genCmpEq"));
4166 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4167 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4168 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4170 /* if literal, literal on the right or
4171 if the right is in a pointer register and left
4173 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4174 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4176 operand *t = IC_RIGHT (ic);
4177 IC_RIGHT (ic) = IC_LEFT (ic);
4181 if (ifx && !AOP_SIZE (result))
4184 /* if they are both bit variables */
4185 if (AOP_TYPE (left) == AOP_CRY &&
4186 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4188 if (AOP_TYPE (right) == AOP_LIT)
4190 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4193 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4194 emitcode ("cpl", "c");
4198 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4202 emitcode ("clr", "c");
4204 /* AOP_TYPE(right) == AOP_CRY */
4208 symbol *lbl = newiTempLabel (NULL);
4209 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4210 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4211 emitcode ("cpl", "c");
4212 emitcode ("", "%05d$:", (lbl->key + 100));
4214 /* if true label then we jump if condition
4216 tlbl = newiTempLabel (NULL);
4219 emitcode ("jnc", "%05d$", tlbl->key + 100);
4220 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4224 emitcode ("jc", "%05d$", tlbl->key + 100);
4225 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4227 emitcode ("", "%05d$:", tlbl->key + 100);
4231 tlbl = newiTempLabel (NULL);
4232 gencjneshort (left, right, tlbl);
4235 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4236 emitcode ("", "%05d$:", tlbl->key + 100);
4240 symbol *lbl = newiTempLabel (NULL);
4241 emitcode ("sjmp", "%05d$", lbl->key + 100);
4242 emitcode ("", "%05d$:", tlbl->key + 100);
4243 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4244 emitcode ("", "%05d$:", lbl->key + 100);
4247 /* mark the icode as generated */
4252 /* if they are both bit variables */
4253 if (AOP_TYPE (left) == AOP_CRY &&
4254 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4256 if (AOP_TYPE (right) == AOP_LIT)
4258 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4262 emitcode ("cpl", "c");
4266 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4270 emitcode ("clr", "c");
4272 /* AOP_TYPE(right) == AOP_CRY */
4276 symbol *lbl = newiTempLabel (NULL);
4277 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4278 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4279 emitcode ("cpl", "c");
4280 emitcode ("", "%05d$:", (lbl->key + 100));
4283 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4290 genIfxJump (ifx, "c");
4293 /* if the result is used in an arithmetic operation
4294 then put the result in place */
4299 gencjne (left, right, newiTempLabel (NULL));
4300 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4302 aopPut (AOP (result), "a", 0);
4307 genIfxJump (ifx, "a");
4310 /* if the result is used in an arithmetic operation
4311 then put the result in place */
4312 if (AOP_TYPE (result) != AOP_CRY)
4314 /* leave the result in acc */
4318 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4319 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4320 freeAsmop (result, NULL, ic, TRUE);
4323 /*-----------------------------------------------------------------*/
4324 /* ifxForOp - returns the icode containing the ifx for operand */
4325 /*-----------------------------------------------------------------*/
4327 ifxForOp (operand * op, iCode * ic)
4329 /* if true symbol then needs to be assigned */
4330 if (IS_TRUE_SYMOP (op))
4333 /* if this has register type condition and
4334 the next instruction is ifx with the same operand
4335 and live to of the operand is upto the ifx only then */
4337 ic->next->op == IFX &&
4338 IC_COND (ic->next)->key == op->key &&
4339 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4345 /*-----------------------------------------------------------------*/
4346 /* hasInc - operand is incremented before any other use */
4347 /*-----------------------------------------------------------------*/
4349 hasInc (operand *op, iCode *ic,int osize)
4351 sym_link *type = operandType(op);
4352 sym_link *retype = getSpec (type);
4353 iCode *lic = ic->next;
4356 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4357 if (!IS_SYMOP(op)) return NULL;
4359 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4360 if (osize != (isize = getSize(type->next))) return NULL;
4362 /* if operand of the form op = op + <sizeof *op> */
4363 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4364 isOperandEqual(IC_RESULT(lic),op) &&
4365 isOperandLiteral(IC_RIGHT(lic)) &&
4366 operandLitValue(IC_RIGHT(lic)) == isize) {
4369 /* if the operand used or deffed */
4370 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4373 /* if GOTO or IFX */
4374 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4380 /*-----------------------------------------------------------------*/
4381 /* genAndOp - for && operation */
4382 /*-----------------------------------------------------------------*/
4384 genAndOp (iCode * ic)
4386 operand *left, *right, *result;
4389 D(emitcode (";", "genAndOp"));
4391 /* note here that && operations that are in an
4392 if statement are taken away by backPatchLabels
4393 only those used in arthmetic operations remain */
4394 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4395 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4396 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4398 /* if both are bit variables */
4399 if (AOP_TYPE (left) == AOP_CRY &&
4400 AOP_TYPE (right) == AOP_CRY)
4402 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4403 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4408 tlbl = newiTempLabel (NULL);
4410 emitcode ("jz", "%05d$", tlbl->key + 100);
4412 emitcode ("", "%05d$:", tlbl->key + 100);
4416 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4417 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4418 freeAsmop (result, NULL, ic, TRUE);
4422 /*-----------------------------------------------------------------*/
4423 /* genOrOp - for || operation */
4424 /*-----------------------------------------------------------------*/
4426 genOrOp (iCode * ic)
4428 operand *left, *right, *result;
4431 D(emitcode (";", "genOrOp"));
4433 /* note here that || operations that are in an
4434 if statement are taken away by backPatchLabels
4435 only those used in arthmetic operations remain */
4436 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4437 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4438 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4440 /* if both are bit variables */
4441 if (AOP_TYPE (left) == AOP_CRY &&
4442 AOP_TYPE (right) == AOP_CRY)
4444 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4445 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4450 tlbl = newiTempLabel (NULL);
4452 emitcode ("jnz", "%05d$", tlbl->key + 100);
4454 emitcode ("", "%05d$:", tlbl->key + 100);
4458 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4459 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4460 freeAsmop (result, NULL, ic, TRUE);
4463 /*-----------------------------------------------------------------*/
4464 /* isLiteralBit - test if lit == 2^n */
4465 /*-----------------------------------------------------------------*/
4467 isLiteralBit (unsigned long lit)
4469 unsigned long pw[32] =
4470 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4471 0x100L, 0x200L, 0x400L, 0x800L,
4472 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4473 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4474 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4475 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4476 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4479 for (idx = 0; idx < 32; idx++)
4485 /*-----------------------------------------------------------------*/
4486 /* continueIfTrue - */
4487 /*-----------------------------------------------------------------*/
4489 continueIfTrue (iCode * ic)
4492 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4496 /*-----------------------------------------------------------------*/
4498 /*-----------------------------------------------------------------*/
4500 jumpIfTrue (iCode * ic)
4503 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4507 /*-----------------------------------------------------------------*/
4508 /* jmpTrueOrFalse - */
4509 /*-----------------------------------------------------------------*/
4511 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4513 // ugly but optimized by peephole
4516 symbol *nlbl = newiTempLabel (NULL);
4517 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4518 emitcode ("", "%05d$:", tlbl->key + 100);
4519 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4520 emitcode ("", "%05d$:", nlbl->key + 100);
4524 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4525 emitcode ("", "%05d$:", tlbl->key + 100);
4530 /*-----------------------------------------------------------------*/
4531 /* genAnd - code for and */
4532 /*-----------------------------------------------------------------*/
4534 genAnd (iCode * ic, iCode * ifx)
4536 operand *left, *right, *result;
4537 int size, offset = 0;
4538 unsigned long lit = 0L;
4542 D(emitcode (";", "genAnd"));
4544 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4545 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4546 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4549 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4551 AOP_TYPE (left), AOP_TYPE (right));
4552 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4554 AOP_SIZE (left), AOP_SIZE (right));
4557 /* if left is a literal & right is not then exchange them */
4558 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4559 AOP_NEEDSACC (left))
4561 operand *tmp = right;
4566 /* if result = right then exchange them */
4567 if (sameRegs (AOP (result), AOP (right)))
4569 operand *tmp = right;
4574 /* if right is bit then exchange them */
4575 if (AOP_TYPE (right) == AOP_CRY &&
4576 AOP_TYPE (left) != AOP_CRY)
4578 operand *tmp = right;
4582 if (AOP_TYPE (right) == AOP_LIT)
4583 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4585 size = AOP_SIZE (result);
4588 // result = bit & yy;
4589 if (AOP_TYPE (left) == AOP_CRY)
4591 // c = bit & literal;
4592 if (AOP_TYPE (right) == AOP_LIT)
4596 if (size && sameRegs (AOP (result), AOP (left)))
4599 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4604 if (size && (AOP_TYPE (result) == AOP_CRY))
4606 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4609 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4614 emitcode ("clr", "c");
4619 if (AOP_TYPE (right) == AOP_CRY)
4622 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4623 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4628 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4630 emitcode ("rrc", "a");
4631 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4639 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4640 genIfxJump (ifx, "c");
4644 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4645 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4646 if ((AOP_TYPE (right) == AOP_LIT) &&
4647 (AOP_TYPE (result) == AOP_CRY) &&
4648 (AOP_TYPE (left) != AOP_CRY))
4650 int posbit = isLiteralBit (lit);
4655 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4658 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4664 sprintf (buffer, "acc.%d", posbit & 0x07);
4665 genIfxJump (ifx, buffer);
4672 symbol *tlbl = newiTempLabel (NULL);
4673 int sizel = AOP_SIZE (left);
4675 emitcode ("setb", "c");
4678 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4680 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4682 if ((posbit = isLiteralBit (bytelit)) != 0)
4683 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4686 if (bytelit != 0x0FFL)
4687 emitcode ("anl", "a,%s",
4688 aopGet (AOP (right), offset, FALSE, TRUE));
4689 emitcode ("jnz", "%05d$", tlbl->key + 100);
4694 // bit = left & literal
4697 emitcode ("clr", "c");
4698 emitcode ("", "%05d$:", tlbl->key + 100);
4700 // if(left & literal)
4704 jmpTrueOrFalse (ifx, tlbl);
4712 /* if left is same as result */
4713 if (sameRegs (AOP (result), AOP (left)))
4715 for (; size--; offset++)
4717 if (AOP_TYPE (right) == AOP_LIT)
4719 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4721 else if (bytelit == 0)
4722 aopPut (AOP (result), zero, offset);
4723 else if (IS_AOP_PREG (result))
4725 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4726 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4727 aopPut (AOP (result), "a", offset);
4730 emitcode ("anl", "%s,%s",
4731 aopGet (AOP (left), offset, FALSE, TRUE),
4732 aopGet (AOP (right), offset, FALSE, FALSE));
4736 if (AOP_TYPE (left) == AOP_ACC)
4737 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4740 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4741 if (IS_AOP_PREG (result))
4743 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4744 aopPut (AOP (result), "a", offset);
4748 emitcode ("anl", "%s,a",
4749 aopGet (AOP (left), offset, FALSE, TRUE));
4756 // left & result in different registers
4757 if (AOP_TYPE (result) == AOP_CRY)
4760 // if(size), result in bit
4761 // if(!size && ifx), conditional oper: if(left & right)
4762 symbol *tlbl = newiTempLabel (NULL);
4763 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4765 emitcode ("setb", "c");
4768 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4769 emitcode ("anl", "a,%s",
4770 aopGet (AOP (right), offset, FALSE, FALSE));
4772 if (AOP_TYPE(left)==AOP_ACC) {
4773 emitcode("mov", "b,a");
4774 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4775 emitcode("anl", "a,b");
4777 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4778 emitcode ("anl", "a,%s",
4779 aopGet (AOP (left), offset, FALSE, FALSE));
4782 emitcode ("jnz", "%05d$", tlbl->key + 100);
4788 emitcode ("", "%05d$:", tlbl->key + 100);
4792 jmpTrueOrFalse (ifx, tlbl);
4796 for (; (size--); offset++)
4799 // result = left & right
4800 if (AOP_TYPE (right) == AOP_LIT)
4802 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4804 aopPut (AOP (result),
4805 aopGet (AOP (left), offset, FALSE, FALSE),
4809 else if (bytelit == 0)
4811 aopPut (AOP (result), zero, offset);
4815 // faster than result <- left, anl result,right
4816 // and better if result is SFR
4817 if (AOP_TYPE (left) == AOP_ACC)
4818 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4821 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4822 emitcode ("anl", "a,%s",
4823 aopGet (AOP (left), offset, FALSE, FALSE));
4825 aopPut (AOP (result), "a", offset);
4831 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4832 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4833 freeAsmop (result, NULL, ic, TRUE);
4836 /*-----------------------------------------------------------------*/
4837 /* genOr - code for or */
4838 /*-----------------------------------------------------------------*/
4840 genOr (iCode * ic, iCode * ifx)
4842 operand *left, *right, *result;
4843 int size, offset = 0;
4844 unsigned long lit = 0L;
4846 D(emitcode (";", "genOr"));
4848 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4849 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4850 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4853 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4855 AOP_TYPE (left), AOP_TYPE (right));
4856 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4858 AOP_SIZE (left), AOP_SIZE (right));
4861 /* if left is a literal & right is not then exchange them */
4862 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4863 AOP_NEEDSACC (left))
4865 operand *tmp = right;
4870 /* if result = right then exchange them */
4871 if (sameRegs (AOP (result), AOP (right)))
4873 operand *tmp = right;
4878 /* if right is bit then exchange them */
4879 if (AOP_TYPE (right) == AOP_CRY &&
4880 AOP_TYPE (left) != AOP_CRY)
4882 operand *tmp = right;
4886 if (AOP_TYPE (right) == AOP_LIT)
4887 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4889 size = AOP_SIZE (result);
4893 if (AOP_TYPE (left) == AOP_CRY)
4895 if (AOP_TYPE (right) == AOP_LIT)
4897 // c = bit & literal;
4900 // lit != 0 => result = 1
4901 if (AOP_TYPE (result) == AOP_CRY)
4904 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4906 continueIfTrue (ifx);
4909 emitcode ("setb", "c");
4913 // lit == 0 => result = left
4914 if (size && sameRegs (AOP (result), AOP (left)))
4916 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4921 if (AOP_TYPE (right) == AOP_CRY)
4924 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4925 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4930 symbol *tlbl = newiTempLabel (NULL);
4931 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4932 emitcode ("setb", "c");
4933 emitcode ("jb", "%s,%05d$",
4934 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4936 emitcode ("jnz", "%05d$", tlbl->key + 100);
4937 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4939 jmpTrueOrFalse (ifx, tlbl);
4945 emitcode ("", "%05d$:", tlbl->key + 100);
4954 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4955 genIfxJump (ifx, "c");
4959 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4960 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4961 if ((AOP_TYPE (right) == AOP_LIT) &&
4962 (AOP_TYPE (result) == AOP_CRY) &&
4963 (AOP_TYPE (left) != AOP_CRY))
4969 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4971 continueIfTrue (ifx);
4976 // lit = 0, result = boolean(left)
4978 emitcode ("setb", "c");
4982 symbol *tlbl = newiTempLabel (NULL);
4983 emitcode ("jnz", "%05d$", tlbl->key + 100);
4985 emitcode ("", "%05d$:", tlbl->key + 100);
4989 genIfxJump (ifx, "a");
4997 /* if left is same as result */
4998 if (sameRegs (AOP (result), AOP (left)))
5000 for (; size--; offset++)
5002 if (AOP_TYPE (right) == AOP_LIT)
5004 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5006 else if (IS_AOP_PREG (left))
5008 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5009 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5010 aopPut (AOP (result), "a", offset);
5013 emitcode ("orl", "%s,%s",
5014 aopGet (AOP (left), offset, FALSE, TRUE),
5015 aopGet (AOP (right), offset, FALSE, FALSE));
5019 if (AOP_TYPE (left) == AOP_ACC)
5020 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5023 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5024 if (IS_AOP_PREG (left))
5026 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5027 aopPut (AOP (result), "a", offset);
5030 emitcode ("orl", "%s,a",
5031 aopGet (AOP (left), offset, FALSE, TRUE));
5038 // left & result in different registers
5039 if (AOP_TYPE (result) == AOP_CRY)
5042 // if(size), result in bit
5043 // if(!size && ifx), conditional oper: if(left | right)
5044 symbol *tlbl = newiTempLabel (NULL);
5045 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5047 emitcode ("setb", "c");
5050 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5051 emitcode ("orl", "a,%s",
5052 aopGet (AOP (right), offset, FALSE, FALSE));
5054 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5055 emitcode ("orl", "a,%s",
5056 aopGet (AOP (left), offset, FALSE, FALSE));
5058 emitcode ("jnz", "%05d$", tlbl->key + 100);
5064 emitcode ("", "%05d$:", tlbl->key + 100);
5068 jmpTrueOrFalse (ifx, tlbl);
5071 for (; (size--); offset++)
5074 // result = left & right
5075 if (AOP_TYPE (right) == AOP_LIT)
5077 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5079 aopPut (AOP (result),
5080 aopGet (AOP (left), offset, FALSE, FALSE),
5085 // faster than result <- left, anl result,right
5086 // and better if result is SFR
5087 if (AOP_TYPE (left) == AOP_ACC)
5088 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5091 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5092 emitcode ("orl", "a,%s",
5093 aopGet (AOP (left), offset, FALSE, FALSE));
5095 aopPut (AOP (result), "a", offset);
5100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5102 freeAsmop (result, NULL, ic, TRUE);
5105 /*-----------------------------------------------------------------*/
5106 /* genXor - code for xclusive or */
5107 /*-----------------------------------------------------------------*/
5109 genXor (iCode * ic, iCode * ifx)
5111 operand *left, *right, *result;
5112 int size, offset = 0;
5113 unsigned long lit = 0L;
5115 D(emitcode (";", "genXor"));
5117 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5118 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5119 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5122 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5124 AOP_TYPE (left), AOP_TYPE (right));
5125 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5127 AOP_SIZE (left), AOP_SIZE (right));
5130 /* if left is a literal & right is not ||
5131 if left needs acc & right does not */
5132 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5133 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5135 operand *tmp = right;
5140 /* if result = right then exchange them */
5141 if (sameRegs (AOP (result), AOP (right)))
5143 operand *tmp = right;
5148 /* if right is bit then exchange them */
5149 if (AOP_TYPE (right) == AOP_CRY &&
5150 AOP_TYPE (left) != AOP_CRY)
5152 operand *tmp = right;
5156 if (AOP_TYPE (right) == AOP_LIT)
5157 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5159 size = AOP_SIZE (result);
5163 if (AOP_TYPE (left) == AOP_CRY)
5165 if (AOP_TYPE (right) == AOP_LIT)
5167 // c = bit & literal;
5170 // lit>>1 != 0 => result = 1
5171 if (AOP_TYPE (result) == AOP_CRY)
5174 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5176 continueIfTrue (ifx);
5179 emitcode ("setb", "c");
5186 // lit == 0, result = left
5187 if (size && sameRegs (AOP (result), AOP (left)))
5189 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5193 // lit == 1, result = not(left)
5194 if (size && sameRegs (AOP (result), AOP (left)))
5196 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5201 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5202 emitcode ("cpl", "c");
5211 symbol *tlbl = newiTempLabel (NULL);
5212 if (AOP_TYPE (right) == AOP_CRY)
5215 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5219 int sizer = AOP_SIZE (right);
5221 // if val>>1 != 0, result = 1
5222 emitcode ("setb", "c");
5225 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5227 // test the msb of the lsb
5228 emitcode ("anl", "a,#0xfe");
5229 emitcode ("jnz", "%05d$", tlbl->key + 100);
5233 emitcode ("rrc", "a");
5235 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5236 emitcode ("cpl", "c");
5237 emitcode ("", "%05d$:", (tlbl->key + 100));
5244 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5245 genIfxJump (ifx, "c");
5249 if (sameRegs (AOP (result), AOP (left)))
5251 /* if left is same as result */
5252 for (; size--; offset++)
5254 if (AOP_TYPE (right) == AOP_LIT)
5256 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5258 else if (IS_AOP_PREG (left))
5260 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5261 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5262 aopPut (AOP (result), "a", offset);
5265 emitcode ("xrl", "%s,%s",
5266 aopGet (AOP (left), offset, FALSE, TRUE),
5267 aopGet (AOP (right), offset, FALSE, FALSE));
5271 if (AOP_TYPE (left) == AOP_ACC)
5272 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5275 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5276 if (IS_AOP_PREG (left))
5278 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5279 aopPut (AOP (result), "a", offset);
5282 emitcode ("xrl", "%s,a",
5283 aopGet (AOP (left), offset, FALSE, TRUE));
5290 // left & result in different registers
5291 if (AOP_TYPE (result) == AOP_CRY)
5294 // if(size), result in bit
5295 // if(!size && ifx), conditional oper: if(left ^ right)
5296 symbol *tlbl = newiTempLabel (NULL);
5297 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5299 emitcode ("setb", "c");
5302 if ((AOP_TYPE (right) == AOP_LIT) &&
5303 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5305 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5309 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5310 emitcode ("xrl", "a,%s",
5311 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, FALSE));
5318 emitcode ("jnz", "%05d$", tlbl->key + 100);
5324 emitcode ("", "%05d$:", tlbl->key + 100);
5328 jmpTrueOrFalse (ifx, tlbl);
5331 for (; (size--); offset++)
5334 // result = left & right
5335 if (AOP_TYPE (right) == AOP_LIT)
5337 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5339 aopPut (AOP (result),
5340 aopGet (AOP (left), offset, FALSE, FALSE),
5345 // faster than result <- left, anl result,right
5346 // and better if result is SFR
5347 if (AOP_TYPE (left) == AOP_ACC)
5348 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5351 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5352 emitcode ("xrl", "a,%s",
5353 aopGet (AOP (left), offset, FALSE, TRUE));
5355 aopPut (AOP (result), "a", offset);
5360 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5361 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362 freeAsmop (result, NULL, ic, TRUE);
5365 /*-----------------------------------------------------------------*/
5366 /* genInline - write the inline code out */
5367 /*-----------------------------------------------------------------*/
5369 genInline (iCode * ic)
5371 char *buffer, *bp, *bp1;
5373 D(emitcode (";", "genInline"));
5375 _G.inLine += (!options.asmpeep);
5377 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5378 strcpy (buffer, IC_INLINE (ic));
5380 /* emit each line as a code */
5405 /* emitcode("",buffer); */
5406 _G.inLine -= (!options.asmpeep);
5409 /*-----------------------------------------------------------------*/
5410 /* genRRC - rotate right with carry */
5411 /*-----------------------------------------------------------------*/
5415 operand *left, *result;
5416 int size, offset = 0;
5419 D(emitcode (";", "genRRC"));
5421 /* rotate right with carry */
5422 left = IC_LEFT (ic);
5423 result = IC_RESULT (ic);
5424 aopOp (left, ic, FALSE);
5425 aopOp (result, ic, FALSE);
5427 /* move it to the result */
5428 size = AOP_SIZE (result);
5430 if (size == 1) { /* special case for 1 byte */
5431 l = aopGet (AOP (left), offset, FALSE, FALSE);
5433 emitcode ("rr", "a");
5439 l = aopGet (AOP (left), offset, FALSE, FALSE);
5441 emitcode ("rrc", "a");
5442 if (AOP_SIZE (result) > 1)
5443 aopPut (AOP (result), "a", offset--);
5445 /* now we need to put the carry into the
5446 highest order byte of the result */
5447 if (AOP_SIZE (result) > 1)
5449 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5452 emitcode ("mov", "acc.7,c");
5454 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5455 freeAsmop (left, NULL, ic, TRUE);
5456 freeAsmop (result, NULL, ic, TRUE);
5459 /*-----------------------------------------------------------------*/
5460 /* genRLC - generate code for rotate left with carry */
5461 /*-----------------------------------------------------------------*/
5465 operand *left, *result;
5466 int size, offset = 0;
5469 D(emitcode (";", "genRLC"));
5471 /* rotate right with carry */
5472 left = IC_LEFT (ic);
5473 result = IC_RESULT (ic);
5474 aopOp (left, ic, FALSE);
5475 aopOp (result, ic, FALSE);
5477 /* move it to the result */
5478 size = AOP_SIZE (result);
5482 l = aopGet (AOP (left), offset, FALSE, FALSE);
5484 if (size == 0) { /* special case for 1 byte */
5488 emitcode ("add", "a,acc");
5489 if (AOP_SIZE (result) > 1)
5490 aopPut (AOP (result), "a", offset++);
5493 l = aopGet (AOP (left), offset, FALSE, FALSE);
5495 emitcode ("rlc", "a");
5496 if (AOP_SIZE (result) > 1)
5497 aopPut (AOP (result), "a", offset++);
5500 /* now we need to put the carry into the
5501 highest order byte of the result */
5502 if (AOP_SIZE (result) > 1)
5504 l = aopGet (AOP (result), 0, FALSE, FALSE);
5507 emitcode ("mov", "acc.0,c");
5509 aopPut (AOP (result), "a", 0);
5510 freeAsmop (left, NULL, ic, TRUE);
5511 freeAsmop (result, NULL, ic, TRUE);
5514 /*-----------------------------------------------------------------*/
5515 /* genGetHbit - generates code get highest order bit */
5516 /*-----------------------------------------------------------------*/
5518 genGetHbit (iCode * ic)
5520 operand *left, *result;
5522 D(emitcode (";", "genGetHbit"));
5524 left = IC_LEFT (ic);
5525 result = IC_RESULT (ic);
5526 aopOp (left, ic, FALSE);
5527 aopOp (result, ic, FALSE);
5529 /* get the highest order byte into a */
5530 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5531 if (AOP_TYPE (result) == AOP_CRY)
5533 emitcode ("rlc", "a");
5538 emitcode ("rl", "a");
5539 emitcode ("anl", "a,#0x01");
5544 freeAsmop (left, NULL, ic, TRUE);
5545 freeAsmop (result, NULL, ic, TRUE);
5548 /*-----------------------------------------------------------------*/
5549 /* AccRol - rotate left accumulator by known count */
5550 /*-----------------------------------------------------------------*/
5552 AccRol (int shCount)
5554 shCount &= 0x0007; // shCount : 0..7
5561 emitcode ("rl", "a");
5564 emitcode ("rl", "a");
5565 emitcode ("rl", "a");
5568 emitcode ("swap", "a");
5569 emitcode ("rr", "a");
5572 emitcode ("swap", "a");
5575 emitcode ("swap", "a");
5576 emitcode ("rl", "a");
5579 emitcode ("rr", "a");
5580 emitcode ("rr", "a");
5583 emitcode ("rr", "a");
5588 /*-----------------------------------------------------------------*/
5589 /* AccLsh - left shift accumulator by known count */
5590 /*-----------------------------------------------------------------*/
5592 AccLsh (int shCount)
5597 emitcode ("add", "a,acc");
5598 else if (shCount == 2)
5600 emitcode ("add", "a,acc");
5601 emitcode ("add", "a,acc");
5605 /* rotate left accumulator */
5607 /* and kill the lower order bits */
5608 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5613 /*-----------------------------------------------------------------*/
5614 /* AccRsh - right shift accumulator by known count */
5615 /*-----------------------------------------------------------------*/
5617 AccRsh (int shCount)
5624 emitcode ("rrc", "a");
5628 /* rotate right accumulator */
5629 AccRol (8 - shCount);
5630 /* and kill the higher order bits */
5631 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5636 /*-----------------------------------------------------------------*/
5637 /* AccSRsh - signed right shift accumulator by known count */
5638 /*-----------------------------------------------------------------*/
5640 AccSRsh (int shCount)
5647 emitcode ("mov", "c,acc.7");
5648 emitcode ("rrc", "a");
5650 else if (shCount == 2)
5652 emitcode ("mov", "c,acc.7");
5653 emitcode ("rrc", "a");
5654 emitcode ("mov", "c,acc.7");
5655 emitcode ("rrc", "a");
5659 tlbl = newiTempLabel (NULL);
5660 /* rotate right accumulator */
5661 AccRol (8 - shCount);
5662 /* and kill the higher order bits */
5663 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5664 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5665 emitcode ("orl", "a,#0x%02x",
5666 (unsigned char) ~SRMask[shCount]);
5667 emitcode ("", "%05d$:", tlbl->key + 100);
5672 /*-----------------------------------------------------------------*/
5673 /* shiftR1Left2Result - shift right one byte from left to result */
5674 /*-----------------------------------------------------------------*/
5676 shiftR1Left2Result (operand * left, int offl,
5677 operand * result, int offr,
5678 int shCount, int sign)
5680 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5681 /* shift right accumulator */
5686 aopPut (AOP (result), "a", offr);
5689 /*-----------------------------------------------------------------*/
5690 /* shiftL1Left2Result - shift left one byte from left to result */
5691 /*-----------------------------------------------------------------*/
5693 shiftL1Left2Result (operand * left, int offl,
5694 operand * result, int offr, int shCount)
5697 l = aopGet (AOP (left), offl, FALSE, FALSE);
5699 /* shift left accumulator */
5701 aopPut (AOP (result), "a", offr);
5704 /*-----------------------------------------------------------------*/
5705 /* movLeft2Result - move byte from left to result */
5706 /*-----------------------------------------------------------------*/
5708 movLeft2Result (operand * left, int offl,
5709 operand * result, int offr, int sign)
5712 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5714 l = aopGet (AOP (left), offl, FALSE, FALSE);
5716 if (*l == '@' && (IS_AOP_PREG (result)))
5718 emitcode ("mov", "a,%s", l);
5719 aopPut (AOP (result), "a", offr);
5724 aopPut (AOP (result), l, offr);
5727 /* MSB sign in acc.7 ! */
5728 if (getDataSize (left) == offl + 1)
5730 emitcode ("mov", "a,%s", l);
5731 aopPut (AOP (result), "a", offr);
5738 /*-----------------------------------------------------------------*/
5739 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5740 /*-----------------------------------------------------------------*/
5744 emitcode ("rrc", "a");
5745 emitcode ("xch", "a,%s", x);
5746 emitcode ("rrc", "a");
5747 emitcode ("xch", "a,%s", x);
5750 /*-----------------------------------------------------------------*/
5751 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5752 /*-----------------------------------------------------------------*/
5756 emitcode ("xch", "a,%s", x);
5757 emitcode ("rlc", "a");
5758 emitcode ("xch", "a,%s", x);
5759 emitcode ("rlc", "a");
5762 /*-----------------------------------------------------------------*/
5763 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5764 /*-----------------------------------------------------------------*/
5768 emitcode ("xch", "a,%s", x);
5769 emitcode ("add", "a,acc");
5770 emitcode ("xch", "a,%s", x);
5771 emitcode ("rlc", "a");
5774 /*-----------------------------------------------------------------*/
5775 /* AccAXLsh - left shift a:x by known count (0..7) */
5776 /*-----------------------------------------------------------------*/
5778 AccAXLsh (char *x, int shCount)
5793 case 5: // AAAAABBB:CCCCCDDD
5795 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5797 emitcode ("anl", "a,#0x%02x",
5798 SLMask[shCount]); // BBB00000:CCCCCDDD
5800 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5802 AccRol (shCount); // DDDCCCCC:BBB00000
5804 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5806 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5808 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5810 emitcode ("anl", "a,#0x%02x",
5811 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5813 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5815 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5818 case 6: // AAAAAABB:CCCCCCDD
5819 emitcode ("anl", "a,#0x%02x",
5820 SRMask[shCount]); // 000000BB:CCCCCCDD
5821 emitcode ("mov", "c,acc.0"); // c = B
5822 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5824 AccAXRrl1 (x); // BCCCCCCD:D000000B
5825 AccAXRrl1 (x); // BBCCCCCC:DD000000
5827 emitcode("rrc","a");
5828 emitcode("xch","a,%s", x);
5829 emitcode("rrc","a");
5830 emitcode("mov","c,acc.0"); //<< get correct bit
5831 emitcode("xch","a,%s", x);
5833 emitcode("rrc","a");
5834 emitcode("xch","a,%s", x);
5835 emitcode("rrc","a");
5836 emitcode("xch","a,%s", x);
5839 case 7: // a:x <<= 7
5841 emitcode ("anl", "a,#0x%02x",
5842 SRMask[shCount]); // 0000000B:CCCCCCCD
5844 emitcode ("mov", "c,acc.0"); // c = B
5846 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5848 AccAXRrl1 (x); // BCCCCCCC:D0000000
5856 /*-----------------------------------------------------------------*/
5857 /* AccAXRsh - right shift a:x known count (0..7) */
5858 /*-----------------------------------------------------------------*/
5860 AccAXRsh (char *x, int shCount)
5868 AccAXRrl1 (x); // 0->a:x
5873 AccAXRrl1 (x); // 0->a:x
5876 AccAXRrl1 (x); // 0->a:x
5881 case 5: // AAAAABBB:CCCCCDDD = a:x
5883 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5885 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5887 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5889 emitcode ("anl", "a,#0x%02x",
5890 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5892 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5894 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5896 emitcode ("anl", "a,#0x%02x",
5897 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5899 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5901 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5903 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5906 case 6: // AABBBBBB:CCDDDDDD
5908 emitcode ("mov", "c,acc.7");
5909 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5911 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5913 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5915 emitcode ("anl", "a,#0x%02x",
5916 SRMask[shCount]); // 000000AA:BBBBBBCC
5919 case 7: // ABBBBBBB:CDDDDDDD
5921 emitcode ("mov", "c,acc.7"); // c = A
5923 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5925 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5927 emitcode ("anl", "a,#0x%02x",
5928 SRMask[shCount]); // 0000000A:BBBBBBBC
5936 /*-----------------------------------------------------------------*/
5937 /* AccAXRshS - right shift signed a:x known count (0..7) */
5938 /*-----------------------------------------------------------------*/
5940 AccAXRshS (char *x, int shCount)
5948 emitcode ("mov", "c,acc.7");
5949 AccAXRrl1 (x); // s->a:x
5953 emitcode ("mov", "c,acc.7");
5954 AccAXRrl1 (x); // s->a:x
5956 emitcode ("mov", "c,acc.7");
5957 AccAXRrl1 (x); // s->a:x
5962 case 5: // AAAAABBB:CCCCCDDD = a:x
5964 tlbl = newiTempLabel (NULL);
5965 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5967 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5969 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5971 emitcode ("anl", "a,#0x%02x",
5972 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5974 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5976 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5978 emitcode ("anl", "a,#0x%02x",
5979 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5981 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5983 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5985 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5987 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5988 emitcode ("orl", "a,#0x%02x",
5989 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5991 emitcode ("", "%05d$:", tlbl->key + 100);
5992 break; // SSSSAAAA:BBBCCCCC
5994 case 6: // AABBBBBB:CCDDDDDD
5996 tlbl = newiTempLabel (NULL);
5997 emitcode ("mov", "c,acc.7");
5998 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6000 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6002 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6004 emitcode ("anl", "a,#0x%02x",
6005 SRMask[shCount]); // 000000AA:BBBBBBCC
6007 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6008 emitcode ("orl", "a,#0x%02x",
6009 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6011 emitcode ("", "%05d$:", tlbl->key + 100);
6013 case 7: // ABBBBBBB:CDDDDDDD
6015 tlbl = newiTempLabel (NULL);
6016 emitcode ("mov", "c,acc.7"); // c = A
6018 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6020 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6022 emitcode ("anl", "a,#0x%02x",
6023 SRMask[shCount]); // 0000000A:BBBBBBBC
6025 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6026 emitcode ("orl", "a,#0x%02x",
6027 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6029 emitcode ("", "%05d$:", tlbl->key + 100);
6036 /*-----------------------------------------------------------------*/
6037 /* shiftL2Left2Result - shift left two bytes from left to result */
6038 /*-----------------------------------------------------------------*/
6040 shiftL2Left2Result (operand * left, int offl,
6041 operand * result, int offr, int shCount)
6043 if (sameRegs (AOP (result), AOP (left)) &&
6044 ((offl + MSB16) == offr))
6046 /* don't crash result[offr] */
6047 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6048 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6052 movLeft2Result (left, offl, result, offr, 0);
6053 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6055 /* ax << shCount (x = lsb(result)) */
6056 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6057 aopPut (AOP (result), "a", offr + MSB16);
6061 /*-----------------------------------------------------------------*/
6062 /* shiftR2Left2Result - shift right two bytes from left to result */
6063 /*-----------------------------------------------------------------*/
6065 shiftR2Left2Result (operand * left, int offl,
6066 operand * result, int offr,
6067 int shCount, int sign)
6069 if (sameRegs (AOP (result), AOP (left)) &&
6070 ((offl + MSB16) == offr))
6072 /* don't crash result[offr] */
6073 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6074 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6078 movLeft2Result (left, offl, result, offr, 0);
6079 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6081 /* a:x >> shCount (x = lsb(result)) */
6083 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6085 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6086 if (getDataSize (result) > 1)
6087 aopPut (AOP (result), "a", offr + MSB16);
6090 /*-----------------------------------------------------------------*/
6091 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6092 /*-----------------------------------------------------------------*/
6094 shiftLLeftOrResult (operand * left, int offl,
6095 operand * result, int offr, int shCount)
6097 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6098 /* shift left accumulator */
6100 /* or with result */
6101 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6102 /* back to result */
6103 aopPut (AOP (result), "a", offr);
6106 /*-----------------------------------------------------------------*/
6107 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6108 /*-----------------------------------------------------------------*/
6110 shiftRLeftOrResult (operand * left, int offl,
6111 operand * result, int offr, int shCount)
6113 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6114 /* shift right accumulator */
6116 /* or with result */
6117 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6118 /* back to result */
6119 aopPut (AOP (result), "a", offr);
6122 /*-----------------------------------------------------------------*/
6123 /* genlshOne - left shift a one byte quantity by known count */
6124 /*-----------------------------------------------------------------*/
6126 genlshOne (operand * result, operand * left, int shCount)
6128 D(emitcode (";", "genlshOne"));
6130 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6133 /*-----------------------------------------------------------------*/
6134 /* genlshTwo - left shift two bytes by known amount != 0 */
6135 /*-----------------------------------------------------------------*/
6137 genlshTwo (operand * result, operand * left, int shCount)
6141 D(emitcode (";", "genlshTwo"));
6143 size = getDataSize (result);
6145 /* if shCount >= 8 */
6153 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6155 movLeft2Result (left, LSB, result, MSB16, 0);
6157 aopPut (AOP (result), zero, LSB);
6160 /* 1 <= shCount <= 7 */
6164 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6166 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6170 /*-----------------------------------------------------------------*/
6171 /* shiftLLong - shift left one long from left to result */
6172 /* offl = LSB or MSB16 */
6173 /*-----------------------------------------------------------------*/
6175 shiftLLong (operand * left, operand * result, int offr)
6178 int size = AOP_SIZE (result);
6180 if (size >= LSB + offr)
6182 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6184 emitcode ("add", "a,acc");
6185 if (sameRegs (AOP (left), AOP (result)) &&
6186 size >= MSB16 + offr && offr != LSB)
6187 emitcode ("xch", "a,%s",
6188 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6190 aopPut (AOP (result), "a", LSB + offr);
6193 if (size >= MSB16 + offr)
6195 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6197 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6200 emitcode ("rlc", "a");
6201 if (sameRegs (AOP (left), AOP (result)) &&
6202 size >= MSB24 + offr && offr != LSB)
6203 emitcode ("xch", "a,%s",
6204 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6206 aopPut (AOP (result), "a", MSB16 + offr);
6209 if (size >= MSB24 + offr)
6211 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6213 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6216 emitcode ("rlc", "a");
6217 if (sameRegs (AOP (left), AOP (result)) &&
6218 size >= MSB32 + offr && offr != LSB)
6219 emitcode ("xch", "a,%s",
6220 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6222 aopPut (AOP (result), "a", MSB24 + offr);
6225 if (size > MSB32 + offr)
6227 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6229 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6232 emitcode ("rlc", "a");
6233 aopPut (AOP (result), "a", MSB32 + offr);
6236 aopPut (AOP (result), zero, LSB);
6239 /*-----------------------------------------------------------------*/
6240 /* genlshFour - shift four byte by a known amount != 0 */
6241 /*-----------------------------------------------------------------*/
6243 genlshFour (operand * result, operand * left, int shCount)
6247 D(emitcode (";", "genlshFour"));
6249 size = AOP_SIZE (result);
6251 /* if shifting more that 3 bytes */
6256 /* lowest order of left goes to the highest
6257 order of the destination */
6258 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6260 movLeft2Result (left, LSB, result, MSB32, 0);
6261 aopPut (AOP (result), zero, LSB);
6262 aopPut (AOP (result), zero, MSB16);
6263 aopPut (AOP (result), zero, MSB24);
6267 /* more than two bytes */
6268 else if (shCount >= 16)
6270 /* lower order two bytes goes to higher order two bytes */
6272 /* if some more remaining */
6274 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6277 movLeft2Result (left, MSB16, result, MSB32, 0);
6278 movLeft2Result (left, LSB, result, MSB24, 0);
6280 aopPut (AOP (result), zero, MSB16);
6281 aopPut (AOP (result), zero, LSB);
6285 /* if more than 1 byte */
6286 else if (shCount >= 8)
6288 /* lower order three bytes goes to higher order three bytes */
6293 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6295 movLeft2Result (left, LSB, result, MSB16, 0);
6301 movLeft2Result (left, MSB24, result, MSB32, 0);
6302 movLeft2Result (left, MSB16, result, MSB24, 0);
6303 movLeft2Result (left, LSB, result, MSB16, 0);
6304 aopPut (AOP (result), zero, LSB);
6306 else if (shCount == 1)
6307 shiftLLong (left, result, MSB16);
6310 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6311 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6312 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6313 aopPut (AOP (result), zero, LSB);
6318 /* 1 <= shCount <= 7 */
6319 else if (shCount <= 2)
6321 shiftLLong (left, result, LSB);
6323 shiftLLong (result, result, LSB);
6325 /* 3 <= shCount <= 7, optimize */
6328 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6329 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6330 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6334 /*-----------------------------------------------------------------*/
6335 /* genLeftShiftLiteral - left shifting by known count */
6336 /*-----------------------------------------------------------------*/
6338 genLeftShiftLiteral (operand * left,
6343 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6346 D(emitcode (";", "genLeftShiftLiteral"));
6348 freeAsmop (right, NULL, ic, TRUE);
6350 aopOp (left, ic, FALSE);
6351 aopOp (result, ic, FALSE);
6353 size = getSize (operandType (result));
6356 emitcode ("; shift left ", "result %d, left %d", size,
6360 /* I suppose that the left size >= result size */
6365 movLeft2Result (left, size, result, size, 0);
6369 else if (shCount >= (size * 8))
6371 aopPut (AOP (result), zero, size);
6377 genlshOne (result, left, shCount);
6381 genlshTwo (result, left, shCount);
6385 genlshFour (result, left, shCount);
6388 fprintf(stderr, "*** ack! mystery literal shift!\n");
6392 freeAsmop (left, NULL, ic, TRUE);
6393 freeAsmop (result, NULL, ic, TRUE);
6396 /*-----------------------------------------------------------------*/
6397 /* genLeftShift - generates code for left shifting */
6398 /*-----------------------------------------------------------------*/
6400 genLeftShift (iCode * ic)
6402 operand *left, *right, *result;
6405 symbol *tlbl, *tlbl1;
6407 D(emitcode (";", "genLeftShift"));
6409 right = IC_RIGHT (ic);
6410 left = IC_LEFT (ic);
6411 result = IC_RESULT (ic);
6413 aopOp (right, ic, FALSE);
6415 /* if the shift count is known then do it
6416 as efficiently as possible */
6417 if (AOP_TYPE (right) == AOP_LIT)
6419 genLeftShiftLiteral (left, right, result, ic);
6423 /* shift count is unknown then we have to form
6424 a loop get the loop count in B : Note: we take
6425 only the lower order byte since shifting
6426 more that 32 bits make no sense anyway, ( the
6427 largest size of an object can be only 32 bits ) */
6429 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6430 emitcode ("inc", "b");
6431 freeAsmop (right, NULL, ic, TRUE);
6432 aopOp (left, ic, FALSE);
6433 aopOp (result, ic, FALSE);
6435 /* now move the left to the result if they are not the
6437 if (!sameRegs (AOP (left), AOP (result)) &&
6438 AOP_SIZE (result) > 1)
6441 size = AOP_SIZE (result);
6445 l = aopGet (AOP (left), offset, FALSE, TRUE);
6446 if (*l == '@' && (IS_AOP_PREG (result)))
6449 emitcode ("mov", "a,%s", l);
6450 aopPut (AOP (result), "a", offset);
6453 aopPut (AOP (result), l, offset);
6458 tlbl = newiTempLabel (NULL);
6459 size = AOP_SIZE (result);
6461 tlbl1 = newiTempLabel (NULL);
6463 /* if it is only one byte then */
6466 symbol *tlbl1 = newiTempLabel (NULL);
6468 l = aopGet (AOP (left), 0, FALSE, FALSE);
6470 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6471 emitcode ("", "%05d$:", tlbl->key + 100);
6472 emitcode ("add", "a,acc");
6473 emitcode ("", "%05d$:", tlbl1->key + 100);
6474 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6475 aopPut (AOP (result), "a", 0);
6479 reAdjustPreg (AOP (result));
6481 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6482 emitcode ("", "%05d$:", tlbl->key + 100);
6483 l = aopGet (AOP (result), offset, FALSE, FALSE);
6485 emitcode ("add", "a,acc");
6486 aopPut (AOP (result), "a", offset++);
6489 l = aopGet (AOP (result), offset, FALSE, FALSE);
6491 emitcode ("rlc", "a");
6492 aopPut (AOP (result), "a", offset++);
6494 reAdjustPreg (AOP (result));
6496 emitcode ("", "%05d$:", tlbl1->key + 100);
6497 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6499 freeAsmop (left, NULL, ic, TRUE);
6500 freeAsmop (result, NULL, ic, TRUE);
6503 /*-----------------------------------------------------------------*/
6504 /* genrshOne - right shift a one byte quantity by known count */
6505 /*-----------------------------------------------------------------*/
6507 genrshOne (operand * result, operand * left,
6508 int shCount, int sign)
6510 D(emitcode (";", "genrshOne"));
6512 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6515 /*-----------------------------------------------------------------*/
6516 /* genrshTwo - right shift two bytes by known amount != 0 */
6517 /*-----------------------------------------------------------------*/
6519 genrshTwo (operand * result, operand * left,
6520 int shCount, int sign)
6522 D(emitcode (";", "genrshTwo"));
6524 /* if shCount >= 8 */
6529 shiftR1Left2Result (left, MSB16, result, LSB,
6532 movLeft2Result (left, MSB16, result, LSB, sign);
6533 addSign (result, MSB16, sign);
6536 /* 1 <= shCount <= 7 */
6538 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6541 /*-----------------------------------------------------------------*/
6542 /* shiftRLong - shift right one long from left to result */
6543 /* offl = LSB or MSB16 */
6544 /*-----------------------------------------------------------------*/
6546 shiftRLong (operand * left, int offl,
6547 operand * result, int sign)
6549 int isSameRegs=sameRegs(AOP(left),AOP(result));
6551 if (isSameRegs && offl>1) {
6552 // we are in big trouble, but this shouldn't happen
6553 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6556 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6561 emitcode ("rlc", "a");
6562 emitcode ("subb", "a,acc");
6563 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6565 aopPut (AOP(result), zero, MSB32);
6570 emitcode ("clr", "c");
6572 emitcode ("mov", "c,acc.7");
6575 emitcode ("rrc", "a");
6577 if (isSameRegs && offl==MSB16) {
6578 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6580 aopPut (AOP (result), "a", MSB32);
6581 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6584 emitcode ("rrc", "a");
6585 if (isSameRegs && offl==1) {
6586 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6588 aopPut (AOP (result), "a", MSB24);
6589 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6591 emitcode ("rrc", "a");
6592 aopPut (AOP (result), "a", MSB16 - offl);
6596 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6597 emitcode ("rrc", "a");
6598 aopPut (AOP (result), "a", LSB);
6602 /*-----------------------------------------------------------------*/
6603 /* genrshFour - shift four byte by a known amount != 0 */
6604 /*-----------------------------------------------------------------*/
6606 genrshFour (operand * result, operand * left,
6607 int shCount, int sign)
6609 D(emitcode (";", "genrshFour"));
6611 /* if shifting more that 3 bytes */
6616 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6618 movLeft2Result (left, MSB32, result, LSB, sign);
6619 addSign (result, MSB16, sign);
6621 else if (shCount >= 16)
6625 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6628 movLeft2Result (left, MSB24, result, LSB, 0);
6629 movLeft2Result (left, MSB32, result, MSB16, sign);
6631 addSign (result, MSB24, sign);
6633 else if (shCount >= 8)
6637 shiftRLong (left, MSB16, result, sign);
6638 else if (shCount == 0)
6640 movLeft2Result (left, MSB16, result, LSB, 0);
6641 movLeft2Result (left, MSB24, result, MSB16, 0);
6642 movLeft2Result (left, MSB32, result, MSB24, sign);
6643 addSign (result, MSB32, sign);
6647 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6648 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6649 /* the last shift is signed */
6650 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6651 addSign (result, MSB32, sign);
6655 { /* 1 <= shCount <= 7 */
6658 shiftRLong (left, LSB, result, sign);
6660 shiftRLong (result, LSB, result, sign);
6664 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6665 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6666 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6671 /*-----------------------------------------------------------------*/
6672 /* genRightShiftLiteral - right shifting by known count */
6673 /*-----------------------------------------------------------------*/
6675 genRightShiftLiteral (operand * left,
6681 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6684 D(emitcode (";", "genRightShiftLiteral"));
6686 freeAsmop (right, NULL, ic, TRUE);
6688 aopOp (left, ic, FALSE);
6689 aopOp (result, ic, FALSE);
6692 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6696 size = getDataSize (left);
6697 /* test the LEFT size !!! */
6699 /* I suppose that the left size >= result size */
6702 size = getDataSize (result);
6704 movLeft2Result (left, size, result, size, 0);
6707 else if (shCount >= (size * 8))
6710 /* get sign in acc.7 */
6711 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6712 addSign (result, LSB, sign);
6719 genrshOne (result, left, shCount, sign);
6723 genrshTwo (result, left, shCount, sign);
6727 genrshFour (result, left, shCount, sign);
6733 freeAsmop (left, NULL, ic, TRUE);
6734 freeAsmop (result, NULL, ic, TRUE);
6738 /*-----------------------------------------------------------------*/
6739 /* genSignedRightShift - right shift of signed number */
6740 /*-----------------------------------------------------------------*/
6742 genSignedRightShift (iCode * ic)
6744 operand *right, *left, *result;
6747 symbol *tlbl, *tlbl1;
6749 D(emitcode (";", "genSignedRightShift"));
6751 /* we do it the hard way put the shift count in b
6752 and loop thru preserving the sign */
6754 right = IC_RIGHT (ic);
6755 left = IC_LEFT (ic);
6756 result = IC_RESULT (ic);
6758 aopOp (right, ic, FALSE);
6761 if (AOP_TYPE (right) == AOP_LIT)
6763 genRightShiftLiteral (left, right, result, ic, 1);
6766 /* shift count is unknown then we have to form
6767 a loop get the loop count in B : Note: we take
6768 only the lower order byte since shifting
6769 more that 32 bits make no sense anyway, ( the
6770 largest size of an object can be only 32 bits ) */
6772 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6773 emitcode ("inc", "b");
6774 freeAsmop (right, NULL, ic, TRUE);
6775 aopOp (left, ic, FALSE);
6776 aopOp (result, ic, FALSE);
6778 /* now move the left to the result if they are not the
6780 if (!sameRegs (AOP (left), AOP (result)) &&
6781 AOP_SIZE (result) > 1)
6784 size = AOP_SIZE (result);
6788 l = aopGet (AOP (left), offset, FALSE, TRUE);
6789 if (*l == '@' && IS_AOP_PREG (result))
6792 emitcode ("mov", "a,%s", l);
6793 aopPut (AOP (result), "a", offset);
6796 aopPut (AOP (result), l, offset);
6801 /* mov the highest order bit to OVR */
6802 tlbl = newiTempLabel (NULL);
6803 tlbl1 = newiTempLabel (NULL);
6805 size = AOP_SIZE (result);
6807 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6808 emitcode ("rlc", "a");
6809 emitcode ("mov", "ov,c");
6810 /* if it is only one byte then */
6813 l = aopGet (AOP (left), 0, FALSE, FALSE);
6815 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6816 emitcode ("", "%05d$:", tlbl->key + 100);
6817 emitcode ("mov", "c,ov");
6818 emitcode ("rrc", "a");
6819 emitcode ("", "%05d$:", tlbl1->key + 100);
6820 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6821 aopPut (AOP (result), "a", 0);
6825 reAdjustPreg (AOP (result));
6826 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6827 emitcode ("", "%05d$:", tlbl->key + 100);
6828 emitcode ("mov", "c,ov");
6831 l = aopGet (AOP (result), offset, FALSE, FALSE);
6833 emitcode ("rrc", "a");
6834 aopPut (AOP (result), "a", offset--);
6836 reAdjustPreg (AOP (result));
6837 emitcode ("", "%05d$:", tlbl1->key + 100);
6838 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6841 freeAsmop (left, NULL, ic, TRUE);
6842 freeAsmop (result, NULL, ic, TRUE);
6845 /*-----------------------------------------------------------------*/
6846 /* genRightShift - generate code for right shifting */
6847 /*-----------------------------------------------------------------*/
6849 genRightShift (iCode * ic)
6851 operand *right, *left, *result;
6855 symbol *tlbl, *tlbl1;
6857 D(emitcode (";", "genRightShift"));
6859 /* if signed then we do it the hard way preserve the
6860 sign bit moving it inwards */
6861 retype = getSpec (operandType (IC_RESULT (ic)));
6863 if (!SPEC_USIGN (retype))
6865 genSignedRightShift (ic);
6869 /* signed & unsigned types are treated the same : i.e. the
6870 signed is NOT propagated inwards : quoting from the
6871 ANSI - standard : "for E1 >> E2, is equivalent to division
6872 by 2**E2 if unsigned or if it has a non-negative value,
6873 otherwise the result is implementation defined ", MY definition
6874 is that the sign does not get propagated */
6876 right = IC_RIGHT (ic);
6877 left = IC_LEFT (ic);
6878 result = IC_RESULT (ic);
6880 aopOp (right, ic, FALSE);
6882 /* if the shift count is known then do it
6883 as efficiently as possible */
6884 if (AOP_TYPE (right) == AOP_LIT)
6886 genRightShiftLiteral (left, right, result, ic, 0);
6890 /* shift count is unknown then we have to form
6891 a loop get the loop count in B : Note: we take
6892 only the lower order byte since shifting
6893 more that 32 bits make no sense anyway, ( the
6894 largest size of an object can be only 32 bits ) */
6896 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6897 emitcode ("inc", "b");
6898 freeAsmop (right, NULL, ic, TRUE);
6899 aopOp (left, ic, FALSE);
6900 aopOp (result, ic, FALSE);
6902 /* now move the left to the result if they are not the
6904 if (!sameRegs (AOP (left), AOP (result)) &&
6905 AOP_SIZE (result) > 1)
6908 size = AOP_SIZE (result);
6912 l = aopGet (AOP (left), offset, FALSE, TRUE);
6913 if (*l == '@' && IS_AOP_PREG (result))
6916 emitcode ("mov", "a,%s", l);
6917 aopPut (AOP (result), "a", offset);
6920 aopPut (AOP (result), l, offset);
6925 tlbl = newiTempLabel (NULL);
6926 tlbl1 = newiTempLabel (NULL);
6927 size = AOP_SIZE (result);
6930 /* if it is only one byte then */
6933 l = aopGet (AOP (left), 0, FALSE, FALSE);
6935 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6936 emitcode ("", "%05d$:", tlbl->key + 100);
6938 emitcode ("rrc", "a");
6939 emitcode ("", "%05d$:", tlbl1->key + 100);
6940 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6941 aopPut (AOP (result), "a", 0);
6945 reAdjustPreg (AOP (result));
6946 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6947 emitcode ("", "%05d$:", tlbl->key + 100);
6951 l = aopGet (AOP (result), offset, FALSE, FALSE);
6953 emitcode ("rrc", "a");
6954 aopPut (AOP (result), "a", offset--);
6956 reAdjustPreg (AOP (result));
6958 emitcode ("", "%05d$:", tlbl1->key + 100);
6959 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6962 freeAsmop (left, NULL, ic, TRUE);
6963 freeAsmop (result, NULL, ic, TRUE);
6966 /*-----------------------------------------------------------------*/
6967 /* genUnpackBits - generates code for unpacking bits */
6968 /*-----------------------------------------------------------------*/
6970 genUnpackBits (operand * result, char *rname, int ptype)
6978 D(emitcode (";", "genUnpackBits"));
6980 etype = getSpec (operandType (result));
6981 rsize = getSize (operandType (result));
6982 /* read the first byte */
6988 emitcode ("mov", "a,@%s", rname);
6992 emitcode ("movx", "a,@%s", rname);
6996 emitcode ("movx", "a,@dptr");
7000 emitcode ("clr", "a");
7001 emitcode ("movc", "a,@a+dptr");
7005 emitcode ("lcall", "__gptrget");
7009 rlen = SPEC_BLEN (etype);
7011 /* if we have bitdisplacement then it fits */
7012 /* into this byte completely or if length is */
7013 /* less than a byte */
7014 if ((shCnt = SPEC_BSTR (etype)) ||
7015 (SPEC_BLEN (etype) <= 8))
7018 /* shift right acc */
7021 emitcode ("anl", "a,#0x%02x",
7022 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7023 aopPut (AOP (result), "a", offset++);
7027 /* bit field did not fit in a byte */
7028 aopPut (AOP (result), "a", offset++);
7037 emitcode ("inc", "%s", rname);
7038 emitcode ("mov", "a,@%s", rname);
7042 emitcode ("inc", "%s", rname);
7043 emitcode ("movx", "a,@%s", rname);
7047 emitcode ("inc", "dptr");
7048 emitcode ("movx", "a,@dptr");
7052 emitcode ("clr", "a");
7053 emitcode ("inc", "dptr");
7054 emitcode ("movc", "a,@a+dptr");
7058 emitcode ("inc", "dptr");
7059 emitcode ("lcall", "__gptrget");
7064 /* if we are done */
7068 aopPut (AOP (result), "a", offset++);
7074 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7076 aopPut (AOP (result), "a", offset++);
7084 aopPut (AOP (result), zero, offset++);
7090 /*-----------------------------------------------------------------*/
7091 /* genDataPointerGet - generates code when ptr offset is known */
7092 /*-----------------------------------------------------------------*/
7094 genDataPointerGet (operand * left,
7100 int size, offset = 0;
7102 D(emitcode (";", "genDataPointerGet"));
7104 aopOp (result, ic, TRUE);
7106 /* get the string representation of the name */
7107 l = aopGet (AOP (left), 0, FALSE, TRUE);
7108 size = AOP_SIZE (result);
7112 sprintf (buffer, "(%s + %d)", l + 1, offset);
7114 sprintf (buffer, "%s", l + 1);
7115 aopPut (AOP (result), buffer, offset++);
7118 freeAsmop (left, NULL, ic, TRUE);
7119 freeAsmop (result, NULL, ic, TRUE);
7122 /*-----------------------------------------------------------------*/
7123 /* genNearPointerGet - emitcode for near pointer fetch */
7124 /*-----------------------------------------------------------------*/
7126 genNearPointerGet (operand * left,
7134 sym_link *rtype, *retype;
7135 sym_link *ltype = operandType (left);
7138 D(emitcode (";", "genNearPointerGet"));
7140 rtype = operandType (result);
7141 retype = getSpec (rtype);
7143 aopOp (left, ic, FALSE);
7145 /* if left is rematerialisable and
7146 result is not bit variable type and
7147 the left is pointer to data space i.e
7148 lower 128 bytes of space */
7149 if (AOP_TYPE (left) == AOP_IMMD &&
7150 !IS_BITVAR (retype) &&
7151 DCL_TYPE (ltype) == POINTER)
7153 genDataPointerGet (left, result, ic);
7157 /* if the value is already in a pointer register
7158 then don't need anything more */
7159 if (!AOP_INPREG (AOP (left)))
7161 /* otherwise get a free pointer register */
7163 preg = getFreePtr (ic, &aop, FALSE);
7164 emitcode ("mov", "%s,%s",
7166 aopGet (AOP (left), 0, FALSE, TRUE));
7170 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7172 //aopOp (result, ic, FALSE);
7173 aopOp (result, ic, result?TRUE:FALSE);
7175 /* if bitfield then unpack the bits */
7176 if (IS_BITVAR (retype))
7177 genUnpackBits (result, rname, POINTER);
7180 /* we have can just get the values */
7181 int size = AOP_SIZE (result);
7186 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7189 emitcode ("mov", "a,@%s", rname);
7190 aopPut (AOP (result), "a", offset);
7194 sprintf (buffer, "@%s", rname);
7195 aopPut (AOP (result), buffer, offset);
7199 emitcode ("inc", "%s", rname);
7203 /* now some housekeeping stuff */
7204 if (aop) /* we had to allocate for this iCode */
7206 if (pi) { /* post increment present */
7207 aopPut(AOP ( left ),rname,0);
7209 freeAsmop (NULL, aop, ic, TRUE);
7213 /* we did not allocate which means left
7214 already in a pointer register, then
7215 if size > 0 && this could be used again
7216 we have to point it back to where it
7218 if ((AOP_SIZE (result) > 1 &&
7219 !OP_SYMBOL (left)->remat &&
7220 (OP_SYMBOL (left)->liveTo > ic->seq ||
7224 int size = AOP_SIZE (result) - 1;
7226 emitcode ("dec", "%s", rname);
7231 freeAsmop (left, NULL, ic, TRUE);
7232 freeAsmop (result, NULL, ic, TRUE);
7233 if (pi) pi->generated = 1;
7236 /*-----------------------------------------------------------------*/
7237 /* genPagedPointerGet - emitcode for paged pointer fetch */
7238 /*-----------------------------------------------------------------*/
7240 genPagedPointerGet (operand * left,
7248 sym_link *rtype, *retype;
7250 D(emitcode (";", "genPagedPointerGet"));
7252 rtype = operandType (result);
7253 retype = getSpec (rtype);
7255 aopOp (left, ic, FALSE);
7257 /* if the value is already in a pointer register
7258 then don't need anything more */
7259 if (!AOP_INPREG (AOP (left)))
7261 /* otherwise get a free pointer register */
7263 preg = getFreePtr (ic, &aop, FALSE);
7264 emitcode ("mov", "%s,%s",
7266 aopGet (AOP (left), 0, FALSE, TRUE));
7270 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7272 aopOp (result, ic, FALSE);
7274 /* if bitfield then unpack the bits */
7275 if (IS_BITVAR (retype))
7276 genUnpackBits (result, rname, PPOINTER);
7279 /* we have can just get the values */
7280 int size = AOP_SIZE (result);
7286 emitcode ("movx", "a,@%s", rname);
7287 aopPut (AOP (result), "a", offset);
7292 emitcode ("inc", "%s", rname);
7296 /* now some housekeeping stuff */
7297 if (aop) /* we had to allocate for this iCode */
7299 if (pi) aopPut ( AOP (left), rname, 0);
7300 freeAsmop (NULL, aop, ic, TRUE);
7304 /* we did not allocate which means left
7305 already in a pointer register, then
7306 if size > 0 && this could be used again
7307 we have to point it back to where it
7309 if ((AOP_SIZE (result) > 1 &&
7310 !OP_SYMBOL (left)->remat &&
7311 (OP_SYMBOL (left)->liveTo > ic->seq ||
7315 int size = AOP_SIZE (result) - 1;
7317 emitcode ("dec", "%s", rname);
7322 freeAsmop (left, NULL, ic, TRUE);
7323 freeAsmop (result, NULL, ic, TRUE);
7324 if (pi) pi->generated = 1;
7328 /*-----------------------------------------------------------------*/
7329 /* genFarPointerGet - gget value from far space */
7330 /*-----------------------------------------------------------------*/
7332 genFarPointerGet (operand * left,
7333 operand * result, iCode * ic, iCode * pi)
7336 sym_link *retype = getSpec (operandType (result));
7338 D(emitcode (";", "genFarPointerGet"));
7340 aopOp (left, ic, FALSE);
7342 /* if the operand is already in dptr
7343 then we do nothing else we move the value to dptr */
7344 if (AOP_TYPE (left) != AOP_STR)
7346 /* if this is remateriazable */
7347 if (AOP_TYPE (left) == AOP_IMMD)
7348 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7350 { /* we need to get it byte by byte */
7351 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7352 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7355 /* so dptr know contains the address */
7356 aopOp (result, ic, FALSE);
7358 /* if bit then unpack */
7359 if (IS_BITVAR (retype))
7360 genUnpackBits (result, "dptr", FPOINTER);
7363 size = AOP_SIZE (result);
7368 emitcode ("movx", "a,@dptr");
7369 aopPut (AOP (result), "a", offset++);
7371 emitcode ("inc", "dptr");
7375 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7376 aopPut ( AOP (left), "dpl", 0);
7377 aopPut ( AOP (left), "dph", 1);
7380 freeAsmop (left, NULL, ic, TRUE);
7381 freeAsmop (result, NULL, ic, TRUE);
7384 /*-----------------------------------------------------------------*/
7385 /* genCodePointerGet - gget value from code space */
7386 /*-----------------------------------------------------------------*/
7388 genCodePointerGet (operand * left,
7389 operand * result, iCode * ic, iCode *pi)
7392 sym_link *retype = getSpec (operandType (result));
7394 D(emitcode (";", "genCodePointerGet"));
7396 aopOp (left, ic, FALSE);
7398 /* if the operand is already in dptr
7399 then we do nothing else we move the value to dptr */
7400 if (AOP_TYPE (left) != AOP_STR)
7402 /* if this is remateriazable */
7403 if (AOP_TYPE (left) == AOP_IMMD)
7404 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7406 { /* we need to get it byte by byte */
7407 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7408 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7411 /* so dptr know contains the address */
7412 aopOp (result, ic, FALSE);
7414 /* if bit then unpack */
7415 if (IS_BITVAR (retype))
7416 genUnpackBits (result, "dptr", CPOINTER);
7419 size = AOP_SIZE (result);
7424 emitcode ("clr", "a");
7425 emitcode ("movc", "a,@a+dptr");
7426 aopPut (AOP (result), "a", offset++);
7428 emitcode ("inc", "dptr");
7432 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7433 aopPut ( AOP (left), "dpl", 0);
7434 aopPut ( AOP (left), "dph", 1);
7437 freeAsmop (left, NULL, ic, TRUE);
7438 freeAsmop (result, NULL, ic, TRUE);
7441 /*-----------------------------------------------------------------*/
7442 /* genGenPointerGet - gget value from generic pointer space */
7443 /*-----------------------------------------------------------------*/
7445 genGenPointerGet (operand * left,
7446 operand * result, iCode * ic, iCode *pi)
7449 sym_link *retype = getSpec (operandType (result));
7451 D(emitcode (";", "genGenPointerGet"));
7453 aopOp (left, ic, FALSE);
7455 /* if the operand is already in dptr
7456 then we do nothing else we move the value to dptr */
7457 if (AOP_TYPE (left) != AOP_STR)
7459 /* if this is remateriazable */
7460 if (AOP_TYPE (left) == AOP_IMMD)
7462 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7463 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7464 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7466 emitcode ("mov", "b,#%d", pointerCode (retype));
7469 { /* we need to get it byte by byte */
7470 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7471 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7472 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7475 /* so dptr know contains the address */
7476 aopOp (result, ic, FALSE);
7478 /* if bit then unpack */
7479 if (IS_BITVAR (retype))
7480 genUnpackBits (result, "dptr", GPOINTER);
7483 size = AOP_SIZE (result);
7488 emitcode ("lcall", "__gptrget");
7489 aopPut (AOP (result), "a", offset++);
7491 emitcode ("inc", "dptr");
7495 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7496 aopPut ( AOP (left), "dpl", 0);
7497 aopPut ( AOP (left), "dph", 1);
7498 aopPut ( AOP (left), "b", 2);
7501 freeAsmop (left, NULL, ic, TRUE);
7502 freeAsmop (result, NULL, ic, TRUE);
7505 /*-----------------------------------------------------------------*/
7506 /* genPointerGet - generate code for pointer get */
7507 /*-----------------------------------------------------------------*/
7509 genPointerGet (iCode * ic, iCode *pi)
7511 operand *left, *result;
7512 sym_link *type, *etype;
7515 D(emitcode (";", "genPointerGet"));
7517 left = IC_LEFT (ic);
7518 result = IC_RESULT (ic);
7520 /* depending on the type of pointer we need to
7521 move it to the correct pointer register */
7522 type = operandType (left);
7523 etype = getSpec (type);
7524 /* if left is of type of pointer then it is simple */
7525 if (IS_PTR (type) && !IS_FUNC (type->next))
7526 p_type = DCL_TYPE (type);
7529 /* we have to go by the storage class */
7530 p_type = PTR_TYPE (SPEC_OCLS (etype));
7533 /* special case when cast remat */
7534 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7535 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7536 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7537 type = type = operandType (left);
7538 p_type = DCL_TYPE (type);
7540 /* now that we have the pointer type we assign
7541 the pointer values */
7547 genNearPointerGet (left, result, ic, pi);
7551 genPagedPointerGet (left, result, ic, pi);
7555 genFarPointerGet (left, result, ic, pi);
7559 genCodePointerGet (left, result, ic, pi);
7563 genGenPointerGet (left, result, ic, pi);
7569 /*-----------------------------------------------------------------*/
7570 /* genPackBits - generates code for packed bit storage */
7571 /*-----------------------------------------------------------------*/
7573 genPackBits (sym_link * etype,
7575 char *rname, int p_type)
7583 D(emitcode (";", "genPackBits"));
7585 blen = SPEC_BLEN (etype);
7586 bstr = SPEC_BSTR (etype);
7588 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7591 /* if the bit lenth is less than or */
7592 /* it exactly fits a byte then */
7593 if (SPEC_BLEN (etype) <= 8)
7595 shCount = SPEC_BSTR (etype);
7597 /* shift left acc */
7600 if (SPEC_BLEN (etype) < 8)
7601 { /* if smaller than a byte */
7607 emitcode ("mov", "b,a");
7608 emitcode ("mov", "a,@%s", rname);
7612 emitcode ("mov", "b,a");
7613 emitcode ("movx", "a,@dptr");
7617 emitcode ("push", "b");
7618 emitcode ("push", "acc");
7619 emitcode ("lcall", "__gptrget");
7620 emitcode ("pop", "b");
7624 emitcode ("anl", "a,#0x%02x", (unsigned char)
7625 ((unsigned char) (0xFF << (blen + bstr)) |
7626 (unsigned char) (0xFF >> (8 - bstr))));
7627 emitcode ("orl", "a,b");
7628 if (p_type == GPOINTER)
7629 emitcode ("pop", "b");
7636 emitcode ("mov", "@%s,a", rname);
7640 emitcode ("movx", "@dptr,a");
7644 emitcode ("lcall", "__gptrput");
7649 if (SPEC_BLEN (etype) <= 8)
7652 emitcode ("inc", "%s", rname);
7653 rLen = SPEC_BLEN (etype);
7655 /* now generate for lengths greater than one byte */
7659 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7671 emitcode ("mov", "@%s,a", rname);
7674 emitcode ("mov", "@%s,%s", rname, l);
7679 emitcode ("movx", "@dptr,a");
7684 emitcode ("lcall", "__gptrput");
7687 emitcode ("inc", "%s", rname);
7692 /* last last was not complete */
7695 /* save the byte & read byte */
7699 emitcode ("mov", "b,a");
7700 emitcode ("mov", "a,@%s", rname);
7704 emitcode ("mov", "b,a");
7705 emitcode ("movx", "a,@dptr");
7709 emitcode ("push", "b");
7710 emitcode ("push", "acc");
7711 emitcode ("lcall", "__gptrget");
7712 emitcode ("pop", "b");
7716 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7717 emitcode ("orl", "a,b");
7720 if (p_type == GPOINTER)
7721 emitcode ("pop", "b");
7727 emitcode ("mov", "@%s,a", rname);
7731 emitcode ("movx", "@dptr,a");
7735 emitcode ("lcall", "__gptrput");
7739 /*-----------------------------------------------------------------*/
7740 /* genDataPointerSet - remat pointer to data space */
7741 /*-----------------------------------------------------------------*/
7743 genDataPointerSet (operand * right,
7747 int size, offset = 0;
7748 char *l, buffer[256];
7750 D(emitcode (";", "genDataPointerSet"));
7752 aopOp (right, ic, FALSE);
7754 l = aopGet (AOP (result), 0, FALSE, TRUE);
7755 size = AOP_SIZE (right);
7759 sprintf (buffer, "(%s + %d)", l + 1, offset);
7761 sprintf (buffer, "%s", l + 1);
7762 emitcode ("mov", "%s,%s", buffer,
7763 aopGet (AOP (right), offset++, FALSE, FALSE));
7766 freeAsmop (right, NULL, ic, TRUE);
7767 freeAsmop (result, NULL, ic, TRUE);
7770 /*-----------------------------------------------------------------*/
7771 /* genNearPointerSet - emitcode for near pointer put */
7772 /*-----------------------------------------------------------------*/
7774 genNearPointerSet (operand * right,
7782 sym_link *retype, *letype;
7783 sym_link *ptype = operandType (result);
7785 D(emitcode (";", "genNearPointerSet"));
7787 retype = getSpec (operandType (right));
7788 letype = getSpec (ptype);
7789 aopOp (result, ic, FALSE);
7791 /* if the result is rematerializable &
7792 in data space & not a bit variable */
7793 if (AOP_TYPE (result) == AOP_IMMD &&
7794 DCL_TYPE (ptype) == POINTER &&
7795 !IS_BITVAR (retype) &&
7796 !IS_BITVAR (letype))
7798 genDataPointerSet (right, result, ic);
7802 /* if the value is already in a pointer register
7803 then don't need anything more */
7804 if (!AOP_INPREG (AOP (result)))
7807 //AOP_TYPE (result) == AOP_STK
7811 // Aha, it is a pointer, just in disguise.
7812 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7815 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7816 __FILE__, __LINE__);
7821 rname++; // skip the '@'.
7826 /* otherwise get a free pointer register */
7828 preg = getFreePtr (ic, &aop, FALSE);
7829 emitcode ("mov", "%s,%s",
7831 aopGet (AOP (result), 0, FALSE, TRUE));
7837 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7840 aopOp (right, ic, FALSE);
7842 /* if bitfield then unpack the bits */
7843 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7844 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7847 /* we have can just get the values */
7848 int size = AOP_SIZE (right);
7853 l = aopGet (AOP (right), offset, FALSE, TRUE);
7857 emitcode ("mov", "@%s,a", rname);
7860 emitcode ("mov", "@%s,%s", rname, l);
7862 emitcode ("inc", "%s", rname);
7867 /* now some housekeeping stuff */
7868 if (aop) /* we had to allocate for this iCode */
7870 if (pi) aopPut (AOP (result),rname,0);
7871 freeAsmop (NULL, aop, ic, TRUE);
7875 /* we did not allocate which means left
7876 already in a pointer register, then
7877 if size > 0 && this could be used again
7878 we have to point it back to where it
7880 if ((AOP_SIZE (right) > 1 &&
7881 !OP_SYMBOL (result)->remat &&
7882 (OP_SYMBOL (result)->liveTo > ic->seq ||
7886 int size = AOP_SIZE (right) - 1;
7888 emitcode ("dec", "%s", rname);
7893 if (pi) pi->generated = 1;
7894 freeAsmop (result, NULL, ic, TRUE);
7895 freeAsmop (right, NULL, ic, TRUE);
7898 /*-----------------------------------------------------------------*/
7899 /* genPagedPointerSet - emitcode for Paged pointer put */
7900 /*-----------------------------------------------------------------*/
7902 genPagedPointerSet (operand * right,
7910 sym_link *retype, *letype;
7912 D(emitcode (";", "genPagedPointerSet"));
7914 retype = getSpec (operandType (right));
7915 letype = getSpec (operandType (result));
7917 aopOp (result, ic, FALSE);
7919 /* if the value is already in a pointer register
7920 then don't need anything more */
7921 if (!AOP_INPREG (AOP (result)))
7923 /* otherwise get a free pointer register */
7925 preg = getFreePtr (ic, &aop, FALSE);
7926 emitcode ("mov", "%s,%s",
7928 aopGet (AOP (result), 0, FALSE, TRUE));
7932 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7934 aopOp (right, ic, FALSE);
7936 /* if bitfield then unpack the bits */
7937 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7938 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7941 /* we have can just get the values */
7942 int size = AOP_SIZE (right);
7947 l = aopGet (AOP (right), offset, FALSE, TRUE);
7950 emitcode ("movx", "@%s,a", rname);
7953 emitcode ("inc", "%s", rname);
7959 /* now some housekeeping stuff */
7960 if (aop) /* we had to allocate for this iCode */
7962 if (pi) aopPut (AOP (result),rname,0);
7963 freeAsmop (NULL, aop, ic, TRUE);
7967 /* we did not allocate which means left
7968 already in a pointer register, then
7969 if size > 0 && this could be used again
7970 we have to point it back to where it
7972 if (AOP_SIZE (right) > 1 &&
7973 !OP_SYMBOL (result)->remat &&
7974 (OP_SYMBOL (result)->liveTo > ic->seq ||
7977 int size = AOP_SIZE (right) - 1;
7979 emitcode ("dec", "%s", rname);
7984 if (pi) pi->generated = 1;
7985 freeAsmop (result, NULL, ic, TRUE);
7986 freeAsmop (right, NULL, ic, TRUE);
7991 /*-----------------------------------------------------------------*/
7992 /* genFarPointerSet - set value from far space */
7993 /*-----------------------------------------------------------------*/
7995 genFarPointerSet (operand * right,
7996 operand * result, iCode * ic, iCode * pi)
7999 sym_link *retype = getSpec (operandType (right));
8000 sym_link *letype = getSpec (operandType (result));
8002 D(emitcode (";", "genFarPointerSet"));
8004 aopOp (result, ic, FALSE);
8006 /* if the operand is already in dptr
8007 then we do nothing else we move the value to dptr */
8008 if (AOP_TYPE (result) != AOP_STR)
8010 /* if this is remateriazable */
8011 if (AOP_TYPE (result) == AOP_IMMD)
8012 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8014 { /* we need to get it byte by byte */
8015 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8016 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8019 /* so dptr know contains the address */
8020 aopOp (right, ic, FALSE);
8022 /* if bit then unpack */
8023 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8024 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8027 size = AOP_SIZE (right);
8032 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8034 emitcode ("movx", "@dptr,a");
8036 emitcode ("inc", "dptr");
8039 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8040 aopPut (AOP(result),"dpl",0);
8041 aopPut (AOP(result),"dph",1);
8044 freeAsmop (result, NULL, ic, TRUE);
8045 freeAsmop (right, NULL, ic, TRUE);
8048 /*-----------------------------------------------------------------*/
8049 /* genGenPointerSet - set value from generic pointer space */
8050 /*-----------------------------------------------------------------*/
8052 genGenPointerSet (operand * right,
8053 operand * result, iCode * ic, iCode * pi)
8056 sym_link *retype = getSpec (operandType (right));
8057 sym_link *letype = getSpec (operandType (result));
8059 D(emitcode (";", "genGenPointerSet"));
8061 aopOp (result, ic, FALSE);
8063 /* if the operand is already in dptr
8064 then we do nothing else we move the value to dptr */
8065 if (AOP_TYPE (result) != AOP_STR)
8067 /* if this is remateriazable */
8068 if (AOP_TYPE (result) == AOP_IMMD)
8070 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8071 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8072 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8074 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8077 { /* we need to get it byte by byte */
8078 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8079 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8080 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8083 /* so dptr know contains the address */
8084 aopOp (right, ic, FALSE);
8086 /* if bit then unpack */
8087 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8088 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8091 size = AOP_SIZE (right);
8096 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8098 emitcode ("lcall", "__gptrput");
8100 emitcode ("inc", "dptr");
8104 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8105 aopPut (AOP(result),"dpl",0);
8106 aopPut (AOP(result),"dph",1);
8107 aopPut (AOP(result),"b",2);
8110 freeAsmop (result, NULL, ic, TRUE);
8111 freeAsmop (right, NULL, ic, TRUE);
8114 /*-----------------------------------------------------------------*/
8115 /* genPointerSet - stores the value into a pointer location */
8116 /*-----------------------------------------------------------------*/
8118 genPointerSet (iCode * ic, iCode *pi)
8120 operand *right, *result;
8121 sym_link *type, *etype;
8124 D(emitcode (";", "genPointerSet"));
8126 right = IC_RIGHT (ic);
8127 result = IC_RESULT (ic);
8129 /* depending on the type of pointer we need to
8130 move it to the correct pointer register */
8131 type = operandType (result);
8132 etype = getSpec (type);
8133 /* if left is of type of pointer then it is simple */
8134 if (IS_PTR (type) && !IS_FUNC (type->next))
8136 p_type = DCL_TYPE (type);
8140 /* we have to go by the storage class */
8141 p_type = PTR_TYPE (SPEC_OCLS (etype));
8144 /* special case when cast remat */
8145 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8146 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8147 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8148 type = type = operandType (result);
8149 p_type = DCL_TYPE (type);
8151 /* now that we have the pointer type we assign
8152 the pointer values */
8158 genNearPointerSet (right, result, ic, pi);
8162 genPagedPointerSet (right, result, ic, pi);
8166 genFarPointerSet (right, result, ic, pi);
8170 genGenPointerSet (right, result, ic, pi);
8176 /*-----------------------------------------------------------------*/
8177 /* genIfx - generate code for Ifx statement */
8178 /*-----------------------------------------------------------------*/
8180 genIfx (iCode * ic, iCode * popIc)
8182 operand *cond = IC_COND (ic);
8185 D(emitcode (";", "genIfx"));
8187 aopOp (cond, ic, FALSE);
8189 /* get the value into acc */
8190 if (AOP_TYPE (cond) != AOP_CRY)
8194 /* the result is now in the accumulator */
8195 freeAsmop (cond, NULL, ic, TRUE);
8197 /* if there was something to be popped then do it */
8201 /* if the condition is a bit variable */
8202 if (isbit && IS_ITEMP (cond) &&
8204 genIfxJump (ic, SPIL_LOC (cond)->rname);
8205 else if (isbit && !IS_ITEMP (cond))
8206 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8208 genIfxJump (ic, "a");
8213 /*-----------------------------------------------------------------*/
8214 /* genAddrOf - generates code for address of */
8215 /*-----------------------------------------------------------------*/
8217 genAddrOf (iCode * ic)
8219 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8222 D(emitcode (";", "genAddrOf"));
8224 aopOp (IC_RESULT (ic), ic, FALSE);
8226 /* if the operand is on the stack then we
8227 need to get the stack offset of this
8231 /* if it has an offset then we need to compute
8235 emitcode ("mov", "a,_bp");
8236 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8237 ((char) (sym->stack - _G.nRegsSaved)) :
8238 ((char) sym->stack)) & 0xff);
8239 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8243 /* we can just move _bp */
8244 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8246 /* fill the result with zero */
8247 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8252 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8258 /* object not on stack then we need the name */
8259 size = AOP_SIZE (IC_RESULT (ic));
8264 char s[SDCC_NAME_MAX];
8266 sprintf (s, "#(%s >> %d)",
8270 sprintf (s, "#%s", sym->rname);
8271 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8275 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8279 /*-----------------------------------------------------------------*/
8280 /* genFarFarAssign - assignment when both are in far space */
8281 /*-----------------------------------------------------------------*/
8283 genFarFarAssign (operand * result, operand * right, iCode * ic)
8285 int size = AOP_SIZE (right);
8289 D(emitcode (";", "genFarFarAssign"));
8291 /* first push the right side on to the stack */
8294 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8296 emitcode ("push", "acc");
8299 freeAsmop (right, NULL, ic, FALSE);
8300 /* now assign DPTR to result */
8301 aopOp (result, ic, FALSE);
8302 size = AOP_SIZE (result);
8305 emitcode ("pop", "acc");
8306 aopPut (AOP (result), "a", --offset);
8308 freeAsmop (result, NULL, ic, FALSE);
8312 /*-----------------------------------------------------------------*/
8313 /* genAssign - generate code for assignment */
8314 /*-----------------------------------------------------------------*/
8316 genAssign (iCode * ic)
8318 operand *result, *right;
8320 unsigned long lit = 0L;
8322 D(emitcode(";","genAssign"));
8324 result = IC_RESULT (ic);
8325 right = IC_RIGHT (ic);
8327 /* if they are the same */
8328 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8331 aopOp (right, ic, FALSE);
8333 /* special case both in far space */
8334 if (AOP_TYPE (right) == AOP_DPTR &&
8335 IS_TRUE_SYMOP (result) &&
8336 isOperandInFarSpace (result))
8339 genFarFarAssign (result, right, ic);
8343 aopOp (result, ic, TRUE);
8345 /* if they are the same registers */
8346 if (sameRegs (AOP (right), AOP (result)))
8349 /* if the result is a bit */
8350 if (AOP_TYPE (result) == AOP_CRY)
8353 /* if the right size is a literal then
8354 we know what the value is */
8355 if (AOP_TYPE (right) == AOP_LIT)
8357 if (((int) operandLitValue (right)))
8358 aopPut (AOP (result), one, 0);
8360 aopPut (AOP (result), zero, 0);
8364 /* the right is also a bit variable */
8365 if (AOP_TYPE (right) == AOP_CRY)
8367 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8368 aopPut (AOP (result), "c", 0);
8374 aopPut (AOP (result), "a", 0);
8378 /* bit variables done */
8380 size = AOP_SIZE (result);
8382 if (AOP_TYPE (right) == AOP_LIT)
8383 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8385 (AOP_TYPE (result) != AOP_REG) &&
8386 (AOP_TYPE (right) == AOP_LIT) &&
8387 !IS_FLOAT (operandType (right)) &&
8390 emitcode ("clr", "a");
8393 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8394 aopPut (AOP (result), "a", size);
8396 aopPut (AOP (result),
8397 aopGet (AOP (right), size, FALSE, FALSE),
8405 aopPut (AOP (result),
8406 aopGet (AOP (right), offset, FALSE, FALSE),
8413 freeAsmop (right, NULL, ic, TRUE);
8414 freeAsmop (result, NULL, ic, TRUE);
8417 /*-----------------------------------------------------------------*/
8418 /* genJumpTab - genrates code for jump table */
8419 /*-----------------------------------------------------------------*/
8421 genJumpTab (iCode * ic)
8426 D(emitcode (";", "genJumpTab"));
8428 aopOp (IC_JTCOND (ic), ic, FALSE);
8429 /* get the condition into accumulator */
8430 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8432 /* multiply by three */
8433 emitcode ("add", "a,acc");
8434 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8435 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8437 jtab = newiTempLabel (NULL);
8438 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8439 emitcode ("jmp", "@a+dptr");
8440 emitcode ("", "%05d$:", jtab->key + 100);
8441 /* now generate the jump labels */
8442 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8443 jtab = setNextItem (IC_JTLABELS (ic)))
8444 emitcode ("ljmp", "%05d$", jtab->key + 100);
8448 /*-----------------------------------------------------------------*/
8449 /* genCast - gen code for casting */
8450 /*-----------------------------------------------------------------*/
8452 genCast (iCode * ic)
8454 operand *result = IC_RESULT (ic);
8455 sym_link *ctype = operandType (IC_LEFT (ic));
8456 sym_link *rtype = operandType (IC_RIGHT (ic));
8457 operand *right = IC_RIGHT (ic);
8460 D(emitcode(";", "genCast"));
8462 /* if they are equivalent then do nothing */
8463 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8466 aopOp (right, ic, FALSE);
8467 aopOp (result, ic, FALSE);
8469 /* if the result is a bit */
8470 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8471 if (IS_BITVAR(OP_SYMBOL(result)->type))
8473 /* if the right size is a literal then
8474 we know what the value is */
8475 if (AOP_TYPE (right) == AOP_LIT)
8477 if (((int) operandLitValue (right)))
8478 aopPut (AOP (result), one, 0);
8480 aopPut (AOP (result), zero, 0);
8485 /* the right is also a bit variable */
8486 if (AOP_TYPE (right) == AOP_CRY)
8488 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8489 aopPut (AOP (result), "c", 0);
8495 aopPut (AOP (result), "a", 0);
8499 /* if they are the same size : or less */
8500 if (AOP_SIZE (result) <= AOP_SIZE (right))
8503 /* if they are in the same place */
8504 if (sameRegs (AOP (right), AOP (result)))
8507 /* if they in different places then copy */
8508 size = AOP_SIZE (result);
8512 aopPut (AOP (result),
8513 aopGet (AOP (right), offset, FALSE, FALSE),
8521 /* if the result is of type pointer */
8526 sym_link *type = operandType (right);
8527 sym_link *etype = getSpec (type);
8529 /* pointer to generic pointer */
8530 if (IS_GENPTR (ctype))
8535 p_type = DCL_TYPE (type);
8538 if (SPEC_SCLS(etype)==S_REGISTER) {
8539 // let's assume it is a generic pointer
8542 /* we have to go by the storage class */
8543 p_type = PTR_TYPE (SPEC_OCLS (etype));
8547 /* the first two bytes are known */
8548 size = GPTRSIZE - 1;
8552 aopPut (AOP (result),
8553 aopGet (AOP (right), offset, FALSE, FALSE),
8557 /* the last byte depending on type */
8573 case PPOINTER: // what the fck is this?
8578 /* this should never happen */
8579 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8580 "got unknown pointer type");
8583 aopPut (AOP (result), l, GPTRSIZE - 1);
8587 /* just copy the pointers */
8588 size = AOP_SIZE (result);
8592 aopPut (AOP (result),
8593 aopGet (AOP (right), offset, FALSE, FALSE),
8600 /* so we now know that the size of destination is greater
8601 than the size of the source */
8602 /* we move to result for the size of source */
8603 size = AOP_SIZE (right);
8607 aopPut (AOP (result),
8608 aopGet (AOP (right), offset, FALSE, FALSE),
8613 /* now depending on the sign of the source && destination */
8614 size = AOP_SIZE (result) - AOP_SIZE (right);
8615 /* if unsigned or not an integral type */
8616 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8619 aopPut (AOP (result), zero, offset++);
8623 /* we need to extend the sign :{ */
8624 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8627 emitcode ("rlc", "a");
8628 emitcode ("subb", "a,acc");
8630 aopPut (AOP (result), "a", offset++);
8633 /* we are done hurray !!!! */
8636 freeAsmop (right, NULL, ic, TRUE);
8637 freeAsmop (result, NULL, ic, TRUE);
8641 /*-----------------------------------------------------------------*/
8642 /* genDjnz - generate decrement & jump if not zero instrucion */
8643 /*-----------------------------------------------------------------*/
8645 genDjnz (iCode * ic, iCode * ifx)
8651 D(emitcode (";", "genDjnz"));
8653 /* if the if condition has a false label
8654 then we cannot save */
8658 /* if the minus is not of the form
8660 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8661 !IS_OP_LITERAL (IC_RIGHT (ic)))
8664 if (operandLitValue (IC_RIGHT (ic)) != 1)
8667 /* if the size of this greater than one then no
8669 if (getSize (operandType (IC_RESULT (ic))) > 1)
8672 /* otherwise we can save BIG */
8673 lbl = newiTempLabel (NULL);
8674 lbl1 = newiTempLabel (NULL);
8676 aopOp (IC_RESULT (ic), ic, FALSE);
8678 if (AOP_NEEDSACC(IC_RESULT(ic)))
8680 /* If the result is accessed indirectly via
8681 * the accumulator, we must explicitly write
8682 * it back after the decrement.
8684 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8686 if (strcmp(rByte, "a"))
8688 /* Something is hopelessly wrong */
8689 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8690 __FILE__, __LINE__);
8691 /* We can just give up; the generated code will be inefficient,
8694 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8697 emitcode ("dec", "%s", rByte);
8698 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8699 emitcode ("jnz", "%05d$", lbl->key + 100);
8701 else if (IS_AOP_PREG (IC_RESULT (ic)))
8703 emitcode ("dec", "%s",
8704 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8705 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8706 emitcode ("jnz", "%05d$", lbl->key + 100);
8710 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8713 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8714 emitcode ("", "%05d$:", lbl->key + 100);
8715 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8716 emitcode ("", "%05d$:", lbl1->key + 100);
8718 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8723 /*-----------------------------------------------------------------*/
8724 /* genReceive - generate code for a receive iCode */
8725 /*-----------------------------------------------------------------*/
8727 genReceive (iCode * ic)
8729 D(emitcode (";", "genReceive"));
8731 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8732 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8733 IS_TRUE_SYMOP (IC_RESULT (ic))))
8736 int size = getSize (operandType (IC_RESULT (ic)));
8737 int offset = fReturnSizeMCS51 - size;
8740 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8741 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8744 aopOp (IC_RESULT (ic), ic, FALSE);
8745 size = AOP_SIZE (IC_RESULT (ic));
8749 emitcode ("pop", "acc");
8750 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8757 aopOp (IC_RESULT (ic), ic, FALSE);
8759 assignResultValue (IC_RESULT (ic));
8762 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8765 /*-----------------------------------------------------------------*/
8766 /* gen51Code - generate code for 8051 based controllers */
8767 /*-----------------------------------------------------------------*/
8769 gen51Code (iCode * lic)
8774 lineHead = lineCurr = NULL;
8776 /* print the allocation information */
8778 printAllocInfo (currFunc, codeOutFile);
8779 /* if debug information required */
8780 if (options.debug && currFunc)
8782 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8784 if (IS_STATIC (currFunc->etype))
8785 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8787 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8790 /* stack pointer name */
8791 if (options.useXstack)
8797 for (ic = lic; ic; ic = ic->next)
8800 if (cln != ic->lineno)
8805 emitcode ("", "C$%s$%d$%d$%d ==.",
8806 FileBaseName (ic->filename), ic->lineno,
8807 ic->level, ic->block);
8810 emitcode (";", "%s %d", ic->filename, ic->lineno);
8813 /* if the result is marked as
8814 spilt and rematerializable or code for
8815 this has already been generated then
8817 if (resultRemat (ic) || ic->generated)
8820 /* depending on the operation */
8840 /* IPOP happens only when trying to restore a
8841 spilt live range, if there is an ifx statement
8842 following this pop then the if statement might
8843 be using some of the registers being popped which
8844 would destory the contents of the register so
8845 we need to check for this condition and handle it */
8847 ic->next->op == IFX &&
8848 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8849 genIfx (ic->next, ic);
8867 genEndFunction (ic);
8887 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8904 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8908 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8915 /* note these two are xlated by algebraic equivalence
8916 during parsing SDCC.y */
8917 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8918 "got '>=' or '<=' shouldn't have come here");
8922 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8934 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8938 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8942 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8969 case GET_VALUE_AT_ADDRESS:
8970 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_LEFT(ic)))));
8974 if (POINTER_SET (ic))
8975 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9001 addSet (&_G.sendSet, ic);
9010 /* now we are ready to call the
9011 peep hole optimizer */
9012 if (!options.nopeep)
9013 peepHole (&lineHead);
9015 /* now do the actual printing */
9016 printLine (lineHead, codeOutFile);