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 /* if we have no return value then
2630 just generate the "ret" */
2634 /* we have something to return then
2635 move the return value into place */
2636 aopOp (IC_LEFT (ic), ic, FALSE);
2637 size = AOP_SIZE (IC_LEFT (ic));
2642 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2645 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2647 emitcode ("push", "%s", l);
2652 l = aopGet (AOP (IC_LEFT (ic)), offset,
2654 if (strcmp (fReturn[offset], l))
2655 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2664 if (strcmp (fReturn[pushed], "a"))
2665 emitcode ("pop", fReturn[pushed]);
2667 emitcode ("pop", "acc");
2670 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2673 /* generate a jump to the return label
2674 if the next is not the return statement */
2675 if (!(ic->next && ic->next->op == LABEL &&
2676 IC_LABEL (ic->next) == returnLabel))
2678 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2682 /*-----------------------------------------------------------------*/
2683 /* genLabel - generates a label */
2684 /*-----------------------------------------------------------------*/
2686 genLabel (iCode * ic)
2688 /* special case never generate */
2689 if (IC_LABEL (ic) == entryLabel)
2692 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2695 /*-----------------------------------------------------------------*/
2696 /* genGoto - generates a ljmp */
2697 /*-----------------------------------------------------------------*/
2699 genGoto (iCode * ic)
2701 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2704 /*-----------------------------------------------------------------*/
2705 /* findLabelBackwards: walks back through the iCode chain looking */
2706 /* for the given label. Returns number of iCode instructions */
2707 /* between that label and given ic. */
2708 /* Returns zero if label not found. */
2709 /*-----------------------------------------------------------------*/
2711 findLabelBackwards (iCode * ic, int key)
2720 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2722 /* printf("findLabelBackwards = %d\n", count); */
2730 /*-----------------------------------------------------------------*/
2731 /* genPlusIncr :- does addition with increment if possible */
2732 /*-----------------------------------------------------------------*/
2734 genPlusIncr (iCode * ic)
2736 unsigned int icount;
2737 unsigned int size = getDataSize (IC_RESULT (ic));
2739 /* will try to generate an increment */
2740 /* if the right side is not a literal
2742 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2745 /* if the literal value of the right hand side
2746 is greater than 4 then it is not worth it */
2747 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2750 D(emitcode (";", "genPlusIncr"));
2752 /* if increment 16 bits in register */
2753 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2761 /* If the next instruction is a goto and the goto target
2762 * is < 10 instructions previous to this, we can generate
2763 * jumps straight to that target.
2765 if (ic->next && ic->next->op == GOTO
2766 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2767 && labelRange <= 10)
2769 emitcode (";", "tail increment optimized");
2770 tlbl = IC_LABEL (ic->next);
2775 tlbl = newiTempLabel (NULL);
2778 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2779 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2780 IS_AOP_PREG (IC_RESULT (ic)))
2781 emitcode ("cjne", "%s,#0x00,%05d$"
2782 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2786 emitcode ("clr", "a");
2787 emitcode ("cjne", "a,%s,%05d$"
2788 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2792 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2795 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2796 IS_AOP_PREG (IC_RESULT (ic)))
2797 emitcode ("cjne", "%s,#0x00,%05d$"
2798 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2801 emitcode ("cjne", "a,%s,%05d$"
2802 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2805 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2809 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2810 IS_AOP_PREG (IC_RESULT (ic)))
2811 emitcode ("cjne", "%s,#0x00,%05d$"
2812 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2816 emitcode ("cjne", "a,%s,%05d$"
2817 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2820 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2825 emitcode ("", "%05d$:", tlbl->key + 100);
2830 /* if the sizes are greater than 1 then we cannot */
2831 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2832 AOP_SIZE (IC_LEFT (ic)) > 1)
2835 /* we can if the aops of the left & result match or
2836 if they are in registers and the registers are the
2838 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2843 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2844 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2845 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2851 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2860 /*-----------------------------------------------------------------*/
2861 /* outBitAcc - output a bit in acc */
2862 /*-----------------------------------------------------------------*/
2864 outBitAcc (operand * result)
2866 symbol *tlbl = newiTempLabel (NULL);
2867 /* if the result is a bit */
2868 if (AOP_TYPE (result) == AOP_CRY)
2870 aopPut (AOP (result), "a", 0);
2874 emitcode ("jz", "%05d$", tlbl->key + 100);
2875 emitcode ("mov", "a,%s", one);
2876 emitcode ("", "%05d$:", tlbl->key + 100);
2881 /*-----------------------------------------------------------------*/
2882 /* genPlusBits - generates code for addition of two bits */
2883 /*-----------------------------------------------------------------*/
2885 genPlusBits (iCode * ic)
2887 D(emitcode (";", "genPlusBits"));
2889 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2891 symbol *lbl = newiTempLabel (NULL);
2892 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2893 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2894 emitcode ("cpl", "c");
2895 emitcode ("", "%05d$:", (lbl->key + 100));
2896 outBitC (IC_RESULT (ic));
2900 emitcode ("clr", "a");
2901 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2902 emitcode ("rlc", "a");
2903 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2904 emitcode ("addc", "a,#0x00");
2905 outAcc (IC_RESULT (ic));
2910 /* This is the original version of this code.
2912 * This is being kept around for reference,
2913 * because I am not entirely sure I got it right...
2916 adjustArithmeticResult (iCode * ic)
2918 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2919 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2920 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2921 aopPut (AOP (IC_RESULT (ic)),
2922 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2925 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2926 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2927 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2928 aopPut (AOP (IC_RESULT (ic)),
2929 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2932 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2933 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2934 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2935 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2936 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2939 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2940 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2944 /* This is the pure and virtuous version of this code.
2945 * I'm pretty certain it's right, but not enough to toss the old
2949 adjustArithmeticResult (iCode * ic)
2951 if (opIsGptr (IC_RESULT (ic)) &&
2952 opIsGptr (IC_LEFT (ic)) &&
2953 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2955 aopPut (AOP (IC_RESULT (ic)),
2956 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2960 if (opIsGptr (IC_RESULT (ic)) &&
2961 opIsGptr (IC_RIGHT (ic)) &&
2962 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2964 aopPut (AOP (IC_RESULT (ic)),
2965 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2969 if (opIsGptr (IC_RESULT (ic)) &&
2970 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2971 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2972 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2973 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2976 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2977 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2982 /*-----------------------------------------------------------------*/
2983 /* genPlus - generates code for addition */
2984 /*-----------------------------------------------------------------*/
2986 genPlus (iCode * ic)
2988 int size, offset = 0;
2990 /* special cases :- */
2992 D(emitcode (";", "genPlus"));
2994 aopOp (IC_LEFT (ic), ic, FALSE);
2995 aopOp (IC_RIGHT (ic), ic, FALSE);
2996 aopOp (IC_RESULT (ic), ic, TRUE);
2998 /* if literal, literal on the right or
2999 if left requires ACC or right is already
3001 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3002 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3003 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3005 operand *t = IC_RIGHT (ic);
3006 IC_RIGHT (ic) = IC_LEFT (ic);
3010 /* if both left & right are in bit
3012 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3013 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3019 /* if left in bit space & right literal */
3020 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3021 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3023 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3024 /* if result in bit space */
3025 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3027 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3028 emitcode ("cpl", "c");
3029 outBitC (IC_RESULT (ic));
3033 size = getDataSize (IC_RESULT (ic));
3036 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3037 emitcode ("addc", "a,#00");
3038 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3044 /* if I can do an increment instead
3045 of add then GOOD for ME */
3046 if (genPlusIncr (ic) == TRUE)
3049 size = getDataSize (IC_RESULT (ic));
3053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3055 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3057 emitcode ("add", "a,%s",
3058 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3060 emitcode ("addc", "a,%s",
3061 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3065 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3067 emitcode ("add", "a,%s",
3068 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3070 emitcode ("addc", "a,%s",
3071 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3073 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3076 adjustArithmeticResult (ic);
3079 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3080 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3081 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3084 /*-----------------------------------------------------------------*/
3085 /* genMinusDec :- does subtraction with deccrement if possible */
3086 /*-----------------------------------------------------------------*/
3088 genMinusDec (iCode * ic)
3090 unsigned int icount;
3091 unsigned int size = getDataSize (IC_RESULT (ic));
3093 /* will try to generate an increment */
3094 /* if the right side is not a literal
3096 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3099 /* if the literal value of the right hand side
3100 is greater than 4 then it is not worth it */
3101 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3104 D(emitcode (";", "genMinusDec"));
3106 /* if decrement 16 bits in register */
3107 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3115 /* If the next instruction is a goto and the goto target
3116 * is <= 10 instructions previous to this, we can generate
3117 * jumps straight to that target.
3119 if (ic->next && ic->next->op == GOTO
3120 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3121 && labelRange <= 10)
3123 emitcode (";", "tail decrement optimized");
3124 tlbl = IC_LABEL (ic->next);
3129 tlbl = newiTempLabel (NULL);
3133 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3134 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3135 IS_AOP_PREG (IC_RESULT (ic)))
3136 emitcode ("cjne", "%s,#0xff,%05d$"
3137 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3141 emitcode ("mov", "a,#0xff");
3142 emitcode ("cjne", "a,%s,%05d$"
3143 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3146 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3149 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3150 IS_AOP_PREG (IC_RESULT (ic)))
3151 emitcode ("cjne", "%s,#0xff,%05d$"
3152 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3156 emitcode ("cjne", "a,%s,%05d$"
3157 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3160 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3164 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3165 IS_AOP_PREG (IC_RESULT (ic)))
3166 emitcode ("cjne", "%s,#0xff,%05d$"
3167 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3171 emitcode ("cjne", "a,%s,%05d$"
3172 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3175 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3179 emitcode ("", "%05d$:", tlbl->key + 100);
3184 /* if the sizes are greater than 1 then we cannot */
3185 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3186 AOP_SIZE (IC_LEFT (ic)) > 1)
3189 /* we can if the aops of the left & result match or
3190 if they are in registers and the registers are the
3192 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3196 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3204 /*-----------------------------------------------------------------*/
3205 /* addSign - complete with sign */
3206 /*-----------------------------------------------------------------*/
3208 addSign (operand * result, int offset, int sign)
3210 int size = (getDataSize (result) - offset);
3215 emitcode ("rlc", "a");
3216 emitcode ("subb", "a,acc");
3218 aopPut (AOP (result), "a", offset++);
3222 aopPut (AOP (result), zero, offset++);
3226 /*-----------------------------------------------------------------*/
3227 /* genMinusBits - generates code for subtraction of two bits */
3228 /*-----------------------------------------------------------------*/
3230 genMinusBits (iCode * ic)
3232 symbol *lbl = newiTempLabel (NULL);
3234 D(emitcode (";", "genMinusBits"));
3236 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3238 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3239 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3240 emitcode ("cpl", "c");
3241 emitcode ("", "%05d$:", (lbl->key + 100));
3242 outBitC (IC_RESULT (ic));
3246 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3247 emitcode ("subb", "a,acc");
3248 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3249 emitcode ("inc", "a");
3250 emitcode ("", "%05d$:", (lbl->key + 100));
3251 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3252 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3256 /*-----------------------------------------------------------------*/
3257 /* genMinus - generates code for subtraction */
3258 /*-----------------------------------------------------------------*/
3260 genMinus (iCode * ic)
3262 int size, offset = 0;
3263 unsigned long lit = 0L;
3265 D(emitcode (";", "genMinus"));
3267 aopOp (IC_LEFT (ic), ic, FALSE);
3268 aopOp (IC_RIGHT (ic), ic, FALSE);
3269 aopOp (IC_RESULT (ic), ic, TRUE);
3271 /* special cases :- */
3272 /* if both left & right are in bit space */
3273 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3274 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3280 /* if I can do an decrement instead
3281 of subtract then GOOD for ME */
3282 if (genMinusDec (ic) == TRUE)
3285 size = getDataSize (IC_RESULT (ic));
3287 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3293 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3297 /* if literal, add a,#-lit, else normal subb */
3300 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3301 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3302 emitcode ("subb", "a,%s",
3303 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3306 /* first add without previous c */
3308 if (!size && lit==-1) {
3309 emitcode ("dec", "a");
3311 emitcode ("add", "a,#0x%02x",
3312 (unsigned int) (lit & 0x0FFL));
3315 emitcode ("addc", "a,#0x%02x",
3316 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3319 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3322 adjustArithmeticResult (ic);
3325 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3326 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3327 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3331 /*-----------------------------------------------------------------*/
3332 /* genMultbits :- multiplication of bits */
3333 /*-----------------------------------------------------------------*/
3335 genMultbits (operand * left,
3339 D(emitcode (";", "genMultbits"));
3341 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3342 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3347 /*-----------------------------------------------------------------*/
3348 /* genMultOneByte : 8*8=8/16 bit multiplication */
3349 /*-----------------------------------------------------------------*/
3351 genMultOneByte (operand * left,
3355 sym_link *opetype = operandType (result);
3357 int size=AOP_SIZE(result);
3359 D(emitcode (";", "genMultOneByte"));
3361 if (size<1 || size>2) {
3362 // this should never happen
3363 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3364 AOP_SIZE(result), __FILE__, lineno);
3368 /* (if two literals: the value is computed before) */
3369 /* if one literal, literal on the right */
3370 if (AOP_TYPE (left) == AOP_LIT)
3375 //emitcode (";", "swapped left and right");
3378 if (SPEC_USIGN(opetype)
3379 // ignore the sign of left and right, what else can we do?
3380 || (SPEC_USIGN(operandType(left)) &&
3381 SPEC_USIGN(operandType(right)))) {
3382 // just an unsigned 8*8=8/16 multiply
3383 //emitcode (";","unsigned");
3384 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3385 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3386 emitcode ("mul", "ab");
3387 aopPut (AOP (result), "a", 0);
3389 aopPut (AOP (result), "b", 1);
3394 // we have to do a signed multiply
3396 //emitcode (";", "signed");
3397 emitcode ("clr", "F0"); // reset sign flag
3398 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3400 lbl=newiTempLabel(NULL);
3401 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3402 // left side is negative, 8-bit two's complement, this fails for -128
3403 emitcode ("setb", "F0"); // set sign flag
3404 emitcode ("cpl", "a");
3405 emitcode ("inc", "a");
3407 emitcode ("", "%05d$:", lbl->key+100);
3410 if (AOP_TYPE(right)==AOP_LIT) {
3411 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3412 /* AND literal negative */
3414 emitcode ("cpl", "F0"); // complement sign flag
3415 emitcode ("mov", "b,#0x%02x", -val);
3417 emitcode ("mov", "b,#0x%02x", val);
3420 lbl=newiTempLabel(NULL);
3421 emitcode ("mov", "b,a");
3422 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3423 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3424 // right side is negative, 8-bit two's complement
3425 emitcode ("cpl", "F0"); // complement sign flag
3426 emitcode ("cpl", "a");
3427 emitcode ("inc", "a");
3428 emitcode ("", "%05d$:", lbl->key+100);
3430 emitcode ("mul", "ab");
3432 lbl=newiTempLabel(NULL);
3433 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3434 // only ONE op was negative, we have to do a 8/16-bit two's complement
3435 emitcode ("cpl", "a"); // lsb
3437 emitcode ("inc", "a");
3439 emitcode ("add", "a,#1");
3440 emitcode ("xch", "a,b");
3441 emitcode ("cpl", "a"); // msb
3442 emitcode ("addc", "a,#0");
3443 emitcode ("xch", "a,b");
3446 emitcode ("", "%05d$:", lbl->key+100);
3447 aopPut (AOP (result), "a", 0);
3449 aopPut (AOP (result), "b", 1);
3453 /*-----------------------------------------------------------------*/
3454 /* genMult - generates code for multiplication */
3455 /*-----------------------------------------------------------------*/
3457 genMult (iCode * ic)
3459 operand *left = IC_LEFT (ic);
3460 operand *right = IC_RIGHT (ic);
3461 operand *result = IC_RESULT (ic);
3463 D(emitcode (";", "genMult"));
3465 /* assign the amsops */
3466 aopOp (left, ic, FALSE);
3467 aopOp (right, ic, FALSE);
3468 aopOp (result, ic, TRUE);
3470 /* special cases first */
3472 if (AOP_TYPE (left) == AOP_CRY &&
3473 AOP_TYPE (right) == AOP_CRY)
3475 genMultbits (left, right, result);
3479 /* if both are of size == 1 */
3480 #if 0 // one of them can be a sloc shared with the result
3481 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3483 if (getSize(operandType(left)) == 1 &&
3484 getSize(operandType(right)) == 1)
3487 genMultOneByte (left, right, result);
3491 /* should have been converted to function call */
3492 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3493 getSize(OP_SYMBOL(right)->type));
3497 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3498 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3499 freeAsmop (result, NULL, ic, TRUE);
3502 /*-----------------------------------------------------------------*/
3503 /* genDivbits :- division of bits */
3504 /*-----------------------------------------------------------------*/
3506 genDivbits (operand * left,
3513 D(emitcode (";", "genDivbits"));
3515 /* the result must be bit */
3516 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3517 l = aopGet (AOP (left), 0, FALSE, FALSE);
3521 emitcode ("div", "ab");
3522 emitcode ("rrc", "a");
3523 aopPut (AOP (result), "c", 0);
3526 /*-----------------------------------------------------------------*/
3527 /* genDivOneByte : 8 bit division */
3528 /*-----------------------------------------------------------------*/
3530 genDivOneByte (operand * left,
3534 sym_link *opetype = operandType (result);
3539 D(emitcode (";", "genDivOneByte"));
3541 size = AOP_SIZE (result) - 1;
3543 /* signed or unsigned */
3544 if (SPEC_USIGN (opetype))
3546 /* unsigned is easy */
3547 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3548 l = aopGet (AOP (left), 0, FALSE, FALSE);
3550 emitcode ("div", "ab");
3551 aopPut (AOP (result), "a", 0);
3553 aopPut (AOP (result), zero, offset++);
3557 /* signed is a little bit more difficult */
3559 /* save the signs of the operands */
3560 l = aopGet (AOP (left), 0, FALSE, FALSE);
3562 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3563 emitcode ("push", "acc"); /* save it on the stack */
3565 /* now sign adjust for both left & right */
3566 l = aopGet (AOP (right), 0, FALSE, FALSE);
3568 lbl = newiTempLabel (NULL);
3569 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3570 emitcode ("cpl", "a");
3571 emitcode ("inc", "a");
3572 emitcode ("", "%05d$:", (lbl->key + 100));
3573 emitcode ("mov", "b,a");
3575 /* sign adjust left side */
3576 l = aopGet (AOP (left), 0, FALSE, FALSE);
3579 lbl = newiTempLabel (NULL);
3580 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3581 emitcode ("cpl", "a");
3582 emitcode ("inc", "a");
3583 emitcode ("", "%05d$:", (lbl->key + 100));
3585 /* now the division */
3586 emitcode ("div", "ab");
3587 /* we are interested in the lower order
3589 emitcode ("mov", "b,a");
3590 lbl = newiTempLabel (NULL);
3591 emitcode ("pop", "acc");
3592 /* if there was an over flow we don't
3593 adjust the sign of the result */
3594 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3595 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3597 emitcode ("clr", "a");
3598 emitcode ("subb", "a,b");
3599 emitcode ("mov", "b,a");
3600 emitcode ("", "%05d$:", (lbl->key + 100));
3602 /* now we are done */
3603 aopPut (AOP (result), "b", 0);
3606 emitcode ("mov", "c,b.7");
3607 emitcode ("subb", "a,acc");
3610 aopPut (AOP (result), "a", offset++);
3614 /*-----------------------------------------------------------------*/
3615 /* genDiv - generates code for division */
3616 /*-----------------------------------------------------------------*/
3620 operand *left = IC_LEFT (ic);
3621 operand *right = IC_RIGHT (ic);
3622 operand *result = IC_RESULT (ic);
3624 D(emitcode (";", "genDiv"));
3626 /* assign the amsops */
3627 aopOp (left, ic, FALSE);
3628 aopOp (right, ic, FALSE);
3629 aopOp (result, ic, TRUE);
3631 /* special cases first */
3633 if (AOP_TYPE (left) == AOP_CRY &&
3634 AOP_TYPE (right) == AOP_CRY)
3636 genDivbits (left, right, result);
3640 /* if both are of size == 1 */
3641 if (AOP_SIZE (left) == 1 &&
3642 AOP_SIZE (right) == 1)
3644 genDivOneByte (left, right, result);
3648 /* should have been converted to function call */
3651 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3652 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3653 freeAsmop (result, NULL, ic, TRUE);
3656 /*-----------------------------------------------------------------*/
3657 /* genModbits :- modulus of bits */
3658 /*-----------------------------------------------------------------*/
3660 genModbits (operand * left,
3667 D(emitcode (";", "genModbits"));
3669 /* the result must be bit */
3670 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3671 l = aopGet (AOP (left), 0, FALSE, FALSE);
3675 emitcode ("div", "ab");
3676 emitcode ("mov", "a,b");
3677 emitcode ("rrc", "a");
3678 aopPut (AOP (result), "c", 0);
3681 /*-----------------------------------------------------------------*/
3682 /* genModOneByte : 8 bit modulus */
3683 /*-----------------------------------------------------------------*/
3685 genModOneByte (operand * left,
3689 sym_link *opetype = operandType (result);
3693 D(emitcode (";", "genModOneByte"));
3695 /* signed or unsigned */
3696 if (SPEC_USIGN (opetype))
3698 /* unsigned is easy */
3699 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3700 l = aopGet (AOP (left), 0, FALSE, FALSE);
3702 emitcode ("div", "ab");
3703 aopPut (AOP (result), "b", 0);
3707 /* signed is a little bit more difficult */
3709 /* save the signs of the operands */
3710 l = aopGet (AOP (left), 0, FALSE, FALSE);
3713 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3714 emitcode ("push", "acc"); /* save it on the stack */
3716 /* now sign adjust for both left & right */
3717 l = aopGet (AOP (right), 0, FALSE, FALSE);
3720 lbl = newiTempLabel (NULL);
3721 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3722 emitcode ("cpl", "a");
3723 emitcode ("inc", "a");
3724 emitcode ("", "%05d$:", (lbl->key + 100));
3725 emitcode ("mov", "b,a");
3727 /* sign adjust left side */
3728 l = aopGet (AOP (left), 0, FALSE, FALSE);
3731 lbl = newiTempLabel (NULL);
3732 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3733 emitcode ("cpl", "a");
3734 emitcode ("inc", "a");
3735 emitcode ("", "%05d$:", (lbl->key + 100));
3737 /* now the multiplication */
3738 emitcode ("div", "ab");
3739 /* we are interested in the lower order
3741 lbl = newiTempLabel (NULL);
3742 emitcode ("pop", "acc");
3743 /* if there was an over flow we don't
3744 adjust the sign of the result */
3745 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3746 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3748 emitcode ("clr", "a");
3749 emitcode ("subb", "a,b");
3750 emitcode ("mov", "b,a");
3751 emitcode ("", "%05d$:", (lbl->key + 100));
3753 /* now we are done */
3754 aopPut (AOP (result), "b", 0);
3758 /*-----------------------------------------------------------------*/
3759 /* genMod - generates code for division */
3760 /*-----------------------------------------------------------------*/
3764 operand *left = IC_LEFT (ic);
3765 operand *right = IC_RIGHT (ic);
3766 operand *result = IC_RESULT (ic);
3768 D(emitcode (";", "genMod"));
3770 /* assign the amsops */
3771 aopOp (left, ic, FALSE);
3772 aopOp (right, ic, FALSE);
3773 aopOp (result, ic, TRUE);
3775 /* special cases first */
3777 if (AOP_TYPE (left) == AOP_CRY &&
3778 AOP_TYPE (right) == AOP_CRY)
3780 genModbits (left, right, result);
3784 /* if both are of size == 1 */
3785 if (AOP_SIZE (left) == 1 &&
3786 AOP_SIZE (right) == 1)
3788 genModOneByte (left, right, result);
3792 /* should have been converted to function call */
3796 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3797 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3798 freeAsmop (result, NULL, ic, TRUE);
3801 /*-----------------------------------------------------------------*/
3802 /* genIfxJump :- will create a jump depending on the ifx */
3803 /*-----------------------------------------------------------------*/
3805 genIfxJump (iCode * ic, char *jval)
3808 symbol *tlbl = newiTempLabel (NULL);
3811 D(emitcode (";", "genIfxJump"));
3813 /* if true label then we jump if condition
3817 jlbl = IC_TRUE (ic);
3818 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3819 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3823 /* false label is present */
3824 jlbl = IC_FALSE (ic);
3825 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3826 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3828 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3829 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3831 emitcode (inst, "%05d$", tlbl->key + 100);
3832 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3833 emitcode ("", "%05d$:", tlbl->key + 100);
3835 /* mark the icode as generated */
3839 /*-----------------------------------------------------------------*/
3840 /* genCmp :- greater or less than comparison */
3841 /*-----------------------------------------------------------------*/
3843 genCmp (operand * left, operand * right,
3844 operand * result, iCode * ifx, int sign, iCode *ic)
3846 int size, offset = 0;
3847 unsigned long lit = 0L;
3849 D(emitcode (";", "genCmp"));
3851 /* if left & right are bit variables */
3852 if (AOP_TYPE (left) == AOP_CRY &&
3853 AOP_TYPE (right) == AOP_CRY)
3855 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3856 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3860 /* subtract right from left if at the
3861 end the carry flag is set then we know that
3862 left is greater than right */
3863 size = max (AOP_SIZE (left), AOP_SIZE (right));
3865 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3866 if ((size == 1) && !sign &&
3867 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3869 symbol *lbl = newiTempLabel (NULL);
3870 emitcode ("cjne", "%s,%s,%05d$",
3871 aopGet (AOP (left), offset, FALSE, FALSE),
3872 aopGet (AOP (right), offset, FALSE, FALSE),
3874 emitcode ("", "%05d$:", lbl->key + 100);
3878 if (AOP_TYPE (right) == AOP_LIT)
3880 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3881 /* optimize if(x < 0) or if(x >= 0) */
3890 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3891 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3893 genIfxJump (ifx, "acc.7");
3897 emitcode ("rlc", "a");
3905 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3906 if (sign && size == 0)
3908 emitcode ("xrl", "a,#0x80");
3909 if (AOP_TYPE (right) == AOP_LIT)
3911 unsigned long lit = (unsigned long)
3912 floatFromVal (AOP (right)->aopu.aop_lit);
3913 emitcode ("subb", "a,#0x%02x",
3914 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3918 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3919 emitcode ("xrl", "b,#0x80");
3920 emitcode ("subb", "a,b");
3924 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3930 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3931 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3932 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3938 /* if the result is used in the next
3939 ifx conditional branch then generate
3940 code a little differently */
3942 genIfxJump (ifx, "c");
3945 /* leave the result in acc */
3949 /*-----------------------------------------------------------------*/
3950 /* genCmpGt :- greater than comparison */
3951 /*-----------------------------------------------------------------*/
3953 genCmpGt (iCode * ic, iCode * ifx)
3955 operand *left, *right, *result;
3956 sym_link *letype, *retype;
3959 D(emitcode (";", "genCmpGt"));
3961 left = IC_LEFT (ic);
3962 right = IC_RIGHT (ic);
3963 result = IC_RESULT (ic);
3965 letype = getSpec (operandType (left));
3966 retype = getSpec (operandType (right));
3967 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3968 /* assign the amsops */
3969 aopOp (left, ic, FALSE);
3970 aopOp (right, ic, FALSE);
3971 aopOp (result, ic, TRUE);
3973 genCmp (right, left, result, ifx, sign,ic);
3975 freeAsmop (result, NULL, ic, TRUE);
3978 /*-----------------------------------------------------------------*/
3979 /* genCmpLt - less than comparisons */
3980 /*-----------------------------------------------------------------*/
3982 genCmpLt (iCode * ic, iCode * ifx)
3984 operand *left, *right, *result;
3985 sym_link *letype, *retype;
3988 D(emitcode (";", "genCmpLt"));
3990 left = IC_LEFT (ic);
3991 right = IC_RIGHT (ic);
3992 result = IC_RESULT (ic);
3994 letype = getSpec (operandType (left));
3995 retype = getSpec (operandType (right));
3996 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3998 /* assign the amsops */
3999 aopOp (left, ic, FALSE);
4000 aopOp (right, ic, FALSE);
4001 aopOp (result, ic, TRUE);
4003 genCmp (left, right, result, ifx, sign,ic);
4005 freeAsmop (result, NULL, ic, TRUE);
4008 /*-----------------------------------------------------------------*/
4009 /* gencjneshort - compare and jump if not equal */
4010 /*-----------------------------------------------------------------*/
4012 gencjneshort (operand * left, operand * right, symbol * lbl)
4014 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4016 unsigned long lit = 0L;
4018 /* if the left side is a literal or
4019 if the right is in a pointer register and left
4021 if ((AOP_TYPE (left) == AOP_LIT) ||
4022 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4028 if (AOP_TYPE (right) == AOP_LIT)
4029 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4031 /* if the right side is a literal then anything goes */
4032 if (AOP_TYPE (right) == AOP_LIT &&
4033 AOP_TYPE (left) != AOP_DIR)
4037 emitcode ("cjne", "%s,%s,%05d$",
4038 aopGet (AOP (left), offset, FALSE, FALSE),
4039 aopGet (AOP (right), offset, FALSE, FALSE),
4045 /* if the right side is in a register or in direct space or
4046 if the left is a pointer register & right is not */
4047 else if (AOP_TYPE (right) == AOP_REG ||
4048 AOP_TYPE (right) == AOP_DIR ||
4049 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4050 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4054 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4055 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4056 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4057 emitcode ("jnz", "%05d$", lbl->key + 100);
4059 emitcode ("cjne", "a,%s,%05d$",
4060 aopGet (AOP (right), offset, FALSE, TRUE),
4067 /* right is a pointer reg need both a & b */
4070 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4071 if (strcmp (l, "b"))
4072 emitcode ("mov", "b,%s", l);
4073 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4074 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4080 /*-----------------------------------------------------------------*/
4081 /* gencjne - compare and jump if not equal */
4082 /*-----------------------------------------------------------------*/
4084 gencjne (operand * left, operand * right, symbol * lbl)
4086 symbol *tlbl = newiTempLabel (NULL);
4088 gencjneshort (left, right, lbl);
4090 emitcode ("mov", "a,%s", one);
4091 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4092 emitcode ("", "%05d$:", lbl->key + 100);
4093 emitcode ("clr", "a");
4094 emitcode ("", "%05d$:", tlbl->key + 100);
4097 /*-----------------------------------------------------------------*/
4098 /* genCmpEq - generates code for equal to */
4099 /*-----------------------------------------------------------------*/
4101 genCmpEq (iCode * ic, iCode * ifx)
4103 operand *left, *right, *result;
4105 D(emitcode (";", "genCmpEq"));
4107 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4108 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4109 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4111 /* if literal, literal on the right or
4112 if the right is in a pointer register and left
4114 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4115 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4117 operand *t = IC_RIGHT (ic);
4118 IC_RIGHT (ic) = IC_LEFT (ic);
4122 if (ifx && !AOP_SIZE (result))
4125 /* if they are both bit variables */
4126 if (AOP_TYPE (left) == AOP_CRY &&
4127 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4129 if (AOP_TYPE (right) == AOP_LIT)
4131 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4134 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4135 emitcode ("cpl", "c");
4139 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4143 emitcode ("clr", "c");
4145 /* AOP_TYPE(right) == AOP_CRY */
4149 symbol *lbl = newiTempLabel (NULL);
4150 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4151 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4152 emitcode ("cpl", "c");
4153 emitcode ("", "%05d$:", (lbl->key + 100));
4155 /* if true label then we jump if condition
4157 tlbl = newiTempLabel (NULL);
4160 emitcode ("jnc", "%05d$", tlbl->key + 100);
4161 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4165 emitcode ("jc", "%05d$", tlbl->key + 100);
4166 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4168 emitcode ("", "%05d$:", tlbl->key + 100);
4172 tlbl = newiTempLabel (NULL);
4173 gencjneshort (left, right, tlbl);
4176 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4177 emitcode ("", "%05d$:", tlbl->key + 100);
4181 symbol *lbl = newiTempLabel (NULL);
4182 emitcode ("sjmp", "%05d$", lbl->key + 100);
4183 emitcode ("", "%05d$:", tlbl->key + 100);
4184 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4185 emitcode ("", "%05d$:", lbl->key + 100);
4188 /* mark the icode as generated */
4193 /* if they are both bit variables */
4194 if (AOP_TYPE (left) == AOP_CRY &&
4195 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4197 if (AOP_TYPE (right) == AOP_LIT)
4199 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4202 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4203 emitcode ("cpl", "c");
4207 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4211 emitcode ("clr", "c");
4213 /* AOP_TYPE(right) == AOP_CRY */
4217 symbol *lbl = newiTempLabel (NULL);
4218 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4219 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4220 emitcode ("cpl", "c");
4221 emitcode ("", "%05d$:", (lbl->key + 100));
4224 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4231 genIfxJump (ifx, "c");
4234 /* if the result is used in an arithmetic operation
4235 then put the result in place */
4240 gencjne (left, right, newiTempLabel (NULL));
4241 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4243 aopPut (AOP (result), "a", 0);
4248 genIfxJump (ifx, "a");
4251 /* if the result is used in an arithmetic operation
4252 then put the result in place */
4253 if (AOP_TYPE (result) != AOP_CRY)
4255 /* leave the result in acc */
4259 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4260 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4261 freeAsmop (result, NULL, ic, TRUE);
4264 /*-----------------------------------------------------------------*/
4265 /* ifxForOp - returns the icode containing the ifx for operand */
4266 /*-----------------------------------------------------------------*/
4268 ifxForOp (operand * op, iCode * ic)
4270 /* if true symbol then needs to be assigned */
4271 if (IS_TRUE_SYMOP (op))
4274 /* if this has register type condition and
4275 the next instruction is ifx with the same operand
4276 and live to of the operand is upto the ifx only then */
4278 ic->next->op == IFX &&
4279 IC_COND (ic->next)->key == op->key &&
4280 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4286 /*-----------------------------------------------------------------*/
4287 /* hasInc - operand is incremented before any other use */
4288 /*-----------------------------------------------------------------*/
4290 hasInc (operand *op, iCode *ic)
4292 sym_link *type = operandType(op);
4293 sym_link *retype = getSpec (type);
4294 iCode *lic = ic->next;
4297 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4298 if (!IS_SYMOP(op)) return NULL;
4300 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4301 isize = getSize(type->next);
4303 /* if operand of the form op = op + <sizeof *op> */
4304 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4305 isOperandEqual(IC_RESULT(lic),op) &&
4306 isOperandLiteral(IC_RIGHT(lic)) &&
4307 operandLitValue(IC_RIGHT(lic)) == isize) {
4310 /* if the operand used or deffed */
4311 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4319 /*-----------------------------------------------------------------*/
4320 /* genAndOp - for && operation */
4321 /*-----------------------------------------------------------------*/
4323 genAndOp (iCode * ic)
4325 operand *left, *right, *result;
4328 D(emitcode (";", "genAndOp"));
4330 /* note here that && operations that are in an
4331 if statement are taken away by backPatchLabels
4332 only those used in arthmetic operations remain */
4333 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4334 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4335 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4337 /* if both are bit variables */
4338 if (AOP_TYPE (left) == AOP_CRY &&
4339 AOP_TYPE (right) == AOP_CRY)
4341 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4342 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4347 tlbl = newiTempLabel (NULL);
4349 emitcode ("jz", "%05d$", tlbl->key + 100);
4351 emitcode ("", "%05d$:", tlbl->key + 100);
4355 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4356 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4357 freeAsmop (result, NULL, ic, TRUE);
4361 /*-----------------------------------------------------------------*/
4362 /* genOrOp - for || operation */
4363 /*-----------------------------------------------------------------*/
4365 genOrOp (iCode * ic)
4367 operand *left, *right, *result;
4370 D(emitcode (";", "genOrOp"));
4372 /* note here that || operations that are in an
4373 if statement are taken away by backPatchLabels
4374 only those used in arthmetic operations remain */
4375 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4376 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4377 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4379 /* if both are bit variables */
4380 if (AOP_TYPE (left) == AOP_CRY &&
4381 AOP_TYPE (right) == AOP_CRY)
4383 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4384 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4389 tlbl = newiTempLabel (NULL);
4391 emitcode ("jnz", "%05d$", tlbl->key + 100);
4393 emitcode ("", "%05d$:", tlbl->key + 100);
4397 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4398 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4399 freeAsmop (result, NULL, ic, TRUE);
4402 /*-----------------------------------------------------------------*/
4403 /* isLiteralBit - test if lit == 2^n */
4404 /*-----------------------------------------------------------------*/
4406 isLiteralBit (unsigned long lit)
4408 unsigned long pw[32] =
4409 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4410 0x100L, 0x200L, 0x400L, 0x800L,
4411 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4412 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4413 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4414 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4415 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4418 for (idx = 0; idx < 32; idx++)
4424 /*-----------------------------------------------------------------*/
4425 /* continueIfTrue - */
4426 /*-----------------------------------------------------------------*/
4428 continueIfTrue (iCode * ic)
4431 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4435 /*-----------------------------------------------------------------*/
4437 /*-----------------------------------------------------------------*/
4439 jumpIfTrue (iCode * ic)
4442 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4446 /*-----------------------------------------------------------------*/
4447 /* jmpTrueOrFalse - */
4448 /*-----------------------------------------------------------------*/
4450 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4452 // ugly but optimized by peephole
4455 symbol *nlbl = newiTempLabel (NULL);
4456 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4457 emitcode ("", "%05d$:", tlbl->key + 100);
4458 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4459 emitcode ("", "%05d$:", nlbl->key + 100);
4463 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4464 emitcode ("", "%05d$:", tlbl->key + 100);
4469 /*-----------------------------------------------------------------*/
4470 /* genAnd - code for and */
4471 /*-----------------------------------------------------------------*/
4473 genAnd (iCode * ic, iCode * ifx)
4475 operand *left, *right, *result;
4476 int size, offset = 0;
4477 unsigned long lit = 0L;
4481 D(emitcode (";", "genAnd"));
4483 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4484 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4485 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4488 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4490 AOP_TYPE (left), AOP_TYPE (right));
4491 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4493 AOP_SIZE (left), AOP_SIZE (right));
4496 /* if left is a literal & right is not then exchange them */
4497 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4498 AOP_NEEDSACC (left))
4500 operand *tmp = right;
4505 /* if result = right then exchange them */
4506 if (sameRegs (AOP (result), AOP (right)))
4508 operand *tmp = right;
4513 /* if right is bit then exchange them */
4514 if (AOP_TYPE (right) == AOP_CRY &&
4515 AOP_TYPE (left) != AOP_CRY)
4517 operand *tmp = right;
4521 if (AOP_TYPE (right) == AOP_LIT)
4522 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4524 size = AOP_SIZE (result);
4527 // result = bit & yy;
4528 if (AOP_TYPE (left) == AOP_CRY)
4530 // c = bit & literal;
4531 if (AOP_TYPE (right) == AOP_LIT)
4535 if (size && sameRegs (AOP (result), AOP (left)))
4538 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4543 if (size && (AOP_TYPE (result) == AOP_CRY))
4545 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4548 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4553 emitcode ("clr", "c");
4558 if (AOP_TYPE (right) == AOP_CRY)
4561 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4562 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4567 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4569 emitcode ("rrc", "a");
4570 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4578 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4579 genIfxJump (ifx, "c");
4583 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4584 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4585 if ((AOP_TYPE (right) == AOP_LIT) &&
4586 (AOP_TYPE (result) == AOP_CRY) &&
4587 (AOP_TYPE (left) != AOP_CRY))
4589 int posbit = isLiteralBit (lit);
4594 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4597 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4603 sprintf (buffer, "acc.%d", posbit & 0x07);
4604 genIfxJump (ifx, buffer);
4611 symbol *tlbl = newiTempLabel (NULL);
4612 int sizel = AOP_SIZE (left);
4614 emitcode ("setb", "c");
4617 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4619 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4621 if ((posbit = isLiteralBit (bytelit)) != 0)
4622 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4625 if (bytelit != 0x0FFL)
4626 emitcode ("anl", "a,%s",
4627 aopGet (AOP (right), offset, FALSE, TRUE));
4628 emitcode ("jnz", "%05d$", tlbl->key + 100);
4633 // bit = left & literal
4636 emitcode ("clr", "c");
4637 emitcode ("", "%05d$:", tlbl->key + 100);
4639 // if(left & literal)
4643 jmpTrueOrFalse (ifx, tlbl);
4651 /* if left is same as result */
4652 if (sameRegs (AOP (result), AOP (left)))
4654 for (; size--; offset++)
4656 if (AOP_TYPE (right) == AOP_LIT)
4658 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4660 else if (bytelit == 0)
4661 aopPut (AOP (result), zero, offset);
4662 else if (IS_AOP_PREG (result))
4664 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4665 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4666 aopPut (AOP (result), "a", offset);
4669 emitcode ("anl", "%s,%s",
4670 aopGet (AOP (left), offset, FALSE, TRUE),
4671 aopGet (AOP (right), offset, FALSE, FALSE));
4675 if (AOP_TYPE (left) == AOP_ACC)
4676 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4679 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4680 if (IS_AOP_PREG (result))
4682 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4683 aopPut (AOP (result), "a", offset);
4687 emitcode ("anl", "%s,a",
4688 aopGet (AOP (left), offset, FALSE, TRUE));
4695 // left & result in different registers
4696 if (AOP_TYPE (result) == AOP_CRY)
4699 // if(size), result in bit
4700 // if(!size && ifx), conditional oper: if(left & right)
4701 symbol *tlbl = newiTempLabel (NULL);
4702 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4704 emitcode ("setb", "c");
4707 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4708 emitcode ("anl", "a,%s",
4709 aopGet (AOP (right), offset, FALSE, FALSE));
4711 if (AOP_TYPE(left)==AOP_ACC) {
4712 emitcode("mov", "b,a");
4713 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4714 emitcode("anl", "a,b");
4716 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4717 emitcode ("anl", "a,%s",
4718 aopGet (AOP (left), offset, FALSE, FALSE));
4721 emitcode ("jnz", "%05d$", tlbl->key + 100);
4727 emitcode ("", "%05d$:", tlbl->key + 100);
4731 jmpTrueOrFalse (ifx, tlbl);
4735 for (; (size--); offset++)
4738 // result = left & right
4739 if (AOP_TYPE (right) == AOP_LIT)
4741 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4743 aopPut (AOP (result),
4744 aopGet (AOP (left), offset, FALSE, FALSE),
4748 else if (bytelit == 0)
4750 aopPut (AOP (result), zero, offset);
4754 // faster than result <- left, anl result,right
4755 // and better if result is SFR
4756 if (AOP_TYPE (left) == AOP_ACC)
4757 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4760 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4761 emitcode ("anl", "a,%s",
4762 aopGet (AOP (left), offset, FALSE, FALSE));
4764 aopPut (AOP (result), "a", offset);
4770 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4772 freeAsmop (result, NULL, ic, TRUE);
4775 /*-----------------------------------------------------------------*/
4776 /* genOr - code for or */
4777 /*-----------------------------------------------------------------*/
4779 genOr (iCode * ic, iCode * ifx)
4781 operand *left, *right, *result;
4782 int size, offset = 0;
4783 unsigned long lit = 0L;
4785 D(emitcode (";", "genOr"));
4787 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4788 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4789 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4792 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4794 AOP_TYPE (left), AOP_TYPE (right));
4795 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4797 AOP_SIZE (left), AOP_SIZE (right));
4800 /* if left is a literal & right is not then exchange them */
4801 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4802 AOP_NEEDSACC (left))
4804 operand *tmp = right;
4809 /* if result = right then exchange them */
4810 if (sameRegs (AOP (result), AOP (right)))
4812 operand *tmp = right;
4817 /* if right is bit then exchange them */
4818 if (AOP_TYPE (right) == AOP_CRY &&
4819 AOP_TYPE (left) != AOP_CRY)
4821 operand *tmp = right;
4825 if (AOP_TYPE (right) == AOP_LIT)
4826 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4828 size = AOP_SIZE (result);
4832 if (AOP_TYPE (left) == AOP_CRY)
4834 if (AOP_TYPE (right) == AOP_LIT)
4836 // c = bit & literal;
4839 // lit != 0 => result = 1
4840 if (AOP_TYPE (result) == AOP_CRY)
4843 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4845 continueIfTrue (ifx);
4848 emitcode ("setb", "c");
4852 // lit == 0 => result = left
4853 if (size && sameRegs (AOP (result), AOP (left)))
4855 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4860 if (AOP_TYPE (right) == AOP_CRY)
4863 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4864 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4869 symbol *tlbl = newiTempLabel (NULL);
4870 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4871 emitcode ("setb", "c");
4872 emitcode ("jb", "%s,%05d$",
4873 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4875 emitcode ("jnz", "%05d$", tlbl->key + 100);
4876 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4878 jmpTrueOrFalse (ifx, tlbl);
4884 emitcode ("", "%05d$:", tlbl->key + 100);
4893 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4894 genIfxJump (ifx, "c");
4898 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4899 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4900 if ((AOP_TYPE (right) == AOP_LIT) &&
4901 (AOP_TYPE (result) == AOP_CRY) &&
4902 (AOP_TYPE (left) != AOP_CRY))
4908 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4910 continueIfTrue (ifx);
4915 // lit = 0, result = boolean(left)
4917 emitcode ("setb", "c");
4921 symbol *tlbl = newiTempLabel (NULL);
4922 emitcode ("jnz", "%05d$", tlbl->key + 100);
4924 emitcode ("", "%05d$:", tlbl->key + 100);
4928 genIfxJump (ifx, "a");
4936 /* if left is same as result */
4937 if (sameRegs (AOP (result), AOP (left)))
4939 for (; size--; offset++)
4941 if (AOP_TYPE (right) == AOP_LIT)
4943 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4945 else if (IS_AOP_PREG (left))
4947 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4948 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4949 aopPut (AOP (result), "a", offset);
4952 emitcode ("orl", "%s,%s",
4953 aopGet (AOP (left), offset, FALSE, TRUE),
4954 aopGet (AOP (right), offset, FALSE, FALSE));
4958 if (AOP_TYPE (left) == AOP_ACC)
4959 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4962 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4963 if (IS_AOP_PREG (left))
4965 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4966 aopPut (AOP (result), "a", offset);
4969 emitcode ("orl", "%s,a",
4970 aopGet (AOP (left), offset, FALSE, TRUE));
4977 // left & result in different registers
4978 if (AOP_TYPE (result) == AOP_CRY)
4981 // if(size), result in bit
4982 // if(!size && ifx), conditional oper: if(left | right)
4983 symbol *tlbl = newiTempLabel (NULL);
4984 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4986 emitcode ("setb", "c");
4989 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4990 emitcode ("orl", "a,%s",
4991 aopGet (AOP (right), offset, FALSE, FALSE));
4993 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4994 emitcode ("orl", "a,%s",
4995 aopGet (AOP (left), offset, FALSE, FALSE));
4997 emitcode ("jnz", "%05d$", tlbl->key + 100);
5003 emitcode ("", "%05d$:", tlbl->key + 100);
5007 jmpTrueOrFalse (ifx, tlbl);
5010 for (; (size--); offset++)
5013 // result = left & right
5014 if (AOP_TYPE (right) == AOP_LIT)
5016 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5018 aopPut (AOP (result),
5019 aopGet (AOP (left), offset, FALSE, FALSE),
5024 // faster than result <- left, anl result,right
5025 // and better if result is SFR
5026 if (AOP_TYPE (left) == AOP_ACC)
5027 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5030 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5031 emitcode ("orl", "a,%s",
5032 aopGet (AOP (left), offset, FALSE, FALSE));
5034 aopPut (AOP (result), "a", offset);
5039 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5040 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5041 freeAsmop (result, NULL, ic, TRUE);
5044 /*-----------------------------------------------------------------*/
5045 /* genXor - code for xclusive or */
5046 /*-----------------------------------------------------------------*/
5048 genXor (iCode * ic, iCode * ifx)
5050 operand *left, *right, *result;
5051 int size, offset = 0;
5052 unsigned long lit = 0L;
5054 D(emitcode (";", "genXor"));
5056 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5057 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5058 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5061 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5063 AOP_TYPE (left), AOP_TYPE (right));
5064 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5066 AOP_SIZE (left), AOP_SIZE (right));
5069 /* if left is a literal & right is not ||
5070 if left needs acc & right does not */
5071 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5072 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5074 operand *tmp = right;
5079 /* if result = right then exchange them */
5080 if (sameRegs (AOP (result), AOP (right)))
5082 operand *tmp = right;
5087 /* if right is bit then exchange them */
5088 if (AOP_TYPE (right) == AOP_CRY &&
5089 AOP_TYPE (left) != AOP_CRY)
5091 operand *tmp = right;
5095 if (AOP_TYPE (right) == AOP_LIT)
5096 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5098 size = AOP_SIZE (result);
5102 if (AOP_TYPE (left) == AOP_CRY)
5104 if (AOP_TYPE (right) == AOP_LIT)
5106 // c = bit & literal;
5109 // lit>>1 != 0 => result = 1
5110 if (AOP_TYPE (result) == AOP_CRY)
5113 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5115 continueIfTrue (ifx);
5118 emitcode ("setb", "c");
5125 // lit == 0, result = left
5126 if (size && sameRegs (AOP (result), AOP (left)))
5128 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5132 // lit == 1, result = not(left)
5133 if (size && sameRegs (AOP (result), AOP (left)))
5135 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5140 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5141 emitcode ("cpl", "c");
5150 symbol *tlbl = newiTempLabel (NULL);
5151 if (AOP_TYPE (right) == AOP_CRY)
5154 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5158 int sizer = AOP_SIZE (right);
5160 // if val>>1 != 0, result = 1
5161 emitcode ("setb", "c");
5164 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5166 // test the msb of the lsb
5167 emitcode ("anl", "a,#0xfe");
5168 emitcode ("jnz", "%05d$", tlbl->key + 100);
5172 emitcode ("rrc", "a");
5174 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5175 emitcode ("cpl", "c");
5176 emitcode ("", "%05d$:", (tlbl->key + 100));
5183 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5184 genIfxJump (ifx, "c");
5188 if (sameRegs (AOP (result), AOP (left)))
5190 /* if left is same as result */
5191 for (; size--; offset++)
5193 if (AOP_TYPE (right) == AOP_LIT)
5195 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5197 else if (IS_AOP_PREG (left))
5199 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5200 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5201 aopPut (AOP (result), "a", offset);
5204 emitcode ("xrl", "%s,%s",
5205 aopGet (AOP (left), offset, FALSE, TRUE),
5206 aopGet (AOP (right), offset, FALSE, FALSE));
5210 if (AOP_TYPE (left) == AOP_ACC)
5211 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5214 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5215 if (IS_AOP_PREG (left))
5217 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5218 aopPut (AOP (result), "a", offset);
5221 emitcode ("xrl", "%s,a",
5222 aopGet (AOP (left), offset, FALSE, TRUE));
5229 // left & result in different registers
5230 if (AOP_TYPE (result) == AOP_CRY)
5233 // if(size), result in bit
5234 // if(!size && ifx), conditional oper: if(left ^ right)
5235 symbol *tlbl = newiTempLabel (NULL);
5236 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5238 emitcode ("setb", "c");
5241 if ((AOP_TYPE (right) == AOP_LIT) &&
5242 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5244 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5248 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5249 emitcode ("xrl", "a,%s",
5250 aopGet (AOP (right), offset, FALSE, FALSE));
5252 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5253 emitcode ("xrl", "a,%s",
5254 aopGet (AOP (left), offset, FALSE, FALSE));
5257 emitcode ("jnz", "%05d$", tlbl->key + 100);
5263 emitcode ("", "%05d$:", tlbl->key + 100);
5267 jmpTrueOrFalse (ifx, tlbl);
5270 for (; (size--); offset++)
5273 // result = left & right
5274 if (AOP_TYPE (right) == AOP_LIT)
5276 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5278 aopPut (AOP (result),
5279 aopGet (AOP (left), offset, FALSE, FALSE),
5284 // faster than result <- left, anl result,right
5285 // and better if result is SFR
5286 if (AOP_TYPE (left) == AOP_ACC)
5287 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5290 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5291 emitcode ("xrl", "a,%s",
5292 aopGet (AOP (left), offset, FALSE, TRUE));
5294 aopPut (AOP (result), "a", offset);
5299 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5300 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5301 freeAsmop (result, NULL, ic, TRUE);
5304 /*-----------------------------------------------------------------*/
5305 /* genInline - write the inline code out */
5306 /*-----------------------------------------------------------------*/
5308 genInline (iCode * ic)
5310 char *buffer, *bp, *bp1;
5312 D(emitcode (";", "genInline"));
5314 _G.inLine += (!options.asmpeep);
5316 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5317 strcpy (buffer, IC_INLINE (ic));
5319 /* emit each line as a code */
5344 /* emitcode("",buffer); */
5345 _G.inLine -= (!options.asmpeep);
5348 /*-----------------------------------------------------------------*/
5349 /* genRRC - rotate right with carry */
5350 /*-----------------------------------------------------------------*/
5354 operand *left, *result;
5355 int size, offset = 0;
5358 D(emitcode (";", "genRRC"));
5360 /* rotate right with carry */
5361 left = IC_LEFT (ic);
5362 result = IC_RESULT (ic);
5363 aopOp (left, ic, FALSE);
5364 aopOp (result, ic, FALSE);
5366 /* move it to the result */
5367 size = AOP_SIZE (result);
5369 if (size == 1) { /* special case for 1 byte */
5370 l = aopGet (AOP (left), offset, FALSE, FALSE);
5372 emitcode ("rr", "a");
5378 l = aopGet (AOP (left), offset, FALSE, FALSE);
5380 emitcode ("rrc", "a");
5381 if (AOP_SIZE (result) > 1)
5382 aopPut (AOP (result), "a", offset--);
5384 /* now we need to put the carry into the
5385 highest order byte of the result */
5386 if (AOP_SIZE (result) > 1)
5388 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5391 emitcode ("mov", "acc.7,c");
5393 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5394 freeAsmop (left, NULL, ic, TRUE);
5395 freeAsmop (result, NULL, ic, TRUE);
5398 /*-----------------------------------------------------------------*/
5399 /* genRLC - generate code for rotate left with carry */
5400 /*-----------------------------------------------------------------*/
5404 operand *left, *result;
5405 int size, offset = 0;
5408 D(emitcode (";", "genRLC"));
5410 /* rotate right with carry */
5411 left = IC_LEFT (ic);
5412 result = IC_RESULT (ic);
5413 aopOp (left, ic, FALSE);
5414 aopOp (result, ic, FALSE);
5416 /* move it to the result */
5417 size = AOP_SIZE (result);
5421 l = aopGet (AOP (left), offset, FALSE, FALSE);
5423 if (size == 0) { /* special case for 1 byte */
5427 emitcode ("add", "a,acc");
5428 if (AOP_SIZE (result) > 1)
5429 aopPut (AOP (result), "a", offset++);
5432 l = aopGet (AOP (left), offset, FALSE, FALSE);
5434 emitcode ("rlc", "a");
5435 if (AOP_SIZE (result) > 1)
5436 aopPut (AOP (result), "a", offset++);
5439 /* now we need to put the carry into the
5440 highest order byte of the result */
5441 if (AOP_SIZE (result) > 1)
5443 l = aopGet (AOP (result), 0, FALSE, FALSE);
5446 emitcode ("mov", "acc.0,c");
5448 aopPut (AOP (result), "a", 0);
5449 freeAsmop (left, NULL, ic, TRUE);
5450 freeAsmop (result, NULL, ic, TRUE);
5453 /*-----------------------------------------------------------------*/
5454 /* genGetHbit - generates code get highest order bit */
5455 /*-----------------------------------------------------------------*/
5457 genGetHbit (iCode * ic)
5459 operand *left, *result;
5461 D(emitcode (";", "genGetHbit"));
5463 left = IC_LEFT (ic);
5464 result = IC_RESULT (ic);
5465 aopOp (left, ic, FALSE);
5466 aopOp (result, ic, FALSE);
5468 /* get the highest order byte into a */
5469 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5470 if (AOP_TYPE (result) == AOP_CRY)
5472 emitcode ("rlc", "a");
5477 emitcode ("rl", "a");
5478 emitcode ("anl", "a,#0x01");
5483 freeAsmop (left, NULL, ic, TRUE);
5484 freeAsmop (result, NULL, ic, TRUE);
5487 /*-----------------------------------------------------------------*/
5488 /* AccRol - rotate left accumulator by known count */
5489 /*-----------------------------------------------------------------*/
5491 AccRol (int shCount)
5493 shCount &= 0x0007; // shCount : 0..7
5500 emitcode ("rl", "a");
5503 emitcode ("rl", "a");
5504 emitcode ("rl", "a");
5507 emitcode ("swap", "a");
5508 emitcode ("rr", "a");
5511 emitcode ("swap", "a");
5514 emitcode ("swap", "a");
5515 emitcode ("rl", "a");
5518 emitcode ("rr", "a");
5519 emitcode ("rr", "a");
5522 emitcode ("rr", "a");
5527 /*-----------------------------------------------------------------*/
5528 /* AccLsh - left shift accumulator by known count */
5529 /*-----------------------------------------------------------------*/
5531 AccLsh (int shCount)
5536 emitcode ("add", "a,acc");
5537 else if (shCount == 2)
5539 emitcode ("add", "a,acc");
5540 emitcode ("add", "a,acc");
5544 /* rotate left accumulator */
5546 /* and kill the lower order bits */
5547 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5552 /*-----------------------------------------------------------------*/
5553 /* AccRsh - right shift accumulator by known count */
5554 /*-----------------------------------------------------------------*/
5556 AccRsh (int shCount)
5563 emitcode ("rrc", "a");
5567 /* rotate right accumulator */
5568 AccRol (8 - shCount);
5569 /* and kill the higher order bits */
5570 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5575 /*-----------------------------------------------------------------*/
5576 /* AccSRsh - signed right shift accumulator by known count */
5577 /*-----------------------------------------------------------------*/
5579 AccSRsh (int shCount)
5586 emitcode ("mov", "c,acc.7");
5587 emitcode ("rrc", "a");
5589 else if (shCount == 2)
5591 emitcode ("mov", "c,acc.7");
5592 emitcode ("rrc", "a");
5593 emitcode ("mov", "c,acc.7");
5594 emitcode ("rrc", "a");
5598 tlbl = newiTempLabel (NULL);
5599 /* rotate right accumulator */
5600 AccRol (8 - shCount);
5601 /* and kill the higher order bits */
5602 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5603 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5604 emitcode ("orl", "a,#0x%02x",
5605 (unsigned char) ~SRMask[shCount]);
5606 emitcode ("", "%05d$:", tlbl->key + 100);
5611 /*-----------------------------------------------------------------*/
5612 /* shiftR1Left2Result - shift right one byte from left to result */
5613 /*-----------------------------------------------------------------*/
5615 shiftR1Left2Result (operand * left, int offl,
5616 operand * result, int offr,
5617 int shCount, int sign)
5619 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5620 /* shift right accumulator */
5625 aopPut (AOP (result), "a", offr);
5628 /*-----------------------------------------------------------------*/
5629 /* shiftL1Left2Result - shift left one byte from left to result */
5630 /*-----------------------------------------------------------------*/
5632 shiftL1Left2Result (operand * left, int offl,
5633 operand * result, int offr, int shCount)
5636 l = aopGet (AOP (left), offl, FALSE, FALSE);
5638 /* shift left accumulator */
5640 aopPut (AOP (result), "a", offr);
5643 /*-----------------------------------------------------------------*/
5644 /* movLeft2Result - move byte from left to result */
5645 /*-----------------------------------------------------------------*/
5647 movLeft2Result (operand * left, int offl,
5648 operand * result, int offr, int sign)
5651 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5653 l = aopGet (AOP (left), offl, FALSE, FALSE);
5655 if (*l == '@' && (IS_AOP_PREG (result)))
5657 emitcode ("mov", "a,%s", l);
5658 aopPut (AOP (result), "a", offr);
5663 aopPut (AOP (result), l, offr);
5666 /* MSB sign in acc.7 ! */
5667 if (getDataSize (left) == offl + 1)
5669 emitcode ("mov", "a,%s", l);
5670 aopPut (AOP (result), "a", offr);
5677 /*-----------------------------------------------------------------*/
5678 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5679 /*-----------------------------------------------------------------*/
5683 emitcode ("rrc", "a");
5684 emitcode ("xch", "a,%s", x);
5685 emitcode ("rrc", "a");
5686 emitcode ("xch", "a,%s", x);
5689 /*-----------------------------------------------------------------*/
5690 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5691 /*-----------------------------------------------------------------*/
5695 emitcode ("xch", "a,%s", x);
5696 emitcode ("rlc", "a");
5697 emitcode ("xch", "a,%s", x);
5698 emitcode ("rlc", "a");
5701 /*-----------------------------------------------------------------*/
5702 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5703 /*-----------------------------------------------------------------*/
5707 emitcode ("xch", "a,%s", x);
5708 emitcode ("add", "a,acc");
5709 emitcode ("xch", "a,%s", x);
5710 emitcode ("rlc", "a");
5713 /*-----------------------------------------------------------------*/
5714 /* AccAXLsh - left shift a:x by known count (0..7) */
5715 /*-----------------------------------------------------------------*/
5717 AccAXLsh (char *x, int shCount)
5732 case 5: // AAAAABBB:CCCCCDDD
5734 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5736 emitcode ("anl", "a,#0x%02x",
5737 SLMask[shCount]); // BBB00000:CCCCCDDD
5739 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5741 AccRol (shCount); // DDDCCCCC:BBB00000
5743 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5745 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5747 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5749 emitcode ("anl", "a,#0x%02x",
5750 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5752 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5754 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5757 case 6: // AAAAAABB:CCCCCCDD
5758 emitcode ("anl", "a,#0x%02x",
5759 SRMask[shCount]); // 000000BB:CCCCCCDD
5760 emitcode ("mov", "c,acc.0"); // c = B
5761 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5763 AccAXRrl1 (x); // BCCCCCCD:D000000B
5764 AccAXRrl1 (x); // BBCCCCCC:DD000000
5766 emitcode("rrc","a");
5767 emitcode("xch","a,%s", x);
5768 emitcode("rrc","a");
5769 emitcode("mov","c,acc.0"); //<< get correct bit
5770 emitcode("xch","a,%s", x);
5772 emitcode("rrc","a");
5773 emitcode("xch","a,%s", x);
5774 emitcode("rrc","a");
5775 emitcode("xch","a,%s", x);
5778 case 7: // a:x <<= 7
5780 emitcode ("anl", "a,#0x%02x",
5781 SRMask[shCount]); // 0000000B:CCCCCCCD
5783 emitcode ("mov", "c,acc.0"); // c = B
5785 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5787 AccAXRrl1 (x); // BCCCCCCC:D0000000
5795 /*-----------------------------------------------------------------*/
5796 /* AccAXRsh - right shift a:x known count (0..7) */
5797 /*-----------------------------------------------------------------*/
5799 AccAXRsh (char *x, int shCount)
5807 AccAXRrl1 (x); // 0->a:x
5812 AccAXRrl1 (x); // 0->a:x
5815 AccAXRrl1 (x); // 0->a:x
5820 case 5: // AAAAABBB:CCCCCDDD = a:x
5822 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5824 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5826 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5828 emitcode ("anl", "a,#0x%02x",
5829 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5831 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5833 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5835 emitcode ("anl", "a,#0x%02x",
5836 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5838 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5840 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5842 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5845 case 6: // AABBBBBB:CCDDDDDD
5847 emitcode ("mov", "c,acc.7");
5848 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5850 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5852 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5854 emitcode ("anl", "a,#0x%02x",
5855 SRMask[shCount]); // 000000AA:BBBBBBCC
5858 case 7: // ABBBBBBB:CDDDDDDD
5860 emitcode ("mov", "c,acc.7"); // c = A
5862 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5864 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5866 emitcode ("anl", "a,#0x%02x",
5867 SRMask[shCount]); // 0000000A:BBBBBBBC
5875 /*-----------------------------------------------------------------*/
5876 /* AccAXRshS - right shift signed a:x known count (0..7) */
5877 /*-----------------------------------------------------------------*/
5879 AccAXRshS (char *x, int shCount)
5887 emitcode ("mov", "c,acc.7");
5888 AccAXRrl1 (x); // s->a:x
5892 emitcode ("mov", "c,acc.7");
5893 AccAXRrl1 (x); // s->a:x
5895 emitcode ("mov", "c,acc.7");
5896 AccAXRrl1 (x); // s->a:x
5901 case 5: // AAAAABBB:CCCCCDDD = a:x
5903 tlbl = newiTempLabel (NULL);
5904 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5906 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5908 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5910 emitcode ("anl", "a,#0x%02x",
5911 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5913 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5915 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5917 emitcode ("anl", "a,#0x%02x",
5918 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5920 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5922 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5924 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5926 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5927 emitcode ("orl", "a,#0x%02x",
5928 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5930 emitcode ("", "%05d$:", tlbl->key + 100);
5931 break; // SSSSAAAA:BBBCCCCC
5933 case 6: // AABBBBBB:CCDDDDDD
5935 tlbl = newiTempLabel (NULL);
5936 emitcode ("mov", "c,acc.7");
5937 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5939 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5941 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5943 emitcode ("anl", "a,#0x%02x",
5944 SRMask[shCount]); // 000000AA:BBBBBBCC
5946 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5947 emitcode ("orl", "a,#0x%02x",
5948 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5950 emitcode ("", "%05d$:", tlbl->key + 100);
5952 case 7: // ABBBBBBB:CDDDDDDD
5954 tlbl = newiTempLabel (NULL);
5955 emitcode ("mov", "c,acc.7"); // c = A
5957 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5959 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5961 emitcode ("anl", "a,#0x%02x",
5962 SRMask[shCount]); // 0000000A:BBBBBBBC
5964 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5965 emitcode ("orl", "a,#0x%02x",
5966 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5968 emitcode ("", "%05d$:", tlbl->key + 100);
5975 /*-----------------------------------------------------------------*/
5976 /* shiftL2Left2Result - shift left two bytes from left to result */
5977 /*-----------------------------------------------------------------*/
5979 shiftL2Left2Result (operand * left, int offl,
5980 operand * result, int offr, int shCount)
5982 if (sameRegs (AOP (result), AOP (left)) &&
5983 ((offl + MSB16) == offr))
5985 /* don't crash result[offr] */
5986 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5987 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5991 movLeft2Result (left, offl, result, offr, 0);
5992 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5994 /* ax << shCount (x = lsb(result)) */
5995 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5996 aopPut (AOP (result), "a", offr + MSB16);
6000 /*-----------------------------------------------------------------*/
6001 /* shiftR2Left2Result - shift right two bytes from left to result */
6002 /*-----------------------------------------------------------------*/
6004 shiftR2Left2Result (operand * left, int offl,
6005 operand * result, int offr,
6006 int shCount, int sign)
6008 if (sameRegs (AOP (result), AOP (left)) &&
6009 ((offl + MSB16) == offr))
6011 /* don't crash result[offr] */
6012 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6013 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6017 movLeft2Result (left, offl, result, offr, 0);
6018 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6020 /* a:x >> shCount (x = lsb(result)) */
6022 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6024 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6025 if (getDataSize (result) > 1)
6026 aopPut (AOP (result), "a", offr + MSB16);
6029 /*-----------------------------------------------------------------*/
6030 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6031 /*-----------------------------------------------------------------*/
6033 shiftLLeftOrResult (operand * left, int offl,
6034 operand * result, int offr, int shCount)
6036 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6037 /* shift left accumulator */
6039 /* or with result */
6040 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6041 /* back to result */
6042 aopPut (AOP (result), "a", offr);
6045 /*-----------------------------------------------------------------*/
6046 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6047 /*-----------------------------------------------------------------*/
6049 shiftRLeftOrResult (operand * left, int offl,
6050 operand * result, int offr, int shCount)
6052 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6053 /* shift right accumulator */
6055 /* or with result */
6056 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6057 /* back to result */
6058 aopPut (AOP (result), "a", offr);
6061 /*-----------------------------------------------------------------*/
6062 /* genlshOne - left shift a one byte quantity by known count */
6063 /*-----------------------------------------------------------------*/
6065 genlshOne (operand * result, operand * left, int shCount)
6067 D(emitcode (";", "genlshOne"));
6069 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6072 /*-----------------------------------------------------------------*/
6073 /* genlshTwo - left shift two bytes by known amount != 0 */
6074 /*-----------------------------------------------------------------*/
6076 genlshTwo (operand * result, operand * left, int shCount)
6080 D(emitcode (";", "genlshTwo"));
6082 size = getDataSize (result);
6084 /* if shCount >= 8 */
6092 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6094 movLeft2Result (left, LSB, result, MSB16, 0);
6096 aopPut (AOP (result), zero, LSB);
6099 /* 1 <= shCount <= 7 */
6103 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6105 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6109 /*-----------------------------------------------------------------*/
6110 /* shiftLLong - shift left one long from left to result */
6111 /* offl = LSB or MSB16 */
6112 /*-----------------------------------------------------------------*/
6114 shiftLLong (operand * left, operand * result, int offr)
6117 int size = AOP_SIZE (result);
6119 if (size >= LSB + offr)
6121 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6123 emitcode ("add", "a,acc");
6124 if (sameRegs (AOP (left), AOP (result)) &&
6125 size >= MSB16 + offr && offr != LSB)
6126 emitcode ("xch", "a,%s",
6127 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6129 aopPut (AOP (result), "a", LSB + offr);
6132 if (size >= MSB16 + offr)
6134 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6136 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6139 emitcode ("rlc", "a");
6140 if (sameRegs (AOP (left), AOP (result)) &&
6141 size >= MSB24 + offr && offr != LSB)
6142 emitcode ("xch", "a,%s",
6143 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6145 aopPut (AOP (result), "a", MSB16 + offr);
6148 if (size >= MSB24 + offr)
6150 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6152 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6155 emitcode ("rlc", "a");
6156 if (sameRegs (AOP (left), AOP (result)) &&
6157 size >= MSB32 + offr && offr != LSB)
6158 emitcode ("xch", "a,%s",
6159 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6161 aopPut (AOP (result), "a", MSB24 + offr);
6164 if (size > MSB32 + offr)
6166 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6168 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6171 emitcode ("rlc", "a");
6172 aopPut (AOP (result), "a", MSB32 + offr);
6175 aopPut (AOP (result), zero, LSB);
6178 /*-----------------------------------------------------------------*/
6179 /* genlshFour - shift four byte by a known amount != 0 */
6180 /*-----------------------------------------------------------------*/
6182 genlshFour (operand * result, operand * left, int shCount)
6186 D(emitcode (";", "genlshFour"));
6188 size = AOP_SIZE (result);
6190 /* if shifting more that 3 bytes */
6195 /* lowest order of left goes to the highest
6196 order of the destination */
6197 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6199 movLeft2Result (left, LSB, result, MSB32, 0);
6200 aopPut (AOP (result), zero, LSB);
6201 aopPut (AOP (result), zero, MSB16);
6202 aopPut (AOP (result), zero, MSB24);
6206 /* more than two bytes */
6207 else if (shCount >= 16)
6209 /* lower order two bytes goes to higher order two bytes */
6211 /* if some more remaining */
6213 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6216 movLeft2Result (left, MSB16, result, MSB32, 0);
6217 movLeft2Result (left, LSB, result, MSB24, 0);
6219 aopPut (AOP (result), zero, MSB16);
6220 aopPut (AOP (result), zero, LSB);
6224 /* if more than 1 byte */
6225 else if (shCount >= 8)
6227 /* lower order three bytes goes to higher order three bytes */
6232 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6234 movLeft2Result (left, LSB, result, MSB16, 0);
6240 movLeft2Result (left, MSB24, result, MSB32, 0);
6241 movLeft2Result (left, MSB16, result, MSB24, 0);
6242 movLeft2Result (left, LSB, result, MSB16, 0);
6243 aopPut (AOP (result), zero, LSB);
6245 else if (shCount == 1)
6246 shiftLLong (left, result, MSB16);
6249 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6250 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6251 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6252 aopPut (AOP (result), zero, LSB);
6257 /* 1 <= shCount <= 7 */
6258 else if (shCount <= 2)
6260 shiftLLong (left, result, LSB);
6262 shiftLLong (result, result, LSB);
6264 /* 3 <= shCount <= 7, optimize */
6267 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6268 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6269 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6273 /*-----------------------------------------------------------------*/
6274 /* genLeftShiftLiteral - left shifting by known count */
6275 /*-----------------------------------------------------------------*/
6277 genLeftShiftLiteral (operand * left,
6282 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6285 D(emitcode (";", "genLeftShiftLiteral"));
6287 freeAsmop (right, NULL, ic, TRUE);
6289 aopOp (left, ic, FALSE);
6290 aopOp (result, ic, FALSE);
6292 size = getSize (operandType (result));
6295 emitcode ("; shift left ", "result %d, left %d", size,
6299 /* I suppose that the left size >= result size */
6304 movLeft2Result (left, size, result, size, 0);
6308 else if (shCount >= (size * 8))
6310 aopPut (AOP (result), zero, size);
6316 genlshOne (result, left, shCount);
6320 genlshTwo (result, left, shCount);
6324 genlshFour (result, left, shCount);
6327 fprintf(stderr, "*** ack! mystery literal shift!\n");
6331 freeAsmop (left, NULL, ic, TRUE);
6332 freeAsmop (result, NULL, ic, TRUE);
6335 /*-----------------------------------------------------------------*/
6336 /* genLeftShift - generates code for left shifting */
6337 /*-----------------------------------------------------------------*/
6339 genLeftShift (iCode * ic)
6341 operand *left, *right, *result;
6344 symbol *tlbl, *tlbl1;
6346 D(emitcode (";", "genLeftShift"));
6348 right = IC_RIGHT (ic);
6349 left = IC_LEFT (ic);
6350 result = IC_RESULT (ic);
6352 aopOp (right, ic, FALSE);
6354 /* if the shift count is known then do it
6355 as efficiently as possible */
6356 if (AOP_TYPE (right) == AOP_LIT)
6358 genLeftShiftLiteral (left, right, result, ic);
6362 /* shift count is unknown then we have to form
6363 a loop get the loop count in B : Note: we take
6364 only the lower order byte since shifting
6365 more that 32 bits make no sense anyway, ( the
6366 largest size of an object can be only 32 bits ) */
6368 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6369 emitcode ("inc", "b");
6370 freeAsmop (right, NULL, ic, TRUE);
6371 aopOp (left, ic, FALSE);
6372 aopOp (result, ic, FALSE);
6374 /* now move the left to the result if they are not the
6376 if (!sameRegs (AOP (left), AOP (result)) &&
6377 AOP_SIZE (result) > 1)
6380 size = AOP_SIZE (result);
6384 l = aopGet (AOP (left), offset, FALSE, TRUE);
6385 if (*l == '@' && (IS_AOP_PREG (result)))
6388 emitcode ("mov", "a,%s", l);
6389 aopPut (AOP (result), "a", offset);
6392 aopPut (AOP (result), l, offset);
6397 tlbl = newiTempLabel (NULL);
6398 size = AOP_SIZE (result);
6400 tlbl1 = newiTempLabel (NULL);
6402 /* if it is only one byte then */
6405 symbol *tlbl1 = newiTempLabel (NULL);
6407 l = aopGet (AOP (left), 0, FALSE, FALSE);
6409 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6410 emitcode ("", "%05d$:", tlbl->key + 100);
6411 emitcode ("add", "a,acc");
6412 emitcode ("", "%05d$:", tlbl1->key + 100);
6413 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6414 aopPut (AOP (result), "a", 0);
6418 reAdjustPreg (AOP (result));
6420 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6421 emitcode ("", "%05d$:", tlbl->key + 100);
6422 l = aopGet (AOP (result), offset, FALSE, FALSE);
6424 emitcode ("add", "a,acc");
6425 aopPut (AOP (result), "a", offset++);
6428 l = aopGet (AOP (result), offset, FALSE, FALSE);
6430 emitcode ("rlc", "a");
6431 aopPut (AOP (result), "a", offset++);
6433 reAdjustPreg (AOP (result));
6435 emitcode ("", "%05d$:", tlbl1->key + 100);
6436 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6438 freeAsmop (left, NULL, ic, TRUE);
6439 freeAsmop (result, NULL, ic, TRUE);
6442 /*-----------------------------------------------------------------*/
6443 /* genrshOne - right shift a one byte quantity by known count */
6444 /*-----------------------------------------------------------------*/
6446 genrshOne (operand * result, operand * left,
6447 int shCount, int sign)
6449 D(emitcode (";", "genrshOne"));
6451 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6454 /*-----------------------------------------------------------------*/
6455 /* genrshTwo - right shift two bytes by known amount != 0 */
6456 /*-----------------------------------------------------------------*/
6458 genrshTwo (operand * result, operand * left,
6459 int shCount, int sign)
6461 D(emitcode (";", "genrshTwo"));
6463 /* if shCount >= 8 */
6468 shiftR1Left2Result (left, MSB16, result, LSB,
6471 movLeft2Result (left, MSB16, result, LSB, sign);
6472 addSign (result, MSB16, sign);
6475 /* 1 <= shCount <= 7 */
6477 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6480 /*-----------------------------------------------------------------*/
6481 /* shiftRLong - shift right one long from left to result */
6482 /* offl = LSB or MSB16 */
6483 /*-----------------------------------------------------------------*/
6485 shiftRLong (operand * left, int offl,
6486 operand * result, int sign)
6488 int isSameRegs=sameRegs(AOP(left),AOP(result));
6490 if (isSameRegs && offl>1) {
6491 // we are in big trouble, but this shouldn't happen
6492 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6495 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6500 emitcode ("rlc", "a");
6501 emitcode ("subb", "a,acc");
6502 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6504 aopPut (AOP(result), zero, MSB32);
6509 emitcode ("clr", "c");
6511 emitcode ("mov", "c,acc.7");
6514 emitcode ("rrc", "a");
6516 if (isSameRegs && offl==MSB16) {
6517 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6519 aopPut (AOP (result), "a", MSB32);
6520 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6523 emitcode ("rrc", "a");
6524 if (isSameRegs && offl==1) {
6525 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6527 aopPut (AOP (result), "a", MSB24);
6528 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6530 emitcode ("rrc", "a");
6531 aopPut (AOP (result), "a", MSB16 - offl);
6535 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6536 emitcode ("rrc", "a");
6537 aopPut (AOP (result), "a", LSB);
6541 /*-----------------------------------------------------------------*/
6542 /* genrshFour - shift four byte by a known amount != 0 */
6543 /*-----------------------------------------------------------------*/
6545 genrshFour (operand * result, operand * left,
6546 int shCount, int sign)
6548 D(emitcode (";", "genrshFour"));
6550 /* if shifting more that 3 bytes */
6555 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6557 movLeft2Result (left, MSB32, result, LSB, sign);
6558 addSign (result, MSB16, sign);
6560 else if (shCount >= 16)
6564 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6567 movLeft2Result (left, MSB24, result, LSB, 0);
6568 movLeft2Result (left, MSB32, result, MSB16, sign);
6570 addSign (result, MSB24, sign);
6572 else if (shCount >= 8)
6576 shiftRLong (left, MSB16, result, sign);
6577 else if (shCount == 0)
6579 movLeft2Result (left, MSB16, result, LSB, 0);
6580 movLeft2Result (left, MSB24, result, MSB16, 0);
6581 movLeft2Result (left, MSB32, result, MSB24, sign);
6582 addSign (result, MSB32, sign);
6586 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6587 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6588 /* the last shift is signed */
6589 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6590 addSign (result, MSB32, sign);
6594 { /* 1 <= shCount <= 7 */
6597 shiftRLong (left, LSB, result, sign);
6599 shiftRLong (result, LSB, result, sign);
6603 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6604 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6605 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6610 /*-----------------------------------------------------------------*/
6611 /* genRightShiftLiteral - right shifting by known count */
6612 /*-----------------------------------------------------------------*/
6614 genRightShiftLiteral (operand * left,
6620 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6623 D(emitcode (";", "genRightShiftLiteral"));
6625 freeAsmop (right, NULL, ic, TRUE);
6627 aopOp (left, ic, FALSE);
6628 aopOp (result, ic, FALSE);
6631 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6635 size = getDataSize (left);
6636 /* test the LEFT size !!! */
6638 /* I suppose that the left size >= result size */
6641 size = getDataSize (result);
6643 movLeft2Result (left, size, result, size, 0);
6646 else if (shCount >= (size * 8))
6649 /* get sign in acc.7 */
6650 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6651 addSign (result, LSB, sign);
6658 genrshOne (result, left, shCount, sign);
6662 genrshTwo (result, left, shCount, sign);
6666 genrshFour (result, left, shCount, sign);
6672 freeAsmop (left, NULL, ic, TRUE);
6673 freeAsmop (result, NULL, ic, TRUE);
6677 /*-----------------------------------------------------------------*/
6678 /* genSignedRightShift - right shift of signed number */
6679 /*-----------------------------------------------------------------*/
6681 genSignedRightShift (iCode * ic)
6683 operand *right, *left, *result;
6686 symbol *tlbl, *tlbl1;
6688 D(emitcode (";", "genSignedRightShift"));
6690 /* we do it the hard way put the shift count in b
6691 and loop thru preserving the sign */
6693 right = IC_RIGHT (ic);
6694 left = IC_LEFT (ic);
6695 result = IC_RESULT (ic);
6697 aopOp (right, ic, FALSE);
6700 if (AOP_TYPE (right) == AOP_LIT)
6702 genRightShiftLiteral (left, right, result, ic, 1);
6705 /* shift count is unknown then we have to form
6706 a loop get the loop count in B : Note: we take
6707 only the lower order byte since shifting
6708 more that 32 bits make no sense anyway, ( the
6709 largest size of an object can be only 32 bits ) */
6711 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6712 emitcode ("inc", "b");
6713 freeAsmop (right, NULL, ic, TRUE);
6714 aopOp (left, ic, FALSE);
6715 aopOp (result, ic, FALSE);
6717 /* now move the left to the result if they are not the
6719 if (!sameRegs (AOP (left), AOP (result)) &&
6720 AOP_SIZE (result) > 1)
6723 size = AOP_SIZE (result);
6727 l = aopGet (AOP (left), offset, FALSE, TRUE);
6728 if (*l == '@' && IS_AOP_PREG (result))
6731 emitcode ("mov", "a,%s", l);
6732 aopPut (AOP (result), "a", offset);
6735 aopPut (AOP (result), l, offset);
6740 /* mov the highest order bit to OVR */
6741 tlbl = newiTempLabel (NULL);
6742 tlbl1 = newiTempLabel (NULL);
6744 size = AOP_SIZE (result);
6746 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6747 emitcode ("rlc", "a");
6748 emitcode ("mov", "ov,c");
6749 /* if it is only one byte then */
6752 l = aopGet (AOP (left), 0, FALSE, FALSE);
6754 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6755 emitcode ("", "%05d$:", tlbl->key + 100);
6756 emitcode ("mov", "c,ov");
6757 emitcode ("rrc", "a");
6758 emitcode ("", "%05d$:", tlbl1->key + 100);
6759 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6760 aopPut (AOP (result), "a", 0);
6764 reAdjustPreg (AOP (result));
6765 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6766 emitcode ("", "%05d$:", tlbl->key + 100);
6767 emitcode ("mov", "c,ov");
6770 l = aopGet (AOP (result), offset, FALSE, FALSE);
6772 emitcode ("rrc", "a");
6773 aopPut (AOP (result), "a", offset--);
6775 reAdjustPreg (AOP (result));
6776 emitcode ("", "%05d$:", tlbl1->key + 100);
6777 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6780 freeAsmop (left, NULL, ic, TRUE);
6781 freeAsmop (result, NULL, ic, TRUE);
6784 /*-----------------------------------------------------------------*/
6785 /* genRightShift - generate code for right shifting */
6786 /*-----------------------------------------------------------------*/
6788 genRightShift (iCode * ic)
6790 operand *right, *left, *result;
6794 symbol *tlbl, *tlbl1;
6796 D(emitcode (";", "genRightShift"));
6798 /* if signed then we do it the hard way preserve the
6799 sign bit moving it inwards */
6800 retype = getSpec (operandType (IC_RESULT (ic)));
6802 if (!SPEC_USIGN (retype))
6804 genSignedRightShift (ic);
6808 /* signed & unsigned types are treated the same : i.e. the
6809 signed is NOT propagated inwards : quoting from the
6810 ANSI - standard : "for E1 >> E2, is equivalent to division
6811 by 2**E2 if unsigned or if it has a non-negative value,
6812 otherwise the result is implementation defined ", MY definition
6813 is that the sign does not get propagated */
6815 right = IC_RIGHT (ic);
6816 left = IC_LEFT (ic);
6817 result = IC_RESULT (ic);
6819 aopOp (right, ic, FALSE);
6821 /* if the shift count is known then do it
6822 as efficiently as possible */
6823 if (AOP_TYPE (right) == AOP_LIT)
6825 genRightShiftLiteral (left, right, result, ic, 0);
6829 /* shift count is unknown then we have to form
6830 a loop get the loop count in B : Note: we take
6831 only the lower order byte since shifting
6832 more that 32 bits make no sense anyway, ( the
6833 largest size of an object can be only 32 bits ) */
6835 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6836 emitcode ("inc", "b");
6837 freeAsmop (right, NULL, ic, TRUE);
6838 aopOp (left, ic, FALSE);
6839 aopOp (result, ic, FALSE);
6841 /* now move the left to the result if they are not the
6843 if (!sameRegs (AOP (left), AOP (result)) &&
6844 AOP_SIZE (result) > 1)
6847 size = AOP_SIZE (result);
6851 l = aopGet (AOP (left), offset, FALSE, TRUE);
6852 if (*l == '@' && IS_AOP_PREG (result))
6855 emitcode ("mov", "a,%s", l);
6856 aopPut (AOP (result), "a", offset);
6859 aopPut (AOP (result), l, offset);
6864 tlbl = newiTempLabel (NULL);
6865 tlbl1 = newiTempLabel (NULL);
6866 size = AOP_SIZE (result);
6869 /* if it is only one byte then */
6872 l = aopGet (AOP (left), 0, FALSE, FALSE);
6874 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6875 emitcode ("", "%05d$:", tlbl->key + 100);
6877 emitcode ("rrc", "a");
6878 emitcode ("", "%05d$:", tlbl1->key + 100);
6879 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6880 aopPut (AOP (result), "a", 0);
6884 reAdjustPreg (AOP (result));
6885 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6886 emitcode ("", "%05d$:", tlbl->key + 100);
6890 l = aopGet (AOP (result), offset, FALSE, FALSE);
6892 emitcode ("rrc", "a");
6893 aopPut (AOP (result), "a", offset--);
6895 reAdjustPreg (AOP (result));
6897 emitcode ("", "%05d$:", tlbl1->key + 100);
6898 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6901 freeAsmop (left, NULL, ic, TRUE);
6902 freeAsmop (result, NULL, ic, TRUE);
6905 /*-----------------------------------------------------------------*/
6906 /* genUnpackBits - generates code for unpacking bits */
6907 /*-----------------------------------------------------------------*/
6909 genUnpackBits (operand * result, char *rname, int ptype)
6917 D(emitcode (";", "genUnpackBits"));
6919 etype = getSpec (operandType (result));
6920 rsize = getSize (operandType (result));
6921 /* read the first byte */
6927 emitcode ("mov", "a,@%s", rname);
6931 emitcode ("movx", "a,@%s", rname);
6935 emitcode ("movx", "a,@dptr");
6939 emitcode ("clr", "a");
6940 emitcode ("movc", "a,@a+dptr");
6944 emitcode ("lcall", "__gptrget");
6948 rlen = SPEC_BLEN (etype);
6950 /* if we have bitdisplacement then it fits */
6951 /* into this byte completely or if length is */
6952 /* less than a byte */
6953 if ((shCnt = SPEC_BSTR (etype)) ||
6954 (SPEC_BLEN (etype) <= 8))
6957 /* shift right acc */
6960 emitcode ("anl", "a,#0x%02x",
6961 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6962 aopPut (AOP (result), "a", offset++);
6966 /* bit field did not fit in a byte */
6967 aopPut (AOP (result), "a", offset++);
6976 emitcode ("inc", "%s", rname);
6977 emitcode ("mov", "a,@%s", rname);
6981 emitcode ("inc", "%s", rname);
6982 emitcode ("movx", "a,@%s", rname);
6986 emitcode ("inc", "dptr");
6987 emitcode ("movx", "a,@dptr");
6991 emitcode ("clr", "a");
6992 emitcode ("inc", "dptr");
6993 emitcode ("movc", "a,@a+dptr");
6997 emitcode ("inc", "dptr");
6998 emitcode ("lcall", "__gptrget");
7003 /* if we are done */
7007 aopPut (AOP (result), "a", offset++);
7013 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7015 aopPut (AOP (result), "a", offset++);
7023 aopPut (AOP (result), zero, offset++);
7029 /*-----------------------------------------------------------------*/
7030 /* genDataPointerGet - generates code when ptr offset is known */
7031 /*-----------------------------------------------------------------*/
7033 genDataPointerGet (operand * left,
7039 int size, offset = 0;
7041 D(emitcode (";", "genDataPointerGet"));
7043 aopOp (result, ic, TRUE);
7045 /* get the string representation of the name */
7046 l = aopGet (AOP (left), 0, FALSE, TRUE);
7047 size = AOP_SIZE (result);
7051 sprintf (buffer, "(%s + %d)", l + 1, offset);
7053 sprintf (buffer, "%s", l + 1);
7054 aopPut (AOP (result), buffer, offset++);
7057 freeAsmop (left, NULL, ic, TRUE);
7058 freeAsmop (result, NULL, ic, TRUE);
7061 /*-----------------------------------------------------------------*/
7062 /* genNearPointerGet - emitcode for near pointer fetch */
7063 /*-----------------------------------------------------------------*/
7065 genNearPointerGet (operand * left,
7073 sym_link *rtype, *retype;
7074 sym_link *ltype = operandType (left);
7077 D(emitcode (";", "genNearPointerGet"));
7079 rtype = operandType (result);
7080 retype = getSpec (rtype);
7082 aopOp (left, ic, FALSE);
7084 /* if left is rematerialisable and
7085 result is not bit variable type and
7086 the left is pointer to data space i.e
7087 lower 128 bytes of space */
7088 if (AOP_TYPE (left) == AOP_IMMD &&
7089 !IS_BITVAR (retype) &&
7090 DCL_TYPE (ltype) == POINTER)
7092 genDataPointerGet (left, result, ic);
7096 /* if the value is already in a pointer register
7097 then don't need anything more */
7098 if (!AOP_INPREG (AOP (left)))
7100 /* otherwise get a free pointer register */
7102 preg = getFreePtr (ic, &aop, FALSE);
7103 emitcode ("mov", "%s,%s",
7105 aopGet (AOP (left), 0, FALSE, TRUE));
7109 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7111 //aopOp (result, ic, FALSE);
7112 aopOp (result, ic, result?TRUE:FALSE);
7114 /* if bitfield then unpack the bits */
7115 if (IS_BITVAR (retype))
7116 genUnpackBits (result, rname, POINTER);
7119 /* we have can just get the values */
7120 int size = AOP_SIZE (result);
7125 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7128 emitcode ("mov", "a,@%s", rname);
7129 aopPut (AOP (result), "a", offset);
7133 sprintf (buffer, "@%s", rname);
7134 aopPut (AOP (result), buffer, offset);
7138 emitcode ("inc", "%s", rname);
7142 /* now some housekeeping stuff */
7143 if (aop) /* we had to allocate for this iCode */
7145 if (pi) { /* post increment present */
7146 aopPut(AOP ( left ),rname,0);
7148 freeAsmop (NULL, aop, ic, TRUE);
7152 /* we did not allocate which means left
7153 already in a pointer register, then
7154 if size > 0 && this could be used again
7155 we have to point it back to where it
7157 if ((AOP_SIZE (result) > 1 &&
7158 !OP_SYMBOL (left)->remat &&
7159 (OP_SYMBOL (left)->liveTo > ic->seq ||
7163 int size = AOP_SIZE (result) - 1;
7165 emitcode ("dec", "%s", rname);
7170 freeAsmop (left, NULL, ic, TRUE);
7171 freeAsmop (result, NULL, ic, TRUE);
7172 if (pi) pi->generated = 1;
7175 /*-----------------------------------------------------------------*/
7176 /* genPagedPointerGet - emitcode for paged pointer fetch */
7177 /*-----------------------------------------------------------------*/
7179 genPagedPointerGet (operand * left,
7187 sym_link *rtype, *retype;
7189 D(emitcode (";", "genPagedPointerGet"));
7191 rtype = operandType (result);
7192 retype = getSpec (rtype);
7194 aopOp (left, ic, FALSE);
7196 /* if the value is already in a pointer register
7197 then don't need anything more */
7198 if (!AOP_INPREG (AOP (left)))
7200 /* otherwise get a free pointer register */
7202 preg = getFreePtr (ic, &aop, FALSE);
7203 emitcode ("mov", "%s,%s",
7205 aopGet (AOP (left), 0, FALSE, TRUE));
7209 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7211 aopOp (result, ic, FALSE);
7213 /* if bitfield then unpack the bits */
7214 if (IS_BITVAR (retype))
7215 genUnpackBits (result, rname, PPOINTER);
7218 /* we have can just get the values */
7219 int size = AOP_SIZE (result);
7225 emitcode ("movx", "a,@%s", rname);
7226 aopPut (AOP (result), "a", offset);
7231 emitcode ("inc", "%s", rname);
7235 /* now some housekeeping stuff */
7236 if (aop) /* we had to allocate for this iCode */
7238 if (pi) aopPut ( AOP (left), rname, 0);
7239 freeAsmop (NULL, aop, ic, TRUE);
7243 /* we did not allocate which means left
7244 already in a pointer register, then
7245 if size > 0 && this could be used again
7246 we have to point it back to where it
7248 if ((AOP_SIZE (result) > 1 &&
7249 !OP_SYMBOL (left)->remat &&
7250 (OP_SYMBOL (left)->liveTo > ic->seq ||
7254 int size = AOP_SIZE (result) - 1;
7256 emitcode ("dec", "%s", rname);
7261 freeAsmop (left, NULL, ic, TRUE);
7262 freeAsmop (result, NULL, ic, TRUE);
7263 if (pi) pi->generated = 1;
7267 /*-----------------------------------------------------------------*/
7268 /* genFarPointerGet - gget value from far space */
7269 /*-----------------------------------------------------------------*/
7271 genFarPointerGet (operand * left,
7272 operand * result, iCode * ic, iCode * pi)
7275 sym_link *retype = getSpec (operandType (result));
7277 D(emitcode (";", "genFarPointerGet"));
7279 aopOp (left, ic, FALSE);
7281 /* if the operand is already in dptr
7282 then we do nothing else we move the value to dptr */
7283 if (AOP_TYPE (left) != AOP_STR)
7285 /* if this is remateriazable */
7286 if (AOP_TYPE (left) == AOP_IMMD)
7287 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7289 { /* we need to get it byte by byte */
7290 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7291 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7294 /* so dptr know contains the address */
7295 aopOp (result, ic, FALSE);
7297 /* if bit then unpack */
7298 if (IS_BITVAR (retype))
7299 genUnpackBits (result, "dptr", FPOINTER);
7302 size = AOP_SIZE (result);
7307 emitcode ("movx", "a,@dptr");
7308 aopPut (AOP (result), "a", offset++);
7310 emitcode ("inc", "dptr");
7314 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7315 aopPut ( AOP (left), "dpl", 0);
7316 aopPut ( AOP (left), "dph", 1);
7319 freeAsmop (left, NULL, ic, TRUE);
7320 freeAsmop (result, NULL, ic, TRUE);
7323 /*-----------------------------------------------------------------*/
7324 /* genCodePointerGet - gget value from code space */
7325 /*-----------------------------------------------------------------*/
7327 genCodePointerGet (operand * left,
7328 operand * result, iCode * ic, iCode *pi)
7331 sym_link *retype = getSpec (operandType (result));
7333 D(emitcode (";", "genCodePointerGet"));
7335 aopOp (left, ic, FALSE);
7337 /* if the operand is already in dptr
7338 then we do nothing else we move the value to dptr */
7339 if (AOP_TYPE (left) != AOP_STR)
7341 /* if this is remateriazable */
7342 if (AOP_TYPE (left) == AOP_IMMD)
7343 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7345 { /* we need to get it byte by byte */
7346 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7347 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7350 /* so dptr know contains the address */
7351 aopOp (result, ic, FALSE);
7353 /* if bit then unpack */
7354 if (IS_BITVAR (retype))
7355 genUnpackBits (result, "dptr", CPOINTER);
7358 size = AOP_SIZE (result);
7363 emitcode ("clr", "a");
7364 emitcode ("movc", "a,@a+dptr");
7365 aopPut (AOP (result), "a", offset++);
7367 emitcode ("inc", "dptr");
7371 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7372 aopPut ( AOP (left), "dpl", 0);
7373 aopPut ( AOP (left), "dph", 1);
7376 freeAsmop (left, NULL, ic, TRUE);
7377 freeAsmop (result, NULL, ic, TRUE);
7380 /*-----------------------------------------------------------------*/
7381 /* genGenPointerGet - gget value from generic pointer space */
7382 /*-----------------------------------------------------------------*/
7384 genGenPointerGet (operand * left,
7385 operand * result, iCode * ic, iCode *pi)
7388 sym_link *retype = getSpec (operandType (result));
7390 D(emitcode (";", "genGenPointerGet"));
7392 aopOp (left, ic, FALSE);
7394 /* if the operand is already in dptr
7395 then we do nothing else we move the value to dptr */
7396 if (AOP_TYPE (left) != AOP_STR)
7398 /* if this is remateriazable */
7399 if (AOP_TYPE (left) == AOP_IMMD)
7401 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7402 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7403 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7405 emitcode ("mov", "b,#%d", pointerCode (retype));
7408 { /* we need to get it byte by byte */
7409 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7410 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7411 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7414 /* so dptr know contains the address */
7415 aopOp (result, ic, FALSE);
7417 /* if bit then unpack */
7418 if (IS_BITVAR (retype))
7419 genUnpackBits (result, "dptr", GPOINTER);
7422 size = AOP_SIZE (result);
7427 emitcode ("lcall", "__gptrget");
7428 aopPut (AOP (result), "a", offset++);
7430 emitcode ("inc", "dptr");
7434 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7435 aopPut ( AOP (left), "dpl", 0);
7436 aopPut ( AOP (left), "dph", 1);
7437 aopPut ( AOP (left), "b", 2);
7440 freeAsmop (left, NULL, ic, TRUE);
7441 freeAsmop (result, NULL, ic, TRUE);
7444 /*-----------------------------------------------------------------*/
7445 /* genPointerGet - generate code for pointer get */
7446 /*-----------------------------------------------------------------*/
7448 genPointerGet (iCode * ic, iCode *pi)
7450 operand *left, *result;
7451 sym_link *type, *etype;
7454 D(emitcode (";", "genPointerGet"));
7456 left = IC_LEFT (ic);
7457 result = IC_RESULT (ic);
7459 /* depending on the type of pointer we need to
7460 move it to the correct pointer register */
7461 type = operandType (left);
7462 etype = getSpec (type);
7463 /* if left is of type of pointer then it is simple */
7464 if (IS_PTR (type) && !IS_FUNC (type->next))
7465 p_type = DCL_TYPE (type);
7468 /* we have to go by the storage class */
7469 p_type = PTR_TYPE (SPEC_OCLS (etype));
7472 /* special case when cast remat */
7473 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7474 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7475 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7476 type = type = operandType (left);
7477 p_type = DCL_TYPE (type);
7479 /* now that we have the pointer type we assign
7480 the pointer values */
7486 genNearPointerGet (left, result, ic, pi);
7490 genPagedPointerGet (left, result, ic, pi);
7494 genFarPointerGet (left, result, ic, pi);
7498 genCodePointerGet (left, result, ic, pi);
7502 genGenPointerGet (left, result, ic, pi);
7508 /*-----------------------------------------------------------------*/
7509 /* genPackBits - generates code for packed bit storage */
7510 /*-----------------------------------------------------------------*/
7512 genPackBits (sym_link * etype,
7514 char *rname, int p_type)
7522 D(emitcode (";", "genPackBits"));
7524 blen = SPEC_BLEN (etype);
7525 bstr = SPEC_BSTR (etype);
7527 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7530 /* if the bit lenth is less than or */
7531 /* it exactly fits a byte then */
7532 if (SPEC_BLEN (etype) <= 8)
7534 shCount = SPEC_BSTR (etype);
7536 /* shift left acc */
7539 if (SPEC_BLEN (etype) < 8)
7540 { /* if smaller than a byte */
7546 emitcode ("mov", "b,a");
7547 emitcode ("mov", "a,@%s", rname);
7551 emitcode ("mov", "b,a");
7552 emitcode ("movx", "a,@dptr");
7556 emitcode ("push", "b");
7557 emitcode ("push", "acc");
7558 emitcode ("lcall", "__gptrget");
7559 emitcode ("pop", "b");
7563 emitcode ("anl", "a,#0x%02x", (unsigned char)
7564 ((unsigned char) (0xFF << (blen + bstr)) |
7565 (unsigned char) (0xFF >> (8 - bstr))));
7566 emitcode ("orl", "a,b");
7567 if (p_type == GPOINTER)
7568 emitcode ("pop", "b");
7575 emitcode ("mov", "@%s,a", rname);
7579 emitcode ("movx", "@dptr,a");
7583 emitcode ("lcall", "__gptrput");
7588 if (SPEC_BLEN (etype) <= 8)
7591 emitcode ("inc", "%s", rname);
7592 rLen = SPEC_BLEN (etype);
7594 /* now generate for lengths greater than one byte */
7598 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7610 emitcode ("mov", "@%s,a", rname);
7613 emitcode ("mov", "@%s,%s", rname, l);
7618 emitcode ("movx", "@dptr,a");
7623 emitcode ("lcall", "__gptrput");
7626 emitcode ("inc", "%s", rname);
7631 /* last last was not complete */
7634 /* save the byte & read byte */
7638 emitcode ("mov", "b,a");
7639 emitcode ("mov", "a,@%s", rname);
7643 emitcode ("mov", "b,a");
7644 emitcode ("movx", "a,@dptr");
7648 emitcode ("push", "b");
7649 emitcode ("push", "acc");
7650 emitcode ("lcall", "__gptrget");
7651 emitcode ("pop", "b");
7655 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7656 emitcode ("orl", "a,b");
7659 if (p_type == GPOINTER)
7660 emitcode ("pop", "b");
7666 emitcode ("mov", "@%s,a", rname);
7670 emitcode ("movx", "@dptr,a");
7674 emitcode ("lcall", "__gptrput");
7678 /*-----------------------------------------------------------------*/
7679 /* genDataPointerSet - remat pointer to data space */
7680 /*-----------------------------------------------------------------*/
7682 genDataPointerSet (operand * right,
7686 int size, offset = 0;
7687 char *l, buffer[256];
7689 D(emitcode (";", "genDataPointerSet"));
7691 aopOp (right, ic, FALSE);
7693 l = aopGet (AOP (result), 0, FALSE, TRUE);
7694 size = AOP_SIZE (right);
7698 sprintf (buffer, "(%s + %d)", l + 1, offset);
7700 sprintf (buffer, "%s", l + 1);
7701 emitcode ("mov", "%s,%s", buffer,
7702 aopGet (AOP (right), offset++, FALSE, FALSE));
7705 freeAsmop (right, NULL, ic, TRUE);
7706 freeAsmop (result, NULL, ic, TRUE);
7709 /*-----------------------------------------------------------------*/
7710 /* genNearPointerSet - emitcode for near pointer put */
7711 /*-----------------------------------------------------------------*/
7713 genNearPointerSet (operand * right,
7721 sym_link *retype, *letype;
7722 sym_link *ptype = operandType (result);
7724 D(emitcode (";", "genNearPointerSet"));
7726 retype = getSpec (operandType (right));
7727 letype = getSpec (ptype);
7728 aopOp (result, ic, FALSE);
7730 /* if the result is rematerializable &
7731 in data space & not a bit variable */
7732 if (AOP_TYPE (result) == AOP_IMMD &&
7733 DCL_TYPE (ptype) == POINTER &&
7734 !IS_BITVAR (retype) &&
7735 !IS_BITVAR (letype))
7737 genDataPointerSet (right, result, ic);
7741 /* if the value is already in a pointer register
7742 then don't need anything more */
7743 if (!AOP_INPREG (AOP (result)))
7746 //AOP_TYPE (result) == AOP_STK
7750 // Aha, it is a pointer, just in disguise.
7751 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7754 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7755 __FILE__, __LINE__);
7760 rname++; // skip the '@'.
7765 /* otherwise get a free pointer register */
7767 preg = getFreePtr (ic, &aop, FALSE);
7768 emitcode ("mov", "%s,%s",
7770 aopGet (AOP (result), 0, FALSE, TRUE));
7776 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7779 aopOp (right, ic, FALSE);
7781 /* if bitfield then unpack the bits */
7782 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7783 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7786 /* we have can just get the values */
7787 int size = AOP_SIZE (right);
7792 l = aopGet (AOP (right), offset, FALSE, TRUE);
7796 emitcode ("mov", "@%s,a", rname);
7799 emitcode ("mov", "@%s,%s", rname, l);
7801 emitcode ("inc", "%s", rname);
7806 /* now some housekeeping stuff */
7807 if (aop) /* we had to allocate for this iCode */
7809 if (pi) aopPut (AOP (result),rname,0);
7810 freeAsmop (NULL, aop, ic, TRUE);
7814 /* we did not allocate which means left
7815 already in a pointer register, then
7816 if size > 0 && this could be used again
7817 we have to point it back to where it
7819 if ((AOP_SIZE (right) > 1 &&
7820 !OP_SYMBOL (result)->remat &&
7821 (OP_SYMBOL (result)->liveTo > ic->seq ||
7825 int size = AOP_SIZE (right) - 1;
7827 emitcode ("dec", "%s", rname);
7832 if (pi) pi->generated = 1;
7833 freeAsmop (result, NULL, ic, TRUE);
7834 freeAsmop (right, NULL, ic, TRUE);
7837 /*-----------------------------------------------------------------*/
7838 /* genPagedPointerSet - emitcode for Paged pointer put */
7839 /*-----------------------------------------------------------------*/
7841 genPagedPointerSet (operand * right,
7849 sym_link *retype, *letype;
7851 D(emitcode (";", "genPagedPointerSet"));
7853 retype = getSpec (operandType (right));
7854 letype = getSpec (operandType (result));
7856 aopOp (result, ic, FALSE);
7858 /* if the value is already in a pointer register
7859 then don't need anything more */
7860 if (!AOP_INPREG (AOP (result)))
7862 /* otherwise get a free pointer register */
7864 preg = getFreePtr (ic, &aop, FALSE);
7865 emitcode ("mov", "%s,%s",
7867 aopGet (AOP (result), 0, FALSE, TRUE));
7871 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7873 aopOp (right, ic, FALSE);
7875 /* if bitfield then unpack the bits */
7876 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7877 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7880 /* we have can just get the values */
7881 int size = AOP_SIZE (right);
7886 l = aopGet (AOP (right), offset, FALSE, TRUE);
7889 emitcode ("movx", "@%s,a", rname);
7892 emitcode ("inc", "%s", rname);
7898 /* now some housekeeping stuff */
7899 if (aop) /* we had to allocate for this iCode */
7901 if (pi) aopPut (AOP (result),rname,0);
7902 freeAsmop (NULL, aop, ic, TRUE);
7906 /* we did not allocate which means left
7907 already in a pointer register, then
7908 if size > 0 && this could be used again
7909 we have to point it back to where it
7911 if (AOP_SIZE (right) > 1 &&
7912 !OP_SYMBOL (result)->remat &&
7913 (OP_SYMBOL (result)->liveTo > ic->seq ||
7916 int size = AOP_SIZE (right) - 1;
7918 emitcode ("dec", "%s", rname);
7923 if (pi) pi->generated = 1;
7924 freeAsmop (result, NULL, ic, TRUE);
7925 freeAsmop (right, NULL, ic, TRUE);
7930 /*-----------------------------------------------------------------*/
7931 /* genFarPointerSet - set value from far space */
7932 /*-----------------------------------------------------------------*/
7934 genFarPointerSet (operand * right,
7935 operand * result, iCode * ic, iCode * pi)
7938 sym_link *retype = getSpec (operandType (right));
7939 sym_link *letype = getSpec (operandType (result));
7941 D(emitcode (";", "genFarPointerSet"));
7943 aopOp (result, ic, FALSE);
7945 /* if the operand is already in dptr
7946 then we do nothing else we move the value to dptr */
7947 if (AOP_TYPE (result) != AOP_STR)
7949 /* if this is remateriazable */
7950 if (AOP_TYPE (result) == AOP_IMMD)
7951 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7953 { /* we need to get it byte by byte */
7954 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7955 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7958 /* so dptr know contains the address */
7959 aopOp (right, ic, FALSE);
7961 /* if bit then unpack */
7962 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7963 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7966 size = AOP_SIZE (right);
7971 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7973 emitcode ("movx", "@dptr,a");
7975 emitcode ("inc", "dptr");
7978 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7979 aopPut (AOP(result),"dpl",0);
7980 aopPut (AOP(result),"dph",1);
7983 freeAsmop (result, NULL, ic, TRUE);
7984 freeAsmop (right, NULL, ic, TRUE);
7987 /*-----------------------------------------------------------------*/
7988 /* genGenPointerSet - set value from generic pointer space */
7989 /*-----------------------------------------------------------------*/
7991 genGenPointerSet (operand * right,
7992 operand * result, iCode * ic, iCode * pi)
7995 sym_link *retype = getSpec (operandType (right));
7996 sym_link *letype = getSpec (operandType (result));
7998 D(emitcode (";", "genGenPointerSet"));
8000 aopOp (result, ic, FALSE);
8002 /* if the operand is already in dptr
8003 then we do nothing else we move the value to dptr */
8004 if (AOP_TYPE (result) != AOP_STR)
8006 /* if this is remateriazable */
8007 if (AOP_TYPE (result) == AOP_IMMD)
8009 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8010 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8011 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8013 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8016 { /* we need to get it byte by byte */
8017 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8018 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8019 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8022 /* so dptr know contains the address */
8023 aopOp (right, ic, FALSE);
8025 /* if bit then unpack */
8026 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8027 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8030 size = AOP_SIZE (right);
8035 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8037 emitcode ("lcall", "__gptrput");
8039 emitcode ("inc", "dptr");
8043 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8044 aopPut (AOP(result),"dpl",0);
8045 aopPut (AOP(result),"dph",1);
8046 aopPut (AOP(result),"b",2);
8049 freeAsmop (result, NULL, ic, TRUE);
8050 freeAsmop (right, NULL, ic, TRUE);
8053 /*-----------------------------------------------------------------*/
8054 /* genPointerSet - stores the value into a pointer location */
8055 /*-----------------------------------------------------------------*/
8057 genPointerSet (iCode * ic, iCode *pi)
8059 operand *right, *result;
8060 sym_link *type, *etype;
8063 D(emitcode (";", "genPointerSet"));
8065 right = IC_RIGHT (ic);
8066 result = IC_RESULT (ic);
8068 /* depending on the type of pointer we need to
8069 move it to the correct pointer register */
8070 type = operandType (result);
8071 etype = getSpec (type);
8072 /* if left is of type of pointer then it is simple */
8073 if (IS_PTR (type) && !IS_FUNC (type->next))
8075 p_type = DCL_TYPE (type);
8079 /* we have to go by the storage class */
8080 p_type = PTR_TYPE (SPEC_OCLS (etype));
8083 /* special case when cast remat */
8084 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8085 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8086 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8087 type = type = operandType (result);
8088 p_type = DCL_TYPE (type);
8090 /* now that we have the pointer type we assign
8091 the pointer values */
8097 genNearPointerSet (right, result, ic, pi);
8101 genPagedPointerSet (right, result, ic, pi);
8105 genFarPointerSet (right, result, ic, pi);
8109 genGenPointerSet (right, result, ic, pi);
8115 /*-----------------------------------------------------------------*/
8116 /* genIfx - generate code for Ifx statement */
8117 /*-----------------------------------------------------------------*/
8119 genIfx (iCode * ic, iCode * popIc)
8121 operand *cond = IC_COND (ic);
8124 D(emitcode (";", "genIfx"));
8126 aopOp (cond, ic, FALSE);
8128 /* get the value into acc */
8129 if (AOP_TYPE (cond) != AOP_CRY)
8133 /* the result is now in the accumulator */
8134 freeAsmop (cond, NULL, ic, TRUE);
8136 /* if there was something to be popped then do it */
8140 /* if the condition is a bit variable */
8141 if (isbit && IS_ITEMP (cond) &&
8143 genIfxJump (ic, SPIL_LOC (cond)->rname);
8144 else if (isbit && !IS_ITEMP (cond))
8145 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8147 genIfxJump (ic, "a");
8152 /*-----------------------------------------------------------------*/
8153 /* genAddrOf - generates code for address of */
8154 /*-----------------------------------------------------------------*/
8156 genAddrOf (iCode * ic)
8158 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8161 D(emitcode (";", "genAddrOf"));
8163 aopOp (IC_RESULT (ic), ic, FALSE);
8165 /* if the operand is on the stack then we
8166 need to get the stack offset of this
8170 /* if it has an offset then we need to compute
8174 emitcode ("mov", "a,_bp");
8175 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8176 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8180 /* we can just move _bp */
8181 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8183 /* fill the result with zero */
8184 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8189 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8195 /* object not on stack then we need the name */
8196 size = AOP_SIZE (IC_RESULT (ic));
8201 char s[SDCC_NAME_MAX];
8203 sprintf (s, "#(%s >> %d)",
8207 sprintf (s, "#%s", sym->rname);
8208 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8212 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8216 /*-----------------------------------------------------------------*/
8217 /* genFarFarAssign - assignment when both are in far space */
8218 /*-----------------------------------------------------------------*/
8220 genFarFarAssign (operand * result, operand * right, iCode * ic)
8222 int size = AOP_SIZE (right);
8226 D(emitcode (";", "genFarFarAssign"));
8228 /* first push the right side on to the stack */
8231 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8233 emitcode ("push", "acc");
8236 freeAsmop (right, NULL, ic, FALSE);
8237 /* now assign DPTR to result */
8238 aopOp (result, ic, FALSE);
8239 size = AOP_SIZE (result);
8242 emitcode ("pop", "acc");
8243 aopPut (AOP (result), "a", --offset);
8245 freeAsmop (result, NULL, ic, FALSE);
8249 /*-----------------------------------------------------------------*/
8250 /* genAssign - generate code for assignment */
8251 /*-----------------------------------------------------------------*/
8253 genAssign (iCode * ic)
8255 operand *result, *right;
8257 unsigned long lit = 0L;
8259 D(emitcode(";","genAssign"));
8261 result = IC_RESULT (ic);
8262 right = IC_RIGHT (ic);
8264 /* if they are the same */
8265 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8268 aopOp (right, ic, FALSE);
8270 /* special case both in far space */
8271 if (AOP_TYPE (right) == AOP_DPTR &&
8272 IS_TRUE_SYMOP (result) &&
8273 isOperandInFarSpace (result))
8276 genFarFarAssign (result, right, ic);
8280 aopOp (result, ic, TRUE);
8282 /* if they are the same registers */
8283 if (sameRegs (AOP (right), AOP (result)))
8286 /* if the result is a bit */
8287 if (AOP_TYPE (result) == AOP_CRY)
8290 /* if the right size is a literal then
8291 we know what the value is */
8292 if (AOP_TYPE (right) == AOP_LIT)
8294 if (((int) operandLitValue (right)))
8295 aopPut (AOP (result), one, 0);
8297 aopPut (AOP (result), zero, 0);
8301 /* the right is also a bit variable */
8302 if (AOP_TYPE (right) == AOP_CRY)
8304 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8305 aopPut (AOP (result), "c", 0);
8311 aopPut (AOP (result), "a", 0);
8315 /* bit variables done */
8317 size = AOP_SIZE (result);
8319 if (AOP_TYPE (right) == AOP_LIT)
8320 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8322 (AOP_TYPE (result) != AOP_REG) &&
8323 (AOP_TYPE (right) == AOP_LIT) &&
8324 !IS_FLOAT (operandType (right)) &&
8327 emitcode ("clr", "a");
8330 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8331 aopPut (AOP (result), "a", size);
8333 aopPut (AOP (result),
8334 aopGet (AOP (right), size, FALSE, FALSE),
8342 aopPut (AOP (result),
8343 aopGet (AOP (right), offset, FALSE, FALSE),
8350 freeAsmop (right, NULL, ic, TRUE);
8351 freeAsmop (result, NULL, ic, TRUE);
8354 /*-----------------------------------------------------------------*/
8355 /* genJumpTab - genrates code for jump table */
8356 /*-----------------------------------------------------------------*/
8358 genJumpTab (iCode * ic)
8363 D(emitcode (";", "genJumpTab"));
8365 aopOp (IC_JTCOND (ic), ic, FALSE);
8366 /* get the condition into accumulator */
8367 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8369 /* multiply by three */
8370 emitcode ("add", "a,acc");
8371 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8372 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8374 jtab = newiTempLabel (NULL);
8375 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8376 emitcode ("jmp", "@a+dptr");
8377 emitcode ("", "%05d$:", jtab->key + 100);
8378 /* now generate the jump labels */
8379 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8380 jtab = setNextItem (IC_JTLABELS (ic)))
8381 emitcode ("ljmp", "%05d$", jtab->key + 100);
8385 /*-----------------------------------------------------------------*/
8386 /* genCast - gen code for casting */
8387 /*-----------------------------------------------------------------*/
8389 genCast (iCode * ic)
8391 operand *result = IC_RESULT (ic);
8392 sym_link *ctype = operandType (IC_LEFT (ic));
8393 sym_link *rtype = operandType (IC_RIGHT (ic));
8394 operand *right = IC_RIGHT (ic);
8397 D(emitcode(";", "genCast"));
8399 /* if they are equivalent then do nothing */
8400 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8403 aopOp (right, ic, FALSE);
8404 aopOp (result, ic, FALSE);
8406 /* if the result is a bit */
8407 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8408 if (IS_BITVAR(OP_SYMBOL(result)->type))
8410 /* if the right size is a literal then
8411 we know what the value is */
8412 if (AOP_TYPE (right) == AOP_LIT)
8414 if (((int) operandLitValue (right)))
8415 aopPut (AOP (result), one, 0);
8417 aopPut (AOP (result), zero, 0);
8422 /* the right is also a bit variable */
8423 if (AOP_TYPE (right) == AOP_CRY)
8425 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8426 aopPut (AOP (result), "c", 0);
8432 aopPut (AOP (result), "a", 0);
8436 /* if they are the same size : or less */
8437 if (AOP_SIZE (result) <= AOP_SIZE (right))
8440 /* if they are in the same place */
8441 if (sameRegs (AOP (right), AOP (result)))
8444 /* if they in different places then copy */
8445 size = AOP_SIZE (result);
8449 aopPut (AOP (result),
8450 aopGet (AOP (right), offset, FALSE, FALSE),
8458 /* if the result is of type pointer */
8463 sym_link *type = operandType (right);
8464 sym_link *etype = getSpec (type);
8466 /* pointer to generic pointer */
8467 if (IS_GENPTR (ctype))
8472 p_type = DCL_TYPE (type);
8475 if (SPEC_SCLS(etype)==S_REGISTER) {
8476 // let's assume it is a generic pointer
8479 /* we have to go by the storage class */
8480 p_type = PTR_TYPE (SPEC_OCLS (etype));
8484 /* the first two bytes are known */
8485 size = GPTRSIZE - 1;
8489 aopPut (AOP (result),
8490 aopGet (AOP (right), offset, FALSE, FALSE),
8494 /* the last byte depending on type */
8510 case PPOINTER: // what the fck is this?
8515 /* this should never happen */
8516 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8517 "got unknown pointer type");
8520 aopPut (AOP (result), l, GPTRSIZE - 1);
8524 /* just copy the pointers */
8525 size = AOP_SIZE (result);
8529 aopPut (AOP (result),
8530 aopGet (AOP (right), offset, FALSE, FALSE),
8537 /* so we now know that the size of destination is greater
8538 than the size of the source */
8539 /* we move to result for the size of source */
8540 size = AOP_SIZE (right);
8544 aopPut (AOP (result),
8545 aopGet (AOP (right), offset, FALSE, FALSE),
8550 /* now depending on the sign of the source && destination */
8551 size = AOP_SIZE (result) - AOP_SIZE (right);
8552 /* if unsigned or not an integral type */
8553 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8556 aopPut (AOP (result), zero, offset++);
8560 /* we need to extend the sign :{ */
8561 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8564 emitcode ("rlc", "a");
8565 emitcode ("subb", "a,acc");
8567 aopPut (AOP (result), "a", offset++);
8570 /* we are done hurray !!!! */
8573 freeAsmop (right, NULL, ic, TRUE);
8574 freeAsmop (result, NULL, ic, TRUE);
8578 /*-----------------------------------------------------------------*/
8579 /* genDjnz - generate decrement & jump if not zero instrucion */
8580 /*-----------------------------------------------------------------*/
8582 genDjnz (iCode * ic, iCode * ifx)
8588 D(emitcode (";", "genDjnz"));
8590 /* if the if condition has a false label
8591 then we cannot save */
8595 /* if the minus is not of the form
8597 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8598 !IS_OP_LITERAL (IC_RIGHT (ic)))
8601 if (operandLitValue (IC_RIGHT (ic)) != 1)
8604 /* if the size of this greater than one then no
8606 if (getSize (operandType (IC_RESULT (ic))) > 1)
8609 /* otherwise we can save BIG */
8610 lbl = newiTempLabel (NULL);
8611 lbl1 = newiTempLabel (NULL);
8613 aopOp (IC_RESULT (ic), ic, FALSE);
8615 if (AOP_NEEDSACC(IC_RESULT(ic)))
8617 /* If the result is accessed indirectly via
8618 * the accumulator, we must explicitly write
8619 * it back after the decrement.
8621 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8623 if (strcmp(rByte, "a"))
8625 /* Something is hopelessly wrong */
8626 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8627 __FILE__, __LINE__);
8628 /* We can just give up; the generated code will be inefficient,
8631 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8634 emitcode ("dec", "%s", rByte);
8635 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8636 emitcode ("jnz", "%05d$", lbl->key + 100);
8638 else if (IS_AOP_PREG (IC_RESULT (ic)))
8640 emitcode ("dec", "%s",
8641 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8642 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8643 emitcode ("jnz", "%05d$", lbl->key + 100);
8647 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8650 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8651 emitcode ("", "%05d$:", lbl->key + 100);
8652 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8653 emitcode ("", "%05d$:", lbl1->key + 100);
8655 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8660 /*-----------------------------------------------------------------*/
8661 /* genReceive - generate code for a receive iCode */
8662 /*-----------------------------------------------------------------*/
8664 genReceive (iCode * ic)
8666 D(emitcode (";", "genReceive"));
8668 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8669 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8670 IS_TRUE_SYMOP (IC_RESULT (ic))))
8673 int size = getSize (operandType (IC_RESULT (ic)));
8674 int offset = fReturnSizeMCS51 - size;
8677 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8678 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8681 aopOp (IC_RESULT (ic), ic, FALSE);
8682 size = AOP_SIZE (IC_RESULT (ic));
8686 emitcode ("pop", "acc");
8687 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8694 aopOp (IC_RESULT (ic), ic, FALSE);
8696 assignResultValue (IC_RESULT (ic));
8699 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8702 /*-----------------------------------------------------------------*/
8703 /* gen51AggregateAssign - copy complete array's or structures */
8704 /*-----------------------------------------------------------------*/
8705 void gen51AggregateAssign(iCode *ic) {
8706 operand *left=IC_LEFT(ic);
8707 operand *right=IC_RIGHT(ic);
8708 char *fromName=OP_SYMBOL(right)->rname;
8709 char *toName=OP_SYMBOL(left)->rname;
8710 int fromSize=getSize(OP_SYMBOL(right)->type);
8711 int toSize=getSize(OP_SYMBOL(left)->type);
8714 D(emitcode (";", "gen51AggregateAssign"));
8716 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8717 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8718 // well, this code isn't used yet from anywhere else as for initialising
8719 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8723 if (fromSize!=toSize) {
8724 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8725 ic->filename, ic->lineno);
8730 // use the generic memcpy() for now
8731 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8732 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8733 emitcode ("mov", "a,#%s", fromName);
8734 emitcode ("movx", "@dptr,a");
8735 emitcode ("inc", "dptr");
8736 emitcode ("mov", "a,#(%s>>8)", fromName);
8737 emitcode ("movx", "@dptr,a");
8738 emitcode ("inc", "dptr");
8739 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8740 emitcode ("movx", "@dptr,a");
8741 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8742 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8743 emitcode ("movx", "@dptr,a");
8744 emitcode ("inc", "dptr");
8745 emitcode ("mov", "a,#(%d>>8)", count);
8746 emitcode ("movx", "@dptr,a");
8747 emitcode ("mov", "dptr,#%s", toName);
8748 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8749 emitcode ("lcall", "_memcpy");
8751 // more efficient, but will require the native_memcpy_cs2xs
8752 emitcode ("mov", "r0,#%s", fromName);
8753 emitcode ("mov", "r1,#(%s>>8)", fromName);
8754 emitcode ("mov", "r2,#%s", toName);
8755 emitcode ("mov", "r3,#(%s>>8)", toName);
8756 emitcode ("mov", "r4,#%d", count);
8757 emitcode ("mov", "r5,#(%d>>8)", count);
8758 emitcode ("lcall", "_native_memcpy_cs2xs");
8762 /*-----------------------------------------------------------------*/
8763 /* gen51Code - generate code for 8051 based controllers */
8764 /*-----------------------------------------------------------------*/
8766 gen51Code (iCode * lic)
8771 lineHead = lineCurr = NULL;
8773 /* print the allocation information */
8775 printAllocInfo (currFunc, codeOutFile);
8776 /* if debug information required */
8777 /* if (options.debug && currFunc) { */
8778 if (options.debug && currFunc)
8780 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8782 if (IS_STATIC (currFunc->etype))
8783 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8785 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8788 /* stack pointer name */
8789 if (options.useXstack)
8795 for (ic = lic; ic; ic = ic->next)
8798 if (cln != ic->lineno)
8803 emitcode ("", "C$%s$%d$%d$%d ==.",
8804 FileBaseName (ic->filename), ic->lineno,
8805 ic->level, ic->block);
8808 emitcode (";", "%s %d", ic->filename, ic->lineno);
8811 /* if the result is marked as
8812 spilt and rematerializable or code for
8813 this has already been generated then
8815 if (resultRemat (ic) || ic->generated)
8818 /* depending on the operation */
8838 /* IPOP happens only when trying to restore a
8839 spilt live range, if there is an ifx statement
8840 following this pop then the if statement might
8841 be using some of the registers being popped which
8842 would destory the contents of the register so
8843 we need to check for this condition and handle it */
8845 ic->next->op == IFX &&
8846 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8847 genIfx (ic->next, ic);
8865 genEndFunction (ic);
8885 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8902 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8906 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8913 /* note these two are xlated by algebraic equivalence
8914 during parsing SDCC.y */
8915 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8916 "got '>=' or '<=' shouldn't have come here");
8920 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8932 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8936 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8940 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8967 case GET_VALUE_AT_ADDRESS:
8968 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8972 if (POINTER_SET (ic))
8973 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8999 addSet (&_G.sendSet, ic);
9003 gen51AggregateAssign(ic);
9012 /* now we are ready to call the
9013 peep hole optimizer */
9014 if (!options.nopeep)
9015 peepHole (&lineHead);
9017 /* now do the actual printing */
9018 printLine (lineHead, codeOutFile);