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");
1006 emitcode ("push", "%s", s);
1011 /* if bit variable */
1012 if (!aop->aopu.aop_dir)
1014 emitcode ("clr", "a");
1015 emitcode ("rlc", "a");
1020 emitcode ("clr", "%s", aop->aopu.aop_dir);
1022 emitcode ("setb", "%s", aop->aopu.aop_dir);
1023 else if (!strcmp (s, "c"))
1024 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1027 if (strcmp (s, "a"))
1032 symbol *lbl = newiTempLabel (NULL);
1033 emitcode ("clr", "c");
1034 emitcode ("jz", "%05d$", lbl->key + 100);
1035 emitcode ("cpl", "c");
1036 emitcode ("", "%05d$:", lbl->key + 100);
1037 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1045 if (strcmp (aop->aopu.aop_str[offset], s))
1046 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1051 if (!offset && (strcmp (s, "acc") == 0))
1054 if (strcmp (aop->aopu.aop_str[offset], s))
1055 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1059 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1060 "aopPut got unsupported aop->type");
1068 /*-----------------------------------------------------------------*/
1069 /* pointToEnd :- points to the last byte of the operand */
1070 /*-----------------------------------------------------------------*/
1072 pointToEnd (asmop * aop)
1078 aop->coff = count = (aop->size - 1);
1084 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1088 emitcode ("inc", "dptr");
1095 /*-----------------------------------------------------------------*/
1096 /* reAdjustPreg - points a register back to where it should */
1097 /*-----------------------------------------------------------------*/
1099 reAdjustPreg (asmop * aop)
1101 if ((aop->coff==0) || aop->size <= 1)
1109 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1114 emitcode ("lcall", "__decdptr");
1121 #define AOP(op) op->aop
1122 #define AOP_TYPE(op) AOP(op)->type
1123 #define AOP_SIZE(op) AOP(op)->size
1124 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1125 AOP_TYPE(x) == AOP_R0))
1127 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1128 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1130 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1131 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1132 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1134 /*-----------------------------------------------------------------*/
1135 /* genNotFloat - generates not for float operations */
1136 /*-----------------------------------------------------------------*/
1138 genNotFloat (operand * op, operand * res)
1144 /* we will put 127 in the first byte of
1146 aopPut (AOP (res), "#127", 0);
1147 size = AOP_SIZE (op) - 1;
1150 l = aopGet (op->aop, offset++, FALSE, FALSE);
1155 emitcode ("orl", "a,%s",
1157 offset++, FALSE, FALSE));
1160 tlbl = newiTempLabel (NULL);
1161 aopPut (res->aop, one, 1);
1162 emitcode ("jz", "%05d$", (tlbl->key + 100));
1163 aopPut (res->aop, zero, 1);
1164 emitcode ("", "%05d$:", (tlbl->key + 100));
1166 size = res->aop->size - 2;
1168 /* put zeros in the rest */
1170 aopPut (res->aop, zero, offset++);
1173 /*-----------------------------------------------------------------*/
1174 /* opIsGptr: returns non-zero if the passed operand is */
1175 /* a generic pointer type. */
1176 /*-----------------------------------------------------------------*/
1178 opIsGptr (operand * op)
1180 sym_link *type = operandType (op);
1182 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1189 /*-----------------------------------------------------------------*/
1190 /* getDataSize - get the operand data size */
1191 /*-----------------------------------------------------------------*/
1193 getDataSize (operand * op)
1196 size = AOP_SIZE (op);
1197 if (size == GPTRSIZE)
1199 sym_link *type = operandType (op);
1200 if (IS_GENPTR (type))
1202 /* generic pointer; arithmetic operations
1203 * should ignore the high byte (pointer type).
1211 /*-----------------------------------------------------------------*/
1212 /* outAcc - output Acc */
1213 /*-----------------------------------------------------------------*/
1215 outAcc (operand * result)
1218 size = getDataSize (result);
1221 aopPut (AOP (result), "a", 0);
1224 /* unsigned or positive */
1227 aopPut (AOP (result), zero, offset++);
1232 /*-----------------------------------------------------------------*/
1233 /* outBitC - output a bit C */
1234 /*-----------------------------------------------------------------*/
1236 outBitC (operand * result)
1238 /* if the result is bit */
1239 if (AOP_TYPE (result) == AOP_CRY)
1240 aopPut (AOP (result), "c", 0);
1243 emitcode ("clr", "a");
1244 emitcode ("rlc", "a");
1249 /*-----------------------------------------------------------------*/
1250 /* toBoolean - emit code for orl a,operator(sizeop) */
1251 /*-----------------------------------------------------------------*/
1253 toBoolean (operand * oper)
1255 int size = AOP_SIZE (oper) - 1;
1257 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1259 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1263 /*-----------------------------------------------------------------*/
1264 /* genNot - generate code for ! operation */
1265 /*-----------------------------------------------------------------*/
1270 sym_link *optype = operandType (IC_LEFT (ic));
1272 /* assign asmOps to operand & result */
1273 aopOp (IC_LEFT (ic), ic, FALSE);
1274 aopOp (IC_RESULT (ic), ic, TRUE);
1276 /* if in bit space then a special case */
1277 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1279 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1280 emitcode ("cpl", "c");
1281 outBitC (IC_RESULT (ic));
1285 /* if type float then do float */
1286 if (IS_FLOAT (optype))
1288 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1292 toBoolean (IC_LEFT (ic));
1294 tlbl = newiTempLabel (NULL);
1295 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1296 emitcode ("", "%05d$:", tlbl->key + 100);
1297 outBitC (IC_RESULT (ic));
1300 /* release the aops */
1301 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1302 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1306 /*-----------------------------------------------------------------*/
1307 /* genCpl - generate code for complement */
1308 /*-----------------------------------------------------------------*/
1316 /* assign asmOps to operand & result */
1317 aopOp (IC_LEFT (ic), ic, FALSE);
1318 aopOp (IC_RESULT (ic), ic, TRUE);
1320 /* if both are in bit space then
1322 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1323 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1326 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1327 emitcode ("cpl", "c");
1328 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1332 size = AOP_SIZE (IC_RESULT (ic));
1335 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1337 emitcode ("cpl", "a");
1338 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1343 /* release the aops */
1344 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1345 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1348 /*-----------------------------------------------------------------*/
1349 /* genUminusFloat - unary minus for floating points */
1350 /*-----------------------------------------------------------------*/
1352 genUminusFloat (operand * op, operand * result)
1354 int size, offset = 0;
1356 /* for this we just need to flip the
1357 first it then copy the rest in place */
1358 size = AOP_SIZE (op) - 1;
1359 l = aopGet (AOP (op), 3, FALSE, FALSE);
1363 emitcode ("cpl", "acc.7");
1364 aopPut (AOP (result), "a", 3);
1368 aopPut (AOP (result),
1369 aopGet (AOP (op), offset, FALSE, FALSE),
1375 /*-----------------------------------------------------------------*/
1376 /* genUminus - unary minus code generation */
1377 /*-----------------------------------------------------------------*/
1379 genUminus (iCode * ic)
1382 sym_link *optype, *rtype;
1386 aopOp (IC_LEFT (ic), ic, FALSE);
1387 aopOp (IC_RESULT (ic), ic, TRUE);
1389 /* if both in bit space then special
1391 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1392 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1395 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1396 emitcode ("cpl", "c");
1397 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1401 optype = operandType (IC_LEFT (ic));
1402 rtype = operandType (IC_RESULT (ic));
1404 /* if float then do float stuff */
1405 if (IS_FLOAT (optype))
1407 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1411 /* otherwise subtract from zero */
1412 size = AOP_SIZE (IC_LEFT (ic));
1417 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1418 if (!strcmp (l, "a"))
1422 emitcode ("cpl", "a");
1423 emitcode ("addc", "a,#0");
1429 emitcode ("clr", "a");
1430 emitcode ("subb", "a,%s", l);
1432 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1435 /* if any remaining bytes in the result */
1436 /* we just need to propagate the sign */
1437 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1439 emitcode ("rlc", "a");
1440 emitcode ("subb", "a,acc");
1442 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1446 /* release the aops */
1447 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1448 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1451 /*-----------------------------------------------------------------*/
1452 /* saveRegisters - will look for a call and save the registers */
1453 /*-----------------------------------------------------------------*/
1455 saveRegisters (iCode * lic)
1462 for (ic = lic; ic; ic = ic->next)
1463 if (ic->op == CALL || ic->op == PCALL)
1468 fprintf (stderr, "found parameter push with no function call\n");
1472 /* if the registers have been saved already or don't need to be then
1474 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1475 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1478 /* safe the registers in use at this time but skip the
1479 ones for the result */
1480 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1481 mcs51_rUmaskForOp (IC_RESULT(ic)));
1484 if (options.useXstack)
1486 if (bitVectBitValue (rsave, R0_IDX))
1487 emitcode ("mov", "b,r0");
1488 emitcode ("mov", "r0,%s", spname);
1489 for (i = 0; i < mcs51_nRegs; i++)
1491 if (bitVectBitValue (rsave, i))
1494 emitcode ("mov", "a,b");
1496 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1497 emitcode ("movx", "@r0,a");
1498 emitcode ("inc", "r0");
1501 emitcode ("mov", "%s,r0", spname);
1502 if (bitVectBitValue (rsave, R0_IDX))
1503 emitcode ("mov", "r0,b");
1506 for (i = 0; i < mcs51_nRegs; i++)
1508 if (bitVectBitValue (rsave, i))
1509 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1513 /*-----------------------------------------------------------------*/
1514 /* unsaveRegisters - pop the pushed registers */
1515 /*-----------------------------------------------------------------*/
1517 unsaveRegisters (iCode * ic)
1522 /* restore the registers in use at this time but skip the
1523 ones for the result */
1524 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1525 mcs51_rUmaskForOp (IC_RESULT(ic)));
1527 if (options.useXstack)
1529 emitcode ("mov", "r0,%s", spname);
1530 for (i = mcs51_nRegs; i >= 0; i--)
1532 if (bitVectBitValue (rsave, i))
1534 emitcode ("dec", "r0");
1535 emitcode ("movx", "a,@r0");
1537 emitcode ("mov", "b,a");
1539 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1543 emitcode ("mov", "%s,r0", spname);
1544 if (bitVectBitValue (rsave, R0_IDX))
1545 emitcode ("mov", "r0,b");
1548 for (i = mcs51_nRegs; i >= 0; i--)
1550 if (bitVectBitValue (rsave, i))
1551 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1557 /*-----------------------------------------------------------------*/
1559 /*-----------------------------------------------------------------*/
1561 pushSide (operand * oper, int size)
1566 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1567 if (AOP_TYPE (oper) != AOP_REG &&
1568 AOP_TYPE (oper) != AOP_DIR &&
1571 emitcode ("mov", "a,%s", l);
1572 emitcode ("push", "acc");
1575 emitcode ("push", "%s", l);
1579 /*-----------------------------------------------------------------*/
1580 /* assignResultValue - */
1581 /*-----------------------------------------------------------------*/
1583 assignResultValue (operand * oper)
1586 int size = AOP_SIZE (oper);
1589 aopPut (AOP (oper), fReturn[offset], offset);
1595 /*-----------------------------------------------------------------*/
1596 /* genXpush - pushes onto the external stack */
1597 /*-----------------------------------------------------------------*/
1599 genXpush (iCode * ic)
1601 asmop *aop = newAsmop (0);
1603 int size, offset = 0;
1605 aopOp (IC_LEFT (ic), ic, FALSE);
1606 r = getFreePtr (ic, &aop, FALSE);
1609 emitcode ("mov", "%s,_spx", r->name);
1611 size = AOP_SIZE (IC_LEFT (ic));
1615 char *l = aopGet (AOP (IC_LEFT (ic)),
1616 offset++, FALSE, FALSE);
1618 emitcode ("movx", "@%s,a", r->name);
1619 emitcode ("inc", "%s", r->name);
1624 emitcode ("mov", "_spx,%s", r->name);
1626 freeAsmop (NULL, aop, ic, TRUE);
1627 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1630 /*-----------------------------------------------------------------*/
1631 /* genIpush - genrate code for pushing this gets a little complex */
1632 /*-----------------------------------------------------------------*/
1634 genIpush (iCode * ic)
1636 int size, offset = 0;
1639 D(emitcode (";", "genIpush"));
1641 /* if this is not a parm push : ie. it is spill push
1642 and spill push is always done on the local stack */
1646 /* and the item is spilt then do nothing */
1647 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1650 aopOp (IC_LEFT (ic), ic, FALSE);
1651 size = AOP_SIZE (IC_LEFT (ic));
1652 /* push it on the stack */
1655 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1661 emitcode ("push", "%s", l);
1666 /* this is a paramter push: in this case we call
1667 the routine to find the call and save those
1668 registers that need to be saved */
1671 /* if use external stack then call the external
1672 stack pushing routine */
1673 if (options.useXstack)
1679 /* then do the push */
1680 aopOp (IC_LEFT (ic), ic, FALSE);
1683 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1684 size = AOP_SIZE (IC_LEFT (ic));
1688 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1689 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1690 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1693 emitcode ("mov", "a,%s", l);
1694 emitcode ("push", "acc");
1697 emitcode ("push", "%s", l);
1700 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1703 /*-----------------------------------------------------------------*/
1704 /* genIpop - recover the registers: can happen only for spilling */
1705 /*-----------------------------------------------------------------*/
1707 genIpop (iCode * ic)
1712 /* if the temp was not pushed then */
1713 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1716 aopOp (IC_LEFT (ic), ic, FALSE);
1717 size = AOP_SIZE (IC_LEFT (ic));
1718 offset = (size - 1);
1720 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1723 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1726 /*-----------------------------------------------------------------*/
1727 /* unsaveRBank - restores the resgister bank from stack */
1728 /*-----------------------------------------------------------------*/
1730 unsaveRBank (int bank, iCode * ic, bool popPsw)
1736 if (options.useXstack)
1740 /* Assume r0 is available for use. */
1741 r = mcs51_regWithIdx (R0_IDX);;
1746 r = getFreePtr (ic, &aop, FALSE);
1748 emitcode ("mov", "%s,_spx", r->name);
1753 if (options.useXstack)
1755 emitcode ("movx", "a,@%s", r->name);
1756 emitcode ("mov", "psw,a");
1757 emitcode ("dec", "%s", r->name);
1761 emitcode ("pop", "psw");
1765 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1767 if (options.useXstack)
1769 emitcode ("movx", "a,@%s", r->name);
1770 emitcode ("mov", "(%s+%d),a",
1771 regs8051[i].base, 8 * bank + regs8051[i].offset);
1772 emitcode ("dec", "%s", r->name);
1776 emitcode ("pop", "(%s+%d)",
1777 regs8051[i].base, 8 * bank + regs8051[i].offset);
1780 if (options.useXstack)
1782 emitcode ("mov", "_spx,%s", r->name);
1787 freeAsmop (NULL, aop, ic, TRUE);
1791 /*-----------------------------------------------------------------*/
1792 /* saveRBank - saves an entire register bank on the stack */
1793 /*-----------------------------------------------------------------*/
1795 saveRBank (int bank, iCode * ic, bool pushPsw)
1801 if (options.useXstack)
1805 /* Assume r0 is available for use. */
1806 r = mcs51_regWithIdx (R0_IDX);;
1811 r = getFreePtr (ic, &aop, FALSE);
1813 emitcode ("mov", "%s,_spx", r->name);
1816 for (i = 0; i < mcs51_nRegs; i++)
1818 if (options.useXstack)
1820 emitcode ("inc", "%s", r->name);
1821 emitcode ("mov", "a,(%s+%d)",
1822 regs8051[i].base, 8 * bank + regs8051[i].offset);
1823 emitcode ("movx", "@%s,a", r->name);
1826 emitcode ("push", "(%s+%d)",
1827 regs8051[i].base, 8 * bank + regs8051[i].offset);
1832 if (options.useXstack)
1834 emitcode ("mov", "a,psw");
1835 emitcode ("movx", "@%s,a", r->name);
1836 emitcode ("inc", "%s", r->name);
1837 emitcode ("mov", "_spx,%s", r->name);
1842 emitcode ("push", "psw");
1845 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1850 freeAsmop (NULL, aop, ic, TRUE);
1859 /*-----------------------------------------------------------------*/
1860 /* genCall - generates a call statement */
1861 /*-----------------------------------------------------------------*/
1863 genCall (iCode * ic)
1866 bool restoreBank = FALSE;
1867 bool swapBanks = FALSE;
1869 D(emitcode(";", "genCall"));
1870 /* if send set is not empty the assign */
1875 for (sic = setFirstItem (_G.sendSet); sic;
1876 sic = setNextItem (_G.sendSet))
1878 int size, offset = 0;
1879 aopOp (IC_LEFT (sic), sic, FALSE);
1880 size = AOP_SIZE (IC_LEFT (sic));
1883 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1885 if (strcmp (l, fReturn[offset]))
1886 emitcode ("mov", "%s,%s",
1891 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1896 /* if we are calling a not _naked function that is not using
1897 the same register bank then we need to save the
1898 destination registers on the stack */
1899 dtype = operandType (IC_LEFT (ic));
1900 if (dtype && !IFFUNC_ISNAKED(dtype) &&
1901 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1902 IFFUNC_ISISR (currFunc->type))
1906 /* This is unexpected; the bank should have been saved in
1909 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1915 /* if caller saves & we have not saved then */
1921 emitcode ("mov", "psw,#0x%02x",
1922 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1926 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1927 OP_SYMBOL (IC_LEFT (ic))->rname :
1928 OP_SYMBOL (IC_LEFT (ic))->name));
1932 emitcode ("mov", "psw,#0x%02x",
1933 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1936 /* if we need assign a result value */
1937 if ((IS_ITEMP (IC_RESULT (ic)) &&
1938 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1939 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1940 IS_TRUE_SYMOP (IC_RESULT (ic)))
1944 aopOp (IC_RESULT (ic), ic, FALSE);
1947 assignResultValue (IC_RESULT (ic));
1949 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1952 /* adjust the stack for parameters if
1957 if (ic->parmBytes > 3)
1959 emitcode ("mov", "a,%s", spname);
1960 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1961 emitcode ("mov", "%s,a", spname);
1964 for (i = 0; i < ic->parmBytes; i++)
1965 emitcode ("dec", "%s", spname);
1968 /* if we hade saved some registers then unsave them */
1969 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1970 unsaveRegisters (ic);
1972 /* if register bank was saved then pop them */
1974 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1977 /*-----------------------------------------------------------------*/
1978 /* genPcall - generates a call by pointer statement */
1979 /*-----------------------------------------------------------------*/
1981 genPcall (iCode * ic)
1984 symbol *rlbl = newiTempLabel (NULL);
1986 D(emitcode(";", "genPCall"));
1987 /* if caller saves & we have not saved then */
1991 /* if we are calling a function that is not using
1992 the same register bank then we need to save the
1993 destination registers on the stack */
1994 dtype = operandType (IC_LEFT (ic));
1996 IFFUNC_ISISR (currFunc->type) &&
1997 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
1998 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2001 /* push the return address on to the stack */
2002 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2003 emitcode ("push", "acc");
2004 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2005 emitcode ("push", "acc");
2007 /* now push the calling address */
2008 aopOp (IC_LEFT (ic), ic, FALSE);
2010 pushSide (IC_LEFT (ic), FPTRSIZE);
2012 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2014 /* if send set is not empty the assign */
2019 for (sic = setFirstItem (_G.sendSet); sic;
2020 sic = setNextItem (_G.sendSet))
2022 int size, offset = 0;
2023 aopOp (IC_LEFT (sic), sic, FALSE);
2024 size = AOP_SIZE (IC_LEFT (sic));
2027 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2029 if (strcmp (l, fReturn[offset]))
2030 emitcode ("mov", "%s,%s",
2035 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2040 emitcode ("ret", "");
2041 emitcode ("", "%05d$:", (rlbl->key + 100));
2044 /* if we need assign a result value */
2045 if ((IS_ITEMP (IC_RESULT (ic)) &&
2046 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2047 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2048 IS_TRUE_SYMOP (IC_RESULT (ic)))
2052 aopOp (IC_RESULT (ic), ic, FALSE);
2055 assignResultValue (IC_RESULT (ic));
2057 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2060 /* adjust the stack for parameters if
2065 if (ic->parmBytes > 3)
2067 emitcode ("mov", "a,%s", spname);
2068 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2069 emitcode ("mov", "%s,a", spname);
2072 for (i = 0; i < ic->parmBytes; i++)
2073 emitcode ("dec", "%s", spname);
2077 /* if register bank was saved then unsave them */
2079 (FUNC_REGBANK (currFunc->type) !=
2080 FUNC_REGBANK (dtype)))
2081 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2083 /* if we hade saved some registers then
2086 unsaveRegisters (ic);
2089 /*-----------------------------------------------------------------*/
2090 /* resultRemat - result is rematerializable */
2091 /*-----------------------------------------------------------------*/
2093 resultRemat (iCode * ic)
2095 if (SKIP_IC (ic) || ic->op == IFX)
2098 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2100 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2101 if (sym->remat && !POINTER_SET (ic))
2108 #if defined(__BORLANDC__) || defined(_MSC_VER)
2109 #define STRCASECMP stricmp
2111 #define STRCASECMP strcasecmp
2114 /*-----------------------------------------------------------------*/
2115 /* inExcludeList - return 1 if the string is in exclude Reg list */
2116 /*-----------------------------------------------------------------*/
2118 inExcludeList (char *s)
2122 if (options.excludeRegs[i] &&
2123 STRCASECMP (options.excludeRegs[i], "none") == 0)
2126 for (i = 0; options.excludeRegs[i]; i++)
2128 if (options.excludeRegs[i] &&
2129 STRCASECMP (s, options.excludeRegs[i]) == 0)
2135 /*-----------------------------------------------------------------*/
2136 /* genFunction - generated code for function entry */
2137 /*-----------------------------------------------------------------*/
2139 genFunction (iCode * ic)
2143 bool switchedPSW = FALSE;
2146 /* create the function header */
2147 emitcode (";", "-----------------------------------------");
2148 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2149 emitcode (";", "-----------------------------------------");
2151 emitcode ("", "%s:", sym->rname);
2152 ftype = operandType (IC_LEFT (ic));
2154 if (IFFUNC_ISNAKED(ftype))
2156 emitcode(";", "naked function: no prologue.");
2160 /* if critical function then turn interrupts off */
2161 if (IFFUNC_ISCRITICAL (ftype))
2162 emitcode ("clr", "ea");
2164 /* here we need to generate the equates for the
2165 register bank if required */
2166 if (FUNC_REGBANK (ftype) != rbank)
2170 rbank = FUNC_REGBANK (ftype);
2171 for (i = 0; i < mcs51_nRegs; i++)
2173 if (strcmp (regs8051[i].base, "0") == 0)
2174 emitcode ("", "%s = 0x%02x",
2176 8 * rbank + regs8051[i].offset);
2178 emitcode ("", "%s = %s + 0x%02x",
2181 8 * rbank + regs8051[i].offset);
2185 /* if this is an interrupt service routine then
2186 save acc, b, dpl, dph */
2187 if (IFFUNC_ISISR (sym->type))
2190 if (!inExcludeList ("acc"))
2191 emitcode ("push", "acc");
2192 if (!inExcludeList ("b"))
2193 emitcode ("push", "b");
2194 if (!inExcludeList ("dpl"))
2195 emitcode ("push", "dpl");
2196 if (!inExcludeList ("dph"))
2197 emitcode ("push", "dph");
2198 /* if this isr has no bank i.e. is going to
2199 run with bank 0 , then we need to save more
2201 if (!FUNC_REGBANK (sym->type))
2204 /* if this function does not call any other
2205 function then we can be economical and
2206 save only those registers that are used */
2207 if (!IFFUNC_HASFCALL(sym->type))
2211 /* if any registers used */
2214 /* save the registers used */
2215 for (i = 0; i < sym->regsUsed->size; i++)
2217 if (bitVectBitValue (sym->regsUsed, i) ||
2218 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2219 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2226 /* this function has a function call cannot
2227 determines register usage so we will have to push the
2229 saveRBank (0, ic, FALSE);
2234 /* This ISR uses a non-zero bank.
2236 * We assume that the bank is available for our
2239 * However, if this ISR calls a function which uses some
2240 * other bank, we must save that bank entirely.
2242 unsigned long banksToSave = 0;
2244 if (IFFUNC_HASFCALL(sym->type))
2247 #define MAX_REGISTER_BANKS 4
2252 for (i = ic; i; i = i->next)
2254 if (i->op == ENDFUNCTION)
2256 /* we got to the end OK. */
2264 dtype = operandType (IC_LEFT(i));
2266 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2268 /* Mark this bank for saving. */
2269 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2271 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2275 banksToSave |= (1 << FUNC_REGBANK(dtype));
2278 /* And note that we don't need to do it in
2286 /* This is a mess; we have no idea what
2287 * register bank the called function might
2290 * The only thing I can think of to do is
2291 * throw a warning and hope.
2293 werror(W_FUNCPTR_IN_USING_ISR);
2297 if (banksToSave && options.useXstack)
2299 /* Since we aren't passing it an ic,
2300 * saveRBank will assume r0 is available to abuse.
2302 * So switch to our (trashable) bank now, so
2303 * the caller's R0 isn't trashed.
2305 emitcode ("push", "psw");
2306 emitcode ("mov", "psw,#0x%02x",
2307 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2311 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2313 if (banksToSave & (1 << ix))
2315 saveRBank(ix, NULL, FALSE);
2319 // jwk: this needs a closer look
2320 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2325 /* if callee-save to be used for this function
2326 then save the registers being used in this function */
2327 if (IFFUNC_CALLEESAVES(sym->type))
2331 /* if any registers used */
2334 /* save the registers used */
2335 for (i = 0; i < sym->regsUsed->size; i++)
2337 if (bitVectBitValue (sym->regsUsed, i) ||
2338 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2340 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2348 /* set the register bank to the desired value */
2349 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2352 emitcode ("push", "psw");
2353 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2356 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2359 if (options.useXstack)
2361 emitcode ("mov", "r0,%s", spname);
2362 emitcode ("mov", "a,_bp");
2363 emitcode ("movx", "@r0,a");
2364 emitcode ("inc", "%s", spname);
2368 /* set up the stack */
2369 emitcode ("push", "_bp"); /* save the callers stack */
2371 emitcode ("mov", "_bp,%s", spname);
2374 /* adjust the stack for the function */
2380 werror (W_STACK_OVERFLOW, sym->name);
2382 if (i > 3 && sym->recvSize < 4)
2385 emitcode ("mov", "a,sp");
2386 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2387 emitcode ("mov", "sp,a");
2392 emitcode ("inc", "sp");
2398 emitcode ("mov", "a,_spx");
2399 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2400 emitcode ("mov", "_spx,a");
2405 /*-----------------------------------------------------------------*/
2406 /* genEndFunction - generates epilogue for functions */
2407 /*-----------------------------------------------------------------*/
2409 genEndFunction (iCode * ic)
2411 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2413 if (IFFUNC_ISNAKED(sym->type))
2415 emitcode(";", "naked function: no epilogue.");
2419 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2421 emitcode ("mov", "%s,_bp", spname);
2424 /* if use external stack but some variables were
2425 added to the local stack then decrement the
2427 if (options.useXstack && sym->stack)
2429 emitcode ("mov", "a,sp");
2430 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2431 emitcode ("mov", "sp,a");
2435 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2437 if (options.useXstack)
2439 emitcode ("mov", "r0,%s", spname);
2440 emitcode ("movx", "a,@r0");
2441 emitcode ("mov", "_bp,a");
2442 emitcode ("dec", "%s", spname);
2446 emitcode ("pop", "_bp");
2450 /* restore the register bank */
2451 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2453 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2454 || !options.useXstack)
2456 /* Special case of ISR using non-zero bank with useXstack
2459 emitcode ("pop", "psw");
2463 if (IFFUNC_ISISR (sym->type))
2466 /* now we need to restore the registers */
2467 /* if this isr has no bank i.e. is going to
2468 run with bank 0 , then we need to save more
2470 if (!FUNC_REGBANK (sym->type))
2472 /* if this function does not call any other
2473 function then we can be economical and
2474 save only those registers that are used */
2475 if (!IFFUNC_HASFCALL(sym->type))
2479 /* if any registers used */
2482 /* save the registers used */
2483 for (i = sym->regsUsed->size; i >= 0; i--)
2485 if (bitVectBitValue (sym->regsUsed, i) ||
2486 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2487 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2494 /* this function has a function call cannot
2495 determines register usage so we will have to pop the
2497 unsaveRBank (0, ic, FALSE);
2502 /* This ISR uses a non-zero bank.
2504 * Restore any register banks saved by genFunction
2507 // jwk: this needs a closer look
2508 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2511 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2513 if (savedBanks & (1 << ix))
2515 unsaveRBank(ix, NULL, FALSE);
2519 if (options.useXstack)
2521 /* Restore bank AFTER calling unsaveRBank,
2522 * since it can trash r0.
2524 emitcode ("pop", "psw");
2528 if (!inExcludeList ("dph"))
2529 emitcode ("pop", "dph");
2530 if (!inExcludeList ("dpl"))
2531 emitcode ("pop", "dpl");
2532 if (!inExcludeList ("b"))
2533 emitcode ("pop", "b");
2534 if (!inExcludeList ("acc"))
2535 emitcode ("pop", "acc");
2537 if (IFFUNC_ISCRITICAL (sym->type))
2538 emitcode ("setb", "ea");
2540 /* if debug then send end of function */
2541 /* if (options.debug && currFunc) */
2542 if (options.debug && currFunc)
2545 emitcode ("", "C$%s$%d$%d$%d ==.",
2546 FileBaseName (ic->filename), currFunc->lastLine,
2547 ic->level, ic->block);
2548 if (IS_STATIC (currFunc->etype))
2549 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2551 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2555 emitcode ("reti", "");
2559 if (IFFUNC_ISCRITICAL (sym->type))
2560 emitcode ("setb", "ea");
2562 if (IFFUNC_CALLEESAVES(sym->type))
2566 /* if any registers used */
2569 /* save the registers used */
2570 for (i = sym->regsUsed->size; i >= 0; i--)
2572 if (bitVectBitValue (sym->regsUsed, i) ||
2573 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2574 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2580 /* if debug then send end of function */
2581 if (options.debug && currFunc)
2584 emitcode ("", "C$%s$%d$%d$%d ==.",
2585 FileBaseName (ic->filename), currFunc->lastLine,
2586 ic->level, ic->block);
2587 if (IS_STATIC (currFunc->etype))
2588 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2590 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2594 emitcode ("ret", "");
2599 /*-----------------------------------------------------------------*/
2600 /* genRet - generate code for return statement */
2601 /*-----------------------------------------------------------------*/
2605 int size, offset = 0, pushed = 0;
2607 /* if we have no return value then
2608 just generate the "ret" */
2612 /* we have something to return then
2613 move the return value into place */
2614 aopOp (IC_LEFT (ic), ic, FALSE);
2615 size = AOP_SIZE (IC_LEFT (ic));
2620 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2623 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2625 emitcode ("push", "%s", l);
2630 l = aopGet (AOP (IC_LEFT (ic)), offset,
2632 if (strcmp (fReturn[offset], l))
2633 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2642 if (strcmp (fReturn[pushed], "a"))
2643 emitcode ("pop", fReturn[pushed]);
2645 emitcode ("pop", "acc");
2648 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2651 /* generate a jump to the return label
2652 if the next is not the return statement */
2653 if (!(ic->next && ic->next->op == LABEL &&
2654 IC_LABEL (ic->next) == returnLabel))
2656 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2660 /*-----------------------------------------------------------------*/
2661 /* genLabel - generates a label */
2662 /*-----------------------------------------------------------------*/
2664 genLabel (iCode * ic)
2666 /* special case never generate */
2667 if (IC_LABEL (ic) == entryLabel)
2670 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2673 /*-----------------------------------------------------------------*/
2674 /* genGoto - generates a ljmp */
2675 /*-----------------------------------------------------------------*/
2677 genGoto (iCode * ic)
2679 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2682 /*-----------------------------------------------------------------*/
2683 /* findLabelBackwards: walks back through the iCode chain looking */
2684 /* for the given label. Returns number of iCode instructions */
2685 /* between that label and given ic. */
2686 /* Returns zero if label not found. */
2687 /*-----------------------------------------------------------------*/
2689 findLabelBackwards (iCode * ic, int key)
2698 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2700 /* printf("findLabelBackwards = %d\n", count); */
2708 /*-----------------------------------------------------------------*/
2709 /* genPlusIncr :- does addition with increment if possible */
2710 /*-----------------------------------------------------------------*/
2712 genPlusIncr (iCode * ic)
2714 unsigned int icount;
2715 unsigned int size = getDataSize (IC_RESULT (ic));
2717 /* will try to generate an increment */
2718 /* if the right side is not a literal
2720 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2723 /* if the literal value of the right hand side
2724 is greater than 4 then it is not worth it */
2725 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2728 /* if increment 16 bits in register */
2729 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2737 /* If the next instruction is a goto and the goto target
2738 * is < 10 instructions previous to this, we can generate
2739 * jumps straight to that target.
2741 if (ic->next && ic->next->op == GOTO
2742 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2743 && labelRange <= 10)
2745 emitcode (";", "tail increment optimized");
2746 tlbl = IC_LABEL (ic->next);
2751 tlbl = newiTempLabel (NULL);
2754 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2755 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2756 IS_AOP_PREG (IC_RESULT (ic)))
2757 emitcode ("cjne", "%s,#0x00,%05d$"
2758 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2762 emitcode ("clr", "a");
2763 emitcode ("cjne", "a,%s,%05d$"
2764 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2768 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2771 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2772 IS_AOP_PREG (IC_RESULT (ic)))
2773 emitcode ("cjne", "%s,#0x00,%05d$"
2774 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2777 emitcode ("cjne", "a,%s,%05d$"
2778 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2781 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2785 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2786 IS_AOP_PREG (IC_RESULT (ic)))
2787 emitcode ("cjne", "%s,#0x00,%05d$"
2788 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2792 emitcode ("cjne", "a,%s,%05d$"
2793 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2796 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2801 emitcode ("", "%05d$:", tlbl->key + 100);
2806 /* if the sizes are greater than 1 then we cannot */
2807 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2808 AOP_SIZE (IC_LEFT (ic)) > 1)
2811 /* we can if the aops of the left & result match or
2812 if they are in registers and the registers are the
2814 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2819 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2820 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2821 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2827 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2836 /*-----------------------------------------------------------------*/
2837 /* outBitAcc - output a bit in acc */
2838 /*-----------------------------------------------------------------*/
2840 outBitAcc (operand * result)
2842 symbol *tlbl = newiTempLabel (NULL);
2843 /* if the result is a bit */
2844 if (AOP_TYPE (result) == AOP_CRY)
2846 aopPut (AOP (result), "a", 0);
2850 emitcode ("jz", "%05d$", tlbl->key + 100);
2851 emitcode ("mov", "a,%s", one);
2852 emitcode ("", "%05d$:", tlbl->key + 100);
2857 /*-----------------------------------------------------------------*/
2858 /* genPlusBits - generates code for addition of two bits */
2859 /*-----------------------------------------------------------------*/
2861 genPlusBits (iCode * ic)
2863 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2865 symbol *lbl = newiTempLabel (NULL);
2866 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2867 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2868 emitcode ("cpl", "c");
2869 emitcode ("", "%05d$:", (lbl->key + 100));
2870 outBitC (IC_RESULT (ic));
2874 emitcode ("clr", "a");
2875 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2876 emitcode ("rlc", "a");
2877 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2878 emitcode ("addc", "a,#0x00");
2879 outAcc (IC_RESULT (ic));
2884 /* This is the original version of this code.
2886 * This is being kept around for reference,
2887 * because I am not entirely sure I got it right...
2890 adjustArithmeticResult (iCode * ic)
2892 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2893 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2894 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2895 aopPut (AOP (IC_RESULT (ic)),
2896 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2899 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2900 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2901 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2902 aopPut (AOP (IC_RESULT (ic)),
2903 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2906 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2907 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2908 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2909 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2910 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2913 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2914 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2918 /* This is the pure and virtuous version of this code.
2919 * I'm pretty certain it's right, but not enough to toss the old
2923 adjustArithmeticResult (iCode * ic)
2925 if (opIsGptr (IC_RESULT (ic)) &&
2926 opIsGptr (IC_LEFT (ic)) &&
2927 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2929 aopPut (AOP (IC_RESULT (ic)),
2930 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2934 if (opIsGptr (IC_RESULT (ic)) &&
2935 opIsGptr (IC_RIGHT (ic)) &&
2936 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2938 aopPut (AOP (IC_RESULT (ic)),
2939 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2943 if (opIsGptr (IC_RESULT (ic)) &&
2944 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2945 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2946 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2947 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2950 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2951 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2956 /*-----------------------------------------------------------------*/
2957 /* genPlus - generates code for addition */
2958 /*-----------------------------------------------------------------*/
2960 genPlus (iCode * ic)
2962 int size, offset = 0;
2964 /* special cases :- */
2966 aopOp (IC_LEFT (ic), ic, FALSE);
2967 aopOp (IC_RIGHT (ic), ic, FALSE);
2968 aopOp (IC_RESULT (ic), ic, TRUE);
2970 /* if literal, literal on the right or
2971 if left requires ACC or right is already
2973 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2974 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2975 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2977 operand *t = IC_RIGHT (ic);
2978 IC_RIGHT (ic) = IC_LEFT (ic);
2982 /* if both left & right are in bit
2984 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2985 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2991 /* if left in bit space & right literal */
2992 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2993 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2995 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2996 /* if result in bit space */
2997 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2999 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3000 emitcode ("cpl", "c");
3001 outBitC (IC_RESULT (ic));
3005 size = getDataSize (IC_RESULT (ic));
3008 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3009 emitcode ("addc", "a,#00");
3010 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3016 /* if I can do an increment instead
3017 of add then GOOD for ME */
3018 if (genPlusIncr (ic) == TRUE)
3021 size = getDataSize (IC_RESULT (ic));
3025 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3027 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3029 emitcode ("add", "a,%s",
3030 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3032 emitcode ("addc", "a,%s",
3033 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3037 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3039 emitcode ("add", "a,%s",
3040 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3042 emitcode ("addc", "a,%s",
3043 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3045 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3048 adjustArithmeticResult (ic);
3051 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3052 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3053 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3056 /*-----------------------------------------------------------------*/
3057 /* genMinusDec :- does subtraction with deccrement if possible */
3058 /*-----------------------------------------------------------------*/
3060 genMinusDec (iCode * ic)
3062 unsigned int icount;
3063 unsigned int size = getDataSize (IC_RESULT (ic));
3065 /* will try to generate an increment */
3066 /* if the right side is not a literal
3068 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3071 /* if the literal value of the right hand side
3072 is greater than 4 then it is not worth it */
3073 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3076 /* if decrement 16 bits in register */
3077 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3085 /* If the next instruction is a goto and the goto target
3086 * is <= 10 instructions previous to this, we can generate
3087 * jumps straight to that target.
3089 if (ic->next && ic->next->op == GOTO
3090 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3091 && labelRange <= 10)
3093 emitcode (";", "tail decrement optimized");
3094 tlbl = IC_LABEL (ic->next);
3099 tlbl = newiTempLabel (NULL);
3103 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3104 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3105 IS_AOP_PREG (IC_RESULT (ic)))
3106 emitcode ("cjne", "%s,#0xff,%05d$"
3107 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3111 emitcode ("mov", "a,#0xff");
3112 emitcode ("cjne", "a,%s,%05d$"
3113 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3116 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3119 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3120 IS_AOP_PREG (IC_RESULT (ic)))
3121 emitcode ("cjne", "%s,#0xff,%05d$"
3122 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3126 emitcode ("cjne", "a,%s,%05d$"
3127 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3130 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, 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)), MSB24, FALSE, FALSE)
3141 emitcode ("cjne", "a,%s,%05d$"
3142 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3145 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3149 emitcode ("", "%05d$:", tlbl->key + 100);
3154 /* if the sizes are greater than 1 then we cannot */
3155 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3156 AOP_SIZE (IC_LEFT (ic)) > 1)
3159 /* we can if the aops of the left & result match or
3160 if they are in registers and the registers are the
3162 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3166 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3174 /*-----------------------------------------------------------------*/
3175 /* addSign - complete with sign */
3176 /*-----------------------------------------------------------------*/
3178 addSign (operand * result, int offset, int sign)
3180 int size = (getDataSize (result) - offset);
3185 emitcode ("rlc", "a");
3186 emitcode ("subb", "a,acc");
3188 aopPut (AOP (result), "a", offset++);
3192 aopPut (AOP (result), zero, offset++);
3196 /*-----------------------------------------------------------------*/
3197 /* genMinusBits - generates code for subtraction of two bits */
3198 /*-----------------------------------------------------------------*/
3200 genMinusBits (iCode * ic)
3202 symbol *lbl = newiTempLabel (NULL);
3203 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3205 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3206 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3207 emitcode ("cpl", "c");
3208 emitcode ("", "%05d$:", (lbl->key + 100));
3209 outBitC (IC_RESULT (ic));
3213 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3214 emitcode ("subb", "a,acc");
3215 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3216 emitcode ("inc", "a");
3217 emitcode ("", "%05d$:", (lbl->key + 100));
3218 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3219 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3223 /*-----------------------------------------------------------------*/
3224 /* genMinus - generates code for subtraction */
3225 /*-----------------------------------------------------------------*/
3227 genMinus (iCode * ic)
3229 int size, offset = 0;
3230 unsigned long lit = 0L;
3232 aopOp (IC_LEFT (ic), ic, FALSE);
3233 aopOp (IC_RIGHT (ic), ic, FALSE);
3234 aopOp (IC_RESULT (ic), ic, TRUE);
3236 /* special cases :- */
3237 /* if both left & right are in bit space */
3238 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3239 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3245 /* if I can do an decrement instead
3246 of subtract then GOOD for ME */
3247 if (genMinusDec (ic) == TRUE)
3250 size = getDataSize (IC_RESULT (ic));
3252 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3258 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3262 /* if literal, add a,#-lit, else normal subb */
3265 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3266 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3267 emitcode ("subb", "a,%s",
3268 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3271 /* first add without previous c */
3273 if (!size && lit==-1) {
3274 emitcode ("dec", "a");
3276 emitcode ("add", "a,#0x%02x",
3277 (unsigned int) (lit & 0x0FFL));
3280 emitcode ("addc", "a,#0x%02x",
3281 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3284 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3287 adjustArithmeticResult (ic);
3290 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3291 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3292 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3296 /*-----------------------------------------------------------------*/
3297 /* genMultbits :- multiplication of bits */
3298 /*-----------------------------------------------------------------*/
3300 genMultbits (operand * left,
3304 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3305 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3310 /*-----------------------------------------------------------------*/
3311 /* genMultOneByte : 8*8=8/16 bit multiplication */
3312 /*-----------------------------------------------------------------*/
3314 genMultOneByte (operand * left,
3318 sym_link *opetype = operandType (result);
3320 int size=AOP_SIZE(result);
3322 if (size<1 || size>2) {
3323 // this should never happen
3324 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3325 AOP_SIZE(result), __FILE__, lineno);
3329 /* (if two literals: the value is computed before) */
3330 /* if one literal, literal on the right */
3331 if (AOP_TYPE (left) == AOP_LIT)
3336 //emitcode (";", "swapped left and right");
3339 if (SPEC_USIGN(opetype)
3340 // ignore the sign of left and right, what else can we do?
3341 || (SPEC_USIGN(operandType(left)) &&
3342 SPEC_USIGN(operandType(right)))) {
3343 // just an unsigned 8*8=8/16 multiply
3344 //emitcode (";","unsigned");
3345 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3346 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3347 emitcode ("mul", "ab");
3348 aopPut (AOP (result), "a", 0);
3350 aopPut (AOP (result), "b", 1);
3355 // we have to do a signed multiply
3357 //emitcode (";", "signed");
3358 emitcode ("clr", "F0"); // reset sign flag
3359 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3361 lbl=newiTempLabel(NULL);
3362 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3363 // left side is negative, 8-bit two's complement, this fails for -128
3364 emitcode ("setb", "F0"); // set sign flag
3365 emitcode ("cpl", "a");
3366 emitcode ("inc", "a");
3368 emitcode ("", "%05d$:", lbl->key+100);
3371 if (AOP_TYPE(right)==AOP_LIT) {
3372 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3373 /* AND literal negative */
3375 emitcode ("cpl", "F0"); // complement sign flag
3376 emitcode ("mov", "b,#0x%02x", -val);
3378 emitcode ("mov", "b,#0x%02x", val);
3381 lbl=newiTempLabel(NULL);
3382 emitcode ("mov", "b,a");
3383 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3384 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3385 // right side is negative, 8-bit two's complement
3386 emitcode ("cpl", "F0"); // complement sign flag
3387 emitcode ("cpl", "a");
3388 emitcode ("inc", "a");
3389 emitcode ("", "%05d$:", lbl->key+100);
3391 emitcode ("mul", "ab");
3393 lbl=newiTempLabel(NULL);
3394 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3395 // only ONE op was negative, we have to do a 8/16-bit two's complement
3396 emitcode ("cpl", "a"); // lsb
3398 emitcode ("inc", "a");
3400 emitcode ("add", "a,#1");
3401 emitcode ("xch", "a,b");
3402 emitcode ("cpl", "a"); // msb
3403 emitcode ("addc", "a,#0");
3404 emitcode ("xch", "a,b");
3407 emitcode ("", "%05d$:", lbl->key+100);
3408 aopPut (AOP (result), "a", 0);
3410 aopPut (AOP (result), "b", 1);
3414 /*-----------------------------------------------------------------*/
3415 /* genMult - generates code for multiplication */
3416 /*-----------------------------------------------------------------*/
3418 genMult (iCode * ic)
3420 operand *left = IC_LEFT (ic);
3421 operand *right = IC_RIGHT (ic);
3422 operand *result = IC_RESULT (ic);
3424 /* assign the amsops */
3425 aopOp (left, ic, FALSE);
3426 aopOp (right, ic, FALSE);
3427 aopOp (result, ic, TRUE);
3429 /* special cases first */
3431 if (AOP_TYPE (left) == AOP_CRY &&
3432 AOP_TYPE (right) == AOP_CRY)
3434 genMultbits (left, right, result);
3438 /* if both are of size == 1 */
3439 #if 0 // one of them can be a sloc shared with the result
3440 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3442 if (getSize(operandType(left)) == 1 &&
3443 getSize(operandType(right)) == 1)
3446 genMultOneByte (left, right, result);
3450 /* should have been converted to function call */
3451 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3452 getSize(OP_SYMBOL(right)->type));
3456 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3457 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3458 freeAsmop (result, NULL, ic, TRUE);
3461 /*-----------------------------------------------------------------*/
3462 /* genDivbits :- division of bits */
3463 /*-----------------------------------------------------------------*/
3465 genDivbits (operand * left,
3472 /* the result must be bit */
3473 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3474 l = aopGet (AOP (left), 0, FALSE, FALSE);
3478 emitcode ("div", "ab");
3479 emitcode ("rrc", "a");
3480 aopPut (AOP (result), "c", 0);
3483 /*-----------------------------------------------------------------*/
3484 /* genDivOneByte : 8 bit division */
3485 /*-----------------------------------------------------------------*/
3487 genDivOneByte (operand * left,
3491 sym_link *opetype = operandType (result);
3496 size = AOP_SIZE (result) - 1;
3498 /* signed or unsigned */
3499 if (SPEC_USIGN (opetype))
3501 /* unsigned is easy */
3502 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3503 l = aopGet (AOP (left), 0, FALSE, FALSE);
3505 emitcode ("div", "ab");
3506 aopPut (AOP (result), "a", 0);
3508 aopPut (AOP (result), zero, offset++);
3512 /* signed is a little bit more difficult */
3514 /* save the signs of the operands */
3515 l = aopGet (AOP (left), 0, FALSE, FALSE);
3517 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3518 emitcode ("push", "acc"); /* save it on the stack */
3520 /* now sign adjust for both left & right */
3521 l = aopGet (AOP (right), 0, FALSE, FALSE);
3523 lbl = newiTempLabel (NULL);
3524 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3525 emitcode ("cpl", "a");
3526 emitcode ("inc", "a");
3527 emitcode ("", "%05d$:", (lbl->key + 100));
3528 emitcode ("mov", "b,a");
3530 /* sign adjust left side */
3531 l = aopGet (AOP (left), 0, FALSE, FALSE);
3534 lbl = newiTempLabel (NULL);
3535 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3536 emitcode ("cpl", "a");
3537 emitcode ("inc", "a");
3538 emitcode ("", "%05d$:", (lbl->key + 100));
3540 /* now the division */
3541 emitcode ("div", "ab");
3542 /* we are interested in the lower order
3544 emitcode ("mov", "b,a");
3545 lbl = newiTempLabel (NULL);
3546 emitcode ("pop", "acc");
3547 /* if there was an over flow we don't
3548 adjust the sign of the result */
3549 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3550 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3552 emitcode ("clr", "a");
3553 emitcode ("subb", "a,b");
3554 emitcode ("mov", "b,a");
3555 emitcode ("", "%05d$:", (lbl->key + 100));
3557 /* now we are done */
3558 aopPut (AOP (result), "b", 0);
3561 emitcode ("mov", "c,b.7");
3562 emitcode ("subb", "a,acc");
3565 aopPut (AOP (result), "a", offset++);
3569 /*-----------------------------------------------------------------*/
3570 /* genDiv - generates code for division */
3571 /*-----------------------------------------------------------------*/
3575 operand *left = IC_LEFT (ic);
3576 operand *right = IC_RIGHT (ic);
3577 operand *result = IC_RESULT (ic);
3579 /* assign the amsops */
3580 aopOp (left, ic, FALSE);
3581 aopOp (right, ic, FALSE);
3582 aopOp (result, ic, TRUE);
3584 /* special cases first */
3586 if (AOP_TYPE (left) == AOP_CRY &&
3587 AOP_TYPE (right) == AOP_CRY)
3589 genDivbits (left, right, result);
3593 /* if both are of size == 1 */
3594 if (AOP_SIZE (left) == 1 &&
3595 AOP_SIZE (right) == 1)
3597 genDivOneByte (left, right, result);
3601 /* should have been converted to function call */
3604 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3605 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3606 freeAsmop (result, NULL, ic, TRUE);
3609 /*-----------------------------------------------------------------*/
3610 /* genModbits :- modulus of bits */
3611 /*-----------------------------------------------------------------*/
3613 genModbits (operand * left,
3620 /* the result must be bit */
3621 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3622 l = aopGet (AOP (left), 0, FALSE, FALSE);
3626 emitcode ("div", "ab");
3627 emitcode ("mov", "a,b");
3628 emitcode ("rrc", "a");
3629 aopPut (AOP (result), "c", 0);
3632 /*-----------------------------------------------------------------*/
3633 /* genModOneByte : 8 bit modulus */
3634 /*-----------------------------------------------------------------*/
3636 genModOneByte (operand * left,
3640 sym_link *opetype = operandType (result);
3644 /* signed or unsigned */
3645 if (SPEC_USIGN (opetype))
3647 /* unsigned is easy */
3648 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3649 l = aopGet (AOP (left), 0, FALSE, FALSE);
3651 emitcode ("div", "ab");
3652 aopPut (AOP (result), "b", 0);
3656 /* signed is a little bit more difficult */
3658 /* save the signs of the operands */
3659 l = aopGet (AOP (left), 0, FALSE, FALSE);
3662 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3663 emitcode ("push", "acc"); /* save it on the stack */
3665 /* now sign adjust for both left & right */
3666 l = aopGet (AOP (right), 0, FALSE, FALSE);
3669 lbl = newiTempLabel (NULL);
3670 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3671 emitcode ("cpl", "a");
3672 emitcode ("inc", "a");
3673 emitcode ("", "%05d$:", (lbl->key + 100));
3674 emitcode ("mov", "b,a");
3676 /* sign adjust left side */
3677 l = aopGet (AOP (left), 0, FALSE, FALSE);
3680 lbl = newiTempLabel (NULL);
3681 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3682 emitcode ("cpl", "a");
3683 emitcode ("inc", "a");
3684 emitcode ("", "%05d$:", (lbl->key + 100));
3686 /* now the multiplication */
3687 emitcode ("div", "ab");
3688 /* we are interested in the lower order
3690 lbl = newiTempLabel (NULL);
3691 emitcode ("pop", "acc");
3692 /* if there was an over flow we don't
3693 adjust the sign of the result */
3694 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3695 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3697 emitcode ("clr", "a");
3698 emitcode ("subb", "a,b");
3699 emitcode ("mov", "b,a");
3700 emitcode ("", "%05d$:", (lbl->key + 100));
3702 /* now we are done */
3703 aopPut (AOP (result), "b", 0);
3707 /*-----------------------------------------------------------------*/
3708 /* genMod - generates code for division */
3709 /*-----------------------------------------------------------------*/
3713 operand *left = IC_LEFT (ic);
3714 operand *right = IC_RIGHT (ic);
3715 operand *result = IC_RESULT (ic);
3717 /* assign the amsops */
3718 aopOp (left, ic, FALSE);
3719 aopOp (right, ic, FALSE);
3720 aopOp (result, ic, TRUE);
3722 /* special cases first */
3724 if (AOP_TYPE (left) == AOP_CRY &&
3725 AOP_TYPE (right) == AOP_CRY)
3727 genModbits (left, right, result);
3731 /* if both are of size == 1 */
3732 if (AOP_SIZE (left) == 1 &&
3733 AOP_SIZE (right) == 1)
3735 genModOneByte (left, right, result);
3739 /* should have been converted to function call */
3743 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3744 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3745 freeAsmop (result, NULL, ic, TRUE);
3748 /*-----------------------------------------------------------------*/
3749 /* genIfxJump :- will create a jump depending on the ifx */
3750 /*-----------------------------------------------------------------*/
3752 genIfxJump (iCode * ic, char *jval)
3755 symbol *tlbl = newiTempLabel (NULL);
3758 /* if true label then we jump if condition
3762 jlbl = IC_TRUE (ic);
3763 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3764 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3768 /* false label is present */
3769 jlbl = IC_FALSE (ic);
3770 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3771 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3773 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3774 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3776 emitcode (inst, "%05d$", tlbl->key + 100);
3777 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3778 emitcode ("", "%05d$:", tlbl->key + 100);
3780 /* mark the icode as generated */
3784 /*-----------------------------------------------------------------*/
3785 /* genCmp :- greater or less than comparison */
3786 /*-----------------------------------------------------------------*/
3788 genCmp (operand * left, operand * right,
3789 operand * result, iCode * ifx, int sign, iCode *ic)
3791 int size, offset = 0;
3792 unsigned long lit = 0L;
3794 /* if left & right are bit variables */
3795 if (AOP_TYPE (left) == AOP_CRY &&
3796 AOP_TYPE (right) == AOP_CRY)
3798 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3799 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3803 /* subtract right from left if at the
3804 end the carry flag is set then we know that
3805 left is greater than right */
3806 size = max (AOP_SIZE (left), AOP_SIZE (right));
3808 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3809 if ((size == 1) && !sign &&
3810 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3812 symbol *lbl = newiTempLabel (NULL);
3813 emitcode ("cjne", "%s,%s,%05d$",
3814 aopGet (AOP (left), offset, FALSE, FALSE),
3815 aopGet (AOP (right), offset, FALSE, FALSE),
3817 emitcode ("", "%05d$:", lbl->key + 100);
3821 if (AOP_TYPE (right) == AOP_LIT)
3823 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3824 /* optimize if(x < 0) or if(x >= 0) */
3833 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3834 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3836 genIfxJump (ifx, "acc.7");
3840 emitcode ("rlc", "a");
3848 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3849 if (sign && size == 0)
3851 emitcode ("xrl", "a,#0x80");
3852 if (AOP_TYPE (right) == AOP_LIT)
3854 unsigned long lit = (unsigned long)
3855 floatFromVal (AOP (right)->aopu.aop_lit);
3856 emitcode ("subb", "a,#0x%02x",
3857 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3861 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3862 emitcode ("xrl", "b,#0x80");
3863 emitcode ("subb", "a,b");
3867 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3873 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3874 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3875 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3881 /* if the result is used in the next
3882 ifx conditional branch then generate
3883 code a little differently */
3885 genIfxJump (ifx, "c");
3888 /* leave the result in acc */
3892 /*-----------------------------------------------------------------*/
3893 /* genCmpGt :- greater than comparison */
3894 /*-----------------------------------------------------------------*/
3896 genCmpGt (iCode * ic, iCode * ifx)
3898 operand *left, *right, *result;
3899 sym_link *letype, *retype;
3902 left = IC_LEFT (ic);
3903 right = IC_RIGHT (ic);
3904 result = IC_RESULT (ic);
3906 letype = getSpec (operandType (left));
3907 retype = getSpec (operandType (right));
3908 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3909 /* assign the amsops */
3910 aopOp (left, ic, FALSE);
3911 aopOp (right, ic, FALSE);
3912 aopOp (result, ic, TRUE);
3914 genCmp (right, left, result, ifx, sign,ic);
3916 freeAsmop (result, NULL, ic, TRUE);
3919 /*-----------------------------------------------------------------*/
3920 /* genCmpLt - less than comparisons */
3921 /*-----------------------------------------------------------------*/
3923 genCmpLt (iCode * ic, iCode * ifx)
3925 operand *left, *right, *result;
3926 sym_link *letype, *retype;
3929 left = IC_LEFT (ic);
3930 right = IC_RIGHT (ic);
3931 result = IC_RESULT (ic);
3933 letype = getSpec (operandType (left));
3934 retype = getSpec (operandType (right));
3935 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3937 /* assign the amsops */
3938 aopOp (left, ic, FALSE);
3939 aopOp (right, ic, FALSE);
3940 aopOp (result, ic, TRUE);
3942 genCmp (left, right, result, ifx, sign,ic);
3944 freeAsmop (result, NULL, ic, TRUE);
3947 /*-----------------------------------------------------------------*/
3948 /* gencjneshort - compare and jump if not equal */
3949 /*-----------------------------------------------------------------*/
3951 gencjneshort (operand * left, operand * right, symbol * lbl)
3953 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3955 unsigned long lit = 0L;
3957 /* if the left side is a literal or
3958 if the right is in a pointer register and left
3960 if ((AOP_TYPE (left) == AOP_LIT) ||
3961 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3967 if (AOP_TYPE (right) == AOP_LIT)
3968 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3970 /* if the right side is a literal then anything goes */
3971 if (AOP_TYPE (right) == AOP_LIT &&
3972 AOP_TYPE (left) != AOP_DIR)
3976 emitcode ("cjne", "%s,%s,%05d$",
3977 aopGet (AOP (left), offset, FALSE, FALSE),
3978 aopGet (AOP (right), offset, FALSE, FALSE),
3984 /* if the right side is in a register or in direct space or
3985 if the left is a pointer register & right is not */
3986 else if (AOP_TYPE (right) == AOP_REG ||
3987 AOP_TYPE (right) == AOP_DIR ||
3988 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3989 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3993 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3994 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3995 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3996 emitcode ("jnz", "%05d$", lbl->key + 100);
3998 emitcode ("cjne", "a,%s,%05d$",
3999 aopGet (AOP (right), offset, FALSE, TRUE),
4006 /* right is a pointer reg need both a & b */
4009 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4010 if (strcmp (l, "b"))
4011 emitcode ("mov", "b,%s", l);
4012 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4013 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4019 /*-----------------------------------------------------------------*/
4020 /* gencjne - compare and jump if not equal */
4021 /*-----------------------------------------------------------------*/
4023 gencjne (operand * left, operand * right, symbol * lbl)
4025 symbol *tlbl = newiTempLabel (NULL);
4027 gencjneshort (left, right, lbl);
4029 emitcode ("mov", "a,%s", one);
4030 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4031 emitcode ("", "%05d$:", lbl->key + 100);
4032 emitcode ("clr", "a");
4033 emitcode ("", "%05d$:", tlbl->key + 100);
4036 /*-----------------------------------------------------------------*/
4037 /* genCmpEq - generates code for equal to */
4038 /*-----------------------------------------------------------------*/
4040 genCmpEq (iCode * ic, iCode * ifx)
4042 operand *left, *right, *result;
4044 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4045 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4046 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4048 /* if literal, literal on the right or
4049 if the right is in a pointer register and left
4051 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4052 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4054 operand *t = IC_RIGHT (ic);
4055 IC_RIGHT (ic) = IC_LEFT (ic);
4059 if (ifx && !AOP_SIZE (result))
4062 /* if they are both bit variables */
4063 if (AOP_TYPE (left) == AOP_CRY &&
4064 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4066 if (AOP_TYPE (right) == AOP_LIT)
4068 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4071 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4072 emitcode ("cpl", "c");
4076 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4080 emitcode ("clr", "c");
4082 /* AOP_TYPE(right) == AOP_CRY */
4086 symbol *lbl = newiTempLabel (NULL);
4087 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4088 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4089 emitcode ("cpl", "c");
4090 emitcode ("", "%05d$:", (lbl->key + 100));
4092 /* if true label then we jump if condition
4094 tlbl = newiTempLabel (NULL);
4097 emitcode ("jnc", "%05d$", tlbl->key + 100);
4098 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4102 emitcode ("jc", "%05d$", tlbl->key + 100);
4103 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4105 emitcode ("", "%05d$:", tlbl->key + 100);
4109 tlbl = newiTempLabel (NULL);
4110 gencjneshort (left, right, tlbl);
4113 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4114 emitcode ("", "%05d$:", tlbl->key + 100);
4118 symbol *lbl = newiTempLabel (NULL);
4119 emitcode ("sjmp", "%05d$", lbl->key + 100);
4120 emitcode ("", "%05d$:", tlbl->key + 100);
4121 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4122 emitcode ("", "%05d$:", lbl->key + 100);
4125 /* mark the icode as generated */
4130 /* if they are both bit variables */
4131 if (AOP_TYPE (left) == AOP_CRY &&
4132 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4134 if (AOP_TYPE (right) == AOP_LIT)
4136 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4139 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4140 emitcode ("cpl", "c");
4144 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4148 emitcode ("clr", "c");
4150 /* AOP_TYPE(right) == AOP_CRY */
4154 symbol *lbl = newiTempLabel (NULL);
4155 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4156 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4157 emitcode ("cpl", "c");
4158 emitcode ("", "%05d$:", (lbl->key + 100));
4161 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4168 genIfxJump (ifx, "c");
4171 /* if the result is used in an arithmetic operation
4172 then put the result in place */
4177 gencjne (left, right, newiTempLabel (NULL));
4178 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4180 aopPut (AOP (result), "a", 0);
4185 genIfxJump (ifx, "a");
4188 /* if the result is used in an arithmetic operation
4189 then put the result in place */
4190 if (AOP_TYPE (result) != AOP_CRY)
4192 /* leave the result in acc */
4196 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4197 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4198 freeAsmop (result, NULL, ic, TRUE);
4201 /*-----------------------------------------------------------------*/
4202 /* ifxForOp - returns the icode containing the ifx for operand */
4203 /*-----------------------------------------------------------------*/
4205 ifxForOp (operand * op, iCode * ic)
4207 /* if true symbol then needs to be assigned */
4208 if (IS_TRUE_SYMOP (op))
4211 /* if this has register type condition and
4212 the next instruction is ifx with the same operand
4213 and live to of the operand is upto the ifx only then */
4215 ic->next->op == IFX &&
4216 IC_COND (ic->next)->key == op->key &&
4217 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4223 /*-----------------------------------------------------------------*/
4224 /* hasInc - operand is incremented before any other use */
4225 /*-----------------------------------------------------------------*/
4227 hasInc (operand *op, iCode *ic)
4229 sym_link *type = operandType(op);
4230 sym_link *retype = getSpec (type);
4231 iCode *lic = ic->next;
4234 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4235 if (!IS_SYMOP(op)) return NULL;
4237 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4238 isize = getSize(type->next);
4240 /* if operand of the form op = op + <sizeof *op> */
4241 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4242 isOperandEqual(IC_RESULT(lic),op) &&
4243 isOperandLiteral(IC_RIGHT(lic)) &&
4244 operandLitValue(IC_RIGHT(lic)) == isize) {
4247 /* if the operand used or deffed */
4248 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4256 /*-----------------------------------------------------------------*/
4257 /* genAndOp - for && operation */
4258 /*-----------------------------------------------------------------*/
4260 genAndOp (iCode * ic)
4262 operand *left, *right, *result;
4265 /* note here that && operations that are in an
4266 if statement are taken away by backPatchLabels
4267 only those used in arthmetic operations remain */
4268 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4269 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4270 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4272 /* if both are bit variables */
4273 if (AOP_TYPE (left) == AOP_CRY &&
4274 AOP_TYPE (right) == AOP_CRY)
4276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4277 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4282 tlbl = newiTempLabel (NULL);
4284 emitcode ("jz", "%05d$", tlbl->key + 100);
4286 emitcode ("", "%05d$:", tlbl->key + 100);
4290 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4291 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4292 freeAsmop (result, NULL, ic, TRUE);
4296 /*-----------------------------------------------------------------*/
4297 /* genOrOp - for || operation */
4298 /*-----------------------------------------------------------------*/
4300 genOrOp (iCode * ic)
4302 operand *left, *right, *result;
4305 /* note here that || operations that are in an
4306 if statement are taken away by backPatchLabels
4307 only those used in arthmetic operations remain */
4308 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4309 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4310 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4312 /* if both are bit variables */
4313 if (AOP_TYPE (left) == AOP_CRY &&
4314 AOP_TYPE (right) == AOP_CRY)
4316 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4317 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4322 tlbl = newiTempLabel (NULL);
4324 emitcode ("jnz", "%05d$", tlbl->key + 100);
4326 emitcode ("", "%05d$:", tlbl->key + 100);
4330 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4331 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4332 freeAsmop (result, NULL, ic, TRUE);
4335 /*-----------------------------------------------------------------*/
4336 /* isLiteralBit - test if lit == 2^n */
4337 /*-----------------------------------------------------------------*/
4339 isLiteralBit (unsigned long lit)
4341 unsigned long pw[32] =
4342 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4343 0x100L, 0x200L, 0x400L, 0x800L,
4344 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4345 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4346 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4347 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4348 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4351 for (idx = 0; idx < 32; idx++)
4357 /*-----------------------------------------------------------------*/
4358 /* continueIfTrue - */
4359 /*-----------------------------------------------------------------*/
4361 continueIfTrue (iCode * ic)
4364 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4368 /*-----------------------------------------------------------------*/
4370 /*-----------------------------------------------------------------*/
4372 jumpIfTrue (iCode * ic)
4375 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4379 /*-----------------------------------------------------------------*/
4380 /* jmpTrueOrFalse - */
4381 /*-----------------------------------------------------------------*/
4383 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4385 // ugly but optimized by peephole
4388 symbol *nlbl = newiTempLabel (NULL);
4389 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4390 emitcode ("", "%05d$:", tlbl->key + 100);
4391 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4392 emitcode ("", "%05d$:", nlbl->key + 100);
4396 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4397 emitcode ("", "%05d$:", tlbl->key + 100);
4402 /*-----------------------------------------------------------------*/
4403 /* genAnd - code for and */
4404 /*-----------------------------------------------------------------*/
4406 genAnd (iCode * ic, iCode * ifx)
4408 operand *left, *right, *result;
4409 int size, offset = 0;
4410 unsigned long lit = 0L;
4414 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4415 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4416 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4419 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4421 AOP_TYPE (left), AOP_TYPE (right));
4422 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4424 AOP_SIZE (left), AOP_SIZE (right));
4427 /* if left is a literal & right is not then exchange them */
4428 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4429 AOP_NEEDSACC (left))
4431 operand *tmp = right;
4436 /* if result = right then exchange them */
4437 if (sameRegs (AOP (result), AOP (right)))
4439 operand *tmp = right;
4444 /* if right is bit then exchange them */
4445 if (AOP_TYPE (right) == AOP_CRY &&
4446 AOP_TYPE (left) != AOP_CRY)
4448 operand *tmp = right;
4452 if (AOP_TYPE (right) == AOP_LIT)
4453 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4455 size = AOP_SIZE (result);
4458 // result = bit & yy;
4459 if (AOP_TYPE (left) == AOP_CRY)
4461 // c = bit & literal;
4462 if (AOP_TYPE (right) == AOP_LIT)
4466 if (size && sameRegs (AOP (result), AOP (left)))
4469 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4474 if (size && (AOP_TYPE (result) == AOP_CRY))
4476 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4479 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4484 emitcode ("clr", "c");
4489 if (AOP_TYPE (right) == AOP_CRY)
4492 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4493 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4498 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4500 emitcode ("rrc", "a");
4501 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4509 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4510 genIfxJump (ifx, "c");
4514 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4515 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4516 if ((AOP_TYPE (right) == AOP_LIT) &&
4517 (AOP_TYPE (result) == AOP_CRY) &&
4518 (AOP_TYPE (left) != AOP_CRY))
4520 int posbit = isLiteralBit (lit);
4525 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4528 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4534 sprintf (buffer, "acc.%d", posbit & 0x07);
4535 genIfxJump (ifx, buffer);
4542 symbol *tlbl = newiTempLabel (NULL);
4543 int sizel = AOP_SIZE (left);
4545 emitcode ("setb", "c");
4548 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4550 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4552 if ((posbit = isLiteralBit (bytelit)) != 0)
4553 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4556 if (bytelit != 0x0FFL)
4557 emitcode ("anl", "a,%s",
4558 aopGet (AOP (right), offset, FALSE, TRUE));
4559 emitcode ("jnz", "%05d$", tlbl->key + 100);
4564 // bit = left & literal
4567 emitcode ("clr", "c");
4568 emitcode ("", "%05d$:", tlbl->key + 100);
4570 // if(left & literal)
4574 jmpTrueOrFalse (ifx, tlbl);
4582 /* if left is same as result */
4583 if (sameRegs (AOP (result), AOP (left)))
4585 for (; size--; offset++)
4587 if (AOP_TYPE (right) == AOP_LIT)
4589 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4591 else if (bytelit == 0)
4592 aopPut (AOP (result), zero, offset);
4593 else if (IS_AOP_PREG (result))
4595 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4596 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4597 aopPut (AOP (result), "a", offset);
4600 emitcode ("anl", "%s,%s",
4601 aopGet (AOP (left), offset, FALSE, TRUE),
4602 aopGet (AOP (right), offset, FALSE, FALSE));
4606 if (AOP_TYPE (left) == AOP_ACC)
4607 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4610 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4611 if (IS_AOP_PREG (result))
4613 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4614 aopPut (AOP (result), "a", offset);
4618 emitcode ("anl", "%s,a",
4619 aopGet (AOP (left), offset, FALSE, TRUE));
4626 // left & result in different registers
4627 if (AOP_TYPE (result) == AOP_CRY)
4630 // if(size), result in bit
4631 // if(!size && ifx), conditional oper: if(left & right)
4632 symbol *tlbl = newiTempLabel (NULL);
4633 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4635 emitcode ("setb", "c");
4638 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4639 emitcode ("anl", "a,%s",
4640 aopGet (AOP (right), offset, FALSE, FALSE));
4642 if (AOP_TYPE(left)==AOP_ACC) {
4643 emitcode("mov", "b,a");
4644 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4645 emitcode("anl", "a,b");
4647 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4648 emitcode ("anl", "a,%s",
4649 aopGet (AOP (left), offset, FALSE, FALSE));
4652 emitcode ("jnz", "%05d$", tlbl->key + 100);
4658 emitcode ("", "%05d$:", tlbl->key + 100);
4662 jmpTrueOrFalse (ifx, tlbl);
4666 for (; (size--); offset++)
4669 // result = left & right
4670 if (AOP_TYPE (right) == AOP_LIT)
4672 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4674 aopPut (AOP (result),
4675 aopGet (AOP (left), offset, FALSE, FALSE),
4679 else if (bytelit == 0)
4681 aopPut (AOP (result), zero, offset);
4685 // faster than result <- left, anl result,right
4686 // and better if result is SFR
4687 if (AOP_TYPE (left) == AOP_ACC)
4688 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4691 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4692 emitcode ("anl", "a,%s",
4693 aopGet (AOP (left), offset, FALSE, FALSE));
4695 aopPut (AOP (result), "a", offset);
4701 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4702 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4703 freeAsmop (result, NULL, ic, TRUE);
4706 /*-----------------------------------------------------------------*/
4707 /* genOr - code for or */
4708 /*-----------------------------------------------------------------*/
4710 genOr (iCode * ic, iCode * ifx)
4712 operand *left, *right, *result;
4713 int size, offset = 0;
4714 unsigned long lit = 0L;
4716 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4717 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4718 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4721 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4723 AOP_TYPE (left), AOP_TYPE (right));
4724 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4726 AOP_SIZE (left), AOP_SIZE (right));
4729 /* if left is a literal & right is not then exchange them */
4730 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4731 AOP_NEEDSACC (left))
4733 operand *tmp = right;
4738 /* if result = right then exchange them */
4739 if (sameRegs (AOP (result), AOP (right)))
4741 operand *tmp = right;
4746 /* if right is bit then exchange them */
4747 if (AOP_TYPE (right) == AOP_CRY &&
4748 AOP_TYPE (left) != AOP_CRY)
4750 operand *tmp = right;
4754 if (AOP_TYPE (right) == AOP_LIT)
4755 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4757 size = AOP_SIZE (result);
4761 if (AOP_TYPE (left) == AOP_CRY)
4763 if (AOP_TYPE (right) == AOP_LIT)
4765 // c = bit & literal;
4768 // lit != 0 => result = 1
4769 if (AOP_TYPE (result) == AOP_CRY)
4772 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4774 continueIfTrue (ifx);
4777 emitcode ("setb", "c");
4781 // lit == 0 => result = left
4782 if (size && sameRegs (AOP (result), AOP (left)))
4784 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4789 if (AOP_TYPE (right) == AOP_CRY)
4792 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4793 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4798 symbol *tlbl = newiTempLabel (NULL);
4799 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4800 emitcode ("setb", "c");
4801 emitcode ("jb", "%s,%05d$",
4802 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4804 emitcode ("jnz", "%05d$", tlbl->key + 100);
4805 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4807 jmpTrueOrFalse (ifx, tlbl);
4813 emitcode ("", "%05d$:", tlbl->key + 100);
4822 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4823 genIfxJump (ifx, "c");
4827 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4828 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4829 if ((AOP_TYPE (right) == AOP_LIT) &&
4830 (AOP_TYPE (result) == AOP_CRY) &&
4831 (AOP_TYPE (left) != AOP_CRY))
4837 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4839 continueIfTrue (ifx);
4844 // lit = 0, result = boolean(left)
4846 emitcode ("setb", "c");
4850 symbol *tlbl = newiTempLabel (NULL);
4851 emitcode ("jnz", "%05d$", tlbl->key + 100);
4853 emitcode ("", "%05d$:", tlbl->key + 100);
4857 genIfxJump (ifx, "a");
4865 /* if left is same as result */
4866 if (sameRegs (AOP (result), AOP (left)))
4868 for (; size--; offset++)
4870 if (AOP_TYPE (right) == AOP_LIT)
4872 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4874 else if (IS_AOP_PREG (left))
4876 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4877 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4878 aopPut (AOP (result), "a", offset);
4881 emitcode ("orl", "%s,%s",
4882 aopGet (AOP (left), offset, FALSE, TRUE),
4883 aopGet (AOP (right), offset, FALSE, FALSE));
4887 if (AOP_TYPE (left) == AOP_ACC)
4888 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4891 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4892 if (IS_AOP_PREG (left))
4894 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4895 aopPut (AOP (result), "a", offset);
4898 emitcode ("orl", "%s,a",
4899 aopGet (AOP (left), offset, FALSE, TRUE));
4906 // left & result in different registers
4907 if (AOP_TYPE (result) == AOP_CRY)
4910 // if(size), result in bit
4911 // if(!size && ifx), conditional oper: if(left | right)
4912 symbol *tlbl = newiTempLabel (NULL);
4913 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4915 emitcode ("setb", "c");
4918 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4919 emitcode ("orl", "a,%s",
4920 aopGet (AOP (right), offset, FALSE, FALSE));
4922 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4923 emitcode ("orl", "a,%s",
4924 aopGet (AOP (left), offset, FALSE, FALSE));
4926 emitcode ("jnz", "%05d$", tlbl->key + 100);
4932 emitcode ("", "%05d$:", tlbl->key + 100);
4936 jmpTrueOrFalse (ifx, tlbl);
4939 for (; (size--); offset++)
4942 // result = left & right
4943 if (AOP_TYPE (right) == AOP_LIT)
4945 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4947 aopPut (AOP (result),
4948 aopGet (AOP (left), offset, FALSE, FALSE),
4953 // faster than result <- left, anl result,right
4954 // and better if result is SFR
4955 if (AOP_TYPE (left) == AOP_ACC)
4956 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4959 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4960 emitcode ("orl", "a,%s",
4961 aopGet (AOP (left), offset, FALSE, FALSE));
4963 aopPut (AOP (result), "a", offset);
4968 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4969 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4970 freeAsmop (result, NULL, ic, TRUE);
4973 /*-----------------------------------------------------------------*/
4974 /* genXor - code for xclusive or */
4975 /*-----------------------------------------------------------------*/
4977 genXor (iCode * ic, iCode * ifx)
4979 operand *left, *right, *result;
4980 int size, offset = 0;
4981 unsigned long lit = 0L;
4983 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4984 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4985 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4988 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4990 AOP_TYPE (left), AOP_TYPE (right));
4991 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4993 AOP_SIZE (left), AOP_SIZE (right));
4996 /* if left is a literal & right is not ||
4997 if left needs acc & right does not */
4998 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4999 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5001 operand *tmp = right;
5006 /* if result = right then exchange them */
5007 if (sameRegs (AOP (result), AOP (right)))
5009 operand *tmp = right;
5014 /* if right is bit then exchange them */
5015 if (AOP_TYPE (right) == AOP_CRY &&
5016 AOP_TYPE (left) != AOP_CRY)
5018 operand *tmp = right;
5022 if (AOP_TYPE (right) == AOP_LIT)
5023 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5025 size = AOP_SIZE (result);
5029 if (AOP_TYPE (left) == AOP_CRY)
5031 if (AOP_TYPE (right) == AOP_LIT)
5033 // c = bit & literal;
5036 // lit>>1 != 0 => result = 1
5037 if (AOP_TYPE (result) == AOP_CRY)
5040 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5042 continueIfTrue (ifx);
5045 emitcode ("setb", "c");
5052 // lit == 0, result = left
5053 if (size && sameRegs (AOP (result), AOP (left)))
5055 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5059 // lit == 1, result = not(left)
5060 if (size && sameRegs (AOP (result), AOP (left)))
5062 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5067 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5068 emitcode ("cpl", "c");
5077 symbol *tlbl = newiTempLabel (NULL);
5078 if (AOP_TYPE (right) == AOP_CRY)
5081 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5085 int sizer = AOP_SIZE (right);
5087 // if val>>1 != 0, result = 1
5088 emitcode ("setb", "c");
5091 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5093 // test the msb of the lsb
5094 emitcode ("anl", "a,#0xfe");
5095 emitcode ("jnz", "%05d$", tlbl->key + 100);
5099 emitcode ("rrc", "a");
5101 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5102 emitcode ("cpl", "c");
5103 emitcode ("", "%05d$:", (tlbl->key + 100));
5110 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5111 genIfxJump (ifx, "c");
5115 if (sameRegs (AOP (result), AOP (left)))
5117 /* if left is same as result */
5118 for (; size--; offset++)
5120 if (AOP_TYPE (right) == AOP_LIT)
5122 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5124 else if (IS_AOP_PREG (left))
5126 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5127 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5128 aopPut (AOP (result), "a", offset);
5131 emitcode ("xrl", "%s,%s",
5132 aopGet (AOP (left), offset, FALSE, TRUE),
5133 aopGet (AOP (right), offset, FALSE, FALSE));
5137 if (AOP_TYPE (left) == AOP_ACC)
5138 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5141 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5142 if (IS_AOP_PREG (left))
5144 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5145 aopPut (AOP (result), "a", offset);
5148 emitcode ("xrl", "%s,a",
5149 aopGet (AOP (left), offset, FALSE, TRUE));
5156 // left & result in different registers
5157 if (AOP_TYPE (result) == AOP_CRY)
5160 // if(size), result in bit
5161 // if(!size && ifx), conditional oper: if(left ^ right)
5162 symbol *tlbl = newiTempLabel (NULL);
5163 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5165 emitcode ("setb", "c");
5168 if ((AOP_TYPE (right) == AOP_LIT) &&
5169 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5171 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5175 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5176 emitcode ("xrl", "a,%s",
5177 aopGet (AOP (right), offset, FALSE, FALSE));
5179 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5180 emitcode ("xrl", "a,%s",
5181 aopGet (AOP (left), offset, FALSE, FALSE));
5184 emitcode ("jnz", "%05d$", tlbl->key + 100);
5190 emitcode ("", "%05d$:", tlbl->key + 100);
5194 jmpTrueOrFalse (ifx, tlbl);
5197 for (; (size--); offset++)
5200 // result = left & right
5201 if (AOP_TYPE (right) == AOP_LIT)
5203 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5205 aopPut (AOP (result),
5206 aopGet (AOP (left), offset, FALSE, FALSE),
5211 // faster than result <- left, anl result,right
5212 // and better if result is SFR
5213 if (AOP_TYPE (left) == AOP_ACC)
5214 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5217 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5218 emitcode ("xrl", "a,%s",
5219 aopGet (AOP (left), offset, FALSE, TRUE));
5221 aopPut (AOP (result), "a", offset);
5226 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5228 freeAsmop (result, NULL, ic, TRUE);
5231 /*-----------------------------------------------------------------*/
5232 /* genInline - write the inline code out */
5233 /*-----------------------------------------------------------------*/
5235 genInline (iCode * ic)
5237 char *buffer, *bp, *bp1;
5239 _G.inLine += (!options.asmpeep);
5241 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5242 strcpy (buffer, IC_INLINE (ic));
5244 /* emit each line as a code */
5269 /* emitcode("",buffer); */
5270 _G.inLine -= (!options.asmpeep);
5273 /*-----------------------------------------------------------------*/
5274 /* genRRC - rotate right with carry */
5275 /*-----------------------------------------------------------------*/
5279 operand *left, *result;
5280 int size, offset = 0;
5283 /* rotate right with carry */
5284 left = IC_LEFT (ic);
5285 result = IC_RESULT (ic);
5286 aopOp (left, ic, FALSE);
5287 aopOp (result, ic, FALSE);
5289 /* move it to the result */
5290 size = AOP_SIZE (result);
5292 if (size == 1) { /* special case for 1 byte */
5293 l = aopGet (AOP (left), offset, FALSE, FALSE);
5295 emitcode ("rr", "a");
5301 l = aopGet (AOP (left), offset, FALSE, FALSE);
5303 emitcode ("rrc", "a");
5304 if (AOP_SIZE (result) > 1)
5305 aopPut (AOP (result), "a", offset--);
5307 /* now we need to put the carry into the
5308 highest order byte of the result */
5309 if (AOP_SIZE (result) > 1)
5311 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5314 emitcode ("mov", "acc.7,c");
5316 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5317 freeAsmop (left, NULL, ic, TRUE);
5318 freeAsmop (result, NULL, ic, TRUE);
5321 /*-----------------------------------------------------------------*/
5322 /* genRLC - generate code for rotate left with carry */
5323 /*-----------------------------------------------------------------*/
5327 operand *left, *result;
5328 int size, offset = 0;
5331 /* rotate right with carry */
5332 left = IC_LEFT (ic);
5333 result = IC_RESULT (ic);
5334 aopOp (left, ic, FALSE);
5335 aopOp (result, ic, FALSE);
5337 /* move it to the result */
5338 size = AOP_SIZE (result);
5342 l = aopGet (AOP (left), offset, FALSE, FALSE);
5344 if (size == 0) { /* special case for 1 byte */
5348 emitcode ("add", "a,acc");
5349 if (AOP_SIZE (result) > 1)
5350 aopPut (AOP (result), "a", offset++);
5353 l = aopGet (AOP (left), offset, FALSE, FALSE);
5355 emitcode ("rlc", "a");
5356 if (AOP_SIZE (result) > 1)
5357 aopPut (AOP (result), "a", offset++);
5360 /* now we need to put the carry into the
5361 highest order byte of the result */
5362 if (AOP_SIZE (result) > 1)
5364 l = aopGet (AOP (result), 0, FALSE, FALSE);
5367 emitcode ("mov", "acc.0,c");
5369 aopPut (AOP (result), "a", 0);
5370 freeAsmop (left, NULL, ic, TRUE);
5371 freeAsmop (result, NULL, ic, TRUE);
5374 /*-----------------------------------------------------------------*/
5375 /* genGetHbit - generates code get highest order bit */
5376 /*-----------------------------------------------------------------*/
5378 genGetHbit (iCode * ic)
5380 operand *left, *result;
5381 left = IC_LEFT (ic);
5382 result = IC_RESULT (ic);
5383 aopOp (left, ic, FALSE);
5384 aopOp (result, ic, FALSE);
5386 /* get the highest order byte into a */
5387 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5388 if (AOP_TYPE (result) == AOP_CRY)
5390 emitcode ("rlc", "a");
5395 emitcode ("rl", "a");
5396 emitcode ("anl", "a,#0x01");
5401 freeAsmop (left, NULL, ic, TRUE);
5402 freeAsmop (result, NULL, ic, TRUE);
5405 /*-----------------------------------------------------------------*/
5406 /* AccRol - rotate left accumulator by known count */
5407 /*-----------------------------------------------------------------*/
5409 AccRol (int shCount)
5411 shCount &= 0x0007; // shCount : 0..7
5418 emitcode ("rl", "a");
5421 emitcode ("rl", "a");
5422 emitcode ("rl", "a");
5425 emitcode ("swap", "a");
5426 emitcode ("rr", "a");
5429 emitcode ("swap", "a");
5432 emitcode ("swap", "a");
5433 emitcode ("rl", "a");
5436 emitcode ("rr", "a");
5437 emitcode ("rr", "a");
5440 emitcode ("rr", "a");
5445 /*-----------------------------------------------------------------*/
5446 /* AccLsh - left shift accumulator by known count */
5447 /*-----------------------------------------------------------------*/
5449 AccLsh (int shCount)
5454 emitcode ("add", "a,acc");
5455 else if (shCount == 2)
5457 emitcode ("add", "a,acc");
5458 emitcode ("add", "a,acc");
5462 /* rotate left accumulator */
5464 /* and kill the lower order bits */
5465 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5470 /*-----------------------------------------------------------------*/
5471 /* AccRsh - right shift accumulator by known count */
5472 /*-----------------------------------------------------------------*/
5474 AccRsh (int shCount)
5481 emitcode ("rrc", "a");
5485 /* rotate right accumulator */
5486 AccRol (8 - shCount);
5487 /* and kill the higher order bits */
5488 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5493 /*-----------------------------------------------------------------*/
5494 /* AccSRsh - signed right shift accumulator by known count */
5495 /*-----------------------------------------------------------------*/
5497 AccSRsh (int shCount)
5504 emitcode ("mov", "c,acc.7");
5505 emitcode ("rrc", "a");
5507 else if (shCount == 2)
5509 emitcode ("mov", "c,acc.7");
5510 emitcode ("rrc", "a");
5511 emitcode ("mov", "c,acc.7");
5512 emitcode ("rrc", "a");
5516 tlbl = newiTempLabel (NULL);
5517 /* rotate right accumulator */
5518 AccRol (8 - shCount);
5519 /* and kill the higher order bits */
5520 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5521 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5522 emitcode ("orl", "a,#0x%02x",
5523 (unsigned char) ~SRMask[shCount]);
5524 emitcode ("", "%05d$:", tlbl->key + 100);
5529 /*-----------------------------------------------------------------*/
5530 /* shiftR1Left2Result - shift right one byte from left to result */
5531 /*-----------------------------------------------------------------*/
5533 shiftR1Left2Result (operand * left, int offl,
5534 operand * result, int offr,
5535 int shCount, int sign)
5537 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5538 /* shift right accumulator */
5543 aopPut (AOP (result), "a", offr);
5546 /*-----------------------------------------------------------------*/
5547 /* shiftL1Left2Result - shift left one byte from left to result */
5548 /*-----------------------------------------------------------------*/
5550 shiftL1Left2Result (operand * left, int offl,
5551 operand * result, int offr, int shCount)
5554 l = aopGet (AOP (left), offl, FALSE, FALSE);
5556 /* shift left accumulator */
5558 aopPut (AOP (result), "a", offr);
5561 /*-----------------------------------------------------------------*/
5562 /* movLeft2Result - move byte from left to result */
5563 /*-----------------------------------------------------------------*/
5565 movLeft2Result (operand * left, int offl,
5566 operand * result, int offr, int sign)
5569 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5571 l = aopGet (AOP (left), offl, FALSE, FALSE);
5573 if (*l == '@' && (IS_AOP_PREG (result)))
5575 emitcode ("mov", "a,%s", l);
5576 aopPut (AOP (result), "a", offr);
5581 aopPut (AOP (result), l, offr);
5584 /* MSB sign in acc.7 ! */
5585 if (getDataSize (left) == offl + 1)
5587 emitcode ("mov", "a,%s", l);
5588 aopPut (AOP (result), "a", offr);
5595 /*-----------------------------------------------------------------*/
5596 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5597 /*-----------------------------------------------------------------*/
5601 emitcode ("rrc", "a");
5602 emitcode ("xch", "a,%s", x);
5603 emitcode ("rrc", "a");
5604 emitcode ("xch", "a,%s", x);
5607 /*-----------------------------------------------------------------*/
5608 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5609 /*-----------------------------------------------------------------*/
5613 emitcode ("xch", "a,%s", x);
5614 emitcode ("rlc", "a");
5615 emitcode ("xch", "a,%s", x);
5616 emitcode ("rlc", "a");
5619 /*-----------------------------------------------------------------*/
5620 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5621 /*-----------------------------------------------------------------*/
5625 emitcode ("xch", "a,%s", x);
5626 emitcode ("add", "a,acc");
5627 emitcode ("xch", "a,%s", x);
5628 emitcode ("rlc", "a");
5631 /*-----------------------------------------------------------------*/
5632 /* AccAXLsh - left shift a:x by known count (0..7) */
5633 /*-----------------------------------------------------------------*/
5635 AccAXLsh (char *x, int shCount)
5650 case 5: // AAAAABBB:CCCCCDDD
5652 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5654 emitcode ("anl", "a,#0x%02x",
5655 SLMask[shCount]); // BBB00000:CCCCCDDD
5657 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5659 AccRol (shCount); // DDDCCCCC:BBB00000
5661 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5663 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5665 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5667 emitcode ("anl", "a,#0x%02x",
5668 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5670 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5672 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5675 case 6: // AAAAAABB:CCCCCCDD
5676 emitcode ("anl", "a,#0x%02x",
5677 SRMask[shCount]); // 000000BB:CCCCCCDD
5678 emitcode ("mov", "c,acc.0"); // c = B
5679 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5681 AccAXRrl1 (x); // BCCCCCCD:D000000B
5682 AccAXRrl1 (x); // BBCCCCCC:DD000000
5684 emitcode("rrc","a");
5685 emitcode("xch","a,%s", x);
5686 emitcode("rrc","a");
5687 emitcode("mov","c,acc.0"); //<< get correct bit
5688 emitcode("xch","a,%s", x);
5690 emitcode("rrc","a");
5691 emitcode("xch","a,%s", x);
5692 emitcode("rrc","a");
5693 emitcode("xch","a,%s", x);
5696 case 7: // a:x <<= 7
5698 emitcode ("anl", "a,#0x%02x",
5699 SRMask[shCount]); // 0000000B:CCCCCCCD
5701 emitcode ("mov", "c,acc.0"); // c = B
5703 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5705 AccAXRrl1 (x); // BCCCCCCC:D0000000
5713 /*-----------------------------------------------------------------*/
5714 /* AccAXRsh - right shift a:x known count (0..7) */
5715 /*-----------------------------------------------------------------*/
5717 AccAXRsh (char *x, int shCount)
5725 AccAXRrl1 (x); // 0->a:x
5730 AccAXRrl1 (x); // 0->a:x
5733 AccAXRrl1 (x); // 0->a:x
5738 case 5: // AAAAABBB:CCCCCDDD = a:x
5740 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5742 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5744 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5746 emitcode ("anl", "a,#0x%02x",
5747 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5749 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5751 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5753 emitcode ("anl", "a,#0x%02x",
5754 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5756 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5758 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5760 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5763 case 6: // AABBBBBB:CCDDDDDD
5765 emitcode ("mov", "c,acc.7");
5766 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5768 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5770 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5772 emitcode ("anl", "a,#0x%02x",
5773 SRMask[shCount]); // 000000AA:BBBBBBCC
5776 case 7: // ABBBBBBB:CDDDDDDD
5778 emitcode ("mov", "c,acc.7"); // c = A
5780 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5782 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5784 emitcode ("anl", "a,#0x%02x",
5785 SRMask[shCount]); // 0000000A:BBBBBBBC
5793 /*-----------------------------------------------------------------*/
5794 /* AccAXRshS - right shift signed a:x known count (0..7) */
5795 /*-----------------------------------------------------------------*/
5797 AccAXRshS (char *x, int shCount)
5805 emitcode ("mov", "c,acc.7");
5806 AccAXRrl1 (x); // s->a:x
5810 emitcode ("mov", "c,acc.7");
5811 AccAXRrl1 (x); // s->a:x
5813 emitcode ("mov", "c,acc.7");
5814 AccAXRrl1 (x); // s->a:x
5819 case 5: // AAAAABBB:CCCCCDDD = a:x
5821 tlbl = newiTempLabel (NULL);
5822 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
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); // 000SAAAA:BBBCCCCC
5844 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5845 emitcode ("orl", "a,#0x%02x",
5846 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5848 emitcode ("", "%05d$:", tlbl->key + 100);
5849 break; // SSSSAAAA:BBBCCCCC
5851 case 6: // AABBBBBB:CCDDDDDD
5853 tlbl = newiTempLabel (NULL);
5854 emitcode ("mov", "c,acc.7");
5855 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5857 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5859 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5861 emitcode ("anl", "a,#0x%02x",
5862 SRMask[shCount]); // 000000AA:BBBBBBCC
5864 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5865 emitcode ("orl", "a,#0x%02x",
5866 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5868 emitcode ("", "%05d$:", tlbl->key + 100);
5870 case 7: // ABBBBBBB:CDDDDDDD
5872 tlbl = newiTempLabel (NULL);
5873 emitcode ("mov", "c,acc.7"); // c = A
5875 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5877 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5879 emitcode ("anl", "a,#0x%02x",
5880 SRMask[shCount]); // 0000000A:BBBBBBBC
5882 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5883 emitcode ("orl", "a,#0x%02x",
5884 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5886 emitcode ("", "%05d$:", tlbl->key + 100);
5893 /*-----------------------------------------------------------------*/
5894 /* shiftL2Left2Result - shift left two bytes from left to result */
5895 /*-----------------------------------------------------------------*/
5897 shiftL2Left2Result (operand * left, int offl,
5898 operand * result, int offr, int shCount)
5900 if (sameRegs (AOP (result), AOP (left)) &&
5901 ((offl + MSB16) == offr))
5903 /* don't crash result[offr] */
5904 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5905 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5909 movLeft2Result (left, offl, result, offr, 0);
5910 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5912 /* ax << shCount (x = lsb(result)) */
5913 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5914 aopPut (AOP (result), "a", offr + MSB16);
5918 /*-----------------------------------------------------------------*/
5919 /* shiftR2Left2Result - shift right two bytes from left to result */
5920 /*-----------------------------------------------------------------*/
5922 shiftR2Left2Result (operand * left, int offl,
5923 operand * result, int offr,
5924 int shCount, int sign)
5926 if (sameRegs (AOP (result), AOP (left)) &&
5927 ((offl + MSB16) == offr))
5929 /* don't crash result[offr] */
5930 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5931 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5935 movLeft2Result (left, offl, result, offr, 0);
5936 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5938 /* a:x >> shCount (x = lsb(result)) */
5940 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5942 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5943 if (getDataSize (result) > 1)
5944 aopPut (AOP (result), "a", offr + MSB16);
5947 /*-----------------------------------------------------------------*/
5948 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5949 /*-----------------------------------------------------------------*/
5951 shiftLLeftOrResult (operand * left, int offl,
5952 operand * result, int offr, int shCount)
5954 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5955 /* shift left accumulator */
5957 /* or with result */
5958 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5959 /* back to result */
5960 aopPut (AOP (result), "a", offr);
5963 /*-----------------------------------------------------------------*/
5964 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5965 /*-----------------------------------------------------------------*/
5967 shiftRLeftOrResult (operand * left, int offl,
5968 operand * result, int offr, int shCount)
5970 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5971 /* shift right accumulator */
5973 /* or with result */
5974 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5975 /* back to result */
5976 aopPut (AOP (result), "a", offr);
5979 /*-----------------------------------------------------------------*/
5980 /* genlshOne - left shift a one byte quantity by known count */
5981 /*-----------------------------------------------------------------*/
5983 genlshOne (operand * result, operand * left, int shCount)
5985 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5988 /*-----------------------------------------------------------------*/
5989 /* genlshTwo - left shift two bytes by known amount != 0 */
5990 /*-----------------------------------------------------------------*/
5992 genlshTwo (operand * result, operand * left, int shCount)
5996 size = getDataSize (result);
5998 /* if shCount >= 8 */
6006 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6008 movLeft2Result (left, LSB, result, MSB16, 0);
6010 aopPut (AOP (result), zero, LSB);
6013 /* 1 <= shCount <= 7 */
6017 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6019 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6023 /*-----------------------------------------------------------------*/
6024 /* shiftLLong - shift left one long from left to result */
6025 /* offl = LSB or MSB16 */
6026 /*-----------------------------------------------------------------*/
6028 shiftLLong (operand * left, operand * result, int offr)
6031 int size = AOP_SIZE (result);
6033 if (size >= LSB + offr)
6035 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6037 emitcode ("add", "a,acc");
6038 if (sameRegs (AOP (left), AOP (result)) &&
6039 size >= MSB16 + offr && offr != LSB)
6040 emitcode ("xch", "a,%s",
6041 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6043 aopPut (AOP (result), "a", LSB + offr);
6046 if (size >= MSB16 + offr)
6048 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6050 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6053 emitcode ("rlc", "a");
6054 if (sameRegs (AOP (left), AOP (result)) &&
6055 size >= MSB24 + offr && offr != LSB)
6056 emitcode ("xch", "a,%s",
6057 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6059 aopPut (AOP (result), "a", MSB16 + offr);
6062 if (size >= MSB24 + offr)
6064 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6066 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6069 emitcode ("rlc", "a");
6070 if (sameRegs (AOP (left), AOP (result)) &&
6071 size >= MSB32 + offr && offr != LSB)
6072 emitcode ("xch", "a,%s",
6073 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6075 aopPut (AOP (result), "a", MSB24 + offr);
6078 if (size > MSB32 + offr)
6080 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6082 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6085 emitcode ("rlc", "a");
6086 aopPut (AOP (result), "a", MSB32 + offr);
6089 aopPut (AOP (result), zero, LSB);
6092 /*-----------------------------------------------------------------*/
6093 /* genlshFour - shift four byte by a known amount != 0 */
6094 /*-----------------------------------------------------------------*/
6096 genlshFour (operand * result, operand * left, int shCount)
6100 size = AOP_SIZE (result);
6102 /* if shifting more that 3 bytes */
6107 /* lowest order of left goes to the highest
6108 order of the destination */
6109 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6111 movLeft2Result (left, LSB, result, MSB32, 0);
6112 aopPut (AOP (result), zero, LSB);
6113 aopPut (AOP (result), zero, MSB16);
6114 aopPut (AOP (result), zero, MSB24);
6118 /* more than two bytes */
6119 else if (shCount >= 16)
6121 /* lower order two bytes goes to higher order two bytes */
6123 /* if some more remaining */
6125 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6128 movLeft2Result (left, MSB16, result, MSB32, 0);
6129 movLeft2Result (left, LSB, result, MSB24, 0);
6131 aopPut (AOP (result), zero, MSB16);
6132 aopPut (AOP (result), zero, LSB);
6136 /* if more than 1 byte */
6137 else if (shCount >= 8)
6139 /* lower order three bytes goes to higher order three bytes */
6144 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6146 movLeft2Result (left, LSB, result, MSB16, 0);
6152 movLeft2Result (left, MSB24, result, MSB32, 0);
6153 movLeft2Result (left, MSB16, result, MSB24, 0);
6154 movLeft2Result (left, LSB, result, MSB16, 0);
6155 aopPut (AOP (result), zero, LSB);
6157 else if (shCount == 1)
6158 shiftLLong (left, result, MSB16);
6161 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6162 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6163 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6164 aopPut (AOP (result), zero, LSB);
6169 /* 1 <= shCount <= 7 */
6170 else if (shCount <= 2)
6172 shiftLLong (left, result, LSB);
6174 shiftLLong (result, result, LSB);
6176 /* 3 <= shCount <= 7, optimize */
6179 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6180 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6181 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6185 /*-----------------------------------------------------------------*/
6186 /* genLeftShiftLiteral - left shifting by known count */
6187 /*-----------------------------------------------------------------*/
6189 genLeftShiftLiteral (operand * left,
6194 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6197 freeAsmop (right, NULL, ic, TRUE);
6199 aopOp (left, ic, FALSE);
6200 aopOp (result, ic, FALSE);
6202 size = getSize (operandType (result));
6205 emitcode ("; shift left ", "result %d, left %d", size,
6209 /* I suppose that the left size >= result size */
6214 movLeft2Result (left, size, result, size, 0);
6218 else if (shCount >= (size * 8))
6220 aopPut (AOP (result), zero, size);
6226 genlshOne (result, left, shCount);
6230 genlshTwo (result, left, shCount);
6234 genlshFour (result, left, shCount);
6237 fprintf(stderr, "*** ack! mystery literal shift!\n");
6241 freeAsmop (left, NULL, ic, TRUE);
6242 freeAsmop (result, NULL, ic, TRUE);
6245 /*-----------------------------------------------------------------*/
6246 /* genLeftShift - generates code for left shifting */
6247 /*-----------------------------------------------------------------*/
6249 genLeftShift (iCode * ic)
6251 operand *left, *right, *result;
6254 symbol *tlbl, *tlbl1;
6256 right = IC_RIGHT (ic);
6257 left = IC_LEFT (ic);
6258 result = IC_RESULT (ic);
6260 aopOp (right, ic, FALSE);
6262 /* if the shift count is known then do it
6263 as efficiently as possible */
6264 if (AOP_TYPE (right) == AOP_LIT)
6266 genLeftShiftLiteral (left, right, result, ic);
6270 /* shift count is unknown then we have to form
6271 a loop get the loop count in B : Note: we take
6272 only the lower order byte since shifting
6273 more that 32 bits make no sense anyway, ( the
6274 largest size of an object can be only 32 bits ) */
6276 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6277 emitcode ("inc", "b");
6278 freeAsmop (right, NULL, ic, TRUE);
6279 aopOp (left, ic, FALSE);
6280 aopOp (result, ic, FALSE);
6282 /* now move the left to the result if they are not the
6284 if (!sameRegs (AOP (left), AOP (result)) &&
6285 AOP_SIZE (result) > 1)
6288 size = AOP_SIZE (result);
6292 l = aopGet (AOP (left), offset, FALSE, TRUE);
6293 if (*l == '@' && (IS_AOP_PREG (result)))
6296 emitcode ("mov", "a,%s", l);
6297 aopPut (AOP (result), "a", offset);
6300 aopPut (AOP (result), l, offset);
6305 tlbl = newiTempLabel (NULL);
6306 size = AOP_SIZE (result);
6308 tlbl1 = newiTempLabel (NULL);
6310 /* if it is only one byte then */
6313 symbol *tlbl1 = newiTempLabel (NULL);
6315 l = aopGet (AOP (left), 0, FALSE, FALSE);
6317 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6318 emitcode ("", "%05d$:", tlbl->key + 100);
6319 emitcode ("add", "a,acc");
6320 emitcode ("", "%05d$:", tlbl1->key + 100);
6321 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6322 aopPut (AOP (result), "a", 0);
6326 reAdjustPreg (AOP (result));
6328 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6329 emitcode ("", "%05d$:", tlbl->key + 100);
6330 l = aopGet (AOP (result), offset, FALSE, FALSE);
6332 emitcode ("add", "a,acc");
6333 aopPut (AOP (result), "a", offset++);
6336 l = aopGet (AOP (result), offset, FALSE, FALSE);
6338 emitcode ("rlc", "a");
6339 aopPut (AOP (result), "a", offset++);
6341 reAdjustPreg (AOP (result));
6343 emitcode ("", "%05d$:", tlbl1->key + 100);
6344 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6346 freeAsmop (left, NULL, ic, TRUE);
6347 freeAsmop (result, NULL, ic, TRUE);
6350 /*-----------------------------------------------------------------*/
6351 /* genrshOne - right shift a one byte quantity by known count */
6352 /*-----------------------------------------------------------------*/
6354 genrshOne (operand * result, operand * left,
6355 int shCount, int sign)
6357 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6360 /*-----------------------------------------------------------------*/
6361 /* genrshTwo - right shift two bytes by known amount != 0 */
6362 /*-----------------------------------------------------------------*/
6364 genrshTwo (operand * result, operand * left,
6365 int shCount, int sign)
6367 /* if shCount >= 8 */
6372 shiftR1Left2Result (left, MSB16, result, LSB,
6375 movLeft2Result (left, MSB16, result, LSB, sign);
6376 addSign (result, MSB16, sign);
6379 /* 1 <= shCount <= 7 */
6381 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6384 /*-----------------------------------------------------------------*/
6385 /* shiftRLong - shift right one long from left to result */
6386 /* offl = LSB or MSB16 */
6387 /*-----------------------------------------------------------------*/
6389 shiftRLong (operand * left, int offl,
6390 operand * result, int sign)
6392 int isSameRegs=sameRegs(AOP(left),AOP(result));
6394 if (isSameRegs && offl>1) {
6395 // we are in big trouble, but this shouldn't happen
6396 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6399 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6404 emitcode ("rlc", "a");
6405 emitcode ("subb", "a,acc");
6406 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6408 aopPut (AOP(result), zero, MSB32);
6413 emitcode ("clr", "c");
6415 emitcode ("mov", "c,acc.7");
6418 emitcode ("rrc", "a");
6420 if (isSameRegs && offl==MSB16) {
6421 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6423 aopPut (AOP (result), "a", MSB32);
6424 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6427 emitcode ("rrc", "a");
6428 if (isSameRegs && offl==1) {
6429 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6431 aopPut (AOP (result), "a", MSB24);
6432 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6434 emitcode ("rrc", "a");
6435 aopPut (AOP (result), "a", MSB16 - offl);
6439 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6440 emitcode ("rrc", "a");
6441 aopPut (AOP (result), "a", LSB);
6445 /*-----------------------------------------------------------------*/
6446 /* genrshFour - shift four byte by a known amount != 0 */
6447 /*-----------------------------------------------------------------*/
6449 genrshFour (operand * result, operand * left,
6450 int shCount, int sign)
6452 /* if shifting more that 3 bytes */
6457 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6459 movLeft2Result (left, MSB32, result, LSB, sign);
6460 addSign (result, MSB16, sign);
6462 else if (shCount >= 16)
6466 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6469 movLeft2Result (left, MSB24, result, LSB, 0);
6470 movLeft2Result (left, MSB32, result, MSB16, sign);
6472 addSign (result, MSB24, sign);
6474 else if (shCount >= 8)
6478 shiftRLong (left, MSB16, result, sign);
6479 else if (shCount == 0)
6481 movLeft2Result (left, MSB16, result, LSB, 0);
6482 movLeft2Result (left, MSB24, result, MSB16, 0);
6483 movLeft2Result (left, MSB32, result, MSB24, sign);
6484 addSign (result, MSB32, sign);
6488 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6489 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6490 /* the last shift is signed */
6491 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6492 addSign (result, MSB32, sign);
6496 { /* 1 <= shCount <= 7 */
6499 shiftRLong (left, LSB, result, sign);
6501 shiftRLong (result, LSB, result, sign);
6505 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6506 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6507 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6512 /*-----------------------------------------------------------------*/
6513 /* genRightShiftLiteral - right shifting by known count */
6514 /*-----------------------------------------------------------------*/
6516 genRightShiftLiteral (operand * left,
6522 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6525 freeAsmop (right, NULL, ic, TRUE);
6527 aopOp (left, ic, FALSE);
6528 aopOp (result, ic, FALSE);
6531 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6535 size = getDataSize (left);
6536 /* test the LEFT size !!! */
6538 /* I suppose that the left size >= result size */
6541 size = getDataSize (result);
6543 movLeft2Result (left, size, result, size, 0);
6546 else if (shCount >= (size * 8))
6549 /* get sign in acc.7 */
6550 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6551 addSign (result, LSB, sign);
6558 genrshOne (result, left, shCount, sign);
6562 genrshTwo (result, left, shCount, sign);
6566 genrshFour (result, left, shCount, sign);
6572 freeAsmop (left, NULL, ic, TRUE);
6573 freeAsmop (result, NULL, ic, TRUE);
6577 /*-----------------------------------------------------------------*/
6578 /* genSignedRightShift - right shift of signed number */
6579 /*-----------------------------------------------------------------*/
6581 genSignedRightShift (iCode * ic)
6583 operand *right, *left, *result;
6586 symbol *tlbl, *tlbl1;
6588 /* we do it the hard way put the shift count in b
6589 and loop thru preserving the sign */
6591 right = IC_RIGHT (ic);
6592 left = IC_LEFT (ic);
6593 result = IC_RESULT (ic);
6595 aopOp (right, ic, FALSE);
6598 if (AOP_TYPE (right) == AOP_LIT)
6600 genRightShiftLiteral (left, right, result, ic, 1);
6603 /* shift count is unknown then we have to form
6604 a loop get the loop count in B : Note: we take
6605 only the lower order byte since shifting
6606 more that 32 bits make no sense anyway, ( the
6607 largest size of an object can be only 32 bits ) */
6609 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6610 emitcode ("inc", "b");
6611 freeAsmop (right, NULL, ic, TRUE);
6612 aopOp (left, ic, FALSE);
6613 aopOp (result, ic, FALSE);
6615 /* now move the left to the result if they are not the
6617 if (!sameRegs (AOP (left), AOP (result)) &&
6618 AOP_SIZE (result) > 1)
6621 size = AOP_SIZE (result);
6625 l = aopGet (AOP (left), offset, FALSE, TRUE);
6626 if (*l == '@' && IS_AOP_PREG (result))
6629 emitcode ("mov", "a,%s", l);
6630 aopPut (AOP (result), "a", offset);
6633 aopPut (AOP (result), l, offset);
6638 /* mov the highest order bit to OVR */
6639 tlbl = newiTempLabel (NULL);
6640 tlbl1 = newiTempLabel (NULL);
6642 size = AOP_SIZE (result);
6644 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6645 emitcode ("rlc", "a");
6646 emitcode ("mov", "ov,c");
6647 /* if it is only one byte then */
6650 l = aopGet (AOP (left), 0, FALSE, FALSE);
6652 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6653 emitcode ("", "%05d$:", tlbl->key + 100);
6654 emitcode ("mov", "c,ov");
6655 emitcode ("rrc", "a");
6656 emitcode ("", "%05d$:", tlbl1->key + 100);
6657 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6658 aopPut (AOP (result), "a", 0);
6662 reAdjustPreg (AOP (result));
6663 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6664 emitcode ("", "%05d$:", tlbl->key + 100);
6665 emitcode ("mov", "c,ov");
6668 l = aopGet (AOP (result), offset, FALSE, FALSE);
6670 emitcode ("rrc", "a");
6671 aopPut (AOP (result), "a", offset--);
6673 reAdjustPreg (AOP (result));
6674 emitcode ("", "%05d$:", tlbl1->key + 100);
6675 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6678 freeAsmop (left, NULL, ic, TRUE);
6679 freeAsmop (result, NULL, ic, TRUE);
6682 /*-----------------------------------------------------------------*/
6683 /* genRightShift - generate code for right shifting */
6684 /*-----------------------------------------------------------------*/
6686 genRightShift (iCode * ic)
6688 operand *right, *left, *result;
6692 symbol *tlbl, *tlbl1;
6694 /* if signed then we do it the hard way preserve the
6695 sign bit moving it inwards */
6696 retype = getSpec (operandType (IC_RESULT (ic)));
6698 if (!SPEC_USIGN (retype))
6700 genSignedRightShift (ic);
6704 /* signed & unsigned types are treated the same : i.e. the
6705 signed is NOT propagated inwards : quoting from the
6706 ANSI - standard : "for E1 >> E2, is equivalent to division
6707 by 2**E2 if unsigned or if it has a non-negative value,
6708 otherwise the result is implementation defined ", MY definition
6709 is that the sign does not get propagated */
6711 right = IC_RIGHT (ic);
6712 left = IC_LEFT (ic);
6713 result = IC_RESULT (ic);
6715 aopOp (right, ic, FALSE);
6717 /* if the shift count is known then do it
6718 as efficiently as possible */
6719 if (AOP_TYPE (right) == AOP_LIT)
6721 genRightShiftLiteral (left, right, result, ic, 0);
6725 /* shift count is unknown then we have to form
6726 a loop get the loop count in B : Note: we take
6727 only the lower order byte since shifting
6728 more that 32 bits make no sense anyway, ( the
6729 largest size of an object can be only 32 bits ) */
6731 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6732 emitcode ("inc", "b");
6733 freeAsmop (right, NULL, ic, TRUE);
6734 aopOp (left, ic, FALSE);
6735 aopOp (result, ic, FALSE);
6737 /* now move the left to the result if they are not the
6739 if (!sameRegs (AOP (left), AOP (result)) &&
6740 AOP_SIZE (result) > 1)
6743 size = AOP_SIZE (result);
6747 l = aopGet (AOP (left), offset, FALSE, TRUE);
6748 if (*l == '@' && IS_AOP_PREG (result))
6751 emitcode ("mov", "a,%s", l);
6752 aopPut (AOP (result), "a", offset);
6755 aopPut (AOP (result), l, offset);
6760 tlbl = newiTempLabel (NULL);
6761 tlbl1 = newiTempLabel (NULL);
6762 size = AOP_SIZE (result);
6765 /* if it is only one byte then */
6768 l = aopGet (AOP (left), 0, FALSE, FALSE);
6770 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6771 emitcode ("", "%05d$:", tlbl->key + 100);
6773 emitcode ("rrc", "a");
6774 emitcode ("", "%05d$:", tlbl1->key + 100);
6775 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6776 aopPut (AOP (result), "a", 0);
6780 reAdjustPreg (AOP (result));
6781 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6782 emitcode ("", "%05d$:", tlbl->key + 100);
6786 l = aopGet (AOP (result), offset, FALSE, FALSE);
6788 emitcode ("rrc", "a");
6789 aopPut (AOP (result), "a", offset--);
6791 reAdjustPreg (AOP (result));
6793 emitcode ("", "%05d$:", tlbl1->key + 100);
6794 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6797 freeAsmop (left, NULL, ic, TRUE);
6798 freeAsmop (result, NULL, ic, TRUE);
6801 /*-----------------------------------------------------------------*/
6802 /* genUnpackBits - generates code for unpacking bits */
6803 /*-----------------------------------------------------------------*/
6805 genUnpackBits (operand * result, char *rname, int ptype)
6813 etype = getSpec (operandType (result));
6814 rsize = getSize (operandType (result));
6815 /* read the first byte */
6821 emitcode ("mov", "a,@%s", rname);
6825 emitcode ("movx", "a,@%s", rname);
6829 emitcode ("movx", "a,@dptr");
6833 emitcode ("clr", "a");
6834 emitcode ("movc", "a,@a+dptr");
6838 emitcode ("lcall", "__gptrget");
6842 rlen = SPEC_BLEN (etype);
6844 /* if we have bitdisplacement then it fits */
6845 /* into this byte completely or if length is */
6846 /* less than a byte */
6847 if ((shCnt = SPEC_BSTR (etype)) ||
6848 (SPEC_BLEN (etype) <= 8))
6851 /* shift right acc */
6854 emitcode ("anl", "a,#0x%02x",
6855 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6856 aopPut (AOP (result), "a", offset++);
6860 /* bit field did not fit in a byte */
6861 aopPut (AOP (result), "a", offset++);
6870 emitcode ("inc", "%s", rname);
6871 emitcode ("mov", "a,@%s", rname);
6875 emitcode ("inc", "%s", rname);
6876 emitcode ("movx", "a,@%s", rname);
6880 emitcode ("inc", "dptr");
6881 emitcode ("movx", "a,@dptr");
6885 emitcode ("clr", "a");
6886 emitcode ("inc", "dptr");
6887 emitcode ("movc", "a,@a+dptr");
6891 emitcode ("inc", "dptr");
6892 emitcode ("lcall", "__gptrget");
6897 /* if we are done */
6901 aopPut (AOP (result), "a", offset++);
6907 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6909 aopPut (AOP (result), "a", offset++);
6917 aopPut (AOP (result), zero, offset++);
6923 /*-----------------------------------------------------------------*/
6924 /* genDataPointerGet - generates code when ptr offset is known */
6925 /*-----------------------------------------------------------------*/
6927 genDataPointerGet (operand * left,
6933 int size, offset = 0;
6934 aopOp (result, ic, TRUE);
6936 /* get the string representation of the name */
6937 l = aopGet (AOP (left), 0, FALSE, TRUE);
6938 size = AOP_SIZE (result);
6942 sprintf (buffer, "(%s + %d)", l + 1, offset);
6944 sprintf (buffer, "%s", l + 1);
6945 aopPut (AOP (result), buffer, offset++);
6948 freeAsmop (left, NULL, ic, TRUE);
6949 freeAsmop (result, NULL, ic, TRUE);
6952 /*-----------------------------------------------------------------*/
6953 /* genNearPointerGet - emitcode for near pointer fetch */
6954 /*-----------------------------------------------------------------*/
6956 genNearPointerGet (operand * left,
6964 sym_link *rtype, *retype;
6965 sym_link *ltype = operandType (left);
6968 rtype = operandType (result);
6969 retype = getSpec (rtype);
6971 aopOp (left, ic, FALSE);
6973 /* if left is rematerialisable and
6974 result is not bit variable type and
6975 the left is pointer to data space i.e
6976 lower 128 bytes of space */
6977 if (AOP_TYPE (left) == AOP_IMMD &&
6978 !IS_BITVAR (retype) &&
6979 DCL_TYPE (ltype) == POINTER)
6981 genDataPointerGet (left, result, ic);
6985 /* if the value is already in a pointer register
6986 then don't need anything more */
6987 if (!AOP_INPREG (AOP (left)))
6989 /* otherwise get a free pointer register */
6991 preg = getFreePtr (ic, &aop, FALSE);
6992 emitcode ("mov", "%s,%s",
6994 aopGet (AOP (left), 0, FALSE, TRUE));
6998 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7000 //aopOp (result, ic, FALSE);
7001 aopOp (result, ic, result?TRUE:FALSE);
7003 /* if bitfield then unpack the bits */
7004 if (IS_BITVAR (retype))
7005 genUnpackBits (result, rname, POINTER);
7008 /* we have can just get the values */
7009 int size = AOP_SIZE (result);
7014 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7017 emitcode ("mov", "a,@%s", rname);
7018 aopPut (AOP (result), "a", offset);
7022 sprintf (buffer, "@%s", rname);
7023 aopPut (AOP (result), buffer, offset);
7027 emitcode ("inc", "%s", rname);
7031 /* now some housekeeping stuff */
7032 if (aop) /* we had to allocate for this iCode */
7034 if (pi) { /* post increment present */
7035 aopPut(AOP ( left ),rname,0);
7037 freeAsmop (NULL, aop, ic, TRUE);
7041 /* we did not allocate which means left
7042 already in a pointer register, then
7043 if size > 0 && this could be used again
7044 we have to point it back to where it
7046 if ((AOP_SIZE (result) > 1 &&
7047 !OP_SYMBOL (left)->remat &&
7048 (OP_SYMBOL (left)->liveTo > ic->seq ||
7052 int size = AOP_SIZE (result) - 1;
7054 emitcode ("dec", "%s", rname);
7059 freeAsmop (left, NULL, ic, TRUE);
7060 freeAsmop (result, NULL, ic, TRUE);
7061 if (pi) pi->generated = 1;
7064 /*-----------------------------------------------------------------*/
7065 /* genPagedPointerGet - emitcode for paged pointer fetch */
7066 /*-----------------------------------------------------------------*/
7068 genPagedPointerGet (operand * left,
7076 sym_link *rtype, *retype;
7078 rtype = operandType (result);
7079 retype = getSpec (rtype);
7081 aopOp (left, ic, FALSE);
7083 /* if the value is already in a pointer register
7084 then don't need anything more */
7085 if (!AOP_INPREG (AOP (left)))
7087 /* otherwise get a free pointer register */
7089 preg = getFreePtr (ic, &aop, FALSE);
7090 emitcode ("mov", "%s,%s",
7092 aopGet (AOP (left), 0, FALSE, TRUE));
7096 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7098 aopOp (result, ic, FALSE);
7100 /* if bitfield then unpack the bits */
7101 if (IS_BITVAR (retype))
7102 genUnpackBits (result, rname, PPOINTER);
7105 /* we have can just get the values */
7106 int size = AOP_SIZE (result);
7112 emitcode ("movx", "a,@%s", rname);
7113 aopPut (AOP (result), "a", offset);
7118 emitcode ("inc", "%s", rname);
7122 /* now some housekeeping stuff */
7123 if (aop) /* we had to allocate for this iCode */
7125 if (pi) aopPut ( AOP (left), rname, 0);
7126 freeAsmop (NULL, aop, ic, TRUE);
7130 /* we did not allocate which means left
7131 already in a pointer register, then
7132 if size > 0 && this could be used again
7133 we have to point it back to where it
7135 if ((AOP_SIZE (result) > 1 &&
7136 !OP_SYMBOL (left)->remat &&
7137 (OP_SYMBOL (left)->liveTo > ic->seq ||
7141 int size = AOP_SIZE (result) - 1;
7143 emitcode ("dec", "%s", rname);
7148 freeAsmop (left, NULL, ic, TRUE);
7149 freeAsmop (result, NULL, ic, TRUE);
7150 if (pi) pi->generated = 1;
7154 /*-----------------------------------------------------------------*/
7155 /* genFarPointerGet - gget value from far space */
7156 /*-----------------------------------------------------------------*/
7158 genFarPointerGet (operand * left,
7159 operand * result, iCode * ic, iCode * pi)
7162 sym_link *retype = getSpec (operandType (result));
7164 aopOp (left, ic, FALSE);
7166 /* if the operand is already in dptr
7167 then we do nothing else we move the value to dptr */
7168 if (AOP_TYPE (left) != AOP_STR)
7170 /* if this is remateriazable */
7171 if (AOP_TYPE (left) == AOP_IMMD)
7172 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7174 { /* we need to get it byte by byte */
7175 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7176 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7179 /* so dptr know contains the address */
7180 aopOp (result, ic, FALSE);
7182 /* if bit then unpack */
7183 if (IS_BITVAR (retype))
7184 genUnpackBits (result, "dptr", FPOINTER);
7187 size = AOP_SIZE (result);
7192 emitcode ("movx", "a,@dptr");
7193 aopPut (AOP (result), "a", offset++);
7195 emitcode ("inc", "dptr");
7199 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7200 aopPut ( AOP (left), "dpl", 0);
7201 aopPut ( AOP (left), "dph", 1);
7204 freeAsmop (left, NULL, ic, TRUE);
7205 freeAsmop (result, NULL, ic, TRUE);
7208 /*-----------------------------------------------------------------*/
7209 /* genCodePointerGet - gget value from code space */
7210 /*-----------------------------------------------------------------*/
7212 genCodePointerGet (operand * left,
7213 operand * result, iCode * ic, iCode *pi)
7216 sym_link *retype = getSpec (operandType (result));
7218 aopOp (left, ic, FALSE);
7220 /* if the operand is already in dptr
7221 then we do nothing else we move the value to dptr */
7222 if (AOP_TYPE (left) != AOP_STR)
7224 /* if this is remateriazable */
7225 if (AOP_TYPE (left) == AOP_IMMD)
7226 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7228 { /* we need to get it byte by byte */
7229 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7230 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7233 /* so dptr know contains the address */
7234 aopOp (result, ic, FALSE);
7236 /* if bit then unpack */
7237 if (IS_BITVAR (retype))
7238 genUnpackBits (result, "dptr", CPOINTER);
7241 size = AOP_SIZE (result);
7246 emitcode ("clr", "a");
7247 emitcode ("movc", "a,@a+dptr");
7248 aopPut (AOP (result), "a", offset++);
7250 emitcode ("inc", "dptr");
7254 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7255 aopPut ( AOP (left), "dpl", 0);
7256 aopPut ( AOP (left), "dph", 1);
7259 freeAsmop (left, NULL, ic, TRUE);
7260 freeAsmop (result, NULL, ic, TRUE);
7263 /*-----------------------------------------------------------------*/
7264 /* genGenPointerGet - gget value from generic pointer space */
7265 /*-----------------------------------------------------------------*/
7267 genGenPointerGet (operand * left,
7268 operand * result, iCode * ic, iCode *pi)
7271 sym_link *retype = getSpec (operandType (result));
7273 aopOp (left, ic, FALSE);
7275 /* if the operand is already in dptr
7276 then we do nothing else we move the value to dptr */
7277 if (AOP_TYPE (left) != AOP_STR)
7279 /* if this is remateriazable */
7280 if (AOP_TYPE (left) == AOP_IMMD)
7282 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7283 emitcode ("mov", "b,#%d", pointerCode (retype));
7286 { /* we need to get it byte by byte */
7287 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7288 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7289 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7292 /* so dptr know contains the address */
7293 aopOp (result, ic, FALSE);
7295 /* if bit then unpack */
7296 if (IS_BITVAR (retype))
7297 genUnpackBits (result, "dptr", GPOINTER);
7300 size = AOP_SIZE (result);
7305 emitcode ("lcall", "__gptrget");
7306 aopPut (AOP (result), "a", offset++);
7308 emitcode ("inc", "dptr");
7312 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7313 aopPut ( AOP (left), "dpl", 0);
7314 aopPut ( AOP (left), "dph", 1);
7317 freeAsmop (left, NULL, ic, TRUE);
7318 freeAsmop (result, NULL, ic, TRUE);
7321 /*-----------------------------------------------------------------*/
7322 /* genPointerGet - generate code for pointer get */
7323 /*-----------------------------------------------------------------*/
7325 genPointerGet (iCode * ic, iCode *pi)
7327 operand *left, *result;
7328 sym_link *type, *etype;
7331 left = IC_LEFT (ic);
7332 result = IC_RESULT (ic);
7334 /* depending on the type of pointer we need to
7335 move it to the correct pointer register */
7336 type = operandType (left);
7337 etype = getSpec (type);
7338 /* if left is of type of pointer then it is simple */
7339 if (IS_PTR (type) && !IS_FUNC (type->next))
7340 p_type = DCL_TYPE (type);
7343 /* we have to go by the storage class */
7344 p_type = PTR_TYPE (SPEC_OCLS (etype));
7347 /* now that we have the pointer type we assign
7348 the pointer values */
7354 genNearPointerGet (left, result, ic, pi);
7358 genPagedPointerGet (left, result, ic, pi);
7362 genFarPointerGet (left, result, ic, pi);
7366 genCodePointerGet (left, result, ic, pi);
7370 genGenPointerGet (left, result, ic, pi);
7376 /*-----------------------------------------------------------------*/
7377 /* genPackBits - generates code for packed bit storage */
7378 /*-----------------------------------------------------------------*/
7380 genPackBits (sym_link * etype,
7382 char *rname, int p_type)
7390 blen = SPEC_BLEN (etype);
7391 bstr = SPEC_BSTR (etype);
7393 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7396 /* if the bit lenth is less than or */
7397 /* it exactly fits a byte then */
7398 if (SPEC_BLEN (etype) <= 8)
7400 shCount = SPEC_BSTR (etype);
7402 /* shift left acc */
7405 if (SPEC_BLEN (etype) < 8)
7406 { /* if smaller than a byte */
7412 emitcode ("mov", "b,a");
7413 emitcode ("mov", "a,@%s", rname);
7417 emitcode ("mov", "b,a");
7418 emitcode ("movx", "a,@dptr");
7422 emitcode ("push", "b");
7423 emitcode ("push", "acc");
7424 emitcode ("lcall", "__gptrget");
7425 emitcode ("pop", "b");
7429 emitcode ("anl", "a,#0x%02x", (unsigned char)
7430 ((unsigned char) (0xFF << (blen + bstr)) |
7431 (unsigned char) (0xFF >> (8 - bstr))));
7432 emitcode ("orl", "a,b");
7433 if (p_type == GPOINTER)
7434 emitcode ("pop", "b");
7441 emitcode ("mov", "@%s,a", rname);
7445 emitcode ("movx", "@dptr,a");
7449 emitcode ("lcall", "__gptrput");
7454 if (SPEC_BLEN (etype) <= 8)
7457 emitcode ("inc", "%s", rname);
7458 rLen = SPEC_BLEN (etype);
7460 /* now generate for lengths greater than one byte */
7464 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7476 emitcode ("mov", "@%s,a", rname);
7479 emitcode ("mov", "@%s,%s", rname, l);
7484 emitcode ("movx", "@dptr,a");
7489 emitcode ("lcall", "__gptrput");
7492 emitcode ("inc", "%s", rname);
7497 /* last last was not complete */
7500 /* save the byte & read byte */
7504 emitcode ("mov", "b,a");
7505 emitcode ("mov", "a,@%s", rname);
7509 emitcode ("mov", "b,a");
7510 emitcode ("movx", "a,@dptr");
7514 emitcode ("push", "b");
7515 emitcode ("push", "acc");
7516 emitcode ("lcall", "__gptrget");
7517 emitcode ("pop", "b");
7521 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7522 emitcode ("orl", "a,b");
7525 if (p_type == GPOINTER)
7526 emitcode ("pop", "b");
7532 emitcode ("mov", "@%s,a", rname);
7536 emitcode ("movx", "@dptr,a");
7540 emitcode ("lcall", "__gptrput");
7544 /*-----------------------------------------------------------------*/
7545 /* genDataPointerSet - remat pointer to data space */
7546 /*-----------------------------------------------------------------*/
7548 genDataPointerSet (operand * right,
7552 int size, offset = 0;
7553 char *l, buffer[256];
7555 aopOp (right, ic, FALSE);
7557 l = aopGet (AOP (result), 0, FALSE, TRUE);
7558 size = AOP_SIZE (right);
7562 sprintf (buffer, "(%s + %d)", l + 1, offset);
7564 sprintf (buffer, "%s", l + 1);
7565 emitcode ("mov", "%s,%s", buffer,
7566 aopGet (AOP (right), offset++, FALSE, FALSE));
7569 freeAsmop (right, NULL, ic, TRUE);
7570 freeAsmop (result, NULL, ic, TRUE);
7573 /*-----------------------------------------------------------------*/
7574 /* genNearPointerSet - emitcode for near pointer put */
7575 /*-----------------------------------------------------------------*/
7577 genNearPointerSet (operand * right,
7585 sym_link *retype, *letype;
7586 sym_link *ptype = operandType (result);
7588 retype = getSpec (operandType (right));
7589 letype = getSpec (ptype);
7590 aopOp (result, ic, FALSE);
7592 /* if the result is rematerializable &
7593 in data space & not a bit variable */
7594 if (AOP_TYPE (result) == AOP_IMMD &&
7595 DCL_TYPE (ptype) == POINTER &&
7596 !IS_BITVAR (retype) &&
7597 !IS_BITVAR (letype))
7599 genDataPointerSet (right, result, ic);
7603 /* if the value is already in a pointer register
7604 then don't need anything more */
7605 if (!AOP_INPREG (AOP (result)))
7608 //AOP_TYPE (result) == AOP_STK
7612 // Aha, it is a pointer, just in disguise.
7613 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7616 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7617 __FILE__, __LINE__);
7622 rname++; // skip the '@'.
7627 /* otherwise get a free pointer register */
7629 preg = getFreePtr (ic, &aop, FALSE);
7630 emitcode ("mov", "%s,%s",
7632 aopGet (AOP (result), 0, FALSE, TRUE));
7638 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7641 aopOp (right, ic, FALSE);
7643 /* if bitfield then unpack the bits */
7644 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7645 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7648 /* we have can just get the values */
7649 int size = AOP_SIZE (right);
7654 l = aopGet (AOP (right), offset, FALSE, TRUE);
7658 emitcode ("mov", "@%s,a", rname);
7661 emitcode ("mov", "@%s,%s", rname, l);
7663 emitcode ("inc", "%s", rname);
7668 /* now some housekeeping stuff */
7669 if (aop) /* we had to allocate for this iCode */
7671 if (pi) aopPut (AOP (result),rname,0);
7672 freeAsmop (NULL, aop, ic, TRUE);
7676 /* we did not allocate which means left
7677 already in a pointer register, then
7678 if size > 0 && this could be used again
7679 we have to point it back to where it
7681 if ((AOP_SIZE (right) > 1 &&
7682 !OP_SYMBOL (result)->remat &&
7683 (OP_SYMBOL (result)->liveTo > ic->seq ||
7687 int size = AOP_SIZE (right) - 1;
7689 emitcode ("dec", "%s", rname);
7694 if (pi) pi->generated = 1;
7695 freeAsmop (result, NULL, ic, TRUE);
7696 freeAsmop (right, NULL, ic, TRUE);
7699 /*-----------------------------------------------------------------*/
7700 /* genPagedPointerSet - emitcode for Paged pointer put */
7701 /*-----------------------------------------------------------------*/
7703 genPagedPointerSet (operand * right,
7711 sym_link *retype, *letype;
7713 retype = getSpec (operandType (right));
7714 letype = getSpec (operandType (result));
7716 aopOp (result, ic, FALSE);
7718 /* if the value is already in a pointer register
7719 then don't need anything more */
7720 if (!AOP_INPREG (AOP (result)))
7722 /* otherwise get a free pointer register */
7724 preg = getFreePtr (ic, &aop, FALSE);
7725 emitcode ("mov", "%s,%s",
7727 aopGet (AOP (result), 0, FALSE, TRUE));
7731 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7733 aopOp (right, ic, FALSE);
7735 /* if bitfield then unpack the bits */
7736 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7737 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7740 /* we have can just get the values */
7741 int size = AOP_SIZE (right);
7746 l = aopGet (AOP (right), offset, FALSE, TRUE);
7749 emitcode ("movx", "@%s,a", rname);
7752 emitcode ("inc", "%s", rname);
7758 /* now some housekeeping stuff */
7759 if (aop) /* we had to allocate for this iCode */
7761 if (pi) aopPut (AOP (result),rname,0);
7762 freeAsmop (NULL, aop, ic, TRUE);
7766 /* we did not allocate which means left
7767 already in a pointer register, then
7768 if size > 0 && this could be used again
7769 we have to point it back to where it
7771 if (AOP_SIZE (right) > 1 &&
7772 !OP_SYMBOL (result)->remat &&
7773 (OP_SYMBOL (result)->liveTo > ic->seq ||
7776 int size = AOP_SIZE (right) - 1;
7778 emitcode ("dec", "%s", rname);
7783 if (pi) pi->generated = 1;
7784 freeAsmop (result, NULL, ic, TRUE);
7785 freeAsmop (right, NULL, ic, TRUE);
7790 /*-----------------------------------------------------------------*/
7791 /* genFarPointerSet - set value from far space */
7792 /*-----------------------------------------------------------------*/
7794 genFarPointerSet (operand * right,
7795 operand * result, iCode * ic, iCode * pi)
7798 sym_link *retype = getSpec (operandType (right));
7799 sym_link *letype = getSpec (operandType (result));
7800 aopOp (result, ic, FALSE);
7802 /* if the operand is already in dptr
7803 then we do nothing else we move the value to dptr */
7804 if (AOP_TYPE (result) != AOP_STR)
7806 /* if this is remateriazable */
7807 if (AOP_TYPE (result) == AOP_IMMD)
7808 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7810 { /* we need to get it byte by byte */
7811 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7812 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7815 /* so dptr know contains the address */
7816 aopOp (right, ic, FALSE);
7818 /* if bit then unpack */
7819 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7820 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7823 size = AOP_SIZE (right);
7828 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7830 emitcode ("movx", "@dptr,a");
7832 emitcode ("inc", "dptr");
7835 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7836 aopPut (AOP(result),"dpl",0);
7837 aopPut (AOP(result),"dph",1);
7840 freeAsmop (result, NULL, ic, TRUE);
7841 freeAsmop (right, NULL, ic, TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* genGenPointerSet - set value from generic pointer space */
7846 /*-----------------------------------------------------------------*/
7848 genGenPointerSet (operand * right,
7849 operand * result, iCode * ic, iCode * pi)
7852 sym_link *retype = getSpec (operandType (right));
7853 sym_link *letype = getSpec (operandType (result));
7855 aopOp (result, ic, FALSE);
7857 /* if the operand is already in dptr
7858 then we do nothing else we move the value to dptr */
7859 if (AOP_TYPE (result) != AOP_STR)
7861 /* if this is remateriazable */
7862 if (AOP_TYPE (result) == AOP_IMMD)
7864 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7865 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7868 { /* we need to get it byte by byte */
7869 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7870 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7871 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7874 /* so dptr know contains the address */
7875 aopOp (right, ic, FALSE);
7877 /* if bit then unpack */
7878 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7879 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7882 size = AOP_SIZE (right);
7887 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7889 emitcode ("lcall", "__gptrput");
7891 emitcode ("inc", "dptr");
7895 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7896 aopPut (AOP(result),"dpl",0);
7897 aopPut (AOP(result),"dph",1);
7900 freeAsmop (result, NULL, ic, TRUE);
7901 freeAsmop (right, NULL, ic, TRUE);
7904 /*-----------------------------------------------------------------*/
7905 /* genPointerSet - stores the value into a pointer location */
7906 /*-----------------------------------------------------------------*/
7908 genPointerSet (iCode * ic, iCode *pi)
7910 operand *right, *result;
7911 sym_link *type, *etype;
7914 right = IC_RIGHT (ic);
7915 result = IC_RESULT (ic);
7917 /* depending on the type of pointer we need to
7918 move it to the correct pointer register */
7919 type = operandType (result);
7920 etype = getSpec (type);
7921 /* if left is of type of pointer then it is simple */
7922 if (IS_PTR (type) && !IS_FUNC (type->next))
7924 p_type = DCL_TYPE (type);
7928 /* we have to go by the storage class */
7929 p_type = PTR_TYPE (SPEC_OCLS (etype));
7932 /* now that we have the pointer type we assign
7933 the pointer values */
7939 genNearPointerSet (right, result, ic, pi);
7943 genPagedPointerSet (right, result, ic, pi);
7947 genFarPointerSet (right, result, ic, pi);
7951 genGenPointerSet (right, result, ic, pi);
7957 /*-----------------------------------------------------------------*/
7958 /* genIfx - generate code for Ifx statement */
7959 /*-----------------------------------------------------------------*/
7961 genIfx (iCode * ic, iCode * popIc)
7963 operand *cond = IC_COND (ic);
7966 aopOp (cond, ic, FALSE);
7968 /* get the value into acc */
7969 if (AOP_TYPE (cond) != AOP_CRY)
7973 /* the result is now in the accumulator */
7974 freeAsmop (cond, NULL, ic, TRUE);
7976 /* if there was something to be popped then do it */
7980 /* if the condition is a bit variable */
7981 if (isbit && IS_ITEMP (cond) &&
7983 genIfxJump (ic, SPIL_LOC (cond)->rname);
7984 else if (isbit && !IS_ITEMP (cond))
7985 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7987 genIfxJump (ic, "a");
7992 /*-----------------------------------------------------------------*/
7993 /* genAddrOf - generates code for address of */
7994 /*-----------------------------------------------------------------*/
7996 genAddrOf (iCode * ic)
7998 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8001 aopOp (IC_RESULT (ic), ic, FALSE);
8003 /* if the operand is on the stack then we
8004 need to get the stack offset of this
8008 /* if it has an offset then we need to compute
8012 emitcode ("mov", "a,_bp");
8013 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8014 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8018 /* we can just move _bp */
8019 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8021 /* fill the result with zero */
8022 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8027 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8033 /* object not on stack then we need the name */
8034 size = AOP_SIZE (IC_RESULT (ic));
8039 char s[SDCC_NAME_MAX];
8041 sprintf (s, "#(%s >> %d)",
8045 sprintf (s, "#%s", sym->rname);
8046 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8050 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8054 /*-----------------------------------------------------------------*/
8055 /* genFarFarAssign - assignment when both are in far space */
8056 /*-----------------------------------------------------------------*/
8058 genFarFarAssign (operand * result, operand * right, iCode * ic)
8060 int size = AOP_SIZE (right);
8063 /* first push the right side on to the stack */
8066 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8068 emitcode ("push", "acc");
8071 freeAsmop (right, NULL, ic, FALSE);
8072 /* now assign DPTR to result */
8073 aopOp (result, ic, FALSE);
8074 size = AOP_SIZE (result);
8077 emitcode ("pop", "acc");
8078 aopPut (AOP (result), "a", --offset);
8080 freeAsmop (result, NULL, ic, FALSE);
8084 /*-----------------------------------------------------------------*/
8085 /* genAssign - generate code for assignment */
8086 /*-----------------------------------------------------------------*/
8088 genAssign (iCode * ic)
8090 operand *result, *right;
8092 unsigned long lit = 0L;
8094 D(emitcode(";","genAssign"));
8096 result = IC_RESULT (ic);
8097 right = IC_RIGHT (ic);
8099 /* if they are the same */
8100 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8103 aopOp (right, ic, FALSE);
8105 /* special case both in far space */
8106 if (AOP_TYPE (right) == AOP_DPTR &&
8107 IS_TRUE_SYMOP (result) &&
8108 isOperandInFarSpace (result))
8111 genFarFarAssign (result, right, ic);
8115 aopOp (result, ic, TRUE);
8117 /* if they are the same registers */
8118 if (sameRegs (AOP (right), AOP (result)))
8121 /* if the result is a bit */
8122 if (AOP_TYPE (result) == AOP_CRY)
8125 /* if the right size is a literal then
8126 we know what the value is */
8127 if (AOP_TYPE (right) == AOP_LIT)
8129 if (((int) operandLitValue (right)))
8130 aopPut (AOP (result), one, 0);
8132 aopPut (AOP (result), zero, 0);
8136 /* the right is also a bit variable */
8137 if (AOP_TYPE (right) == AOP_CRY)
8139 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8140 aopPut (AOP (result), "c", 0);
8146 aopPut (AOP (result), "a", 0);
8150 /* bit variables done */
8152 size = AOP_SIZE (result);
8154 if (AOP_TYPE (right) == AOP_LIT)
8155 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8157 (AOP_TYPE (result) != AOP_REG) &&
8158 (AOP_TYPE (right) == AOP_LIT) &&
8159 !IS_FLOAT (operandType (right)) &&
8162 emitcode ("clr", "a");
8165 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8166 aopPut (AOP (result), "a", size);
8168 aopPut (AOP (result),
8169 aopGet (AOP (right), size, FALSE, FALSE),
8177 aopPut (AOP (result),
8178 aopGet (AOP (right), offset, FALSE, FALSE),
8185 freeAsmop (right, NULL, ic, TRUE);
8186 freeAsmop (result, NULL, ic, TRUE);
8189 /*-----------------------------------------------------------------*/
8190 /* genJumpTab - genrates code for jump table */
8191 /*-----------------------------------------------------------------*/
8193 genJumpTab (iCode * ic)
8198 aopOp (IC_JTCOND (ic), ic, FALSE);
8199 /* get the condition into accumulator */
8200 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8202 /* multiply by three */
8203 emitcode ("add", "a,acc");
8204 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8205 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8207 jtab = newiTempLabel (NULL);
8208 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8209 emitcode ("jmp", "@a+dptr");
8210 emitcode ("", "%05d$:", jtab->key + 100);
8211 /* now generate the jump labels */
8212 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8213 jtab = setNextItem (IC_JTLABELS (ic)))
8214 emitcode ("ljmp", "%05d$", jtab->key + 100);
8218 /*-----------------------------------------------------------------*/
8219 /* genCast - gen code for casting */
8220 /*-----------------------------------------------------------------*/
8222 genCast (iCode * ic)
8224 operand *result = IC_RESULT (ic);
8225 sym_link *ctype = operandType (IC_LEFT (ic));
8226 sym_link *rtype = operandType (IC_RIGHT (ic));
8227 operand *right = IC_RIGHT (ic);
8230 D(emitcode(";", "genCast"));
8232 /* if they are equivalent then do nothing */
8233 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8236 aopOp (right, ic, FALSE);
8237 aopOp (result, ic, FALSE);
8239 /* if the result is a bit */
8240 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8241 if (IS_BITVAR(OP_SYMBOL(result)->type))
8243 /* if the right size is a literal then
8244 we know what the value is */
8245 if (AOP_TYPE (right) == AOP_LIT)
8247 if (((int) operandLitValue (right)))
8248 aopPut (AOP (result), one, 0);
8250 aopPut (AOP (result), zero, 0);
8255 /* the right is also a bit variable */
8256 if (AOP_TYPE (right) == AOP_CRY)
8258 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8259 aopPut (AOP (result), "c", 0);
8265 aopPut (AOP (result), "a", 0);
8269 /* if they are the same size : or less */
8270 if (AOP_SIZE (result) <= AOP_SIZE (right))
8273 /* if they are in the same place */
8274 if (sameRegs (AOP (right), AOP (result)))
8277 /* if they in different places then copy */
8278 size = AOP_SIZE (result);
8282 aopPut (AOP (result),
8283 aopGet (AOP (right), offset, FALSE, FALSE),
8291 /* if the result is of type pointer */
8296 sym_link *type = operandType (right);
8297 sym_link *etype = getSpec (type);
8299 /* pointer to generic pointer */
8300 if (IS_GENPTR (ctype))
8305 p_type = DCL_TYPE (type);
8308 if (SPEC_SCLS(etype)==S_REGISTER) {
8309 // let's assume it is a generic pointer
8312 /* we have to go by the storage class */
8313 p_type = PTR_TYPE (SPEC_OCLS (etype));
8317 /* the first two bytes are known */
8318 size = GPTRSIZE - 1;
8322 aopPut (AOP (result),
8323 aopGet (AOP (right), offset, FALSE, FALSE),
8327 /* the last byte depending on type */
8343 case PPOINTER: // what the fck is this?
8348 /* this should never happen */
8349 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8350 "got unknown pointer type");
8353 aopPut (AOP (result), l, GPTRSIZE - 1);
8357 /* just copy the pointers */
8358 size = AOP_SIZE (result);
8362 aopPut (AOP (result),
8363 aopGet (AOP (right), offset, FALSE, FALSE),
8370 /* so we now know that the size of destination is greater
8371 than the size of the source */
8372 /* we move to result for the size of source */
8373 size = AOP_SIZE (right);
8377 aopPut (AOP (result),
8378 aopGet (AOP (right), offset, FALSE, FALSE),
8383 /* now depending on the sign of the source && destination */
8384 size = AOP_SIZE (result) - AOP_SIZE (right);
8385 /* if unsigned or not an integral type */
8386 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8389 aopPut (AOP (result), zero, offset++);
8393 /* we need to extend the sign :{ */
8394 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8397 emitcode ("rlc", "a");
8398 emitcode ("subb", "a,acc");
8400 aopPut (AOP (result), "a", offset++);
8403 /* we are done hurray !!!! */
8406 freeAsmop (right, NULL, ic, TRUE);
8407 freeAsmop (result, NULL, ic, TRUE);
8411 /*-----------------------------------------------------------------*/
8412 /* genDjnz - generate decrement & jump if not zero instrucion */
8413 /*-----------------------------------------------------------------*/
8415 genDjnz (iCode * ic, iCode * ifx)
8421 /* if the if condition has a false label
8422 then we cannot save */
8426 /* if the minus is not of the form
8428 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8429 !IS_OP_LITERAL (IC_RIGHT (ic)))
8432 if (operandLitValue (IC_RIGHT (ic)) != 1)
8435 /* if the size of this greater than one then no
8437 if (getSize (operandType (IC_RESULT (ic))) > 1)
8440 /* otherwise we can save BIG */
8441 lbl = newiTempLabel (NULL);
8442 lbl1 = newiTempLabel (NULL);
8444 aopOp (IC_RESULT (ic), ic, FALSE);
8446 if (AOP_NEEDSACC(IC_RESULT(ic)))
8448 /* If the result is accessed indirectly via
8449 * the accumulator, we must explicitly write
8450 * it back after the decrement.
8452 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8454 if (strcmp(rByte, "a"))
8456 /* Something is hopelessly wrong */
8457 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8458 __FILE__, __LINE__);
8459 /* We can just give up; the generated code will be inefficient,
8462 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8465 emitcode ("dec", "%s", rByte);
8466 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8467 emitcode ("jnz", "%05d$", lbl->key + 100);
8469 else if (IS_AOP_PREG (IC_RESULT (ic)))
8471 emitcode ("dec", "%s",
8472 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8473 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8474 emitcode ("jnz", "%05d$", lbl->key + 100);
8478 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8481 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8482 emitcode ("", "%05d$:", lbl->key + 100);
8483 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8484 emitcode ("", "%05d$:", lbl1->key + 100);
8486 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8491 /*-----------------------------------------------------------------*/
8492 /* genReceive - generate code for a receive iCode */
8493 /*-----------------------------------------------------------------*/
8495 genReceive (iCode * ic)
8497 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8498 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8499 IS_TRUE_SYMOP (IC_RESULT (ic))))
8502 int size = getSize (operandType (IC_RESULT (ic)));
8503 int offset = fReturnSizeMCS51 - size;
8506 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8507 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8510 aopOp (IC_RESULT (ic), ic, FALSE);
8511 size = AOP_SIZE (IC_RESULT (ic));
8515 emitcode ("pop", "acc");
8516 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8523 aopOp (IC_RESULT (ic), ic, FALSE);
8525 assignResultValue (IC_RESULT (ic));
8528 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8531 /*-----------------------------------------------------------------*/
8532 /* gen51AggregateAssign - copy complete array's or structures */
8533 /*-----------------------------------------------------------------*/
8534 void gen51AggregateAssign(iCode *ic) {
8535 operand *left=IC_LEFT(ic);
8536 operand *right=IC_RIGHT(ic);
8537 char *fromName=OP_SYMBOL(right)->rname;
8538 char *toName=OP_SYMBOL(left)->rname;
8539 int fromSize=getSize(OP_SYMBOL(right)->type);
8540 int toSize=getSize(OP_SYMBOL(left)->type);
8543 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8544 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8545 // well, this code isn't used yet from anywhere else as for initialising
8546 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8550 if (fromSize!=toSize) {
8551 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8552 ic->filename, ic->lineno);
8557 // use the generic memcpy() for now
8558 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8559 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8560 emitcode ("mov", "a,#%s", fromName);
8561 emitcode ("movx", "@dptr,a");
8562 emitcode ("inc", "dptr");
8563 emitcode ("mov", "a,#(%s>>8)", fromName);
8564 emitcode ("movx", "@dptr,a");
8565 emitcode ("inc", "dptr");
8566 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8567 emitcode ("movx", "@dptr,a");
8568 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8569 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8570 emitcode ("movx", "@dptr,a");
8571 emitcode ("inc", "dptr");
8572 emitcode ("mov", "a,#(%d>>8)", count);
8573 emitcode ("movx", "@dptr,a");
8574 emitcode ("mov", "dptr,#%s", toName);
8575 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8576 emitcode ("lcall", "_memcpy");
8578 // more efficient, but will require the native_memcpy_cs2xs
8579 emitcode ("mov", "r0,#%s", fromName);
8580 emitcode ("mov", "r1,#(%s>>8)", fromName);
8581 emitcode ("mov", "r2,#%s", toName);
8582 emitcode ("mov", "r3,#(%s>>8)", toName);
8583 emitcode ("mov", "r4,#%d", count);
8584 emitcode ("mov", "r5,#(%d>>8)", count);
8585 emitcode ("lcall", "_native_memcpy_cs2xs");
8589 /*-----------------------------------------------------------------*/
8590 /* gen51Code - generate code for 8051 based controllers */
8591 /*-----------------------------------------------------------------*/
8593 gen51Code (iCode * lic)
8598 lineHead = lineCurr = NULL;
8600 /* print the allocation information */
8602 printAllocInfo (currFunc, codeOutFile);
8603 /* if debug information required */
8604 /* if (options.debug && currFunc) { */
8605 if (options.debug && currFunc)
8607 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8609 if (IS_STATIC (currFunc->etype))
8610 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8612 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8615 /* stack pointer name */
8616 if (options.useXstack)
8622 for (ic = lic; ic; ic = ic->next)
8625 if (cln != ic->lineno)
8630 emitcode ("", "C$%s$%d$%d$%d ==.",
8631 FileBaseName (ic->filename), ic->lineno,
8632 ic->level, ic->block);
8635 emitcode (";", "%s %d", ic->filename, ic->lineno);
8638 /* if the result is marked as
8639 spilt and rematerializable or code for
8640 this has already been generated then
8642 if (resultRemat (ic) || ic->generated)
8645 /* depending on the operation */
8665 /* IPOP happens only when trying to restore a
8666 spilt live range, if there is an ifx statement
8667 following this pop then the if statement might
8668 be using some of the registers being popped which
8669 would destory the contents of the register so
8670 we need to check for this condition and handle it */
8672 ic->next->op == IFX &&
8673 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8674 genIfx (ic->next, ic);
8692 genEndFunction (ic);
8712 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8729 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8733 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8740 /* note these two are xlated by algebraic equivalence
8741 during parsing SDCC.y */
8742 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8743 "got '>=' or '<=' shouldn't have come here");
8747 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8759 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8763 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8767 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8794 case GET_VALUE_AT_ADDRESS:
8795 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8799 if (POINTER_SET (ic))
8800 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8826 addSet (&_G.sendSet, ic);
8830 gen51AggregateAssign(ic);
8839 /* now we are ready to call the
8840 peep hole optimizer */
8841 if (!options.nopeep)
8842 peepHole (&lineHead);
8844 /* now do the actual printing */
8845 printLine (lineHead, codeOutFile);