1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
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!
25 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #define BETTER_LITERAL_SHIFT
53 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
66 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
67 static char *fReturn[] =
68 {"dpl", "dph", "dpx", "b", "a"};
69 static char *accUse[] =
72 static short rbank = -1;
86 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
93 #define MOVA(x) { char *_mova_tmp = strdup(x); \
94 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96 emitcode("mov","a,%s",_mova_tmp); \
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
122 /*-----------------------------------------------------------------*/
123 /* emitcode - writes the code into a file : for now it is simple */
124 /*-----------------------------------------------------------------*/
126 emitcode (char *inst, char *fmt,...)
129 char lb[INITIAL_INLINEASM];
137 sprintf (lb, "%s\t", inst);
139 sprintf (lb, "%s", inst);
140 vsprintf (lb + (strlen (lb)), fmt, ap);
143 vsprintf (lb, fmt, ap);
145 while (isspace (*lbp))
149 lineCurr = (lineCurr ?
150 connectLine (lineCurr, newLineNode (lb)) :
151 (lineHead = newLineNode (lb)));
152 lineCurr->isInline = _G.inLine;
153 lineCurr->isDebug = _G.debugLine;
157 /*-----------------------------------------------------------------*/
158 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
159 /*-----------------------------------------------------------------*/
161 getFreePtr (iCode * ic, asmop ** aopp, bool result)
163 bool r0iu = FALSE, r1iu = FALSE;
164 bool r0ou = FALSE, r1ou = FALSE;
166 /* the logic: if r0 & r1 used in the instruction
167 then we are in trouble otherwise */
169 /* first check if r0 & r1 are used by this
170 instruction, in which case we are in trouble */
171 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
172 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
177 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
178 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
180 /* if no usage of r0 then return it */
183 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
184 (*aopp)->type = AOP_R0;
186 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
189 /* if no usage of r1 then return it */
192 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
193 (*aopp)->type = AOP_R1;
195 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
198 /* now we know they both have usage */
199 /* if r0 not used in this instruction */
202 /* push it if not already pushed */
205 emitcode ("push", "%s",
206 ds390_regWithIdx (R0_IDX)->dname);
210 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
211 (*aopp)->type = AOP_R0;
213 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
216 /* if r1 not used then */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 ds390_regWithIdx (R1_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
229 (*aopp)->type = AOP_R1;
230 return ds390_regWithIdx (R1_IDX);
234 /* I said end of world but not quite end of world yet */
235 /* if this is a result then we can push it on the stack */
238 (*aopp)->type = AOP_STK;
242 /* other wise this is true end of the world */
243 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
244 "getFreePtr should never reach here");
248 /*-----------------------------------------------------------------*/
249 /* newAsmop - creates a new asmOp */
250 /*-----------------------------------------------------------------*/
252 newAsmop (short type)
256 aop = Safe_calloc (1, sizeof (asmop));
261 static int _currentDPS; /* Current processor DPS. */
262 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
263 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
265 /*-----------------------------------------------------------------*/
266 /* genSetDPTR: generate code to select which DPTR is in use (zero */
267 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
268 /* alternate DPTR (DPL1/DPH1/DPX1). */
269 /*-----------------------------------------------------------------*/
274 /* If we are doing lazy evaluation, simply note the desired
275 * change, but don't emit any code yet.
285 emitcode ("mov", "dps, #0x00");
289 emitcode ("mov", "dps, #0x01");
293 /*-----------------------------------------------------------------*/
294 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
296 /* Any code that operates on DPTR (NB: not on the individual */
297 /* components, like DPH) *must* call _flushLazyDPS() before using */
298 /* DPTR within a lazy DPS evaluation block. */
300 /* Note that aopPut and aopGet already contain the proper calls to */
301 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
302 /* DPS evaluation block. */
304 /* Also, _flushLazyDPS must be called before any flow control */
305 /* operations that could potentially branch out of the block. */
307 /* Lazy DPS evaluation is simply an optimization (though an */
308 /* important one), so if in doubt, leave it out. */
309 /*-----------------------------------------------------------------*/
311 _startLazyDPSEvaluation (void)
315 #ifdef BETTER_LITERAL_SHIFT
322 /*-----------------------------------------------------------------*/
323 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
324 /* desired one. Call before using DPTR within a lazy DPS evaluation */
326 /*-----------------------------------------------------------------*/
336 if (_desiredDPS != _currentDPS)
340 emitcode ("inc", "dps");
344 emitcode ("dec", "dps");
346 _currentDPS = _desiredDPS;
350 /*-----------------------------------------------------------------*/
351 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
353 /* Forces us back to the safe state (standard DPTR selected). */
354 /*-----------------------------------------------------------------*/
356 _endLazyDPSEvaluation (void)
358 #ifdef BETTER_LITERAL_SHIFT
377 /*-----------------------------------------------------------------*/
378 /* pointerCode - returns the code for a pointer type */
379 /*-----------------------------------------------------------------*/
381 pointerCode (sym_link * etype)
384 return PTR_TYPE (SPEC_OCLS (etype));
388 /*-----------------------------------------------------------------*/
389 /* aopForSym - for a true symbol */
390 /*-----------------------------------------------------------------*/
392 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
395 memmap *space = SPEC_OCLS (sym->etype);
397 /* if already has one */
401 /* assign depending on the storage class */
402 /* if it is on the stack or indirectly addressable */
403 /* space we need to assign either r0 or r1 to it */
404 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
406 sym->aop = aop = newAsmop (0);
407 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
408 aop->size = getSize (sym->type);
410 /* now assign the address of the variable to
411 the pointer register */
412 if (aop->type != AOP_STK)
418 emitcode ("push", "acc");
420 emitcode ("mov", "a,_bp");
421 emitcode ("add", "a,#0x%02x",
423 ((char) (sym->stack - _G.nRegsSaved)) :
424 ((char) sym->stack)) & 0xff);
425 emitcode ("mov", "%s,a",
426 aop->aopu.aop_ptr->name);
429 emitcode ("pop", "acc");
432 emitcode ("mov", "%s,#%s",
433 aop->aopu.aop_ptr->name,
435 aop->paged = space->paged;
438 aop->aopu.aop_stk = sym->stack;
442 if (sym->onStack && options.stack10bit)
444 /* It's on the 10 bit stack, which is located in
449 emitcode ("push", "acc");
451 emitcode ("mov", "a,_bp");
452 emitcode ("add", "a,#0x%02x",
454 ((char) (sym->stack - _G.nRegsSaved)) :
455 ((char) sym->stack)) & 0xff);
459 emitcode ("mov", "dpx1,#0x40");
460 emitcode ("mov", "dph1,#0x00");
461 emitcode ("mov", "dpl1, a");
465 emitcode ("mov", "dpx,#0x40");
466 emitcode ("mov", "dph,#0x00");
467 emitcode ("mov", "dpl, a");
471 emitcode ("pop", "acc");
473 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
474 aop->size = getSize (sym->type);
478 /* if in bit space */
479 if (IN_BITSPACE (space))
481 sym->aop = aop = newAsmop (AOP_CRY);
482 aop->aopu.aop_dir = sym->rname;
483 aop->size = getSize (sym->type);
486 /* if it is in direct space */
487 if (IN_DIRSPACE (space))
489 sym->aop = aop = newAsmop (AOP_DIR);
490 aop->aopu.aop_dir = sym->rname;
491 aop->size = getSize (sym->type);
495 /* special case for a function */
496 if (IS_FUNC (sym->type))
498 sym->aop = aop = newAsmop (AOP_IMMD);
499 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
500 strcpy (aop->aopu.aop_immd, sym->rname);
501 aop->size = FPTRSIZE;
505 /* only remaining is far space */
506 /* in which case DPTR gets the address */
507 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
512 emitcode ("mov", "dptr,#%s", sym->rname);
517 emitcode ("mov", "dptr,#%s", sym->rname);
519 aop->size = getSize (sym->type);
521 /* if it is in code space */
522 if (IN_CODESPACE (space))
528 /*-----------------------------------------------------------------*/
529 /* aopForRemat - rematerialzes an object */
530 /*-----------------------------------------------------------------*/
532 aopForRemat (symbol * sym)
534 iCode *ic = sym->rematiCode;
535 asmop *aop = newAsmop (AOP_IMMD);
542 val += (int) operandLitValue (IC_RIGHT (ic));
543 else if (ic->op == '-')
544 val -= (int) operandLitValue (IC_RIGHT (ic));
548 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
552 sprintf (buffer, "(%s %c 0x%04x)",
553 OP_SYMBOL (IC_LEFT (ic))->rname,
554 val >= 0 ? '+' : '-',
557 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
559 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
560 strcpy (aop->aopu.aop_immd, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
658 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
665 if (aop1->type != AOP_REG ||
666 aop2->type != AOP_REG)
669 if (aop1->size != aop2->size)
672 for (i = 0; i < aop1->size; i++)
673 if (aop1->aopu.aop_reg[i] !=
674 aop2->aopu.aop_reg[i])
680 /*-----------------------------------------------------------------*/
681 /* aopOp - allocates an asmop for an operand : */
682 /*-----------------------------------------------------------------*/
684 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
693 /* if this a literal */
694 if (IS_OP_LITERAL (op))
696 op->aop = aop = newAsmop (AOP_LIT);
697 aop->aopu.aop_lit = op->operand.valOperand;
698 aop->size = getSize (operandType (op));
702 /* if already has a asmop then continue */
706 /* if the underlying symbol has a aop */
707 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
709 op->aop = OP_SYMBOL (op)->aop;
713 /* if this is a true symbol */
714 if (IS_TRUE_SYMOP (op))
716 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
720 /* this is a temporary : this has
726 e) can be a return use only */
728 sym = OP_SYMBOL (op);
731 /* if the type is a conditional */
732 if (sym->regType == REG_CND)
734 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
739 /* if it is spilt then two situations
741 b) has a spill location */
742 if (sym->isspilt || sym->nRegs == 0)
745 /* rematerialize it NOW */
748 sym->aop = op->aop = aop =
750 aop->size = getSize (sym->type);
757 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
758 aop->size = getSize (sym->type);
759 for (i = 0; i < 2; i++)
760 aop->aopu.aop_str[i] = accUse[i];
770 /* a AOP_STR uses DPTR, but DPTR is already in use;
773 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
776 aop = op->aop = sym->aop = newAsmop (AOP_STR);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < (int) fReturnSizeDS390; i++)
779 aop->aopu.aop_str[i] = fReturn[i];
783 /* else spill location */
784 sym->aop = op->aop = aop =
785 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
786 aop->size = getSize (sym->type);
790 /* must be in a register */
791 sym->aop = op->aop = aop = newAsmop (AOP_REG);
792 aop->size = sym->nRegs;
793 for (i = 0; i < sym->nRegs; i++)
794 aop->aopu.aop_reg[i] = sym->regs[i];
797 /*-----------------------------------------------------------------*/
798 /* freeAsmop - free up the asmop given to an operand */
799 /*----------------------------------------------------------------*/
801 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
818 /* depending on the asmop type only three cases need work AOP_RO
819 , AOP_R1 && AOP_STK */
827 emitcode ("pop", "ar0");
831 bitVectUnSetBit (ic->rUsed, R0_IDX);
839 emitcode ("pop", "ar1");
843 bitVectUnSetBit (ic->rUsed, R1_IDX);
849 int stk = aop->aopu.aop_stk + aop->size;
850 bitVectUnSetBit (ic->rUsed, R0_IDX);
851 bitVectUnSetBit (ic->rUsed, R1_IDX);
853 getFreePtr (ic, &aop, FALSE);
855 if (options.stack10bit)
857 /* I'm not sure what to do here yet... */
860 "*** Warning: probably generating bad code for "
861 "10 bit stack mode.\n");
866 emitcode ("mov", "a,_bp");
867 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
868 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
872 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
877 emitcode ("pop", "acc");
878 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
881 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
884 freeAsmop (op, NULL, ic, TRUE);
887 emitcode ("pop", "ar0");
893 emitcode ("pop", "ar1");
900 /* all other cases just dealloc */
906 OP_SYMBOL (op)->aop = NULL;
907 /* if the symbol has a spill */
909 SPIL_LOC (op)->aop = NULL;
914 /*------------------------------------------------------------------*/
915 /* aopGet - for fetching value of the aop */
917 /* Set canClobberACC if you are sure it is OK to clobber the value */
918 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
919 /* just less efficient. */
920 /*------------------------------------------------------------------*/
932 /* offset is greater than
934 if (offset > (aop->size - 1) &&
935 aop->type != AOP_LIT)
938 /* depending on type */
944 /* if we need to increment it */
945 while (offset > aop->coff)
947 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
951 while (offset < aop->coff)
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
960 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
961 return (dname ? "acc" : "a");
963 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
964 rs = Safe_calloc (1, strlen (s) + 1);
971 if (aop->type == AOP_DPTR2)
976 emitcode ("xch", "a, %s", DP2_RESULT_REG);
982 while (offset > aop->coff)
984 emitcode ("inc", "dptr");
988 while (offset < aop->coff)
990 emitcode ("lcall", "__decdptr");
997 emitcode ("clr", "a");
998 emitcode ("movc", "a,@a+dptr");
1002 emitcode ("movx", "a,@dptr");
1005 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011 return DP2_RESULT_REG;
1014 return (dname ? "acc" : "a");
1018 sprintf (s, "#%s", aop->aopu.aop_immd);
1020 sprintf (s, "#(%s >> %d)",
1025 aop->aopu.aop_immd);
1026 rs = Safe_calloc (1, strlen (s) + 1);
1032 sprintf (s, "(%s + %d)",
1036 sprintf (s, "%s", aop->aopu.aop_dir);
1037 rs = Safe_calloc (1, strlen (s) + 1);
1043 return aop->aopu.aop_reg[offset]->dname;
1045 return aop->aopu.aop_reg[offset]->name;
1048 emitcode ("clr", "a");
1049 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1050 emitcode ("rlc", "a");
1051 return (dname ? "acc" : "a");
1054 if (!offset && dname)
1056 return aop->aopu.aop_str[offset];
1059 return aopLiteral (aop->aopu.aop_lit, offset);
1063 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1067 return aop->aopu.aop_str[offset];
1071 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1072 "aopget got unsupported aop->type");
1075 /*-----------------------------------------------------------------*/
1076 /* aopPut - puts a string for a aop */
1077 /*-----------------------------------------------------------------*/
1079 aopPut (asmop * aop, char *s, int offset)
1083 if (aop->size && offset > (aop->size - 1))
1085 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1086 "aopPut got offset > aop->size");
1090 /* will assign value to value */
1091 /* depending on where it is ofcourse */
1096 sprintf (d, "(%s + %d)",
1097 aop->aopu.aop_dir, offset);
1099 sprintf (d, "%s", aop->aopu.aop_dir);
1102 emitcode ("mov", "%s,%s", d, s);
1107 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1108 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1111 strcmp (s, "r0") == 0 ||
1112 strcmp (s, "r1") == 0 ||
1113 strcmp (s, "r2") == 0 ||
1114 strcmp (s, "r3") == 0 ||
1115 strcmp (s, "r4") == 0 ||
1116 strcmp (s, "r5") == 0 ||
1117 strcmp (s, "r6") == 0 ||
1118 strcmp (s, "r7") == 0)
1119 emitcode ("mov", "%s,%s",
1120 aop->aopu.aop_reg[offset]->dname, s);
1122 emitcode ("mov", "%s,%s",
1123 aop->aopu.aop_reg[offset]->name, s);
1130 if (aop->type == AOP_DPTR2)
1138 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139 "aopPut writting to code space");
1143 while (offset > aop->coff)
1146 emitcode ("inc", "dptr");
1149 while (offset < aop->coff)
1152 emitcode ("lcall", "__decdptr");
1157 /* if not in accumulater */
1160 emitcode ("movx", "@dptr,a");
1162 if (aop->type == AOP_DPTR2)
1170 while (offset > aop->coff)
1173 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1175 while (offset < aop->coff)
1178 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1185 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1191 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1193 else if (strcmp (s, "r0") == 0 ||
1194 strcmp (s, "r1") == 0 ||
1195 strcmp (s, "r2") == 0 ||
1196 strcmp (s, "r3") == 0 ||
1197 strcmp (s, "r4") == 0 ||
1198 strcmp (s, "r5") == 0 ||
1199 strcmp (s, "r6") == 0 ||
1200 strcmp (s, "r7") == 0)
1203 sprintf (buffer, "a%s", s);
1204 emitcode ("mov", "@%s,%s",
1205 aop->aopu.aop_ptr->name, buffer);
1208 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1213 if (strcmp (s, "a") == 0)
1214 emitcode ("push", "acc");
1216 emitcode ("push", "%s", s);
1221 /* if bit variable */
1222 if (!aop->aopu.aop_dir)
1224 emitcode ("clr", "a");
1225 emitcode ("rlc", "a");
1230 emitcode ("clr", "%s", aop->aopu.aop_dir);
1232 emitcode ("setb", "%s", aop->aopu.aop_dir);
1233 else if (!strcmp (s, "c"))
1234 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237 if (strcmp (s, "a"))
1242 symbol *lbl = newiTempLabel (NULL);
1243 emitcode ("clr", "c");
1244 emitcode ("jz", "%05d$", lbl->key + 100);
1245 emitcode ("cpl", "c");
1246 emitcode ("", "%05d$:", lbl->key + 100);
1247 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1255 if (strcmp (aop->aopu.aop_str[offset], s))
1256 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1261 if (!offset && (strcmp (s, "acc") == 0))
1264 if (strcmp (aop->aopu.aop_str[offset], s))
1265 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1270 "aopPut got unsupported aop->type");
1277 /*--------------------------------------------------------------------*/
1278 /* reAdjustPreg - points a register back to where it should (coff==0) */
1279 /*--------------------------------------------------------------------*/
1281 reAdjustPreg (asmop * aop)
1283 if ((aop->coff==0) || (aop->size <= 1)) {
1292 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1296 if (aop->type == AOP_DPTR2)
1303 emitcode ("lcall", "__decdptr");
1306 if (aop->type == AOP_DPTR2)
1316 #define AOP(op) op->aop
1317 #define AOP_TYPE(op) AOP(op)->type
1318 #define AOP_SIZE(op) AOP(op)->size
1319 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1320 AOP_TYPE(x) == AOP_R0))
1322 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1323 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1326 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1327 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1328 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1330 /* Workaround for DS80C390 bug: div ab may return bogus results
1331 * if A is accessed in instruction immediately before the div.
1333 * Will be fixed in B4 rev of processor, Dallas claims.
1336 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1337 if (!AOP_NEEDSACC(RIGHT)) \
1339 /* We can load A first, then B, since \
1340 * B (the RIGHT operand) won't clobber A, \
1341 * thus avoiding touching A right before the div. \
1343 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1344 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1346 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1350 /* Just stuff in a nop after loading A. */ \
1351 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1352 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1354 emitcode("nop", "; workaround for DS80C390 div bug."); \
1357 /*-----------------------------------------------------------------*/
1358 /* genNotFloat - generates not for float operations */
1359 /*-----------------------------------------------------------------*/
1361 genNotFloat (operand * op, operand * res)
1367 D (emitcode (";", "genNotFloat ");
1370 /* we will put 127 in the first byte of
1372 aopPut (AOP (res), "#127", 0);
1373 size = AOP_SIZE (op) - 1;
1376 _startLazyDPSEvaluation ();
1377 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1382 emitcode ("orl", "a,%s",
1384 offset++, FALSE, FALSE, FALSE));
1386 _endLazyDPSEvaluation ();
1388 tlbl = newiTempLabel (NULL);
1389 aopPut (res->aop, one, 1);
1390 emitcode ("jz", "%05d$", (tlbl->key + 100));
1391 aopPut (res->aop, zero, 1);
1392 emitcode ("", "%05d$:", (tlbl->key + 100));
1394 size = res->aop->size - 2;
1396 /* put zeros in the rest */
1398 aopPut (res->aop, zero, offset++);
1401 /*-----------------------------------------------------------------*/
1402 /* opIsGptr: returns non-zero if the passed operand is */
1403 /* a generic pointer type. */
1404 /*-----------------------------------------------------------------*/
1406 opIsGptr (operand * op)
1408 sym_link *type = operandType (op);
1410 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1417 /*-----------------------------------------------------------------*/
1418 /* getDataSize - get the operand data size */
1419 /*-----------------------------------------------------------------*/
1421 getDataSize (operand * op)
1424 size = AOP_SIZE (op);
1425 if (size == GPTRSIZE)
1427 sym_link *type = operandType (op);
1428 if (IS_GENPTR (type))
1430 /* generic pointer; arithmetic operations
1431 * should ignore the high byte (pointer type).
1439 /*-----------------------------------------------------------------*/
1440 /* outAcc - output Acc */
1441 /*-----------------------------------------------------------------*/
1443 outAcc (operand * result)
1446 size = getDataSize (result);
1449 aopPut (AOP (result), "a", 0);
1452 /* unsigned or positive */
1455 aopPut (AOP (result), zero, offset++);
1460 /*-----------------------------------------------------------------*/
1461 /* outBitC - output a bit C */
1462 /*-----------------------------------------------------------------*/
1464 outBitC (operand * result)
1466 /* if the result is bit */
1467 if (AOP_TYPE (result) == AOP_CRY)
1469 aopPut (AOP (result), "c", 0);
1473 emitcode ("clr", "a");
1474 emitcode ("rlc", "a");
1479 /*-----------------------------------------------------------------*/
1480 /* toBoolean - emit code for orl a,operator(sizeop) */
1481 /*-----------------------------------------------------------------*/
1483 toBoolean (operand * oper)
1485 int size = AOP_SIZE (oper) - 1;
1489 /* The generic part of a generic pointer should
1490 * not participate in it's truth value.
1492 * i.e. 0x10000000 is zero.
1494 if (opIsGptr (oper))
1496 D (emitcode (";", "toBoolean: generic ptr special case.");
1501 _startLazyDPSEvaluation ();
1502 if (AOP_NEEDSACC (oper) && size)
1505 emitcode ("push", "b");
1506 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1510 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1516 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1520 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1523 _endLazyDPSEvaluation ();
1527 emitcode ("mov", "a,b");
1528 emitcode ("pop", "b");
1533 /*-----------------------------------------------------------------*/
1534 /* genNot - generate code for ! operation */
1535 /*-----------------------------------------------------------------*/
1540 sym_link *optype = operandType (IC_LEFT (ic));
1542 D (emitcode (";", "genNot ");
1545 /* assign asmOps to operand & result */
1546 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1547 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1549 /* if in bit space then a special case */
1550 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1552 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1553 emitcode ("cpl", "c");
1554 outBitC (IC_RESULT (ic));
1558 /* if type float then do float */
1559 if (IS_FLOAT (optype))
1561 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1565 toBoolean (IC_LEFT (ic));
1567 tlbl = newiTempLabel (NULL);
1568 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1569 emitcode ("", "%05d$:", tlbl->key + 100);
1570 outBitC (IC_RESULT (ic));
1573 /* release the aops */
1574 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1575 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1579 /*-----------------------------------------------------------------*/
1580 /* genCpl - generate code for complement */
1581 /*-----------------------------------------------------------------*/
1588 D (emitcode (";", "genCpl ");
1592 /* assign asmOps to operand & result */
1593 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1594 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1596 /* if both are in bit space then
1598 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1599 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1602 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1603 emitcode ("cpl", "c");
1604 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1608 size = AOP_SIZE (IC_RESULT (ic));
1609 _startLazyDPSEvaluation ();
1612 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1614 emitcode ("cpl", "a");
1615 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1617 _endLazyDPSEvaluation ();
1621 /* release the aops */
1622 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1623 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* genUminusFloat - unary minus for floating points */
1628 /*-----------------------------------------------------------------*/
1630 genUminusFloat (operand * op, operand * result)
1632 int size, offset = 0;
1634 /* for this we just need to flip the
1635 first it then copy the rest in place */
1636 D (emitcode (";", "genUminusFloat");
1639 _startLazyDPSEvaluation ();
1640 size = AOP_SIZE (op) - 1;
1641 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1644 emitcode ("cpl", "acc.7");
1645 aopPut (AOP (result), "a", 3);
1649 aopPut (AOP (result),
1650 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1654 _endLazyDPSEvaluation ();
1657 /*-----------------------------------------------------------------*/
1658 /* genUminus - unary minus code generation */
1659 /*-----------------------------------------------------------------*/
1661 genUminus (iCode * ic)
1664 sym_link *optype, *rtype;
1666 D (emitcode (";", "genUminus ");
1671 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1672 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1674 /* if both in bit space then special
1676 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1677 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1680 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1681 emitcode ("cpl", "c");
1682 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1686 optype = operandType (IC_LEFT (ic));
1687 rtype = operandType (IC_RESULT (ic));
1689 /* if float then do float stuff */
1690 if (IS_FLOAT (optype))
1692 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1696 /* otherwise subtract from zero */
1697 size = AOP_SIZE (IC_LEFT (ic));
1699 _startLazyDPSEvaluation ();
1702 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1703 if (!strcmp (l, "a"))
1707 emitcode ("cpl", "a");
1708 emitcode ("addc", "a,#0");
1714 emitcode ("clr", "a");
1715 emitcode ("subb", "a,%s", l);
1717 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1719 _endLazyDPSEvaluation ();
1721 /* if any remaining bytes in the result */
1722 /* we just need to propagate the sign */
1723 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1725 emitcode ("rlc", "a");
1726 emitcode ("subb", "a,acc");
1728 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1732 /* release the aops */
1733 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1734 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1737 /*-----------------------------------------------------------------*/
1738 /* saveRegisters - will look for a call and save the registers */
1739 /*-----------------------------------------------------------------*/
1741 saveRegisters (iCode * lic)
1749 for (ic = lic; ic; ic = ic->next)
1750 if (ic->op == CALL || ic->op == PCALL)
1755 fprintf (stderr, "found parameter push with no function call\n");
1759 /* if the registers have been saved already then
1761 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1764 /* find the registers in use at this time
1765 and push them away to safety */
1766 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1770 if (options.useXstack)
1772 if (bitVectBitValue (rsave, R0_IDX))
1773 emitcode ("mov", "b,r0");
1774 emitcode ("mov", "r0,%s", spname);
1775 for (i = 0; i < ds390_nRegs; i++)
1777 if (bitVectBitValue (rsave, i))
1780 emitcode ("mov", "a,b");
1782 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1783 emitcode ("movx", "@r0,a");
1784 emitcode ("inc", "r0");
1787 emitcode ("mov", "%s,r0", spname);
1788 if (bitVectBitValue (rsave, R0_IDX))
1789 emitcode ("mov", "r0,b");
1792 for (i = 0; i < ds390_nRegs; i++)
1794 if (bitVectBitValue (rsave, i))
1795 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1798 detype = getSpec (operandType (IC_LEFT (ic)));
1800 #if 0 // why should we do this here??? jwk20011105
1802 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1803 IS_ISR (currFunc->etype) &&
1805 saveRBank (SPEC_BANK (detype), ic, TRUE);
1809 /*-----------------------------------------------------------------*/
1810 /* unsaveRegisters - pop the pushed registers */
1811 /*-----------------------------------------------------------------*/
1813 unsaveRegisters (iCode * ic)
1817 /* find the registers in use at this time
1818 and push them away to safety */
1819 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1822 if (options.useXstack)
1824 emitcode ("mov", "r0,%s", spname);
1825 for (i = ds390_nRegs; i >= 0; i--)
1827 if (bitVectBitValue (rsave, i))
1829 emitcode ("dec", "r0");
1830 emitcode ("movx", "a,@r0");
1832 emitcode ("mov", "b,a");
1834 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1838 emitcode ("mov", "%s,r0", spname);
1839 if (bitVectBitValue (rsave, R0_IDX))
1840 emitcode ("mov", "r0,b");
1843 for (i = ds390_nRegs; i >= 0; i--)
1845 if (bitVectBitValue (rsave, i))
1846 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1852 /*-----------------------------------------------------------------*/
1854 /*-----------------------------------------------------------------*/
1856 pushSide (operand * oper, int size)
1859 _startLazyDPSEvaluation ();
1862 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1863 if (AOP_TYPE (oper) != AOP_REG &&
1864 AOP_TYPE (oper) != AOP_DIR &&
1867 emitcode ("mov", "a,%s", l);
1868 emitcode ("push", "acc");
1871 emitcode ("push", "%s", l);
1873 _endLazyDPSEvaluation ();
1876 /*-----------------------------------------------------------------*/
1877 /* assignResultValue - */
1878 /*-----------------------------------------------------------------*/
1880 assignResultValue (operand * oper)
1883 int size = AOP_SIZE (oper);
1885 _startLazyDPSEvaluation ();
1888 aopPut (AOP (oper), fReturn[offset], offset);
1891 _endLazyDPSEvaluation ();
1895 /*-----------------------------------------------------------------*/
1896 /* genXpush - pushes onto the external stack */
1897 /*-----------------------------------------------------------------*/
1899 genXpush (iCode * ic)
1901 asmop *aop = newAsmop (0);
1903 int size, offset = 0;
1905 D (emitcode (";", "genXpush ");
1908 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1909 r = getFreePtr (ic, &aop, FALSE);
1912 emitcode ("mov", "%s,_spx", r->name);
1914 size = AOP_SIZE (IC_LEFT (ic));
1915 _startLazyDPSEvaluation ();
1919 char *l = aopGet (AOP (IC_LEFT (ic)),
1920 offset++, FALSE, FALSE, TRUE);
1922 emitcode ("movx", "@%s,a", r->name);
1923 emitcode ("inc", "%s", r->name);
1926 _endLazyDPSEvaluation ();
1929 emitcode ("mov", "_spx,%s", r->name);
1931 freeAsmop (NULL, aop, ic, TRUE);
1932 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1935 /*-----------------------------------------------------------------*/
1936 /* genIpush - genrate code for pushing this gets a little complex */
1937 /*-----------------------------------------------------------------*/
1939 genIpush (iCode * ic)
1941 int size, offset = 0;
1944 D (emitcode (";", "genIpush ");
1947 /* if this is not a parm push : ie. it is spill push
1948 and spill push is always done on the local stack */
1952 /* and the item is spilt then do nothing */
1953 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1956 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1957 size = AOP_SIZE (IC_LEFT (ic));
1958 /* push it on the stack */
1959 _startLazyDPSEvaluation ();
1962 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1968 emitcode ("push", "%s", l);
1970 _endLazyDPSEvaluation ();
1974 /* this is a paramter push: in this case we call
1975 the routine to find the call and save those
1976 registers that need to be saved */
1979 /* if use external stack then call the external
1980 stack pushing routine */
1981 if (options.useXstack)
1987 /* then do the push */
1988 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1990 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1991 size = AOP_SIZE (IC_LEFT (ic));
1993 _startLazyDPSEvaluation ();
1996 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1997 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1998 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2001 emitcode ("mov", "a,%s", l);
2002 emitcode ("push", "acc");
2005 emitcode ("push", "%s", l);
2007 _endLazyDPSEvaluation ();
2009 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genIpop - recover the registers: can happen only for spilling */
2014 /*-----------------------------------------------------------------*/
2016 genIpop (iCode * ic)
2020 D (emitcode (";", "genIpop ");
2024 /* if the temp was not pushed then */
2025 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2028 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2029 size = AOP_SIZE (IC_LEFT (ic));
2030 offset = (size - 1);
2031 _startLazyDPSEvaluation ();
2034 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2035 FALSE, TRUE, TRUE));
2037 _endLazyDPSEvaluation ();
2039 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2042 /*-----------------------------------------------------------------*/
2043 /* unsaveRBank - restores the resgister bank from stack */
2044 /*-----------------------------------------------------------------*/
2046 unsaveRBank (int bank, iCode * ic, bool popPsw)
2054 if (options.useXstack)
2058 werror(E_INTERNAL_ERROR, __FILE__, __LINE__,
2059 "unexpected null IC in saveRBank");
2064 r = getFreePtr (ic, &aop, FALSE);
2067 emitcode ("mov", "%s,_spx", r->name);
2068 emitcode ("movx", "a,@%s", r->name);
2069 emitcode ("mov", "psw,a");
2070 emitcode ("dec", "%s", r->name);
2074 emitcode ("pop", "psw");
2077 for (i = (ds390_nRegs - 1); i >= 0; i--)
2079 if (options.useXstack)
2081 emitcode ("movx", "a,@%s", r->name);
2082 emitcode ("mov", "(%s+%d),a",
2083 regs390[i].base, 8 * bank + regs390[i].offset);
2084 emitcode ("dec", "%s", r->name);
2088 emitcode ("pop", "(%s+%d)",
2089 regs390[i].base, 8 * bank + regs390[i].offset);
2092 if (options.useXstack)
2095 emitcode ("mov", "_spx,%s", r->name);
2096 freeAsmop (NULL, aop, ic, TRUE);
2101 /*-----------------------------------------------------------------*/
2102 /* saveRBank - saves an entire register bank on the stack */
2103 /*-----------------------------------------------------------------*/
2105 saveRBank (int bank, iCode * ic, bool pushPsw)
2111 if (options.useXstack)
2115 werror(E_INTERNAL_ERROR, __FILE__, __LINE__,
2116 "unexpected null IC in saveRBank");
2120 r = getFreePtr (ic, &aop, FALSE);
2121 emitcode ("mov", "%s,_spx", r->name);
2125 for (i = 0; i < ds390_nRegs; i++)
2127 if (options.useXstack)
2129 emitcode ("inc", "%s", r->name);
2130 emitcode ("mov", "a,(%s+%d)",
2131 regs390[i].base, 8 * bank + regs390[i].offset);
2132 emitcode ("movx", "@%s,a", r->name);
2135 emitcode ("push", "(%s+%d)",
2136 regs390[i].base, 8 * bank + regs390[i].offset);
2141 if (options.useXstack)
2143 emitcode ("mov", "a,psw");
2144 emitcode ("movx", "@%s,a", r->name);
2145 emitcode ("inc", "%s", r->name);
2146 emitcode ("mov", "_spx,%s", r->name);
2147 freeAsmop (NULL, aop, ic, TRUE);
2152 emitcode ("push", "psw");
2155 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2164 /*-----------------------------------------------------------------*/
2165 /* genCall - generates a call statement */
2166 /*-----------------------------------------------------------------*/
2168 genCall (iCode * ic)
2171 bool restoreBank = FALSE;
2172 bool swapBanks = FALSE;
2174 D (emitcode (";", "genCall "););
2176 /* if we are calling a function that is not using
2177 the same register bank then we need to save the
2178 destination registers on the stack */
2179 detype = getSpec (operandType (IC_LEFT (ic)));
2181 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2182 IS_ISR (currFunc->etype))
2186 /* This is unexpected; the bank should have been saved in
2189 saveRBank (SPEC_BANK (detype), ic, FALSE);
2195 /* if caller saves & we have not saved then */
2199 /* if send set is not empty the assign */
2200 /* We've saved all the registers we care about;
2201 * therefore, we may clobber any register not used
2202 * in the calling convention (i.e. anything not in
2209 for (sic = setFirstItem (_G.sendSet); sic;
2210 sic = setNextItem (_G.sendSet))
2212 int size, offset = 0;
2214 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2215 size = AOP_SIZE (IC_LEFT (sic));
2217 _startLazyDPSEvaluation ();
2220 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2221 FALSE, FALSE, TRUE);
2222 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2224 emitcode("mov", "%s,%s", regs390[offset].name, l);
2226 else if (strcmp (l, fReturn[offset]))
2228 emitcode ("mov", "%s,%s",
2234 _endLazyDPSEvaluation ();
2235 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2237 size = AOP_SIZE (IC_LEFT (sic));
2245 emitcode("mov", "%s,%s",
2246 fReturn[size], regs390[size].name);
2249 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2256 emitcode ("mov", "psw,#0x%02x",
2257 ((SPEC_BANK(detype)) << 3) & 0xff);
2261 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2262 OP_SYMBOL (IC_LEFT (ic))->rname :
2263 OP_SYMBOL (IC_LEFT (ic))->name));
2267 emitcode ("mov", "psw,#0x%02x",
2268 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
2271 /* if we need assign a result value */
2272 if ((IS_ITEMP (IC_RESULT (ic)) &&
2273 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2274 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2275 IS_TRUE_SYMOP (IC_RESULT (ic)))
2277 if (isOperandInFarSpace (IC_RESULT (ic))
2278 && getSize (operandType (IC_RESULT (ic))) <= 2)
2280 int size = getSize (operandType (IC_RESULT (ic)));
2282 /* Special case for 1 or 2 byte return in far space. */
2286 emitcode ("mov", "b,%s", fReturn[1]);
2289 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2290 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2294 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2296 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2301 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2304 assignResultValue (IC_RESULT (ic));
2306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2310 /* adjust the stack for parameters if
2315 if (ic->parmBytes > 3)
2317 emitcode ("mov", "a,%s", spname);
2318 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2319 emitcode ("mov", "%s,a", spname);
2322 for (i = 0; i < ic->parmBytes; i++)
2323 emitcode ("dec", "%s", spname);
2326 /* if we hade saved some registers then unsave them */
2327 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2328 unsaveRegisters (ic);
2330 /* if register bank was saved then pop them */
2332 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
2335 /*-----------------------------------------------------------------*/
2336 /* genPcall - generates a call by pointer statement */
2337 /*-----------------------------------------------------------------*/
2339 genPcall (iCode * ic)
2342 symbol *rlbl = newiTempLabel (NULL);
2344 D (emitcode (";", "genPcall ");
2348 /* if caller saves & we have not saved then */
2352 /* if we are calling a function that is not using
2353 the same register bank then we need to save the
2354 destination registers on the stack */
2355 detype = getSpec (operandType (IC_LEFT (ic)));
2357 IS_ISR (currFunc->etype) &&
2358 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2359 saveRBank (SPEC_BANK (detype), ic, TRUE);
2362 /* push the return address on to the stack */
2363 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2364 emitcode ("push", "acc");
2365 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2366 emitcode ("push", "acc");
2368 if (options.model == MODEL_FLAT24)
2370 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2371 emitcode ("push", "acc");
2374 /* now push the calling address */
2375 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2377 pushSide (IC_LEFT (ic), FPTRSIZE);
2379 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2381 /* if send set is not empty the assign */
2386 for (sic = setFirstItem (_G.sendSet); sic;
2387 sic = setNextItem (_G.sendSet))
2389 int size, offset = 0;
2391 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2392 size = AOP_SIZE (IC_LEFT (sic));
2393 _startLazyDPSEvaluation ();
2396 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2397 FALSE, FALSE, TRUE);
2398 if (strcmp (l, fReturn[offset]))
2400 emitcode ("mov", "%s,%s",
2406 _endLazyDPSEvaluation ();
2407 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2412 emitcode ("ret", "");
2413 emitcode ("", "%05d$:", (rlbl->key + 100));
2416 /* if we need assign a result value */
2417 if ((IS_ITEMP (IC_RESULT (ic)) &&
2418 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2419 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2420 IS_TRUE_SYMOP (IC_RESULT (ic)))
2424 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2427 assignResultValue (IC_RESULT (ic));
2429 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2432 /* adjust the stack for parameters if
2437 if (ic->parmBytes > 3)
2439 emitcode ("mov", "a,%s", spname);
2440 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2441 emitcode ("mov", "%s,a", spname);
2444 for (i = 0; i < ic->parmBytes; i++)
2445 emitcode ("dec", "%s", spname);
2449 /* if register bank was saved then unsave them */
2451 (SPEC_BANK (currFunc->etype) !=
2452 SPEC_BANK (detype)))
2453 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2455 /* if we hade saved some registers then
2458 unsaveRegisters (ic);
2462 /*-----------------------------------------------------------------*/
2463 /* resultRemat - result is rematerializable */
2464 /*-----------------------------------------------------------------*/
2466 resultRemat (iCode * ic)
2468 if (SKIP_IC (ic) || ic->op == IFX)
2471 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2473 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2474 if (sym->remat && !POINTER_SET (ic))
2481 #if defined(__BORLANDC__) || defined(_MSC_VER)
2482 #define STRCASECMP stricmp
2484 #define STRCASECMP strcasecmp
2487 /*-----------------------------------------------------------------*/
2488 /* inExcludeList - return 1 if the string is in exclude Reg list */
2489 /*-----------------------------------------------------------------*/
2491 inExcludeList (char *s)
2495 if (options.excludeRegs[i] &&
2496 STRCASECMP (options.excludeRegs[i], "none") == 0)
2499 for (i = 0; options.excludeRegs[i]; i++)
2501 if (options.excludeRegs[i] &&
2502 STRCASECMP (s, options.excludeRegs[i]) == 0)
2508 /*-----------------------------------------------------------------*/
2509 /* genFunction - generated code for function entry */
2510 /*-----------------------------------------------------------------*/
2512 genFunction (iCode * ic)
2517 D (emitcode (";", "genFunction "););
2520 /* create the function header */
2521 emitcode (";", "-----------------------------------------");
2522 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2523 emitcode (";", "-----------------------------------------");
2525 emitcode ("", "%s:", sym->rname);
2526 fetype = getSpec (operandType (IC_LEFT (ic)));
2528 /* if critical function then turn interrupts off */
2529 if (SPEC_CRTCL (fetype))
2530 emitcode ("clr", "ea");
2532 /* here we need to generate the equates for the
2533 register bank if required */
2534 if (SPEC_BANK (fetype) != rbank)
2538 rbank = SPEC_BANK (fetype);
2539 for (i = 0; i < ds390_nRegs; i++)
2541 if (strcmp (regs390[i].base, "0") == 0)
2542 emitcode ("", "%s = 0x%02x",
2544 8 * rbank + regs390[i].offset);
2546 emitcode ("", "%s = %s + 0x%02x",
2549 8 * rbank + regs390[i].offset);
2553 /* if this is an interrupt service routine then
2554 save acc, b, dpl, dph */
2555 if (IS_ISR (sym->etype))
2558 if (!inExcludeList ("acc"))
2559 emitcode ("push", "acc");
2560 if (!inExcludeList ("b"))
2561 emitcode ("push", "b");
2562 if (!inExcludeList ("dpl"))
2563 emitcode ("push", "dpl");
2564 if (!inExcludeList ("dph"))
2565 emitcode ("push", "dph");
2566 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2568 emitcode ("push", "dpx");
2569 /* Make sure we're using standard DPTR */
2570 emitcode ("push", "dps");
2571 emitcode ("mov", "dps, #0x00");
2572 if (options.stack10bit)
2574 /* This ISR could conceivably use DPTR2. Better save it. */
2575 emitcode ("push", "dpl1");
2576 emitcode ("push", "dph1");
2577 emitcode ("push", "dpx1");
2578 emitcode ("push", DP2_RESULT_REG);
2581 /* if this isr has no bank i.e. is going to
2582 run with bank 0 , then we need to save more
2584 if (!SPEC_BANK (sym->etype))
2587 /* if this function does not call any other
2588 function then we can be economical and
2589 save only those registers that are used */
2594 /* if any registers used */
2597 /* save the registers used */
2598 for (i = 0; i < sym->regsUsed->size; i++)
2600 if (bitVectBitValue (sym->regsUsed, i) ||
2601 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2602 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2609 /* this function has a function call cannot
2610 determines register usage so we will have to push the
2612 saveRBank (0, ic, FALSE);
2617 /* This ISR uses a non-zero bank.
2619 * We assume that the bank is available for our
2622 * However, if this ISR calls a function which uses some
2623 * other bank, we must save that bank entirely.
2625 unsigned long banksToSave = 0;
2630 #define MAX_REGISTER_BANKS 4
2635 D(emitcode(";", "seeking function calls..."););
2637 for (i = ic; i; i = i->next)
2639 if (i->op == ENDFUNCTION)
2641 /* we got to the end OK. */
2649 detype = getSpec(operandType (IC_LEFT(i)));
2651 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2653 /* Mark this bank for saving. */
2654 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2656 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2660 D(emitcode(";", "should save bank %d",
2661 SPEC_BANK(detype)););
2662 banksToSave |= (1 << SPEC_BANK(detype));
2665 /* And note that we don't need to do it in
2673 /* This is a mess; we have no idea what
2674 * register bank the called function might
2677 * The only thing I can think of to do is
2678 * throw a warning and hope.
2680 werror(W_FUNCPTR_IN_USING_ISR);
2684 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2686 if (banksToSave & (1 << ix))
2688 saveRBank(ix, NULL, FALSE);
2692 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2697 /* if callee-save to be used for this function
2698 then save the registers being used in this function */
2699 if (sym->calleeSave)
2703 /* if any registers used */
2706 /* save the registers used */
2707 for (i = 0; i < sym->regsUsed->size; i++)
2709 if (bitVectBitValue (sym->regsUsed, i) ||
2710 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2712 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2720 /* set the register bank to the desired value */
2721 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2723 emitcode ("push", "psw");
2724 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2727 if (IS_RENT (sym->etype) || options.stackAuto)
2730 if (options.useXstack)
2732 emitcode ("mov", "r0,%s", spname);
2733 emitcode ("mov", "a,_bp");
2734 emitcode ("movx", "@r0,a");
2735 emitcode ("inc", "%s", spname);
2739 /* set up the stack */
2740 emitcode ("push", "_bp"); /* save the callers stack */
2742 emitcode ("mov", "_bp,%s", spname);
2745 /* adjust the stack for the function */
2751 werror (W_STACK_OVERFLOW, sym->name);
2753 if (i > 3 && sym->recvSize < 4)
2756 emitcode ("mov", "a,sp");
2757 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2758 emitcode ("mov", "sp,a");
2763 emitcode ("inc", "sp");
2769 emitcode ("mov", "a,_spx");
2770 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2771 emitcode ("mov", "_spx,a");
2776 /*-----------------------------------------------------------------*/
2777 /* genEndFunction - generates epilogue for functions */
2778 /*-----------------------------------------------------------------*/
2780 genEndFunction (iCode * ic)
2782 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2784 D (emitcode (";", "genEndFunction "););
2786 if (IS_RENT (sym->etype) || options.stackAuto)
2788 emitcode ("mov", "%s,_bp", spname);
2791 /* if use external stack but some variables were
2792 added to the local stack then decrement the
2794 if (options.useXstack && sym->stack)
2796 emitcode ("mov", "a,sp");
2797 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2798 emitcode ("mov", "sp,a");
2802 if ((IS_RENT (sym->etype) || options.stackAuto))
2804 if (options.useXstack)
2806 emitcode ("mov", "r0,%s", spname);
2807 emitcode ("movx", "a,@r0");
2808 emitcode ("mov", "_bp,a");
2809 emitcode ("dec", "%s", spname);
2813 emitcode ("pop", "_bp");
2817 /* restore the register bank */
2818 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2819 emitcode ("pop", "psw");
2821 if (IS_ISR (sym->etype))
2824 /* now we need to restore the registers */
2825 /* if this isr has no bank i.e. is going to
2826 run with bank 0 , then we need to save more
2828 if (!SPEC_BANK (sym->etype))
2831 /* if this function does not call any other
2832 function then we can be economical and
2833 save only those registers that are used */
2838 /* if any registers used */
2841 /* save the registers used */
2842 for (i = sym->regsUsed->size; i >= 0; i--)
2844 if (bitVectBitValue (sym->regsUsed, i) ||
2845 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2846 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2853 /* this function has a function call cannot
2854 determines register usage so we will have to pop the
2856 unsaveRBank (0, ic, FALSE);
2861 /* This ISR uses a non-zero bank.
2863 * Restore any register banks saved by genFunction
2866 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2869 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2871 if (savedBanks & (1 << ix))
2873 unsaveRBank(ix, NULL, FALSE);
2878 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2880 if (options.stack10bit)
2882 emitcode ("pop", DP2_RESULT_REG);
2883 emitcode ("pop", "dpx1");
2884 emitcode ("pop", "dph1");
2885 emitcode ("pop", "dpl1");
2887 emitcode ("pop", "dps");
2888 emitcode ("pop", "dpx");
2890 if (!inExcludeList ("dph"))
2891 emitcode ("pop", "dph");
2892 if (!inExcludeList ("dpl"))
2893 emitcode ("pop", "dpl");
2894 if (!inExcludeList ("b"))
2895 emitcode ("pop", "b");
2896 if (!inExcludeList ("acc"))
2897 emitcode ("pop", "acc");
2899 if (SPEC_CRTCL (sym->etype))
2900 emitcode ("setb", "ea");
2902 /* if debug then send end of function */
2903 /* if (options.debug && currFunc) { */
2907 emitcode ("", "C$%s$%d$%d$%d ==.",
2908 FileBaseName (ic->filename), currFunc->lastLine,
2909 ic->level, ic->block);
2910 if (IS_STATIC (currFunc->etype))
2911 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2913 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2917 emitcode ("reti", "");
2921 if (SPEC_CRTCL (sym->etype))
2922 emitcode ("setb", "ea");
2924 if (sym->calleeSave)
2928 /* if any registers used */
2931 /* save the registers used */
2932 for (i = sym->regsUsed->size; i >= 0; i--)
2934 if (bitVectBitValue (sym->regsUsed, i) ||
2935 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2936 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2942 /* if debug then send end of function */
2946 emitcode ("", "C$%s$%d$%d$%d ==.",
2947 FileBaseName (ic->filename), currFunc->lastLine,
2948 ic->level, ic->block);
2949 if (IS_STATIC (currFunc->etype))
2950 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2952 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2956 emitcode ("ret", "");
2961 /*-----------------------------------------------------------------*/
2962 /* genRet - generate code for return statement */
2963 /*-----------------------------------------------------------------*/
2967 int size, offset = 0, pushed = 0;
2969 D (emitcode (";", "genRet ");
2972 /* if we have no return value then
2973 just generate the "ret" */
2977 /* we have something to return then
2978 move the return value into place */
2979 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2980 size = AOP_SIZE (IC_LEFT (ic));
2982 _startLazyDPSEvaluation ();
2986 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2988 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2989 FALSE, TRUE, FALSE);
2990 emitcode ("push", "%s", l);
2995 /* Since A is the last element of fReturn,
2996 * is is OK to clobber it in the aopGet.
2998 l = aopGet (AOP (IC_LEFT (ic)), offset,
2999 FALSE, FALSE, TRUE);
3000 if (strcmp (fReturn[offset], l))
3001 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3004 _endLazyDPSEvaluation ();
3011 if (strcmp (fReturn[pushed], "a"))
3012 emitcode ("pop", fReturn[pushed]);
3014 emitcode ("pop", "acc");
3017 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3020 /* generate a jump to the return label
3021 if the next is not the return statement */
3022 if (!(ic->next && ic->next->op == LABEL &&
3023 IC_LABEL (ic->next) == returnLabel))
3025 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3029 /*-----------------------------------------------------------------*/
3030 /* genLabel - generates a label */
3031 /*-----------------------------------------------------------------*/
3033 genLabel (iCode * ic)
3035 /* special case never generate */
3036 if (IC_LABEL (ic) == entryLabel)
3039 D (emitcode (";", "genLabel ");
3042 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3045 /*-----------------------------------------------------------------*/
3046 /* genGoto - generates a ljmp */
3047 /*-----------------------------------------------------------------*/
3049 genGoto (iCode * ic)
3051 D (emitcode (";", "genGoto ");
3053 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3056 /*-----------------------------------------------------------------*/
3057 /* findLabelBackwards: walks back through the iCode chain looking */
3058 /* for the given label. Returns number of iCode instructions */
3059 /* between that label and given ic. */
3060 /* Returns zero if label not found. */
3061 /*-----------------------------------------------------------------*/
3063 findLabelBackwards (iCode * ic, int key)
3072 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3074 /* printf("findLabelBackwards = %d\n", count); */
3082 /*-----------------------------------------------------------------*/
3083 /* genPlusIncr :- does addition with increment if possible */
3084 /*-----------------------------------------------------------------*/
3086 genPlusIncr (iCode * ic)
3088 unsigned int icount;
3089 unsigned int size = getDataSize (IC_RESULT (ic));
3091 /* will try to generate an increment */
3092 /* if the right side is not a literal
3094 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3097 /* if the literal value of the right hand side
3098 is greater than 4 then it is not worth it */
3099 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3102 /* if increment 16 bits in register */
3104 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3105 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3106 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3114 /* If the next instruction is a goto and the goto target
3115 * is <= 5 instructions previous to this, we can generate
3116 * jumps straight to that target.
3118 if (ic->next && ic->next->op == GOTO
3119 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3122 emitcode (";", "tail increment optimized (range %d)", labelRange);
3123 tlbl = IC_LABEL (ic->next);
3128 tlbl = newiTempLabel (NULL);
3131 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3132 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3133 IS_AOP_PREG (IC_RESULT (ic)))
3134 emitcode ("cjne", "%s,#0x00,%05d$"
3135 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3139 emitcode ("clr", "a");
3140 emitcode ("cjne", "a,%s,%05d$"
3141 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3145 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3148 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3149 IS_AOP_PREG (IC_RESULT (ic)))
3150 emitcode ("cjne", "%s,#0x00,%05d$"
3151 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3154 emitcode ("cjne", "a,%s,%05d$"
3155 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3158 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3162 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3163 IS_AOP_PREG (IC_RESULT (ic)))
3164 emitcode ("cjne", "%s,#0x00,%05d$"
3165 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3169 emitcode ("cjne", "a,%s,%05d$"
3170 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3173 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3178 emitcode ("", "%05d$:", tlbl->key + 100);
3183 /* if the sizes are greater than 1 then we cannot */
3184 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3185 AOP_SIZE (IC_LEFT (ic)) > 1)
3188 /* we can if the aops of the left & result match or
3189 if they are in registers and the registers are the
3192 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3193 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3194 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3199 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3200 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3201 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3206 _startLazyDPSEvaluation ();
3209 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3211 _endLazyDPSEvaluation ();
3220 /*-----------------------------------------------------------------*/
3221 /* outBitAcc - output a bit in acc */
3222 /*-----------------------------------------------------------------*/
3224 outBitAcc (operand * result)
3226 symbol *tlbl = newiTempLabel (NULL);
3227 /* if the result is a bit */
3228 if (AOP_TYPE (result) == AOP_CRY)
3230 aopPut (AOP (result), "a", 0);
3234 emitcode ("jz", "%05d$", tlbl->key + 100);
3235 emitcode ("mov", "a,%s", one);
3236 emitcode ("", "%05d$:", tlbl->key + 100);
3241 /*-----------------------------------------------------------------*/
3242 /* genPlusBits - generates code for addition of two bits */
3243 /*-----------------------------------------------------------------*/
3245 genPlusBits (iCode * ic)
3247 D (emitcode (";", "genPlusBits ");
3249 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3251 symbol *lbl = newiTempLabel (NULL);
3252 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3253 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3254 emitcode ("cpl", "c");
3255 emitcode ("", "%05d$:", (lbl->key + 100));
3256 outBitC (IC_RESULT (ic));
3260 emitcode ("clr", "a");
3261 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3262 emitcode ("rlc", "a");
3263 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3264 emitcode ("addc", "a,#0x00");
3265 outAcc (IC_RESULT (ic));
3270 adjustArithmeticResult (iCode * ic)
3272 if (opIsGptr (IC_RESULT (ic)) &&
3273 opIsGptr (IC_LEFT (ic)) &&
3274 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3276 aopPut (AOP (IC_RESULT (ic)),
3277 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3281 if (opIsGptr (IC_RESULT (ic)) &&
3282 opIsGptr (IC_RIGHT (ic)) &&
3283 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3285 aopPut (AOP (IC_RESULT (ic)),
3286 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3290 if (opIsGptr (IC_RESULT (ic)) &&
3291 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3292 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3293 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3294 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3297 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3298 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3302 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3303 // (because all three operands are in far space).
3304 #define AOP_OP_3(ic) \
3305 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3306 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3307 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3308 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3309 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3310 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3312 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3314 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3317 // Macro to aopOp all three operands of an ic. If this cannot be done,
3318 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3319 // will be set TRUE. The caller must then handle the case specially, noting
3320 // that the IC_RESULT operand is not aopOp'd.
3321 #define AOP_OP_3_NOFATAL(ic, rc) \
3322 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3323 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3324 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3325 isOperandInFarSpace(IC_RESULT(ic))) \
3327 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3332 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3333 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3335 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3336 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3338 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3340 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3344 // aopOp the left & right operands of an ic.
3345 #define AOP_OP_2(ic) \
3346 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3347 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3349 // convienience macro.
3350 #define AOP_SET_LOCALS(ic) \
3351 left = IC_LEFT(ic); \
3352 right = IC_RIGHT(ic); \
3353 result = IC_RESULT(ic);
3356 // Given an integer value of pushedSize bytes on the stack,
3357 // adjust it to be resultSize bytes, either by discarding
3358 // the most significant bytes or by zero-padding.
3360 // On exit from this macro, pushedSize will have been adjusted to
3361 // equal resultSize, and ACC may be trashed.
3362 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3363 /* If the pushed data is bigger than the result, \
3364 * simply discard unused bytes. Icky, but works. \
3366 while (pushedSize > resultSize) \
3368 D (emitcode (";", "discarding unused result byte."););\
3369 emitcode ("pop", "acc"); \
3372 if (pushedSize < resultSize) \
3374 emitcode ("clr", "a"); \
3375 /* Conversly, we haven't pushed enough here. \
3376 * just zero-pad, and all is well. \
3378 while (pushedSize < resultSize) \
3380 emitcode("push", "acc"); \
3384 assert(pushedSize == resultSize);
3386 /*-----------------------------------------------------------------*/
3387 /* genPlus - generates code for addition */
3388 /*-----------------------------------------------------------------*/
3390 genPlus (iCode * ic)
3392 int size, offset = 0;
3393 bool pushResult = FALSE;
3396 D (emitcode (";", "genPlus "););
3398 /* special cases :- */
3400 AOP_OP_3_NOFATAL (ic, pushResult);
3403 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3408 /* if literal, literal on the right or
3409 if left requires ACC or right is already
3411 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3412 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3413 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3415 operand *t = IC_RIGHT (ic);
3416 IC_RIGHT (ic) = IC_LEFT (ic);
3418 emitcode (";", "Swapped plus args.");
3421 /* if both left & right are in bit
3423 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3424 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3430 /* if left in bit space & right literal */
3431 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3432 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3434 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3435 /* if result in bit space */
3436 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3438 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3439 emitcode ("cpl", "c");
3440 outBitC (IC_RESULT (ic));
3444 size = getDataSize (IC_RESULT (ic));
3445 _startLazyDPSEvaluation ();
3448 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3449 emitcode ("addc", "a,#00");
3450 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3452 _endLazyDPSEvaluation ();
3457 /* if I can do an increment instead
3458 of add then GOOD for ME */
3459 if (genPlusIncr (ic) == TRUE)
3461 emitcode (";", "did genPlusIncr");
3466 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3468 _startLazyDPSEvaluation ();
3471 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3473 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3475 emitcode ("add", "a,%s",
3476 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3478 emitcode ("addc", "a,%s",
3479 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3483 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3485 /* right is going to use ACC or we would have taken the
3488 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3489 D(emitcode(";", "+ AOP_ACC special case."););
3490 emitcode("xch", "a, %s", DP2_RESULT_REG);
3492 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3495 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3497 emitcode("add", "a, %s", DP2_RESULT_REG);
3501 emitcode ("add", "a,%s",
3502 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3507 emitcode ("addc", "a,%s",
3508 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3513 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3517 emitcode ("push", "acc");
3521 _endLazyDPSEvaluation ();
3525 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3527 size = getDataSize (IC_LEFT (ic));
3528 rSize = getDataSize (IC_RESULT (ic));
3530 ADJUST_PUSHED_RESULT(size, rSize);
3532 _startLazyDPSEvaluation ();
3535 emitcode ("pop", "acc");
3536 aopPut (AOP (IC_RESULT (ic)), "a", size);
3538 _endLazyDPSEvaluation ();
3541 adjustArithmeticResult (ic);
3544 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3545 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3546 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3549 /*-----------------------------------------------------------------*/
3550 /* genMinusDec :- does subtraction with deccrement if possible */
3551 /*-----------------------------------------------------------------*/
3553 genMinusDec (iCode * ic)
3555 unsigned int icount;
3556 unsigned int size = getDataSize (IC_RESULT (ic));
3558 /* will try to generate an increment */
3559 /* if the right side is not a literal
3561 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3564 /* if the literal value of the right hand side
3565 is greater than 4 then it is not worth it */
3566 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3569 /* if decrement 16 bits in register */
3570 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3571 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3572 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3580 /* If the next instruction is a goto and the goto target
3581 * is <= 5 instructions previous to this, we can generate
3582 * jumps straight to that target.
3584 if (ic->next && ic->next->op == GOTO
3585 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3588 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3589 tlbl = IC_LABEL (ic->next);
3594 tlbl = newiTempLabel (NULL);
3598 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3599 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3600 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3601 IS_AOP_PREG (IC_RESULT (ic)))
3602 emitcode ("cjne", "%s,#0xff,%05d$"
3603 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3607 emitcode ("mov", "a,#0xff");
3608 emitcode ("cjne", "a,%s,%05d$"
3609 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3612 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3615 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3616 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3617 IS_AOP_PREG (IC_RESULT (ic)))
3618 emitcode ("cjne", "%s,#0xff,%05d$"
3619 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3623 emitcode ("cjne", "a,%s,%05d$"
3624 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3627 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3631 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3632 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3633 IS_AOP_PREG (IC_RESULT (ic)))
3634 emitcode ("cjne", "%s,#0xff,%05d$"
3635 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3639 emitcode ("cjne", "a,%s,%05d$"
3640 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3643 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3647 emitcode ("", "%05d$:", tlbl->key + 100);
3652 /* if the sizes are greater than 1 then we cannot */
3653 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3654 AOP_SIZE (IC_LEFT (ic)) > 1)
3657 /* we can if the aops of the left & result match or
3658 if they are in registers and the registers are the
3661 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3662 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3663 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3666 _startLazyDPSEvaluation ();
3669 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3671 _endLazyDPSEvaluation ();
3679 /*-----------------------------------------------------------------*/
3680 /* addSign - complete with sign */
3681 /*-----------------------------------------------------------------*/
3683 addSign (operand * result, int offset, int sign)
3685 int size = (getDataSize (result) - offset);
3688 _startLazyDPSEvaluation();
3691 emitcode ("rlc", "a");
3692 emitcode ("subb", "a,acc");
3695 aopPut (AOP (result), "a", offset++);
3702 aopPut (AOP (result), zero, offset++);
3705 _endLazyDPSEvaluation();
3709 /*-----------------------------------------------------------------*/
3710 /* genMinusBits - generates code for subtraction of two bits */
3711 /*-----------------------------------------------------------------*/
3713 genMinusBits (iCode * ic)
3715 symbol *lbl = newiTempLabel (NULL);
3717 D (emitcode (";", "genMinusBits "););
3719 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3721 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3722 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3723 emitcode ("cpl", "c");
3724 emitcode ("", "%05d$:", (lbl->key + 100));
3725 outBitC (IC_RESULT (ic));
3729 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3730 emitcode ("subb", "a,acc");
3731 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3732 emitcode ("inc", "a");
3733 emitcode ("", "%05d$:", (lbl->key + 100));
3734 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3735 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3739 /*-----------------------------------------------------------------*/
3740 /* genMinus - generates code for subtraction */
3741 /*-----------------------------------------------------------------*/
3743 genMinus (iCode * ic)
3745 int size, offset = 0;
3747 unsigned long lit = 0L;
3748 bool pushResult = FALSE;
3750 D (emitcode (";", "genMinus "););
3752 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3753 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3754 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3755 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3761 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3763 /* special cases :- */
3764 /* if both left & right are in bit space */
3765 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3766 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3772 /* if I can do an decrement instead
3773 of subtract then GOOD for ME */
3774 if (genMinusDec (ic) == TRUE)
3779 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3781 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3787 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3792 /* if literal, add a,#-lit, else normal subb */
3793 _startLazyDPSEvaluation ();
3796 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3797 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3798 emitcode ("subb", "a,%s",
3799 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3802 /* first add without previous c */
3804 emitcode ("add", "a,#0x%02x",
3805 (unsigned int) (lit & 0x0FFL));
3807 emitcode ("addc", "a,#0x%02x",
3808 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3813 emitcode ("push", "acc");
3817 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3821 _endLazyDPSEvaluation ();
3825 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3827 size = getDataSize (IC_LEFT (ic));
3828 rSize = getDataSize (IC_RESULT (ic));
3830 ADJUST_PUSHED_RESULT(size, rSize);
3832 _startLazyDPSEvaluation ();
3835 emitcode ("pop", "acc");
3836 aopPut (AOP (IC_RESULT (ic)), "a", size);
3838 _endLazyDPSEvaluation ();
3841 adjustArithmeticResult (ic);
3844 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3845 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3846 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3850 /*-----------------------------------------------------------------*/
3851 /* genMultbits :- multiplication of bits */
3852 /*-----------------------------------------------------------------*/
3854 genMultbits (operand * left,
3858 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3859 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3864 /*-----------------------------------------------------------------*/
3865 /* genMultOneByte : 8*8=8/16 bit multiplication */
3866 /*-----------------------------------------------------------------*/
3868 genMultOneByte (operand * left,
3872 sym_link *opetype = operandType (result);
3874 int size=AOP_SIZE(result);
3876 if (size<1 || size>2) {
3877 // this should never happen
3878 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3879 AOP_SIZE(result), __FILE__, lineno);
3883 /* (if two literals: the value is computed before) */
3884 /* if one literal, literal on the right */
3885 if (AOP_TYPE (left) == AOP_LIT)
3890 emitcode (";", "swapped left and right");
3893 if (SPEC_USIGN(opetype)
3894 // ignore the sign of left and right, what else can we do?
3895 || (SPEC_USIGN(operandType(left)) &&
3896 SPEC_USIGN(operandType(right)))) {
3897 // just an unsigned 8*8=8/16 multiply
3898 //emitcode (";","unsigned");
3899 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3900 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3901 emitcode ("mul", "ab");
3902 aopPut (AOP (result), "a", 0);
3904 aopPut (AOP (result), "b", 1);
3909 // we have to do a signed multiply
3911 emitcode (";", "signed");
3912 emitcode ("clr", "F0"); // reset sign flag
3913 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3914 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3916 lbl=newiTempLabel(NULL);
3917 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3918 // left side is negative, 8-bit two's complement, this fails for -128
3919 emitcode ("setb", "F0"); // set sign flag
3920 emitcode ("cpl", "a");
3921 emitcode ("inc", "a");
3923 emitcode ("", "%05d$:", lbl->key+100);
3924 emitcode ("xch", "a,b");
3927 if (AOP_TYPE(right)==AOP_LIT) {
3928 /* AND literal negative */
3929 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3930 // two's complement for literal<0
3931 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3932 emitcode ("cpl", "a");
3933 emitcode ("inc", "a");
3936 lbl=newiTempLabel(NULL);
3937 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3938 // right side is negative, 8-bit two's complement
3939 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3940 emitcode ("cpl", "a");
3941 emitcode ("inc", "a");
3942 emitcode ("", "%05d$:", lbl->key+100);
3944 emitcode ("mul", "ab");
3946 lbl=newiTempLabel(NULL);
3947 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3948 // only ONE op was negative, we have to do a 8/16-bit two's complement
3949 emitcode ("cpl", "a"); // lsb
3951 emitcode ("inc", "a");
3953 emitcode ("add", "a,#1");
3954 emitcode ("xch", "a,b");
3955 emitcode ("cpl", "a"); // msb
3956 emitcode ("addc", "a,#0");
3957 emitcode ("xch", "a,b");
3960 emitcode ("", "%05d$:", lbl->key+100);
3961 aopPut (AOP (result), "a", 0);
3963 aopPut (AOP (result), "b", 1);
3967 /*-----------------------------------------------------------------*/
3968 /* genMult - generates code for multiplication */
3969 /*-----------------------------------------------------------------*/
3971 genMult (iCode * ic)
3973 operand *left = IC_LEFT (ic);
3974 operand *right = IC_RIGHT (ic);
3975 operand *result = IC_RESULT (ic);
3977 D (emitcode (";", "genMult "););
3979 /* assign the amsops */
3982 /* special cases first */
3984 if (AOP_TYPE (left) == AOP_CRY &&
3985 AOP_TYPE (right) == AOP_CRY)
3987 genMultbits (left, right, result);
3991 /* if both are of size == 1 */
3992 if (AOP_SIZE (left) == 1 &&
3993 AOP_SIZE (right) == 1)
3995 genMultOneByte (left, right, result);
3999 /* should have been converted to function call */
4003 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4004 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4005 freeAsmop (result, NULL, ic, TRUE);
4008 /*-----------------------------------------------------------------*/
4009 /* genDivbits :- division of bits */
4010 /*-----------------------------------------------------------------*/
4012 genDivbits (operand * left,
4019 /* the result must be bit */
4020 LOAD_AB_FOR_DIV (left, right, l);
4021 emitcode ("div", "ab");
4022 emitcode ("rrc", "a");
4023 aopPut (AOP (result), "c", 0);
4026 /*-----------------------------------------------------------------*/
4027 /* genDivOneByte : 8 bit division */
4028 /*-----------------------------------------------------------------*/
4030 genDivOneByte (operand * left,
4034 sym_link *opetype = operandType (result);
4039 size = AOP_SIZE (result) - 1;
4041 /* signed or unsigned */
4042 if (SPEC_USIGN (opetype))
4044 /* unsigned is easy */
4045 LOAD_AB_FOR_DIV (left, right, l);
4046 emitcode ("div", "ab");
4047 aopPut (AOP (result), "a", 0);
4049 aopPut (AOP (result), zero, offset++);
4053 /* signed is a little bit more difficult */
4055 /* save the signs of the operands */
4056 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4058 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4059 emitcode ("push", "acc"); /* save it on the stack */
4061 /* now sign adjust for both left & right */
4062 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4064 lbl = newiTempLabel (NULL);
4065 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4066 emitcode ("cpl", "a");
4067 emitcode ("inc", "a");
4068 emitcode ("", "%05d$:", (lbl->key + 100));
4069 emitcode ("mov", "b,a");
4071 /* sign adjust left side */
4072 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4075 lbl = newiTempLabel (NULL);
4076 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4077 emitcode ("cpl", "a");
4078 emitcode ("inc", "a");
4079 emitcode ("", "%05d$:", (lbl->key + 100));
4081 /* now the division */
4082 emitcode ("nop", "; workaround for DS80C390 div bug.");
4083 emitcode ("div", "ab");
4084 /* we are interested in the lower order
4086 emitcode ("mov", "b,a");
4087 lbl = newiTempLabel (NULL);
4088 emitcode ("pop", "acc");
4089 /* if there was an over flow we don't
4090 adjust the sign of the result */
4091 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4092 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4094 emitcode ("clr", "a");
4095 emitcode ("subb", "a,b");
4096 emitcode ("mov", "b,a");
4097 emitcode ("", "%05d$:", (lbl->key + 100));
4099 /* now we are done */
4100 aopPut (AOP (result), "b", 0);
4103 emitcode ("mov", "c,b.7");
4104 emitcode ("subb", "a,acc");
4107 aopPut (AOP (result), "a", offset++);
4111 /*-----------------------------------------------------------------*/
4112 /* genDiv - generates code for division */
4113 /*-----------------------------------------------------------------*/
4117 operand *left = IC_LEFT (ic);
4118 operand *right = IC_RIGHT (ic);
4119 operand *result = IC_RESULT (ic);
4121 D (emitcode (";", "genDiv ");
4124 /* assign the amsops */
4127 /* special cases first */
4129 if (AOP_TYPE (left) == AOP_CRY &&
4130 AOP_TYPE (right) == AOP_CRY)
4132 genDivbits (left, right, result);
4136 /* if both are of size == 1 */
4137 if (AOP_SIZE (left) == 1 &&
4138 AOP_SIZE (right) == 1)
4140 genDivOneByte (left, right, result);
4144 /* should have been converted to function call */
4147 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4148 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4149 freeAsmop (result, NULL, ic, TRUE);
4152 /*-----------------------------------------------------------------*/
4153 /* genModbits :- modulus of bits */
4154 /*-----------------------------------------------------------------*/
4156 genModbits (operand * left,
4163 /* the result must be bit */
4164 LOAD_AB_FOR_DIV (left, right, l);
4165 emitcode ("div", "ab");
4166 emitcode ("mov", "a,b");
4167 emitcode ("rrc", "a");
4168 aopPut (AOP (result), "c", 0);
4171 /*-----------------------------------------------------------------*/
4172 /* genModOneByte : 8 bit modulus */
4173 /*-----------------------------------------------------------------*/
4175 genModOneByte (operand * left,
4179 sym_link *opetype = operandType (result);
4183 /* signed or unsigned */
4184 if (SPEC_USIGN (opetype))
4186 /* unsigned is easy */
4187 LOAD_AB_FOR_DIV (left, right, l);
4188 emitcode ("div", "ab");
4189 aopPut (AOP (result), "b", 0);
4193 /* signed is a little bit more difficult */
4195 /* save the signs of the operands */
4196 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4199 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4200 emitcode ("push", "acc"); /* save it on the stack */
4202 /* now sign adjust for both left & right */
4203 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4206 lbl = newiTempLabel (NULL);
4207 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4208 emitcode ("cpl", "a");
4209 emitcode ("inc", "a");
4210 emitcode ("", "%05d$:", (lbl->key + 100));
4211 emitcode ("mov", "b,a");
4213 /* sign adjust left side */
4214 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4217 lbl = newiTempLabel (NULL);
4218 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4219 emitcode ("cpl", "a");
4220 emitcode ("inc", "a");
4221 emitcode ("", "%05d$:", (lbl->key + 100));
4223 /* now the multiplication */
4224 emitcode ("nop", "; workaround for DS80C390 div bug.");
4225 emitcode ("div", "ab");
4226 /* we are interested in the lower order
4228 lbl = newiTempLabel (NULL);
4229 emitcode ("pop", "acc");
4230 /* if there was an over flow we don't
4231 adjust the sign of the result */
4232 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4233 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4235 emitcode ("clr", "a");
4236 emitcode ("subb", "a,b");
4237 emitcode ("mov", "b,a");
4238 emitcode ("", "%05d$:", (lbl->key + 100));
4240 /* now we are done */
4241 aopPut (AOP (result), "b", 0);
4245 /*-----------------------------------------------------------------*/
4246 /* genMod - generates code for division */
4247 /*-----------------------------------------------------------------*/
4251 operand *left = IC_LEFT (ic);
4252 operand *right = IC_RIGHT (ic);
4253 operand *result = IC_RESULT (ic);
4255 D (emitcode (";", "genMod ");
4258 /* assign the amsops */
4261 /* special cases first */
4263 if (AOP_TYPE (left) == AOP_CRY &&
4264 AOP_TYPE (right) == AOP_CRY)
4266 genModbits (left, right, result);
4270 /* if both are of size == 1 */
4271 if (AOP_SIZE (left) == 1 &&
4272 AOP_SIZE (right) == 1)
4274 genModOneByte (left, right, result);
4278 /* should have been converted to function call */
4282 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4283 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4284 freeAsmop (result, NULL, ic, TRUE);
4287 /*-----------------------------------------------------------------*/
4288 /* genIfxJump :- will create a jump depending on the ifx */
4289 /*-----------------------------------------------------------------*/
4291 genIfxJump (iCode * ic, char *jval)
4294 symbol *tlbl = newiTempLabel (NULL);
4297 D (emitcode (";", "genIfxJump ");
4300 /* if true label then we jump if condition
4304 jlbl = IC_TRUE (ic);
4305 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4306 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4310 /* false label is present */
4311 jlbl = IC_FALSE (ic);
4312 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4313 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4315 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4316 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4318 emitcode (inst, "%05d$", tlbl->key + 100);
4319 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4320 emitcode ("", "%05d$:", tlbl->key + 100);
4322 /* mark the icode as generated */
4326 /*-----------------------------------------------------------------*/
4327 /* genCmp :- greater or less than comparison */
4328 /*-----------------------------------------------------------------*/
4330 genCmp (operand * left, operand * right,
4331 iCode * ic, iCode * ifx, int sign)
4333 int size, offset = 0;
4334 unsigned long lit = 0L;
4337 D (emitcode (";", "genCmp");
4340 result = IC_RESULT (ic);
4342 /* if left & right are bit variables */
4343 if (AOP_TYPE (left) == AOP_CRY &&
4344 AOP_TYPE (right) == AOP_CRY)
4346 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4347 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4351 /* subtract right from left if at the
4352 end the carry flag is set then we know that
4353 left is greater than right */
4354 size = max (AOP_SIZE (left), AOP_SIZE (right));
4356 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4357 if ((size == 1) && !sign &&
4358 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4360 symbol *lbl = newiTempLabel (NULL);
4361 emitcode ("cjne", "%s,%s,%05d$",
4362 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4363 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4365 emitcode ("", "%05d$:", lbl->key + 100);
4369 if (AOP_TYPE (right) == AOP_LIT)
4371 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4372 /* optimize if(x < 0) or if(x >= 0) */
4381 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4383 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4384 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4386 aopOp (result, ic, FALSE, FALSE);
4388 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4390 freeAsmop (result, NULL, ic, TRUE);
4391 genIfxJump (ifx, "acc.7");
4396 emitcode ("rlc", "a");
4398 goto release_freedLR;
4406 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4407 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4408 emitcode (";", "genCmp #2");
4409 if (sign && (size == 0))
4411 emitcode (";", "genCmp #3");
4412 emitcode ("xrl", "a,#0x80");
4413 if (AOP_TYPE (right) == AOP_LIT)
4415 unsigned long lit = (unsigned long)
4416 floatFromVal (AOP (right)->aopu.aop_lit);
4417 emitcode (";", "genCmp #3.1");
4418 emitcode ("subb", "a,#0x%02x",
4419 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4423 emitcode (";", "genCmp #3.2");
4424 if (AOP_NEEDSACC (right))
4426 emitcode ("push", "acc");
4428 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4429 FALSE, FALSE, FALSE));
4430 emitcode ("xrl", "b,#0x80");
4431 if (AOP_NEEDSACC (right))
4433 emitcode ("pop", "acc");
4435 emitcode ("subb", "a,b");
4442 emitcode (";", "genCmp #4");
4443 if (AOP_NEEDSACC (right))
4446 emitcode (";", "genCmp #4.1");
4447 emitcode ("xch", "a, b");
4448 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4449 emitcode ("xch", "a, b");
4454 emitcode (";", "genCmp #4.2");
4455 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4458 emitcode ("subb", "a,%s", s);
4465 /* Don't need the left & right operands any more; do need the result. */
4466 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4467 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4469 aopOp (result, ic, FALSE, FALSE);
4473 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4479 /* if the result is used in the next
4480 ifx conditional branch then generate
4481 code a little differently */
4484 genIfxJump (ifx, "c");
4490 /* leave the result in acc */
4492 freeAsmop (result, NULL, ic, TRUE);
4495 /*-----------------------------------------------------------------*/
4496 /* genCmpGt :- greater than comparison */
4497 /*-----------------------------------------------------------------*/
4499 genCmpGt (iCode * ic, iCode * ifx)
4501 operand *left, *right;
4502 sym_link *letype, *retype;
4505 D (emitcode (";", "genCmpGt ");
4508 left = IC_LEFT (ic);
4509 right = IC_RIGHT (ic);
4511 letype = getSpec (operandType (left));
4512 retype = getSpec (operandType (right));
4513 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4515 /* assign the left & right amsops */
4518 genCmp (right, left, ic, ifx, sign);
4521 /*-----------------------------------------------------------------*/
4522 /* genCmpLt - less than comparisons */
4523 /*-----------------------------------------------------------------*/
4525 genCmpLt (iCode * ic, iCode * ifx)
4527 operand *left, *right;
4528 sym_link *letype, *retype;
4531 D (emitcode (";", "genCmpLt "););
4533 left = IC_LEFT (ic);
4534 right = IC_RIGHT (ic);
4536 letype = getSpec (operandType (left));
4537 retype = getSpec (operandType (right));
4538 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4540 /* assign the left & right amsops */
4543 genCmp (left, right, ic, ifx, sign);
4546 /*-----------------------------------------------------------------*/
4547 /* gencjneshort - compare and jump if not equal */
4548 /*-----------------------------------------------------------------*/
4550 gencjneshort (operand * left, operand * right, symbol * lbl)
4552 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4554 unsigned long lit = 0L;
4556 D (emitcode (";", "gencjneshort");
4559 /* if the left side is a literal or
4560 if the right is in a pointer register and left
4562 if ((AOP_TYPE (left) == AOP_LIT) ||
4563 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4570 if (AOP_TYPE (right) == AOP_LIT)
4571 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4573 if (opIsGptr (left) || opIsGptr (right))
4575 /* We are comparing a generic pointer to something.
4576 * Exclude the generic type byte from the comparison.
4579 D (emitcode (";", "cjneshort: generic ptr special case.");
4584 /* if the right side is a literal then anything goes */
4585 if (AOP_TYPE (right) == AOP_LIT &&
4586 AOP_TYPE (left) != AOP_DIR)
4590 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4592 emitcode ("cjne", "a,%s,%05d$",
4593 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4599 /* if the right side is in a register or in direct space or
4600 if the left is a pointer register & right is not */
4601 else if (AOP_TYPE (right) == AOP_REG ||
4602 AOP_TYPE (right) == AOP_DIR ||
4603 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4604 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4608 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4609 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4610 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4611 emitcode ("jnz", "%05d$", lbl->key + 100);
4613 emitcode ("cjne", "a,%s,%05d$",
4614 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4621 /* right is a pointer reg need both a & b */
4624 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4625 if (strcmp (l, "b"))
4626 emitcode ("mov", "b,%s", l);
4627 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4628 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4634 /*-----------------------------------------------------------------*/
4635 /* gencjne - compare and jump if not equal */
4636 /*-----------------------------------------------------------------*/
4638 gencjne (operand * left, operand * right, symbol * lbl)
4640 symbol *tlbl = newiTempLabel (NULL);
4642 D (emitcode (";", "gencjne");
4645 gencjneshort (left, right, lbl);
4647 emitcode ("mov", "a,%s", one);
4648 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4649 emitcode ("", "%05d$:", lbl->key + 100);
4650 emitcode ("clr", "a");
4651 emitcode ("", "%05d$:", tlbl->key + 100);
4654 /*-----------------------------------------------------------------*/
4655 /* genCmpEq - generates code for equal to */
4656 /*-----------------------------------------------------------------*/
4658 genCmpEq (iCode * ic, iCode * ifx)
4660 operand *left, *right, *result;
4662 D (emitcode (";", "genCmpEq ");
4666 AOP_SET_LOCALS (ic);
4668 /* if literal, literal on the right or
4669 if the right is in a pointer register and left
4671 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4672 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4674 operand *t = IC_RIGHT (ic);
4675 IC_RIGHT (ic) = IC_LEFT (ic);
4679 if (ifx && /* !AOP_SIZE(result) */
4680 OP_SYMBOL (result) &&
4681 OP_SYMBOL (result)->regType == REG_CND)
4684 /* if they are both bit variables */
4685 if (AOP_TYPE (left) == AOP_CRY &&
4686 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4688 if (AOP_TYPE (right) == AOP_LIT)
4690 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4693 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4694 emitcode ("cpl", "c");
4698 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4702 emitcode ("clr", "c");
4704 /* AOP_TYPE(right) == AOP_CRY */
4708 symbol *lbl = newiTempLabel (NULL);
4709 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4710 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4711 emitcode ("cpl", "c");
4712 emitcode ("", "%05d$:", (lbl->key + 100));
4714 /* if true label then we jump if condition
4716 tlbl = newiTempLabel (NULL);
4719 emitcode ("jnc", "%05d$", tlbl->key + 100);
4720 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4724 emitcode ("jc", "%05d$", tlbl->key + 100);
4725 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4727 emitcode ("", "%05d$:", tlbl->key + 100);
4731 tlbl = newiTempLabel (NULL);
4732 gencjneshort (left, right, tlbl);
4735 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4736 emitcode ("", "%05d$:", tlbl->key + 100);
4740 symbol *lbl = newiTempLabel (NULL);
4741 emitcode ("sjmp", "%05d$", lbl->key + 100);
4742 emitcode ("", "%05d$:", tlbl->key + 100);
4743 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4744 emitcode ("", "%05d$:", lbl->key + 100);
4747 /* mark the icode as generated */
4750 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4751 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4755 /* if they are both bit variables */
4756 if (AOP_TYPE (left) == AOP_CRY &&
4757 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4759 if (AOP_TYPE (right) == AOP_LIT)
4761 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4764 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4765 emitcode ("cpl", "c");
4769 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4773 emitcode ("clr", "c");
4775 /* AOP_TYPE(right) == AOP_CRY */
4779 symbol *lbl = newiTempLabel (NULL);
4780 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4781 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4782 emitcode ("cpl", "c");
4783 emitcode ("", "%05d$:", (lbl->key + 100));
4786 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4787 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4789 aopOp (result, ic, TRUE, FALSE);
4792 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4799 genIfxJump (ifx, "c");
4802 /* if the result is used in an arithmetic operation
4803 then put the result in place */
4808 gencjne (left, right, newiTempLabel (NULL));
4810 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4811 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4813 aopOp (result, ic, TRUE, FALSE);
4815 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4817 aopPut (AOP (result), "a", 0);
4822 genIfxJump (ifx, "a");
4825 /* if the result is used in an arithmetic operation
4826 then put the result in place */
4827 if (AOP_TYPE (result) != AOP_CRY)
4829 /* leave the result in acc */
4833 freeAsmop (result, NULL, ic, TRUE);
4836 /*-----------------------------------------------------------------*/
4837 /* ifxForOp - returns the icode containing the ifx for operand */
4838 /*-----------------------------------------------------------------*/
4840 ifxForOp (operand * op, iCode * ic)
4842 /* if true symbol then needs to be assigned */
4843 if (IS_TRUE_SYMOP (op))
4846 /* if this has register type condition and
4847 the next instruction is ifx with the same operand
4848 and live to of the operand is upto the ifx only then */
4850 ic->next->op == IFX &&
4851 IC_COND (ic->next)->key == op->key &&
4852 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4857 /*-----------------------------------------------------------------*/
4858 /* genAndOp - for && operation */
4859 /*-----------------------------------------------------------------*/
4861 genAndOp (iCode * ic)
4863 operand *left, *right, *result;
4866 D (emitcode (";", "genAndOp "););
4868 /* note here that && operations that are in an
4869 if statement are taken away by backPatchLabels
4870 only those used in arthmetic operations remain */
4872 AOP_SET_LOCALS (ic);
4874 /* if both are bit variables */
4875 if (AOP_TYPE (left) == AOP_CRY &&
4876 AOP_TYPE (right) == AOP_CRY)
4878 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4879 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4880 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4881 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4883 aopOp (result,ic,FALSE, FALSE);
4888 tlbl = newiTempLabel (NULL);
4890 emitcode ("jz", "%05d$", tlbl->key + 100);
4892 emitcode ("", "%05d$:", tlbl->key + 100);
4893 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4894 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4896 aopOp (result,ic,FALSE, FALSE);
4899 freeAsmop (result, NULL, ic, TRUE);
4903 /*-----------------------------------------------------------------*/
4904 /* genOrOp - for || operation */
4905 /*-----------------------------------------------------------------*/
4907 genOrOp (iCode * ic)
4909 operand *left, *right, *result;
4912 D (emitcode (";", "genOrOp "););
4914 /* note here that || operations that are in an
4915 if statement are taken away by backPatchLabels
4916 only those used in arthmetic operations remain */
4918 AOP_SET_LOCALS (ic);
4920 /* if both are bit variables */
4921 if (AOP_TYPE (left) == AOP_CRY &&
4922 AOP_TYPE (right) == AOP_CRY)
4924 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4925 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4926 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4927 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4929 aopOp (result,ic,FALSE, FALSE);
4935 tlbl = newiTempLabel (NULL);
4937 emitcode ("jnz", "%05d$", tlbl->key + 100);
4939 emitcode ("", "%05d$:", tlbl->key + 100);
4940 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4941 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 aopOp (result,ic,FALSE, FALSE);
4948 freeAsmop (result, NULL, ic, TRUE);
4951 /*-----------------------------------------------------------------*/
4952 /* isLiteralBit - test if lit == 2^n */
4953 /*-----------------------------------------------------------------*/
4955 isLiteralBit (unsigned long lit)
4957 unsigned long pw[32] =
4958 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4959 0x100L, 0x200L, 0x400L, 0x800L,
4960 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4961 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4962 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4963 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4964 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4967 for (idx = 0; idx < 32; idx++)
4973 /*-----------------------------------------------------------------*/
4974 /* continueIfTrue - */
4975 /*-----------------------------------------------------------------*/
4977 continueIfTrue (iCode * ic)
4980 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4984 /*-----------------------------------------------------------------*/
4986 /*-----------------------------------------------------------------*/
4988 jumpIfTrue (iCode * ic)
4991 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4995 /*-----------------------------------------------------------------*/
4996 /* jmpTrueOrFalse - */
4997 /*-----------------------------------------------------------------*/
4999 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5001 // ugly but optimized by peephole
5004 symbol *nlbl = newiTempLabel (NULL);
5005 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5006 emitcode ("", "%05d$:", tlbl->key + 100);
5007 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5008 emitcode ("", "%05d$:", nlbl->key + 100);
5012 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5013 emitcode ("", "%05d$:", tlbl->key + 100);
5018 // Generate code to perform a bit-wise logic operation
5019 // on two operands in far space (assumed to already have been
5020 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5021 // in far space. This requires pushing the result on the stack
5022 // then popping it into the result.
5024 genFarFarLogicOp(iCode *ic, char *logicOp)
5026 int size, resultSize, compSize;
5029 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5030 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5031 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5033 _startLazyDPSEvaluation();
5034 for (size = compSize; (size--); offset++)
5036 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5037 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5038 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5040 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5041 emitcode ("push", "acc");
5043 _endLazyDPSEvaluation();
5045 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5046 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5047 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5049 resultSize = AOP_SIZE(IC_RESULT(ic));
5051 ADJUST_PUSHED_RESULT(compSize, resultSize);
5053 _startLazyDPSEvaluation();
5056 emitcode ("pop", "acc");
5057 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5059 _endLazyDPSEvaluation();
5060 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5064 /*-----------------------------------------------------------------*/
5065 /* genAnd - code for and */
5066 /*-----------------------------------------------------------------*/
5068 genAnd (iCode * ic, iCode * ifx)
5070 operand *left, *right, *result;
5071 int size, offset = 0;
5072 unsigned long lit = 0L;
5077 D (emitcode (";", "genAnd "););
5079 AOP_OP_3_NOFATAL (ic, pushResult);
5080 AOP_SET_LOCALS (ic);
5084 genFarFarLogicOp(ic, "anl");
5089 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5091 AOP_TYPE (left), AOP_TYPE (right));
5092 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5094 AOP_SIZE (left), AOP_SIZE (right));
5097 /* if left is a literal & right is not then exchange them */
5098 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5099 AOP_NEEDSACC (left))
5101 operand *tmp = right;
5106 /* if result = right then exchange them */
5107 if (sameRegs (AOP (result), AOP (right)))
5109 operand *tmp = right;
5114 /* if right is bit then exchange them */
5115 if (AOP_TYPE (right) == AOP_CRY &&
5116 AOP_TYPE (left) != AOP_CRY)
5118 operand *tmp = right;
5122 if (AOP_TYPE (right) == AOP_LIT)
5123 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5125 size = AOP_SIZE (result);
5128 // result = bit & yy;
5129 if (AOP_TYPE (left) == AOP_CRY)
5131 // c = bit & literal;
5132 if (AOP_TYPE (right) == AOP_LIT)
5136 if (size && sameRegs (AOP (result), AOP (left)))
5139 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5144 if (size && (AOP_TYPE (result) == AOP_CRY))
5146 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5149 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5154 emitcode ("clr", "c");
5159 if (AOP_TYPE (right) == AOP_CRY)
5162 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5163 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5168 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5170 emitcode ("rrc", "a");
5171 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5179 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5180 genIfxJump (ifx, "c");
5184 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5185 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5186 if ((AOP_TYPE (right) == AOP_LIT) &&
5187 (AOP_TYPE (result) == AOP_CRY) &&
5188 (AOP_TYPE (left) != AOP_CRY))
5190 int posbit = isLiteralBit (lit);
5195 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5198 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5204 sprintf (buffer, "acc.%d", posbit & 0x07);
5205 genIfxJump (ifx, buffer);
5212 symbol *tlbl = newiTempLabel (NULL);
5213 int sizel = AOP_SIZE (left);
5215 emitcode ("setb", "c");
5218 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5220 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5222 if ((posbit = isLiteralBit (bytelit)) != 0)
5223 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5226 if (bytelit != 0x0FFL)
5227 emitcode ("anl", "a,%s",
5228 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5229 emitcode ("jnz", "%05d$", tlbl->key + 100);
5234 // bit = left & literal
5237 emitcode ("clr", "c");
5238 emitcode ("", "%05d$:", tlbl->key + 100);
5240 // if(left & literal)
5244 jmpTrueOrFalse (ifx, tlbl);
5252 /* if left is same as result */
5253 if (sameRegs (AOP (result), AOP (left)))
5255 for (; size--; offset++)
5257 if (AOP_TYPE (right) == AOP_LIT)
5259 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5261 else if (bytelit == 0)
5262 aopPut (AOP (result), zero, offset);
5263 else if (IS_AOP_PREG (result))
5265 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5266 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5267 aopPut (AOP (result), "a", offset);
5270 emitcode ("anl", "%s,%s",
5271 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5272 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5276 if (AOP_TYPE (left) == AOP_ACC)
5277 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5280 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5281 if (IS_AOP_PREG (result))
5283 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5284 aopPut (AOP (result), "a", offset);
5288 emitcode ("anl", "%s,a",
5289 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5296 // left & result in different registers
5297 if (AOP_TYPE (result) == AOP_CRY)
5300 // if(size), result in bit
5301 // if(!size && ifx), conditional oper: if(left & right)
5302 symbol *tlbl = newiTempLabel (NULL);
5303 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5305 emitcode ("setb", "c");
5308 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5309 emitcode ("anl", "a,%s",
5310 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5311 emitcode ("jnz", "%05d$", tlbl->key + 100);
5317 emitcode ("", "%05d$:", tlbl->key + 100);
5321 jmpTrueOrFalse (ifx, tlbl);
5325 for (; (size--); offset++)
5328 // result = left & right
5329 if (AOP_TYPE (right) == AOP_LIT)
5331 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5333 aopPut (AOP (result),
5334 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5338 else if (bytelit == 0)
5340 aopPut (AOP (result), zero, offset);
5343 D (emitcode (";", "better literal AND.");
5345 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5346 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5347 FALSE, FALSE, FALSE));
5352 // faster than result <- left, anl result,right
5353 // and better if result is SFR
5354 if (AOP_TYPE (left) == AOP_ACC)
5356 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5357 FALSE, FALSE, FALSE));
5361 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5362 emitcode ("anl", "a,%s",
5363 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5366 aopPut (AOP (result), "a", offset);
5372 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5373 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5374 freeAsmop (result, NULL, ic, TRUE);
5378 /*-----------------------------------------------------------------*/
5379 /* genOr - code for or */
5380 /*-----------------------------------------------------------------*/
5382 genOr (iCode * ic, iCode * ifx)
5384 operand *left, *right, *result;
5385 int size, offset = 0;
5386 unsigned long lit = 0L;
5389 D (emitcode (";", "genOr "););
5391 AOP_OP_3_NOFATAL (ic, pushResult);
5392 AOP_SET_LOCALS (ic);
5396 genFarFarLogicOp(ic, "orl");
5402 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5404 AOP_TYPE (left), AOP_TYPE (right));
5405 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5407 AOP_SIZE (left), AOP_SIZE (right));
5410 /* if left is a literal & right is not then exchange them */
5411 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5412 AOP_NEEDSACC (left))
5414 operand *tmp = right;
5419 /* if result = right then exchange them */
5420 if (sameRegs (AOP (result), AOP (right)))
5422 operand *tmp = right;
5427 /* if right is bit then exchange them */
5428 if (AOP_TYPE (right) == AOP_CRY &&
5429 AOP_TYPE (left) != AOP_CRY)
5431 operand *tmp = right;
5435 if (AOP_TYPE (right) == AOP_LIT)
5436 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5438 size = AOP_SIZE (result);
5442 if (AOP_TYPE (left) == AOP_CRY)
5444 if (AOP_TYPE (right) == AOP_LIT)
5446 // c = bit & literal;
5449 // lit != 0 => result = 1
5450 if (AOP_TYPE (result) == AOP_CRY)
5453 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5455 continueIfTrue (ifx);
5458 emitcode ("setb", "c");
5462 // lit == 0 => result = left
5463 if (size && sameRegs (AOP (result), AOP (left)))
5465 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5470 if (AOP_TYPE (right) == AOP_CRY)
5473 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5474 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5479 symbol *tlbl = newiTempLabel (NULL);
5480 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5481 emitcode ("setb", "c");
5482 emitcode ("jb", "%s,%05d$",
5483 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5485 emitcode ("jnz", "%05d$", tlbl->key + 100);
5486 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5488 jmpTrueOrFalse (ifx, tlbl);
5494 emitcode ("", "%05d$:", tlbl->key + 100);
5503 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5504 genIfxJump (ifx, "c");
5508 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5509 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5510 if ((AOP_TYPE (right) == AOP_LIT) &&
5511 (AOP_TYPE (result) == AOP_CRY) &&
5512 (AOP_TYPE (left) != AOP_CRY))
5518 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5520 continueIfTrue (ifx);
5525 // lit = 0, result = boolean(left)
5527 emitcode ("setb", "c");
5531 symbol *tlbl = newiTempLabel (NULL);
5532 emitcode ("jnz", "%05d$", tlbl->key + 100);
5534 emitcode ("", "%05d$:", tlbl->key + 100);
5538 genIfxJump (ifx, "a");
5546 /* if left is same as result */
5547 if (sameRegs (AOP (result), AOP (left)))
5549 for (; size--; offset++)
5551 if (AOP_TYPE (right) == AOP_LIT)
5553 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5559 if (IS_AOP_PREG (left))
5561 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5562 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5563 aopPut (AOP (result), "a", offset);
5567 emitcode ("orl", "%s,%s",
5568 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5569 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5575 if (AOP_TYPE (left) == AOP_ACC)
5577 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5581 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5582 if (IS_AOP_PREG (left))
5584 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5585 aopPut (AOP (result), "a", offset);
5589 emitcode ("orl", "%s,a",
5590 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5598 // left & result in different registers
5599 if (AOP_TYPE (result) == AOP_CRY)
5602 // if(size), result in bit
5603 // if(!size && ifx), conditional oper: if(left | right)
5604 symbol *tlbl = newiTempLabel (NULL);
5605 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5607 emitcode ("setb", "c");
5610 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5611 emitcode ("orl", "a,%s",
5612 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5613 emitcode ("jnz", "%05d$", tlbl->key + 100);
5619 emitcode ("", "%05d$:", tlbl->key + 100);
5623 jmpTrueOrFalse (ifx, tlbl);
5627 for (; (size--); offset++)
5630 // result = left & right
5631 if (AOP_TYPE (right) == AOP_LIT)
5633 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5635 aopPut (AOP (result),
5636 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5640 D (emitcode (";", "better literal OR.");
5642 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5643 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5644 FALSE, FALSE, FALSE));
5649 // faster than result <- left, anl result,right
5650 // and better if result is SFR
5651 if (AOP_TYPE (left) == AOP_ACC)
5653 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5654 FALSE, FALSE, FALSE));
5658 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5659 emitcode ("orl", "a,%s",
5660 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5663 aopPut (AOP (result), "a", offset);
5669 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5670 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5671 freeAsmop (result, NULL, ic, TRUE);
5674 /*-----------------------------------------------------------------*/
5675 /* genXor - code for xclusive or */
5676 /*-----------------------------------------------------------------*/
5678 genXor (iCode * ic, iCode * ifx)
5680 operand *left, *right, *result;
5681 int size, offset = 0;
5682 unsigned long lit = 0L;
5685 D (emitcode (";", "genXor "););
5687 AOP_OP_3_NOFATAL (ic, pushResult);
5688 AOP_SET_LOCALS (ic);
5692 genFarFarLogicOp(ic, "xrl");
5697 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5699 AOP_TYPE (left), AOP_TYPE (right));
5700 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5702 AOP_SIZE (left), AOP_SIZE (right));
5705 /* if left is a literal & right is not ||
5706 if left needs acc & right does not */
5707 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5708 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5710 operand *tmp = right;
5715 /* if result = right then exchange them */
5716 if (sameRegs (AOP (result), AOP (right)))
5718 operand *tmp = right;
5723 /* if right is bit then exchange them */
5724 if (AOP_TYPE (right) == AOP_CRY &&
5725 AOP_TYPE (left) != AOP_CRY)
5727 operand *tmp = right;
5731 if (AOP_TYPE (right) == AOP_LIT)
5732 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5734 size = AOP_SIZE (result);
5738 if (AOP_TYPE (left) == AOP_CRY)
5740 if (AOP_TYPE (right) == AOP_LIT)
5742 // c = bit & literal;
5745 // lit>>1 != 0 => result = 1
5746 if (AOP_TYPE (result) == AOP_CRY)
5749 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5751 continueIfTrue (ifx);
5754 emitcode ("setb", "c");
5761 // lit == 0, result = left
5762 if (size && sameRegs (AOP (result), AOP (left)))
5764 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5768 // lit == 1, result = not(left)
5769 if (size && sameRegs (AOP (result), AOP (left)))
5771 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5776 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5777 emitcode ("cpl", "c");
5786 symbol *tlbl = newiTempLabel (NULL);
5787 if (AOP_TYPE (right) == AOP_CRY)
5790 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5794 int sizer = AOP_SIZE (right);
5796 // if val>>1 != 0, result = 1
5797 emitcode ("setb", "c");
5800 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5802 // test the msb of the lsb
5803 emitcode ("anl", "a,#0xfe");
5804 emitcode ("jnz", "%05d$", tlbl->key + 100);
5808 emitcode ("rrc", "a");
5810 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5811 emitcode ("cpl", "c");
5812 emitcode ("", "%05d$:", (tlbl->key + 100));
5819 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5820 genIfxJump (ifx, "c");
5824 if (sameRegs (AOP (result), AOP (left)))
5826 /* if left is same as result */
5827 for (; size--; offset++)
5829 if (AOP_TYPE (right) == AOP_LIT)
5831 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5833 else if (IS_AOP_PREG (left))
5835 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5836 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5837 aopPut (AOP (result), "a", offset);
5840 emitcode ("xrl", "%s,%s",
5841 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5842 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5846 if (AOP_TYPE (left) == AOP_ACC)
5847 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5850 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5851 if (IS_AOP_PREG (left))
5853 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5854 aopPut (AOP (result), "a", offset);
5857 emitcode ("xrl", "%s,a",
5858 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5865 // left & result in different registers
5866 if (AOP_TYPE (result) == AOP_CRY)
5869 // if(size), result in bit
5870 // if(!size && ifx), conditional oper: if(left ^ right)
5871 symbol *tlbl = newiTempLabel (NULL);
5872 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5874 emitcode ("setb", "c");
5877 if ((AOP_TYPE (right) == AOP_LIT) &&
5878 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5880 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5884 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5885 emitcode ("xrl", "a,%s",
5886 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5888 emitcode ("jnz", "%05d$", tlbl->key + 100);
5894 emitcode ("", "%05d$:", tlbl->key + 100);
5898 jmpTrueOrFalse (ifx, tlbl);
5901 for (; (size--); offset++)
5904 // result = left & right
5905 if (AOP_TYPE (right) == AOP_LIT)
5907 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5909 aopPut (AOP (result),
5910 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5914 D (emitcode (";", "better literal XOR.");
5916 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5917 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5918 FALSE, FALSE, FALSE));
5922 // faster than result <- left, anl result,right
5923 // and better if result is SFR
5924 if (AOP_TYPE (left) == AOP_ACC)
5926 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5927 FALSE, FALSE, FALSE));
5931 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5932 emitcode ("xrl", "a,%s",
5933 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5936 aopPut (AOP (result), "a", offset);
5941 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5942 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5943 freeAsmop (result, NULL, ic, TRUE);
5946 /*-----------------------------------------------------------------*/
5947 /* genInline - write the inline code out */
5948 /*-----------------------------------------------------------------*/
5950 genInline (iCode * ic)
5952 char *buffer, *bp, *bp1;
5954 D (emitcode (";", "genInline ");
5957 _G.inLine += (!options.asmpeep);
5959 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5960 strcpy (buffer, IC_INLINE (ic));
5962 /* emit each line as a code */
5987 /* emitcode("",buffer); */
5988 _G.inLine -= (!options.asmpeep);
5991 /*-----------------------------------------------------------------*/
5992 /* genRRC - rotate right with carry */
5993 /*-----------------------------------------------------------------*/
5997 operand *left, *result;
5998 int size, offset = 0;
6001 D (emitcode (";", "genRRC ");
6004 /* rotate right with carry */
6005 left = IC_LEFT (ic);
6006 result = IC_RESULT (ic);
6007 aopOp (left, ic, FALSE, FALSE);
6008 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6010 /* move it to the result */
6011 size = AOP_SIZE (result);
6015 _startLazyDPSEvaluation ();
6018 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6020 emitcode ("rrc", "a");
6021 if (AOP_SIZE (result) > 1)
6022 aopPut (AOP (result), "a", offset--);
6024 _endLazyDPSEvaluation ();
6026 /* now we need to put the carry into the
6027 highest order byte of the result */
6028 if (AOP_SIZE (result) > 1)
6030 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6033 emitcode ("mov", "acc.7,c");
6034 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6035 freeAsmop (left, NULL, ic, TRUE);
6036 freeAsmop (result, NULL, ic, TRUE);
6039 /*-----------------------------------------------------------------*/
6040 /* genRLC - generate code for rotate left with carry */
6041 /*-----------------------------------------------------------------*/
6045 operand *left, *result;
6046 int size, offset = 0;
6049 D (emitcode (";", "genRLC ");
6052 /* rotate right with carry */
6053 left = IC_LEFT (ic);
6054 result = IC_RESULT (ic);
6055 aopOp (left, ic, FALSE, FALSE);
6056 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6058 /* move it to the result */
6059 size = AOP_SIZE (result);
6063 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6065 emitcode ("add", "a,acc");
6066 if (AOP_SIZE (result) > 1)
6068 aopPut (AOP (result), "a", offset++);
6071 _startLazyDPSEvaluation ();
6074 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6076 emitcode ("rlc", "a");
6077 if (AOP_SIZE (result) > 1)
6078 aopPut (AOP (result), "a", offset++);
6080 _endLazyDPSEvaluation ();
6082 /* now we need to put the carry into the
6083 highest order byte of the result */
6084 if (AOP_SIZE (result) > 1)
6086 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6089 emitcode ("mov", "acc.0,c");
6090 aopPut (AOP (result), "a", 0);
6091 freeAsmop (left, NULL, ic, TRUE);
6092 freeAsmop (result, NULL, ic, TRUE);
6095 /*-----------------------------------------------------------------*/
6096 /* genGetHbit - generates code get highest order bit */
6097 /*-----------------------------------------------------------------*/
6099 genGetHbit (iCode * ic)
6101 operand *left, *result;
6102 left = IC_LEFT (ic);
6103 result = IC_RESULT (ic);
6104 aopOp (left, ic, FALSE, FALSE);
6105 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6107 D (emitcode (";", "genGetHbit ");
6110 /* get the highest order byte into a */
6111 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6112 if (AOP_TYPE (result) == AOP_CRY)
6114 emitcode ("rlc", "a");
6119 emitcode ("rl", "a");
6120 emitcode ("anl", "a,#0x01");
6125 freeAsmop (left, NULL, ic, TRUE);
6126 freeAsmop (result, NULL, ic, TRUE);
6129 /*-----------------------------------------------------------------*/
6130 /* AccRol - rotate left accumulator by known count */
6131 /*-----------------------------------------------------------------*/
6133 AccRol (int shCount)
6135 shCount &= 0x0007; // shCount : 0..7
6142 emitcode ("rl", "a");
6145 emitcode ("rl", "a");
6146 emitcode ("rl", "a");
6149 emitcode ("swap", "a");
6150 emitcode ("rr", "a");
6153 emitcode ("swap", "a");
6156 emitcode ("swap", "a");
6157 emitcode ("rl", "a");
6160 emitcode ("rr", "a");
6161 emitcode ("rr", "a");
6164 emitcode ("rr", "a");
6169 /*-----------------------------------------------------------------*/
6170 /* AccLsh - left shift accumulator by known count */
6171 /*-----------------------------------------------------------------*/
6173 AccLsh (int shCount)
6178 emitcode ("add", "a,acc");
6179 else if (shCount == 2)
6181 emitcode ("add", "a,acc");
6182 emitcode ("add", "a,acc");
6186 /* rotate left accumulator */
6188 /* and kill the lower order bits */
6189 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6194 /*-----------------------------------------------------------------*/
6195 /* AccRsh - right shift accumulator by known count */
6196 /*-----------------------------------------------------------------*/
6198 AccRsh (int shCount)
6205 emitcode ("rrc", "a");
6209 /* rotate right accumulator */
6210 AccRol (8 - shCount);
6211 /* and kill the higher order bits */
6212 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6217 #ifdef BETTER_LITERAL_SHIFT
6218 /*-----------------------------------------------------------------*/
6219 /* AccSRsh - signed right shift accumulator by known count */
6220 /*-----------------------------------------------------------------*/
6222 AccSRsh (int shCount)
6229 emitcode ("mov", "c,acc.7");
6230 emitcode ("rrc", "a");
6232 else if (shCount == 2)
6234 emitcode ("mov", "c,acc.7");
6235 emitcode ("rrc", "a");
6236 emitcode ("mov", "c,acc.7");
6237 emitcode ("rrc", "a");
6241 tlbl = newiTempLabel (NULL);
6242 /* rotate right accumulator */
6243 AccRol (8 - shCount);
6244 /* and kill the higher order bits */
6245 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6246 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6247 emitcode ("orl", "a,#0x%02x",
6248 (unsigned char) ~SRMask[shCount]);
6249 emitcode ("", "%05d$:", tlbl->key + 100);
6255 #ifdef BETTER_LITERAL_SHIFT
6256 /*-----------------------------------------------------------------*/
6257 /* shiftR1Left2Result - shift right one byte from left to result */
6258 /*-----------------------------------------------------------------*/
6260 shiftR1Left2Result (operand * left, int offl,
6261 operand * result, int offr,
6262 int shCount, int sign)
6264 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6265 /* shift right accumulator */
6270 aopPut (AOP (result), "a", offr);
6274 #ifdef BETTER_LITERAL_SHIFT
6275 /*-----------------------------------------------------------------*/
6276 /* shiftL1Left2Result - shift left one byte from left to result */
6277 /*-----------------------------------------------------------------*/
6279 shiftL1Left2Result (operand * left, int offl,
6280 operand * result, int offr, int shCount)
6282 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6283 /* shift left accumulator */
6285 aopPut (AOP (result), "a", offr);
6289 #ifdef BETTER_LITERAL_SHIFT
6290 /*-----------------------------------------------------------------*/
6291 /* movLeft2Result - move byte from left to result */
6292 /*-----------------------------------------------------------------*/
6294 movLeft2Result (operand * left, int offl,
6295 operand * result, int offr, int sign)
6298 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6300 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6302 if (*l == '@' && (IS_AOP_PREG (result)))
6304 emitcode ("mov", "a,%s", l);
6305 aopPut (AOP (result), "a", offr);
6311 aopPut (AOP (result), l, offr);
6315 /* MSB sign in acc.7 ! */
6316 if (getDataSize (left) == offl + 1)
6318 emitcode ("mov", "a,%s", l);
6319 aopPut (AOP (result), "a", offr);
6327 #ifdef BETTER_LITERAL_SHIFT
6328 /*-----------------------------------------------------------------*/
6329 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6330 /*-----------------------------------------------------------------*/
6334 emitcode ("rrc", "a");
6335 emitcode ("xch", "a,%s", x);
6336 emitcode ("rrc", "a");
6337 emitcode ("xch", "a,%s", x);
6341 #ifdef BETTER_LITERAL_SHIFT
6343 /*-----------------------------------------------------------------*/
6344 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6345 /*-----------------------------------------------------------------*/
6349 emitcode ("xch", "a,%s", x);
6350 emitcode ("rlc", "a");
6351 emitcode ("xch", "a,%s", x);
6352 emitcode ("rlc", "a");
6356 #ifdef BETTER_LITERAL_SHIFT
6357 /*-----------------------------------------------------------------*/
6358 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6359 /*-----------------------------------------------------------------*/
6363 emitcode ("xch", "a,%s", x);
6364 emitcode ("add", "a,acc");
6365 emitcode ("xch", "a,%s", x);
6366 emitcode ("rlc", "a");
6370 #ifdef BETTER_LITERAL_SHIFT
6371 /*-----------------------------------------------------------------*/
6372 /* AccAXLsh - left shift a:x by known count (0..7) */
6373 /*-----------------------------------------------------------------*/
6375 AccAXLsh (char *x, int shCount)
6390 case 5: // AAAAABBB:CCCCCDDD
6392 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6394 emitcode ("anl", "a,#0x%02x",
6395 SLMask[shCount]); // BBB00000:CCCCCDDD
6397 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6399 AccRol (shCount); // DDDCCCCC:BBB00000
6401 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6403 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6405 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6407 emitcode ("anl", "a,#0x%02x",
6408 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6410 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6412 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6415 case 6: // AAAAAABB:CCCCCCDD
6416 emitcode ("anl", "a,#0x%02x",
6417 SRMask[shCount]); // 000000BB:CCCCCCDD
6418 emitcode ("mov", "c,acc.0"); // c = B
6419 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6421 AccAXRrl1 (x); // BCCCCCCD:D000000B
6422 AccAXRrl1 (x); // BBCCCCCC:DD000000
6424 emitcode("rrc","a");
6425 emitcode("xch","a,%s", x);
6426 emitcode("rrc","a");
6427 emitcode("mov","c,acc.0"); //<< get correct bit
6428 emitcode("xch","a,%s", x);
6430 emitcode("rrc","a");
6431 emitcode("xch","a,%s", x);
6432 emitcode("rrc","a");
6433 emitcode("xch","a,%s", x);
6436 case 7: // a:x <<= 7
6438 emitcode ("anl", "a,#0x%02x",
6439 SRMask[shCount]); // 0000000B:CCCCCCCD
6441 emitcode ("mov", "c,acc.0"); // c = B
6443 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6445 AccAXRrl1 (x); // BCCCCCCC:D0000000
6454 #ifdef BETTER_LITERAL_SHIFT
6456 /*-----------------------------------------------------------------*/
6457 /* AccAXRsh - right shift a:x known count (0..7) */
6458 /*-----------------------------------------------------------------*/
6460 AccAXRsh (char *x, int shCount)
6468 AccAXRrl1 (x); // 0->a:x
6473 AccAXRrl1 (x); // 0->a:x
6476 AccAXRrl1 (x); // 0->a:x
6481 case 5: // AAAAABBB:CCCCCDDD = a:x
6483 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6485 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6487 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6489 emitcode ("anl", "a,#0x%02x",
6490 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6492 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6494 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6496 emitcode ("anl", "a,#0x%02x",
6497 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6499 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6501 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6503 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6506 case 6: // AABBBBBB:CCDDDDDD
6508 emitcode ("mov", "c,acc.7");
6509 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6511 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6513 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6515 emitcode ("anl", "a,#0x%02x",
6516 SRMask[shCount]); // 000000AA:BBBBBBCC
6519 case 7: // ABBBBBBB:CDDDDDDD
6521 emitcode ("mov", "c,acc.7"); // c = A
6523 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6525 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6527 emitcode ("anl", "a,#0x%02x",
6528 SRMask[shCount]); // 0000000A:BBBBBBBC
6537 #ifdef BETTER_LITERAL_SHIFT
6539 /*-----------------------------------------------------------------*/
6540 /* AccAXRshS - right shift signed a:x known count (0..7) */
6541 /*-----------------------------------------------------------------*/
6543 AccAXRshS (char *x, int shCount)
6551 emitcode ("mov", "c,acc.7");
6552 AccAXRrl1 (x); // s->a:x
6556 emitcode ("mov", "c,acc.7");
6557 AccAXRrl1 (x); // s->a:x
6559 emitcode ("mov", "c,acc.7");
6560 AccAXRrl1 (x); // s->a:x
6565 case 5: // AAAAABBB:CCCCCDDD = a:x
6567 tlbl = newiTempLabel (NULL);
6568 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6570 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6572 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6574 emitcode ("anl", "a,#0x%02x",
6575 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6577 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6579 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6581 emitcode ("anl", "a,#0x%02x",
6582 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6584 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6586 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6588 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6590 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6591 emitcode ("orl", "a,#0x%02x",
6592 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6594 emitcode ("", "%05d$:", tlbl->key + 100);
6595 break; // SSSSAAAA:BBBCCCCC
6597 case 6: // AABBBBBB:CCDDDDDD
6599 tlbl = newiTempLabel (NULL);
6600 emitcode ("mov", "c,acc.7");
6601 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6603 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6605 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6607 emitcode ("anl", "a,#0x%02x",
6608 SRMask[shCount]); // 000000AA:BBBBBBCC
6610 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6611 emitcode ("orl", "a,#0x%02x",
6612 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6614 emitcode ("", "%05d$:", tlbl->key + 100);
6616 case 7: // ABBBBBBB:CDDDDDDD
6618 tlbl = newiTempLabel (NULL);
6619 emitcode ("mov", "c,acc.7"); // c = A
6621 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6623 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6625 emitcode ("anl", "a,#0x%02x",
6626 SRMask[shCount]); // 0000000A:BBBBBBBC
6628 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6629 emitcode ("orl", "a,#0x%02x",
6630 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6632 emitcode ("", "%05d$:", tlbl->key + 100);
6640 #ifdef BETTER_LITERAL_SHIFT
6642 _loadLeftIntoAx(char **lsb,
6648 // Get the initial value from left into a pair of registers.
6649 // MSB must be in A, LSB can be any register.
6651 // If the result is held in registers, it is an optimization
6652 // if the LSB can be held in the register which will hold the,
6653 // result LSB since this saves us from having to copy it into
6654 // the result following AccAXLsh.
6656 // If the result is addressed indirectly, this is not a gain.
6657 if (AOP_NEEDSACC(result))
6661 _startLazyDPSEvaluation();
6662 if (AOP_TYPE(left) == AOP_DPTR2)
6665 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6666 // get LSB in DP2_RESULT_REG.
6667 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6668 assert(!strcmp(leftByte, DP2_RESULT_REG));
6672 // get LSB into DP2_RESULT_REG
6673 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6674 if (strcmp(leftByte, DP2_RESULT_REG))
6676 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6679 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6680 assert(strcmp(leftByte, DP2_RESULT_REG));
6683 _endLazyDPSEvaluation();
6684 *lsb = DP2_RESULT_REG;
6688 if (sameRegs (AOP (result), AOP (left)) &&
6689 ((offl + MSB16) == offr))
6691 /* don't crash result[offr] */
6692 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6693 emitcode ("xch", "a,%s",
6694 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6698 movLeft2Result (left, offl, result, offr, 0);
6699 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6701 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6702 assert(strcmp(*lsb,"a"));
6707 _storeAxResults(char *lsb,
6711 _startLazyDPSEvaluation();
6712 if (AOP_NEEDSACC(result))
6714 /* We have to explicitly update the result LSB.
6716 emitcode("xch","a,%s", lsb);
6717 aopPut(AOP(result), "a", offr);
6718 emitcode("mov","a,%s", lsb);
6720 if (getDataSize (result) > 1)
6722 aopPut (AOP (result), "a", offr + MSB16);
6724 _endLazyDPSEvaluation();
6727 /*-----------------------------------------------------------------*/
6728 /* shiftL2Left2Result - shift left two bytes from left to result */
6729 /*-----------------------------------------------------------------*/
6731 shiftL2Left2Result (operand * left, int offl,
6732 operand * result, int offr, int shCount)
6736 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6738 AccAXLsh (lsb, shCount);
6740 _storeAxResults(lsb, result, offr);
6744 #ifdef BETTER_LITERAL_SHIFT
6745 /*-----------------------------------------------------------------*/
6746 /* shiftR2Left2Result - shift right two bytes from left to result */
6747 /*-----------------------------------------------------------------*/
6749 shiftR2Left2Result (operand * left, int offl,
6750 operand * result, int offr,
6751 int shCount, int sign)
6755 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6757 /* a:x >> shCount (x = lsb(result)) */
6760 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6764 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6767 _storeAxResults(lsb, result, offr);
6773 /*-----------------------------------------------------------------*/
6774 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6775 /*-----------------------------------------------------------------*/
6777 shiftLLeftOrResult (operand * left, int offl,
6778 operand * result, int offr, int shCount)
6780 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6781 /* shift left accumulator */
6783 /* or with result */
6784 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6785 /* back to result */
6786 aopPut (AOP (result), "a", offr);
6792 /*-----------------------------------------------------------------*/
6793 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6794 /*-----------------------------------------------------------------*/
6796 shiftRLeftOrResult (operand * left, int offl,
6797 operand * result, int offr, int shCount)
6799 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6800 /* shift right accumulator */
6802 /* or with result */
6803 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6804 /* back to result */
6805 aopPut (AOP (result), "a", offr);
6809 #ifdef BETTER_LITERAL_SHIFT
6810 /*-----------------------------------------------------------------*/
6811 /* genlshOne - left shift a one byte quantity by known count */
6812 /*-----------------------------------------------------------------*/
6814 genlshOne (operand * result, operand * left, int shCount)
6816 D (emitcode (";", "genlshOne "););
6817 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6821 #ifdef BETTER_LITERAL_SHIFT
6822 /*-----------------------------------------------------------------*/
6823 /* genlshTwo - left shift two bytes by known amount != 0 */
6824 /*-----------------------------------------------------------------*/
6826 genlshTwo (operand * result, operand * left, int shCount)
6830 D (emitcode (";", "genlshTwo "););
6832 size = getDataSize (result);
6834 /* if shCount >= 8 */
6839 _startLazyDPSEvaluation();
6845 _endLazyDPSEvaluation();
6846 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6847 aopPut (AOP (result), zero, LSB);
6851 movLeft2Result (left, LSB, result, MSB16, 0);
6852 aopPut (AOP (result), zero, LSB);
6853 _endLazyDPSEvaluation();
6858 aopPut (AOP (result), zero, LSB);
6859 _endLazyDPSEvaluation();
6863 /* 1 <= shCount <= 7 */
6868 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6872 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6880 /*-----------------------------------------------------------------*/
6881 /* shiftLLong - shift left one long from left to result */
6882 /* offl = LSB or MSB16 */
6883 /*-----------------------------------------------------------------*/
6885 shiftLLong (operand * left, operand * result, int offr)
6888 int size = AOP_SIZE (result);
6890 if (size >= LSB + offr)
6892 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6894 emitcode ("add", "a,acc");
6895 if (sameRegs (AOP (left), AOP (result)) &&
6896 size >= MSB16 + offr && offr != LSB)
6897 emitcode ("xch", "a,%s",
6898 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6900 aopPut (AOP (result), "a", LSB + offr);
6903 if (size >= MSB16 + offr)
6905 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6907 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6910 emitcode ("rlc", "a");
6911 if (sameRegs (AOP (left), AOP (result)) &&
6912 size >= MSB24 + offr && offr != LSB)
6913 emitcode ("xch", "a,%s",
6914 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6916 aopPut (AOP (result), "a", MSB16 + offr);
6919 if (size >= MSB24 + offr)
6921 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6923 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6926 emitcode ("rlc", "a");
6927 if (sameRegs (AOP (left), AOP (result)) &&
6928 size >= MSB32 + offr && offr != LSB)
6929 emitcode ("xch", "a,%s",
6930 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6932 aopPut (AOP (result), "a", MSB24 + offr);
6935 if (size > MSB32 + offr)
6937 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6939 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6942 emitcode ("rlc", "a");
6943 aopPut (AOP (result), "a", MSB32 + offr);
6946 aopPut (AOP (result), zero, LSB);
6952 /*-----------------------------------------------------------------*/
6953 /* genlshFour - shift four byte by a known amount != 0 */
6954 /*-----------------------------------------------------------------*/
6956 genlshFour (operand * result, operand * left, int shCount)
6960 D (emitcode (";", "genlshFour ");
6963 size = AOP_SIZE (result);
6965 /* if shifting more that 3 bytes */
6970 /* lowest order of left goes to the highest
6971 order of the destination */
6972 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6974 movLeft2Result (left, LSB, result, MSB32, 0);
6975 aopPut (AOP (result), zero, LSB);
6976 aopPut (AOP (result), zero, MSB16);
6977 aopPut (AOP (result), zero, MSB24);
6981 /* more than two bytes */
6982 else if (shCount >= 16)
6984 /* lower order two bytes goes to higher order two bytes */
6986 /* if some more remaining */
6988 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6991 movLeft2Result (left, MSB16, result, MSB32, 0);
6992 movLeft2Result (left, LSB, result, MSB24, 0);
6994 aopPut (AOP (result), zero, MSB16);
6995 aopPut (AOP (result), zero, LSB);
6999 /* if more than 1 byte */
7000 else if (shCount >= 8)
7002 /* lower order three bytes goes to higher order three bytes */
7007 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7009 movLeft2Result (left, LSB, result, MSB16, 0);
7015 movLeft2Result (left, MSB24, result, MSB32, 0);
7016 movLeft2Result (left, MSB16, result, MSB24, 0);
7017 movLeft2Result (left, LSB, result, MSB16, 0);
7018 aopPut (AOP (result), zero, LSB);
7020 else if (shCount == 1)
7021 shiftLLong (left, result, MSB16);
7024 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7025 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7026 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7027 aopPut (AOP (result), zero, LSB);
7032 /* 1 <= shCount <= 7 */
7033 else if (shCount <= 2)
7035 shiftLLong (left, result, LSB);
7037 shiftLLong (result, result, LSB);
7039 /* 3 <= shCount <= 7, optimize */
7042 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7043 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7044 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7049 #ifdef BETTER_LITERAL_SHIFT
7050 /*-----------------------------------------------------------------*/
7051 /* genLeftShiftLiteral - left shifting by known count */
7052 /*-----------------------------------------------------------------*/
7054 genLeftShiftLiteral (operand * left,
7059 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7062 size = getSize (operandType (result));
7064 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7066 /* We only handle certain easy cases so far. */
7068 && (shCount < (size * 8))
7072 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7076 freeAsmop (right, NULL, ic, TRUE);
7078 aopOp(left, ic, FALSE, FALSE);
7079 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7082 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7084 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7085 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7087 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7090 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7092 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7093 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7095 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7101 emitcode ("; shift left ", "result %d, left %d", size,
7105 /* I suppose that the left size >= result size */
7108 _startLazyDPSEvaluation();
7111 movLeft2Result (left, size, result, size, 0);
7113 _endLazyDPSEvaluation();
7115 else if (shCount >= (size * 8))
7117 _startLazyDPSEvaluation();
7120 aopPut (AOP (result), zero, size);
7122 _endLazyDPSEvaluation();
7129 genlshOne (result, left, shCount);
7133 genlshTwo (result, left, shCount);
7137 genlshFour (result, left, shCount);
7141 fprintf(stderr, "*** ack! mystery literal shift!\n");
7145 freeAsmop (left, NULL, ic, TRUE);
7146 freeAsmop (result, NULL, ic, TRUE);
7151 /*-----------------------------------------------------------------*/
7152 /* genLeftShift - generates code for left shifting */
7153 /*-----------------------------------------------------------------*/
7155 genLeftShift (iCode * ic)
7157 operand *left, *right, *result;
7160 symbol *tlbl, *tlbl1;
7162 D (emitcode (";", "genLeftShift "););
7164 right = IC_RIGHT (ic);
7165 left = IC_LEFT (ic);
7166 result = IC_RESULT (ic);
7168 aopOp (right, ic, FALSE, FALSE);
7171 #ifdef BETTER_LITERAL_SHIFT
7172 /* if the shift count is known then do it
7173 as efficiently as possible */
7174 if (AOP_TYPE (right) == AOP_LIT)
7176 if (genLeftShiftLiteral (left, right, result, ic))
7183 /* shift count is unknown then we have to form
7184 a loop get the loop count in B : Note: we take
7185 only the lower order byte since shifting
7186 more that 32 bits make no sense anyway, ( the
7187 largest size of an object can be only 32 bits ) */
7189 if (AOP_TYPE (right) == AOP_LIT)
7191 /* Really should be handled by genLeftShiftLiteral,
7192 * but since I'm too lazy to fix that today, at least we can make
7193 * some small improvement.
7195 emitcode("mov", "b,#0x%02x",
7196 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7200 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7201 emitcode ("inc", "b");
7203 freeAsmop (right, NULL, ic, TRUE);
7204 aopOp (left, ic, FALSE, FALSE);
7205 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7207 /* now move the left to the result if they are not the
7209 if (!sameRegs (AOP (left), AOP (result)) &&
7210 AOP_SIZE (result) > 1)
7213 size = AOP_SIZE (result);
7215 _startLazyDPSEvaluation ();
7218 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7219 if (*l == '@' && (IS_AOP_PREG (result)))
7222 emitcode ("mov", "a,%s", l);
7223 aopPut (AOP (result), "a", offset);
7226 aopPut (AOP (result), l, offset);
7229 _endLazyDPSEvaluation ();
7232 tlbl = newiTempLabel (NULL);
7233 size = AOP_SIZE (result);
7235 tlbl1 = newiTempLabel (NULL);
7237 /* if it is only one byte then */
7240 symbol *tlbl1 = newiTempLabel (NULL);
7242 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7244 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7245 emitcode ("", "%05d$:", tlbl->key + 100);
7246 emitcode ("add", "a,acc");
7247 emitcode ("", "%05d$:", tlbl1->key + 100);
7248 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7249 aopPut (AOP (result), "a", 0);
7253 reAdjustPreg (AOP (result));
7255 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7256 emitcode ("", "%05d$:", tlbl->key + 100);
7257 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7259 emitcode ("add", "a,acc");
7260 aopPut (AOP (result), "a", offset++);
7261 _startLazyDPSEvaluation ();
7264 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7266 emitcode ("rlc", "a");
7267 aopPut (AOP (result), "a", offset++);
7269 _endLazyDPSEvaluation ();
7270 reAdjustPreg (AOP (result));
7272 emitcode ("", "%05d$:", tlbl1->key + 100);
7273 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7275 freeAsmop (left, NULL, ic, TRUE);
7276 freeAsmop (result, NULL, ic, TRUE);
7279 #ifdef BETTER_LITERAL_SHIFT
7280 /*-----------------------------------------------------------------*/
7281 /* genrshOne - right shift a one byte quantity by known count */
7282 /*-----------------------------------------------------------------*/
7284 genrshOne (operand * result, operand * left,
7285 int shCount, int sign)
7287 D (emitcode (";", "genrshOne"););
7288 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7292 #ifdef BETTER_LITERAL_SHIFT
7293 /*-----------------------------------------------------------------*/
7294 /* genrshTwo - right shift two bytes by known amount != 0 */
7295 /*-----------------------------------------------------------------*/
7297 genrshTwo (operand * result, operand * left,
7298 int shCount, int sign)
7300 D (emitcode (";", "genrshTwo"););
7302 /* if shCount >= 8 */
7306 _startLazyDPSEvaluation();
7309 shiftR1Left2Result (left, MSB16, result, LSB,
7314 movLeft2Result (left, MSB16, result, LSB, sign);
7316 addSign (result, MSB16, sign);
7317 _endLazyDPSEvaluation();
7320 /* 1 <= shCount <= 7 */
7323 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7330 /*-----------------------------------------------------------------*/
7331 /* shiftRLong - shift right one long from left to result */
7332 /* offl = LSB or MSB16 */
7333 /*-----------------------------------------------------------------*/
7335 shiftRLong (operand * left, int offl,
7336 operand * result, int sign)
7339 emitcode ("clr", "c");
7340 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7342 emitcode ("mov", "c,acc.7");
7343 emitcode ("rrc", "a");
7344 aopPut (AOP (result), "a", MSB32 - offl);
7346 /* add sign of "a" */
7347 addSign (result, MSB32, sign);
7349 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7350 emitcode ("rrc", "a");
7351 aopPut (AOP (result), "a", MSB24 - offl);
7353 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7354 emitcode ("rrc", "a");
7355 aopPut (AOP (result), "a", MSB16 - offl);
7359 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7360 emitcode ("rrc", "a");
7361 aopPut (AOP (result), "a", LSB);
7368 /*-----------------------------------------------------------------*/
7369 /* genrshFour - shift four byte by a known amount != 0 */
7370 /*-----------------------------------------------------------------*/
7372 genrshFour (operand * result, operand * left,
7373 int shCount, int sign)
7375 D (emitcode (";", "genrshFour");
7378 /* if shifting more that 3 bytes */
7383 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7385 movLeft2Result (left, MSB32, result, LSB, sign);
7386 addSign (result, MSB16, sign);
7388 else if (shCount >= 16)
7392 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7395 movLeft2Result (left, MSB24, result, LSB, 0);
7396 movLeft2Result (left, MSB32, result, MSB16, sign);
7398 addSign (result, MSB24, sign);
7400 else if (shCount >= 8)
7404 shiftRLong (left, MSB16, result, sign);
7405 else if (shCount == 0)
7407 movLeft2Result (left, MSB16, result, LSB, 0);
7408 movLeft2Result (left, MSB24, result, MSB16, 0);
7409 movLeft2Result (left, MSB32, result, MSB24, sign);
7410 addSign (result, MSB32, sign);
7414 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7415 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7416 /* the last shift is signed */
7417 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7418 addSign (result, MSB32, sign);
7422 { /* 1 <= shCount <= 7 */
7425 shiftRLong (left, LSB, result, sign);
7427 shiftRLong (result, LSB, result, sign);
7431 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7432 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7433 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7439 #ifdef BETTER_LITERAL_SHIFT
7440 /*-----------------------------------------------------------------*/
7441 /* genRightShiftLiteral - right shifting by known count */
7442 /*-----------------------------------------------------------------*/
7444 genRightShiftLiteral (operand * left,
7450 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7453 size = getSize (operandType (result));
7455 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7457 /* We only handle certain easy cases so far. */
7459 && (shCount < (size * 8))
7463 D(emitcode (";", "genRightShiftLiteral wimping out"););
7467 freeAsmop (right, NULL, ic, TRUE);
7469 aopOp (left, ic, FALSE, FALSE);
7470 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7473 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7477 /* test the LEFT size !!! */
7479 /* I suppose that the left size >= result size */
7482 size = getDataSize (result);
7483 _startLazyDPSEvaluation();
7486 movLeft2Result (left, size, result, size, 0);
7488 _endLazyDPSEvaluation();
7490 else if (shCount >= (size * 8))
7494 /* get sign in acc.7 */
7495 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7497 addSign (result, LSB, sign);
7504 genrshOne (result, left, shCount, sign);
7508 genrshTwo (result, left, shCount, sign);
7512 genrshFour (result, left, shCount, sign);
7519 freeAsmop (left, NULL, ic, TRUE);
7520 freeAsmop (result, NULL, ic, TRUE);
7526 /*-----------------------------------------------------------------*/
7527 /* genSignedRightShift - right shift of signed number */
7528 /*-----------------------------------------------------------------*/
7530 genSignedRightShift (iCode * ic)
7532 operand *right, *left, *result;
7535 symbol *tlbl, *tlbl1;
7537 D (emitcode (";", "genSignedRightShift "););
7539 /* we do it the hard way put the shift count in b
7540 and loop thru preserving the sign */
7542 right = IC_RIGHT (ic);
7543 left = IC_LEFT (ic);
7544 result = IC_RESULT (ic);
7546 aopOp (right, ic, FALSE, FALSE);
7548 #ifdef BETTER_LITERAL_SHIFT
7549 if (AOP_TYPE (right) == AOP_LIT)
7551 if (genRightShiftLiteral (left, right, result, ic, 1))
7557 /* shift count is unknown then we have to form
7558 a loop get the loop count in B : Note: we take
7559 only the lower order byte since shifting
7560 more that 32 bits make no sense anyway, ( the
7561 largest size of an object can be only 32 bits ) */
7563 if (AOP_TYPE (right) == AOP_LIT)
7565 /* Really should be handled by genRightShiftLiteral,
7566 * but since I'm too lazy to fix that today, at least we can make
7567 * some small improvement.
7569 emitcode("mov", "b,#0x%02x",
7570 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7574 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7575 emitcode ("inc", "b");
7577 freeAsmop (right, NULL, ic, TRUE);
7578 aopOp (left, ic, FALSE, FALSE);
7579 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7581 /* now move the left to the result if they are not the
7583 if (!sameRegs (AOP (left), AOP (result)) &&
7584 AOP_SIZE (result) > 1)
7587 size = AOP_SIZE (result);
7589 _startLazyDPSEvaluation ();
7592 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7593 if (*l == '@' && IS_AOP_PREG (result))
7596 emitcode ("mov", "a,%s", l);
7597 aopPut (AOP (result), "a", offset);
7600 aopPut (AOP (result), l, offset);
7603 _endLazyDPSEvaluation ();
7606 /* mov the highest order bit to OVR */
7607 tlbl = newiTempLabel (NULL);
7608 tlbl1 = newiTempLabel (NULL);
7610 size = AOP_SIZE (result);
7612 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7613 emitcode ("rlc", "a");
7614 emitcode ("mov", "ov,c");
7615 /* if it is only one byte then */
7618 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7620 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7621 emitcode ("", "%05d$:", tlbl->key + 100);
7622 emitcode ("mov", "c,ov");
7623 emitcode ("rrc", "a");
7624 emitcode ("", "%05d$:", tlbl1->key + 100);
7625 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7626 aopPut (AOP (result), "a", 0);
7630 reAdjustPreg (AOP (result));
7631 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7632 emitcode ("", "%05d$:", tlbl->key + 100);
7633 emitcode ("mov", "c,ov");
7634 _startLazyDPSEvaluation ();
7637 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7639 emitcode ("rrc", "a");
7640 aopPut (AOP (result), "a", offset--);
7642 _endLazyDPSEvaluation ();
7643 reAdjustPreg (AOP (result));
7644 emitcode ("", "%05d$:", tlbl1->key + 100);
7645 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7648 freeAsmop (left, NULL, ic, TRUE);
7649 freeAsmop (result, NULL, ic, TRUE);
7652 /*-----------------------------------------------------------------*/
7653 /* genRightShift - generate code for right shifting */
7654 /*-----------------------------------------------------------------*/
7656 genRightShift (iCode * ic)
7658 operand *right, *left, *result;
7662 symbol *tlbl, *tlbl1;
7664 D (emitcode (";", "genRightShift "););
7666 /* if signed then we do it the hard way preserve the
7667 sign bit moving it inwards */
7668 retype = getSpec (operandType (IC_RESULT (ic)));
7670 if (!SPEC_USIGN (retype))
7672 genSignedRightShift (ic);
7676 /* signed & unsigned types are treated the same : i.e. the
7677 signed is NOT propagated inwards : quoting from the
7678 ANSI - standard : "for E1 >> E2, is equivalent to division
7679 by 2**E2 if unsigned or if it has a non-negative value,
7680 otherwise the result is implementation defined ", MY definition
7681 is that the sign does not get propagated */
7683 right = IC_RIGHT (ic);
7684 left = IC_LEFT (ic);
7685 result = IC_RESULT (ic);
7687 aopOp (right, ic, FALSE, FALSE);
7689 #ifdef BETTER_LITERAL_SHIFT
7690 /* if the shift count is known then do it
7691 as efficiently as possible */
7692 if (AOP_TYPE (right) == AOP_LIT)
7694 if (genRightShiftLiteral (left, right, result, ic, 0))
7701 /* shift count is unknown then we have to form
7702 a loop get the loop count in B : Note: we take
7703 only the lower order byte since shifting
7704 more that 32 bits make no sense anyway, ( the
7705 largest size of an object can be only 32 bits ) */
7707 if (AOP_TYPE (right) == AOP_LIT)
7709 /* Really should be handled by genRightShiftLiteral,
7710 * but since I'm too lazy to fix that today, at least we can make
7711 * some small improvement.
7713 emitcode("mov", "b,#0x%02x",
7714 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7718 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7719 emitcode ("inc", "b");
7721 freeAsmop (right, NULL, ic, TRUE);
7722 aopOp (left, ic, FALSE, FALSE);
7723 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7725 /* now move the left to the result if they are not the
7727 if (!sameRegs (AOP (left), AOP (result)) &&
7728 AOP_SIZE (result) > 1)
7731 size = AOP_SIZE (result);
7733 _startLazyDPSEvaluation ();
7736 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7737 if (*l == '@' && IS_AOP_PREG (result))
7740 emitcode ("mov", "a,%s", l);
7741 aopPut (AOP (result), "a", offset);
7744 aopPut (AOP (result), l, offset);
7747 _endLazyDPSEvaluation ();
7750 tlbl = newiTempLabel (NULL);
7751 tlbl1 = newiTempLabel (NULL);
7752 size = AOP_SIZE (result);
7755 /* if it is only one byte then */
7758 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7760 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7761 emitcode ("", "%05d$:", tlbl->key + 100);
7763 emitcode ("rrc", "a");
7764 emitcode ("", "%05d$:", tlbl1->key + 100);
7765 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7766 aopPut (AOP (result), "a", 0);
7770 reAdjustPreg (AOP (result));
7771 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7772 emitcode ("", "%05d$:", tlbl->key + 100);
7774 _startLazyDPSEvaluation ();
7777 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7779 emitcode ("rrc", "a");
7780 aopPut (AOP (result), "a", offset--);
7782 _endLazyDPSEvaluation ();
7783 reAdjustPreg (AOP (result));
7785 emitcode ("", "%05d$:", tlbl1->key + 100);
7786 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7789 freeAsmop (left, NULL, ic, TRUE);
7790 freeAsmop (result, NULL, ic, TRUE);
7793 /*-----------------------------------------------------------------*/
7794 /* genUnpackBits - generates code for unpacking bits */
7795 /*-----------------------------------------------------------------*/
7797 genUnpackBits (operand * result, char *rname, int ptype)
7804 D (emitcode (";", "genUnpackBits ");
7807 etype = getSpec (operandType (result));
7809 /* read the first byte */
7815 emitcode ("mov", "a,@%s", rname);
7819 emitcode ("movx", "a,@%s", rname);
7823 emitcode ("movx", "a,@dptr");
7827 emitcode ("clr", "a");
7828 emitcode ("movc", "a", "@a+dptr");
7832 emitcode ("lcall", "__gptrget");
7836 /* if we have bitdisplacement then it fits */
7837 /* into this byte completely or if length is */
7838 /* less than a byte */
7839 if ((shCnt = SPEC_BSTR (etype)) ||
7840 (SPEC_BLEN (etype) <= 8))
7843 /* shift right acc */
7846 emitcode ("anl", "a,#0x%02x",
7847 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7848 aopPut (AOP (result), "a", offset);
7852 /* bit field did not fit in a byte */
7853 rlen = SPEC_BLEN (etype) - 8;
7854 aopPut (AOP (result), "a", offset++);
7863 emitcode ("inc", "%s", rname);
7864 emitcode ("mov", "a,@%s", rname);
7868 emitcode ("inc", "%s", rname);
7869 emitcode ("movx", "a,@%s", rname);
7873 emitcode ("inc", "dptr");
7874 emitcode ("movx", "a,@dptr");
7878 emitcode ("clr", "a");
7879 emitcode ("inc", "dptr");
7880 emitcode ("movc", "a", "@a+dptr");
7884 emitcode ("inc", "dptr");
7885 emitcode ("lcall", "__gptrget");
7890 /* if we are done */
7894 aopPut (AOP (result), "a", offset++);
7900 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7901 aopPut (AOP (result), "a", offset);
7908 /*-----------------------------------------------------------------*/
7909 /* genDataPointerGet - generates code when ptr offset is known */
7910 /*-----------------------------------------------------------------*/
7912 genDataPointerGet (operand * left,
7918 int size, offset = 0;
7919 aopOp (result, ic, TRUE, FALSE);
7921 /* get the string representation of the name */
7922 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7923 size = AOP_SIZE (result);
7924 _startLazyDPSEvaluation ();
7928 sprintf (buffer, "(%s + %d)", l + 1, offset);
7930 sprintf (buffer, "%s", l + 1);
7931 aopPut (AOP (result), buffer, offset++);
7933 _endLazyDPSEvaluation ();
7935 freeAsmop (left, NULL, ic, TRUE);
7936 freeAsmop (result, NULL, ic, TRUE);
7939 /*-----------------------------------------------------------------*/
7940 /* genNearPointerGet - emitcode for near pointer fetch */
7941 /*-----------------------------------------------------------------*/
7943 genNearPointerGet (operand * left,
7950 sym_link *rtype, *retype, *letype;
7951 sym_link *ltype = operandType (left);
7954 rtype = operandType (result);
7955 retype = getSpec (rtype);
7956 letype = getSpec (ltype);
7958 aopOp (left, ic, FALSE, FALSE);
7960 /* if left is rematerialisable and
7961 result is not bit variable type and
7962 the left is pointer to data space i.e
7963 lower 128 bytes of space */
7964 if (AOP_TYPE (left) == AOP_IMMD &&
7965 !IS_BITVAR (retype) &&
7966 !IS_BITVAR (letype) &&
7967 DCL_TYPE (ltype) == POINTER)
7969 genDataPointerGet (left, result, ic);
7973 /* if the value is already in a pointer register
7974 then don't need anything more */
7975 if (!AOP_INPREG (AOP (left)))
7977 /* otherwise get a free pointer register */
7979 preg = getFreePtr (ic, &aop, FALSE);
7980 emitcode ("mov", "%s,%s",
7982 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7986 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7988 freeAsmop (left, NULL, ic, TRUE);
7989 aopOp (result, ic, FALSE, FALSE);
7991 /* if bitfield then unpack the bits */
7992 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7993 genUnpackBits (result, rname, POINTER);
7996 /* we have can just get the values */
7997 int size = AOP_SIZE (result);
8002 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8005 emitcode ("mov", "a,@%s", rname);
8006 aopPut (AOP (result), "a", offset);
8010 sprintf (buffer, "@%s", rname);
8011 aopPut (AOP (result), buffer, offset);
8015 emitcode ("inc", "%s", rname);
8019 /* now some housekeeping stuff */
8022 /* we had to allocate for this iCode */
8023 freeAsmop (NULL, aop, ic, TRUE);
8027 /* we did not allocate which means left
8028 already in a pointer register, then
8029 if size > 0 && this could be used again
8030 we have to point it back to where it
8032 if (AOP_SIZE (result) > 1 &&
8033 !OP_SYMBOL (left)->remat &&
8034 (OP_SYMBOL (left)->liveTo > ic->seq ||
8037 int size = AOP_SIZE (result) - 1;
8039 emitcode ("dec", "%s", rname);
8044 freeAsmop (result, NULL, ic, TRUE);
8048 /*-----------------------------------------------------------------*/
8049 /* genPagedPointerGet - emitcode for paged pointer fetch */
8050 /*-----------------------------------------------------------------*/
8052 genPagedPointerGet (operand * left,
8059 sym_link *rtype, *retype, *letype;
8061 rtype = operandType (result);
8062 retype = getSpec (rtype);
8063 letype = getSpec (operandType (left));
8064 aopOp (left, ic, FALSE, FALSE);
8066 /* if the value is already in a pointer register
8067 then don't need anything more */
8068 if (!AOP_INPREG (AOP (left)))
8070 /* otherwise get a free pointer register */
8072 preg = getFreePtr (ic, &aop, FALSE);
8073 emitcode ("mov", "%s,%s",
8075 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8079 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8081 freeAsmop (left, NULL, ic, TRUE);
8082 aopOp (result, ic, FALSE, FALSE);
8084 /* if bitfield then unpack the bits */
8085 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8086 genUnpackBits (result, rname, PPOINTER);
8089 /* we have can just get the values */
8090 int size = AOP_SIZE (result);
8096 emitcode ("movx", "a,@%s", rname);
8097 aopPut (AOP (result), "a", offset);
8102 emitcode ("inc", "%s", rname);
8106 /* now some housekeeping stuff */
8109 /* we had to allocate for this iCode */
8110 freeAsmop (NULL, aop, ic, TRUE);
8114 /* we did not allocate which means left
8115 already in a pointer register, then
8116 if size > 0 && this could be used again
8117 we have to point it back to where it
8119 if (AOP_SIZE (result) > 1 &&
8120 !OP_SYMBOL (left)->remat &&
8121 (OP_SYMBOL (left)->liveTo > ic->seq ||
8124 int size = AOP_SIZE (result) - 1;
8126 emitcode ("dec", "%s", rname);
8131 freeAsmop (result, NULL, ic, TRUE);
8136 /*-----------------------------------------------------------------*/
8137 /* genFarPointerGet - gget value from far space */
8138 /*-----------------------------------------------------------------*/
8140 genFarPointerGet (operand * left,
8141 operand * result, iCode * ic)
8144 sym_link *retype = getSpec (operandType (result));
8145 sym_link *letype = getSpec (operandType (left));
8146 D (emitcode (";", "genFarPointerGet");
8149 aopOp (left, ic, FALSE, FALSE);
8151 /* if the operand is already in dptr
8152 then we do nothing else we move the value to dptr */
8153 if (AOP_TYPE (left) != AOP_STR)
8155 /* if this is remateriazable */
8156 if (AOP_TYPE (left) == AOP_IMMD)
8158 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8162 /* we need to get it byte by byte */
8163 _startLazyDPSEvaluation ();
8164 if (AOP_TYPE (left) != AOP_DPTR)
8166 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8167 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8168 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8172 /* We need to generate a load to DPTR indirect through DPTR. */
8173 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8175 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8176 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8177 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8178 emitcode ("pop", "dph");
8179 emitcode ("pop", "dpl");
8181 _endLazyDPSEvaluation ();
8184 /* so dptr know contains the address */
8185 freeAsmop (left, NULL, ic, TRUE);
8186 aopOp (result, ic, FALSE, TRUE);
8188 /* if bit then unpack */
8189 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8190 genUnpackBits (result, "dptr", FPOINTER);
8193 size = AOP_SIZE (result);
8196 _startLazyDPSEvaluation ();
8203 emitcode ("movx", "a,@dptr");
8205 emitcode ("inc", "dptr");
8207 aopPut (AOP (result), "a", offset++);
8209 _endLazyDPSEvaluation ();
8212 freeAsmop (result, NULL, ic, TRUE);
8215 /*-----------------------------------------------------------------*/
8216 /* emitcodePointerGet - gget value from code space */
8217 /*-----------------------------------------------------------------*/
8219 emitcodePointerGet (operand * left,
8220 operand * result, iCode * ic)
8223 sym_link *retype = getSpec (operandType (result));
8225 aopOp (left, ic, FALSE, FALSE);
8227 /* if the operand is already in dptr
8228 then we do nothing else we move the value to dptr */
8229 if (AOP_TYPE (left) != AOP_STR)
8231 /* if this is remateriazable */
8232 if (AOP_TYPE (left) == AOP_IMMD)
8234 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8237 { /* we need to get it byte by byte */
8238 _startLazyDPSEvaluation ();
8239 if (AOP_TYPE (left) != AOP_DPTR)
8241 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8242 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8243 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8247 /* We need to generate a load to DPTR indirect through DPTR. */
8248 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8250 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8251 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8252 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8253 emitcode ("pop", "dph");
8254 emitcode ("pop", "dpl");
8256 _endLazyDPSEvaluation ();
8259 /* so dptr know contains the address */
8260 freeAsmop (left, NULL, ic, TRUE);
8261 aopOp (result, ic, FALSE, TRUE);
8263 /* if bit then unpack */
8264 if (IS_BITVAR (retype))
8265 genUnpackBits (result, "dptr", CPOINTER);
8268 size = AOP_SIZE (result);
8271 _startLazyDPSEvaluation ();
8277 emitcode ("clr", "a");
8278 emitcode ("movc", "a,@a+dptr");
8280 emitcode ("inc", "dptr");
8281 aopPut (AOP (result), "a", offset++);
8283 _endLazyDPSEvaluation ();
8286 freeAsmop (result, NULL, ic, TRUE);
8289 /*-----------------------------------------------------------------*/
8290 /* genGenPointerGet - gget value from generic pointer space */
8291 /*-----------------------------------------------------------------*/
8293 genGenPointerGet (operand * left,
8294 operand * result, iCode * ic)
8297 sym_link *retype = getSpec (operandType (result));
8298 sym_link *letype = getSpec (operandType (left));
8300 D (emitcode (";", "genGenPointerGet "); );
8302 aopOp (left, ic, FALSE, TRUE);
8304 /* if the operand is already in dptr
8305 then we do nothing else we move the value to dptr */
8306 if (AOP_TYPE (left) != AOP_STR)
8308 /* if this is remateriazable */
8309 if (AOP_TYPE (left) == AOP_IMMD)
8311 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8312 emitcode ("mov", "b,#%d", pointerCode (retype));
8315 { /* we need to get it byte by byte */
8316 _startLazyDPSEvaluation ();
8317 if (AOP(left)->type==AOP_DPTR2) {
8319 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8322 emitcode ("mov", "dpl,%s", l);
8323 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8326 emitcode ("mov", "dph,%s", l);
8327 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8330 emitcode ("mov", "dpx,%s", l);
8331 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8333 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8334 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8335 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8336 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8338 _endLazyDPSEvaluation ();
8341 /* so dptr know contains the address */
8342 freeAsmop (left, NULL, ic, TRUE);
8343 aopOp (result, ic, FALSE, TRUE);
8345 /* if bit then unpack */
8346 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8347 genUnpackBits (result, "dptr", GPOINTER);
8350 size = AOP_SIZE (result);
8355 emitcode ("lcall", "__gptrget");
8356 aopPut (AOP (result), "a", offset++);
8358 emitcode ("inc", "dptr");
8362 freeAsmop (result, NULL, ic, TRUE);
8365 /*-----------------------------------------------------------------*/
8366 /* genPointerGet - generate code for pointer get */
8367 /*-----------------------------------------------------------------*/
8369 genPointerGet (iCode * ic)
8371 operand *left, *result;
8372 sym_link *type, *etype;
8375 D (emitcode (";", "genPointerGet ");
8378 left = IC_LEFT (ic);
8379 result = IC_RESULT (ic);
8381 /* depending on the type of pointer we need to
8382 move it to the correct pointer register */
8383 type = operandType (left);
8384 etype = getSpec (type);
8385 /* if left is of type of pointer then it is simple */
8386 if (IS_PTR (type) && !IS_FUNC (type->next))
8387 p_type = DCL_TYPE (type);
8390 /* we have to go by the storage class */
8391 p_type = PTR_TYPE (SPEC_OCLS (etype));
8394 /* now that we have the pointer type we assign
8395 the pointer values */
8401 genNearPointerGet (left, result, ic);
8405 genPagedPointerGet (left, result, ic);
8409 genFarPointerGet (left, result, ic);
8413 emitcodePointerGet (left, result, ic);
8417 genGenPointerGet (left, result, ic);
8423 /*-----------------------------------------------------------------*/
8424 /* genPackBits - generates code for packed bit storage */
8425 /*-----------------------------------------------------------------*/
8427 genPackBits (sym_link * etype,
8429 char *rname, int p_type)
8437 blen = SPEC_BLEN (etype);
8438 bstr = SPEC_BSTR (etype);
8440 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8443 /* if the bit lenth is less than or */
8444 /* it exactly fits a byte then */
8445 if (SPEC_BLEN (etype) <= 8)
8447 shCount = SPEC_BSTR (etype);
8449 /* shift left acc */
8452 if (SPEC_BLEN (etype) < 8)
8453 { /* if smaller than a byte */
8459 emitcode ("mov", "b,a");
8460 emitcode ("mov", "a,@%s", rname);
8464 emitcode ("mov", "b,a");
8465 emitcode ("movx", "a,@dptr");
8469 emitcode ("push", "b");
8470 emitcode ("push", "acc");
8471 emitcode ("lcall", "__gptrget");
8472 emitcode ("pop", "b");
8476 emitcode ("anl", "a,#0x%02x", (unsigned char)
8477 ((unsigned char) (0xFF << (blen + bstr)) |
8478 (unsigned char) (0xFF >> (8 - bstr))));
8479 emitcode ("orl", "a,b");
8480 if (p_type == GPOINTER)
8481 emitcode ("pop", "b");
8488 emitcode ("mov", "@%s,a", rname);
8492 emitcode ("movx", "@dptr,a");
8496 emitcode ("lcall", "__gptrput");
8501 if (SPEC_BLEN (etype) <= 8)
8504 emitcode ("inc", "%s", rname);
8505 rLen = SPEC_BLEN (etype);
8507 /* now generate for lengths greater than one byte */
8511 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8523 emitcode ("mov", "@%s,a", rname);
8526 emitcode ("mov", "@%s,%s", rname, l);
8531 emitcode ("movx", "@dptr,a");
8536 emitcode ("lcall", "__gptrput");
8539 emitcode ("inc", "%s", rname);
8544 /* last last was not complete */
8547 /* save the byte & read byte */
8551 emitcode ("mov", "b,a");
8552 emitcode ("mov", "a,@%s", rname);
8556 emitcode ("mov", "b,a");
8557 emitcode ("movx", "a,@dptr");
8561 emitcode ("push", "b");
8562 emitcode ("push", "acc");
8563 emitcode ("lcall", "__gptrget");
8564 emitcode ("pop", "b");
8568 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8569 emitcode ("orl", "a,b");
8572 if (p_type == GPOINTER)
8573 emitcode ("pop", "b");
8579 emitcode ("mov", "@%s,a", rname);
8583 emitcode ("movx", "@dptr,a");
8587 emitcode ("lcall", "__gptrput");
8591 /*-----------------------------------------------------------------*/
8592 /* genDataPointerSet - remat pointer to data space */
8593 /*-----------------------------------------------------------------*/
8595 genDataPointerSet (operand * right,
8599 int size, offset = 0;
8600 char *l, buffer[256];
8602 aopOp (right, ic, FALSE, FALSE);
8604 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8605 size = AOP_SIZE (right);
8609 sprintf (buffer, "(%s + %d)", l + 1, offset);
8611 sprintf (buffer, "%s", l + 1);
8612 emitcode ("mov", "%s,%s", buffer,
8613 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8616 freeAsmop (right, NULL, ic, TRUE);
8617 freeAsmop (result, NULL, ic, TRUE);
8620 /*-----------------------------------------------------------------*/
8621 /* genNearPointerSet - emitcode for near pointer put */
8622 /*-----------------------------------------------------------------*/
8624 genNearPointerSet (operand * right,
8631 sym_link *retype, *letype;
8632 sym_link *ptype = operandType (result);
8634 retype = getSpec (operandType (right));
8635 letype = getSpec (ptype);
8637 aopOp (result, ic, FALSE, FALSE);
8639 /* if the result is rematerializable &
8640 in data space & not a bit variable */
8641 if (AOP_TYPE (result) == AOP_IMMD &&
8642 DCL_TYPE (ptype) == POINTER &&
8643 !IS_BITVAR (retype) &&
8644 !IS_BITVAR (letype))
8646 genDataPointerSet (right, result, ic);
8650 /* if the value is already in a pointer register
8651 then don't need anything more */
8652 if (!AOP_INPREG (AOP (result)))
8654 /* otherwise get a free pointer register */
8656 preg = getFreePtr (ic, &aop, FALSE);
8657 emitcode ("mov", "%s,%s",
8659 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8663 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8665 freeAsmop (result, NULL, ic, TRUE);
8666 aopOp (right, ic, FALSE, FALSE);
8668 /* if bitfield then unpack the bits */
8669 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8670 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8673 /* we have can just get the values */
8674 int size = AOP_SIZE (right);
8679 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8683 emitcode ("mov", "@%s,a", rname);
8686 emitcode ("mov", "@%s,%s", rname, l);
8688 emitcode ("inc", "%s", rname);
8693 /* now some housekeeping stuff */
8696 /* we had to allocate for this iCode */
8697 freeAsmop (NULL, aop, ic, TRUE);
8701 /* we did not allocate which means left
8702 already in a pointer register, then
8703 if size > 0 && this could be used again
8704 we have to point it back to where it
8706 if (AOP_SIZE (right) > 1 &&
8707 !OP_SYMBOL (result)->remat &&
8708 (OP_SYMBOL (result)->liveTo > ic->seq ||
8711 int size = AOP_SIZE (right) - 1;
8713 emitcode ("dec", "%s", rname);
8718 freeAsmop (right, NULL, ic, TRUE);
8723 /*-----------------------------------------------------------------*/
8724 /* genPagedPointerSet - emitcode for Paged pointer put */
8725 /*-----------------------------------------------------------------*/
8727 genPagedPointerSet (operand * right,
8734 sym_link *retype, *letype;
8736 retype = getSpec (operandType (right));
8737 letype = getSpec (operandType (result));
8739 aopOp (result, ic, FALSE, FALSE);
8741 /* if the value is already in a pointer register
8742 then don't need anything more */
8743 if (!AOP_INPREG (AOP (result)))
8745 /* otherwise get a free pointer register */
8747 preg = getFreePtr (ic, &aop, FALSE);
8748 emitcode ("mov", "%s,%s",
8750 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8754 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8756 freeAsmop (result, NULL, ic, TRUE);
8757 aopOp (right, ic, FALSE, FALSE);
8759 /* if bitfield then unpack the bits */
8760 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8761 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8764 /* we have can just get the values */
8765 int size = AOP_SIZE (right);
8770 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8773 emitcode ("movx", "@%s,a", rname);
8776 emitcode ("inc", "%s", rname);
8782 /* now some housekeeping stuff */
8785 /* we had to allocate for this iCode */
8786 freeAsmop (NULL, aop, ic, TRUE);
8790 /* we did not allocate which means left
8791 already in a pointer register, then
8792 if size > 0 && this could be used again
8793 we have to point it back to where it
8795 if (AOP_SIZE (right) > 1 &&
8796 !OP_SYMBOL (result)->remat &&
8797 (OP_SYMBOL (result)->liveTo > ic->seq ||
8800 int size = AOP_SIZE (right) - 1;
8802 emitcode ("dec", "%s", rname);
8807 freeAsmop (right, NULL, ic, TRUE);
8812 /*-----------------------------------------------------------------*/
8813 /* genFarPointerSet - set value from far space */
8814 /*-----------------------------------------------------------------*/
8816 genFarPointerSet (operand * right,
8817 operand * result, iCode * ic)
8820 sym_link *retype = getSpec (operandType (right));
8821 sym_link *letype = getSpec (operandType (result));
8823 aopOp (result, ic, FALSE, FALSE);
8825 /* if the operand is already in dptr
8826 then we do nothing else we move the value to dptr */
8827 if (AOP_TYPE (result) != AOP_STR)
8829 /* if this is remateriazable */
8830 if (AOP_TYPE (result) == AOP_IMMD)
8831 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8834 /* we need to get it byte by byte */
8835 _startLazyDPSEvaluation ();
8836 if (AOP_TYPE (result) != AOP_DPTR)
8838 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8839 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8840 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8844 /* We need to generate a load to DPTR indirect through DPTR. */
8845 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8847 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8848 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8849 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8850 emitcode ("pop", "dph");
8851 emitcode ("pop", "dpl");
8853 _endLazyDPSEvaluation ();
8856 /* so dptr know contains the address */
8857 freeAsmop (result, NULL, ic, TRUE);
8858 aopOp (right, ic, FALSE, TRUE);
8860 /* if bit then unpack */
8861 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8862 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8865 size = AOP_SIZE (right);
8868 _startLazyDPSEvaluation ();
8871 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8877 emitcode ("movx", "@dptr,a");
8879 emitcode ("inc", "dptr");
8881 _endLazyDPSEvaluation ();
8884 freeAsmop (right, NULL, ic, TRUE);
8887 /*-----------------------------------------------------------------*/
8888 /* genGenPointerSet - set value from generic pointer space */
8889 /*-----------------------------------------------------------------*/
8891 genGenPointerSet (operand * right,
8892 operand * result, iCode * ic)
8895 sym_link *retype = getSpec (operandType (right));
8896 sym_link *letype = getSpec (operandType (result));
8898 aopOp (result, ic, FALSE, TRUE);
8900 /* if the operand is already in dptr
8901 then we do nothing else we move the value to dptr */
8902 if (AOP_TYPE (result) != AOP_STR)
8904 _startLazyDPSEvaluation ();
8905 /* if this is remateriazable */
8906 if (AOP_TYPE (result) == AOP_IMMD)
8908 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8909 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8912 { /* we need to get it byte by byte */
8913 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8914 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8915 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8916 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8918 _endLazyDPSEvaluation ();
8920 /* so dptr know contains the address */
8921 freeAsmop (result, NULL, ic, TRUE);
8922 aopOp (right, ic, FALSE, TRUE);
8924 /* if bit then unpack */
8925 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8926 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8929 size = AOP_SIZE (right);
8932 _startLazyDPSEvaluation ();
8935 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8941 emitcode ("lcall", "__gptrput");
8943 emitcode ("inc", "dptr");
8945 _endLazyDPSEvaluation ();
8948 freeAsmop (right, NULL, ic, TRUE);
8951 /*-----------------------------------------------------------------*/
8952 /* genPointerSet - stores the value into a pointer location */
8953 /*-----------------------------------------------------------------*/
8955 genPointerSet (iCode * ic)
8957 operand *right, *result;
8958 sym_link *type, *etype;
8961 D (emitcode (";", "genPointerSet ");
8964 right = IC_RIGHT (ic);
8965 result = IC_RESULT (ic);
8967 /* depending on the type of pointer we need to
8968 move it to the correct pointer register */
8969 type = operandType (result);
8970 etype = getSpec (type);
8971 /* if left is of type of pointer then it is simple */
8972 if (IS_PTR (type) && !IS_FUNC (type->next))
8974 p_type = DCL_TYPE (type);
8978 /* we have to go by the storage class */
8979 p_type = PTR_TYPE (SPEC_OCLS (etype));
8982 /* now that we have the pointer type we assign
8983 the pointer values */
8989 genNearPointerSet (right, result, ic);
8993 genPagedPointerSet (right, result, ic);
8997 genFarPointerSet (right, result, ic);
9001 genGenPointerSet (right, result, ic);
9007 /*-----------------------------------------------------------------*/
9008 /* genIfx - generate code for Ifx statement */
9009 /*-----------------------------------------------------------------*/
9011 genIfx (iCode * ic, iCode * popIc)
9013 operand *cond = IC_COND (ic);
9016 D (emitcode (";", "genIfx "););
9018 aopOp (cond, ic, FALSE, FALSE);
9020 /* get the value into acc */
9021 if (AOP_TYPE (cond) != AOP_CRY)
9025 /* the result is now in the accumulator */
9026 freeAsmop (cond, NULL, ic, TRUE);
9028 /* if there was something to be popped then do it */
9032 /* if the condition is a bit variable */
9033 if (isbit && IS_ITEMP (cond) &&
9035 genIfxJump (ic, SPIL_LOC (cond)->rname);
9036 else if (isbit && !IS_ITEMP (cond))
9037 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9039 genIfxJump (ic, "a");
9044 /*-----------------------------------------------------------------*/
9045 /* genAddrOf - generates code for address of */
9046 /*-----------------------------------------------------------------*/
9048 genAddrOf (iCode * ic)
9050 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9053 D (emitcode (";", "genAddrOf ");
9056 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9058 /* if the operand is on the stack then we
9059 need to get the stack offset of this
9063 /* if it has an offset then we need to compute
9067 emitcode ("mov", "a,_bp");
9068 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9069 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9073 /* we can just move _bp */
9074 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9076 /* fill the result with zero */
9077 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9080 if (options.stack10bit && size < (FPTRSIZE - 1))
9083 "*** warning: pointer to stack var truncated.\n");
9090 if (options.stack10bit && offset == 2)
9092 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9096 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9103 /* object not on stack then we need the name */
9104 size = AOP_SIZE (IC_RESULT (ic));
9109 char s[SDCC_NAME_MAX];
9111 sprintf (s, "#(%s >> %d)",
9115 sprintf (s, "#%s", sym->rname);
9116 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9120 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9124 /*-----------------------------------------------------------------*/
9125 /* genFarFarAssign - assignment when both are in far space */
9126 /*-----------------------------------------------------------------*/
9128 genFarFarAssign (operand * result, operand * right, iCode * ic)
9130 int size = AOP_SIZE (right);
9132 symbol *rSym = NULL;
9136 /* quick & easy case. */
9137 D(emitcode(";","genFarFarAssign (1 byte case)"););
9138 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9139 freeAsmop (right, NULL, ic, FALSE);
9140 /* now assign DPTR to result */
9142 aopOp(result, ic, FALSE, FALSE);
9144 aopPut(AOP(result), "a", 0);
9145 freeAsmop(result, NULL, ic, FALSE);
9149 /* See if we've got an underlying symbol to abuse. */
9150 if (IS_SYMOP(result) && OP_SYMBOL(result))
9152 if (IS_TRUE_SYMOP(result))
9154 rSym = OP_SYMBOL(result);
9156 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9158 rSym = OP_SYMBOL(result)->usl.spillLoc;
9162 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9164 /* We can use the '390 auto-toggle feature to good effect here. */
9166 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9167 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9168 emitcode ("mov", "dptr,#%s", rSym->rname);
9169 /* DP2 = result, DP1 = right, DP1 is current. */
9172 emitcode("movx", "a,@dptr");
9173 emitcode("movx", "@dptr,a");
9176 emitcode("inc", "dptr");
9177 emitcode("inc", "dptr");
9180 emitcode("mov", "dps, #0");
9181 freeAsmop (right, NULL, ic, FALSE);
9185 D (emitcode (";", "genFarFarAssign"););
9186 aopOp (result, ic, TRUE, TRUE);
9188 _startLazyDPSEvaluation ();
9192 aopPut (AOP (result),
9193 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9196 _endLazyDPSEvaluation ();
9197 freeAsmop (result, NULL, ic, FALSE);
9198 freeAsmop (right, NULL, ic, FALSE);
9202 /*-----------------------------------------------------------------*/
9203 /* genAssign - generate code for assignment */
9204 /*-----------------------------------------------------------------*/
9206 genAssign (iCode * ic)
9208 operand *result, *right;
9210 unsigned long lit = 0L;
9212 D (emitcode (";", "genAssign ");
9215 result = IC_RESULT (ic);
9216 right = IC_RIGHT (ic);
9218 /* if they are the same */
9219 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9222 aopOp (right, ic, FALSE, FALSE);
9224 emitcode (";", "genAssign: resultIsFar = %s",
9225 isOperandInFarSpace (result) ?
9228 /* special case both in far space */
9229 if ((AOP_TYPE (right) == AOP_DPTR ||
9230 AOP_TYPE (right) == AOP_DPTR2) &&
9231 /* IS_TRUE_SYMOP(result) && */
9232 isOperandInFarSpace (result))
9234 genFarFarAssign (result, right, ic);
9238 aopOp (result, ic, TRUE, FALSE);
9240 /* if they are the same registers */
9241 if (sameRegs (AOP (right), AOP (result)))
9244 /* if the result is a bit */
9245 if (AOP_TYPE (result) == AOP_CRY)
9248 /* if the right size is a literal then
9249 we know what the value is */
9250 if (AOP_TYPE (right) == AOP_LIT)
9252 if (((int) operandLitValue (right)))
9253 aopPut (AOP (result), one, 0);
9255 aopPut (AOP (result), zero, 0);
9259 /* the right is also a bit variable */
9260 if (AOP_TYPE (right) == AOP_CRY)
9262 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9263 aopPut (AOP (result), "c", 0);
9269 aopPut (AOP (result), "a", 0);
9273 /* bit variables done */
9275 size = AOP_SIZE (result);
9277 if (AOP_TYPE (right) == AOP_LIT)
9278 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9281 (AOP_TYPE (result) != AOP_REG) &&
9282 (AOP_TYPE (right) == AOP_LIT) &&
9283 !IS_FLOAT (operandType (right)))
9285 _startLazyDPSEvaluation ();
9286 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9288 aopPut (AOP (result),
9289 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9294 /* And now fill the rest with zeros. */
9297 emitcode ("clr", "a");
9301 aopPut (AOP (result), "a", offset++);
9303 _endLazyDPSEvaluation ();
9307 _startLazyDPSEvaluation ();
9310 aopPut (AOP (result),
9311 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9315 _endLazyDPSEvaluation ();
9319 freeAsmop (right, NULL, ic, FALSE);
9320 freeAsmop (result, NULL, ic, TRUE);
9323 /*-----------------------------------------------------------------*/
9324 /* genJumpTab - generates code for jump table */
9325 /*-----------------------------------------------------------------*/
9327 genJumpTab (iCode * ic)
9332 D (emitcode (";", "genJumpTab ");
9335 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9336 /* get the condition into accumulator */
9337 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9339 /* multiply by four! */
9340 emitcode ("add", "a,acc");
9341 emitcode ("add", "a,acc");
9342 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9344 jtab = newiTempLabel (NULL);
9345 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9346 emitcode ("jmp", "@a+dptr");
9347 emitcode ("", "%05d$:", jtab->key + 100);
9348 /* now generate the jump labels */
9349 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9350 jtab = setNextItem (IC_JTLABELS (ic)))
9351 emitcode ("ljmp", "%05d$", jtab->key + 100);
9355 /*-----------------------------------------------------------------*/
9356 /* genCast - gen code for casting */
9357 /*-----------------------------------------------------------------*/
9359 genCast (iCode * ic)
9361 operand *result = IC_RESULT (ic);
9362 sym_link *ctype = operandType (IC_LEFT (ic));
9363 sym_link *rtype = operandType (IC_RIGHT (ic));
9364 operand *right = IC_RIGHT (ic);
9367 D (emitcode (";", "genCast ");
9370 /* if they are equivalent then do nothing */
9371 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9374 aopOp (right, ic, FALSE, FALSE);
9375 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9377 /* if the result is a bit */
9378 if (AOP_TYPE (result) == AOP_CRY)
9380 /* if the right size is a literal then
9381 we know what the value is */
9382 if (AOP_TYPE (right) == AOP_LIT)
9384 if (((int) operandLitValue (right)))
9385 aopPut (AOP (result), one, 0);
9387 aopPut (AOP (result), zero, 0);
9392 /* the right is also a bit variable */
9393 if (AOP_TYPE (right) == AOP_CRY)
9395 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9396 aopPut (AOP (result), "c", 0);
9402 aopPut (AOP (result), "a", 0);
9406 /* if they are the same size : or less */
9407 if (AOP_SIZE (result) <= AOP_SIZE (right))
9410 /* if they are in the same place */
9411 if (sameRegs (AOP (right), AOP (result)))
9414 /* if they in different places then copy */
9415 size = AOP_SIZE (result);
9417 _startLazyDPSEvaluation ();
9420 aopPut (AOP (result),
9421 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9425 _endLazyDPSEvaluation ();
9430 /* if the result is of type pointer */
9435 sym_link *type = operandType (right);
9437 /* pointer to generic pointer */
9438 if (IS_GENPTR (ctype))
9444 p_type = DCL_TYPE (type);
9448 #if OLD_CAST_BEHAVIOR
9449 /* KV: we are converting a non-pointer type to
9450 * a generic pointer. This (ifdef'd out) code
9451 * says that the resulting generic pointer
9452 * should have the same class as the storage
9453 * location of the non-pointer variable.
9455 * For example, converting an int (which happens
9456 * to be stored in DATA space) to a pointer results
9457 * in a DATA generic pointer; if the original int
9458 * in XDATA space, so will be the resulting pointer.
9460 * I don't like that behavior, and thus this change:
9461 * all such conversions will be forced to XDATA and
9462 * throw a warning. If you want some non-XDATA
9463 * type, or you want to suppress the warning, you
9464 * must go through an intermediate cast, like so:
9466 * char _generic *gp = (char _xdata *)(intVar);
9468 sym_link *etype = getSpec (type);
9470 /* we have to go by the storage class */
9471 if (SPEC_OCLS (etype) != generic)
9473 p_type = PTR_TYPE (SPEC_OCLS (etype));
9478 /* Converting unknown class (i.e. register variable)
9479 * to generic pointer. This is not good, but
9480 * we'll make a guess (and throw a warning).
9483 werror (W_INT_TO_GEN_PTR_CAST);
9487 /* the first two bytes are known */
9488 size = GPTRSIZE - 1;
9490 _startLazyDPSEvaluation ();
9493 aopPut (AOP (result),
9494 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9498 _endLazyDPSEvaluation ();
9500 /* the last byte depending on type */
9518 /* this should never happen */
9519 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9520 "got unknown pointer type");
9523 aopPut (AOP (result), l, GPTRSIZE - 1);
9527 /* just copy the pointers */
9528 size = AOP_SIZE (result);
9530 _startLazyDPSEvaluation ();
9533 aopPut (AOP (result),
9534 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9538 _endLazyDPSEvaluation ();
9542 /* so we now know that the size of destination is greater
9543 than the size of the source */
9544 /* we move to result for the size of source */
9545 size = AOP_SIZE (right);
9547 _startLazyDPSEvaluation ();
9550 aopPut (AOP (result),
9551 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9555 _endLazyDPSEvaluation ();
9557 /* now depending on the sign of the source && destination */
9558 size = AOP_SIZE (result) - AOP_SIZE (right);
9559 /* if unsigned or not an integral type */
9560 /* also, if the source is a bit, we don't need to sign extend, because
9561 * it can't possibly have set the sign bit.
9563 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9567 aopPut (AOP (result), zero, offset++);
9572 /* we need to extend the sign :{ */
9573 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9574 FALSE, FALSE, TRUE);
9576 emitcode ("rlc", "a");
9577 emitcode ("subb", "a,acc");
9579 aopPut (AOP (result), "a", offset++);
9582 /* we are done hurray !!!! */
9585 freeAsmop (right, NULL, ic, TRUE);
9586 freeAsmop (result, NULL, ic, TRUE);
9590 /*-----------------------------------------------------------------*/
9591 /* genDjnz - generate decrement & jump if not zero instrucion */
9592 /*-----------------------------------------------------------------*/
9594 genDjnz (iCode * ic, iCode * ifx)
9600 /* if the if condition has a false label
9601 then we cannot save */
9605 /* if the minus is not of the form
9607 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9608 !IS_OP_LITERAL (IC_RIGHT (ic)))
9611 if (operandLitValue (IC_RIGHT (ic)) != 1)
9614 /* if the size of this greater than one then no
9616 if (getSize (operandType (IC_RESULT (ic))) > 1)
9619 /* otherwise we can save BIG */
9620 D(emitcode(";", "genDjnz"););
9622 lbl = newiTempLabel (NULL);
9623 lbl1 = newiTempLabel (NULL);
9625 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9627 if (AOP_NEEDSACC(IC_RESULT(ic)))
9629 /* If the result is accessed indirectly via
9630 * the accumulator, we must explicitly write
9631 * it back after the decrement.
9633 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9635 if (strcmp(rByte, "a"))
9637 /* Something is hopelessly wrong */
9638 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9639 __FILE__, __LINE__);
9640 /* We can just give up; the generated code will be inefficient,
9643 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9646 emitcode ("dec", "%s", rByte);
9647 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9648 emitcode ("jnz", "%05d$", lbl->key + 100);
9650 else if (IS_AOP_PREG (IC_RESULT (ic)))
9652 emitcode ("dec", "%s",
9653 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9654 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9655 emitcode ("jnz", "%05d$", lbl->key + 100);
9659 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9662 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9663 emitcode ("", "%05d$:", lbl->key + 100);
9664 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9665 emitcode ("", "%05d$:", lbl1->key + 100);
9667 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9672 /*-----------------------------------------------------------------*/
9673 /* genReceive - generate code for a receive iCode */
9674 /*-----------------------------------------------------------------*/
9676 genReceive (iCode * ic)
9679 D (emitcode (";", "genReceive ");
9682 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9683 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9684 IS_TRUE_SYMOP (IC_RESULT (ic))))
9686 int size = getSize (operandType (IC_RESULT (ic)));
9687 int offset = fReturnSizeDS390 - size;
9690 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9691 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9694 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9695 size = AOP_SIZE (IC_RESULT (ic));
9699 emitcode ("pop", "acc");
9700 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9707 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9709 assignResultValue (IC_RESULT (ic));
9712 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9715 /*-----------------------------------------------------------------*/
9716 /* gen390Code - generate code for Dallas 390 based controllers */
9717 /*-----------------------------------------------------------------*/
9719 gen390Code (iCode * lic)
9724 lineHead = lineCurr = NULL;
9728 /* print the allocation information */
9730 printAllocInfo (currFunc, codeOutFile);
9732 /* if debug information required */
9733 if (options.debug && currFunc)
9735 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9737 if (IS_STATIC (currFunc->etype))
9738 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9740 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9743 /* stack pointer name */
9744 if (options.useXstack)
9750 for (ic = lic; ic; ic = ic->next)
9753 if (cln != ic->lineno)
9758 emitcode ("", "C$%s$%d$%d$%d ==.",
9759 FileBaseName (ic->filename), ic->lineno,
9760 ic->level, ic->block);
9763 emitcode (";", "%s %d", ic->filename, ic->lineno);
9766 /* if the result is marked as
9767 spilt and rematerializable or code for
9768 this has already been generated then
9770 if (resultRemat (ic) || ic->generated)
9773 /* depending on the operation */
9793 /* IPOP happens only when trying to restore a
9794 spilt live range, if there is an ifx statement
9795 following this pop then the if statement might
9796 be using some of the registers being popped which
9797 would destory the contents of the register so
9798 we need to check for this condition and handle it */
9800 ic->next->op == IFX &&
9801 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9802 genIfx (ic->next, ic);
9820 genEndFunction (ic);
9840 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9857 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9861 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9868 /* note these two are xlated by algebraic equivalence
9869 during parsing SDCC.y */
9870 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9871 "got '>=' or '<=' shouldn't have come here");
9875 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9887 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9891 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9895 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9922 case GET_VALUE_AT_ADDRESS:
9927 if (POINTER_SET (ic))
9954 addSet (&_G.sendSet, ic);
9963 /* now we are ready to call the
9964 peep hole optimizer */
9965 if (!options.nopeep)
9966 peepHole (&lineHead);
9968 /* now do the actual printing */
9969 printLine (lineHead, codeOutFile);