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);
397 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
401 sprintf (buffer, "(%s %c 0x%04x)",
402 OP_SYMBOL (IC_LEFT (ic))->rname,
403 val >= 0 ? '+' : '-',
406 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
408 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
409 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
410 /* set immd2 field if required */
411 if (aop->aopu.aop_immd.from_cast_remat) {
412 sprintf(buffer,"#0x%02x",ptr_type);
413 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
414 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
420 /*-----------------------------------------------------------------*/
421 /* regsInCommon - two operands have some registers in common */
422 /*-----------------------------------------------------------------*/
424 regsInCommon (operand * op1, operand * op2)
429 /* if they have registers in common */
430 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
433 sym1 = OP_SYMBOL (op1);
434 sym2 = OP_SYMBOL (op2);
436 if (sym1->nRegs == 0 || sym2->nRegs == 0)
439 for (i = 0; i < sym1->nRegs; i++)
445 for (j = 0; j < sym2->nRegs; j++)
450 if (sym2->regs[j] == sym1->regs[i])
458 /*-----------------------------------------------------------------*/
459 /* operandsEqu - equivalent */
460 /*-----------------------------------------------------------------*/
462 operandsEqu (operand * op1, operand * op2)
466 /* if they not symbols */
467 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
470 sym1 = OP_SYMBOL (op1);
471 sym2 = OP_SYMBOL (op2);
473 /* if both are itemps & one is spilt
474 and the other is not then false */
475 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
476 sym1->isspilt != sym2->isspilt)
479 /* if they are the same */
483 if (strcmp (sym1->rname, sym2->rname) == 0)
487 /* if left is a tmp & right is not */
488 if (IS_ITEMP (op1) &&
491 (sym1->usl.spillLoc == sym2))
494 if (IS_ITEMP (op2) &&
498 (sym2->usl.spillLoc == sym1))
504 /*-----------------------------------------------------------------*/
505 /* sameRegs - two asmops have the same registers */
506 /*-----------------------------------------------------------------*/
508 sameRegs (asmop * aop1, asmop * aop2)
515 if (aop1->type != AOP_REG ||
516 aop2->type != AOP_REG)
519 if (aop1->size != aop2->size)
522 for (i = 0; i < aop1->size; i++)
523 if (aop1->aopu.aop_reg[i] !=
524 aop2->aopu.aop_reg[i])
530 /*-----------------------------------------------------------------*/
531 /* aopOp - allocates an asmop for an operand : */
532 /*-----------------------------------------------------------------*/
534 aopOp (operand * op, iCode * ic, bool result)
543 /* if this a literal */
544 if (IS_OP_LITERAL (op))
546 op->aop = aop = newAsmop (AOP_LIT);
547 aop->aopu.aop_lit = op->operand.valOperand;
548 aop->size = getSize (operandType (op));
552 /* if already has a asmop then continue */
556 /* if the underlying symbol has a aop */
557 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
559 op->aop = OP_SYMBOL (op)->aop;
563 /* if this is a true symbol */
564 if (IS_TRUE_SYMOP (op))
566 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
570 /* this is a temporary : this has
576 e) can be a return use only */
578 sym = OP_SYMBOL (op);
580 /* if the type is a conditional */
581 if (sym->regType == REG_CND)
583 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
588 /* if it is spilt then two situations
590 b) has a spill location */
591 if (sym->isspilt || sym->nRegs == 0)
594 /* rematerialize it NOW */
597 sym->aop = op->aop = aop =
599 aop->size = getSize (sym->type);
606 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
607 aop->size = getSize (sym->type);
608 for (i = 0; i < 2; i++)
609 aop->aopu.aop_str[i] = accUse[i];
617 aop = op->aop = sym->aop = newAsmop (AOP_STR);
618 aop->size = getSize (sym->type);
619 for (i = 0; i < fReturnSizeMCS51; i++)
620 aop->aopu.aop_str[i] = fReturn[i];
624 /* else spill location */
625 sym->aop = op->aop = aop =
626 aopForSym (ic, sym->usl.spillLoc, result);
627 aop->size = getSize (sym->type);
631 /* must be in a register */
632 sym->aop = op->aop = aop = newAsmop (AOP_REG);
633 aop->size = sym->nRegs;
634 for (i = 0; i < sym->nRegs; i++)
635 aop->aopu.aop_reg[i] = sym->regs[i];
638 /*-----------------------------------------------------------------*/
639 /* freeAsmop - free up the asmop given to an operand */
640 /*----------------------------------------------------------------*/
642 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
659 /* depending on the asmop type only three cases need work AOP_RO
660 , AOP_R1 && AOP_STK */
668 emitcode ("pop", "ar0");
672 bitVectUnSetBit (ic->rUsed, R0_IDX);
680 emitcode ("pop", "ar1");
684 bitVectUnSetBit (ic->rUsed, R1_IDX);
690 int stk = aop->aopu.aop_stk + aop->size;
691 bitVectUnSetBit (ic->rUsed, R0_IDX);
692 bitVectUnSetBit (ic->rUsed, R1_IDX);
694 getFreePtr (ic, &aop, FALSE);
698 emitcode ("mov", "a,_bp");
699 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
700 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
704 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
709 emitcode ("pop", "acc");
710 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
713 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
716 freeAsmop (op, NULL, ic, TRUE);
719 emitcode ("pop", "ar0");
725 emitcode ("pop", "ar1");
732 /* all other cases just dealloc */
738 OP_SYMBOL (op)->aop = NULL;
739 /* if the symbol has a spill */
741 SPIL_LOC (op)->aop = NULL;
746 /*-----------------------------------------------------------------*/
747 /* aopGet - for fetching value of the aop */
748 /*-----------------------------------------------------------------*/
750 aopGet (asmop * aop, int offset, bool bit16, bool dname)
755 /* offset is greater than
757 if (offset > (aop->size - 1) &&
758 aop->type != AOP_LIT)
761 /* depending on type */
767 /* if we need to increment it */
768 while (offset > aop->coff)
770 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
774 while (offset < aop->coff)
776 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
783 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
784 return (dname ? "acc" : "a");
786 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
787 rs = Safe_calloc (1, strlen (s) + 1);
792 while (offset > aop->coff)
794 emitcode ("inc", "dptr");
798 while (offset < aop->coff)
800 emitcode ("lcall", "__decdptr");
807 emitcode ("clr", "a");
808 emitcode ("movc", "a,@a+dptr");
812 emitcode ("movx", "a,@dptr");
814 return (dname ? "acc" : "a");
818 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
819 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
821 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
823 sprintf (s, "#(%s >> %d)",
824 aop->aopu.aop_immd.aop_immd1,
828 aop->aopu.aop_immd.aop_immd1);
829 rs = Safe_calloc (1, strlen (s) + 1);
835 sprintf (s, "(%s + %d)",
839 sprintf (s, "%s", aop->aopu.aop_dir);
840 rs = Safe_calloc (1, strlen (s) + 1);
846 return aop->aopu.aop_reg[offset]->dname;
848 return aop->aopu.aop_reg[offset]->name;
851 emitcode ("clr", "a");
852 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
853 emitcode ("rlc", "a");
854 return (dname ? "acc" : "a");
857 if (!offset && dname)
859 return aop->aopu.aop_str[offset];
862 return aopLiteral (aop->aopu.aop_lit, offset);
866 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
870 return aop->aopu.aop_str[offset];
874 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
875 "aopget got unsupported aop->type");
878 /*-----------------------------------------------------------------*/
879 /* aopPut - puts a string for a aop */
880 /*-----------------------------------------------------------------*/
882 aopPut (asmop * aop, char *s, int offset)
886 if (aop->size && offset > (aop->size - 1))
888 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
889 "aopPut got offset > aop->size");
893 /* will assign value to value */
894 /* depending on where it is ofcourse */
899 sprintf (d, "(%s + %d)",
900 aop->aopu.aop_dir, offset);
902 sprintf (d, "%s", aop->aopu.aop_dir);
905 emitcode ("mov", "%s,%s", d, s);
910 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
911 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
914 strcmp (s, "r0") == 0 ||
915 strcmp (s, "r1") == 0 ||
916 strcmp (s, "r2") == 0 ||
917 strcmp (s, "r3") == 0 ||
918 strcmp (s, "r4") == 0 ||
919 strcmp (s, "r5") == 0 ||
920 strcmp (s, "r6") == 0 ||
921 strcmp (s, "r7") == 0)
922 emitcode ("mov", "%s,%s",
923 aop->aopu.aop_reg[offset]->dname, s);
925 emitcode ("mov", "%s,%s",
926 aop->aopu.aop_reg[offset]->name, s);
933 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
934 "aopPut writting to code space");
938 while (offset > aop->coff)
941 emitcode ("inc", "dptr");
944 while (offset < aop->coff)
947 emitcode ("lcall", "__decdptr");
952 /* if not in accumulater */
955 emitcode ("movx", "@dptr,a");
960 while (offset > aop->coff)
963 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
965 while (offset < aop->coff)
968 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
975 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
981 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
983 else if (strcmp (s, "r0") == 0 ||
984 strcmp (s, "r1") == 0 ||
985 strcmp (s, "r2") == 0 ||
986 strcmp (s, "r3") == 0 ||
987 strcmp (s, "r4") == 0 ||
988 strcmp (s, "r5") == 0 ||
989 strcmp (s, "r6") == 0 ||
990 strcmp (s, "r7") == 0)
993 sprintf (buffer, "a%s", s);
994 emitcode ("mov", "@%s,%s",
995 aop->aopu.aop_ptr->name, buffer);
998 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1003 if (strcmp (s, "a") == 0)
1004 emitcode ("push", "acc");
1008 emitcode ("push", "acc");
1010 emitcode ("push", s);
1016 /* if bit variable */
1017 if (!aop->aopu.aop_dir)
1019 emitcode ("clr", "a");
1020 emitcode ("rlc", "a");
1025 emitcode ("clr", "%s", aop->aopu.aop_dir);
1027 emitcode ("setb", "%s", aop->aopu.aop_dir);
1028 else if (!strcmp (s, "c"))
1029 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1032 if (strcmp (s, "a"))
1037 symbol *lbl = newiTempLabel (NULL);
1038 emitcode ("clr", "c");
1039 emitcode ("jz", "%05d$", lbl->key + 100);
1040 emitcode ("cpl", "c");
1041 emitcode ("", "%05d$:", lbl->key + 100);
1042 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1050 if (strcmp (aop->aopu.aop_str[offset], s))
1051 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1056 if (!offset && (strcmp (s, "acc") == 0))
1059 if (strcmp (aop->aopu.aop_str[offset], s))
1060 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1064 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1065 "aopPut got unsupported aop->type");
1073 /*-----------------------------------------------------------------*/
1074 /* pointToEnd :- points to the last byte of the operand */
1075 /*-----------------------------------------------------------------*/
1077 pointToEnd (asmop * aop)
1083 aop->coff = count = (aop->size - 1);
1089 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1093 emitcode ("inc", "dptr");
1100 /*-----------------------------------------------------------------*/
1101 /* reAdjustPreg - points a register back to where it should */
1102 /*-----------------------------------------------------------------*/
1104 reAdjustPreg (asmop * aop)
1106 if ((aop->coff==0) || aop->size <= 1)
1114 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1119 emitcode ("lcall", "__decdptr");
1126 #define AOP(op) op->aop
1127 #define AOP_TYPE(op) AOP(op)->type
1128 #define AOP_SIZE(op) AOP(op)->size
1129 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1130 AOP_TYPE(x) == AOP_R0))
1132 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1133 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1135 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1136 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1137 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1139 /*-----------------------------------------------------------------*/
1140 /* genNotFloat - generates not for float operations */
1141 /*-----------------------------------------------------------------*/
1143 genNotFloat (operand * op, operand * res)
1149 D(emitcode (";", "genNotFloat"));
1151 /* we will put 127 in the first byte of
1153 aopPut (AOP (res), "#127", 0);
1154 size = AOP_SIZE (op) - 1;
1157 l = aopGet (op->aop, offset++, FALSE, FALSE);
1162 emitcode ("orl", "a,%s",
1164 offset++, FALSE, FALSE));
1167 tlbl = newiTempLabel (NULL);
1168 aopPut (res->aop, one, 1);
1169 emitcode ("jz", "%05d$", (tlbl->key + 100));
1170 aopPut (res->aop, zero, 1);
1171 emitcode ("", "%05d$:", (tlbl->key + 100));
1173 size = res->aop->size - 2;
1175 /* put zeros in the rest */
1177 aopPut (res->aop, zero, offset++);
1180 /*-----------------------------------------------------------------*/
1181 /* opIsGptr: returns non-zero if the passed operand is */
1182 /* a generic pointer type. */
1183 /*-----------------------------------------------------------------*/
1185 opIsGptr (operand * op)
1187 sym_link *type = operandType (op);
1189 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1196 /*-----------------------------------------------------------------*/
1197 /* getDataSize - get the operand data size */
1198 /*-----------------------------------------------------------------*/
1200 getDataSize (operand * op)
1203 size = AOP_SIZE (op);
1204 if (size == GPTRSIZE)
1206 sym_link *type = operandType (op);
1207 if (IS_GENPTR (type))
1209 /* generic pointer; arithmetic operations
1210 * should ignore the high byte (pointer type).
1218 /*-----------------------------------------------------------------*/
1219 /* outAcc - output Acc */
1220 /*-----------------------------------------------------------------*/
1222 outAcc (operand * result)
1225 size = getDataSize (result);
1228 aopPut (AOP (result), "a", 0);
1231 /* unsigned or positive */
1234 aopPut (AOP (result), zero, offset++);
1239 /*-----------------------------------------------------------------*/
1240 /* outBitC - output a bit C */
1241 /*-----------------------------------------------------------------*/
1243 outBitC (operand * result)
1245 /* if the result is bit */
1246 if (AOP_TYPE (result) == AOP_CRY)
1247 aopPut (AOP (result), "c", 0);
1250 emitcode ("clr", "a");
1251 emitcode ("rlc", "a");
1256 /*-----------------------------------------------------------------*/
1257 /* toBoolean - emit code for orl a,operator(sizeop) */
1258 /*-----------------------------------------------------------------*/
1260 toBoolean (operand * oper)
1262 int size = AOP_SIZE (oper) - 1;
1264 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1266 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1270 /*-----------------------------------------------------------------*/
1271 /* genNot - generate code for ! operation */
1272 /*-----------------------------------------------------------------*/
1277 sym_link *optype = operandType (IC_LEFT (ic));
1279 D(emitcode (";", "genNot"));
1281 /* assign asmOps to operand & result */
1282 aopOp (IC_LEFT (ic), ic, FALSE);
1283 aopOp (IC_RESULT (ic), ic, TRUE);
1285 /* if in bit space then a special case */
1286 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1288 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1289 emitcode ("cpl", "c");
1290 outBitC (IC_RESULT (ic));
1294 /* if type float then do float */
1295 if (IS_FLOAT (optype))
1297 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1301 toBoolean (IC_LEFT (ic));
1303 tlbl = newiTempLabel (NULL);
1304 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1305 emitcode ("", "%05d$:", tlbl->key + 100);
1306 outBitC (IC_RESULT (ic));
1309 /* release the aops */
1310 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1311 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1315 /*-----------------------------------------------------------------*/
1316 /* genCpl - generate code for complement */
1317 /*-----------------------------------------------------------------*/
1325 D(emitcode (";", "genCpl"));
1327 /* assign asmOps to operand & result */
1328 aopOp (IC_LEFT (ic), ic, FALSE);
1329 aopOp (IC_RESULT (ic), ic, TRUE);
1331 /* if both are in bit space then
1333 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1334 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1337 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1338 emitcode ("cpl", "c");
1339 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1343 size = AOP_SIZE (IC_RESULT (ic));
1346 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1348 emitcode ("cpl", "a");
1349 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1354 /* release the aops */
1355 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1356 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1359 /*-----------------------------------------------------------------*/
1360 /* genUminusFloat - unary minus for floating points */
1361 /*-----------------------------------------------------------------*/
1363 genUminusFloat (operand * op, operand * result)
1365 int size, offset = 0;
1368 D(emitcode (";", "genUminusFloat"));
1370 /* for this we just need to flip the
1371 first it then copy the rest in place */
1372 size = AOP_SIZE (op) - 1;
1373 l = aopGet (AOP (op), 3, FALSE, FALSE);
1377 emitcode ("cpl", "acc.7");
1378 aopPut (AOP (result), "a", 3);
1382 aopPut (AOP (result),
1383 aopGet (AOP (op), offset, FALSE, FALSE),
1389 /*-----------------------------------------------------------------*/
1390 /* genUminus - unary minus code generation */
1391 /*-----------------------------------------------------------------*/
1393 genUminus (iCode * ic)
1396 sym_link *optype, *rtype;
1399 D(emitcode (";", "genUminus"));
1402 aopOp (IC_LEFT (ic), ic, FALSE);
1403 aopOp (IC_RESULT (ic), ic, TRUE);
1405 /* if both in bit space then special
1407 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1408 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1411 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1412 emitcode ("cpl", "c");
1413 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1417 optype = operandType (IC_LEFT (ic));
1418 rtype = operandType (IC_RESULT (ic));
1420 /* if float then do float stuff */
1421 if (IS_FLOAT (optype))
1423 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1427 /* otherwise subtract from zero */
1428 size = AOP_SIZE (IC_LEFT (ic));
1433 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1434 if (!strcmp (l, "a"))
1438 emitcode ("cpl", "a");
1439 emitcode ("addc", "a,#0");
1445 emitcode ("clr", "a");
1446 emitcode ("subb", "a,%s", l);
1448 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1451 /* if any remaining bytes in the result */
1452 /* we just need to propagate the sign */
1453 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1455 emitcode ("rlc", "a");
1456 emitcode ("subb", "a,acc");
1458 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1462 /* release the aops */
1463 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1464 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1467 /*-----------------------------------------------------------------*/
1468 /* saveRegisters - will look for a call and save the registers */
1469 /*-----------------------------------------------------------------*/
1471 saveRegisters (iCode * lic)
1478 for (ic = lic; ic; ic = ic->next)
1479 if (ic->op == CALL || ic->op == PCALL)
1484 fprintf (stderr, "found parameter push with no function call\n");
1488 /* if the registers have been saved already or don't need to be then
1490 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1491 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1494 /* safe the registers in use at this time but skip the
1495 ones for the result */
1496 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1497 mcs51_rUmaskForOp (IC_RESULT(ic)));
1500 if (options.useXstack)
1502 if (bitVectBitValue (rsave, R0_IDX))
1503 emitcode ("mov", "b,r0");
1504 emitcode ("mov", "r0,%s", spname);
1505 for (i = 0; i < mcs51_nRegs; i++)
1507 if (bitVectBitValue (rsave, i))
1510 emitcode ("mov", "a,b");
1512 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1513 emitcode ("movx", "@r0,a");
1514 emitcode ("inc", "r0");
1517 emitcode ("mov", "%s,r0", spname);
1518 if (bitVectBitValue (rsave, R0_IDX))
1519 emitcode ("mov", "r0,b");
1522 for (i = 0; i < mcs51_nRegs; i++)
1524 if (bitVectBitValue (rsave, i))
1525 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1529 /*-----------------------------------------------------------------*/
1530 /* unsaveRegisters - pop the pushed registers */
1531 /*-----------------------------------------------------------------*/
1533 unsaveRegisters (iCode * ic)
1538 /* restore the registers in use at this time but skip the
1539 ones for the result */
1540 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1541 mcs51_rUmaskForOp (IC_RESULT(ic)));
1543 if (options.useXstack)
1545 emitcode ("mov", "r0,%s", spname);
1546 for (i = mcs51_nRegs; i >= 0; i--)
1548 if (bitVectBitValue (rsave, i))
1550 emitcode ("dec", "r0");
1551 emitcode ("movx", "a,@r0");
1553 emitcode ("mov", "b,a");
1555 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1559 emitcode ("mov", "%s,r0", spname);
1560 if (bitVectBitValue (rsave, R0_IDX))
1561 emitcode ("mov", "r0,b");
1564 for (i = mcs51_nRegs; i >= 0; i--)
1566 if (bitVectBitValue (rsave, i))
1567 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1573 /*-----------------------------------------------------------------*/
1575 /*-----------------------------------------------------------------*/
1577 pushSide (operand * oper, int size)
1582 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1583 if (AOP_TYPE (oper) != AOP_REG &&
1584 AOP_TYPE (oper) != AOP_DIR &&
1587 emitcode ("mov", "a,%s", l);
1588 emitcode ("push", "acc");
1591 emitcode ("push", "%s", l);
1595 /*-----------------------------------------------------------------*/
1596 /* assignResultValue - */
1597 /*-----------------------------------------------------------------*/
1599 assignResultValue (operand * oper)
1602 int size = AOP_SIZE (oper);
1605 aopPut (AOP (oper), fReturn[offset], offset);
1611 /*-----------------------------------------------------------------*/
1612 /* genXpush - pushes onto the external stack */
1613 /*-----------------------------------------------------------------*/
1615 genXpush (iCode * ic)
1617 asmop *aop = newAsmop (0);
1619 int size, offset = 0;
1621 D(emitcode (";", "genXpush"));
1623 aopOp (IC_LEFT (ic), ic, FALSE);
1624 r = getFreePtr (ic, &aop, FALSE);
1627 emitcode ("mov", "%s,_spx", r->name);
1629 size = AOP_SIZE (IC_LEFT (ic));
1633 char *l = aopGet (AOP (IC_LEFT (ic)),
1634 offset++, FALSE, FALSE);
1636 emitcode ("movx", "@%s,a", r->name);
1637 emitcode ("inc", "%s", r->name);
1642 emitcode ("mov", "_spx,%s", r->name);
1644 freeAsmop (NULL, aop, ic, TRUE);
1645 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1648 /*-----------------------------------------------------------------*/
1649 /* genIpush - genrate code for pushing this gets a little complex */
1650 /*-----------------------------------------------------------------*/
1652 genIpush (iCode * ic)
1654 int size, offset = 0;
1657 D(emitcode (";", "genIpush"));
1659 /* if this is not a parm push : ie. it is spill push
1660 and spill push is always done on the local stack */
1664 /* and the item is spilt then do nothing */
1665 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1668 aopOp (IC_LEFT (ic), ic, FALSE);
1669 size = AOP_SIZE (IC_LEFT (ic));
1670 /* push it on the stack */
1673 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1679 emitcode ("push", "%s", l);
1684 /* this is a paramter push: in this case we call
1685 the routine to find the call and save those
1686 registers that need to be saved */
1689 /* if use external stack then call the external
1690 stack pushing routine */
1691 if (options.useXstack)
1697 /* then do the push */
1698 aopOp (IC_LEFT (ic), ic, FALSE);
1701 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1702 size = AOP_SIZE (IC_LEFT (ic));
1706 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1707 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1708 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1711 emitcode ("mov", "a,%s", l);
1712 emitcode ("push", "acc");
1715 emitcode ("push", "%s", l);
1718 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1721 /*-----------------------------------------------------------------*/
1722 /* genIpop - recover the registers: can happen only for spilling */
1723 /*-----------------------------------------------------------------*/
1725 genIpop (iCode * ic)
1729 D(emitcode (";", "genIpop"));
1731 /* if the temp was not pushed then */
1732 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1735 aopOp (IC_LEFT (ic), ic, FALSE);
1736 size = AOP_SIZE (IC_LEFT (ic));
1737 offset = (size - 1);
1739 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1742 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1745 /*-----------------------------------------------------------------*/
1746 /* unsaveRBank - restores the resgister bank from stack */
1747 /*-----------------------------------------------------------------*/
1749 unsaveRBank (int bank, iCode * ic, bool popPsw)
1755 if (options.useXstack)
1759 /* Assume r0 is available for use. */
1760 r = mcs51_regWithIdx (R0_IDX);;
1765 r = getFreePtr (ic, &aop, FALSE);
1767 emitcode ("mov", "%s,_spx", r->name);
1772 if (options.useXstack)
1774 emitcode ("movx", "a,@%s", r->name);
1775 emitcode ("mov", "psw,a");
1776 emitcode ("dec", "%s", r->name);
1780 emitcode ("pop", "psw");
1784 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1786 if (options.useXstack)
1788 emitcode ("movx", "a,@%s", r->name);
1789 emitcode ("mov", "(%s+%d),a",
1790 regs8051[i].base, 8 * bank + regs8051[i].offset);
1791 emitcode ("dec", "%s", r->name);
1795 emitcode ("pop", "(%s+%d)",
1796 regs8051[i].base, 8 * bank + regs8051[i].offset);
1799 if (options.useXstack)
1801 emitcode ("mov", "_spx,%s", r->name);
1806 freeAsmop (NULL, aop, ic, TRUE);
1810 /*-----------------------------------------------------------------*/
1811 /* saveRBank - saves an entire register bank on the stack */
1812 /*-----------------------------------------------------------------*/
1814 saveRBank (int bank, iCode * ic, bool pushPsw)
1820 if (options.useXstack)
1824 /* Assume r0 is available for use. */
1825 r = mcs51_regWithIdx (R0_IDX);;
1830 r = getFreePtr (ic, &aop, FALSE);
1832 emitcode ("mov", "%s,_spx", r->name);
1835 for (i = 0; i < mcs51_nRegs; i++)
1837 if (options.useXstack)
1839 emitcode ("inc", "%s", r->name);
1840 emitcode ("mov", "a,(%s+%d)",
1841 regs8051[i].base, 8 * bank + regs8051[i].offset);
1842 emitcode ("movx", "@%s,a", r->name);
1845 emitcode ("push", "(%s+%d)",
1846 regs8051[i].base, 8 * bank + regs8051[i].offset);
1851 if (options.useXstack)
1853 emitcode ("mov", "a,psw");
1854 emitcode ("movx", "@%s,a", r->name);
1855 emitcode ("inc", "%s", r->name);
1856 emitcode ("mov", "_spx,%s", r->name);
1861 emitcode ("push", "psw");
1864 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1869 freeAsmop (NULL, aop, ic, TRUE);
1878 /*-----------------------------------------------------------------*/
1879 /* genCall - generates a call statement */
1880 /*-----------------------------------------------------------------*/
1882 genCall (iCode * ic)
1885 bool restoreBank = FALSE;
1886 bool swapBanks = FALSE;
1888 D(emitcode(";", "genCall"));
1890 /* if send set is not empty the assign */
1895 for (sic = setFirstItem (_G.sendSet); sic;
1896 sic = setNextItem (_G.sendSet))
1898 int size, offset = 0;
1899 aopOp (IC_LEFT (sic), sic, FALSE);
1900 size = AOP_SIZE (IC_LEFT (sic));
1903 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1905 if (strcmp (l, fReturn[offset]))
1906 emitcode ("mov", "%s,%s",
1911 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1916 /* if we are calling a not _naked function that is not using
1917 the same register bank then we need to save the
1918 destination registers on the stack */
1919 dtype = operandType (IC_LEFT (ic));
1920 if (dtype && !IFFUNC_ISNAKED(dtype) &&
1921 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1922 IFFUNC_ISISR (currFunc->type))
1926 /* This is unexpected; the bank should have been saved in
1929 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1935 /* if caller saves & we have not saved then */
1941 emitcode ("mov", "psw,#0x%02x",
1942 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1946 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1947 OP_SYMBOL (IC_LEFT (ic))->rname :
1948 OP_SYMBOL (IC_LEFT (ic))->name));
1952 emitcode ("mov", "psw,#0x%02x",
1953 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1956 /* if we need assign a result value */
1957 if ((IS_ITEMP (IC_RESULT (ic)) &&
1958 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1959 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1960 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1961 IS_TRUE_SYMOP (IC_RESULT (ic)))
1965 aopOp (IC_RESULT (ic), ic, FALSE);
1968 assignResultValue (IC_RESULT (ic));
1970 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1973 /* adjust the stack for parameters if
1978 if (ic->parmBytes > 3)
1980 emitcode ("mov", "a,%s", spname);
1981 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1982 emitcode ("mov", "%s,a", spname);
1985 for (i = 0; i < ic->parmBytes; i++)
1986 emitcode ("dec", "%s", spname);
1989 /* if we hade saved some registers then unsave them */
1990 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1991 unsaveRegisters (ic);
1993 /* if register bank was saved then pop them */
1995 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1998 /*-----------------------------------------------------------------*/
1999 /* genPcall - generates a call by pointer statement */
2000 /*-----------------------------------------------------------------*/
2002 genPcall (iCode * ic)
2005 symbol *rlbl = newiTempLabel (NULL);
2006 bool restoreBank=FALSE;
2008 D(emitcode(";", "genPCall"));
2010 /* if caller saves & we have not saved then */
2014 /* if we are calling a function that is not using
2015 the same register bank then we need to save the
2016 destination registers on the stack */
2017 dtype = operandType (IC_LEFT (ic));
2018 if (dtype && !FUNC_ISNAKED(dtype) &&
2019 IFFUNC_ISISR (currFunc->type) &&
2020 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2021 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2025 /* push the return address on to the stack */
2026 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2027 emitcode ("push", "acc");
2028 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2029 emitcode ("push", "acc");
2031 /* now push the calling address */
2032 aopOp (IC_LEFT (ic), ic, FALSE);
2034 pushSide (IC_LEFT (ic), FPTRSIZE);
2036 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2038 /* if send set is not empty the assign */
2043 for (sic = setFirstItem (_G.sendSet); sic;
2044 sic = setNextItem (_G.sendSet))
2046 int size, offset = 0;
2047 aopOp (IC_LEFT (sic), sic, FALSE);
2048 size = AOP_SIZE (IC_LEFT (sic));
2051 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2053 if (strcmp (l, fReturn[offset]))
2054 emitcode ("mov", "%s,%s",
2059 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2064 emitcode ("ret", "");
2065 emitcode ("", "%05d$:", (rlbl->key + 100));
2068 /* if we need assign a result value */
2069 if ((IS_ITEMP (IC_RESULT (ic)) &&
2070 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2071 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2072 IS_TRUE_SYMOP (IC_RESULT (ic)))
2076 aopOp (IC_RESULT (ic), ic, FALSE);
2079 assignResultValue (IC_RESULT (ic));
2081 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2084 /* adjust the stack for parameters if
2089 if (ic->parmBytes > 3)
2091 emitcode ("mov", "a,%s", spname);
2092 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2093 emitcode ("mov", "%s,a", spname);
2096 for (i = 0; i < ic->parmBytes; i++)
2097 emitcode ("dec", "%s", spname);
2101 /* if register bank was saved then unsave them */
2103 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2105 /* if we hade saved some registers then
2107 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2108 unsaveRegisters (ic);
2111 /*-----------------------------------------------------------------*/
2112 /* resultRemat - result is rematerializable */
2113 /*-----------------------------------------------------------------*/
2115 resultRemat (iCode * ic)
2117 if (SKIP_IC (ic) || ic->op == IFX)
2120 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2122 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2123 if (sym->remat && !POINTER_SET (ic))
2130 #if defined(__BORLANDC__) || defined(_MSC_VER)
2131 #define STRCASECMP stricmp
2133 #define STRCASECMP strcasecmp
2136 /*-----------------------------------------------------------------*/
2137 /* inExcludeList - return 1 if the string is in exclude Reg list */
2138 /*-----------------------------------------------------------------*/
2140 inExcludeList (char *s)
2144 if (options.excludeRegs[i] &&
2145 STRCASECMP (options.excludeRegs[i], "none") == 0)
2148 for (i = 0; options.excludeRegs[i]; i++)
2150 if (options.excludeRegs[i] &&
2151 STRCASECMP (s, options.excludeRegs[i]) == 0)
2157 /*-----------------------------------------------------------------*/
2158 /* genFunction - generated code for function entry */
2159 /*-----------------------------------------------------------------*/
2161 genFunction (iCode * ic)
2165 bool switchedPSW = FALSE;
2168 /* create the function header */
2169 emitcode (";", "-----------------------------------------");
2170 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2171 emitcode (";", "-----------------------------------------");
2173 emitcode ("", "%s:", sym->rname);
2174 ftype = operandType (IC_LEFT (ic));
2176 if (IFFUNC_ISNAKED(ftype))
2178 emitcode(";", "naked function: no prologue.");
2182 /* if critical function then turn interrupts off */
2183 if (IFFUNC_ISCRITICAL (ftype))
2184 emitcode ("clr", "ea");
2186 /* here we need to generate the equates for the
2187 register bank if required */
2188 if (FUNC_REGBANK (ftype) != rbank)
2192 rbank = FUNC_REGBANK (ftype);
2193 for (i = 0; i < mcs51_nRegs; i++)
2195 if (strcmp (regs8051[i].base, "0") == 0)
2196 emitcode ("", "%s = 0x%02x",
2198 8 * rbank + regs8051[i].offset);
2200 emitcode ("", "%s = %s + 0x%02x",
2203 8 * rbank + regs8051[i].offset);
2207 /* if this is an interrupt service routine then
2208 save acc, b, dpl, dph */
2209 if (IFFUNC_ISISR (sym->type))
2212 if (!inExcludeList ("acc"))
2213 emitcode ("push", "acc");
2214 if (!inExcludeList ("b"))
2215 emitcode ("push", "b");
2216 if (!inExcludeList ("dpl"))
2217 emitcode ("push", "dpl");
2218 if (!inExcludeList ("dph"))
2219 emitcode ("push", "dph");
2220 /* if this isr has no bank i.e. is going to
2221 run with bank 0 , then we need to save more
2223 if (!FUNC_REGBANK (sym->type))
2226 /* if this function does not call any other
2227 function then we can be economical and
2228 save only those registers that are used */
2229 if (!IFFUNC_HASFCALL(sym->type))
2233 /* if any registers used */
2236 /* save the registers used */
2237 for (i = 0; i < sym->regsUsed->size; i++)
2239 if (bitVectBitValue (sym->regsUsed, i) ||
2240 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2241 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2248 /* this function has a function call cannot
2249 determines register usage so we will have to push the
2251 saveRBank (0, ic, FALSE);
2256 /* This ISR uses a non-zero bank.
2258 * We assume that the bank is available for our
2261 * However, if this ISR calls a function which uses some
2262 * other bank, we must save that bank entirely.
2264 unsigned long banksToSave = 0;
2266 if (IFFUNC_HASFCALL(sym->type))
2269 #define MAX_REGISTER_BANKS 4
2274 for (i = ic; i; i = i->next)
2276 if (i->op == ENDFUNCTION)
2278 /* we got to the end OK. */
2286 dtype = operandType (IC_LEFT(i));
2288 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2290 /* Mark this bank for saving. */
2291 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2293 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2297 banksToSave |= (1 << FUNC_REGBANK(dtype));
2300 /* And note that we don't need to do it in
2308 /* This is a mess; we have no idea what
2309 * register bank the called function might
2312 * The only thing I can think of to do is
2313 * throw a warning and hope.
2315 werror(W_FUNCPTR_IN_USING_ISR);
2319 if (banksToSave && options.useXstack)
2321 /* Since we aren't passing it an ic,
2322 * saveRBank will assume r0 is available to abuse.
2324 * So switch to our (trashable) bank now, so
2325 * the caller's R0 isn't trashed.
2327 emitcode ("push", "psw");
2328 emitcode ("mov", "psw,#0x%02x",
2329 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2333 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2335 if (banksToSave & (1 << ix))
2337 saveRBank(ix, NULL, FALSE);
2341 // jwk: this needs a closer look
2342 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2347 /* if callee-save to be used for this function
2348 then save the registers being used in this function */
2349 if (IFFUNC_CALLEESAVES(sym->type))
2353 /* if any registers used */
2356 /* save the registers used */
2357 for (i = 0; i < sym->regsUsed->size; i++)
2359 if (bitVectBitValue (sym->regsUsed, i) ||
2360 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2362 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2370 /* set the register bank to the desired value */
2371 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2374 emitcode ("push", "psw");
2375 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2378 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2381 if (options.useXstack)
2383 emitcode ("mov", "r0,%s", spname);
2384 emitcode ("mov", "a,_bp");
2385 emitcode ("movx", "@r0,a");
2386 emitcode ("inc", "%s", spname);
2390 /* set up the stack */
2391 emitcode ("push", "_bp"); /* save the callers stack */
2393 emitcode ("mov", "_bp,%s", spname);
2396 /* adjust the stack for the function */
2402 werror (W_STACK_OVERFLOW, sym->name);
2404 if (i > 3 && sym->recvSize < 4)
2407 emitcode ("mov", "a,sp");
2408 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2409 emitcode ("mov", "sp,a");
2414 emitcode ("inc", "sp");
2420 emitcode ("mov", "a,_spx");
2421 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2422 emitcode ("mov", "_spx,a");
2427 /*-----------------------------------------------------------------*/
2428 /* genEndFunction - generates epilogue for functions */
2429 /*-----------------------------------------------------------------*/
2431 genEndFunction (iCode * ic)
2433 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2435 if (IFFUNC_ISNAKED(sym->type))
2437 emitcode(";", "naked function: no epilogue.");
2441 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2443 emitcode ("mov", "%s,_bp", spname);
2446 /* if use external stack but some variables were
2447 added to the local stack then decrement the
2449 if (options.useXstack && sym->stack)
2451 emitcode ("mov", "a,sp");
2452 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2453 emitcode ("mov", "sp,a");
2457 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2459 if (options.useXstack)
2461 emitcode ("mov", "r0,%s", spname);
2462 emitcode ("movx", "a,@r0");
2463 emitcode ("mov", "_bp,a");
2464 emitcode ("dec", "%s", spname);
2468 emitcode ("pop", "_bp");
2472 /* restore the register bank */
2473 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2475 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2476 || !options.useXstack)
2478 /* Special case of ISR using non-zero bank with useXstack
2481 emitcode ("pop", "psw");
2485 if (IFFUNC_ISISR (sym->type))
2488 /* now we need to restore the registers */
2489 /* if this isr has no bank i.e. is going to
2490 run with bank 0 , then we need to save more
2492 if (!FUNC_REGBANK (sym->type))
2494 /* if this function does not call any other
2495 function then we can be economical and
2496 save only those registers that are used */
2497 if (!IFFUNC_HASFCALL(sym->type))
2501 /* if any registers used */
2504 /* save the registers used */
2505 for (i = sym->regsUsed->size; i >= 0; i--)
2507 if (bitVectBitValue (sym->regsUsed, i) ||
2508 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2509 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2516 /* this function has a function call cannot
2517 determines register usage so we will have to pop the
2519 unsaveRBank (0, ic, FALSE);
2524 /* This ISR uses a non-zero bank.
2526 * Restore any register banks saved by genFunction
2529 // jwk: this needs a closer look
2530 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2533 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2535 if (savedBanks & (1 << ix))
2537 unsaveRBank(ix, NULL, FALSE);
2541 if (options.useXstack)
2543 /* Restore bank AFTER calling unsaveRBank,
2544 * since it can trash r0.
2546 emitcode ("pop", "psw");
2550 if (!inExcludeList ("dph"))
2551 emitcode ("pop", "dph");
2552 if (!inExcludeList ("dpl"))
2553 emitcode ("pop", "dpl");
2554 if (!inExcludeList ("b"))
2555 emitcode ("pop", "b");
2556 if (!inExcludeList ("acc"))
2557 emitcode ("pop", "acc");
2559 if (IFFUNC_ISCRITICAL (sym->type))
2560 emitcode ("setb", "ea");
2562 /* if debug then send end of function */
2563 /* if (options.debug && currFunc) */
2564 if (options.debug && currFunc)
2567 emitcode ("", "C$%s$%d$%d$%d ==.",
2568 FileBaseName (ic->filename), currFunc->lastLine,
2569 ic->level, ic->block);
2570 if (IS_STATIC (currFunc->etype))
2571 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2573 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2577 emitcode ("reti", "");
2581 if (IFFUNC_ISCRITICAL (sym->type))
2582 emitcode ("setb", "ea");
2584 if (IFFUNC_CALLEESAVES(sym->type))
2588 /* if any registers used */
2591 /* save the registers used */
2592 for (i = sym->regsUsed->size; i >= 0; i--)
2594 if (bitVectBitValue (sym->regsUsed, i) ||
2595 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2596 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2602 /* if debug then send end of function */
2603 if (options.debug && currFunc)
2606 emitcode ("", "C$%s$%d$%d$%d ==.",
2607 FileBaseName (ic->filename), currFunc->lastLine,
2608 ic->level, ic->block);
2609 if (IS_STATIC (currFunc->etype))
2610 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2612 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2616 emitcode ("ret", "");
2621 /*-----------------------------------------------------------------*/
2622 /* genRet - generate code for return statement */
2623 /*-----------------------------------------------------------------*/
2627 int size, offset = 0, pushed = 0;
2629 D(emitcode (";", "genRet"));
2631 /* if we have no return value then
2632 just generate the "ret" */
2636 /* we have something to return then
2637 move the return value into place */
2638 aopOp (IC_LEFT (ic), ic, FALSE);
2639 size = AOP_SIZE (IC_LEFT (ic));
2644 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2647 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2649 emitcode ("push", "%s", l);
2654 l = aopGet (AOP (IC_LEFT (ic)), offset,
2656 if (strcmp (fReturn[offset], l))
2657 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2666 if (strcmp (fReturn[pushed], "a"))
2667 emitcode ("pop", fReturn[pushed]);
2669 emitcode ("pop", "acc");
2672 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2675 /* generate a jump to the return label
2676 if the next is not the return statement */
2677 if (!(ic->next && ic->next->op == LABEL &&
2678 IC_LABEL (ic->next) == returnLabel))
2680 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2684 /*-----------------------------------------------------------------*/
2685 /* genLabel - generates a label */
2686 /*-----------------------------------------------------------------*/
2688 genLabel (iCode * ic)
2690 /* special case never generate */
2691 if (IC_LABEL (ic) == entryLabel)
2694 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2697 /*-----------------------------------------------------------------*/
2698 /* genGoto - generates a ljmp */
2699 /*-----------------------------------------------------------------*/
2701 genGoto (iCode * ic)
2703 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2706 /*-----------------------------------------------------------------*/
2707 /* findLabelBackwards: walks back through the iCode chain looking */
2708 /* for the given label. Returns number of iCode instructions */
2709 /* between that label and given ic. */
2710 /* Returns zero if label not found. */
2711 /*-----------------------------------------------------------------*/
2713 findLabelBackwards (iCode * ic, int key)
2722 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2724 /* printf("findLabelBackwards = %d\n", count); */
2732 /*-----------------------------------------------------------------*/
2733 /* genPlusIncr :- does addition with increment if possible */
2734 /*-----------------------------------------------------------------*/
2736 genPlusIncr (iCode * ic)
2738 unsigned int icount;
2739 unsigned int size = getDataSize (IC_RESULT (ic));
2741 /* will try to generate an increment */
2742 /* if the right side is not a literal
2744 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2747 /* if the literal value of the right hand side
2748 is greater than 4 then it is not worth it */
2749 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2752 D(emitcode (";", "genPlusIncr"));
2754 /* if increment 16 bits in register */
2755 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2763 /* If the next instruction is a goto and the goto target
2764 * is < 10 instructions previous to this, we can generate
2765 * jumps straight to that target.
2767 if (ic->next && ic->next->op == GOTO
2768 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2769 && labelRange <= 10)
2771 emitcode (";", "tail increment optimized");
2772 tlbl = IC_LABEL (ic->next);
2777 tlbl = newiTempLabel (NULL);
2780 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2781 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2782 IS_AOP_PREG (IC_RESULT (ic)))
2783 emitcode ("cjne", "%s,#0x00,%05d$"
2784 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2788 emitcode ("clr", "a");
2789 emitcode ("cjne", "a,%s,%05d$"
2790 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2794 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2797 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2798 IS_AOP_PREG (IC_RESULT (ic)))
2799 emitcode ("cjne", "%s,#0x00,%05d$"
2800 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2803 emitcode ("cjne", "a,%s,%05d$"
2804 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2807 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2811 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2812 IS_AOP_PREG (IC_RESULT (ic)))
2813 emitcode ("cjne", "%s,#0x00,%05d$"
2814 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2818 emitcode ("cjne", "a,%s,%05d$"
2819 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2822 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2827 emitcode ("", "%05d$:", tlbl->key + 100);
2832 /* if the sizes are greater than 1 then we cannot */
2833 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2834 AOP_SIZE (IC_LEFT (ic)) > 1)
2837 /* we can if the aops of the left & result match or
2838 if they are in registers and the registers are the
2840 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2845 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2846 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2847 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2853 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2862 /*-----------------------------------------------------------------*/
2863 /* outBitAcc - output a bit in acc */
2864 /*-----------------------------------------------------------------*/
2866 outBitAcc (operand * result)
2868 symbol *tlbl = newiTempLabel (NULL);
2869 /* if the result is a bit */
2870 if (AOP_TYPE (result) == AOP_CRY)
2872 aopPut (AOP (result), "a", 0);
2876 emitcode ("jz", "%05d$", tlbl->key + 100);
2877 emitcode ("mov", "a,%s", one);
2878 emitcode ("", "%05d$:", tlbl->key + 100);
2883 /*-----------------------------------------------------------------*/
2884 /* genPlusBits - generates code for addition of two bits */
2885 /*-----------------------------------------------------------------*/
2887 genPlusBits (iCode * ic)
2889 D(emitcode (";", "genPlusBits"));
2891 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2893 symbol *lbl = newiTempLabel (NULL);
2894 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2895 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2896 emitcode ("cpl", "c");
2897 emitcode ("", "%05d$:", (lbl->key + 100));
2898 outBitC (IC_RESULT (ic));
2902 emitcode ("clr", "a");
2903 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2904 emitcode ("rlc", "a");
2905 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2906 emitcode ("addc", "a,#0x00");
2907 outAcc (IC_RESULT (ic));
2912 /* This is the original version of this code.
2914 * This is being kept around for reference,
2915 * because I am not entirely sure I got it right...
2918 adjustArithmeticResult (iCode * ic)
2920 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2921 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2922 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2923 aopPut (AOP (IC_RESULT (ic)),
2924 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2927 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2928 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2929 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2930 aopPut (AOP (IC_RESULT (ic)),
2931 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2934 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2935 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2936 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2937 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2938 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2941 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2942 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2946 /* This is the pure and virtuous version of this code.
2947 * I'm pretty certain it's right, but not enough to toss the old
2951 adjustArithmeticResult (iCode * ic)
2953 if (opIsGptr (IC_RESULT (ic)) &&
2954 opIsGptr (IC_LEFT (ic)) &&
2955 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2957 aopPut (AOP (IC_RESULT (ic)),
2958 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2962 if (opIsGptr (IC_RESULT (ic)) &&
2963 opIsGptr (IC_RIGHT (ic)) &&
2964 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2966 aopPut (AOP (IC_RESULT (ic)),
2967 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2971 if (opIsGptr (IC_RESULT (ic)) &&
2972 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2973 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2974 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2975 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2978 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2979 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2984 /*-----------------------------------------------------------------*/
2985 /* genPlus - generates code for addition */
2986 /*-----------------------------------------------------------------*/
2988 genPlus (iCode * ic)
2990 int size, offset = 0;
2992 /* special cases :- */
2994 D(emitcode (";", "genPlus"));
2996 aopOp (IC_LEFT (ic), ic, FALSE);
2997 aopOp (IC_RIGHT (ic), ic, FALSE);
2998 aopOp (IC_RESULT (ic), ic, TRUE);
3000 /* if literal, literal on the right or
3001 if left requires ACC or right is already
3003 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3004 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3005 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3007 operand *t = IC_RIGHT (ic);
3008 IC_RIGHT (ic) = IC_LEFT (ic);
3012 /* if both left & right are in bit
3014 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3015 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3021 /* if left in bit space & right literal */
3022 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3023 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3025 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3026 /* if result in bit space */
3027 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3029 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3030 emitcode ("cpl", "c");
3031 outBitC (IC_RESULT (ic));
3035 size = getDataSize (IC_RESULT (ic));
3038 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3039 emitcode ("addc", "a,#00");
3040 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3046 /* if I can do an increment instead
3047 of add then GOOD for ME */
3048 if (genPlusIncr (ic) == TRUE)
3051 size = getDataSize (IC_RESULT (ic));
3055 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3057 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3059 emitcode ("add", "a,%s",
3060 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3062 emitcode ("addc", "a,%s",
3063 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3067 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3069 emitcode ("add", "a,%s",
3070 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3072 emitcode ("addc", "a,%s",
3073 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3075 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3078 adjustArithmeticResult (ic);
3081 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3082 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3083 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3086 /*-----------------------------------------------------------------*/
3087 /* genMinusDec :- does subtraction with deccrement if possible */
3088 /*-----------------------------------------------------------------*/
3090 genMinusDec (iCode * ic)
3092 unsigned int icount;
3093 unsigned int size = getDataSize (IC_RESULT (ic));
3095 /* will try to generate an increment */
3096 /* if the right side is not a literal
3098 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3101 /* if the literal value of the right hand side
3102 is greater than 4 then it is not worth it */
3103 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3106 D(emitcode (";", "genMinusDec"));
3108 /* if decrement 16 bits in register */
3109 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3117 /* If the next instruction is a goto and the goto target
3118 * is <= 10 instructions previous to this, we can generate
3119 * jumps straight to that target.
3121 if (ic->next && ic->next->op == GOTO
3122 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3123 && labelRange <= 10)
3125 emitcode (";", "tail decrement optimized");
3126 tlbl = IC_LABEL (ic->next);
3131 tlbl = newiTempLabel (NULL);
3135 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3136 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3137 IS_AOP_PREG (IC_RESULT (ic)))
3138 emitcode ("cjne", "%s,#0xff,%05d$"
3139 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3143 emitcode ("mov", "a,#0xff");
3144 emitcode ("cjne", "a,%s,%05d$"
3145 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3148 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3151 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3152 IS_AOP_PREG (IC_RESULT (ic)))
3153 emitcode ("cjne", "%s,#0xff,%05d$"
3154 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3158 emitcode ("cjne", "a,%s,%05d$"
3159 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3162 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3166 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3167 IS_AOP_PREG (IC_RESULT (ic)))
3168 emitcode ("cjne", "%s,#0xff,%05d$"
3169 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3173 emitcode ("cjne", "a,%s,%05d$"
3174 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3177 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3181 emitcode ("", "%05d$:", tlbl->key + 100);
3186 /* if the sizes are greater than 1 then we cannot */
3187 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3188 AOP_SIZE (IC_LEFT (ic)) > 1)
3191 /* we can if the aops of the left & result match or
3192 if they are in registers and the registers are the
3194 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3198 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3206 /*-----------------------------------------------------------------*/
3207 /* addSign - complete with sign */
3208 /*-----------------------------------------------------------------*/
3210 addSign (operand * result, int offset, int sign)
3212 int size = (getDataSize (result) - offset);
3217 emitcode ("rlc", "a");
3218 emitcode ("subb", "a,acc");
3220 aopPut (AOP (result), "a", offset++);
3224 aopPut (AOP (result), zero, offset++);
3228 /*-----------------------------------------------------------------*/
3229 /* genMinusBits - generates code for subtraction of two bits */
3230 /*-----------------------------------------------------------------*/
3232 genMinusBits (iCode * ic)
3234 symbol *lbl = newiTempLabel (NULL);
3236 D(emitcode (";", "genMinusBits"));
3238 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3240 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3241 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3242 emitcode ("cpl", "c");
3243 emitcode ("", "%05d$:", (lbl->key + 100));
3244 outBitC (IC_RESULT (ic));
3248 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3249 emitcode ("subb", "a,acc");
3250 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3251 emitcode ("inc", "a");
3252 emitcode ("", "%05d$:", (lbl->key + 100));
3253 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3254 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3258 /*-----------------------------------------------------------------*/
3259 /* genMinus - generates code for subtraction */
3260 /*-----------------------------------------------------------------*/
3262 genMinus (iCode * ic)
3264 int size, offset = 0;
3265 unsigned long lit = 0L;
3267 D(emitcode (";", "genMinus"));
3269 aopOp (IC_LEFT (ic), ic, FALSE);
3270 aopOp (IC_RIGHT (ic), ic, FALSE);
3271 aopOp (IC_RESULT (ic), ic, TRUE);
3273 /* special cases :- */
3274 /* if both left & right are in bit space */
3275 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3276 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3282 /* if I can do an decrement instead
3283 of subtract then GOOD for ME */
3284 if (genMinusDec (ic) == TRUE)
3287 size = getDataSize (IC_RESULT (ic));
3289 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3295 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3299 /* if literal, add a,#-lit, else normal subb */
3302 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3303 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3304 emitcode ("subb", "a,%s",
3305 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3308 /* first add without previous c */
3310 if (!size && lit==-1) {
3311 emitcode ("dec", "a");
3313 emitcode ("add", "a,#0x%02x",
3314 (unsigned int) (lit & 0x0FFL));
3317 emitcode ("addc", "a,#0x%02x",
3318 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3321 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3324 adjustArithmeticResult (ic);
3327 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3328 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3329 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3333 /*-----------------------------------------------------------------*/
3334 /* genMultbits :- multiplication of bits */
3335 /*-----------------------------------------------------------------*/
3337 genMultbits (operand * left,
3341 D(emitcode (";", "genMultbits"));
3343 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3344 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3349 /*-----------------------------------------------------------------*/
3350 /* genMultOneByte : 8*8=8/16 bit multiplication */
3351 /*-----------------------------------------------------------------*/
3353 genMultOneByte (operand * left,
3357 sym_link *opetype = operandType (result);
3359 int size=AOP_SIZE(result);
3361 D(emitcode (";", "genMultOneByte"));
3363 if (size<1 || size>2) {
3364 // this should never happen
3365 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3366 AOP_SIZE(result), __FILE__, lineno);
3370 /* (if two literals: the value is computed before) */
3371 /* if one literal, literal on the right */
3372 if (AOP_TYPE (left) == AOP_LIT)
3377 //emitcode (";", "swapped left and right");
3380 if (SPEC_USIGN(opetype)
3381 // ignore the sign of left and right, what else can we do?
3382 || (SPEC_USIGN(operandType(left)) &&
3383 SPEC_USIGN(operandType(right)))) {
3384 // just an unsigned 8*8=8/16 multiply
3385 //emitcode (";","unsigned");
3386 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3387 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3388 emitcode ("mul", "ab");
3389 aopPut (AOP (result), "a", 0);
3391 aopPut (AOP (result), "b", 1);
3396 // we have to do a signed multiply
3398 //emitcode (";", "signed");
3399 emitcode ("clr", "F0"); // reset sign flag
3400 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3402 lbl=newiTempLabel(NULL);
3403 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3404 // left side is negative, 8-bit two's complement, this fails for -128
3405 emitcode ("setb", "F0"); // set sign flag
3406 emitcode ("cpl", "a");
3407 emitcode ("inc", "a");
3409 emitcode ("", "%05d$:", lbl->key+100);
3412 if (AOP_TYPE(right)==AOP_LIT) {
3413 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3414 /* AND literal negative */
3416 emitcode ("cpl", "F0"); // complement sign flag
3417 emitcode ("mov", "b,#0x%02x", -val);
3419 emitcode ("mov", "b,#0x%02x", val);
3422 lbl=newiTempLabel(NULL);
3423 emitcode ("mov", "b,a");
3424 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3425 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3426 // right side is negative, 8-bit two's complement
3427 emitcode ("cpl", "F0"); // complement sign flag
3428 emitcode ("cpl", "a");
3429 emitcode ("inc", "a");
3430 emitcode ("", "%05d$:", lbl->key+100);
3432 emitcode ("mul", "ab");
3434 lbl=newiTempLabel(NULL);
3435 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3436 // only ONE op was negative, we have to do a 8/16-bit two's complement
3437 emitcode ("cpl", "a"); // lsb
3439 emitcode ("inc", "a");
3441 emitcode ("add", "a,#1");
3442 emitcode ("xch", "a,b");
3443 emitcode ("cpl", "a"); // msb
3444 emitcode ("addc", "a,#0");
3445 emitcode ("xch", "a,b");
3448 emitcode ("", "%05d$:", lbl->key+100);
3449 aopPut (AOP (result), "a", 0);
3451 aopPut (AOP (result), "b", 1);
3455 /*-----------------------------------------------------------------*/
3456 /* genMult - generates code for multiplication */
3457 /*-----------------------------------------------------------------*/
3459 genMult (iCode * ic)
3461 operand *left = IC_LEFT (ic);
3462 operand *right = IC_RIGHT (ic);
3463 operand *result = IC_RESULT (ic);
3465 D(emitcode (";", "genMult"));
3467 /* assign the amsops */
3468 aopOp (left, ic, FALSE);
3469 aopOp (right, ic, FALSE);
3470 aopOp (result, ic, TRUE);
3472 /* special cases first */
3474 if (AOP_TYPE (left) == AOP_CRY &&
3475 AOP_TYPE (right) == AOP_CRY)
3477 genMultbits (left, right, result);
3481 /* if both are of size == 1 */
3482 #if 0 // one of them can be a sloc shared with the result
3483 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3485 if (getSize(operandType(left)) == 1 &&
3486 getSize(operandType(right)) == 1)
3489 genMultOneByte (left, right, result);
3493 /* should have been converted to function call */
3494 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3495 getSize(OP_SYMBOL(right)->type));
3499 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3500 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3501 freeAsmop (result, NULL, ic, TRUE);
3504 /*-----------------------------------------------------------------*/
3505 /* genDivbits :- division of bits */
3506 /*-----------------------------------------------------------------*/
3508 genDivbits (operand * left,
3515 D(emitcode (";", "genDivbits"));
3517 /* the result must be bit */
3518 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3519 l = aopGet (AOP (left), 0, FALSE, FALSE);
3523 emitcode ("div", "ab");
3524 emitcode ("rrc", "a");
3525 aopPut (AOP (result), "c", 0);
3528 /*-----------------------------------------------------------------*/
3529 /* genDivOneByte : 8 bit division */
3530 /*-----------------------------------------------------------------*/
3532 genDivOneByte (operand * left,
3536 sym_link *opetype = operandType (result);
3541 D(emitcode (";", "genDivOneByte"));
3543 size = AOP_SIZE (result) - 1;
3545 /* signed or unsigned */
3546 if (SPEC_USIGN (opetype))
3548 /* unsigned is easy */
3549 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3550 l = aopGet (AOP (left), 0, FALSE, FALSE);
3552 emitcode ("div", "ab");
3553 aopPut (AOP (result), "a", 0);
3555 aopPut (AOP (result), zero, offset++);
3559 /* signed is a little bit more difficult */
3561 /* save the signs of the operands */
3562 l = aopGet (AOP (left), 0, FALSE, FALSE);
3564 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3565 emitcode ("push", "acc"); /* save it on the stack */
3567 /* now sign adjust for both left & right */
3568 l = aopGet (AOP (right), 0, FALSE, FALSE);
3570 lbl = newiTempLabel (NULL);
3571 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3572 emitcode ("cpl", "a");
3573 emitcode ("inc", "a");
3574 emitcode ("", "%05d$:", (lbl->key + 100));
3575 emitcode ("mov", "b,a");
3577 /* sign adjust left side */
3578 l = aopGet (AOP (left), 0, FALSE, FALSE);
3581 lbl = newiTempLabel (NULL);
3582 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3583 emitcode ("cpl", "a");
3584 emitcode ("inc", "a");
3585 emitcode ("", "%05d$:", (lbl->key + 100));
3587 /* now the division */
3588 emitcode ("div", "ab");
3589 /* we are interested in the lower order
3591 emitcode ("mov", "b,a");
3592 lbl = newiTempLabel (NULL);
3593 emitcode ("pop", "acc");
3594 /* if there was an over flow we don't
3595 adjust the sign of the result */
3596 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3597 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3599 emitcode ("clr", "a");
3600 emitcode ("subb", "a,b");
3601 emitcode ("mov", "b,a");
3602 emitcode ("", "%05d$:", (lbl->key + 100));
3604 /* now we are done */
3605 aopPut (AOP (result), "b", 0);
3608 emitcode ("mov", "c,b.7");
3609 emitcode ("subb", "a,acc");
3612 aopPut (AOP (result), "a", offset++);
3616 /*-----------------------------------------------------------------*/
3617 /* genDiv - generates code for division */
3618 /*-----------------------------------------------------------------*/
3622 operand *left = IC_LEFT (ic);
3623 operand *right = IC_RIGHT (ic);
3624 operand *result = IC_RESULT (ic);
3626 D(emitcode (";", "genDiv"));
3628 /* assign the amsops */
3629 aopOp (left, ic, FALSE);
3630 aopOp (right, ic, FALSE);
3631 aopOp (result, ic, TRUE);
3633 /* special cases first */
3635 if (AOP_TYPE (left) == AOP_CRY &&
3636 AOP_TYPE (right) == AOP_CRY)
3638 genDivbits (left, right, result);
3642 /* if both are of size == 1 */
3643 if (AOP_SIZE (left) == 1 &&
3644 AOP_SIZE (right) == 1)
3646 genDivOneByte (left, right, result);
3650 /* should have been converted to function call */
3653 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3654 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3655 freeAsmop (result, NULL, ic, TRUE);
3658 /*-----------------------------------------------------------------*/
3659 /* genModbits :- modulus of bits */
3660 /*-----------------------------------------------------------------*/
3662 genModbits (operand * left,
3669 D(emitcode (";", "genModbits"));
3671 /* the result must be bit */
3672 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3673 l = aopGet (AOP (left), 0, FALSE, FALSE);
3677 emitcode ("div", "ab");
3678 emitcode ("mov", "a,b");
3679 emitcode ("rrc", "a");
3680 aopPut (AOP (result), "c", 0);
3683 /*-----------------------------------------------------------------*/
3684 /* genModOneByte : 8 bit modulus */
3685 /*-----------------------------------------------------------------*/
3687 genModOneByte (operand * left,
3691 sym_link *opetype = operandType (result);
3695 D(emitcode (";", "genModOneByte"));
3697 /* signed or unsigned */
3698 if (SPEC_USIGN (opetype))
3700 /* unsigned is easy */
3701 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3702 l = aopGet (AOP (left), 0, FALSE, FALSE);
3704 emitcode ("div", "ab");
3705 aopPut (AOP (result), "b", 0);
3709 /* signed is a little bit more difficult */
3711 /* save the signs of the operands */
3712 l = aopGet (AOP (left), 0, FALSE, FALSE);
3715 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3716 emitcode ("push", "acc"); /* save it on the stack */
3718 /* now sign adjust for both left & right */
3719 l = aopGet (AOP (right), 0, FALSE, FALSE);
3722 lbl = newiTempLabel (NULL);
3723 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3724 emitcode ("cpl", "a");
3725 emitcode ("inc", "a");
3726 emitcode ("", "%05d$:", (lbl->key + 100));
3727 emitcode ("mov", "b,a");
3729 /* sign adjust left side */
3730 l = aopGet (AOP (left), 0, FALSE, FALSE);
3733 lbl = newiTempLabel (NULL);
3734 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3735 emitcode ("cpl", "a");
3736 emitcode ("inc", "a");
3737 emitcode ("", "%05d$:", (lbl->key + 100));
3739 /* now the multiplication */
3740 emitcode ("div", "ab");
3741 /* we are interested in the lower order
3743 lbl = newiTempLabel (NULL);
3744 emitcode ("pop", "acc");
3745 /* if there was an over flow we don't
3746 adjust the sign of the result */
3747 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3748 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3750 emitcode ("clr", "a");
3751 emitcode ("subb", "a,b");
3752 emitcode ("mov", "b,a");
3753 emitcode ("", "%05d$:", (lbl->key + 100));
3755 /* now we are done */
3756 aopPut (AOP (result), "b", 0);
3760 /*-----------------------------------------------------------------*/
3761 /* genMod - generates code for division */
3762 /*-----------------------------------------------------------------*/
3766 operand *left = IC_LEFT (ic);
3767 operand *right = IC_RIGHT (ic);
3768 operand *result = IC_RESULT (ic);
3770 D(emitcode (";", "genMod"));
3772 /* assign the amsops */
3773 aopOp (left, ic, FALSE);
3774 aopOp (right, ic, FALSE);
3775 aopOp (result, ic, TRUE);
3777 /* special cases first */
3779 if (AOP_TYPE (left) == AOP_CRY &&
3780 AOP_TYPE (right) == AOP_CRY)
3782 genModbits (left, right, result);
3786 /* if both are of size == 1 */
3787 if (AOP_SIZE (left) == 1 &&
3788 AOP_SIZE (right) == 1)
3790 genModOneByte (left, right, result);
3794 /* should have been converted to function call */
3798 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3799 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3800 freeAsmop (result, NULL, ic, TRUE);
3803 /*-----------------------------------------------------------------*/
3804 /* genIfxJump :- will create a jump depending on the ifx */
3805 /*-----------------------------------------------------------------*/
3807 genIfxJump (iCode * ic, char *jval)
3810 symbol *tlbl = newiTempLabel (NULL);
3813 D(emitcode (";", "genIfxJump"));
3815 /* if true label then we jump if condition
3819 jlbl = IC_TRUE (ic);
3820 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3821 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3825 /* false label is present */
3826 jlbl = IC_FALSE (ic);
3827 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3828 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3830 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3831 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3833 emitcode (inst, "%05d$", tlbl->key + 100);
3834 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3835 emitcode ("", "%05d$:", tlbl->key + 100);
3837 /* mark the icode as generated */
3841 /*-----------------------------------------------------------------*/
3842 /* genCmp :- greater or less than comparison */
3843 /*-----------------------------------------------------------------*/
3845 genCmp (operand * left, operand * right,
3846 operand * result, iCode * ifx, int sign, iCode *ic)
3848 int size, offset = 0;
3849 unsigned long lit = 0L;
3851 D(emitcode (";", "genCmp"));
3853 /* if left & right are bit variables */
3854 if (AOP_TYPE (left) == AOP_CRY &&
3855 AOP_TYPE (right) == AOP_CRY)
3857 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3858 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3862 /* subtract right from left if at the
3863 end the carry flag is set then we know that
3864 left is greater than right */
3865 size = max (AOP_SIZE (left), AOP_SIZE (right));
3867 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3868 if ((size == 1) && !sign &&
3869 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3871 symbol *lbl = newiTempLabel (NULL);
3872 emitcode ("cjne", "%s,%s,%05d$",
3873 aopGet (AOP (left), offset, FALSE, FALSE),
3874 aopGet (AOP (right), offset, FALSE, FALSE),
3876 emitcode ("", "%05d$:", lbl->key + 100);
3880 if (AOP_TYPE (right) == AOP_LIT)
3882 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3883 /* optimize if(x < 0) or if(x >= 0) */
3892 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3893 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3895 genIfxJump (ifx, "acc.7");
3899 emitcode ("rlc", "a");
3907 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3908 if (sign && size == 0)
3910 emitcode ("xrl", "a,#0x80");
3911 if (AOP_TYPE (right) == AOP_LIT)
3913 unsigned long lit = (unsigned long)
3914 floatFromVal (AOP (right)->aopu.aop_lit);
3915 emitcode ("subb", "a,#0x%02x",
3916 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3920 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3921 emitcode ("xrl", "b,#0x80");
3922 emitcode ("subb", "a,b");
3926 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3932 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3933 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3934 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3940 /* if the result is used in the next
3941 ifx conditional branch then generate
3942 code a little differently */
3944 genIfxJump (ifx, "c");
3947 /* leave the result in acc */
3951 /*-----------------------------------------------------------------*/
3952 /* genCmpGt :- greater than comparison */
3953 /*-----------------------------------------------------------------*/
3955 genCmpGt (iCode * ic, iCode * ifx)
3957 operand *left, *right, *result;
3958 sym_link *letype, *retype;
3961 D(emitcode (";", "genCmpGt"));
3963 left = IC_LEFT (ic);
3964 right = IC_RIGHT (ic);
3965 result = IC_RESULT (ic);
3967 letype = getSpec (operandType (left));
3968 retype = getSpec (operandType (right));
3969 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3970 /* assign the amsops */
3971 aopOp (left, ic, FALSE);
3972 aopOp (right, ic, FALSE);
3973 aopOp (result, ic, TRUE);
3975 genCmp (right, left, result, ifx, sign,ic);
3977 freeAsmop (result, NULL, ic, TRUE);
3980 /*-----------------------------------------------------------------*/
3981 /* genCmpLt - less than comparisons */
3982 /*-----------------------------------------------------------------*/
3984 genCmpLt (iCode * ic, iCode * ifx)
3986 operand *left, *right, *result;
3987 sym_link *letype, *retype;
3990 D(emitcode (";", "genCmpLt"));
3992 left = IC_LEFT (ic);
3993 right = IC_RIGHT (ic);
3994 result = IC_RESULT (ic);
3996 letype = getSpec (operandType (left));
3997 retype = getSpec (operandType (right));
3998 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4000 /* assign the amsops */
4001 aopOp (left, ic, FALSE);
4002 aopOp (right, ic, FALSE);
4003 aopOp (result, ic, TRUE);
4005 genCmp (left, right, result, ifx, sign,ic);
4007 freeAsmop (result, NULL, ic, TRUE);
4010 /*-----------------------------------------------------------------*/
4011 /* gencjneshort - compare and jump if not equal */
4012 /*-----------------------------------------------------------------*/
4014 gencjneshort (operand * left, operand * right, symbol * lbl)
4016 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4018 unsigned long lit = 0L;
4020 /* if the left side is a literal or
4021 if the right is in a pointer register and left
4023 if ((AOP_TYPE (left) == AOP_LIT) ||
4024 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4030 if (AOP_TYPE (right) == AOP_LIT)
4031 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4033 /* if the right side is a literal then anything goes */
4034 if (AOP_TYPE (right) == AOP_LIT &&
4035 AOP_TYPE (left) != AOP_DIR)
4039 emitcode ("cjne", "%s,%s,%05d$",
4040 aopGet (AOP (left), offset, FALSE, FALSE),
4041 aopGet (AOP (right), offset, FALSE, FALSE),
4047 /* if the right side is in a register or in direct space or
4048 if the left is a pointer register & right is not */
4049 else if (AOP_TYPE (right) == AOP_REG ||
4050 AOP_TYPE (right) == AOP_DIR ||
4051 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4052 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4056 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4057 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4058 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4059 emitcode ("jnz", "%05d$", lbl->key + 100);
4061 emitcode ("cjne", "a,%s,%05d$",
4062 aopGet (AOP (right), offset, FALSE, TRUE),
4069 /* right is a pointer reg need both a & b */
4072 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4073 if (strcmp (l, "b"))
4074 emitcode ("mov", "b,%s", l);
4075 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4076 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4082 /*-----------------------------------------------------------------*/
4083 /* gencjne - compare and jump if not equal */
4084 /*-----------------------------------------------------------------*/
4086 gencjne (operand * left, operand * right, symbol * lbl)
4088 symbol *tlbl = newiTempLabel (NULL);
4090 gencjneshort (left, right, lbl);
4092 emitcode ("mov", "a,%s", one);
4093 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4094 emitcode ("", "%05d$:", lbl->key + 100);
4095 emitcode ("clr", "a");
4096 emitcode ("", "%05d$:", tlbl->key + 100);
4099 /*-----------------------------------------------------------------*/
4100 /* genCmpEq - generates code for equal to */
4101 /*-----------------------------------------------------------------*/
4103 genCmpEq (iCode * ic, iCode * ifx)
4105 operand *left, *right, *result;
4107 D(emitcode (";", "genCmpEq"));
4109 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4110 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4111 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4113 /* if literal, literal on the right or
4114 if the right is in a pointer register and left
4116 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4117 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4119 operand *t = IC_RIGHT (ic);
4120 IC_RIGHT (ic) = IC_LEFT (ic);
4124 if (ifx && !AOP_SIZE (result))
4127 /* if they are both bit variables */
4128 if (AOP_TYPE (left) == AOP_CRY &&
4129 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4131 if (AOP_TYPE (right) == AOP_LIT)
4133 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4136 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4137 emitcode ("cpl", "c");
4141 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4145 emitcode ("clr", "c");
4147 /* AOP_TYPE(right) == AOP_CRY */
4151 symbol *lbl = newiTempLabel (NULL);
4152 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4153 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4154 emitcode ("cpl", "c");
4155 emitcode ("", "%05d$:", (lbl->key + 100));
4157 /* if true label then we jump if condition
4159 tlbl = newiTempLabel (NULL);
4162 emitcode ("jnc", "%05d$", tlbl->key + 100);
4163 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4167 emitcode ("jc", "%05d$", tlbl->key + 100);
4168 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4170 emitcode ("", "%05d$:", tlbl->key + 100);
4174 tlbl = newiTempLabel (NULL);
4175 gencjneshort (left, right, tlbl);
4178 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4179 emitcode ("", "%05d$:", tlbl->key + 100);
4183 symbol *lbl = newiTempLabel (NULL);
4184 emitcode ("sjmp", "%05d$", lbl->key + 100);
4185 emitcode ("", "%05d$:", tlbl->key + 100);
4186 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4187 emitcode ("", "%05d$:", lbl->key + 100);
4190 /* mark the icode as generated */
4195 /* if they are both bit variables */
4196 if (AOP_TYPE (left) == AOP_CRY &&
4197 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4199 if (AOP_TYPE (right) == AOP_LIT)
4201 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4204 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4205 emitcode ("cpl", "c");
4209 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4213 emitcode ("clr", "c");
4215 /* AOP_TYPE(right) == AOP_CRY */
4219 symbol *lbl = newiTempLabel (NULL);
4220 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4221 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4222 emitcode ("cpl", "c");
4223 emitcode ("", "%05d$:", (lbl->key + 100));
4226 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4233 genIfxJump (ifx, "c");
4236 /* if the result is used in an arithmetic operation
4237 then put the result in place */
4242 gencjne (left, right, newiTempLabel (NULL));
4243 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4245 aopPut (AOP (result), "a", 0);
4250 genIfxJump (ifx, "a");
4253 /* if the result is used in an arithmetic operation
4254 then put the result in place */
4255 if (AOP_TYPE (result) != AOP_CRY)
4257 /* leave the result in acc */
4261 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4262 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4263 freeAsmop (result, NULL, ic, TRUE);
4266 /*-----------------------------------------------------------------*/
4267 /* ifxForOp - returns the icode containing the ifx for operand */
4268 /*-----------------------------------------------------------------*/
4270 ifxForOp (operand * op, iCode * ic)
4272 /* if true symbol then needs to be assigned */
4273 if (IS_TRUE_SYMOP (op))
4276 /* if this has register type condition and
4277 the next instruction is ifx with the same operand
4278 and live to of the operand is upto the ifx only then */
4280 ic->next->op == IFX &&
4281 IC_COND (ic->next)->key == op->key &&
4282 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4288 /*-----------------------------------------------------------------*/
4289 /* hasInc - operand is incremented before any other use */
4290 /*-----------------------------------------------------------------*/
4292 hasInc (operand *op, iCode *ic)
4294 sym_link *type = operandType(op);
4295 sym_link *retype = getSpec (type);
4296 iCode *lic = ic->next;
4299 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4300 if (!IS_SYMOP(op)) return NULL;
4302 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4303 isize = getSize(type->next);
4305 /* if operand of the form op = op + <sizeof *op> */
4306 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4307 isOperandEqual(IC_RESULT(lic),op) &&
4308 isOperandLiteral(IC_RIGHT(lic)) &&
4309 operandLitValue(IC_RIGHT(lic)) == isize) {
4312 /* if the operand used or deffed */
4313 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4321 /*-----------------------------------------------------------------*/
4322 /* genAndOp - for && operation */
4323 /*-----------------------------------------------------------------*/
4325 genAndOp (iCode * ic)
4327 operand *left, *right, *result;
4330 D(emitcode (";", "genAndOp"));
4332 /* note here that && operations that are in an
4333 if statement are taken away by backPatchLabels
4334 only those used in arthmetic operations remain */
4335 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4336 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4337 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4339 /* if both are bit variables */
4340 if (AOP_TYPE (left) == AOP_CRY &&
4341 AOP_TYPE (right) == AOP_CRY)
4343 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4344 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4349 tlbl = newiTempLabel (NULL);
4351 emitcode ("jz", "%05d$", tlbl->key + 100);
4353 emitcode ("", "%05d$:", tlbl->key + 100);
4357 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4358 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4359 freeAsmop (result, NULL, ic, TRUE);
4363 /*-----------------------------------------------------------------*/
4364 /* genOrOp - for || operation */
4365 /*-----------------------------------------------------------------*/
4367 genOrOp (iCode * ic)
4369 operand *left, *right, *result;
4372 D(emitcode (";", "genOrOp"));
4374 /* note here that || operations that are in an
4375 if statement are taken away by backPatchLabels
4376 only those used in arthmetic operations remain */
4377 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4378 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4379 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4381 /* if both are bit variables */
4382 if (AOP_TYPE (left) == AOP_CRY &&
4383 AOP_TYPE (right) == AOP_CRY)
4385 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4386 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4391 tlbl = newiTempLabel (NULL);
4393 emitcode ("jnz", "%05d$", tlbl->key + 100);
4395 emitcode ("", "%05d$:", tlbl->key + 100);
4399 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4400 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4401 freeAsmop (result, NULL, ic, TRUE);
4404 /*-----------------------------------------------------------------*/
4405 /* isLiteralBit - test if lit == 2^n */
4406 /*-----------------------------------------------------------------*/
4408 isLiteralBit (unsigned long lit)
4410 unsigned long pw[32] =
4411 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4412 0x100L, 0x200L, 0x400L, 0x800L,
4413 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4414 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4415 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4416 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4417 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4420 for (idx = 0; idx < 32; idx++)
4426 /*-----------------------------------------------------------------*/
4427 /* continueIfTrue - */
4428 /*-----------------------------------------------------------------*/
4430 continueIfTrue (iCode * ic)
4433 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4437 /*-----------------------------------------------------------------*/
4439 /*-----------------------------------------------------------------*/
4441 jumpIfTrue (iCode * ic)
4444 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4448 /*-----------------------------------------------------------------*/
4449 /* jmpTrueOrFalse - */
4450 /*-----------------------------------------------------------------*/
4452 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4454 // ugly but optimized by peephole
4457 symbol *nlbl = newiTempLabel (NULL);
4458 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4459 emitcode ("", "%05d$:", tlbl->key + 100);
4460 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4461 emitcode ("", "%05d$:", nlbl->key + 100);
4465 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4466 emitcode ("", "%05d$:", tlbl->key + 100);
4471 /*-----------------------------------------------------------------*/
4472 /* genAnd - code for and */
4473 /*-----------------------------------------------------------------*/
4475 genAnd (iCode * ic, iCode * ifx)
4477 operand *left, *right, *result;
4478 int size, offset = 0;
4479 unsigned long lit = 0L;
4483 D(emitcode (";", "genAnd"));
4485 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4486 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4487 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4490 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4492 AOP_TYPE (left), AOP_TYPE (right));
4493 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4495 AOP_SIZE (left), AOP_SIZE (right));
4498 /* if left is a literal & right is not then exchange them */
4499 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4500 AOP_NEEDSACC (left))
4502 operand *tmp = right;
4507 /* if result = right then exchange them */
4508 if (sameRegs (AOP (result), AOP (right)))
4510 operand *tmp = right;
4515 /* if right is bit then exchange them */
4516 if (AOP_TYPE (right) == AOP_CRY &&
4517 AOP_TYPE (left) != AOP_CRY)
4519 operand *tmp = right;
4523 if (AOP_TYPE (right) == AOP_LIT)
4524 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4526 size = AOP_SIZE (result);
4529 // result = bit & yy;
4530 if (AOP_TYPE (left) == AOP_CRY)
4532 // c = bit & literal;
4533 if (AOP_TYPE (right) == AOP_LIT)
4537 if (size && sameRegs (AOP (result), AOP (left)))
4540 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4545 if (size && (AOP_TYPE (result) == AOP_CRY))
4547 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4550 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4555 emitcode ("clr", "c");
4560 if (AOP_TYPE (right) == AOP_CRY)
4563 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4564 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4569 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4571 emitcode ("rrc", "a");
4572 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4580 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4581 genIfxJump (ifx, "c");
4585 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4586 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4587 if ((AOP_TYPE (right) == AOP_LIT) &&
4588 (AOP_TYPE (result) == AOP_CRY) &&
4589 (AOP_TYPE (left) != AOP_CRY))
4591 int posbit = isLiteralBit (lit);
4596 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4599 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4605 sprintf (buffer, "acc.%d", posbit & 0x07);
4606 genIfxJump (ifx, buffer);
4613 symbol *tlbl = newiTempLabel (NULL);
4614 int sizel = AOP_SIZE (left);
4616 emitcode ("setb", "c");
4619 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4621 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4623 if ((posbit = isLiteralBit (bytelit)) != 0)
4624 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4627 if (bytelit != 0x0FFL)
4628 emitcode ("anl", "a,%s",
4629 aopGet (AOP (right), offset, FALSE, TRUE));
4630 emitcode ("jnz", "%05d$", tlbl->key + 100);
4635 // bit = left & literal
4638 emitcode ("clr", "c");
4639 emitcode ("", "%05d$:", tlbl->key + 100);
4641 // if(left & literal)
4645 jmpTrueOrFalse (ifx, tlbl);
4653 /* if left is same as result */
4654 if (sameRegs (AOP (result), AOP (left)))
4656 for (; size--; offset++)
4658 if (AOP_TYPE (right) == AOP_LIT)
4660 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4662 else if (bytelit == 0)
4663 aopPut (AOP (result), zero, offset);
4664 else if (IS_AOP_PREG (result))
4666 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4667 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4668 aopPut (AOP (result), "a", offset);
4671 emitcode ("anl", "%s,%s",
4672 aopGet (AOP (left), offset, FALSE, TRUE),
4673 aopGet (AOP (right), offset, FALSE, FALSE));
4677 if (AOP_TYPE (left) == AOP_ACC)
4678 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4681 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4682 if (IS_AOP_PREG (result))
4684 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4685 aopPut (AOP (result), "a", offset);
4689 emitcode ("anl", "%s,a",
4690 aopGet (AOP (left), offset, FALSE, TRUE));
4697 // left & result in different registers
4698 if (AOP_TYPE (result) == AOP_CRY)
4701 // if(size), result in bit
4702 // if(!size && ifx), conditional oper: if(left & right)
4703 symbol *tlbl = newiTempLabel (NULL);
4704 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4706 emitcode ("setb", "c");
4709 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4710 emitcode ("anl", "a,%s",
4711 aopGet (AOP (right), offset, FALSE, FALSE));
4713 if (AOP_TYPE(left)==AOP_ACC) {
4714 emitcode("mov", "b,a");
4715 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4716 emitcode("anl", "a,b");
4718 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4719 emitcode ("anl", "a,%s",
4720 aopGet (AOP (left), offset, FALSE, FALSE));
4723 emitcode ("jnz", "%05d$", tlbl->key + 100);
4729 emitcode ("", "%05d$:", tlbl->key + 100);
4733 jmpTrueOrFalse (ifx, tlbl);
4737 for (; (size--); offset++)
4740 // result = left & right
4741 if (AOP_TYPE (right) == AOP_LIT)
4743 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4745 aopPut (AOP (result),
4746 aopGet (AOP (left), offset, FALSE, FALSE),
4750 else if (bytelit == 0)
4752 aopPut (AOP (result), zero, offset);
4756 // faster than result <- left, anl result,right
4757 // and better if result is SFR
4758 if (AOP_TYPE (left) == AOP_ACC)
4759 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4762 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4763 emitcode ("anl", "a,%s",
4764 aopGet (AOP (left), offset, FALSE, FALSE));
4766 aopPut (AOP (result), "a", offset);
4772 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4773 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4774 freeAsmop (result, NULL, ic, TRUE);
4777 /*-----------------------------------------------------------------*/
4778 /* genOr - code for or */
4779 /*-----------------------------------------------------------------*/
4781 genOr (iCode * ic, iCode * ifx)
4783 operand *left, *right, *result;
4784 int size, offset = 0;
4785 unsigned long lit = 0L;
4787 D(emitcode (";", "genOr"));
4789 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4790 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4791 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4794 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4796 AOP_TYPE (left), AOP_TYPE (right));
4797 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4799 AOP_SIZE (left), AOP_SIZE (right));
4802 /* if left is a literal & right is not then exchange them */
4803 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4804 AOP_NEEDSACC (left))
4806 operand *tmp = right;
4811 /* if result = right then exchange them */
4812 if (sameRegs (AOP (result), AOP (right)))
4814 operand *tmp = right;
4819 /* if right is bit then exchange them */
4820 if (AOP_TYPE (right) == AOP_CRY &&
4821 AOP_TYPE (left) != AOP_CRY)
4823 operand *tmp = right;
4827 if (AOP_TYPE (right) == AOP_LIT)
4828 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4830 size = AOP_SIZE (result);
4834 if (AOP_TYPE (left) == AOP_CRY)
4836 if (AOP_TYPE (right) == AOP_LIT)
4838 // c = bit & literal;
4841 // lit != 0 => result = 1
4842 if (AOP_TYPE (result) == AOP_CRY)
4845 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4847 continueIfTrue (ifx);
4850 emitcode ("setb", "c");
4854 // lit == 0 => result = left
4855 if (size && sameRegs (AOP (result), AOP (left)))
4857 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4862 if (AOP_TYPE (right) == AOP_CRY)
4865 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4866 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4871 symbol *tlbl = newiTempLabel (NULL);
4872 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4873 emitcode ("setb", "c");
4874 emitcode ("jb", "%s,%05d$",
4875 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4877 emitcode ("jnz", "%05d$", tlbl->key + 100);
4878 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4880 jmpTrueOrFalse (ifx, tlbl);
4886 emitcode ("", "%05d$:", tlbl->key + 100);
4895 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4896 genIfxJump (ifx, "c");
4900 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4901 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4902 if ((AOP_TYPE (right) == AOP_LIT) &&
4903 (AOP_TYPE (result) == AOP_CRY) &&
4904 (AOP_TYPE (left) != AOP_CRY))
4910 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4912 continueIfTrue (ifx);
4917 // lit = 0, result = boolean(left)
4919 emitcode ("setb", "c");
4923 symbol *tlbl = newiTempLabel (NULL);
4924 emitcode ("jnz", "%05d$", tlbl->key + 100);
4926 emitcode ("", "%05d$:", tlbl->key + 100);
4930 genIfxJump (ifx, "a");
4938 /* if left is same as result */
4939 if (sameRegs (AOP (result), AOP (left)))
4941 for (; size--; offset++)
4943 if (AOP_TYPE (right) == AOP_LIT)
4945 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4947 else if (IS_AOP_PREG (left))
4949 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4950 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4951 aopPut (AOP (result), "a", offset);
4954 emitcode ("orl", "%s,%s",
4955 aopGet (AOP (left), offset, FALSE, TRUE),
4956 aopGet (AOP (right), offset, FALSE, FALSE));
4960 if (AOP_TYPE (left) == AOP_ACC)
4961 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4964 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4965 if (IS_AOP_PREG (left))
4967 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4968 aopPut (AOP (result), "a", offset);
4971 emitcode ("orl", "%s,a",
4972 aopGet (AOP (left), offset, FALSE, TRUE));
4979 // left & result in different registers
4980 if (AOP_TYPE (result) == AOP_CRY)
4983 // if(size), result in bit
4984 // if(!size && ifx), conditional oper: if(left | right)
4985 symbol *tlbl = newiTempLabel (NULL);
4986 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4988 emitcode ("setb", "c");
4991 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4992 emitcode ("orl", "a,%s",
4993 aopGet (AOP (right), offset, FALSE, FALSE));
4995 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4996 emitcode ("orl", "a,%s",
4997 aopGet (AOP (left), offset, FALSE, FALSE));
4999 emitcode ("jnz", "%05d$", tlbl->key + 100);
5005 emitcode ("", "%05d$:", tlbl->key + 100);
5009 jmpTrueOrFalse (ifx, tlbl);
5012 for (; (size--); offset++)
5015 // result = left & right
5016 if (AOP_TYPE (right) == AOP_LIT)
5018 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5020 aopPut (AOP (result),
5021 aopGet (AOP (left), offset, FALSE, FALSE),
5026 // faster than result <- left, anl result,right
5027 // and better if result is SFR
5028 if (AOP_TYPE (left) == AOP_ACC)
5029 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5032 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5033 emitcode ("orl", "a,%s",
5034 aopGet (AOP (left), offset, FALSE, FALSE));
5036 aopPut (AOP (result), "a", offset);
5041 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5042 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5043 freeAsmop (result, NULL, ic, TRUE);
5046 /*-----------------------------------------------------------------*/
5047 /* genXor - code for xclusive or */
5048 /*-----------------------------------------------------------------*/
5050 genXor (iCode * ic, iCode * ifx)
5052 operand *left, *right, *result;
5053 int size, offset = 0;
5054 unsigned long lit = 0L;
5056 D(emitcode (";", "genXor"));
5058 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5059 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5060 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5063 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5065 AOP_TYPE (left), AOP_TYPE (right));
5066 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5068 AOP_SIZE (left), AOP_SIZE (right));
5071 /* if left is a literal & right is not ||
5072 if left needs acc & right does not */
5073 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5074 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5076 operand *tmp = right;
5081 /* if result = right then exchange them */
5082 if (sameRegs (AOP (result), AOP (right)))
5084 operand *tmp = right;
5089 /* if right is bit then exchange them */
5090 if (AOP_TYPE (right) == AOP_CRY &&
5091 AOP_TYPE (left) != AOP_CRY)
5093 operand *tmp = right;
5097 if (AOP_TYPE (right) == AOP_LIT)
5098 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5100 size = AOP_SIZE (result);
5104 if (AOP_TYPE (left) == AOP_CRY)
5106 if (AOP_TYPE (right) == AOP_LIT)
5108 // c = bit & literal;
5111 // lit>>1 != 0 => result = 1
5112 if (AOP_TYPE (result) == AOP_CRY)
5115 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5117 continueIfTrue (ifx);
5120 emitcode ("setb", "c");
5127 // lit == 0, result = left
5128 if (size && sameRegs (AOP (result), AOP (left)))
5130 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5134 // lit == 1, result = not(left)
5135 if (size && sameRegs (AOP (result), AOP (left)))
5137 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5142 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5143 emitcode ("cpl", "c");
5152 symbol *tlbl = newiTempLabel (NULL);
5153 if (AOP_TYPE (right) == AOP_CRY)
5156 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5160 int sizer = AOP_SIZE (right);
5162 // if val>>1 != 0, result = 1
5163 emitcode ("setb", "c");
5166 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5168 // test the msb of the lsb
5169 emitcode ("anl", "a,#0xfe");
5170 emitcode ("jnz", "%05d$", tlbl->key + 100);
5174 emitcode ("rrc", "a");
5176 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5177 emitcode ("cpl", "c");
5178 emitcode ("", "%05d$:", (tlbl->key + 100));
5185 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5186 genIfxJump (ifx, "c");
5190 if (sameRegs (AOP (result), AOP (left)))
5192 /* if left is same as result */
5193 for (; size--; offset++)
5195 if (AOP_TYPE (right) == AOP_LIT)
5197 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5199 else if (IS_AOP_PREG (left))
5201 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5202 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5203 aopPut (AOP (result), "a", offset);
5206 emitcode ("xrl", "%s,%s",
5207 aopGet (AOP (left), offset, FALSE, TRUE),
5208 aopGet (AOP (right), offset, FALSE, FALSE));
5212 if (AOP_TYPE (left) == AOP_ACC)
5213 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5216 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5217 if (IS_AOP_PREG (left))
5219 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5220 aopPut (AOP (result), "a", offset);
5223 emitcode ("xrl", "%s,a",
5224 aopGet (AOP (left), offset, FALSE, TRUE));
5231 // left & result in different registers
5232 if (AOP_TYPE (result) == AOP_CRY)
5235 // if(size), result in bit
5236 // if(!size && ifx), conditional oper: if(left ^ right)
5237 symbol *tlbl = newiTempLabel (NULL);
5238 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5240 emitcode ("setb", "c");
5243 if ((AOP_TYPE (right) == AOP_LIT) &&
5244 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5246 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5250 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5251 emitcode ("xrl", "a,%s",
5252 aopGet (AOP (right), offset, FALSE, FALSE));
5254 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5255 emitcode ("xrl", "a,%s",
5256 aopGet (AOP (left), offset, FALSE, FALSE));
5259 emitcode ("jnz", "%05d$", tlbl->key + 100);
5265 emitcode ("", "%05d$:", tlbl->key + 100);
5269 jmpTrueOrFalse (ifx, tlbl);
5272 for (; (size--); offset++)
5275 // result = left & right
5276 if (AOP_TYPE (right) == AOP_LIT)
5278 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5280 aopPut (AOP (result),
5281 aopGet (AOP (left), offset, FALSE, FALSE),
5286 // faster than result <- left, anl result,right
5287 // and better if result is SFR
5288 if (AOP_TYPE (left) == AOP_ACC)
5289 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5292 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5293 emitcode ("xrl", "a,%s",
5294 aopGet (AOP (left), offset, FALSE, TRUE));
5296 aopPut (AOP (result), "a", offset);
5301 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5302 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5303 freeAsmop (result, NULL, ic, TRUE);
5306 /*-----------------------------------------------------------------*/
5307 /* genInline - write the inline code out */
5308 /*-----------------------------------------------------------------*/
5310 genInline (iCode * ic)
5312 char *buffer, *bp, *bp1;
5314 D(emitcode (";", "genInline"));
5316 _G.inLine += (!options.asmpeep);
5318 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5319 strcpy (buffer, IC_INLINE (ic));
5321 /* emit each line as a code */
5346 /* emitcode("",buffer); */
5347 _G.inLine -= (!options.asmpeep);
5350 /*-----------------------------------------------------------------*/
5351 /* genRRC - rotate right with carry */
5352 /*-----------------------------------------------------------------*/
5356 operand *left, *result;
5357 int size, offset = 0;
5360 D(emitcode (";", "genRRC"));
5362 /* rotate right with carry */
5363 left = IC_LEFT (ic);
5364 result = IC_RESULT (ic);
5365 aopOp (left, ic, FALSE);
5366 aopOp (result, ic, FALSE);
5368 /* move it to the result */
5369 size = AOP_SIZE (result);
5371 if (size == 1) { /* special case for 1 byte */
5372 l = aopGet (AOP (left), offset, FALSE, FALSE);
5374 emitcode ("rr", "a");
5380 l = aopGet (AOP (left), offset, FALSE, FALSE);
5382 emitcode ("rrc", "a");
5383 if (AOP_SIZE (result) > 1)
5384 aopPut (AOP (result), "a", offset--);
5386 /* now we need to put the carry into the
5387 highest order byte of the result */
5388 if (AOP_SIZE (result) > 1)
5390 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5393 emitcode ("mov", "acc.7,c");
5395 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5396 freeAsmop (left, NULL, ic, TRUE);
5397 freeAsmop (result, NULL, ic, TRUE);
5400 /*-----------------------------------------------------------------*/
5401 /* genRLC - generate code for rotate left with carry */
5402 /*-----------------------------------------------------------------*/
5406 operand *left, *result;
5407 int size, offset = 0;
5410 D(emitcode (";", "genRLC"));
5412 /* rotate right with carry */
5413 left = IC_LEFT (ic);
5414 result = IC_RESULT (ic);
5415 aopOp (left, ic, FALSE);
5416 aopOp (result, ic, FALSE);
5418 /* move it to the result */
5419 size = AOP_SIZE (result);
5423 l = aopGet (AOP (left), offset, FALSE, FALSE);
5425 if (size == 0) { /* special case for 1 byte */
5429 emitcode ("add", "a,acc");
5430 if (AOP_SIZE (result) > 1)
5431 aopPut (AOP (result), "a", offset++);
5434 l = aopGet (AOP (left), offset, FALSE, FALSE);
5436 emitcode ("rlc", "a");
5437 if (AOP_SIZE (result) > 1)
5438 aopPut (AOP (result), "a", offset++);
5441 /* now we need to put the carry into the
5442 highest order byte of the result */
5443 if (AOP_SIZE (result) > 1)
5445 l = aopGet (AOP (result), 0, FALSE, FALSE);
5448 emitcode ("mov", "acc.0,c");
5450 aopPut (AOP (result), "a", 0);
5451 freeAsmop (left, NULL, ic, TRUE);
5452 freeAsmop (result, NULL, ic, TRUE);
5455 /*-----------------------------------------------------------------*/
5456 /* genGetHbit - generates code get highest order bit */
5457 /*-----------------------------------------------------------------*/
5459 genGetHbit (iCode * ic)
5461 operand *left, *result;
5463 D(emitcode (";", "genGetHbit"));
5465 left = IC_LEFT (ic);
5466 result = IC_RESULT (ic);
5467 aopOp (left, ic, FALSE);
5468 aopOp (result, ic, FALSE);
5470 /* get the highest order byte into a */
5471 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5472 if (AOP_TYPE (result) == AOP_CRY)
5474 emitcode ("rlc", "a");
5479 emitcode ("rl", "a");
5480 emitcode ("anl", "a,#0x01");
5485 freeAsmop (left, NULL, ic, TRUE);
5486 freeAsmop (result, NULL, ic, TRUE);
5489 /*-----------------------------------------------------------------*/
5490 /* AccRol - rotate left accumulator by known count */
5491 /*-----------------------------------------------------------------*/
5493 AccRol (int shCount)
5495 shCount &= 0x0007; // shCount : 0..7
5502 emitcode ("rl", "a");
5505 emitcode ("rl", "a");
5506 emitcode ("rl", "a");
5509 emitcode ("swap", "a");
5510 emitcode ("rr", "a");
5513 emitcode ("swap", "a");
5516 emitcode ("swap", "a");
5517 emitcode ("rl", "a");
5520 emitcode ("rr", "a");
5521 emitcode ("rr", "a");
5524 emitcode ("rr", "a");
5529 /*-----------------------------------------------------------------*/
5530 /* AccLsh - left shift accumulator by known count */
5531 /*-----------------------------------------------------------------*/
5533 AccLsh (int shCount)
5538 emitcode ("add", "a,acc");
5539 else if (shCount == 2)
5541 emitcode ("add", "a,acc");
5542 emitcode ("add", "a,acc");
5546 /* rotate left accumulator */
5548 /* and kill the lower order bits */
5549 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5554 /*-----------------------------------------------------------------*/
5555 /* AccRsh - right shift accumulator by known count */
5556 /*-----------------------------------------------------------------*/
5558 AccRsh (int shCount)
5565 emitcode ("rrc", "a");
5569 /* rotate right accumulator */
5570 AccRol (8 - shCount);
5571 /* and kill the higher order bits */
5572 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5577 /*-----------------------------------------------------------------*/
5578 /* AccSRsh - signed right shift accumulator by known count */
5579 /*-----------------------------------------------------------------*/
5581 AccSRsh (int shCount)
5588 emitcode ("mov", "c,acc.7");
5589 emitcode ("rrc", "a");
5591 else if (shCount == 2)
5593 emitcode ("mov", "c,acc.7");
5594 emitcode ("rrc", "a");
5595 emitcode ("mov", "c,acc.7");
5596 emitcode ("rrc", "a");
5600 tlbl = newiTempLabel (NULL);
5601 /* rotate right accumulator */
5602 AccRol (8 - shCount);
5603 /* and kill the higher order bits */
5604 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5605 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5606 emitcode ("orl", "a,#0x%02x",
5607 (unsigned char) ~SRMask[shCount]);
5608 emitcode ("", "%05d$:", tlbl->key + 100);
5613 /*-----------------------------------------------------------------*/
5614 /* shiftR1Left2Result - shift right one byte from left to result */
5615 /*-----------------------------------------------------------------*/
5617 shiftR1Left2Result (operand * left, int offl,
5618 operand * result, int offr,
5619 int shCount, int sign)
5621 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5622 /* shift right accumulator */
5627 aopPut (AOP (result), "a", offr);
5630 /*-----------------------------------------------------------------*/
5631 /* shiftL1Left2Result - shift left one byte from left to result */
5632 /*-----------------------------------------------------------------*/
5634 shiftL1Left2Result (operand * left, int offl,
5635 operand * result, int offr, int shCount)
5638 l = aopGet (AOP (left), offl, FALSE, FALSE);
5640 /* shift left accumulator */
5642 aopPut (AOP (result), "a", offr);
5645 /*-----------------------------------------------------------------*/
5646 /* movLeft2Result - move byte from left to result */
5647 /*-----------------------------------------------------------------*/
5649 movLeft2Result (operand * left, int offl,
5650 operand * result, int offr, int sign)
5653 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5655 l = aopGet (AOP (left), offl, FALSE, FALSE);
5657 if (*l == '@' && (IS_AOP_PREG (result)))
5659 emitcode ("mov", "a,%s", l);
5660 aopPut (AOP (result), "a", offr);
5665 aopPut (AOP (result), l, offr);
5668 /* MSB sign in acc.7 ! */
5669 if (getDataSize (left) == offl + 1)
5671 emitcode ("mov", "a,%s", l);
5672 aopPut (AOP (result), "a", offr);
5679 /*-----------------------------------------------------------------*/
5680 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5681 /*-----------------------------------------------------------------*/
5685 emitcode ("rrc", "a");
5686 emitcode ("xch", "a,%s", x);
5687 emitcode ("rrc", "a");
5688 emitcode ("xch", "a,%s", x);
5691 /*-----------------------------------------------------------------*/
5692 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5693 /*-----------------------------------------------------------------*/
5697 emitcode ("xch", "a,%s", x);
5698 emitcode ("rlc", "a");
5699 emitcode ("xch", "a,%s", x);
5700 emitcode ("rlc", "a");
5703 /*-----------------------------------------------------------------*/
5704 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5705 /*-----------------------------------------------------------------*/
5709 emitcode ("xch", "a,%s", x);
5710 emitcode ("add", "a,acc");
5711 emitcode ("xch", "a,%s", x);
5712 emitcode ("rlc", "a");
5715 /*-----------------------------------------------------------------*/
5716 /* AccAXLsh - left shift a:x by known count (0..7) */
5717 /*-----------------------------------------------------------------*/
5719 AccAXLsh (char *x, int shCount)
5734 case 5: // AAAAABBB:CCCCCDDD
5736 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5738 emitcode ("anl", "a,#0x%02x",
5739 SLMask[shCount]); // BBB00000:CCCCCDDD
5741 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5743 AccRol (shCount); // DDDCCCCC:BBB00000
5745 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5747 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5749 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5751 emitcode ("anl", "a,#0x%02x",
5752 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5754 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5756 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5759 case 6: // AAAAAABB:CCCCCCDD
5760 emitcode ("anl", "a,#0x%02x",
5761 SRMask[shCount]); // 000000BB:CCCCCCDD
5762 emitcode ("mov", "c,acc.0"); // c = B
5763 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5765 AccAXRrl1 (x); // BCCCCCCD:D000000B
5766 AccAXRrl1 (x); // BBCCCCCC:DD000000
5768 emitcode("rrc","a");
5769 emitcode("xch","a,%s", x);
5770 emitcode("rrc","a");
5771 emitcode("mov","c,acc.0"); //<< get correct bit
5772 emitcode("xch","a,%s", x);
5774 emitcode("rrc","a");
5775 emitcode("xch","a,%s", x);
5776 emitcode("rrc","a");
5777 emitcode("xch","a,%s", x);
5780 case 7: // a:x <<= 7
5782 emitcode ("anl", "a,#0x%02x",
5783 SRMask[shCount]); // 0000000B:CCCCCCCD
5785 emitcode ("mov", "c,acc.0"); // c = B
5787 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5789 AccAXRrl1 (x); // BCCCCCCC:D0000000
5797 /*-----------------------------------------------------------------*/
5798 /* AccAXRsh - right shift a:x known count (0..7) */
5799 /*-----------------------------------------------------------------*/
5801 AccAXRsh (char *x, int shCount)
5809 AccAXRrl1 (x); // 0->a:x
5814 AccAXRrl1 (x); // 0->a:x
5817 AccAXRrl1 (x); // 0->a:x
5822 case 5: // AAAAABBB:CCCCCDDD = a:x
5824 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5826 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5828 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5830 emitcode ("anl", "a,#0x%02x",
5831 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5833 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5835 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5837 emitcode ("anl", "a,#0x%02x",
5838 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5840 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5842 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5844 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5847 case 6: // AABBBBBB:CCDDDDDD
5849 emitcode ("mov", "c,acc.7");
5850 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5852 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5854 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5856 emitcode ("anl", "a,#0x%02x",
5857 SRMask[shCount]); // 000000AA:BBBBBBCC
5860 case 7: // ABBBBBBB:CDDDDDDD
5862 emitcode ("mov", "c,acc.7"); // c = A
5864 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5866 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5868 emitcode ("anl", "a,#0x%02x",
5869 SRMask[shCount]); // 0000000A:BBBBBBBC
5877 /*-----------------------------------------------------------------*/
5878 /* AccAXRshS - right shift signed a:x known count (0..7) */
5879 /*-----------------------------------------------------------------*/
5881 AccAXRshS (char *x, int shCount)
5889 emitcode ("mov", "c,acc.7");
5890 AccAXRrl1 (x); // s->a:x
5894 emitcode ("mov", "c,acc.7");
5895 AccAXRrl1 (x); // s->a:x
5897 emitcode ("mov", "c,acc.7");
5898 AccAXRrl1 (x); // s->a:x
5903 case 5: // AAAAABBB:CCCCCDDD = a:x
5905 tlbl = newiTempLabel (NULL);
5906 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5908 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5910 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5912 emitcode ("anl", "a,#0x%02x",
5913 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5915 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5917 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5919 emitcode ("anl", "a,#0x%02x",
5920 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5922 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5924 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5926 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5928 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5929 emitcode ("orl", "a,#0x%02x",
5930 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5932 emitcode ("", "%05d$:", tlbl->key + 100);
5933 break; // SSSSAAAA:BBBCCCCC
5935 case 6: // AABBBBBB:CCDDDDDD
5937 tlbl = newiTempLabel (NULL);
5938 emitcode ("mov", "c,acc.7");
5939 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5941 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5943 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5945 emitcode ("anl", "a,#0x%02x",
5946 SRMask[shCount]); // 000000AA:BBBBBBCC
5948 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5949 emitcode ("orl", "a,#0x%02x",
5950 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5952 emitcode ("", "%05d$:", tlbl->key + 100);
5954 case 7: // ABBBBBBB:CDDDDDDD
5956 tlbl = newiTempLabel (NULL);
5957 emitcode ("mov", "c,acc.7"); // c = A
5959 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5961 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5963 emitcode ("anl", "a,#0x%02x",
5964 SRMask[shCount]); // 0000000A:BBBBBBBC
5966 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5967 emitcode ("orl", "a,#0x%02x",
5968 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5970 emitcode ("", "%05d$:", tlbl->key + 100);
5977 /*-----------------------------------------------------------------*/
5978 /* shiftL2Left2Result - shift left two bytes from left to result */
5979 /*-----------------------------------------------------------------*/
5981 shiftL2Left2Result (operand * left, int offl,
5982 operand * result, int offr, int shCount)
5984 if (sameRegs (AOP (result), AOP (left)) &&
5985 ((offl + MSB16) == offr))
5987 /* don't crash result[offr] */
5988 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5989 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5993 movLeft2Result (left, offl, result, offr, 0);
5994 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5996 /* ax << shCount (x = lsb(result)) */
5997 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5998 aopPut (AOP (result), "a", offr + MSB16);
6002 /*-----------------------------------------------------------------*/
6003 /* shiftR2Left2Result - shift right two bytes from left to result */
6004 /*-----------------------------------------------------------------*/
6006 shiftR2Left2Result (operand * left, int offl,
6007 operand * result, int offr,
6008 int shCount, int sign)
6010 if (sameRegs (AOP (result), AOP (left)) &&
6011 ((offl + MSB16) == offr))
6013 /* don't crash result[offr] */
6014 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6015 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6019 movLeft2Result (left, offl, result, offr, 0);
6020 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6022 /* a:x >> shCount (x = lsb(result)) */
6024 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6026 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6027 if (getDataSize (result) > 1)
6028 aopPut (AOP (result), "a", offr + MSB16);
6031 /*-----------------------------------------------------------------*/
6032 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6033 /*-----------------------------------------------------------------*/
6035 shiftLLeftOrResult (operand * left, int offl,
6036 operand * result, int offr, int shCount)
6038 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6039 /* shift left accumulator */
6041 /* or with result */
6042 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6043 /* back to result */
6044 aopPut (AOP (result), "a", offr);
6047 /*-----------------------------------------------------------------*/
6048 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6049 /*-----------------------------------------------------------------*/
6051 shiftRLeftOrResult (operand * left, int offl,
6052 operand * result, int offr, int shCount)
6054 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6055 /* shift right accumulator */
6057 /* or with result */
6058 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6059 /* back to result */
6060 aopPut (AOP (result), "a", offr);
6063 /*-----------------------------------------------------------------*/
6064 /* genlshOne - left shift a one byte quantity by known count */
6065 /*-----------------------------------------------------------------*/
6067 genlshOne (operand * result, operand * left, int shCount)
6069 D(emitcode (";", "genlshOne"));
6071 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6074 /*-----------------------------------------------------------------*/
6075 /* genlshTwo - left shift two bytes by known amount != 0 */
6076 /*-----------------------------------------------------------------*/
6078 genlshTwo (operand * result, operand * left, int shCount)
6082 D(emitcode (";", "genlshTwo"));
6084 size = getDataSize (result);
6086 /* if shCount >= 8 */
6094 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6096 movLeft2Result (left, LSB, result, MSB16, 0);
6098 aopPut (AOP (result), zero, LSB);
6101 /* 1 <= shCount <= 7 */
6105 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6107 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6111 /*-----------------------------------------------------------------*/
6112 /* shiftLLong - shift left one long from left to result */
6113 /* offl = LSB or MSB16 */
6114 /*-----------------------------------------------------------------*/
6116 shiftLLong (operand * left, operand * result, int offr)
6119 int size = AOP_SIZE (result);
6121 if (size >= LSB + offr)
6123 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6125 emitcode ("add", "a,acc");
6126 if (sameRegs (AOP (left), AOP (result)) &&
6127 size >= MSB16 + offr && offr != LSB)
6128 emitcode ("xch", "a,%s",
6129 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6131 aopPut (AOP (result), "a", LSB + offr);
6134 if (size >= MSB16 + offr)
6136 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6138 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6141 emitcode ("rlc", "a");
6142 if (sameRegs (AOP (left), AOP (result)) &&
6143 size >= MSB24 + offr && offr != LSB)
6144 emitcode ("xch", "a,%s",
6145 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6147 aopPut (AOP (result), "a", MSB16 + offr);
6150 if (size >= MSB24 + offr)
6152 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6154 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6157 emitcode ("rlc", "a");
6158 if (sameRegs (AOP (left), AOP (result)) &&
6159 size >= MSB32 + offr && offr != LSB)
6160 emitcode ("xch", "a,%s",
6161 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6163 aopPut (AOP (result), "a", MSB24 + offr);
6166 if (size > MSB32 + offr)
6168 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6170 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6173 emitcode ("rlc", "a");
6174 aopPut (AOP (result), "a", MSB32 + offr);
6177 aopPut (AOP (result), zero, LSB);
6180 /*-----------------------------------------------------------------*/
6181 /* genlshFour - shift four byte by a known amount != 0 */
6182 /*-----------------------------------------------------------------*/
6184 genlshFour (operand * result, operand * left, int shCount)
6188 D(emitcode (";", "genlshFour"));
6190 size = AOP_SIZE (result);
6192 /* if shifting more that 3 bytes */
6197 /* lowest order of left goes to the highest
6198 order of the destination */
6199 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6201 movLeft2Result (left, LSB, result, MSB32, 0);
6202 aopPut (AOP (result), zero, LSB);
6203 aopPut (AOP (result), zero, MSB16);
6204 aopPut (AOP (result), zero, MSB24);
6208 /* more than two bytes */
6209 else if (shCount >= 16)
6211 /* lower order two bytes goes to higher order two bytes */
6213 /* if some more remaining */
6215 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6218 movLeft2Result (left, MSB16, result, MSB32, 0);
6219 movLeft2Result (left, LSB, result, MSB24, 0);
6221 aopPut (AOP (result), zero, MSB16);
6222 aopPut (AOP (result), zero, LSB);
6226 /* if more than 1 byte */
6227 else if (shCount >= 8)
6229 /* lower order three bytes goes to higher order three bytes */
6234 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6236 movLeft2Result (left, LSB, result, MSB16, 0);
6242 movLeft2Result (left, MSB24, result, MSB32, 0);
6243 movLeft2Result (left, MSB16, result, MSB24, 0);
6244 movLeft2Result (left, LSB, result, MSB16, 0);
6245 aopPut (AOP (result), zero, LSB);
6247 else if (shCount == 1)
6248 shiftLLong (left, result, MSB16);
6251 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6252 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6253 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6254 aopPut (AOP (result), zero, LSB);
6259 /* 1 <= shCount <= 7 */
6260 else if (shCount <= 2)
6262 shiftLLong (left, result, LSB);
6264 shiftLLong (result, result, LSB);
6266 /* 3 <= shCount <= 7, optimize */
6269 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6270 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6271 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6275 /*-----------------------------------------------------------------*/
6276 /* genLeftShiftLiteral - left shifting by known count */
6277 /*-----------------------------------------------------------------*/
6279 genLeftShiftLiteral (operand * left,
6284 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6287 D(emitcode (";", "genLeftShiftLiteral"));
6289 freeAsmop (right, NULL, ic, TRUE);
6291 aopOp (left, ic, FALSE);
6292 aopOp (result, ic, FALSE);
6294 size = getSize (operandType (result));
6297 emitcode ("; shift left ", "result %d, left %d", size,
6301 /* I suppose that the left size >= result size */
6306 movLeft2Result (left, size, result, size, 0);
6310 else if (shCount >= (size * 8))
6312 aopPut (AOP (result), zero, size);
6318 genlshOne (result, left, shCount);
6322 genlshTwo (result, left, shCount);
6326 genlshFour (result, left, shCount);
6329 fprintf(stderr, "*** ack! mystery literal shift!\n");
6333 freeAsmop (left, NULL, ic, TRUE);
6334 freeAsmop (result, NULL, ic, TRUE);
6337 /*-----------------------------------------------------------------*/
6338 /* genLeftShift - generates code for left shifting */
6339 /*-----------------------------------------------------------------*/
6341 genLeftShift (iCode * ic)
6343 operand *left, *right, *result;
6346 symbol *tlbl, *tlbl1;
6348 D(emitcode (";", "genLeftShift"));
6350 right = IC_RIGHT (ic);
6351 left = IC_LEFT (ic);
6352 result = IC_RESULT (ic);
6354 aopOp (right, ic, FALSE);
6356 /* if the shift count is known then do it
6357 as efficiently as possible */
6358 if (AOP_TYPE (right) == AOP_LIT)
6360 genLeftShiftLiteral (left, right, result, ic);
6364 /* shift count is unknown then we have to form
6365 a loop get the loop count in B : Note: we take
6366 only the lower order byte since shifting
6367 more that 32 bits make no sense anyway, ( the
6368 largest size of an object can be only 32 bits ) */
6370 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6371 emitcode ("inc", "b");
6372 freeAsmop (right, NULL, ic, TRUE);
6373 aopOp (left, ic, FALSE);
6374 aopOp (result, ic, FALSE);
6376 /* now move the left to the result if they are not the
6378 if (!sameRegs (AOP (left), AOP (result)) &&
6379 AOP_SIZE (result) > 1)
6382 size = AOP_SIZE (result);
6386 l = aopGet (AOP (left), offset, FALSE, TRUE);
6387 if (*l == '@' && (IS_AOP_PREG (result)))
6390 emitcode ("mov", "a,%s", l);
6391 aopPut (AOP (result), "a", offset);
6394 aopPut (AOP (result), l, offset);
6399 tlbl = newiTempLabel (NULL);
6400 size = AOP_SIZE (result);
6402 tlbl1 = newiTempLabel (NULL);
6404 /* if it is only one byte then */
6407 symbol *tlbl1 = newiTempLabel (NULL);
6409 l = aopGet (AOP (left), 0, FALSE, FALSE);
6411 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6412 emitcode ("", "%05d$:", tlbl->key + 100);
6413 emitcode ("add", "a,acc");
6414 emitcode ("", "%05d$:", tlbl1->key + 100);
6415 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6416 aopPut (AOP (result), "a", 0);
6420 reAdjustPreg (AOP (result));
6422 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6423 emitcode ("", "%05d$:", tlbl->key + 100);
6424 l = aopGet (AOP (result), offset, FALSE, FALSE);
6426 emitcode ("add", "a,acc");
6427 aopPut (AOP (result), "a", offset++);
6430 l = aopGet (AOP (result), offset, FALSE, FALSE);
6432 emitcode ("rlc", "a");
6433 aopPut (AOP (result), "a", offset++);
6435 reAdjustPreg (AOP (result));
6437 emitcode ("", "%05d$:", tlbl1->key + 100);
6438 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6440 freeAsmop (left, NULL, ic, TRUE);
6441 freeAsmop (result, NULL, ic, TRUE);
6444 /*-----------------------------------------------------------------*/
6445 /* genrshOne - right shift a one byte quantity by known count */
6446 /*-----------------------------------------------------------------*/
6448 genrshOne (operand * result, operand * left,
6449 int shCount, int sign)
6451 D(emitcode (";", "genrshOne"));
6453 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6456 /*-----------------------------------------------------------------*/
6457 /* genrshTwo - right shift two bytes by known amount != 0 */
6458 /*-----------------------------------------------------------------*/
6460 genrshTwo (operand * result, operand * left,
6461 int shCount, int sign)
6463 D(emitcode (";", "genrshTwo"));
6465 /* if shCount >= 8 */
6470 shiftR1Left2Result (left, MSB16, result, LSB,
6473 movLeft2Result (left, MSB16, result, LSB, sign);
6474 addSign (result, MSB16, sign);
6477 /* 1 <= shCount <= 7 */
6479 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6482 /*-----------------------------------------------------------------*/
6483 /* shiftRLong - shift right one long from left to result */
6484 /* offl = LSB or MSB16 */
6485 /*-----------------------------------------------------------------*/
6487 shiftRLong (operand * left, int offl,
6488 operand * result, int sign)
6490 int isSameRegs=sameRegs(AOP(left),AOP(result));
6492 if (isSameRegs && offl>1) {
6493 // we are in big trouble, but this shouldn't happen
6494 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6497 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6502 emitcode ("rlc", "a");
6503 emitcode ("subb", "a,acc");
6504 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6506 aopPut (AOP(result), zero, MSB32);
6511 emitcode ("clr", "c");
6513 emitcode ("mov", "c,acc.7");
6516 emitcode ("rrc", "a");
6518 if (isSameRegs && offl==MSB16) {
6519 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6521 aopPut (AOP (result), "a", MSB32);
6522 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6525 emitcode ("rrc", "a");
6526 if (isSameRegs && offl==1) {
6527 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6529 aopPut (AOP (result), "a", MSB24);
6530 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6532 emitcode ("rrc", "a");
6533 aopPut (AOP (result), "a", MSB16 - offl);
6537 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6538 emitcode ("rrc", "a");
6539 aopPut (AOP (result), "a", LSB);
6543 /*-----------------------------------------------------------------*/
6544 /* genrshFour - shift four byte by a known amount != 0 */
6545 /*-----------------------------------------------------------------*/
6547 genrshFour (operand * result, operand * left,
6548 int shCount, int sign)
6550 D(emitcode (";", "genrshFour"));
6552 /* if shifting more that 3 bytes */
6557 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6559 movLeft2Result (left, MSB32, result, LSB, sign);
6560 addSign (result, MSB16, sign);
6562 else if (shCount >= 16)
6566 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6569 movLeft2Result (left, MSB24, result, LSB, 0);
6570 movLeft2Result (left, MSB32, result, MSB16, sign);
6572 addSign (result, MSB24, sign);
6574 else if (shCount >= 8)
6578 shiftRLong (left, MSB16, result, sign);
6579 else if (shCount == 0)
6581 movLeft2Result (left, MSB16, result, LSB, 0);
6582 movLeft2Result (left, MSB24, result, MSB16, 0);
6583 movLeft2Result (left, MSB32, result, MSB24, sign);
6584 addSign (result, MSB32, sign);
6588 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6589 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6590 /* the last shift is signed */
6591 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6592 addSign (result, MSB32, sign);
6596 { /* 1 <= shCount <= 7 */
6599 shiftRLong (left, LSB, result, sign);
6601 shiftRLong (result, LSB, result, sign);
6605 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6606 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6607 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6612 /*-----------------------------------------------------------------*/
6613 /* genRightShiftLiteral - right shifting by known count */
6614 /*-----------------------------------------------------------------*/
6616 genRightShiftLiteral (operand * left,
6622 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6625 D(emitcode (";", "genRightShiftLiteral"));
6627 freeAsmop (right, NULL, ic, TRUE);
6629 aopOp (left, ic, FALSE);
6630 aopOp (result, ic, FALSE);
6633 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6637 size = getDataSize (left);
6638 /* test the LEFT size !!! */
6640 /* I suppose that the left size >= result size */
6643 size = getDataSize (result);
6645 movLeft2Result (left, size, result, size, 0);
6648 else if (shCount >= (size * 8))
6651 /* get sign in acc.7 */
6652 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6653 addSign (result, LSB, sign);
6660 genrshOne (result, left, shCount, sign);
6664 genrshTwo (result, left, shCount, sign);
6668 genrshFour (result, left, shCount, sign);
6674 freeAsmop (left, NULL, ic, TRUE);
6675 freeAsmop (result, NULL, ic, TRUE);
6679 /*-----------------------------------------------------------------*/
6680 /* genSignedRightShift - right shift of signed number */
6681 /*-----------------------------------------------------------------*/
6683 genSignedRightShift (iCode * ic)
6685 operand *right, *left, *result;
6688 symbol *tlbl, *tlbl1;
6690 D(emitcode (";", "genSignedRightShift"));
6692 /* we do it the hard way put the shift count in b
6693 and loop thru preserving the sign */
6695 right = IC_RIGHT (ic);
6696 left = IC_LEFT (ic);
6697 result = IC_RESULT (ic);
6699 aopOp (right, ic, FALSE);
6702 if (AOP_TYPE (right) == AOP_LIT)
6704 genRightShiftLiteral (left, right, result, ic, 1);
6707 /* shift count is unknown then we have to form
6708 a loop get the loop count in B : Note: we take
6709 only the lower order byte since shifting
6710 more that 32 bits make no sense anyway, ( the
6711 largest size of an object can be only 32 bits ) */
6713 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6714 emitcode ("inc", "b");
6715 freeAsmop (right, NULL, ic, TRUE);
6716 aopOp (left, ic, FALSE);
6717 aopOp (result, ic, FALSE);
6719 /* now move the left to the result if they are not the
6721 if (!sameRegs (AOP (left), AOP (result)) &&
6722 AOP_SIZE (result) > 1)
6725 size = AOP_SIZE (result);
6729 l = aopGet (AOP (left), offset, FALSE, TRUE);
6730 if (*l == '@' && IS_AOP_PREG (result))
6733 emitcode ("mov", "a,%s", l);
6734 aopPut (AOP (result), "a", offset);
6737 aopPut (AOP (result), l, offset);
6742 /* mov the highest order bit to OVR */
6743 tlbl = newiTempLabel (NULL);
6744 tlbl1 = newiTempLabel (NULL);
6746 size = AOP_SIZE (result);
6748 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6749 emitcode ("rlc", "a");
6750 emitcode ("mov", "ov,c");
6751 /* if it is only one byte then */
6754 l = aopGet (AOP (left), 0, FALSE, FALSE);
6756 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6757 emitcode ("", "%05d$:", tlbl->key + 100);
6758 emitcode ("mov", "c,ov");
6759 emitcode ("rrc", "a");
6760 emitcode ("", "%05d$:", tlbl1->key + 100);
6761 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6762 aopPut (AOP (result), "a", 0);
6766 reAdjustPreg (AOP (result));
6767 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6768 emitcode ("", "%05d$:", tlbl->key + 100);
6769 emitcode ("mov", "c,ov");
6772 l = aopGet (AOP (result), offset, FALSE, FALSE);
6774 emitcode ("rrc", "a");
6775 aopPut (AOP (result), "a", offset--);
6777 reAdjustPreg (AOP (result));
6778 emitcode ("", "%05d$:", tlbl1->key + 100);
6779 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6782 freeAsmop (left, NULL, ic, TRUE);
6783 freeAsmop (result, NULL, ic, TRUE);
6786 /*-----------------------------------------------------------------*/
6787 /* genRightShift - generate code for right shifting */
6788 /*-----------------------------------------------------------------*/
6790 genRightShift (iCode * ic)
6792 operand *right, *left, *result;
6796 symbol *tlbl, *tlbl1;
6798 D(emitcode (";", "genRightShift"));
6800 /* if signed then we do it the hard way preserve the
6801 sign bit moving it inwards */
6802 retype = getSpec (operandType (IC_RESULT (ic)));
6804 if (!SPEC_USIGN (retype))
6806 genSignedRightShift (ic);
6810 /* signed & unsigned types are treated the same : i.e. the
6811 signed is NOT propagated inwards : quoting from the
6812 ANSI - standard : "for E1 >> E2, is equivalent to division
6813 by 2**E2 if unsigned or if it has a non-negative value,
6814 otherwise the result is implementation defined ", MY definition
6815 is that the sign does not get propagated */
6817 right = IC_RIGHT (ic);
6818 left = IC_LEFT (ic);
6819 result = IC_RESULT (ic);
6821 aopOp (right, ic, FALSE);
6823 /* if the shift count is known then do it
6824 as efficiently as possible */
6825 if (AOP_TYPE (right) == AOP_LIT)
6827 genRightShiftLiteral (left, right, result, ic, 0);
6831 /* shift count is unknown then we have to form
6832 a loop get the loop count in B : Note: we take
6833 only the lower order byte since shifting
6834 more that 32 bits make no sense anyway, ( the
6835 largest size of an object can be only 32 bits ) */
6837 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6838 emitcode ("inc", "b");
6839 freeAsmop (right, NULL, ic, TRUE);
6840 aopOp (left, ic, FALSE);
6841 aopOp (result, ic, FALSE);
6843 /* now move the left to the result if they are not the
6845 if (!sameRegs (AOP (left), AOP (result)) &&
6846 AOP_SIZE (result) > 1)
6849 size = AOP_SIZE (result);
6853 l = aopGet (AOP (left), offset, FALSE, TRUE);
6854 if (*l == '@' && IS_AOP_PREG (result))
6857 emitcode ("mov", "a,%s", l);
6858 aopPut (AOP (result), "a", offset);
6861 aopPut (AOP (result), l, offset);
6866 tlbl = newiTempLabel (NULL);
6867 tlbl1 = newiTempLabel (NULL);
6868 size = AOP_SIZE (result);
6871 /* if it is only one byte then */
6874 l = aopGet (AOP (left), 0, FALSE, FALSE);
6876 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6877 emitcode ("", "%05d$:", tlbl->key + 100);
6879 emitcode ("rrc", "a");
6880 emitcode ("", "%05d$:", tlbl1->key + 100);
6881 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6882 aopPut (AOP (result), "a", 0);
6886 reAdjustPreg (AOP (result));
6887 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6888 emitcode ("", "%05d$:", tlbl->key + 100);
6892 l = aopGet (AOP (result), offset, FALSE, FALSE);
6894 emitcode ("rrc", "a");
6895 aopPut (AOP (result), "a", offset--);
6897 reAdjustPreg (AOP (result));
6899 emitcode ("", "%05d$:", tlbl1->key + 100);
6900 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6903 freeAsmop (left, NULL, ic, TRUE);
6904 freeAsmop (result, NULL, ic, TRUE);
6907 /*-----------------------------------------------------------------*/
6908 /* genUnpackBits - generates code for unpacking bits */
6909 /*-----------------------------------------------------------------*/
6911 genUnpackBits (operand * result, char *rname, int ptype)
6919 D(emitcode (";", "genUnpackBits"));
6921 etype = getSpec (operandType (result));
6922 rsize = getSize (operandType (result));
6923 /* read the first byte */
6929 emitcode ("mov", "a,@%s", rname);
6933 emitcode ("movx", "a,@%s", rname);
6937 emitcode ("movx", "a,@dptr");
6941 emitcode ("clr", "a");
6942 emitcode ("movc", "a,@a+dptr");
6946 emitcode ("lcall", "__gptrget");
6950 rlen = SPEC_BLEN (etype);
6952 /* if we have bitdisplacement then it fits */
6953 /* into this byte completely or if length is */
6954 /* less than a byte */
6955 if ((shCnt = SPEC_BSTR (etype)) ||
6956 (SPEC_BLEN (etype) <= 8))
6959 /* shift right acc */
6962 emitcode ("anl", "a,#0x%02x",
6963 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6964 aopPut (AOP (result), "a", offset++);
6968 /* bit field did not fit in a byte */
6969 aopPut (AOP (result), "a", offset++);
6978 emitcode ("inc", "%s", rname);
6979 emitcode ("mov", "a,@%s", rname);
6983 emitcode ("inc", "%s", rname);
6984 emitcode ("movx", "a,@%s", rname);
6988 emitcode ("inc", "dptr");
6989 emitcode ("movx", "a,@dptr");
6993 emitcode ("clr", "a");
6994 emitcode ("inc", "dptr");
6995 emitcode ("movc", "a,@a+dptr");
6999 emitcode ("inc", "dptr");
7000 emitcode ("lcall", "__gptrget");
7005 /* if we are done */
7009 aopPut (AOP (result), "a", offset++);
7015 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7017 aopPut (AOP (result), "a", offset++);
7025 aopPut (AOP (result), zero, offset++);
7031 /*-----------------------------------------------------------------*/
7032 /* genDataPointerGet - generates code when ptr offset is known */
7033 /*-----------------------------------------------------------------*/
7035 genDataPointerGet (operand * left,
7041 int size, offset = 0;
7043 D(emitcode (";", "genDataPointerGet"));
7045 aopOp (result, ic, TRUE);
7047 /* get the string representation of the name */
7048 l = aopGet (AOP (left), 0, FALSE, TRUE);
7049 size = AOP_SIZE (result);
7053 sprintf (buffer, "(%s + %d)", l + 1, offset);
7055 sprintf (buffer, "%s", l + 1);
7056 aopPut (AOP (result), buffer, offset++);
7059 freeAsmop (left, NULL, ic, TRUE);
7060 freeAsmop (result, NULL, ic, TRUE);
7063 /*-----------------------------------------------------------------*/
7064 /* genNearPointerGet - emitcode for near pointer fetch */
7065 /*-----------------------------------------------------------------*/
7067 genNearPointerGet (operand * left,
7075 sym_link *rtype, *retype;
7076 sym_link *ltype = operandType (left);
7079 D(emitcode (";", "genNearPointerGet"));
7081 rtype = operandType (result);
7082 retype = getSpec (rtype);
7084 aopOp (left, ic, FALSE);
7086 /* if left is rematerialisable and
7087 result is not bit variable type and
7088 the left is pointer to data space i.e
7089 lower 128 bytes of space */
7090 if (AOP_TYPE (left) == AOP_IMMD &&
7091 !IS_BITVAR (retype) &&
7092 DCL_TYPE (ltype) == POINTER)
7094 genDataPointerGet (left, result, ic);
7098 /* if the value is already in a pointer register
7099 then don't need anything more */
7100 if (!AOP_INPREG (AOP (left)))
7102 /* otherwise get a free pointer register */
7104 preg = getFreePtr (ic, &aop, FALSE);
7105 emitcode ("mov", "%s,%s",
7107 aopGet (AOP (left), 0, FALSE, TRUE));
7111 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7113 //aopOp (result, ic, FALSE);
7114 aopOp (result, ic, result?TRUE:FALSE);
7116 /* if bitfield then unpack the bits */
7117 if (IS_BITVAR (retype))
7118 genUnpackBits (result, rname, POINTER);
7121 /* we have can just get the values */
7122 int size = AOP_SIZE (result);
7127 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7130 emitcode ("mov", "a,@%s", rname);
7131 aopPut (AOP (result), "a", offset);
7135 sprintf (buffer, "@%s", rname);
7136 aopPut (AOP (result), buffer, offset);
7140 emitcode ("inc", "%s", rname);
7144 /* now some housekeeping stuff */
7145 if (aop) /* we had to allocate for this iCode */
7147 if (pi) { /* post increment present */
7148 aopPut(AOP ( left ),rname,0);
7150 freeAsmop (NULL, aop, ic, TRUE);
7154 /* we did not allocate which means left
7155 already in a pointer register, then
7156 if size > 0 && this could be used again
7157 we have to point it back to where it
7159 if ((AOP_SIZE (result) > 1 &&
7160 !OP_SYMBOL (left)->remat &&
7161 (OP_SYMBOL (left)->liveTo > ic->seq ||
7165 int size = AOP_SIZE (result) - 1;
7167 emitcode ("dec", "%s", rname);
7172 freeAsmop (left, NULL, ic, TRUE);
7173 freeAsmop (result, NULL, ic, TRUE);
7174 if (pi) pi->generated = 1;
7177 /*-----------------------------------------------------------------*/
7178 /* genPagedPointerGet - emitcode for paged pointer fetch */
7179 /*-----------------------------------------------------------------*/
7181 genPagedPointerGet (operand * left,
7189 sym_link *rtype, *retype;
7191 D(emitcode (";", "genPagedPointerGet"));
7193 rtype = operandType (result);
7194 retype = getSpec (rtype);
7196 aopOp (left, ic, FALSE);
7198 /* if the value is already in a pointer register
7199 then don't need anything more */
7200 if (!AOP_INPREG (AOP (left)))
7202 /* otherwise get a free pointer register */
7204 preg = getFreePtr (ic, &aop, FALSE);
7205 emitcode ("mov", "%s,%s",
7207 aopGet (AOP (left), 0, FALSE, TRUE));
7211 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7213 aopOp (result, ic, FALSE);
7215 /* if bitfield then unpack the bits */
7216 if (IS_BITVAR (retype))
7217 genUnpackBits (result, rname, PPOINTER);
7220 /* we have can just get the values */
7221 int size = AOP_SIZE (result);
7227 emitcode ("movx", "a,@%s", rname);
7228 aopPut (AOP (result), "a", offset);
7233 emitcode ("inc", "%s", rname);
7237 /* now some housekeeping stuff */
7238 if (aop) /* we had to allocate for this iCode */
7240 if (pi) aopPut ( AOP (left), rname, 0);
7241 freeAsmop (NULL, aop, ic, TRUE);
7245 /* we did not allocate which means left
7246 already in a pointer register, then
7247 if size > 0 && this could be used again
7248 we have to point it back to where it
7250 if ((AOP_SIZE (result) > 1 &&
7251 !OP_SYMBOL (left)->remat &&
7252 (OP_SYMBOL (left)->liveTo > ic->seq ||
7256 int size = AOP_SIZE (result) - 1;
7258 emitcode ("dec", "%s", rname);
7263 freeAsmop (left, NULL, ic, TRUE);
7264 freeAsmop (result, NULL, ic, TRUE);
7265 if (pi) pi->generated = 1;
7269 /*-----------------------------------------------------------------*/
7270 /* genFarPointerGet - gget value from far space */
7271 /*-----------------------------------------------------------------*/
7273 genFarPointerGet (operand * left,
7274 operand * result, iCode * ic, iCode * pi)
7277 sym_link *retype = getSpec (operandType (result));
7279 D(emitcode (";", "genFarPointerGet"));
7281 aopOp (left, ic, FALSE);
7283 /* if the operand is already in dptr
7284 then we do nothing else we move the value to dptr */
7285 if (AOP_TYPE (left) != AOP_STR)
7287 /* if this is remateriazable */
7288 if (AOP_TYPE (left) == AOP_IMMD)
7289 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7291 { /* we need to get it byte by byte */
7292 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7293 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7296 /* so dptr know contains the address */
7297 aopOp (result, ic, FALSE);
7299 /* if bit then unpack */
7300 if (IS_BITVAR (retype))
7301 genUnpackBits (result, "dptr", FPOINTER);
7304 size = AOP_SIZE (result);
7309 emitcode ("movx", "a,@dptr");
7310 aopPut (AOP (result), "a", offset++);
7312 emitcode ("inc", "dptr");
7316 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7317 aopPut ( AOP (left), "dpl", 0);
7318 aopPut ( AOP (left), "dph", 1);
7321 freeAsmop (left, NULL, ic, TRUE);
7322 freeAsmop (result, NULL, ic, TRUE);
7325 /*-----------------------------------------------------------------*/
7326 /* genCodePointerGet - gget value from code space */
7327 /*-----------------------------------------------------------------*/
7329 genCodePointerGet (operand * left,
7330 operand * result, iCode * ic, iCode *pi)
7333 sym_link *retype = getSpec (operandType (result));
7335 D(emitcode (";", "genCodePointerGet"));
7337 aopOp (left, ic, FALSE);
7339 /* if the operand is already in dptr
7340 then we do nothing else we move the value to dptr */
7341 if (AOP_TYPE (left) != AOP_STR)
7343 /* if this is remateriazable */
7344 if (AOP_TYPE (left) == AOP_IMMD)
7345 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7347 { /* we need to get it byte by byte */
7348 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7349 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7352 /* so dptr know contains the address */
7353 aopOp (result, ic, FALSE);
7355 /* if bit then unpack */
7356 if (IS_BITVAR (retype))
7357 genUnpackBits (result, "dptr", CPOINTER);
7360 size = AOP_SIZE (result);
7365 emitcode ("clr", "a");
7366 emitcode ("movc", "a,@a+dptr");
7367 aopPut (AOP (result), "a", offset++);
7369 emitcode ("inc", "dptr");
7373 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7374 aopPut ( AOP (left), "dpl", 0);
7375 aopPut ( AOP (left), "dph", 1);
7378 freeAsmop (left, NULL, ic, TRUE);
7379 freeAsmop (result, NULL, ic, TRUE);
7382 /*-----------------------------------------------------------------*/
7383 /* genGenPointerGet - gget value from generic pointer space */
7384 /*-----------------------------------------------------------------*/
7386 genGenPointerGet (operand * left,
7387 operand * result, iCode * ic, iCode *pi)
7390 sym_link *retype = getSpec (operandType (result));
7392 D(emitcode (";", "genGenPointerGet"));
7394 aopOp (left, ic, FALSE);
7396 /* if the operand is already in dptr
7397 then we do nothing else we move the value to dptr */
7398 if (AOP_TYPE (left) != AOP_STR)
7400 /* if this is remateriazable */
7401 if (AOP_TYPE (left) == AOP_IMMD)
7403 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7404 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7405 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7407 emitcode ("mov", "b,#%d", pointerCode (retype));
7410 { /* we need to get it byte by byte */
7411 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7412 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7413 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7416 /* so dptr know contains the address */
7417 aopOp (result, ic, FALSE);
7419 /* if bit then unpack */
7420 if (IS_BITVAR (retype))
7421 genUnpackBits (result, "dptr", GPOINTER);
7424 size = AOP_SIZE (result);
7429 emitcode ("lcall", "__gptrget");
7430 aopPut (AOP (result), "a", offset++);
7432 emitcode ("inc", "dptr");
7436 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7437 aopPut ( AOP (left), "dpl", 0);
7438 aopPut ( AOP (left), "dph", 1);
7439 aopPut ( AOP (left), "b", 2);
7442 freeAsmop (left, NULL, ic, TRUE);
7443 freeAsmop (result, NULL, ic, TRUE);
7446 /*-----------------------------------------------------------------*/
7447 /* genPointerGet - generate code for pointer get */
7448 /*-----------------------------------------------------------------*/
7450 genPointerGet (iCode * ic, iCode *pi)
7452 operand *left, *result;
7453 sym_link *type, *etype;
7456 D(emitcode (";", "genPointerGet"));
7458 left = IC_LEFT (ic);
7459 result = IC_RESULT (ic);
7461 /* depending on the type of pointer we need to
7462 move it to the correct pointer register */
7463 type = operandType (left);
7464 etype = getSpec (type);
7465 /* if left is of type of pointer then it is simple */
7466 if (IS_PTR (type) && !IS_FUNC (type->next))
7467 p_type = DCL_TYPE (type);
7470 /* we have to go by the storage class */
7471 p_type = PTR_TYPE (SPEC_OCLS (etype));
7474 /* special case when cast remat */
7475 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7476 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7477 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7478 type = type = operandType (left);
7479 p_type = DCL_TYPE (type);
7481 /* now that we have the pointer type we assign
7482 the pointer values */
7488 genNearPointerGet (left, result, ic, pi);
7492 genPagedPointerGet (left, result, ic, pi);
7496 genFarPointerGet (left, result, ic, pi);
7500 genCodePointerGet (left, result, ic, pi);
7504 genGenPointerGet (left, result, ic, pi);
7510 /*-----------------------------------------------------------------*/
7511 /* genPackBits - generates code for packed bit storage */
7512 /*-----------------------------------------------------------------*/
7514 genPackBits (sym_link * etype,
7516 char *rname, int p_type)
7524 D(emitcode (";", "genPackBits"));
7526 blen = SPEC_BLEN (etype);
7527 bstr = SPEC_BSTR (etype);
7529 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7532 /* if the bit lenth is less than or */
7533 /* it exactly fits a byte then */
7534 if (SPEC_BLEN (etype) <= 8)
7536 shCount = SPEC_BSTR (etype);
7538 /* shift left acc */
7541 if (SPEC_BLEN (etype) < 8)
7542 { /* if smaller than a byte */
7548 emitcode ("mov", "b,a");
7549 emitcode ("mov", "a,@%s", rname);
7553 emitcode ("mov", "b,a");
7554 emitcode ("movx", "a,@dptr");
7558 emitcode ("push", "b");
7559 emitcode ("push", "acc");
7560 emitcode ("lcall", "__gptrget");
7561 emitcode ("pop", "b");
7565 emitcode ("anl", "a,#0x%02x", (unsigned char)
7566 ((unsigned char) (0xFF << (blen + bstr)) |
7567 (unsigned char) (0xFF >> (8 - bstr))));
7568 emitcode ("orl", "a,b");
7569 if (p_type == GPOINTER)
7570 emitcode ("pop", "b");
7577 emitcode ("mov", "@%s,a", rname);
7581 emitcode ("movx", "@dptr,a");
7585 emitcode ("lcall", "__gptrput");
7590 if (SPEC_BLEN (etype) <= 8)
7593 emitcode ("inc", "%s", rname);
7594 rLen = SPEC_BLEN (etype);
7596 /* now generate for lengths greater than one byte */
7600 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7612 emitcode ("mov", "@%s,a", rname);
7615 emitcode ("mov", "@%s,%s", rname, l);
7620 emitcode ("movx", "@dptr,a");
7625 emitcode ("lcall", "__gptrput");
7628 emitcode ("inc", "%s", rname);
7633 /* last last was not complete */
7636 /* save the byte & read byte */
7640 emitcode ("mov", "b,a");
7641 emitcode ("mov", "a,@%s", rname);
7645 emitcode ("mov", "b,a");
7646 emitcode ("movx", "a,@dptr");
7650 emitcode ("push", "b");
7651 emitcode ("push", "acc");
7652 emitcode ("lcall", "__gptrget");
7653 emitcode ("pop", "b");
7657 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7658 emitcode ("orl", "a,b");
7661 if (p_type == GPOINTER)
7662 emitcode ("pop", "b");
7668 emitcode ("mov", "@%s,a", rname);
7672 emitcode ("movx", "@dptr,a");
7676 emitcode ("lcall", "__gptrput");
7680 /*-----------------------------------------------------------------*/
7681 /* genDataPointerSet - remat pointer to data space */
7682 /*-----------------------------------------------------------------*/
7684 genDataPointerSet (operand * right,
7688 int size, offset = 0;
7689 char *l, buffer[256];
7691 D(emitcode (";", "genDataPointerSet"));
7693 aopOp (right, ic, FALSE);
7695 l = aopGet (AOP (result), 0, FALSE, TRUE);
7696 size = AOP_SIZE (right);
7700 sprintf (buffer, "(%s + %d)", l + 1, offset);
7702 sprintf (buffer, "%s", l + 1);
7703 emitcode ("mov", "%s,%s", buffer,
7704 aopGet (AOP (right), offset++, FALSE, FALSE));
7707 freeAsmop (right, NULL, ic, TRUE);
7708 freeAsmop (result, NULL, ic, TRUE);
7711 /*-----------------------------------------------------------------*/
7712 /* genNearPointerSet - emitcode for near pointer put */
7713 /*-----------------------------------------------------------------*/
7715 genNearPointerSet (operand * right,
7723 sym_link *retype, *letype;
7724 sym_link *ptype = operandType (result);
7726 D(emitcode (";", "genNearPointerSet"));
7728 retype = getSpec (operandType (right));
7729 letype = getSpec (ptype);
7730 aopOp (result, ic, FALSE);
7732 /* if the result is rematerializable &
7733 in data space & not a bit variable */
7734 if (AOP_TYPE (result) == AOP_IMMD &&
7735 DCL_TYPE (ptype) == POINTER &&
7736 !IS_BITVAR (retype) &&
7737 !IS_BITVAR (letype))
7739 genDataPointerSet (right, result, ic);
7743 /* if the value is already in a pointer register
7744 then don't need anything more */
7745 if (!AOP_INPREG (AOP (result)))
7748 //AOP_TYPE (result) == AOP_STK
7752 // Aha, it is a pointer, just in disguise.
7753 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7756 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7757 __FILE__, __LINE__);
7762 rname++; // skip the '@'.
7767 /* otherwise get a free pointer register */
7769 preg = getFreePtr (ic, &aop, FALSE);
7770 emitcode ("mov", "%s,%s",
7772 aopGet (AOP (result), 0, FALSE, TRUE));
7778 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7781 aopOp (right, ic, FALSE);
7783 /* if bitfield then unpack the bits */
7784 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7785 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7788 /* we have can just get the values */
7789 int size = AOP_SIZE (right);
7794 l = aopGet (AOP (right), offset, FALSE, TRUE);
7798 emitcode ("mov", "@%s,a", rname);
7801 emitcode ("mov", "@%s,%s", rname, l);
7803 emitcode ("inc", "%s", rname);
7808 /* now some housekeeping stuff */
7809 if (aop) /* we had to allocate for this iCode */
7811 if (pi) aopPut (AOP (result),rname,0);
7812 freeAsmop (NULL, aop, ic, TRUE);
7816 /* we did not allocate which means left
7817 already in a pointer register, then
7818 if size > 0 && this could be used again
7819 we have to point it back to where it
7821 if ((AOP_SIZE (right) > 1 &&
7822 !OP_SYMBOL (result)->remat &&
7823 (OP_SYMBOL (result)->liveTo > ic->seq ||
7827 int size = AOP_SIZE (right) - 1;
7829 emitcode ("dec", "%s", rname);
7834 if (pi) pi->generated = 1;
7835 freeAsmop (result, NULL, ic, TRUE);
7836 freeAsmop (right, NULL, ic, TRUE);
7839 /*-----------------------------------------------------------------*/
7840 /* genPagedPointerSet - emitcode for Paged pointer put */
7841 /*-----------------------------------------------------------------*/
7843 genPagedPointerSet (operand * right,
7851 sym_link *retype, *letype;
7853 D(emitcode (";", "genPagedPointerSet"));
7855 retype = getSpec (operandType (right));
7856 letype = getSpec (operandType (result));
7858 aopOp (result, ic, FALSE);
7860 /* if the value is already in a pointer register
7861 then don't need anything more */
7862 if (!AOP_INPREG (AOP (result)))
7864 /* otherwise get a free pointer register */
7866 preg = getFreePtr (ic, &aop, FALSE);
7867 emitcode ("mov", "%s,%s",
7869 aopGet (AOP (result), 0, FALSE, TRUE));
7873 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7875 aopOp (right, ic, FALSE);
7877 /* if bitfield then unpack the bits */
7878 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7879 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7882 /* we have can just get the values */
7883 int size = AOP_SIZE (right);
7888 l = aopGet (AOP (right), offset, FALSE, TRUE);
7891 emitcode ("movx", "@%s,a", rname);
7894 emitcode ("inc", "%s", rname);
7900 /* now some housekeeping stuff */
7901 if (aop) /* we had to allocate for this iCode */
7903 if (pi) aopPut (AOP (result),rname,0);
7904 freeAsmop (NULL, aop, ic, TRUE);
7908 /* we did not allocate which means left
7909 already in a pointer register, then
7910 if size > 0 && this could be used again
7911 we have to point it back to where it
7913 if (AOP_SIZE (right) > 1 &&
7914 !OP_SYMBOL (result)->remat &&
7915 (OP_SYMBOL (result)->liveTo > ic->seq ||
7918 int size = AOP_SIZE (right) - 1;
7920 emitcode ("dec", "%s", rname);
7925 if (pi) pi->generated = 1;
7926 freeAsmop (result, NULL, ic, TRUE);
7927 freeAsmop (right, NULL, ic, TRUE);
7932 /*-----------------------------------------------------------------*/
7933 /* genFarPointerSet - set value from far space */
7934 /*-----------------------------------------------------------------*/
7936 genFarPointerSet (operand * right,
7937 operand * result, iCode * ic, iCode * pi)
7940 sym_link *retype = getSpec (operandType (right));
7941 sym_link *letype = getSpec (operandType (result));
7943 D(emitcode (";", "genFarPointerSet"));
7945 aopOp (result, ic, FALSE);
7947 /* if the operand is already in dptr
7948 then we do nothing else we move the value to dptr */
7949 if (AOP_TYPE (result) != AOP_STR)
7951 /* if this is remateriazable */
7952 if (AOP_TYPE (result) == AOP_IMMD)
7953 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7955 { /* we need to get it byte by byte */
7956 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7957 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7960 /* so dptr know contains the address */
7961 aopOp (right, ic, FALSE);
7963 /* if bit then unpack */
7964 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7965 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7968 size = AOP_SIZE (right);
7973 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7975 emitcode ("movx", "@dptr,a");
7977 emitcode ("inc", "dptr");
7980 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7981 aopPut (AOP(result),"dpl",0);
7982 aopPut (AOP(result),"dph",1);
7985 freeAsmop (result, NULL, ic, TRUE);
7986 freeAsmop (right, NULL, ic, TRUE);
7989 /*-----------------------------------------------------------------*/
7990 /* genGenPointerSet - set value from generic pointer space */
7991 /*-----------------------------------------------------------------*/
7993 genGenPointerSet (operand * right,
7994 operand * result, iCode * ic, iCode * pi)
7997 sym_link *retype = getSpec (operandType (right));
7998 sym_link *letype = getSpec (operandType (result));
8000 D(emitcode (";", "genGenPointerSet"));
8002 aopOp (result, ic, FALSE);
8004 /* if the operand is already in dptr
8005 then we do nothing else we move the value to dptr */
8006 if (AOP_TYPE (result) != AOP_STR)
8008 /* if this is remateriazable */
8009 if (AOP_TYPE (result) == AOP_IMMD)
8011 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8012 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8013 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8015 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8018 { /* we need to get it byte by byte */
8019 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8020 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8021 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8024 /* so dptr know contains the address */
8025 aopOp (right, ic, FALSE);
8027 /* if bit then unpack */
8028 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8029 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8032 size = AOP_SIZE (right);
8037 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8039 emitcode ("lcall", "__gptrput");
8041 emitcode ("inc", "dptr");
8045 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8046 aopPut (AOP(result),"dpl",0);
8047 aopPut (AOP(result),"dph",1);
8048 aopPut (AOP(result),"b",2);
8051 freeAsmop (result, NULL, ic, TRUE);
8052 freeAsmop (right, NULL, ic, TRUE);
8055 /*-----------------------------------------------------------------*/
8056 /* genPointerSet - stores the value into a pointer location */
8057 /*-----------------------------------------------------------------*/
8059 genPointerSet (iCode * ic, iCode *pi)
8061 operand *right, *result;
8062 sym_link *type, *etype;
8065 D(emitcode (";", "genPointerSet"));
8067 right = IC_RIGHT (ic);
8068 result = IC_RESULT (ic);
8070 /* depending on the type of pointer we need to
8071 move it to the correct pointer register */
8072 type = operandType (result);
8073 etype = getSpec (type);
8074 /* if left is of type of pointer then it is simple */
8075 if (IS_PTR (type) && !IS_FUNC (type->next))
8077 p_type = DCL_TYPE (type);
8081 /* we have to go by the storage class */
8082 p_type = PTR_TYPE (SPEC_OCLS (etype));
8085 /* special case when cast remat */
8086 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8087 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8088 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8089 type = type = operandType (result);
8090 p_type = DCL_TYPE (type);
8092 /* now that we have the pointer type we assign
8093 the pointer values */
8099 genNearPointerSet (right, result, ic, pi);
8103 genPagedPointerSet (right, result, ic, pi);
8107 genFarPointerSet (right, result, ic, pi);
8111 genGenPointerSet (right, result, ic, pi);
8117 /*-----------------------------------------------------------------*/
8118 /* genIfx - generate code for Ifx statement */
8119 /*-----------------------------------------------------------------*/
8121 genIfx (iCode * ic, iCode * popIc)
8123 operand *cond = IC_COND (ic);
8126 D(emitcode (";", "genIfx"));
8128 aopOp (cond, ic, FALSE);
8130 /* get the value into acc */
8131 if (AOP_TYPE (cond) != AOP_CRY)
8135 /* the result is now in the accumulator */
8136 freeAsmop (cond, NULL, ic, TRUE);
8138 /* if there was something to be popped then do it */
8142 /* if the condition is a bit variable */
8143 if (isbit && IS_ITEMP (cond) &&
8145 genIfxJump (ic, SPIL_LOC (cond)->rname);
8146 else if (isbit && !IS_ITEMP (cond))
8147 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8149 genIfxJump (ic, "a");
8154 /*-----------------------------------------------------------------*/
8155 /* genAddrOf - generates code for address of */
8156 /*-----------------------------------------------------------------*/
8158 genAddrOf (iCode * ic)
8160 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8163 D(emitcode (";", "genAddrOf"));
8165 aopOp (IC_RESULT (ic), ic, FALSE);
8167 /* if the operand is on the stack then we
8168 need to get the stack offset of this
8172 /* if it has an offset then we need to compute
8176 emitcode ("mov", "a,_bp");
8177 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8178 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8182 /* we can just move _bp */
8183 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8185 /* fill the result with zero */
8186 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8191 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8197 /* object not on stack then we need the name */
8198 size = AOP_SIZE (IC_RESULT (ic));
8203 char s[SDCC_NAME_MAX];
8205 sprintf (s, "#(%s >> %d)",
8209 sprintf (s, "#%s", sym->rname);
8210 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8214 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8218 /*-----------------------------------------------------------------*/
8219 /* genFarFarAssign - assignment when both are in far space */
8220 /*-----------------------------------------------------------------*/
8222 genFarFarAssign (operand * result, operand * right, iCode * ic)
8224 int size = AOP_SIZE (right);
8228 D(emitcode (";", "genFarFarAssign"));
8230 /* first push the right side on to the stack */
8233 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8235 emitcode ("push", "acc");
8238 freeAsmop (right, NULL, ic, FALSE);
8239 /* now assign DPTR to result */
8240 aopOp (result, ic, FALSE);
8241 size = AOP_SIZE (result);
8244 emitcode ("pop", "acc");
8245 aopPut (AOP (result), "a", --offset);
8247 freeAsmop (result, NULL, ic, FALSE);
8251 /*-----------------------------------------------------------------*/
8252 /* genAssign - generate code for assignment */
8253 /*-----------------------------------------------------------------*/
8255 genAssign (iCode * ic)
8257 operand *result, *right;
8259 unsigned long lit = 0L;
8261 D(emitcode(";","genAssign"));
8263 result = IC_RESULT (ic);
8264 right = IC_RIGHT (ic);
8266 /* if they are the same */
8267 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8270 aopOp (right, ic, FALSE);
8272 /* special case both in far space */
8273 if (AOP_TYPE (right) == AOP_DPTR &&
8274 IS_TRUE_SYMOP (result) &&
8275 isOperandInFarSpace (result))
8278 genFarFarAssign (result, right, ic);
8282 aopOp (result, ic, TRUE);
8284 /* if they are the same registers */
8285 if (sameRegs (AOP (right), AOP (result)))
8288 /* if the result is a bit */
8289 if (AOP_TYPE (result) == AOP_CRY)
8292 /* if the right size is a literal then
8293 we know what the value is */
8294 if (AOP_TYPE (right) == AOP_LIT)
8296 if (((int) operandLitValue (right)))
8297 aopPut (AOP (result), one, 0);
8299 aopPut (AOP (result), zero, 0);
8303 /* the right is also a bit variable */
8304 if (AOP_TYPE (right) == AOP_CRY)
8306 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8307 aopPut (AOP (result), "c", 0);
8313 aopPut (AOP (result), "a", 0);
8317 /* bit variables done */
8319 size = AOP_SIZE (result);
8321 if (AOP_TYPE (right) == AOP_LIT)
8322 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8324 (AOP_TYPE (result) != AOP_REG) &&
8325 (AOP_TYPE (right) == AOP_LIT) &&
8326 !IS_FLOAT (operandType (right)) &&
8329 emitcode ("clr", "a");
8332 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8333 aopPut (AOP (result), "a", size);
8335 aopPut (AOP (result),
8336 aopGet (AOP (right), size, FALSE, FALSE),
8344 aopPut (AOP (result),
8345 aopGet (AOP (right), offset, FALSE, FALSE),
8352 freeAsmop (right, NULL, ic, TRUE);
8353 freeAsmop (result, NULL, ic, TRUE);
8356 /*-----------------------------------------------------------------*/
8357 /* genJumpTab - genrates code for jump table */
8358 /*-----------------------------------------------------------------*/
8360 genJumpTab (iCode * ic)
8365 D(emitcode (";", "genJumpTab"));
8367 aopOp (IC_JTCOND (ic), ic, FALSE);
8368 /* get the condition into accumulator */
8369 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8371 /* multiply by three */
8372 emitcode ("add", "a,acc");
8373 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8374 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8376 jtab = newiTempLabel (NULL);
8377 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8378 emitcode ("jmp", "@a+dptr");
8379 emitcode ("", "%05d$:", jtab->key + 100);
8380 /* now generate the jump labels */
8381 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8382 jtab = setNextItem (IC_JTLABELS (ic)))
8383 emitcode ("ljmp", "%05d$", jtab->key + 100);
8387 /*-----------------------------------------------------------------*/
8388 /* genCast - gen code for casting */
8389 /*-----------------------------------------------------------------*/
8391 genCast (iCode * ic)
8393 operand *result = IC_RESULT (ic);
8394 sym_link *ctype = operandType (IC_LEFT (ic));
8395 sym_link *rtype = operandType (IC_RIGHT (ic));
8396 operand *right = IC_RIGHT (ic);
8399 D(emitcode(";", "genCast"));
8401 /* if they are equivalent then do nothing */
8402 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8405 aopOp (right, ic, FALSE);
8406 aopOp (result, ic, FALSE);
8408 /* if the result is a bit */
8409 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8410 if (IS_BITVAR(OP_SYMBOL(result)->type))
8412 /* if the right size is a literal then
8413 we know what the value is */
8414 if (AOP_TYPE (right) == AOP_LIT)
8416 if (((int) operandLitValue (right)))
8417 aopPut (AOP (result), one, 0);
8419 aopPut (AOP (result), zero, 0);
8424 /* the right is also a bit variable */
8425 if (AOP_TYPE (right) == AOP_CRY)
8427 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8428 aopPut (AOP (result), "c", 0);
8434 aopPut (AOP (result), "a", 0);
8438 /* if they are the same size : or less */
8439 if (AOP_SIZE (result) <= AOP_SIZE (right))
8442 /* if they are in the same place */
8443 if (sameRegs (AOP (right), AOP (result)))
8446 /* if they in different places then copy */
8447 size = AOP_SIZE (result);
8451 aopPut (AOP (result),
8452 aopGet (AOP (right), offset, FALSE, FALSE),
8460 /* if the result is of type pointer */
8465 sym_link *type = operandType (right);
8466 sym_link *etype = getSpec (type);
8468 /* pointer to generic pointer */
8469 if (IS_GENPTR (ctype))
8474 p_type = DCL_TYPE (type);
8477 if (SPEC_SCLS(etype)==S_REGISTER) {
8478 // let's assume it is a generic pointer
8481 /* we have to go by the storage class */
8482 p_type = PTR_TYPE (SPEC_OCLS (etype));
8486 /* the first two bytes are known */
8487 size = GPTRSIZE - 1;
8491 aopPut (AOP (result),
8492 aopGet (AOP (right), offset, FALSE, FALSE),
8496 /* the last byte depending on type */
8512 case PPOINTER: // what the fck is this?
8517 /* this should never happen */
8518 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8519 "got unknown pointer type");
8522 aopPut (AOP (result), l, GPTRSIZE - 1);
8526 /* just copy the pointers */
8527 size = AOP_SIZE (result);
8531 aopPut (AOP (result),
8532 aopGet (AOP (right), offset, FALSE, FALSE),
8539 /* so we now know that the size of destination is greater
8540 than the size of the source */
8541 /* we move to result for the size of source */
8542 size = AOP_SIZE (right);
8546 aopPut (AOP (result),
8547 aopGet (AOP (right), offset, FALSE, FALSE),
8552 /* now depending on the sign of the source && destination */
8553 size = AOP_SIZE (result) - AOP_SIZE (right);
8554 /* if unsigned or not an integral type */
8555 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8558 aopPut (AOP (result), zero, offset++);
8562 /* we need to extend the sign :{ */
8563 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8566 emitcode ("rlc", "a");
8567 emitcode ("subb", "a,acc");
8569 aopPut (AOP (result), "a", offset++);
8572 /* we are done hurray !!!! */
8575 freeAsmop (right, NULL, ic, TRUE);
8576 freeAsmop (result, NULL, ic, TRUE);
8580 /*-----------------------------------------------------------------*/
8581 /* genDjnz - generate decrement & jump if not zero instrucion */
8582 /*-----------------------------------------------------------------*/
8584 genDjnz (iCode * ic, iCode * ifx)
8590 D(emitcode (";", "genDjnz"));
8592 /* if the if condition has a false label
8593 then we cannot save */
8597 /* if the minus is not of the form
8599 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8600 !IS_OP_LITERAL (IC_RIGHT (ic)))
8603 if (operandLitValue (IC_RIGHT (ic)) != 1)
8606 /* if the size of this greater than one then no
8608 if (getSize (operandType (IC_RESULT (ic))) > 1)
8611 /* otherwise we can save BIG */
8612 lbl = newiTempLabel (NULL);
8613 lbl1 = newiTempLabel (NULL);
8615 aopOp (IC_RESULT (ic), ic, FALSE);
8617 if (AOP_NEEDSACC(IC_RESULT(ic)))
8619 /* If the result is accessed indirectly via
8620 * the accumulator, we must explicitly write
8621 * it back after the decrement.
8623 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8625 if (strcmp(rByte, "a"))
8627 /* Something is hopelessly wrong */
8628 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8629 __FILE__, __LINE__);
8630 /* We can just give up; the generated code will be inefficient,
8633 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8636 emitcode ("dec", "%s", rByte);
8637 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8638 emitcode ("jnz", "%05d$", lbl->key + 100);
8640 else if (IS_AOP_PREG (IC_RESULT (ic)))
8642 emitcode ("dec", "%s",
8643 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8644 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8645 emitcode ("jnz", "%05d$", lbl->key + 100);
8649 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8652 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8653 emitcode ("", "%05d$:", lbl->key + 100);
8654 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8655 emitcode ("", "%05d$:", lbl1->key + 100);
8657 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8662 /*-----------------------------------------------------------------*/
8663 /* genReceive - generate code for a receive iCode */
8664 /*-----------------------------------------------------------------*/
8666 genReceive (iCode * ic)
8668 D(emitcode (";", "genReceive"));
8670 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8671 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8672 IS_TRUE_SYMOP (IC_RESULT (ic))))
8675 int size = getSize (operandType (IC_RESULT (ic)));
8676 int offset = fReturnSizeMCS51 - size;
8679 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8680 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8683 aopOp (IC_RESULT (ic), ic, FALSE);
8684 size = AOP_SIZE (IC_RESULT (ic));
8688 emitcode ("pop", "acc");
8689 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8696 aopOp (IC_RESULT (ic), ic, FALSE);
8698 assignResultValue (IC_RESULT (ic));
8701 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8704 /*-----------------------------------------------------------------*/
8705 /* gen51AggregateAssign - copy complete array's or structures */
8706 /*-----------------------------------------------------------------*/
8707 void gen51AggregateAssign(iCode *ic) {
8708 operand *left=IC_LEFT(ic);
8709 operand *right=IC_RIGHT(ic);
8710 char *fromName=OP_SYMBOL(right)->rname;
8711 char *toName=OP_SYMBOL(left)->rname;
8712 int fromSize=getSize(OP_SYMBOL(right)->type);
8713 int toSize=getSize(OP_SYMBOL(left)->type);
8716 D(emitcode (";", "gen51AggregateAssign"));
8718 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8719 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8720 // well, this code isn't used yet from anywhere else as for initialising
8721 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8725 if (fromSize!=toSize) {
8726 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8727 ic->filename, ic->lineno);
8732 // use the generic memcpy() for now
8733 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8734 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8735 emitcode ("mov", "a,#%s", fromName);
8736 emitcode ("movx", "@dptr,a");
8737 emitcode ("inc", "dptr");
8738 emitcode ("mov", "a,#(%s>>8)", fromName);
8739 emitcode ("movx", "@dptr,a");
8740 emitcode ("inc", "dptr");
8741 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8742 emitcode ("movx", "@dptr,a");
8743 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8744 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8745 emitcode ("movx", "@dptr,a");
8746 emitcode ("inc", "dptr");
8747 emitcode ("mov", "a,#(%d>>8)", count);
8748 emitcode ("movx", "@dptr,a");
8749 emitcode ("mov", "dptr,#%s", toName);
8750 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8751 emitcode ("lcall", "_memcpy");
8753 // more efficient, but will require the native_memcpy_cs2xs
8754 emitcode ("mov", "r0,#%s", fromName);
8755 emitcode ("mov", "r1,#(%s>>8)", fromName);
8756 emitcode ("mov", "r2,#%s", toName);
8757 emitcode ("mov", "r3,#(%s>>8)", toName);
8758 emitcode ("mov", "r4,#%d", count);
8759 emitcode ("mov", "r5,#(%d>>8)", count);
8760 emitcode ("lcall", "_native_memcpy_cs2xs");
8764 /*-----------------------------------------------------------------*/
8765 /* gen51Code - generate code for 8051 based controllers */
8766 /*-----------------------------------------------------------------*/
8768 gen51Code (iCode * lic)
8773 lineHead = lineCurr = NULL;
8775 /* print the allocation information */
8777 printAllocInfo (currFunc, codeOutFile);
8778 /* if debug information required */
8779 /* if (options.debug && currFunc) { */
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));
8974 if (POINTER_SET (ic))
8975 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
9001 addSet (&_G.sendSet, ic);
9005 gen51AggregateAssign(ic);
9014 /* now we are ready to call the
9015 peep hole optimizer */
9016 if (!options.nopeep)
9017 peepHole (&lineHead);
9019 /* now do the actual printing */
9020 printLine (lineHead, codeOutFile);