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) && !defined(__MINGW32__)
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) ||
1762 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
1765 /* find the registers in use at this time
1766 and push them away to safety */
1767 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1771 if (options.useXstack)
1773 if (bitVectBitValue (rsave, R0_IDX))
1774 emitcode ("mov", "b,r0");
1775 emitcode ("mov", "r0,%s", spname);
1776 for (i = 0; i < ds390_nRegs; i++)
1778 if (bitVectBitValue (rsave, i))
1781 emitcode ("mov", "a,b");
1783 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1784 emitcode ("movx", "@r0,a");
1785 emitcode ("inc", "r0");
1788 emitcode ("mov", "%s,r0", spname);
1789 if (bitVectBitValue (rsave, R0_IDX))
1790 emitcode ("mov", "r0,b");
1793 for (i = 0; i < ds390_nRegs; i++)
1795 if (bitVectBitValue (rsave, i))
1796 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1799 detype = getSpec (operandType (IC_LEFT (ic)));
1802 /*-----------------------------------------------------------------*/
1803 /* unsaveRegisters - pop the pushed registers */
1804 /*-----------------------------------------------------------------*/
1806 unsaveRegisters (iCode * ic)
1810 /* find the registers in use at this time
1811 and push them away to safety */
1812 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1815 if (options.useXstack)
1817 emitcode ("mov", "r0,%s", spname);
1818 for (i = ds390_nRegs; i >= 0; i--)
1820 if (bitVectBitValue (rsave, i))
1822 emitcode ("dec", "r0");
1823 emitcode ("movx", "a,@r0");
1825 emitcode ("mov", "b,a");
1827 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1831 emitcode ("mov", "%s,r0", spname);
1832 if (bitVectBitValue (rsave, R0_IDX))
1833 emitcode ("mov", "r0,b");
1836 for (i = ds390_nRegs; i >= 0; i--)
1838 if (bitVectBitValue (rsave, i))
1839 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1845 /*-----------------------------------------------------------------*/
1847 /*-----------------------------------------------------------------*/
1849 pushSide (operand * oper, int size)
1852 _startLazyDPSEvaluation ();
1855 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1856 if (AOP_TYPE (oper) != AOP_REG &&
1857 AOP_TYPE (oper) != AOP_DIR &&
1860 emitcode ("mov", "a,%s", l);
1861 emitcode ("push", "acc");
1864 emitcode ("push", "%s", l);
1866 _endLazyDPSEvaluation ();
1869 /*-----------------------------------------------------------------*/
1870 /* assignResultValue - */
1871 /*-----------------------------------------------------------------*/
1873 assignResultValue (operand * oper)
1876 int size = AOP_SIZE (oper);
1878 _startLazyDPSEvaluation ();
1881 aopPut (AOP (oper), fReturn[offset], offset);
1884 _endLazyDPSEvaluation ();
1888 /*-----------------------------------------------------------------*/
1889 /* genXpush - pushes onto the external stack */
1890 /*-----------------------------------------------------------------*/
1892 genXpush (iCode * ic)
1894 asmop *aop = newAsmop (0);
1896 int size, offset = 0;
1898 D (emitcode (";", "genXpush ");
1901 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1902 r = getFreePtr (ic, &aop, FALSE);
1905 emitcode ("mov", "%s,_spx", r->name);
1907 size = AOP_SIZE (IC_LEFT (ic));
1908 _startLazyDPSEvaluation ();
1912 char *l = aopGet (AOP (IC_LEFT (ic)),
1913 offset++, FALSE, FALSE, TRUE);
1915 emitcode ("movx", "@%s,a", r->name);
1916 emitcode ("inc", "%s", r->name);
1919 _endLazyDPSEvaluation ();
1922 emitcode ("mov", "_spx,%s", r->name);
1924 freeAsmop (NULL, aop, ic, TRUE);
1925 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1928 /*-----------------------------------------------------------------*/
1929 /* genIpush - genrate code for pushing this gets a little complex */
1930 /*-----------------------------------------------------------------*/
1932 genIpush (iCode * ic)
1934 int size, offset = 0;
1937 D (emitcode (";", "genIpush ");
1940 /* if this is not a parm push : ie. it is spill push
1941 and spill push is always done on the local stack */
1945 /* and the item is spilt then do nothing */
1946 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1949 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1950 size = AOP_SIZE (IC_LEFT (ic));
1951 /* push it on the stack */
1952 _startLazyDPSEvaluation ();
1955 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1961 emitcode ("push", "%s", l);
1963 _endLazyDPSEvaluation ();
1967 /* this is a paramter push: in this case we call
1968 the routine to find the call and save those
1969 registers that need to be saved */
1972 /* if use external stack then call the external
1973 stack pushing routine */
1974 if (options.useXstack)
1980 /* then do the push */
1981 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1983 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1984 size = AOP_SIZE (IC_LEFT (ic));
1986 _startLazyDPSEvaluation ();
1989 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1990 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1991 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1994 emitcode ("mov", "a,%s", l);
1995 emitcode ("push", "acc");
1998 emitcode ("push", "%s", l);
2000 _endLazyDPSEvaluation ();
2002 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2005 /*-----------------------------------------------------------------*/
2006 /* genIpop - recover the registers: can happen only for spilling */
2007 /*-----------------------------------------------------------------*/
2009 genIpop (iCode * ic)
2013 D (emitcode (";", "genIpop ");
2017 /* if the temp was not pushed then */
2018 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2021 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2022 size = AOP_SIZE (IC_LEFT (ic));
2023 offset = (size - 1);
2024 _startLazyDPSEvaluation ();
2027 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2028 FALSE, TRUE, TRUE));
2030 _endLazyDPSEvaluation ();
2032 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2035 /*-----------------------------------------------------------------*/
2036 /* unsaveRBank - restores the resgister bank from stack */
2037 /*-----------------------------------------------------------------*/
2039 unsaveRBank (int bank, iCode * ic, bool popPsw)
2045 if (options.useXstack)
2049 /* Assume r0 is available for use. */
2050 r = ds390_regWithIdx (R0_IDX);;
2055 r = getFreePtr (ic, &aop, FALSE);
2057 emitcode ("mov", "%s,_spx", r->name);
2062 if (options.useXstack)
2064 emitcode ("movx", "a,@%s", r->name);
2065 emitcode ("mov", "psw,a");
2066 emitcode ("dec", "%s", r->name);
2070 emitcode ("pop", "psw");
2074 for (i = (ds390_nRegs - 1); i >= 0; i--)
2076 if (options.useXstack)
2078 emitcode ("movx", "a,@%s", r->name);
2079 emitcode ("mov", "(%s+%d),a",
2080 regs390[i].base, 8 * bank + regs390[i].offset);
2081 emitcode ("dec", "%s", r->name);
2085 emitcode ("pop", "(%s+%d)",
2086 regs390[i].base, 8 * bank + regs390[i].offset);
2089 if (options.useXstack)
2091 emitcode ("mov", "_spx,%s", r->name);
2096 freeAsmop (NULL, aop, ic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* saveRBank - saves an entire register bank on the stack */
2102 /*-----------------------------------------------------------------*/
2104 saveRBank (int bank, iCode * ic, bool pushPsw)
2110 if (options.useXstack)
2114 /* Assume r0 is available for use. */
2115 r = ds390_regWithIdx (R0_IDX);;
2120 r = getFreePtr (ic, &aop, FALSE);
2122 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);
2150 emitcode ("push", "psw");
2153 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2158 freeAsmop (NULL, aop, ic, TRUE);
2167 /*-----------------------------------------------------------------*/
2168 /* genCall - generates a call statement */
2169 /*-----------------------------------------------------------------*/
2171 genCall (iCode * ic)
2174 bool restoreBank = FALSE;
2175 bool swapBanks = FALSE;
2177 D (emitcode (";", "genCall "););
2179 /* if we are calling a not _naked function that is not using
2180 the same register bank then we need to save the
2181 destination registers on the stack */
2182 detype = getSpec (operandType (IC_LEFT (ic)));
2183 if (detype && !SPEC_NAKED(detype) &&
2184 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2185 IS_ISR (currFunc->etype))
2189 /* This is unexpected; the bank should have been saved in
2192 saveRBank (SPEC_BANK (detype), ic, FALSE);
2198 /* if caller saves & we have not saved then */
2202 /* if send set is not empty the assign */
2203 /* We've saved all the registers we care about;
2204 * therefore, we may clobber any register not used
2205 * in the calling convention (i.e. anything not in
2212 for (sic = setFirstItem (_G.sendSet); sic;
2213 sic = setNextItem (_G.sendSet))
2215 int size, offset = 0;
2217 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2218 size = AOP_SIZE (IC_LEFT (sic));
2220 _startLazyDPSEvaluation ();
2223 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2224 FALSE, FALSE, TRUE);
2225 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2227 emitcode("mov", "%s,%s", regs390[offset].name, l);
2229 else if (strcmp (l, fReturn[offset]))
2231 emitcode ("mov", "%s,%s",
2237 _endLazyDPSEvaluation ();
2238 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2240 size = AOP_SIZE (IC_LEFT (sic));
2248 emitcode("mov", "%s,%s",
2249 fReturn[size], regs390[size].name);
2252 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2259 emitcode ("mov", "psw,#0x%02x",
2260 ((SPEC_BANK(detype)) << 3) & 0xff);
2264 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2265 OP_SYMBOL (IC_LEFT (ic))->rname :
2266 OP_SYMBOL (IC_LEFT (ic))->name));
2270 emitcode ("mov", "psw,#0x%02x",
2271 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
2274 /* if we need assign a result value */
2275 if ((IS_ITEMP (IC_RESULT (ic)) &&
2276 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2277 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2278 IS_TRUE_SYMOP (IC_RESULT (ic)))
2280 if (isOperandInFarSpace (IC_RESULT (ic))
2281 && getSize (operandType (IC_RESULT (ic))) <= 2)
2283 int size = getSize (operandType (IC_RESULT (ic)));
2285 /* Special case for 1 or 2 byte return in far space. */
2289 emitcode ("mov", "b,%s", fReturn[1]);
2292 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2293 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2297 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2304 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2307 assignResultValue (IC_RESULT (ic));
2309 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2313 /* adjust the stack for parameters if
2318 if (ic->parmBytes > 3)
2320 emitcode ("mov", "a,%s", spname);
2321 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2322 emitcode ("mov", "%s,a", spname);
2325 for (i = 0; i < ic->parmBytes; i++)
2326 emitcode ("dec", "%s", spname);
2329 /* if we hade saved some registers then unsave them */
2330 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2331 unsaveRegisters (ic);
2333 /* if register bank was saved then pop them */
2335 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
2338 /*-----------------------------------------------------------------*/
2339 /* genPcall - generates a call by pointer statement */
2340 /*-----------------------------------------------------------------*/
2342 genPcall (iCode * ic)
2345 symbol *rlbl = newiTempLabel (NULL);
2347 D (emitcode (";", "genPcall ");
2351 /* if caller saves & we have not saved then */
2355 /* if we are calling a function that is not using
2356 the same register bank then we need to save the
2357 destination registers on the stack */
2358 detype = getSpec (operandType (IC_LEFT (ic)));
2360 IS_ISR (currFunc->etype) &&
2361 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2362 saveRBank (SPEC_BANK (detype), ic, TRUE);
2365 /* push the return address on to the stack */
2366 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2367 emitcode ("push", "acc");
2368 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2369 emitcode ("push", "acc");
2371 if (options.model == MODEL_FLAT24)
2373 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2374 emitcode ("push", "acc");
2377 /* now push the calling address */
2378 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2380 pushSide (IC_LEFT (ic), FPTRSIZE);
2382 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2384 /* if send set is not empty the assign */
2389 for (sic = setFirstItem (_G.sendSet); sic;
2390 sic = setNextItem (_G.sendSet))
2392 int size, offset = 0;
2394 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2395 size = AOP_SIZE (IC_LEFT (sic));
2396 _startLazyDPSEvaluation ();
2399 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2400 FALSE, FALSE, TRUE);
2401 if (strcmp (l, fReturn[offset]))
2403 emitcode ("mov", "%s,%s",
2409 _endLazyDPSEvaluation ();
2410 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2415 emitcode ("ret", "");
2416 emitcode ("", "%05d$:", (rlbl->key + 100));
2419 /* if we need assign a result value */
2420 if ((IS_ITEMP (IC_RESULT (ic)) &&
2421 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2422 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2423 IS_TRUE_SYMOP (IC_RESULT (ic)))
2427 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2430 assignResultValue (IC_RESULT (ic));
2432 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2435 /* adjust the stack for parameters if
2440 if (ic->parmBytes > 3)
2442 emitcode ("mov", "a,%s", spname);
2443 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2444 emitcode ("mov", "%s,a", spname);
2447 for (i = 0; i < ic->parmBytes; i++)
2448 emitcode ("dec", "%s", spname);
2452 /* if register bank was saved then unsave them */
2454 (SPEC_BANK (currFunc->etype) !=
2455 SPEC_BANK (detype)))
2456 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2458 /* if we hade saved some registers then
2461 unsaveRegisters (ic);
2465 /*-----------------------------------------------------------------*/
2466 /* resultRemat - result is rematerializable */
2467 /*-----------------------------------------------------------------*/
2469 resultRemat (iCode * ic)
2471 if (SKIP_IC (ic) || ic->op == IFX)
2474 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2476 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2477 if (sym->remat && !POINTER_SET (ic))
2484 #if defined(__BORLANDC__) || defined(_MSC_VER)
2485 #define STRCASECMP stricmp
2487 #define STRCASECMP strcasecmp
2490 /*-----------------------------------------------------------------*/
2491 /* inExcludeList - return 1 if the string is in exclude Reg list */
2492 /*-----------------------------------------------------------------*/
2494 inExcludeList (char *s)
2498 if (options.excludeRegs[i] &&
2499 STRCASECMP (options.excludeRegs[i], "none") == 0)
2502 for (i = 0; options.excludeRegs[i]; i++)
2504 if (options.excludeRegs[i] &&
2505 STRCASECMP (s, options.excludeRegs[i]) == 0)
2511 /*-----------------------------------------------------------------*/
2512 /* genFunction - generated code for function entry */
2513 /*-----------------------------------------------------------------*/
2515 genFunction (iCode * ic)
2519 bool switchedPSW = FALSE;
2521 D (emitcode (";", "genFunction "););
2524 /* create the function header */
2525 emitcode (";", "-----------------------------------------");
2526 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2527 emitcode (";", "-----------------------------------------");
2529 emitcode ("", "%s:", sym->rname);
2530 fetype = getSpec (operandType (IC_LEFT (ic)));
2532 if (SPEC_NAKED(fetype))
2534 emitcode(";", "naked function: no prologue.");
2538 /* if critical function then turn interrupts off */
2539 if (SPEC_CRTCL (fetype))
2540 emitcode ("clr", "ea");
2542 /* here we need to generate the equates for the
2543 register bank if required */
2544 if (SPEC_BANK (fetype) != rbank)
2548 rbank = SPEC_BANK (fetype);
2549 for (i = 0; i < ds390_nRegs; i++)
2551 if (strcmp (regs390[i].base, "0") == 0)
2552 emitcode ("", "%s = 0x%02x",
2554 8 * rbank + regs390[i].offset);
2556 emitcode ("", "%s = %s + 0x%02x",
2559 8 * rbank + regs390[i].offset);
2563 /* if this is an interrupt service routine then
2564 save acc, b, dpl, dph */
2565 if (IS_ISR (sym->etype))
2568 if (!inExcludeList ("acc"))
2569 emitcode ("push", "acc");
2570 if (!inExcludeList ("b"))
2571 emitcode ("push", "b");
2572 if (!inExcludeList ("dpl"))
2573 emitcode ("push", "dpl");
2574 if (!inExcludeList ("dph"))
2575 emitcode ("push", "dph");
2576 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2578 emitcode ("push", "dpx");
2579 /* Make sure we're using standard DPTR */
2580 emitcode ("push", "dps");
2581 emitcode ("mov", "dps, #0x00");
2582 if (options.stack10bit)
2584 /* This ISR could conceivably use DPTR2. Better save it. */
2585 emitcode ("push", "dpl1");
2586 emitcode ("push", "dph1");
2587 emitcode ("push", "dpx1");
2588 emitcode ("push", DP2_RESULT_REG);
2591 /* if this isr has no bank i.e. is going to
2592 run with bank 0 , then we need to save more
2594 if (!SPEC_BANK (sym->etype))
2597 /* if this function does not call any other
2598 function then we can be economical and
2599 save only those registers that are used */
2604 /* if any registers used */
2607 /* save the registers used */
2608 for (i = 0; i < sym->regsUsed->size; i++)
2610 if (bitVectBitValue (sym->regsUsed, i) ||
2611 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2612 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2619 /* this function has a function call cannot
2620 determines register usage so we will have to push the
2622 saveRBank (0, ic, FALSE);
2627 /* This ISR uses a non-zero bank.
2629 * We assume that the bank is available for our
2632 * However, if this ISR calls a function which uses some
2633 * other bank, we must save that bank entirely.
2635 unsigned long banksToSave = 0;
2640 #define MAX_REGISTER_BANKS 4
2645 for (i = ic; i; i = i->next)
2647 if (i->op == ENDFUNCTION)
2649 /* we got to the end OK. */
2657 detype = getSpec(operandType (IC_LEFT(i)));
2659 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2661 /* Mark this bank for saving. */
2662 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2664 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2668 banksToSave |= (1 << SPEC_BANK(detype));
2671 /* And note that we don't need to do it in
2679 /* This is a mess; we have no idea what
2680 * register bank the called function might
2683 * The only thing I can think of to do is
2684 * throw a warning and hope.
2686 werror(W_FUNCPTR_IN_USING_ISR);
2690 if (banksToSave && options.useXstack)
2692 /* Since we aren't passing it an ic,
2693 * saveRBank will assume r0 is available to abuse.
2695 * So switch to our (trashable) bank now, so
2696 * the caller's R0 isn't trashed.
2698 emitcode ("push", "psw");
2699 emitcode ("mov", "psw,#0x%02x",
2700 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2704 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2706 if (banksToSave & (1 << ix))
2708 saveRBank(ix, NULL, FALSE);
2712 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2717 /* if callee-save to be used for this function
2718 then save the registers being used in this function */
2719 if (sym->calleeSave)
2723 /* if any registers used */
2726 /* save the registers used */
2727 for (i = 0; i < sym->regsUsed->size; i++)
2729 if (bitVectBitValue (sym->regsUsed, i) ||
2730 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2732 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2740 /* set the register bank to the desired value */
2741 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2744 emitcode ("push", "psw");
2745 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2748 if (IS_RENT (sym->etype) || options.stackAuto)
2751 if (options.useXstack)
2753 emitcode ("mov", "r0,%s", spname);
2754 emitcode ("mov", "a,_bp");
2755 emitcode ("movx", "@r0,a");
2756 emitcode ("inc", "%s", spname);
2760 /* set up the stack */
2761 emitcode ("push", "_bp"); /* save the callers stack */
2763 emitcode ("mov", "_bp,%s", spname);
2766 /* adjust the stack for the function */
2772 werror (W_STACK_OVERFLOW, sym->name);
2774 if (i > 3 && sym->recvSize < 4)
2777 emitcode ("mov", "a,sp");
2778 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2779 emitcode ("mov", "sp,a");
2784 emitcode ("inc", "sp");
2790 emitcode ("mov", "a,_spx");
2791 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2792 emitcode ("mov", "_spx,a");
2797 /*-----------------------------------------------------------------*/
2798 /* genEndFunction - generates epilogue for functions */
2799 /*-----------------------------------------------------------------*/
2801 genEndFunction (iCode * ic)
2803 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2805 D (emitcode (";", "genEndFunction "););
2807 if (SPEC_NAKED(sym->etype))
2809 emitcode(";", "naked function: no epilogue.");
2813 if (IS_RENT (sym->etype) || options.stackAuto)
2815 emitcode ("mov", "%s,_bp", spname);
2818 /* if use external stack but some variables were
2819 added to the local stack then decrement the
2821 if (options.useXstack && sym->stack)
2823 emitcode ("mov", "a,sp");
2824 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2825 emitcode ("mov", "sp,a");
2829 if ((IS_RENT (sym->etype) || options.stackAuto))
2831 if (options.useXstack)
2833 emitcode ("mov", "r0,%s", spname);
2834 emitcode ("movx", "a,@r0");
2835 emitcode ("mov", "_bp,a");
2836 emitcode ("dec", "%s", spname);
2840 emitcode ("pop", "_bp");
2844 /* restore the register bank */
2845 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2847 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2848 || !options.useXstack)
2850 /* Special case of ISR using non-zero bank with useXstack
2853 emitcode ("pop", "psw");
2857 if (IS_ISR (sym->etype))
2860 /* now we need to restore the registers */
2861 /* if this isr has no bank i.e. is going to
2862 run with bank 0 , then we need to save more
2864 if (!SPEC_BANK (sym->etype))
2866 /* if this function does not call any other
2867 function then we can be economical and
2868 save only those registers that are used */
2873 /* if any registers used */
2876 /* save the registers used */
2877 for (i = sym->regsUsed->size; i >= 0; i--)
2879 if (bitVectBitValue (sym->regsUsed, i) ||
2880 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2881 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2888 /* this function has a function call cannot
2889 determines register usage so we will have to pop the
2891 unsaveRBank (0, ic, FALSE);
2896 /* This ISR uses a non-zero bank.
2898 * Restore any register banks saved by genFunction
2901 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2904 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2906 if (savedBanks & (1 << ix))
2908 unsaveRBank(ix, NULL, FALSE);
2912 if (options.useXstack)
2914 /* Restore bank AFTER calling unsaveRBank,
2915 * since it can trash r0.
2917 emitcode ("pop", "psw");
2921 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2923 if (options.stack10bit)
2925 emitcode ("pop", DP2_RESULT_REG);
2926 emitcode ("pop", "dpx1");
2927 emitcode ("pop", "dph1");
2928 emitcode ("pop", "dpl1");
2930 emitcode ("pop", "dps");
2931 emitcode ("pop", "dpx");
2933 if (!inExcludeList ("dph"))
2934 emitcode ("pop", "dph");
2935 if (!inExcludeList ("dpl"))
2936 emitcode ("pop", "dpl");
2937 if (!inExcludeList ("b"))
2938 emitcode ("pop", "b");
2939 if (!inExcludeList ("acc"))
2940 emitcode ("pop", "acc");
2942 if (SPEC_CRTCL (sym->etype))
2943 emitcode ("setb", "ea");
2945 /* if debug then send end of function */
2946 /* if (options.debug && currFunc) */
2950 emitcode ("", "C$%s$%d$%d$%d ==.",
2951 FileBaseName (ic->filename), currFunc->lastLine,
2952 ic->level, ic->block);
2953 if (IS_STATIC (currFunc->etype))
2954 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2956 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2960 emitcode ("reti", "");
2964 if (SPEC_CRTCL (sym->etype))
2965 emitcode ("setb", "ea");
2967 if (sym->calleeSave)
2971 /* if any registers used */
2974 /* save the registers used */
2975 for (i = sym->regsUsed->size; i >= 0; i--)
2977 if (bitVectBitValue (sym->regsUsed, i) ||
2978 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2979 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2985 /* if debug then send end of function */
2989 emitcode ("", "C$%s$%d$%d$%d ==.",
2990 FileBaseName (ic->filename), currFunc->lastLine,
2991 ic->level, ic->block);
2992 if (IS_STATIC (currFunc->etype))
2993 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2995 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2999 emitcode ("ret", "");
3004 /*-----------------------------------------------------------------*/
3005 /* genRet - generate code for return statement */
3006 /*-----------------------------------------------------------------*/
3010 int size, offset = 0, pushed = 0;
3012 D (emitcode (";", "genRet ");
3015 /* if we have no return value then
3016 just generate the "ret" */
3020 /* we have something to return then
3021 move the return value into place */
3022 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3023 size = AOP_SIZE (IC_LEFT (ic));
3025 _startLazyDPSEvaluation ();
3029 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3031 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3032 FALSE, TRUE, FALSE);
3033 emitcode ("push", "%s", l);
3038 /* Since A is the last element of fReturn,
3039 * is is OK to clobber it in the aopGet.
3041 l = aopGet (AOP (IC_LEFT (ic)), offset,
3042 FALSE, FALSE, TRUE);
3043 if (strcmp (fReturn[offset], l))
3044 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3047 _endLazyDPSEvaluation ();
3054 if (strcmp (fReturn[pushed], "a"))
3055 emitcode ("pop", fReturn[pushed]);
3057 emitcode ("pop", "acc");
3060 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3063 /* generate a jump to the return label
3064 if the next is not the return statement */
3065 if (!(ic->next && ic->next->op == LABEL &&
3066 IC_LABEL (ic->next) == returnLabel))
3068 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3072 /*-----------------------------------------------------------------*/
3073 /* genLabel - generates a label */
3074 /*-----------------------------------------------------------------*/
3076 genLabel (iCode * ic)
3078 /* special case never generate */
3079 if (IC_LABEL (ic) == entryLabel)
3082 D (emitcode (";", "genLabel ");
3085 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3088 /*-----------------------------------------------------------------*/
3089 /* genGoto - generates a ljmp */
3090 /*-----------------------------------------------------------------*/
3092 genGoto (iCode * ic)
3094 D (emitcode (";", "genGoto ");
3096 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3099 /*-----------------------------------------------------------------*/
3100 /* findLabelBackwards: walks back through the iCode chain looking */
3101 /* for the given label. Returns number of iCode instructions */
3102 /* between that label and given ic. */
3103 /* Returns zero if label not found. */
3104 /*-----------------------------------------------------------------*/
3106 findLabelBackwards (iCode * ic, int key)
3115 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3117 /* printf("findLabelBackwards = %d\n", count); */
3125 /*-----------------------------------------------------------------*/
3126 /* genPlusIncr :- does addition with increment if possible */
3127 /*-----------------------------------------------------------------*/
3129 genPlusIncr (iCode * ic)
3131 unsigned int icount;
3132 unsigned int size = getDataSize (IC_RESULT (ic));
3134 /* will try to generate an increment */
3135 /* if the right side is not a literal
3137 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3140 /* if the literal value of the right hand side
3141 is greater than 4 then it is not worth it */
3142 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3145 /* if increment 16 bits in register */
3147 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3148 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3149 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3157 /* If the next instruction is a goto and the goto target
3158 * is <= 5 instructions previous to this, we can generate
3159 * jumps straight to that target.
3161 if (ic->next && ic->next->op == GOTO
3162 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3165 emitcode (";", "tail increment optimized (range %d)", labelRange);
3166 tlbl = IC_LABEL (ic->next);
3171 tlbl = newiTempLabel (NULL);
3174 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3175 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3176 IS_AOP_PREG (IC_RESULT (ic)))
3177 emitcode ("cjne", "%s,#0x00,%05d$"
3178 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3182 emitcode ("clr", "a");
3183 emitcode ("cjne", "a,%s,%05d$"
3184 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3188 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3191 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3192 IS_AOP_PREG (IC_RESULT (ic)))
3193 emitcode ("cjne", "%s,#0x00,%05d$"
3194 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3197 emitcode ("cjne", "a,%s,%05d$"
3198 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3201 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3205 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3206 IS_AOP_PREG (IC_RESULT (ic)))
3207 emitcode ("cjne", "%s,#0x00,%05d$"
3208 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3212 emitcode ("cjne", "a,%s,%05d$"
3213 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3216 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3221 emitcode ("", "%05d$:", tlbl->key + 100);
3226 /* if the sizes are greater than 1 then we cannot */
3227 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3228 AOP_SIZE (IC_LEFT (ic)) > 1)
3231 /* we can if the aops of the left & result match or
3232 if they are in registers and the registers are the
3235 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3236 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3237 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3242 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3243 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3244 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3249 _startLazyDPSEvaluation ();
3252 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3254 _endLazyDPSEvaluation ();
3263 /*-----------------------------------------------------------------*/
3264 /* outBitAcc - output a bit in acc */
3265 /*-----------------------------------------------------------------*/
3267 outBitAcc (operand * result)
3269 symbol *tlbl = newiTempLabel (NULL);
3270 /* if the result is a bit */
3271 if (AOP_TYPE (result) == AOP_CRY)
3273 aopPut (AOP (result), "a", 0);
3277 emitcode ("jz", "%05d$", tlbl->key + 100);
3278 emitcode ("mov", "a,%s", one);
3279 emitcode ("", "%05d$:", tlbl->key + 100);
3284 /*-----------------------------------------------------------------*/
3285 /* genPlusBits - generates code for addition of two bits */
3286 /*-----------------------------------------------------------------*/
3288 genPlusBits (iCode * ic)
3290 D (emitcode (";", "genPlusBits ");
3292 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3294 symbol *lbl = newiTempLabel (NULL);
3295 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3296 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3297 emitcode ("cpl", "c");
3298 emitcode ("", "%05d$:", (lbl->key + 100));
3299 outBitC (IC_RESULT (ic));
3303 emitcode ("clr", "a");
3304 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3305 emitcode ("rlc", "a");
3306 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3307 emitcode ("addc", "a,#0x00");
3308 outAcc (IC_RESULT (ic));
3313 adjustArithmeticResult (iCode * ic)
3315 if (opIsGptr (IC_RESULT (ic)) &&
3316 opIsGptr (IC_LEFT (ic)) &&
3317 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3319 aopPut (AOP (IC_RESULT (ic)),
3320 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3324 if (opIsGptr (IC_RESULT (ic)) &&
3325 opIsGptr (IC_RIGHT (ic)) &&
3326 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3328 aopPut (AOP (IC_RESULT (ic)),
3329 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3333 if (opIsGptr (IC_RESULT (ic)) &&
3334 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3335 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3336 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3337 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3340 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3341 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3345 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3346 // (because all three operands are in far space).
3347 #define AOP_OP_3(ic) \
3348 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3349 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3350 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3351 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3352 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3353 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3355 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3357 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3360 // Macro to aopOp all three operands of an ic. If this cannot be done,
3361 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3362 // will be set TRUE. The caller must then handle the case specially, noting
3363 // that the IC_RESULT operand is not aopOp'd.
3364 #define AOP_OP_3_NOFATAL(ic, rc) \
3365 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3366 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3367 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3368 isOperandInFarSpace(IC_RESULT(ic))) \
3370 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3375 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3376 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3378 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3379 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3381 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3383 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3387 // aopOp the left & right operands of an ic.
3388 #define AOP_OP_2(ic) \
3389 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3390 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3392 // convienience macro.
3393 #define AOP_SET_LOCALS(ic) \
3394 left = IC_LEFT(ic); \
3395 right = IC_RIGHT(ic); \
3396 result = IC_RESULT(ic);
3399 // Given an integer value of pushedSize bytes on the stack,
3400 // adjust it to be resultSize bytes, either by discarding
3401 // the most significant bytes or by zero-padding.
3403 // On exit from this macro, pushedSize will have been adjusted to
3404 // equal resultSize, and ACC may be trashed.
3405 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3406 /* If the pushed data is bigger than the result, \
3407 * simply discard unused bytes. Icky, but works. \
3409 while (pushedSize > resultSize) \
3411 D (emitcode (";", "discarding unused result byte."););\
3412 emitcode ("pop", "acc"); \
3415 if (pushedSize < resultSize) \
3417 emitcode ("clr", "a"); \
3418 /* Conversly, we haven't pushed enough here. \
3419 * just zero-pad, and all is well. \
3421 while (pushedSize < resultSize) \
3423 emitcode("push", "acc"); \
3427 assert(pushedSize == resultSize);
3429 /*-----------------------------------------------------------------*/
3430 /* genPlus - generates code for addition */
3431 /*-----------------------------------------------------------------*/
3433 genPlus (iCode * ic)
3435 int size, offset = 0;
3436 bool pushResult = FALSE;
3439 D (emitcode (";", "genPlus "););
3441 /* special cases :- */
3443 AOP_OP_3_NOFATAL (ic, pushResult);
3446 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3451 /* if literal, literal on the right or
3452 if left requires ACC or right is already
3454 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3455 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3456 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3458 operand *t = IC_RIGHT (ic);
3459 IC_RIGHT (ic) = IC_LEFT (ic);
3461 emitcode (";", "Swapped plus args.");
3464 /* if both left & right are in bit
3466 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3467 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3473 /* if left in bit space & right literal */
3474 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3475 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3477 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3478 /* if result in bit space */
3479 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3481 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3482 emitcode ("cpl", "c");
3483 outBitC (IC_RESULT (ic));
3487 size = getDataSize (IC_RESULT (ic));
3488 _startLazyDPSEvaluation ();
3491 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3492 emitcode ("addc", "a,#00");
3493 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3495 _endLazyDPSEvaluation ();
3500 /* if I can do an increment instead
3501 of add then GOOD for ME */
3502 if (genPlusIncr (ic) == TRUE)
3504 emitcode (";", "did genPlusIncr");
3509 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3511 _startLazyDPSEvaluation ();
3514 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3516 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3518 emitcode ("add", "a,%s",
3519 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3521 emitcode ("addc", "a,%s",
3522 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3526 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3528 /* right is going to use ACC or we would have taken the
3531 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3532 D(emitcode(";", "+ AOP_ACC special case."););
3533 emitcode("xch", "a, %s", DP2_RESULT_REG);
3535 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3538 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3540 emitcode("add", "a, %s", DP2_RESULT_REG);
3544 emitcode ("add", "a,%s",
3545 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3550 emitcode ("addc", "a,%s",
3551 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3556 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3560 emitcode ("push", "acc");
3564 _endLazyDPSEvaluation ();
3568 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3570 size = getDataSize (IC_LEFT (ic));
3571 rSize = getDataSize (IC_RESULT (ic));
3573 ADJUST_PUSHED_RESULT(size, rSize);
3575 _startLazyDPSEvaluation ();
3578 emitcode ("pop", "acc");
3579 aopPut (AOP (IC_RESULT (ic)), "a", size);
3581 _endLazyDPSEvaluation ();
3584 adjustArithmeticResult (ic);
3587 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3588 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3592 /*-----------------------------------------------------------------*/
3593 /* genMinusDec :- does subtraction with deccrement if possible */
3594 /*-----------------------------------------------------------------*/
3596 genMinusDec (iCode * ic)
3598 unsigned int icount;
3599 unsigned int size = getDataSize (IC_RESULT (ic));
3601 /* will try to generate an increment */
3602 /* if the right side is not a literal
3604 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3607 /* if the literal value of the right hand side
3608 is greater than 4 then it is not worth it */
3609 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3612 /* if decrement 16 bits in register */
3613 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3614 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3615 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3623 /* If the next instruction is a goto and the goto target
3624 * is <= 5 instructions previous to this, we can generate
3625 * jumps straight to that target.
3627 if (ic->next && ic->next->op == GOTO
3628 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3631 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3632 tlbl = IC_LABEL (ic->next);
3637 tlbl = newiTempLabel (NULL);
3641 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3642 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3643 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3644 IS_AOP_PREG (IC_RESULT (ic)))
3645 emitcode ("cjne", "%s,#0xff,%05d$"
3646 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3650 emitcode ("mov", "a,#0xff");
3651 emitcode ("cjne", "a,%s,%05d$"
3652 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3655 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3658 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3659 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3660 IS_AOP_PREG (IC_RESULT (ic)))
3661 emitcode ("cjne", "%s,#0xff,%05d$"
3662 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3666 emitcode ("cjne", "a,%s,%05d$"
3667 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3670 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3674 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3676 IS_AOP_PREG (IC_RESULT (ic)))
3677 emitcode ("cjne", "%s,#0xff,%05d$"
3678 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3682 emitcode ("cjne", "a,%s,%05d$"
3683 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3686 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3690 emitcode ("", "%05d$:", tlbl->key + 100);
3695 /* if the sizes are greater than 1 then we cannot */
3696 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3697 AOP_SIZE (IC_LEFT (ic)) > 1)
3700 /* we can if the aops of the left & result match or
3701 if they are in registers and the registers are the
3704 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3705 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3706 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3709 _startLazyDPSEvaluation ();
3712 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3714 _endLazyDPSEvaluation ();
3722 /*-----------------------------------------------------------------*/
3723 /* addSign - complete with sign */
3724 /*-----------------------------------------------------------------*/
3726 addSign (operand * result, int offset, int sign)
3728 int size = (getDataSize (result) - offset);
3731 _startLazyDPSEvaluation();
3734 emitcode ("rlc", "a");
3735 emitcode ("subb", "a,acc");
3738 aopPut (AOP (result), "a", offset++);
3745 aopPut (AOP (result), zero, offset++);
3748 _endLazyDPSEvaluation();
3752 /*-----------------------------------------------------------------*/
3753 /* genMinusBits - generates code for subtraction of two bits */
3754 /*-----------------------------------------------------------------*/
3756 genMinusBits (iCode * ic)
3758 symbol *lbl = newiTempLabel (NULL);
3760 D (emitcode (";", "genMinusBits "););
3762 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3764 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3765 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3766 emitcode ("cpl", "c");
3767 emitcode ("", "%05d$:", (lbl->key + 100));
3768 outBitC (IC_RESULT (ic));
3772 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3773 emitcode ("subb", "a,acc");
3774 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3775 emitcode ("inc", "a");
3776 emitcode ("", "%05d$:", (lbl->key + 100));
3777 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3778 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3782 /*-----------------------------------------------------------------*/
3783 /* genMinus - generates code for subtraction */
3784 /*-----------------------------------------------------------------*/
3786 genMinus (iCode * ic)
3788 int size, offset = 0;
3790 unsigned long lit = 0L;
3791 bool pushResult = FALSE;
3793 D (emitcode (";", "genMinus "););
3795 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3796 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3797 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3798 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3804 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3806 /* special cases :- */
3807 /* if both left & right are in bit space */
3808 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3809 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3815 /* if I can do an decrement instead
3816 of subtract then GOOD for ME */
3817 if (genMinusDec (ic) == TRUE)
3822 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3824 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3830 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3835 /* if literal, add a,#-lit, else normal subb */
3836 _startLazyDPSEvaluation ();
3839 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3840 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3841 emitcode ("subb", "a,%s",
3842 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3845 /* first add without previous c */
3847 emitcode ("add", "a,#0x%02x",
3848 (unsigned int) (lit & 0x0FFL));
3850 emitcode ("addc", "a,#0x%02x",
3851 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3856 emitcode ("push", "acc");
3860 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3864 _endLazyDPSEvaluation ();
3868 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3870 size = getDataSize (IC_LEFT (ic));
3871 rSize = getDataSize (IC_RESULT (ic));
3873 ADJUST_PUSHED_RESULT(size, rSize);
3875 _startLazyDPSEvaluation ();
3878 emitcode ("pop", "acc");
3879 aopPut (AOP (IC_RESULT (ic)), "a", size);
3881 _endLazyDPSEvaluation ();
3884 adjustArithmeticResult (ic);
3887 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3888 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3889 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3893 /*-----------------------------------------------------------------*/
3894 /* genMultbits :- multiplication of bits */
3895 /*-----------------------------------------------------------------*/
3897 genMultbits (operand * left,
3901 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3902 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3907 /*-----------------------------------------------------------------*/
3908 /* genMultOneByte : 8*8=8/16 bit multiplication */
3909 /*-----------------------------------------------------------------*/
3911 genMultOneByte (operand * left,
3915 sym_link *opetype = operandType (result);
3917 int size=AOP_SIZE(result);
3919 if (size<1 || size>2) {
3920 // this should never happen
3921 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3922 AOP_SIZE(result), __FILE__, lineno);
3926 /* (if two literals: the value is computed before) */
3927 /* if one literal, literal on the right */
3928 if (AOP_TYPE (left) == AOP_LIT)
3933 emitcode (";", "swapped left and right");
3936 if (SPEC_USIGN(opetype)
3937 // ignore the sign of left and right, what else can we do?
3938 || (SPEC_USIGN(operandType(left)) &&
3939 SPEC_USIGN(operandType(right)))) {
3940 // just an unsigned 8*8=8/16 multiply
3941 //emitcode (";","unsigned");
3942 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3943 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3944 emitcode ("mul", "ab");
3945 aopPut (AOP (result), "a", 0);
3947 aopPut (AOP (result), "b", 1);
3952 // we have to do a signed multiply
3954 emitcode (";", "signed");
3955 emitcode ("clr", "F0"); // reset sign flag
3956 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3958 lbl=newiTempLabel(NULL);
3959 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3960 // left side is negative, 8-bit two's complement, this fails for -128
3961 emitcode ("setb", "F0"); // set sign flag
3962 emitcode ("cpl", "a");
3963 emitcode ("inc", "a");
3965 emitcode ("", "%05d$:", lbl->key+100);
3968 if (AOP_TYPE(right)==AOP_LIT) {
3969 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3970 /* AND literal negative */
3971 if ((int) val < 0) {
3972 emitcode ("cpl", "F0"); // complement sign flag
3973 emitcode ("mov", "b,#0x%02x", -val);
3975 emitcode ("mov", "b,#0x%02x", val);
3978 lbl=newiTempLabel(NULL);
3979 emitcode ("mov", "b,a");
3980 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3981 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3982 // right side is negative, 8-bit two's complement
3983 emitcode ("cpl", "F0"); // complement sign flag
3984 emitcode ("cpl", "a");
3985 emitcode ("inc", "a");
3986 emitcode ("", "%05d$:", lbl->key+100);
3988 emitcode ("mul", "ab");
3990 lbl=newiTempLabel(NULL);
3991 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3992 // only ONE op was negative, we have to do a 8/16-bit two's complement
3993 emitcode ("cpl", "a"); // lsb
3995 emitcode ("inc", "a");
3997 emitcode ("add", "a,#1");
3998 emitcode ("xch", "a,b");
3999 emitcode ("cpl", "a"); // msb
4000 emitcode ("addc", "a,#0");
4001 emitcode ("xch", "a,b");
4004 emitcode ("", "%05d$:", lbl->key+100);
4005 aopPut (AOP (result), "a", 0);
4007 aopPut (AOP (result), "b", 1);
4011 /*-----------------------------------------------------------------*/
4012 /* genMult - generates code for multiplication */
4013 /*-----------------------------------------------------------------*/
4015 genMult (iCode * ic)
4017 operand *left = IC_LEFT (ic);
4018 operand *right = IC_RIGHT (ic);
4019 operand *result = IC_RESULT (ic);
4021 D (emitcode (";", "genMult "););
4023 /* assign the amsops */
4026 /* special cases first */
4028 if (AOP_TYPE (left) == AOP_CRY &&
4029 AOP_TYPE (right) == AOP_CRY)
4031 genMultbits (left, right, result);
4035 /* if both are of size == 1 */
4036 if (AOP_SIZE (left) == 1 &&
4037 AOP_SIZE (right) == 1)
4039 genMultOneByte (left, right, result);
4043 /* should have been converted to function call */
4047 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4048 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4049 freeAsmop (result, NULL, ic, TRUE);
4052 /*-----------------------------------------------------------------*/
4053 /* genDivbits :- division of bits */
4054 /*-----------------------------------------------------------------*/
4056 genDivbits (operand * left,
4063 /* the result must be bit */
4064 LOAD_AB_FOR_DIV (left, right, l);
4065 emitcode ("div", "ab");
4066 emitcode ("rrc", "a");
4067 aopPut (AOP (result), "c", 0);
4070 /*-----------------------------------------------------------------*/
4071 /* genDivOneByte : 8 bit division */
4072 /*-----------------------------------------------------------------*/
4074 genDivOneByte (operand * left,
4078 sym_link *opetype = operandType (result);
4083 size = AOP_SIZE (result) - 1;
4085 /* signed or unsigned */
4086 if (SPEC_USIGN (opetype))
4088 /* unsigned is easy */
4089 LOAD_AB_FOR_DIV (left, right, l);
4090 emitcode ("div", "ab");
4091 aopPut (AOP (result), "a", 0);
4093 aopPut (AOP (result), zero, offset++);
4097 /* signed is a little bit more difficult */
4099 /* save the signs of the operands */
4100 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4102 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4103 emitcode ("push", "acc"); /* save it on the stack */
4105 /* now sign adjust for both left & right */
4106 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4108 lbl = newiTempLabel (NULL);
4109 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4110 emitcode ("cpl", "a");
4111 emitcode ("inc", "a");
4112 emitcode ("", "%05d$:", (lbl->key + 100));
4113 emitcode ("mov", "b,a");
4115 /* sign adjust left side */
4116 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4119 lbl = newiTempLabel (NULL);
4120 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4121 emitcode ("cpl", "a");
4122 emitcode ("inc", "a");
4123 emitcode ("", "%05d$:", (lbl->key + 100));
4125 /* now the division */
4126 emitcode ("nop", "; workaround for DS80C390 div bug.");
4127 emitcode ("div", "ab");
4128 /* we are interested in the lower order
4130 emitcode ("mov", "b,a");
4131 lbl = newiTempLabel (NULL);
4132 emitcode ("pop", "acc");
4133 /* if there was an over flow we don't
4134 adjust the sign of the result */
4135 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4136 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4138 emitcode ("clr", "a");
4139 emitcode ("subb", "a,b");
4140 emitcode ("mov", "b,a");
4141 emitcode ("", "%05d$:", (lbl->key + 100));
4143 /* now we are done */
4144 aopPut (AOP (result), "b", 0);
4147 emitcode ("mov", "c,b.7");
4148 emitcode ("subb", "a,acc");
4151 aopPut (AOP (result), "a", offset++);
4155 /*-----------------------------------------------------------------*/
4156 /* genDiv - generates code for division */
4157 /*-----------------------------------------------------------------*/
4161 operand *left = IC_LEFT (ic);
4162 operand *right = IC_RIGHT (ic);
4163 operand *result = IC_RESULT (ic);
4165 D (emitcode (";", "genDiv ");
4168 /* assign the amsops */
4171 /* special cases first */
4173 if (AOP_TYPE (left) == AOP_CRY &&
4174 AOP_TYPE (right) == AOP_CRY)
4176 genDivbits (left, right, result);
4180 /* if both are of size == 1 */
4181 if (AOP_SIZE (left) == 1 &&
4182 AOP_SIZE (right) == 1)
4184 genDivOneByte (left, right, result);
4188 /* should have been converted to function call */
4191 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4192 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4193 freeAsmop (result, NULL, ic, TRUE);
4196 /*-----------------------------------------------------------------*/
4197 /* genModbits :- modulus of bits */
4198 /*-----------------------------------------------------------------*/
4200 genModbits (operand * left,
4207 /* the result must be bit */
4208 LOAD_AB_FOR_DIV (left, right, l);
4209 emitcode ("div", "ab");
4210 emitcode ("mov", "a,b");
4211 emitcode ("rrc", "a");
4212 aopPut (AOP (result), "c", 0);
4215 /*-----------------------------------------------------------------*/
4216 /* genModOneByte : 8 bit modulus */
4217 /*-----------------------------------------------------------------*/
4219 genModOneByte (operand * left,
4223 sym_link *opetype = operandType (result);
4227 /* signed or unsigned */
4228 if (SPEC_USIGN (opetype))
4230 /* unsigned is easy */
4231 LOAD_AB_FOR_DIV (left, right, l);
4232 emitcode ("div", "ab");
4233 aopPut (AOP (result), "b", 0);
4237 /* signed is a little bit more difficult */
4239 /* save the signs of the operands */
4240 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4243 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4244 emitcode ("push", "acc"); /* save it on the stack */
4246 /* now sign adjust for both left & right */
4247 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4250 lbl = newiTempLabel (NULL);
4251 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4252 emitcode ("cpl", "a");
4253 emitcode ("inc", "a");
4254 emitcode ("", "%05d$:", (lbl->key + 100));
4255 emitcode ("mov", "b,a");
4257 /* sign adjust left side */
4258 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4261 lbl = newiTempLabel (NULL);
4262 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4263 emitcode ("cpl", "a");
4264 emitcode ("inc", "a");
4265 emitcode ("", "%05d$:", (lbl->key + 100));
4267 /* now the multiplication */
4268 emitcode ("nop", "; workaround for DS80C390 div bug.");
4269 emitcode ("div", "ab");
4270 /* we are interested in the lower order
4272 lbl = newiTempLabel (NULL);
4273 emitcode ("pop", "acc");
4274 /* if there was an over flow we don't
4275 adjust the sign of the result */
4276 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4277 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4279 emitcode ("clr", "a");
4280 emitcode ("subb", "a,b");
4281 emitcode ("mov", "b,a");
4282 emitcode ("", "%05d$:", (lbl->key + 100));
4284 /* now we are done */
4285 aopPut (AOP (result), "b", 0);
4289 /*-----------------------------------------------------------------*/
4290 /* genMod - generates code for division */
4291 /*-----------------------------------------------------------------*/
4295 operand *left = IC_LEFT (ic);
4296 operand *right = IC_RIGHT (ic);
4297 operand *result = IC_RESULT (ic);
4299 D (emitcode (";", "genMod ");
4302 /* assign the amsops */
4305 /* special cases first */
4307 if (AOP_TYPE (left) == AOP_CRY &&
4308 AOP_TYPE (right) == AOP_CRY)
4310 genModbits (left, right, result);
4314 /* if both are of size == 1 */
4315 if (AOP_SIZE (left) == 1 &&
4316 AOP_SIZE (right) == 1)
4318 genModOneByte (left, right, result);
4322 /* should have been converted to function call */
4326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4327 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4328 freeAsmop (result, NULL, ic, TRUE);
4331 /*-----------------------------------------------------------------*/
4332 /* genIfxJump :- will create a jump depending on the ifx */
4333 /*-----------------------------------------------------------------*/
4335 genIfxJump (iCode * ic, char *jval)
4338 symbol *tlbl = newiTempLabel (NULL);
4341 D (emitcode (";", "genIfxJump ");
4344 /* if true label then we jump if condition
4348 jlbl = IC_TRUE (ic);
4349 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4350 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4354 /* false label is present */
4355 jlbl = IC_FALSE (ic);
4356 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4357 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4359 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4360 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4362 emitcode (inst, "%05d$", tlbl->key + 100);
4363 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4364 emitcode ("", "%05d$:", tlbl->key + 100);
4366 /* mark the icode as generated */
4370 /*-----------------------------------------------------------------*/
4371 /* genCmp :- greater or less than comparison */
4372 /*-----------------------------------------------------------------*/
4374 genCmp (operand * left, operand * right,
4375 iCode * ic, iCode * ifx, int sign)
4377 int size, offset = 0;
4378 unsigned long lit = 0L;
4381 D (emitcode (";", "genCmp");
4384 result = IC_RESULT (ic);
4386 /* if left & right are bit variables */
4387 if (AOP_TYPE (left) == AOP_CRY &&
4388 AOP_TYPE (right) == AOP_CRY)
4390 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4391 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4395 /* subtract right from left if at the
4396 end the carry flag is set then we know that
4397 left is greater than right */
4398 size = max (AOP_SIZE (left), AOP_SIZE (right));
4400 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4401 if ((size == 1) && !sign &&
4402 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4404 symbol *lbl = newiTempLabel (NULL);
4405 emitcode ("cjne", "%s,%s,%05d$",
4406 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4407 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4409 emitcode ("", "%05d$:", lbl->key + 100);
4413 if (AOP_TYPE (right) == AOP_LIT)
4415 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4416 /* optimize if(x < 0) or if(x >= 0) */
4425 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4427 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4430 aopOp (result, ic, FALSE, FALSE);
4432 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4434 freeAsmop (result, NULL, ic, TRUE);
4435 genIfxJump (ifx, "acc.7");
4440 emitcode ("rlc", "a");
4442 goto release_freedLR;
4450 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4451 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4452 emitcode (";", "genCmp #2");
4453 if (sign && (size == 0))
4455 emitcode (";", "genCmp #3");
4456 emitcode ("xrl", "a,#0x80");
4457 if (AOP_TYPE (right) == AOP_LIT)
4459 unsigned long lit = (unsigned long)
4460 floatFromVal (AOP (right)->aopu.aop_lit);
4461 emitcode (";", "genCmp #3.1");
4462 emitcode ("subb", "a,#0x%02x",
4463 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4467 emitcode (";", "genCmp #3.2");
4468 if (AOP_NEEDSACC (right))
4470 emitcode ("push", "acc");
4472 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4473 FALSE, FALSE, FALSE));
4474 emitcode ("xrl", "b,#0x80");
4475 if (AOP_NEEDSACC (right))
4477 emitcode ("pop", "acc");
4479 emitcode ("subb", "a,b");
4486 emitcode (";", "genCmp #4");
4487 if (AOP_NEEDSACC (right))
4490 emitcode (";", "genCmp #4.1");
4491 emitcode ("xch", "a, b");
4492 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4493 emitcode ("xch", "a, b");
4498 emitcode (";", "genCmp #4.2");
4499 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4502 emitcode ("subb", "a,%s", s);
4509 /* Don't need the left & right operands any more; do need the result. */
4510 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4511 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4513 aopOp (result, ic, FALSE, FALSE);
4517 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4523 /* if the result is used in the next
4524 ifx conditional branch then generate
4525 code a little differently */
4528 genIfxJump (ifx, "c");
4534 /* leave the result in acc */
4536 freeAsmop (result, NULL, ic, TRUE);
4539 /*-----------------------------------------------------------------*/
4540 /* genCmpGt :- greater than comparison */
4541 /*-----------------------------------------------------------------*/
4543 genCmpGt (iCode * ic, iCode * ifx)
4545 operand *left, *right;
4546 sym_link *letype, *retype;
4549 D (emitcode (";", "genCmpGt ");
4552 left = IC_LEFT (ic);
4553 right = IC_RIGHT (ic);
4555 letype = getSpec (operandType (left));
4556 retype = getSpec (operandType (right));
4557 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4559 /* assign the left & right amsops */
4562 genCmp (right, left, ic, ifx, sign);
4565 /*-----------------------------------------------------------------*/
4566 /* genCmpLt - less than comparisons */
4567 /*-----------------------------------------------------------------*/
4569 genCmpLt (iCode * ic, iCode * ifx)
4571 operand *left, *right;
4572 sym_link *letype, *retype;
4575 D (emitcode (";", "genCmpLt "););
4577 left = IC_LEFT (ic);
4578 right = IC_RIGHT (ic);
4580 letype = getSpec (operandType (left));
4581 retype = getSpec (operandType (right));
4582 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4584 /* assign the left & right amsops */
4587 genCmp (left, right, ic, ifx, sign);
4590 /*-----------------------------------------------------------------*/
4591 /* gencjneshort - compare and jump if not equal */
4592 /*-----------------------------------------------------------------*/
4594 gencjneshort (operand * left, operand * right, symbol * lbl)
4596 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4598 unsigned long lit = 0L;
4600 D (emitcode (";", "gencjneshort");
4603 /* if the left side is a literal or
4604 if the right is in a pointer register and left
4606 if ((AOP_TYPE (left) == AOP_LIT) ||
4607 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4614 if (AOP_TYPE (right) == AOP_LIT)
4615 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4617 if (opIsGptr (left) || opIsGptr (right))
4619 /* We are comparing a generic pointer to something.
4620 * Exclude the generic type byte from the comparison.
4623 D (emitcode (";", "cjneshort: generic ptr special case.");
4628 /* if the right side is a literal then anything goes */
4629 if (AOP_TYPE (right) == AOP_LIT &&
4630 AOP_TYPE (left) != AOP_DIR)
4634 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4636 emitcode ("cjne", "a,%s,%05d$",
4637 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4643 /* if the right side is in a register or in direct space or
4644 if the left is a pointer register & right is not */
4645 else if (AOP_TYPE (right) == AOP_REG ||
4646 AOP_TYPE (right) == AOP_DIR ||
4647 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4648 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4652 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4653 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4654 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4655 emitcode ("jnz", "%05d$", lbl->key + 100);
4657 emitcode ("cjne", "a,%s,%05d$",
4658 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4665 /* right is a pointer reg need both a & b */
4668 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4669 if (strcmp (l, "b"))
4670 emitcode ("mov", "b,%s", l);
4671 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4672 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4678 /*-----------------------------------------------------------------*/
4679 /* gencjne - compare and jump if not equal */
4680 /*-----------------------------------------------------------------*/
4682 gencjne (operand * left, operand * right, symbol * lbl)
4684 symbol *tlbl = newiTempLabel (NULL);
4686 D (emitcode (";", "gencjne");
4689 gencjneshort (left, right, lbl);
4691 emitcode ("mov", "a,%s", one);
4692 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4693 emitcode ("", "%05d$:", lbl->key + 100);
4694 emitcode ("clr", "a");
4695 emitcode ("", "%05d$:", tlbl->key + 100);
4698 /*-----------------------------------------------------------------*/
4699 /* genCmpEq - generates code for equal to */
4700 /*-----------------------------------------------------------------*/
4702 genCmpEq (iCode * ic, iCode * ifx)
4704 operand *left, *right, *result;
4706 D (emitcode (";", "genCmpEq ");
4710 AOP_SET_LOCALS (ic);
4712 /* if literal, literal on the right or
4713 if the right is in a pointer register and left
4715 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4716 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4718 operand *t = IC_RIGHT (ic);
4719 IC_RIGHT (ic) = IC_LEFT (ic);
4723 if (ifx && /* !AOP_SIZE(result) */
4724 OP_SYMBOL (result) &&
4725 OP_SYMBOL (result)->regType == REG_CND)
4728 /* if they are both bit variables */
4729 if (AOP_TYPE (left) == AOP_CRY &&
4730 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4732 if (AOP_TYPE (right) == AOP_LIT)
4734 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4737 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4738 emitcode ("cpl", "c");
4742 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4746 emitcode ("clr", "c");
4748 /* AOP_TYPE(right) == AOP_CRY */
4752 symbol *lbl = newiTempLabel (NULL);
4753 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4754 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4755 emitcode ("cpl", "c");
4756 emitcode ("", "%05d$:", (lbl->key + 100));
4758 /* if true label then we jump if condition
4760 tlbl = newiTempLabel (NULL);
4763 emitcode ("jnc", "%05d$", tlbl->key + 100);
4764 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4768 emitcode ("jc", "%05d$", tlbl->key + 100);
4769 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4771 emitcode ("", "%05d$:", tlbl->key + 100);
4775 tlbl = newiTempLabel (NULL);
4776 gencjneshort (left, right, tlbl);
4779 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4780 emitcode ("", "%05d$:", tlbl->key + 100);
4784 symbol *lbl = newiTempLabel (NULL);
4785 emitcode ("sjmp", "%05d$", lbl->key + 100);
4786 emitcode ("", "%05d$:", tlbl->key + 100);
4787 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4788 emitcode ("", "%05d$:", lbl->key + 100);
4791 /* mark the icode as generated */
4794 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4799 /* if they are both bit variables */
4800 if (AOP_TYPE (left) == AOP_CRY &&
4801 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4803 if (AOP_TYPE (right) == AOP_LIT)
4805 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4808 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4809 emitcode ("cpl", "c");
4813 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4817 emitcode ("clr", "c");
4819 /* AOP_TYPE(right) == AOP_CRY */
4823 symbol *lbl = newiTempLabel (NULL);
4824 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4825 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4826 emitcode ("cpl", "c");
4827 emitcode ("", "%05d$:", (lbl->key + 100));
4830 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4831 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4833 aopOp (result, ic, TRUE, FALSE);
4836 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4843 genIfxJump (ifx, "c");
4846 /* if the result is used in an arithmetic operation
4847 then put the result in place */
4852 gencjne (left, right, newiTempLabel (NULL));
4854 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4855 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4857 aopOp (result, ic, TRUE, FALSE);
4859 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4861 aopPut (AOP (result), "a", 0);
4866 genIfxJump (ifx, "a");
4869 /* if the result is used in an arithmetic operation
4870 then put the result in place */
4871 if (AOP_TYPE (result) != AOP_CRY)
4873 /* leave the result in acc */
4877 freeAsmop (result, NULL, ic, TRUE);
4880 /*-----------------------------------------------------------------*/
4881 /* ifxForOp - returns the icode containing the ifx for operand */
4882 /*-----------------------------------------------------------------*/
4884 ifxForOp (operand * op, iCode * ic)
4886 /* if true symbol then needs to be assigned */
4887 if (IS_TRUE_SYMOP (op))
4890 /* if this has register type condition and
4891 the next instruction is ifx with the same operand
4892 and live to of the operand is upto the ifx only then */
4894 ic->next->op == IFX &&
4895 IC_COND (ic->next)->key == op->key &&
4896 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4901 /*-----------------------------------------------------------------*/
4902 /* genAndOp - for && operation */
4903 /*-----------------------------------------------------------------*/
4905 genAndOp (iCode * ic)
4907 operand *left, *right, *result;
4910 D (emitcode (";", "genAndOp "););
4912 /* note here that && operations that are in an
4913 if statement are taken away by backPatchLabels
4914 only those used in arthmetic operations remain */
4916 AOP_SET_LOCALS (ic);
4918 /* if both are bit variables */
4919 if (AOP_TYPE (left) == AOP_CRY &&
4920 AOP_TYPE (right) == AOP_CRY)
4922 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4923 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4924 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4927 aopOp (result,ic,FALSE, FALSE);
4932 tlbl = newiTempLabel (NULL);
4934 emitcode ("jz", "%05d$", tlbl->key + 100);
4936 emitcode ("", "%05d$:", tlbl->key + 100);
4937 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4940 aopOp (result,ic,FALSE, FALSE);
4943 freeAsmop (result, NULL, ic, TRUE);
4947 /*-----------------------------------------------------------------*/
4948 /* genOrOp - for || operation */
4949 /*-----------------------------------------------------------------*/
4951 genOrOp (iCode * ic)
4953 operand *left, *right, *result;
4956 D (emitcode (";", "genOrOp "););
4958 /* note here that || operations that are in an
4959 if statement are taken away by backPatchLabels
4960 only those used in arthmetic operations remain */
4962 AOP_SET_LOCALS (ic);
4964 /* if both are bit variables */
4965 if (AOP_TYPE (left) == AOP_CRY &&
4966 AOP_TYPE (right) == AOP_CRY)
4968 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4969 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4970 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4971 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4973 aopOp (result,ic,FALSE, FALSE);
4979 tlbl = newiTempLabel (NULL);
4981 emitcode ("jnz", "%05d$", tlbl->key + 100);
4983 emitcode ("", "%05d$:", tlbl->key + 100);
4984 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4985 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4987 aopOp (result,ic,FALSE, FALSE);
4992 freeAsmop (result, NULL, ic, TRUE);
4995 /*-----------------------------------------------------------------*/
4996 /* isLiteralBit - test if lit == 2^n */
4997 /*-----------------------------------------------------------------*/
4999 isLiteralBit (unsigned long lit)
5001 unsigned long pw[32] =
5002 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5003 0x100L, 0x200L, 0x400L, 0x800L,
5004 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5005 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5006 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5007 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5008 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5011 for (idx = 0; idx < 32; idx++)
5017 /*-----------------------------------------------------------------*/
5018 /* continueIfTrue - */
5019 /*-----------------------------------------------------------------*/
5021 continueIfTrue (iCode * ic)
5024 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5028 /*-----------------------------------------------------------------*/
5030 /*-----------------------------------------------------------------*/
5032 jumpIfTrue (iCode * ic)
5035 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5039 /*-----------------------------------------------------------------*/
5040 /* jmpTrueOrFalse - */
5041 /*-----------------------------------------------------------------*/
5043 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5045 // ugly but optimized by peephole
5048 symbol *nlbl = newiTempLabel (NULL);
5049 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5050 emitcode ("", "%05d$:", tlbl->key + 100);
5051 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5052 emitcode ("", "%05d$:", nlbl->key + 100);
5056 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5057 emitcode ("", "%05d$:", tlbl->key + 100);
5062 // Generate code to perform a bit-wise logic operation
5063 // on two operands in far space (assumed to already have been
5064 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5065 // in far space. This requires pushing the result on the stack
5066 // then popping it into the result.
5068 genFarFarLogicOp(iCode *ic, char *logicOp)
5070 int size, resultSize, compSize;
5073 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5074 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5075 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5077 _startLazyDPSEvaluation();
5078 for (size = compSize; (size--); offset++)
5080 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5081 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5082 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5084 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5085 emitcode ("push", "acc");
5087 _endLazyDPSEvaluation();
5089 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5090 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5091 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5093 resultSize = AOP_SIZE(IC_RESULT(ic));
5095 ADJUST_PUSHED_RESULT(compSize, resultSize);
5097 _startLazyDPSEvaluation();
5100 emitcode ("pop", "acc");
5101 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5103 _endLazyDPSEvaluation();
5104 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5108 /*-----------------------------------------------------------------*/
5109 /* genAnd - code for and */
5110 /*-----------------------------------------------------------------*/
5112 genAnd (iCode * ic, iCode * ifx)
5114 operand *left, *right, *result;
5115 int size, offset = 0;
5116 unsigned long lit = 0L;
5121 D (emitcode (";", "genAnd "););
5123 AOP_OP_3_NOFATAL (ic, pushResult);
5124 AOP_SET_LOCALS (ic);
5128 genFarFarLogicOp(ic, "anl");
5133 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5135 AOP_TYPE (left), AOP_TYPE (right));
5136 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5138 AOP_SIZE (left), AOP_SIZE (right));
5141 /* if left is a literal & right is not then exchange them */
5142 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5143 AOP_NEEDSACC (left))
5145 operand *tmp = right;
5150 /* if result = right then exchange them */
5151 if (sameRegs (AOP (result), AOP (right)))
5153 operand *tmp = right;
5158 /* if right is bit then exchange them */
5159 if (AOP_TYPE (right) == AOP_CRY &&
5160 AOP_TYPE (left) != AOP_CRY)
5162 operand *tmp = right;
5166 if (AOP_TYPE (right) == AOP_LIT)
5167 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5169 size = AOP_SIZE (result);
5172 // result = bit & yy;
5173 if (AOP_TYPE (left) == AOP_CRY)
5175 // c = bit & literal;
5176 if (AOP_TYPE (right) == AOP_LIT)
5180 if (size && sameRegs (AOP (result), AOP (left)))
5183 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5188 if (size && (AOP_TYPE (result) == AOP_CRY))
5190 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5193 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5198 emitcode ("clr", "c");
5203 if (AOP_TYPE (right) == AOP_CRY)
5206 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5207 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5212 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5214 emitcode ("rrc", "a");
5215 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5223 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5224 genIfxJump (ifx, "c");
5228 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5229 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5230 if ((AOP_TYPE (right) == AOP_LIT) &&
5231 (AOP_TYPE (result) == AOP_CRY) &&
5232 (AOP_TYPE (left) != AOP_CRY))
5234 int posbit = isLiteralBit (lit);
5239 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5242 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5248 sprintf (buffer, "acc.%d", posbit & 0x07);
5249 genIfxJump (ifx, buffer);
5256 symbol *tlbl = newiTempLabel (NULL);
5257 int sizel = AOP_SIZE (left);
5259 emitcode ("setb", "c");
5262 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5264 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5266 if ((posbit = isLiteralBit (bytelit)) != 0)
5267 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5270 if (bytelit != 0x0FFL)
5271 emitcode ("anl", "a,%s",
5272 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5273 emitcode ("jnz", "%05d$", tlbl->key + 100);
5278 // bit = left & literal
5281 emitcode ("clr", "c");
5282 emitcode ("", "%05d$:", tlbl->key + 100);
5284 // if(left & literal)
5288 jmpTrueOrFalse (ifx, tlbl);
5296 /* if left is same as result */
5297 if (sameRegs (AOP (result), AOP (left)))
5299 for (; size--; offset++)
5301 if (AOP_TYPE (right) == AOP_LIT)
5303 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5305 else if (bytelit == 0)
5306 aopPut (AOP (result), zero, offset);
5307 else if (IS_AOP_PREG (result))
5309 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5310 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5311 aopPut (AOP (result), "a", offset);
5314 emitcode ("anl", "%s,%s",
5315 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5316 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5320 if (AOP_TYPE (left) == AOP_ACC)
5321 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5324 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5325 if (IS_AOP_PREG (result))
5327 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5328 aopPut (AOP (result), "a", offset);
5332 emitcode ("anl", "%s,a",
5333 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5340 // left & result in different registers
5341 if (AOP_TYPE (result) == AOP_CRY)
5344 // if(size), result in bit
5345 // if(!size && ifx), conditional oper: if(left & right)
5346 symbol *tlbl = newiTempLabel (NULL);
5347 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5349 emitcode ("setb", "c");
5352 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5353 emitcode ("anl", "a,%s",
5354 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5355 emitcode ("jnz", "%05d$", tlbl->key + 100);
5361 emitcode ("", "%05d$:", tlbl->key + 100);
5365 jmpTrueOrFalse (ifx, tlbl);
5369 for (; (size--); offset++)
5372 // result = left & right
5373 if (AOP_TYPE (right) == AOP_LIT)
5375 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5377 aopPut (AOP (result),
5378 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5382 else if (bytelit == 0)
5384 aopPut (AOP (result), zero, offset);
5387 D (emitcode (";", "better literal AND.");
5389 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5390 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5391 FALSE, FALSE, FALSE));
5396 // faster than result <- left, anl result,right
5397 // and better if result is SFR
5398 if (AOP_TYPE (left) == AOP_ACC)
5400 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5401 FALSE, FALSE, FALSE));
5405 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5406 emitcode ("anl", "a,%s",
5407 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5410 aopPut (AOP (result), "a", offset);
5416 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418 freeAsmop (result, NULL, ic, TRUE);
5422 /*-----------------------------------------------------------------*/
5423 /* genOr - code for or */
5424 /*-----------------------------------------------------------------*/
5426 genOr (iCode * ic, iCode * ifx)
5428 operand *left, *right, *result;
5429 int size, offset = 0;
5430 unsigned long lit = 0L;
5433 D (emitcode (";", "genOr "););
5435 AOP_OP_3_NOFATAL (ic, pushResult);
5436 AOP_SET_LOCALS (ic);
5440 genFarFarLogicOp(ic, "orl");
5446 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5448 AOP_TYPE (left), AOP_TYPE (right));
5449 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5451 AOP_SIZE (left), AOP_SIZE (right));
5454 /* if left is a literal & right is not then exchange them */
5455 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5456 AOP_NEEDSACC (left))
5458 operand *tmp = right;
5463 /* if result = right then exchange them */
5464 if (sameRegs (AOP (result), AOP (right)))
5466 operand *tmp = right;
5471 /* if right is bit then exchange them */
5472 if (AOP_TYPE (right) == AOP_CRY &&
5473 AOP_TYPE (left) != AOP_CRY)
5475 operand *tmp = right;
5479 if (AOP_TYPE (right) == AOP_LIT)
5480 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5482 size = AOP_SIZE (result);
5486 if (AOP_TYPE (left) == AOP_CRY)
5488 if (AOP_TYPE (right) == AOP_LIT)
5490 // c = bit & literal;
5493 // lit != 0 => result = 1
5494 if (AOP_TYPE (result) == AOP_CRY)
5497 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5499 continueIfTrue (ifx);
5502 emitcode ("setb", "c");
5506 // lit == 0 => result = left
5507 if (size && sameRegs (AOP (result), AOP (left)))
5509 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5514 if (AOP_TYPE (right) == AOP_CRY)
5517 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5518 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5523 symbol *tlbl = newiTempLabel (NULL);
5524 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5525 emitcode ("setb", "c");
5526 emitcode ("jb", "%s,%05d$",
5527 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5529 emitcode ("jnz", "%05d$", tlbl->key + 100);
5530 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5532 jmpTrueOrFalse (ifx, tlbl);
5538 emitcode ("", "%05d$:", tlbl->key + 100);
5547 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5548 genIfxJump (ifx, "c");
5552 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5553 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5554 if ((AOP_TYPE (right) == AOP_LIT) &&
5555 (AOP_TYPE (result) == AOP_CRY) &&
5556 (AOP_TYPE (left) != AOP_CRY))
5562 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5564 continueIfTrue (ifx);
5569 // lit = 0, result = boolean(left)
5571 emitcode ("setb", "c");
5575 symbol *tlbl = newiTempLabel (NULL);
5576 emitcode ("jnz", "%05d$", tlbl->key + 100);
5578 emitcode ("", "%05d$:", tlbl->key + 100);
5582 genIfxJump (ifx, "a");
5590 /* if left is same as result */
5591 if (sameRegs (AOP (result), AOP (left)))
5593 for (; size--; offset++)
5595 if (AOP_TYPE (right) == AOP_LIT)
5597 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5603 if (IS_AOP_PREG (left))
5605 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5606 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5607 aopPut (AOP (result), "a", offset);
5611 emitcode ("orl", "%s,%s",
5612 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5613 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5619 if (AOP_TYPE (left) == AOP_ACC)
5621 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5625 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5626 if (IS_AOP_PREG (left))
5628 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5629 aopPut (AOP (result), "a", offset);
5633 emitcode ("orl", "%s,a",
5634 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5642 // left & result in different registers
5643 if (AOP_TYPE (result) == AOP_CRY)
5646 // if(size), result in bit
5647 // if(!size && ifx), conditional oper: if(left | right)
5648 symbol *tlbl = newiTempLabel (NULL);
5649 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5651 emitcode ("setb", "c");
5654 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5655 emitcode ("orl", "a,%s",
5656 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5657 emitcode ("jnz", "%05d$", tlbl->key + 100);
5663 emitcode ("", "%05d$:", tlbl->key + 100);
5667 jmpTrueOrFalse (ifx, tlbl);
5671 for (; (size--); offset++)
5674 // result = left & right
5675 if (AOP_TYPE (right) == AOP_LIT)
5677 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5679 aopPut (AOP (result),
5680 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5684 D (emitcode (";", "better literal OR.");
5686 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5687 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5688 FALSE, FALSE, FALSE));
5693 // faster than result <- left, anl result,right
5694 // and better if result is SFR
5695 if (AOP_TYPE (left) == AOP_ACC)
5697 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5698 FALSE, FALSE, FALSE));
5702 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5703 emitcode ("orl", "a,%s",
5704 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5707 aopPut (AOP (result), "a", offset);
5713 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5714 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5715 freeAsmop (result, NULL, ic, TRUE);
5718 /*-----------------------------------------------------------------*/
5719 /* genXor - code for xclusive or */
5720 /*-----------------------------------------------------------------*/
5722 genXor (iCode * ic, iCode * ifx)
5724 operand *left, *right, *result;
5725 int size, offset = 0;
5726 unsigned long lit = 0L;
5729 D (emitcode (";", "genXor "););
5731 AOP_OP_3_NOFATAL (ic, pushResult);
5732 AOP_SET_LOCALS (ic);
5736 genFarFarLogicOp(ic, "xrl");
5741 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5743 AOP_TYPE (left), AOP_TYPE (right));
5744 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5746 AOP_SIZE (left), AOP_SIZE (right));
5749 /* if left is a literal & right is not ||
5750 if left needs acc & right does not */
5751 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5752 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5754 operand *tmp = right;
5759 /* if result = right then exchange them */
5760 if (sameRegs (AOP (result), AOP (right)))
5762 operand *tmp = right;
5767 /* if right is bit then exchange them */
5768 if (AOP_TYPE (right) == AOP_CRY &&
5769 AOP_TYPE (left) != AOP_CRY)
5771 operand *tmp = right;
5775 if (AOP_TYPE (right) == AOP_LIT)
5776 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5778 size = AOP_SIZE (result);
5782 if (AOP_TYPE (left) == AOP_CRY)
5784 if (AOP_TYPE (right) == AOP_LIT)
5786 // c = bit & literal;
5789 // lit>>1 != 0 => result = 1
5790 if (AOP_TYPE (result) == AOP_CRY)
5793 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5795 continueIfTrue (ifx);
5798 emitcode ("setb", "c");
5805 // lit == 0, result = left
5806 if (size && sameRegs (AOP (result), AOP (left)))
5808 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5812 // lit == 1, result = not(left)
5813 if (size && sameRegs (AOP (result), AOP (left)))
5815 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5820 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5821 emitcode ("cpl", "c");
5830 symbol *tlbl = newiTempLabel (NULL);
5831 if (AOP_TYPE (right) == AOP_CRY)
5834 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5838 int sizer = AOP_SIZE (right);
5840 // if val>>1 != 0, result = 1
5841 emitcode ("setb", "c");
5844 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5846 // test the msb of the lsb
5847 emitcode ("anl", "a,#0xfe");
5848 emitcode ("jnz", "%05d$", tlbl->key + 100);
5852 emitcode ("rrc", "a");
5854 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5855 emitcode ("cpl", "c");
5856 emitcode ("", "%05d$:", (tlbl->key + 100));
5863 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5864 genIfxJump (ifx, "c");
5868 if (sameRegs (AOP (result), AOP (left)))
5870 /* if left is same as result */
5871 for (; size--; offset++)
5873 if (AOP_TYPE (right) == AOP_LIT)
5875 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5877 else if (IS_AOP_PREG (left))
5879 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5880 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5881 aopPut (AOP (result), "a", offset);
5884 emitcode ("xrl", "%s,%s",
5885 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5886 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5890 if (AOP_TYPE (left) == AOP_ACC)
5891 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5894 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5895 if (IS_AOP_PREG (left))
5897 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5898 aopPut (AOP (result), "a", offset);
5901 emitcode ("xrl", "%s,a",
5902 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5909 // left & result in different registers
5910 if (AOP_TYPE (result) == AOP_CRY)
5913 // if(size), result in bit
5914 // if(!size && ifx), conditional oper: if(left ^ right)
5915 symbol *tlbl = newiTempLabel (NULL);
5916 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5918 emitcode ("setb", "c");
5921 if ((AOP_TYPE (right) == AOP_LIT) &&
5922 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5924 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5928 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5929 emitcode ("xrl", "a,%s",
5930 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5932 emitcode ("jnz", "%05d$", tlbl->key + 100);
5938 emitcode ("", "%05d$:", tlbl->key + 100);
5942 jmpTrueOrFalse (ifx, tlbl);
5945 for (; (size--); offset++)
5948 // result = left & right
5949 if (AOP_TYPE (right) == AOP_LIT)
5951 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5953 aopPut (AOP (result),
5954 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5958 D (emitcode (";", "better literal XOR.");
5960 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5961 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5962 FALSE, FALSE, FALSE));
5966 // faster than result <- left, anl result,right
5967 // and better if result is SFR
5968 if (AOP_TYPE (left) == AOP_ACC)
5970 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5971 FALSE, FALSE, FALSE));
5975 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5976 emitcode ("xrl", "a,%s",
5977 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5980 aopPut (AOP (result), "a", offset);
5985 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5987 freeAsmop (result, NULL, ic, TRUE);
5990 /*-----------------------------------------------------------------*/
5991 /* genInline - write the inline code out */
5992 /*-----------------------------------------------------------------*/
5994 genInline (iCode * ic)
5996 char *buffer, *bp, *bp1;
5998 D (emitcode (";", "genInline ");
6001 _G.inLine += (!options.asmpeep);
6003 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6004 strcpy (buffer, IC_INLINE (ic));
6006 /* emit each line as a code */
6031 /* emitcode("",buffer); */
6032 _G.inLine -= (!options.asmpeep);
6035 /*-----------------------------------------------------------------*/
6036 /* genRRC - rotate right with carry */
6037 /*-----------------------------------------------------------------*/
6041 operand *left, *result;
6042 int size, offset = 0;
6045 D (emitcode (";", "genRRC ");
6048 /* rotate right with carry */
6049 left = IC_LEFT (ic);
6050 result = IC_RESULT (ic);
6051 aopOp (left, ic, FALSE, FALSE);
6052 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6054 /* move it to the result */
6055 size = AOP_SIZE (result);
6059 _startLazyDPSEvaluation ();
6062 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6064 emitcode ("rrc", "a");
6065 if (AOP_SIZE (result) > 1)
6066 aopPut (AOP (result), "a", offset--);
6068 _endLazyDPSEvaluation ();
6070 /* now we need to put the carry into the
6071 highest order byte of the result */
6072 if (AOP_SIZE (result) > 1)
6074 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6077 emitcode ("mov", "acc.7,c");
6078 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6079 freeAsmop (left, NULL, ic, TRUE);
6080 freeAsmop (result, NULL, ic, TRUE);
6083 /*-----------------------------------------------------------------*/
6084 /* genRLC - generate code for rotate left with carry */
6085 /*-----------------------------------------------------------------*/
6089 operand *left, *result;
6090 int size, offset = 0;
6093 D (emitcode (";", "genRLC ");
6096 /* rotate right with carry */
6097 left = IC_LEFT (ic);
6098 result = IC_RESULT (ic);
6099 aopOp (left, ic, FALSE, FALSE);
6100 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6102 /* move it to the result */
6103 size = AOP_SIZE (result);
6107 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6109 emitcode ("add", "a,acc");
6110 if (AOP_SIZE (result) > 1)
6112 aopPut (AOP (result), "a", offset++);
6115 _startLazyDPSEvaluation ();
6118 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6120 emitcode ("rlc", "a");
6121 if (AOP_SIZE (result) > 1)
6122 aopPut (AOP (result), "a", offset++);
6124 _endLazyDPSEvaluation ();
6126 /* now we need to put the carry into the
6127 highest order byte of the result */
6128 if (AOP_SIZE (result) > 1)
6130 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6133 emitcode ("mov", "acc.0,c");
6134 aopPut (AOP (result), "a", 0);
6135 freeAsmop (left, NULL, ic, TRUE);
6136 freeAsmop (result, NULL, ic, TRUE);
6139 /*-----------------------------------------------------------------*/
6140 /* genGetHbit - generates code get highest order bit */
6141 /*-----------------------------------------------------------------*/
6143 genGetHbit (iCode * ic)
6145 operand *left, *result;
6146 left = IC_LEFT (ic);
6147 result = IC_RESULT (ic);
6148 aopOp (left, ic, FALSE, FALSE);
6149 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6151 D (emitcode (";", "genGetHbit ");
6154 /* get the highest order byte into a */
6155 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6156 if (AOP_TYPE (result) == AOP_CRY)
6158 emitcode ("rlc", "a");
6163 emitcode ("rl", "a");
6164 emitcode ("anl", "a,#0x01");
6169 freeAsmop (left, NULL, ic, TRUE);
6170 freeAsmop (result, NULL, ic, TRUE);
6173 /*-----------------------------------------------------------------*/
6174 /* AccRol - rotate left accumulator by known count */
6175 /*-----------------------------------------------------------------*/
6177 AccRol (int shCount)
6179 shCount &= 0x0007; // shCount : 0..7
6186 emitcode ("rl", "a");
6189 emitcode ("rl", "a");
6190 emitcode ("rl", "a");
6193 emitcode ("swap", "a");
6194 emitcode ("rr", "a");
6197 emitcode ("swap", "a");
6200 emitcode ("swap", "a");
6201 emitcode ("rl", "a");
6204 emitcode ("rr", "a");
6205 emitcode ("rr", "a");
6208 emitcode ("rr", "a");
6213 /*-----------------------------------------------------------------*/
6214 /* AccLsh - left shift accumulator by known count */
6215 /*-----------------------------------------------------------------*/
6217 AccLsh (int shCount)
6222 emitcode ("add", "a,acc");
6223 else if (shCount == 2)
6225 emitcode ("add", "a,acc");
6226 emitcode ("add", "a,acc");
6230 /* rotate left accumulator */
6232 /* and kill the lower order bits */
6233 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6238 /*-----------------------------------------------------------------*/
6239 /* AccRsh - right shift accumulator by known count */
6240 /*-----------------------------------------------------------------*/
6242 AccRsh (int shCount)
6249 emitcode ("rrc", "a");
6253 /* rotate right accumulator */
6254 AccRol (8 - shCount);
6255 /* and kill the higher order bits */
6256 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6261 #ifdef BETTER_LITERAL_SHIFT
6262 /*-----------------------------------------------------------------*/
6263 /* AccSRsh - signed right shift accumulator by known count */
6264 /*-----------------------------------------------------------------*/
6266 AccSRsh (int shCount)
6273 emitcode ("mov", "c,acc.7");
6274 emitcode ("rrc", "a");
6276 else if (shCount == 2)
6278 emitcode ("mov", "c,acc.7");
6279 emitcode ("rrc", "a");
6280 emitcode ("mov", "c,acc.7");
6281 emitcode ("rrc", "a");
6285 tlbl = newiTempLabel (NULL);
6286 /* rotate right accumulator */
6287 AccRol (8 - shCount);
6288 /* and kill the higher order bits */
6289 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6290 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6291 emitcode ("orl", "a,#0x%02x",
6292 (unsigned char) ~SRMask[shCount]);
6293 emitcode ("", "%05d$:", tlbl->key + 100);
6299 #ifdef BETTER_LITERAL_SHIFT
6300 /*-----------------------------------------------------------------*/
6301 /* shiftR1Left2Result - shift right one byte from left to result */
6302 /*-----------------------------------------------------------------*/
6304 shiftR1Left2Result (operand * left, int offl,
6305 operand * result, int offr,
6306 int shCount, int sign)
6308 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6309 /* shift right accumulator */
6314 aopPut (AOP (result), "a", offr);
6318 #ifdef BETTER_LITERAL_SHIFT
6319 /*-----------------------------------------------------------------*/
6320 /* shiftL1Left2Result - shift left one byte from left to result */
6321 /*-----------------------------------------------------------------*/
6323 shiftL1Left2Result (operand * left, int offl,
6324 operand * result, int offr, int shCount)
6326 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6327 /* shift left accumulator */
6329 aopPut (AOP (result), "a", offr);
6333 #ifdef BETTER_LITERAL_SHIFT
6334 /*-----------------------------------------------------------------*/
6335 /* movLeft2Result - move byte from left to result */
6336 /*-----------------------------------------------------------------*/
6338 movLeft2Result (operand * left, int offl,
6339 operand * result, int offr, int sign)
6342 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6344 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6346 if (*l == '@' && (IS_AOP_PREG (result)))
6348 emitcode ("mov", "a,%s", l);
6349 aopPut (AOP (result), "a", offr);
6355 aopPut (AOP (result), l, offr);
6359 /* MSB sign in acc.7 ! */
6360 if (getDataSize (left) == offl + 1)
6362 emitcode ("mov", "a,%s", l);
6363 aopPut (AOP (result), "a", offr);
6371 #ifdef BETTER_LITERAL_SHIFT
6372 /*-----------------------------------------------------------------*/
6373 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6374 /*-----------------------------------------------------------------*/
6378 emitcode ("rrc", "a");
6379 emitcode ("xch", "a,%s", x);
6380 emitcode ("rrc", "a");
6381 emitcode ("xch", "a,%s", x);
6385 #ifdef BETTER_LITERAL_SHIFT
6387 /*-----------------------------------------------------------------*/
6388 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6389 /*-----------------------------------------------------------------*/
6393 emitcode ("xch", "a,%s", x);
6394 emitcode ("rlc", "a");
6395 emitcode ("xch", "a,%s", x);
6396 emitcode ("rlc", "a");
6400 #ifdef BETTER_LITERAL_SHIFT
6401 /*-----------------------------------------------------------------*/
6402 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6403 /*-----------------------------------------------------------------*/
6407 emitcode ("xch", "a,%s", x);
6408 emitcode ("add", "a,acc");
6409 emitcode ("xch", "a,%s", x);
6410 emitcode ("rlc", "a");
6414 #ifdef BETTER_LITERAL_SHIFT
6415 /*-----------------------------------------------------------------*/
6416 /* AccAXLsh - left shift a:x by known count (0..7) */
6417 /*-----------------------------------------------------------------*/
6419 AccAXLsh (char *x, int shCount)
6434 case 5: // AAAAABBB:CCCCCDDD
6436 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6438 emitcode ("anl", "a,#0x%02x",
6439 SLMask[shCount]); // BBB00000:CCCCCDDD
6441 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6443 AccRol (shCount); // DDDCCCCC:BBB00000
6445 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6447 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6449 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6451 emitcode ("anl", "a,#0x%02x",
6452 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6454 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6456 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6459 case 6: // AAAAAABB:CCCCCCDD
6460 emitcode ("anl", "a,#0x%02x",
6461 SRMask[shCount]); // 000000BB:CCCCCCDD
6462 emitcode ("mov", "c,acc.0"); // c = B
6463 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6465 AccAXRrl1 (x); // BCCCCCCD:D000000B
6466 AccAXRrl1 (x); // BBCCCCCC:DD000000
6468 emitcode("rrc","a");
6469 emitcode("xch","a,%s", x);
6470 emitcode("rrc","a");
6471 emitcode("mov","c,acc.0"); //<< get correct bit
6472 emitcode("xch","a,%s", x);
6474 emitcode("rrc","a");
6475 emitcode("xch","a,%s", x);
6476 emitcode("rrc","a");
6477 emitcode("xch","a,%s", x);
6480 case 7: // a:x <<= 7
6482 emitcode ("anl", "a,#0x%02x",
6483 SRMask[shCount]); // 0000000B:CCCCCCCD
6485 emitcode ("mov", "c,acc.0"); // c = B
6487 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6489 AccAXRrl1 (x); // BCCCCCCC:D0000000
6498 #ifdef BETTER_LITERAL_SHIFT
6500 /*-----------------------------------------------------------------*/
6501 /* AccAXRsh - right shift a:x known count (0..7) */
6502 /*-----------------------------------------------------------------*/
6504 AccAXRsh (char *x, int shCount)
6512 AccAXRrl1 (x); // 0->a:x
6517 AccAXRrl1 (x); // 0->a:x
6520 AccAXRrl1 (x); // 0->a:x
6525 case 5: // AAAAABBB:CCCCCDDD = a:x
6527 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6529 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6531 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6533 emitcode ("anl", "a,#0x%02x",
6534 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6536 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6538 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6540 emitcode ("anl", "a,#0x%02x",
6541 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6543 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6545 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6547 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6550 case 6: // AABBBBBB:CCDDDDDD
6552 emitcode ("mov", "c,acc.7");
6553 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6555 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6557 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6559 emitcode ("anl", "a,#0x%02x",
6560 SRMask[shCount]); // 000000AA:BBBBBBCC
6563 case 7: // ABBBBBBB:CDDDDDDD
6565 emitcode ("mov", "c,acc.7"); // c = A
6567 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6569 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6571 emitcode ("anl", "a,#0x%02x",
6572 SRMask[shCount]); // 0000000A:BBBBBBBC
6581 #ifdef BETTER_LITERAL_SHIFT
6583 /*-----------------------------------------------------------------*/
6584 /* AccAXRshS - right shift signed a:x known count (0..7) */
6585 /*-----------------------------------------------------------------*/
6587 AccAXRshS (char *x, int shCount)
6595 emitcode ("mov", "c,acc.7");
6596 AccAXRrl1 (x); // s->a:x
6600 emitcode ("mov", "c,acc.7");
6601 AccAXRrl1 (x); // s->a:x
6603 emitcode ("mov", "c,acc.7");
6604 AccAXRrl1 (x); // s->a:x
6609 case 5: // AAAAABBB:CCCCCDDD = a:x
6611 tlbl = newiTempLabel (NULL);
6612 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6614 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6616 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6618 emitcode ("anl", "a,#0x%02x",
6619 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6621 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6623 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6625 emitcode ("anl", "a,#0x%02x",
6626 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6628 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6630 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6632 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6634 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6635 emitcode ("orl", "a,#0x%02x",
6636 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6638 emitcode ("", "%05d$:", tlbl->key + 100);
6639 break; // SSSSAAAA:BBBCCCCC
6641 case 6: // AABBBBBB:CCDDDDDD
6643 tlbl = newiTempLabel (NULL);
6644 emitcode ("mov", "c,acc.7");
6645 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6647 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6649 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6651 emitcode ("anl", "a,#0x%02x",
6652 SRMask[shCount]); // 000000AA:BBBBBBCC
6654 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6655 emitcode ("orl", "a,#0x%02x",
6656 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6658 emitcode ("", "%05d$:", tlbl->key + 100);
6660 case 7: // ABBBBBBB:CDDDDDDD
6662 tlbl = newiTempLabel (NULL);
6663 emitcode ("mov", "c,acc.7"); // c = A
6665 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6667 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6669 emitcode ("anl", "a,#0x%02x",
6670 SRMask[shCount]); // 0000000A:BBBBBBBC
6672 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6673 emitcode ("orl", "a,#0x%02x",
6674 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6676 emitcode ("", "%05d$:", tlbl->key + 100);
6684 #ifdef BETTER_LITERAL_SHIFT
6686 _loadLeftIntoAx(char **lsb,
6692 // Get the initial value from left into a pair of registers.
6693 // MSB must be in A, LSB can be any register.
6695 // If the result is held in registers, it is an optimization
6696 // if the LSB can be held in the register which will hold the,
6697 // result LSB since this saves us from having to copy it into
6698 // the result following AccAXLsh.
6700 // If the result is addressed indirectly, this is not a gain.
6701 if (AOP_NEEDSACC(result))
6705 _startLazyDPSEvaluation();
6706 if (AOP_TYPE(left) == AOP_DPTR2)
6709 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6710 // get LSB in DP2_RESULT_REG.
6711 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6712 assert(!strcmp(leftByte, DP2_RESULT_REG));
6716 // get LSB into DP2_RESULT_REG
6717 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6718 if (strcmp(leftByte, DP2_RESULT_REG))
6720 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6723 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6724 assert(strcmp(leftByte, DP2_RESULT_REG));
6727 _endLazyDPSEvaluation();
6728 *lsb = DP2_RESULT_REG;
6732 if (sameRegs (AOP (result), AOP (left)) &&
6733 ((offl + MSB16) == offr))
6735 /* don't crash result[offr] */
6736 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6737 emitcode ("xch", "a,%s",
6738 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6742 movLeft2Result (left, offl, result, offr, 0);
6743 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6745 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6746 assert(strcmp(*lsb,"a"));
6751 _storeAxResults(char *lsb,
6755 _startLazyDPSEvaluation();
6756 if (AOP_NEEDSACC(result))
6758 /* We have to explicitly update the result LSB.
6760 emitcode("xch","a,%s", lsb);
6761 aopPut(AOP(result), "a", offr);
6762 emitcode("mov","a,%s", lsb);
6764 if (getDataSize (result) > 1)
6766 aopPut (AOP (result), "a", offr + MSB16);
6768 _endLazyDPSEvaluation();
6771 /*-----------------------------------------------------------------*/
6772 /* shiftL2Left2Result - shift left two bytes from left to result */
6773 /*-----------------------------------------------------------------*/
6775 shiftL2Left2Result (operand * left, int offl,
6776 operand * result, int offr, int shCount)
6780 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6782 AccAXLsh (lsb, shCount);
6784 _storeAxResults(lsb, result, offr);
6788 #ifdef BETTER_LITERAL_SHIFT
6789 /*-----------------------------------------------------------------*/
6790 /* shiftR2Left2Result - shift right two bytes from left to result */
6791 /*-----------------------------------------------------------------*/
6793 shiftR2Left2Result (operand * left, int offl,
6794 operand * result, int offr,
6795 int shCount, int sign)
6799 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6801 /* a:x >> shCount (x = lsb(result)) */
6804 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6808 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6811 _storeAxResults(lsb, result, offr);
6817 /*-----------------------------------------------------------------*/
6818 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6819 /*-----------------------------------------------------------------*/
6821 shiftLLeftOrResult (operand * left, int offl,
6822 operand * result, int offr, int shCount)
6824 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6825 /* shift left accumulator */
6827 /* or with result */
6828 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6829 /* back to result */
6830 aopPut (AOP (result), "a", offr);
6836 /*-----------------------------------------------------------------*/
6837 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6838 /*-----------------------------------------------------------------*/
6840 shiftRLeftOrResult (operand * left, int offl,
6841 operand * result, int offr, int shCount)
6843 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6844 /* shift right accumulator */
6846 /* or with result */
6847 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6848 /* back to result */
6849 aopPut (AOP (result), "a", offr);
6853 #ifdef BETTER_LITERAL_SHIFT
6854 /*-----------------------------------------------------------------*/
6855 /* genlshOne - left shift a one byte quantity by known count */
6856 /*-----------------------------------------------------------------*/
6858 genlshOne (operand * result, operand * left, int shCount)
6860 D (emitcode (";", "genlshOne "););
6861 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6865 #ifdef BETTER_LITERAL_SHIFT
6866 /*-----------------------------------------------------------------*/
6867 /* genlshTwo - left shift two bytes by known amount != 0 */
6868 /*-----------------------------------------------------------------*/
6870 genlshTwo (operand * result, operand * left, int shCount)
6874 D (emitcode (";", "genlshTwo "););
6876 size = getDataSize (result);
6878 /* if shCount >= 8 */
6883 _startLazyDPSEvaluation();
6889 _endLazyDPSEvaluation();
6890 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6891 aopPut (AOP (result), zero, LSB);
6895 movLeft2Result (left, LSB, result, MSB16, 0);
6896 aopPut (AOP (result), zero, LSB);
6897 _endLazyDPSEvaluation();
6902 aopPut (AOP (result), zero, LSB);
6903 _endLazyDPSEvaluation();
6907 /* 1 <= shCount <= 7 */
6912 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6916 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6924 /*-----------------------------------------------------------------*/
6925 /* shiftLLong - shift left one long from left to result */
6926 /* offl = LSB or MSB16 */
6927 /*-----------------------------------------------------------------*/
6929 shiftLLong (operand * left, operand * result, int offr)
6932 int size = AOP_SIZE (result);
6934 if (size >= LSB + offr)
6936 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6938 emitcode ("add", "a,acc");
6939 if (sameRegs (AOP (left), AOP (result)) &&
6940 size >= MSB16 + offr && offr != LSB)
6941 emitcode ("xch", "a,%s",
6942 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6944 aopPut (AOP (result), "a", LSB + offr);
6947 if (size >= MSB16 + offr)
6949 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6951 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6954 emitcode ("rlc", "a");
6955 if (sameRegs (AOP (left), AOP (result)) &&
6956 size >= MSB24 + offr && offr != LSB)
6957 emitcode ("xch", "a,%s",
6958 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6960 aopPut (AOP (result), "a", MSB16 + offr);
6963 if (size >= MSB24 + offr)
6965 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6967 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6970 emitcode ("rlc", "a");
6971 if (sameRegs (AOP (left), AOP (result)) &&
6972 size >= MSB32 + offr && offr != LSB)
6973 emitcode ("xch", "a,%s",
6974 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6976 aopPut (AOP (result), "a", MSB24 + offr);
6979 if (size > MSB32 + offr)
6981 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6983 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6986 emitcode ("rlc", "a");
6987 aopPut (AOP (result), "a", MSB32 + offr);
6990 aopPut (AOP (result), zero, LSB);
6996 /*-----------------------------------------------------------------*/
6997 /* genlshFour - shift four byte by a known amount != 0 */
6998 /*-----------------------------------------------------------------*/
7000 genlshFour (operand * result, operand * left, int shCount)
7004 D (emitcode (";", "genlshFour ");
7007 size = AOP_SIZE (result);
7009 /* if shifting more that 3 bytes */
7014 /* lowest order of left goes to the highest
7015 order of the destination */
7016 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7018 movLeft2Result (left, LSB, result, MSB32, 0);
7019 aopPut (AOP (result), zero, LSB);
7020 aopPut (AOP (result), zero, MSB16);
7021 aopPut (AOP (result), zero, MSB24);
7025 /* more than two bytes */
7026 else if (shCount >= 16)
7028 /* lower order two bytes goes to higher order two bytes */
7030 /* if some more remaining */
7032 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7035 movLeft2Result (left, MSB16, result, MSB32, 0);
7036 movLeft2Result (left, LSB, result, MSB24, 0);
7038 aopPut (AOP (result), zero, MSB16);
7039 aopPut (AOP (result), zero, LSB);
7043 /* if more than 1 byte */
7044 else if (shCount >= 8)
7046 /* lower order three bytes goes to higher order three bytes */
7051 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7053 movLeft2Result (left, LSB, result, MSB16, 0);
7059 movLeft2Result (left, MSB24, result, MSB32, 0);
7060 movLeft2Result (left, MSB16, result, MSB24, 0);
7061 movLeft2Result (left, LSB, result, MSB16, 0);
7062 aopPut (AOP (result), zero, LSB);
7064 else if (shCount == 1)
7065 shiftLLong (left, result, MSB16);
7068 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7069 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7070 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7071 aopPut (AOP (result), zero, LSB);
7076 /* 1 <= shCount <= 7 */
7077 else if (shCount <= 2)
7079 shiftLLong (left, result, LSB);
7081 shiftLLong (result, result, LSB);
7083 /* 3 <= shCount <= 7, optimize */
7086 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7087 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7088 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7093 #ifdef BETTER_LITERAL_SHIFT
7094 /*-----------------------------------------------------------------*/
7095 /* genLeftShiftLiteral - left shifting by known count */
7096 /*-----------------------------------------------------------------*/
7098 genLeftShiftLiteral (operand * left,
7103 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7106 size = getSize (operandType (result));
7108 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7110 /* We only handle certain easy cases so far. */
7112 && (shCount < (size * 8))
7116 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7120 freeAsmop (right, NULL, ic, TRUE);
7122 aopOp(left, ic, FALSE, FALSE);
7123 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7126 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7128 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7129 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7131 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7134 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7136 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7137 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7139 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7145 emitcode ("; shift left ", "result %d, left %d", size,
7149 /* I suppose that the left size >= result size */
7152 _startLazyDPSEvaluation();
7155 movLeft2Result (left, size, result, size, 0);
7157 _endLazyDPSEvaluation();
7159 else if (shCount >= (size * 8))
7161 _startLazyDPSEvaluation();
7164 aopPut (AOP (result), zero, size);
7166 _endLazyDPSEvaluation();
7173 genlshOne (result, left, shCount);
7177 genlshTwo (result, left, shCount);
7181 genlshFour (result, left, shCount);
7185 fprintf(stderr, "*** ack! mystery literal shift!\n");
7189 freeAsmop (left, NULL, ic, TRUE);
7190 freeAsmop (result, NULL, ic, TRUE);
7195 /*-----------------------------------------------------------------*/
7196 /* genLeftShift - generates code for left shifting */
7197 /*-----------------------------------------------------------------*/
7199 genLeftShift (iCode * ic)
7201 operand *left, *right, *result;
7204 symbol *tlbl, *tlbl1;
7206 D (emitcode (";", "genLeftShift "););
7208 right = IC_RIGHT (ic);
7209 left = IC_LEFT (ic);
7210 result = IC_RESULT (ic);
7212 aopOp (right, ic, FALSE, FALSE);
7215 #ifdef BETTER_LITERAL_SHIFT
7216 /* if the shift count is known then do it
7217 as efficiently as possible */
7218 if (AOP_TYPE (right) == AOP_LIT)
7220 if (genLeftShiftLiteral (left, right, result, ic))
7227 /* shift count is unknown then we have to form
7228 a loop get the loop count in B : Note: we take
7229 only the lower order byte since shifting
7230 more that 32 bits make no sense anyway, ( the
7231 largest size of an object can be only 32 bits ) */
7233 if (AOP_TYPE (right) == AOP_LIT)
7235 /* Really should be handled by genLeftShiftLiteral,
7236 * but since I'm too lazy to fix that today, at least we can make
7237 * some small improvement.
7239 emitcode("mov", "b,#0x%02x",
7240 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7244 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7245 emitcode ("inc", "b");
7247 freeAsmop (right, NULL, ic, TRUE);
7248 aopOp (left, ic, FALSE, FALSE);
7249 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7251 /* now move the left to the result if they are not the
7253 if (!sameRegs (AOP (left), AOP (result)) &&
7254 AOP_SIZE (result) > 1)
7257 size = AOP_SIZE (result);
7259 _startLazyDPSEvaluation ();
7262 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7263 if (*l == '@' && (IS_AOP_PREG (result)))
7266 emitcode ("mov", "a,%s", l);
7267 aopPut (AOP (result), "a", offset);
7270 aopPut (AOP (result), l, offset);
7273 _endLazyDPSEvaluation ();
7276 tlbl = newiTempLabel (NULL);
7277 size = AOP_SIZE (result);
7279 tlbl1 = newiTempLabel (NULL);
7281 /* if it is only one byte then */
7284 symbol *tlbl1 = newiTempLabel (NULL);
7286 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7288 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7289 emitcode ("", "%05d$:", tlbl->key + 100);
7290 emitcode ("add", "a,acc");
7291 emitcode ("", "%05d$:", tlbl1->key + 100);
7292 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7293 aopPut (AOP (result), "a", 0);
7297 reAdjustPreg (AOP (result));
7299 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7300 emitcode ("", "%05d$:", tlbl->key + 100);
7301 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7303 emitcode ("add", "a,acc");
7304 aopPut (AOP (result), "a", offset++);
7305 _startLazyDPSEvaluation ();
7308 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7310 emitcode ("rlc", "a");
7311 aopPut (AOP (result), "a", offset++);
7313 _endLazyDPSEvaluation ();
7314 reAdjustPreg (AOP (result));
7316 emitcode ("", "%05d$:", tlbl1->key + 100);
7317 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7319 freeAsmop (left, NULL, ic, TRUE);
7320 freeAsmop (result, NULL, ic, TRUE);
7323 #ifdef BETTER_LITERAL_SHIFT
7324 /*-----------------------------------------------------------------*/
7325 /* genrshOne - right shift a one byte quantity by known count */
7326 /*-----------------------------------------------------------------*/
7328 genrshOne (operand * result, operand * left,
7329 int shCount, int sign)
7331 D (emitcode (";", "genrshOne"););
7332 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7336 #ifdef BETTER_LITERAL_SHIFT
7337 /*-----------------------------------------------------------------*/
7338 /* genrshTwo - right shift two bytes by known amount != 0 */
7339 /*-----------------------------------------------------------------*/
7341 genrshTwo (operand * result, operand * left,
7342 int shCount, int sign)
7344 D (emitcode (";", "genrshTwo"););
7346 /* if shCount >= 8 */
7350 _startLazyDPSEvaluation();
7353 shiftR1Left2Result (left, MSB16, result, LSB,
7358 movLeft2Result (left, MSB16, result, LSB, sign);
7360 addSign (result, MSB16, sign);
7361 _endLazyDPSEvaluation();
7364 /* 1 <= shCount <= 7 */
7367 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7374 /*-----------------------------------------------------------------*/
7375 /* shiftRLong - shift right one long from left to result */
7376 /* offl = LSB or MSB16 */
7377 /*-----------------------------------------------------------------*/
7379 shiftRLong (operand * left, int offl,
7380 operand * result, int sign)
7382 int isSameRegs=sameRegs(AOP(left),AOP(result));
7384 if (isSameRegs && offl>1) {
7385 // we are in big trouble, but this shouldn't happen
7386 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7389 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7394 emitcode ("rlc", "a");
7395 emitcode ("subb", "a,acc");
7396 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7398 aopPut (AOP(result), zero, MSB32);
7403 emitcode ("clr", "c");
7405 emitcode ("mov", "c,acc.7");
7408 emitcode ("rrc", "a");
7410 if (isSameRegs && offl==MSB16) {
7411 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7413 aopPut (AOP (result), "a", MSB32);
7414 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7417 emitcode ("rrc", "a");
7418 if (isSameRegs && offl==1) {
7419 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7421 aopPut (AOP (result), "a", MSB24);
7422 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7424 emitcode ("rrc", "a");
7425 aopPut (AOP (result), "a", MSB16 - offl);
7429 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7430 emitcode ("rrc", "a");
7431 aopPut (AOP (result), "a", LSB);
7438 /*-----------------------------------------------------------------*/
7439 /* genrshFour - shift four byte by a known amount != 0 */
7440 /*-----------------------------------------------------------------*/
7442 genrshFour (operand * result, operand * left,
7443 int shCount, int sign)
7445 D (emitcode (";", "genrshFour");
7448 /* if shifting more that 3 bytes */
7453 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7455 movLeft2Result (left, MSB32, result, LSB, sign);
7456 addSign (result, MSB16, sign);
7458 else if (shCount >= 16)
7462 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7465 movLeft2Result (left, MSB24, result, LSB, 0);
7466 movLeft2Result (left, MSB32, result, MSB16, sign);
7468 addSign (result, MSB24, sign);
7470 else if (shCount >= 8)
7474 shiftRLong (left, MSB16, result, sign);
7475 else if (shCount == 0)
7477 movLeft2Result (left, MSB16, result, LSB, 0);
7478 movLeft2Result (left, MSB24, result, MSB16, 0);
7479 movLeft2Result (left, MSB32, result, MSB24, sign);
7480 addSign (result, MSB32, sign);
7484 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7485 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7486 /* the last shift is signed */
7487 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7488 addSign (result, MSB32, sign);
7492 { /* 1 <= shCount <= 7 */
7495 shiftRLong (left, LSB, result, sign);
7497 shiftRLong (result, LSB, result, sign);
7501 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7502 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7503 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7509 #ifdef BETTER_LITERAL_SHIFT
7510 /*-----------------------------------------------------------------*/
7511 /* genRightShiftLiteral - right shifting by known count */
7512 /*-----------------------------------------------------------------*/
7514 genRightShiftLiteral (operand * left,
7520 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7523 size = getSize (operandType (result));
7525 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7527 /* We only handle certain easy cases so far. */
7529 && (shCount < (size * 8))
7533 D(emitcode (";", "genRightShiftLiteral wimping out"););
7537 freeAsmop (right, NULL, ic, TRUE);
7539 aopOp (left, ic, FALSE, FALSE);
7540 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7543 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7547 /* test the LEFT size !!! */
7549 /* I suppose that the left size >= result size */
7552 size = getDataSize (result);
7553 _startLazyDPSEvaluation();
7556 movLeft2Result (left, size, result, size, 0);
7558 _endLazyDPSEvaluation();
7560 else if (shCount >= (size * 8))
7564 /* get sign in acc.7 */
7565 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7567 addSign (result, LSB, sign);
7574 genrshOne (result, left, shCount, sign);
7578 genrshTwo (result, left, shCount, sign);
7582 genrshFour (result, left, shCount, sign);
7589 freeAsmop (left, NULL, ic, TRUE);
7590 freeAsmop (result, NULL, ic, TRUE);
7596 /*-----------------------------------------------------------------*/
7597 /* genSignedRightShift - right shift of signed number */
7598 /*-----------------------------------------------------------------*/
7600 genSignedRightShift (iCode * ic)
7602 operand *right, *left, *result;
7605 symbol *tlbl, *tlbl1;
7607 D (emitcode (";", "genSignedRightShift "););
7609 /* we do it the hard way put the shift count in b
7610 and loop thru preserving the sign */
7612 right = IC_RIGHT (ic);
7613 left = IC_LEFT (ic);
7614 result = IC_RESULT (ic);
7616 aopOp (right, ic, FALSE, FALSE);
7618 #ifdef BETTER_LITERAL_SHIFT
7619 if (AOP_TYPE (right) == AOP_LIT)
7621 if (genRightShiftLiteral (left, right, result, ic, 1))
7627 /* shift count is unknown then we have to form
7628 a loop get the loop count in B : Note: we take
7629 only the lower order byte since shifting
7630 more that 32 bits make no sense anyway, ( the
7631 largest size of an object can be only 32 bits ) */
7633 if (AOP_TYPE (right) == AOP_LIT)
7635 /* Really should be handled by genRightShiftLiteral,
7636 * but since I'm too lazy to fix that today, at least we can make
7637 * some small improvement.
7639 emitcode("mov", "b,#0x%02x",
7640 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7644 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7645 emitcode ("inc", "b");
7647 freeAsmop (right, NULL, ic, TRUE);
7648 aopOp (left, ic, FALSE, FALSE);
7649 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7651 /* now move the left to the result if they are not the
7653 if (!sameRegs (AOP (left), AOP (result)) &&
7654 AOP_SIZE (result) > 1)
7657 size = AOP_SIZE (result);
7659 _startLazyDPSEvaluation ();
7662 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7663 if (*l == '@' && IS_AOP_PREG (result))
7666 emitcode ("mov", "a,%s", l);
7667 aopPut (AOP (result), "a", offset);
7670 aopPut (AOP (result), l, offset);
7673 _endLazyDPSEvaluation ();
7676 /* mov the highest order bit to OVR */
7677 tlbl = newiTempLabel (NULL);
7678 tlbl1 = newiTempLabel (NULL);
7680 size = AOP_SIZE (result);
7682 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7683 emitcode ("rlc", "a");
7684 emitcode ("mov", "ov,c");
7685 /* if it is only one byte then */
7688 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7690 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7691 emitcode ("", "%05d$:", tlbl->key + 100);
7692 emitcode ("mov", "c,ov");
7693 emitcode ("rrc", "a");
7694 emitcode ("", "%05d$:", tlbl1->key + 100);
7695 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7696 aopPut (AOP (result), "a", 0);
7700 reAdjustPreg (AOP (result));
7701 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7702 emitcode ("", "%05d$:", tlbl->key + 100);
7703 emitcode ("mov", "c,ov");
7704 _startLazyDPSEvaluation ();
7707 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7709 emitcode ("rrc", "a");
7710 aopPut (AOP (result), "a", offset--);
7712 _endLazyDPSEvaluation ();
7713 reAdjustPreg (AOP (result));
7714 emitcode ("", "%05d$:", tlbl1->key + 100);
7715 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7718 freeAsmop (left, NULL, ic, TRUE);
7719 freeAsmop (result, NULL, ic, TRUE);
7722 /*-----------------------------------------------------------------*/
7723 /* genRightShift - generate code for right shifting */
7724 /*-----------------------------------------------------------------*/
7726 genRightShift (iCode * ic)
7728 operand *right, *left, *result;
7732 symbol *tlbl, *tlbl1;
7734 D (emitcode (";", "genRightShift "););
7736 /* if signed then we do it the hard way preserve the
7737 sign bit moving it inwards */
7738 retype = getSpec (operandType (IC_RESULT (ic)));
7740 if (!SPEC_USIGN (retype))
7742 genSignedRightShift (ic);
7746 /* signed & unsigned types are treated the same : i.e. the
7747 signed is NOT propagated inwards : quoting from the
7748 ANSI - standard : "for E1 >> E2, is equivalent to division
7749 by 2**E2 if unsigned or if it has a non-negative value,
7750 otherwise the result is implementation defined ", MY definition
7751 is that the sign does not get propagated */
7753 right = IC_RIGHT (ic);
7754 left = IC_LEFT (ic);
7755 result = IC_RESULT (ic);
7757 aopOp (right, ic, FALSE, FALSE);
7759 #ifdef BETTER_LITERAL_SHIFT
7760 /* if the shift count is known then do it
7761 as efficiently as possible */
7762 if (AOP_TYPE (right) == AOP_LIT)
7764 if (genRightShiftLiteral (left, right, result, ic, 0))
7771 /* shift count is unknown then we have to form
7772 a loop get the loop count in B : Note: we take
7773 only the lower order byte since shifting
7774 more that 32 bits make no sense anyway, ( the
7775 largest size of an object can be only 32 bits ) */
7777 if (AOP_TYPE (right) == AOP_LIT)
7779 /* Really should be handled by genRightShiftLiteral,
7780 * but since I'm too lazy to fix that today, at least we can make
7781 * some small improvement.
7783 emitcode("mov", "b,#0x%02x",
7784 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7788 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7789 emitcode ("inc", "b");
7791 freeAsmop (right, NULL, ic, TRUE);
7792 aopOp (left, ic, FALSE, FALSE);
7793 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7795 /* now move the left to the result if they are not the
7797 if (!sameRegs (AOP (left), AOP (result)) &&
7798 AOP_SIZE (result) > 1)
7801 size = AOP_SIZE (result);
7803 _startLazyDPSEvaluation ();
7806 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7807 if (*l == '@' && IS_AOP_PREG (result))
7810 emitcode ("mov", "a,%s", l);
7811 aopPut (AOP (result), "a", offset);
7814 aopPut (AOP (result), l, offset);
7817 _endLazyDPSEvaluation ();
7820 tlbl = newiTempLabel (NULL);
7821 tlbl1 = newiTempLabel (NULL);
7822 size = AOP_SIZE (result);
7825 /* if it is only one byte then */
7828 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7830 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7831 emitcode ("", "%05d$:", tlbl->key + 100);
7833 emitcode ("rrc", "a");
7834 emitcode ("", "%05d$:", tlbl1->key + 100);
7835 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7836 aopPut (AOP (result), "a", 0);
7840 reAdjustPreg (AOP (result));
7841 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7842 emitcode ("", "%05d$:", tlbl->key + 100);
7844 _startLazyDPSEvaluation ();
7847 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7849 emitcode ("rrc", "a");
7850 aopPut (AOP (result), "a", offset--);
7852 _endLazyDPSEvaluation ();
7853 reAdjustPreg (AOP (result));
7855 emitcode ("", "%05d$:", tlbl1->key + 100);
7856 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7859 freeAsmop (left, NULL, ic, TRUE);
7860 freeAsmop (result, NULL, ic, TRUE);
7863 /*-----------------------------------------------------------------*/
7864 /* genUnpackBits - generates code for unpacking bits */
7865 /*-----------------------------------------------------------------*/
7867 genUnpackBits (operand * result, char *rname, int ptype)
7874 D (emitcode (";", "genUnpackBits ");
7877 etype = getSpec (operandType (result));
7879 /* read the first byte */
7885 emitcode ("mov", "a,@%s", rname);
7889 emitcode ("movx", "a,@%s", rname);
7893 emitcode ("movx", "a,@dptr");
7897 emitcode ("clr", "a");
7898 emitcode ("movc", "a", "@a+dptr");
7902 emitcode ("lcall", "__gptrget");
7906 /* if we have bitdisplacement then it fits */
7907 /* into this byte completely or if length is */
7908 /* less than a byte */
7909 if ((shCnt = SPEC_BSTR (etype)) ||
7910 (SPEC_BLEN (etype) <= 8))
7913 /* shift right acc */
7916 emitcode ("anl", "a,#0x%02x",
7917 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7918 aopPut (AOP (result), "a", offset);
7922 /* bit field did not fit in a byte */
7923 rlen = SPEC_BLEN (etype) - 8;
7924 aopPut (AOP (result), "a", offset++);
7933 emitcode ("inc", "%s", rname);
7934 emitcode ("mov", "a,@%s", rname);
7938 emitcode ("inc", "%s", rname);
7939 emitcode ("movx", "a,@%s", rname);
7943 emitcode ("inc", "dptr");
7944 emitcode ("movx", "a,@dptr");
7948 emitcode ("clr", "a");
7949 emitcode ("inc", "dptr");
7950 emitcode ("movc", "a", "@a+dptr");
7954 emitcode ("inc", "dptr");
7955 emitcode ("lcall", "__gptrget");
7960 /* if we are done */
7964 aopPut (AOP (result), "a", offset++);
7970 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7971 aopPut (AOP (result), "a", offset);
7978 /*-----------------------------------------------------------------*/
7979 /* genDataPointerGet - generates code when ptr offset is known */
7980 /*-----------------------------------------------------------------*/
7982 genDataPointerGet (operand * left,
7988 int size, offset = 0;
7989 aopOp (result, ic, TRUE, FALSE);
7991 /* get the string representation of the name */
7992 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7993 size = AOP_SIZE (result);
7994 _startLazyDPSEvaluation ();
7998 sprintf (buffer, "(%s + %d)", l + 1, offset);
8000 sprintf (buffer, "%s", l + 1);
8001 aopPut (AOP (result), buffer, offset++);
8003 _endLazyDPSEvaluation ();
8005 freeAsmop (left, NULL, ic, TRUE);
8006 freeAsmop (result, NULL, ic, TRUE);
8009 /*-----------------------------------------------------------------*/
8010 /* genNearPointerGet - emitcode for near pointer fetch */
8011 /*-----------------------------------------------------------------*/
8013 genNearPointerGet (operand * left,
8020 sym_link *rtype, *retype, *letype;
8021 sym_link *ltype = operandType (left);
8024 rtype = operandType (result);
8025 retype = getSpec (rtype);
8026 letype = getSpec (ltype);
8028 aopOp (left, ic, FALSE, FALSE);
8030 /* if left is rematerialisable and
8031 result is not bit variable type and
8032 the left is pointer to data space i.e
8033 lower 128 bytes of space */
8034 if (AOP_TYPE (left) == AOP_IMMD &&
8035 !IS_BITVAR (retype) &&
8036 !IS_BITVAR (letype) &&
8037 DCL_TYPE (ltype) == POINTER)
8039 genDataPointerGet (left, result, ic);
8043 /* if the value is already in a pointer register
8044 then don't need anything more */
8045 if (!AOP_INPREG (AOP (left)))
8047 /* otherwise get a free pointer register */
8049 preg = getFreePtr (ic, &aop, FALSE);
8050 emitcode ("mov", "%s,%s",
8052 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8056 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8058 freeAsmop (left, NULL, ic, TRUE);
8059 aopOp (result, ic, FALSE, FALSE);
8061 /* if bitfield then unpack the bits */
8062 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8063 genUnpackBits (result, rname, POINTER);
8066 /* we have can just get the values */
8067 int size = AOP_SIZE (result);
8072 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8075 emitcode ("mov", "a,@%s", rname);
8076 aopPut (AOP (result), "a", offset);
8080 sprintf (buffer, "@%s", rname);
8081 aopPut (AOP (result), buffer, offset);
8085 emitcode ("inc", "%s", rname);
8089 /* now some housekeeping stuff */
8092 /* we had to allocate for this iCode */
8093 freeAsmop (NULL, aop, ic, TRUE);
8097 /* we did not allocate which means left
8098 already in a pointer register, then
8099 if size > 0 && this could be used again
8100 we have to point it back to where it
8102 if (AOP_SIZE (result) > 1 &&
8103 !OP_SYMBOL (left)->remat &&
8104 (OP_SYMBOL (left)->liveTo > ic->seq ||
8107 int size = AOP_SIZE (result) - 1;
8109 emitcode ("dec", "%s", rname);
8114 freeAsmop (result, NULL, ic, TRUE);
8118 /*-----------------------------------------------------------------*/
8119 /* genPagedPointerGet - emitcode for paged pointer fetch */
8120 /*-----------------------------------------------------------------*/
8122 genPagedPointerGet (operand * left,
8129 sym_link *rtype, *retype, *letype;
8131 rtype = operandType (result);
8132 retype = getSpec (rtype);
8133 letype = getSpec (operandType (left));
8134 aopOp (left, ic, FALSE, FALSE);
8136 /* if the value is already in a pointer register
8137 then don't need anything more */
8138 if (!AOP_INPREG (AOP (left)))
8140 /* otherwise get a free pointer register */
8142 preg = getFreePtr (ic, &aop, FALSE);
8143 emitcode ("mov", "%s,%s",
8145 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8149 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8151 freeAsmop (left, NULL, ic, TRUE);
8152 aopOp (result, ic, FALSE, FALSE);
8154 /* if bitfield then unpack the bits */
8155 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8156 genUnpackBits (result, rname, PPOINTER);
8159 /* we have can just get the values */
8160 int size = AOP_SIZE (result);
8166 emitcode ("movx", "a,@%s", rname);
8167 aopPut (AOP (result), "a", offset);
8172 emitcode ("inc", "%s", rname);
8176 /* now some housekeeping stuff */
8179 /* we had to allocate for this iCode */
8180 freeAsmop (NULL, aop, ic, TRUE);
8184 /* we did not allocate which means left
8185 already in a pointer register, then
8186 if size > 0 && this could be used again
8187 we have to point it back to where it
8189 if (AOP_SIZE (result) > 1 &&
8190 !OP_SYMBOL (left)->remat &&
8191 (OP_SYMBOL (left)->liveTo > ic->seq ||
8194 int size = AOP_SIZE (result) - 1;
8196 emitcode ("dec", "%s", rname);
8201 freeAsmop (result, NULL, ic, TRUE);
8206 /*-----------------------------------------------------------------*/
8207 /* genFarPointerGet - gget value from far space */
8208 /*-----------------------------------------------------------------*/
8210 genFarPointerGet (operand * left,
8211 operand * result, iCode * ic)
8214 sym_link *retype = getSpec (operandType (result));
8215 sym_link *letype = getSpec (operandType (left));
8216 D (emitcode (";", "genFarPointerGet");
8219 aopOp (left, ic, FALSE, FALSE);
8221 /* if the operand is already in dptr
8222 then we do nothing else we move the value to dptr */
8223 if (AOP_TYPE (left) != AOP_STR)
8225 /* if this is remateriazable */
8226 if (AOP_TYPE (left) == AOP_IMMD)
8228 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8232 /* we need to get it byte by byte */
8233 _startLazyDPSEvaluation ();
8234 if (AOP_TYPE (left) != AOP_DPTR)
8236 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8237 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8238 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8242 /* We need to generate a load to DPTR indirect through DPTR. */
8243 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8245 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8246 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8247 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8248 emitcode ("pop", "dph");
8249 emitcode ("pop", "dpl");
8251 _endLazyDPSEvaluation ();
8254 /* so dptr know contains the address */
8255 freeAsmop (left, NULL, ic, TRUE);
8256 aopOp (result, ic, FALSE, TRUE);
8258 /* if bit then unpack */
8259 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8260 genUnpackBits (result, "dptr", FPOINTER);
8263 size = AOP_SIZE (result);
8266 _startLazyDPSEvaluation ();
8273 emitcode ("movx", "a,@dptr");
8275 emitcode ("inc", "dptr");
8277 aopPut (AOP (result), "a", offset++);
8279 _endLazyDPSEvaluation ();
8282 freeAsmop (result, NULL, ic, TRUE);
8285 /*-----------------------------------------------------------------*/
8286 /* emitcodePointerGet - gget value from code space */
8287 /*-----------------------------------------------------------------*/
8289 emitcodePointerGet (operand * left,
8290 operand * result, iCode * ic)
8293 sym_link *retype = getSpec (operandType (result));
8295 aopOp (left, ic, FALSE, FALSE);
8297 /* if the operand is already in dptr
8298 then we do nothing else we move the value to dptr */
8299 if (AOP_TYPE (left) != AOP_STR)
8301 /* if this is remateriazable */
8302 if (AOP_TYPE (left) == AOP_IMMD)
8304 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8307 { /* we need to get it byte by byte */
8308 _startLazyDPSEvaluation ();
8309 if (AOP_TYPE (left) != AOP_DPTR)
8311 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8312 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8313 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8317 /* We need to generate a load to DPTR indirect through DPTR. */
8318 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8320 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8321 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8322 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8323 emitcode ("pop", "dph");
8324 emitcode ("pop", "dpl");
8326 _endLazyDPSEvaluation ();
8329 /* so dptr know contains the address */
8330 freeAsmop (left, NULL, ic, TRUE);
8331 aopOp (result, ic, FALSE, TRUE);
8333 /* if bit then unpack */
8334 if (IS_BITVAR (retype))
8335 genUnpackBits (result, "dptr", CPOINTER);
8338 size = AOP_SIZE (result);
8341 _startLazyDPSEvaluation ();
8347 emitcode ("clr", "a");
8348 emitcode ("movc", "a,@a+dptr");
8350 emitcode ("inc", "dptr");
8351 aopPut (AOP (result), "a", offset++);
8353 _endLazyDPSEvaluation ();
8356 freeAsmop (result, NULL, ic, TRUE);
8359 /*-----------------------------------------------------------------*/
8360 /* genGenPointerGet - gget value from generic pointer space */
8361 /*-----------------------------------------------------------------*/
8363 genGenPointerGet (operand * left,
8364 operand * result, iCode * ic)
8367 sym_link *retype = getSpec (operandType (result));
8368 sym_link *letype = getSpec (operandType (left));
8370 D (emitcode (";", "genGenPointerGet "); );
8372 aopOp (left, ic, FALSE, TRUE);
8374 /* if the operand is already in dptr
8375 then we do nothing else we move the value to dptr */
8376 if (AOP_TYPE (left) != AOP_STR)
8378 /* if this is remateriazable */
8379 if (AOP_TYPE (left) == AOP_IMMD)
8381 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8382 emitcode ("mov", "b,#%d", pointerCode (retype));
8385 { /* we need to get it byte by byte */
8386 _startLazyDPSEvaluation ();
8387 if (AOP(left)->type==AOP_DPTR2) {
8389 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8392 emitcode ("mov", "dpl,%s", l);
8393 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8396 emitcode ("mov", "dph,%s", l);
8397 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8400 emitcode ("mov", "dpx,%s", l);
8401 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8403 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8404 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8405 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8406 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8408 _endLazyDPSEvaluation ();
8411 /* so dptr know contains the address */
8412 freeAsmop (left, NULL, ic, TRUE);
8413 aopOp (result, ic, FALSE, TRUE);
8415 /* if bit then unpack */
8416 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8417 genUnpackBits (result, "dptr", GPOINTER);
8420 size = AOP_SIZE (result);
8425 emitcode ("lcall", "__gptrget");
8426 aopPut (AOP (result), "a", offset++);
8428 emitcode ("inc", "dptr");
8432 freeAsmop (result, NULL, ic, TRUE);
8435 /*-----------------------------------------------------------------*/
8436 /* genPointerGet - generate code for pointer get */
8437 /*-----------------------------------------------------------------*/
8439 genPointerGet (iCode * ic)
8441 operand *left, *result;
8442 sym_link *type, *etype;
8445 D (emitcode (";", "genPointerGet ");
8448 left = IC_LEFT (ic);
8449 result = IC_RESULT (ic);
8451 /* depending on the type of pointer we need to
8452 move it to the correct pointer register */
8453 type = operandType (left);
8454 etype = getSpec (type);
8455 /* if left is of type of pointer then it is simple */
8456 if (IS_PTR (type) && !IS_FUNC (type->next))
8457 p_type = DCL_TYPE (type);
8460 /* we have to go by the storage class */
8461 p_type = PTR_TYPE (SPEC_OCLS (etype));
8464 /* now that we have the pointer type we assign
8465 the pointer values */
8471 genNearPointerGet (left, result, ic);
8475 genPagedPointerGet (left, result, ic);
8479 genFarPointerGet (left, result, ic);
8483 emitcodePointerGet (left, result, ic);
8487 genGenPointerGet (left, result, ic);
8493 /*-----------------------------------------------------------------*/
8494 /* genPackBits - generates code for packed bit storage */
8495 /*-----------------------------------------------------------------*/
8497 genPackBits (sym_link * etype,
8499 char *rname, int p_type)
8507 blen = SPEC_BLEN (etype);
8508 bstr = SPEC_BSTR (etype);
8510 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8513 /* if the bit lenth is less than or */
8514 /* it exactly fits a byte then */
8515 if (SPEC_BLEN (etype) <= 8)
8517 shCount = SPEC_BSTR (etype);
8519 /* shift left acc */
8522 if (SPEC_BLEN (etype) < 8)
8523 { /* if smaller than a byte */
8529 emitcode ("mov", "b,a");
8530 emitcode ("mov", "a,@%s", rname);
8534 emitcode ("mov", "b,a");
8535 emitcode ("movx", "a,@dptr");
8539 emitcode ("push", "b");
8540 emitcode ("push", "acc");
8541 emitcode ("lcall", "__gptrget");
8542 emitcode ("pop", "b");
8546 emitcode ("anl", "a,#0x%02x", (unsigned char)
8547 ((unsigned char) (0xFF << (blen + bstr)) |
8548 (unsigned char) (0xFF >> (8 - bstr))));
8549 emitcode ("orl", "a,b");
8550 if (p_type == GPOINTER)
8551 emitcode ("pop", "b");
8558 emitcode ("mov", "@%s,a", rname);
8562 emitcode ("movx", "@dptr,a");
8566 emitcode ("lcall", "__gptrput");
8571 if (SPEC_BLEN (etype) <= 8)
8574 emitcode ("inc", "%s", rname);
8575 rLen = SPEC_BLEN (etype);
8577 /* now generate for lengths greater than one byte */
8581 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8593 emitcode ("mov", "@%s,a", rname);
8596 emitcode ("mov", "@%s,%s", rname, l);
8601 emitcode ("movx", "@dptr,a");
8606 emitcode ("lcall", "__gptrput");
8609 emitcode ("inc", "%s", rname);
8614 /* last last was not complete */
8617 /* save the byte & read byte */
8621 emitcode ("mov", "b,a");
8622 emitcode ("mov", "a,@%s", rname);
8626 emitcode ("mov", "b,a");
8627 emitcode ("movx", "a,@dptr");
8631 emitcode ("push", "b");
8632 emitcode ("push", "acc");
8633 emitcode ("lcall", "__gptrget");
8634 emitcode ("pop", "b");
8638 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8639 emitcode ("orl", "a,b");
8642 if (p_type == GPOINTER)
8643 emitcode ("pop", "b");
8649 emitcode ("mov", "@%s,a", rname);
8653 emitcode ("movx", "@dptr,a");
8657 emitcode ("lcall", "__gptrput");
8661 /*-----------------------------------------------------------------*/
8662 /* genDataPointerSet - remat pointer to data space */
8663 /*-----------------------------------------------------------------*/
8665 genDataPointerSet (operand * right,
8669 int size, offset = 0;
8670 char *l, buffer[256];
8672 aopOp (right, ic, FALSE, FALSE);
8674 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8675 size = AOP_SIZE (right);
8679 sprintf (buffer, "(%s + %d)", l + 1, offset);
8681 sprintf (buffer, "%s", l + 1);
8682 emitcode ("mov", "%s,%s", buffer,
8683 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8686 freeAsmop (right, NULL, ic, TRUE);
8687 freeAsmop (result, NULL, ic, TRUE);
8690 /*-----------------------------------------------------------------*/
8691 /* genNearPointerSet - emitcode for near pointer put */
8692 /*-----------------------------------------------------------------*/
8694 genNearPointerSet (operand * right,
8701 sym_link *retype, *letype;
8702 sym_link *ptype = operandType (result);
8704 retype = getSpec (operandType (right));
8705 letype = getSpec (ptype);
8707 aopOp (result, ic, FALSE, FALSE);
8709 /* if the result is rematerializable &
8710 in data space & not a bit variable */
8711 if (AOP_TYPE (result) == AOP_IMMD &&
8712 DCL_TYPE (ptype) == POINTER &&
8713 !IS_BITVAR (retype) &&
8714 !IS_BITVAR (letype))
8716 genDataPointerSet (right, result, ic);
8720 /* if the value is already in a pointer register
8721 then don't need anything more */
8722 if (!AOP_INPREG (AOP (result)))
8724 /* otherwise get a free pointer register */
8726 preg = getFreePtr (ic, &aop, FALSE);
8727 emitcode ("mov", "%s,%s",
8729 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8733 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8735 freeAsmop (result, NULL, ic, TRUE);
8736 aopOp (right, ic, FALSE, FALSE);
8738 /* if bitfield then unpack the bits */
8739 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8740 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8743 /* we have can just get the values */
8744 int size = AOP_SIZE (right);
8749 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8753 emitcode ("mov", "@%s,a", rname);
8756 emitcode ("mov", "@%s,%s", rname, l);
8758 emitcode ("inc", "%s", rname);
8763 /* now some housekeeping stuff */
8766 /* we had to allocate for this iCode */
8767 freeAsmop (NULL, aop, ic, TRUE);
8771 /* we did not allocate which means left
8772 already in a pointer register, then
8773 if size > 0 && this could be used again
8774 we have to point it back to where it
8776 if (AOP_SIZE (right) > 1 &&
8777 !OP_SYMBOL (result)->remat &&
8778 (OP_SYMBOL (result)->liveTo > ic->seq ||
8781 int size = AOP_SIZE (right) - 1;
8783 emitcode ("dec", "%s", rname);
8788 freeAsmop (right, NULL, ic, TRUE);
8793 /*-----------------------------------------------------------------*/
8794 /* genPagedPointerSet - emitcode for Paged pointer put */
8795 /*-----------------------------------------------------------------*/
8797 genPagedPointerSet (operand * right,
8804 sym_link *retype, *letype;
8806 retype = getSpec (operandType (right));
8807 letype = getSpec (operandType (result));
8809 aopOp (result, ic, FALSE, FALSE);
8811 /* if the value is already in a pointer register
8812 then don't need anything more */
8813 if (!AOP_INPREG (AOP (result)))
8815 /* otherwise get a free pointer register */
8817 preg = getFreePtr (ic, &aop, FALSE);
8818 emitcode ("mov", "%s,%s",
8820 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8824 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8826 freeAsmop (result, NULL, ic, TRUE);
8827 aopOp (right, ic, FALSE, FALSE);
8829 /* if bitfield then unpack the bits */
8830 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8831 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8834 /* we have can just get the values */
8835 int size = AOP_SIZE (right);
8840 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8843 emitcode ("movx", "@%s,a", rname);
8846 emitcode ("inc", "%s", rname);
8852 /* now some housekeeping stuff */
8855 /* we had to allocate for this iCode */
8856 freeAsmop (NULL, aop, ic, TRUE);
8860 /* we did not allocate which means left
8861 already in a pointer register, then
8862 if size > 0 && this could be used again
8863 we have to point it back to where it
8865 if (AOP_SIZE (right) > 1 &&
8866 !OP_SYMBOL (result)->remat &&
8867 (OP_SYMBOL (result)->liveTo > ic->seq ||
8870 int size = AOP_SIZE (right) - 1;
8872 emitcode ("dec", "%s", rname);
8877 freeAsmop (right, NULL, ic, TRUE);
8882 /*-----------------------------------------------------------------*/
8883 /* genFarPointerSet - set value from far space */
8884 /*-----------------------------------------------------------------*/
8886 genFarPointerSet (operand * right,
8887 operand * result, iCode * ic)
8890 sym_link *retype = getSpec (operandType (right));
8891 sym_link *letype = getSpec (operandType (result));
8893 aopOp (result, ic, FALSE, FALSE);
8895 /* if the operand is already in dptr
8896 then we do nothing else we move the value to dptr */
8897 if (AOP_TYPE (result) != AOP_STR)
8899 /* if this is remateriazable */
8900 if (AOP_TYPE (result) == AOP_IMMD)
8901 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8904 /* we need to get it byte by byte */
8905 _startLazyDPSEvaluation ();
8906 if (AOP_TYPE (result) != AOP_DPTR)
8908 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8909 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8910 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8914 /* We need to generate a load to DPTR indirect through DPTR. */
8915 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8917 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8918 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8919 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8920 emitcode ("pop", "dph");
8921 emitcode ("pop", "dpl");
8923 _endLazyDPSEvaluation ();
8926 /* so dptr know contains the address */
8927 freeAsmop (result, NULL, ic, TRUE);
8928 aopOp (right, ic, FALSE, TRUE);
8930 /* if bit then unpack */
8931 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8932 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8935 size = AOP_SIZE (right);
8938 _startLazyDPSEvaluation ();
8941 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8947 emitcode ("movx", "@dptr,a");
8949 emitcode ("inc", "dptr");
8951 _endLazyDPSEvaluation ();
8954 freeAsmop (right, NULL, ic, TRUE);
8957 /*-----------------------------------------------------------------*/
8958 /* genGenPointerSet - set value from generic pointer space */
8959 /*-----------------------------------------------------------------*/
8961 genGenPointerSet (operand * right,
8962 operand * result, iCode * ic)
8965 sym_link *retype = getSpec (operandType (right));
8966 sym_link *letype = getSpec (operandType (result));
8968 aopOp (result, ic, FALSE, TRUE);
8970 /* if the operand is already in dptr
8971 then we do nothing else we move the value to dptr */
8972 if (AOP_TYPE (result) != AOP_STR)
8974 _startLazyDPSEvaluation ();
8975 /* if this is remateriazable */
8976 if (AOP_TYPE (result) == AOP_IMMD)
8978 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8979 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8982 { /* we need to get it byte by byte */
8983 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8984 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8985 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8986 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8988 _endLazyDPSEvaluation ();
8990 /* so dptr know contains the address */
8991 freeAsmop (result, NULL, ic, TRUE);
8992 aopOp (right, ic, FALSE, TRUE);
8994 /* if bit then unpack */
8995 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8996 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8999 size = AOP_SIZE (right);
9002 _startLazyDPSEvaluation ();
9005 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9011 emitcode ("lcall", "__gptrput");
9013 emitcode ("inc", "dptr");
9015 _endLazyDPSEvaluation ();
9018 freeAsmop (right, NULL, ic, TRUE);
9021 /*-----------------------------------------------------------------*/
9022 /* genPointerSet - stores the value into a pointer location */
9023 /*-----------------------------------------------------------------*/
9025 genPointerSet (iCode * ic)
9027 operand *right, *result;
9028 sym_link *type, *etype;
9031 D (emitcode (";", "genPointerSet ");
9034 right = IC_RIGHT (ic);
9035 result = IC_RESULT (ic);
9037 /* depending on the type of pointer we need to
9038 move it to the correct pointer register */
9039 type = operandType (result);
9040 etype = getSpec (type);
9041 /* if left is of type of pointer then it is simple */
9042 if (IS_PTR (type) && !IS_FUNC (type->next))
9044 p_type = DCL_TYPE (type);
9048 /* we have to go by the storage class */
9049 p_type = PTR_TYPE (SPEC_OCLS (etype));
9052 /* now that we have the pointer type we assign
9053 the pointer values */
9059 genNearPointerSet (right, result, ic);
9063 genPagedPointerSet (right, result, ic);
9067 genFarPointerSet (right, result, ic);
9071 genGenPointerSet (right, result, ic);
9077 /*-----------------------------------------------------------------*/
9078 /* genIfx - generate code for Ifx statement */
9079 /*-----------------------------------------------------------------*/
9081 genIfx (iCode * ic, iCode * popIc)
9083 operand *cond = IC_COND (ic);
9086 D (emitcode (";", "genIfx "););
9088 aopOp (cond, ic, FALSE, FALSE);
9090 /* get the value into acc */
9091 if (AOP_TYPE (cond) != AOP_CRY)
9095 /* the result is now in the accumulator */
9096 freeAsmop (cond, NULL, ic, TRUE);
9098 /* if there was something to be popped then do it */
9102 /* if the condition is a bit variable */
9103 if (isbit && IS_ITEMP (cond) &&
9105 genIfxJump (ic, SPIL_LOC (cond)->rname);
9106 else if (isbit && !IS_ITEMP (cond))
9107 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9109 genIfxJump (ic, "a");
9114 /*-----------------------------------------------------------------*/
9115 /* genAddrOf - generates code for address of */
9116 /*-----------------------------------------------------------------*/
9118 genAddrOf (iCode * ic)
9120 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9123 D (emitcode (";", "genAddrOf ");
9126 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9128 /* if the operand is on the stack then we
9129 need to get the stack offset of this
9133 /* if it has an offset then we need to compute
9137 emitcode ("mov", "a,_bp");
9138 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9139 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9143 /* we can just move _bp */
9144 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9146 /* fill the result with zero */
9147 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9150 if (options.stack10bit && size < (FPTRSIZE - 1))
9153 "*** warning: pointer to stack var truncated.\n");
9160 if (options.stack10bit && offset == 2)
9162 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9166 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9173 /* object not on stack then we need the name */
9174 size = AOP_SIZE (IC_RESULT (ic));
9179 char s[SDCC_NAME_MAX];
9181 sprintf (s, "#(%s >> %d)",
9185 sprintf (s, "#%s", sym->rname);
9186 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9190 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9194 /*-----------------------------------------------------------------*/
9195 /* genFarFarAssign - assignment when both are in far space */
9196 /*-----------------------------------------------------------------*/
9198 genFarFarAssign (operand * result, operand * right, iCode * ic)
9200 int size = AOP_SIZE (right);
9202 symbol *rSym = NULL;
9206 /* quick & easy case. */
9207 D(emitcode(";","genFarFarAssign (1 byte case)"););
9208 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9209 freeAsmop (right, NULL, ic, FALSE);
9210 /* now assign DPTR to result */
9212 aopOp(result, ic, FALSE, FALSE);
9214 aopPut(AOP(result), "a", 0);
9215 freeAsmop(result, NULL, ic, FALSE);
9219 /* See if we've got an underlying symbol to abuse. */
9220 if (IS_SYMOP(result) && OP_SYMBOL(result))
9222 if (IS_TRUE_SYMOP(result))
9224 rSym = OP_SYMBOL(result);
9226 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9228 rSym = OP_SYMBOL(result)->usl.spillLoc;
9232 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9234 /* We can use the '390 auto-toggle feature to good effect here. */
9236 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9237 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9238 emitcode ("mov", "dptr,#%s", rSym->rname);
9239 /* DP2 = result, DP1 = right, DP1 is current. */
9242 emitcode("movx", "a,@dptr");
9243 emitcode("movx", "@dptr,a");
9246 emitcode("inc", "dptr");
9247 emitcode("inc", "dptr");
9250 emitcode("mov", "dps, #0");
9251 freeAsmop (right, NULL, ic, FALSE);
9255 D (emitcode (";", "genFarFarAssign"););
9256 aopOp (result, ic, TRUE, TRUE);
9258 _startLazyDPSEvaluation ();
9262 aopPut (AOP (result),
9263 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9266 _endLazyDPSEvaluation ();
9267 freeAsmop (result, NULL, ic, FALSE);
9268 freeAsmop (right, NULL, ic, FALSE);
9272 /*-----------------------------------------------------------------*/
9273 /* genAssign - generate code for assignment */
9274 /*-----------------------------------------------------------------*/
9276 genAssign (iCode * ic)
9278 operand *result, *right;
9280 unsigned long lit = 0L;
9282 D (emitcode (";", "genAssign ");
9285 result = IC_RESULT (ic);
9286 right = IC_RIGHT (ic);
9288 /* if they are the same */
9289 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9292 aopOp (right, ic, FALSE, FALSE);
9294 emitcode (";", "genAssign: resultIsFar = %s",
9295 isOperandInFarSpace (result) ?
9298 /* special case both in far space */
9299 if ((AOP_TYPE (right) == AOP_DPTR ||
9300 AOP_TYPE (right) == AOP_DPTR2) &&
9301 /* IS_TRUE_SYMOP(result) && */
9302 isOperandInFarSpace (result))
9304 genFarFarAssign (result, right, ic);
9308 aopOp (result, ic, TRUE, FALSE);
9310 /* if they are the same registers */
9311 if (sameRegs (AOP (right), AOP (result)))
9314 /* if the result is a bit */
9315 if (AOP_TYPE (result) == AOP_CRY)
9318 /* if the right size is a literal then
9319 we know what the value is */
9320 if (AOP_TYPE (right) == AOP_LIT)
9322 if (((int) operandLitValue (right)))
9323 aopPut (AOP (result), one, 0);
9325 aopPut (AOP (result), zero, 0);
9329 /* the right is also a bit variable */
9330 if (AOP_TYPE (right) == AOP_CRY)
9332 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9333 aopPut (AOP (result), "c", 0);
9339 aopPut (AOP (result), "a", 0);
9343 /* bit variables done */
9345 size = AOP_SIZE (result);
9347 if (AOP_TYPE (right) == AOP_LIT)
9348 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9351 (AOP_TYPE (result) != AOP_REG) &&
9352 (AOP_TYPE (right) == AOP_LIT) &&
9353 !IS_FLOAT (operandType (right)))
9355 _startLazyDPSEvaluation ();
9356 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9358 aopPut (AOP (result),
9359 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9364 /* And now fill the rest with zeros. */
9367 emitcode ("clr", "a");
9371 aopPut (AOP (result), "a", offset++);
9373 _endLazyDPSEvaluation ();
9377 _startLazyDPSEvaluation ();
9380 aopPut (AOP (result),
9381 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9385 _endLazyDPSEvaluation ();
9389 freeAsmop (right, NULL, ic, FALSE);
9390 freeAsmop (result, NULL, ic, TRUE);
9393 /*-----------------------------------------------------------------*/
9394 /* genJumpTab - generates code for jump table */
9395 /*-----------------------------------------------------------------*/
9397 genJumpTab (iCode * ic)
9402 D (emitcode (";", "genJumpTab ");
9405 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9406 /* get the condition into accumulator */
9407 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9409 /* multiply by four! */
9410 emitcode ("add", "a,acc");
9411 emitcode ("add", "a,acc");
9412 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9414 jtab = newiTempLabel (NULL);
9415 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9416 emitcode ("jmp", "@a+dptr");
9417 emitcode ("", "%05d$:", jtab->key + 100);
9418 /* now generate the jump labels */
9419 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9420 jtab = setNextItem (IC_JTLABELS (ic)))
9421 emitcode ("ljmp", "%05d$", jtab->key + 100);
9425 /*-----------------------------------------------------------------*/
9426 /* genCast - gen code for casting */
9427 /*-----------------------------------------------------------------*/
9429 genCast (iCode * ic)
9431 operand *result = IC_RESULT (ic);
9432 sym_link *ctype = operandType (IC_LEFT (ic));
9433 sym_link *rtype = operandType (IC_RIGHT (ic));
9434 operand *right = IC_RIGHT (ic);
9437 D (emitcode (";", "genCast ");
9440 /* if they are equivalent then do nothing */
9441 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9444 aopOp (right, ic, FALSE, FALSE);
9445 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9447 /* if the result is a bit */
9448 if (AOP_TYPE (result) == AOP_CRY)
9450 /* if the right size is a literal then
9451 we know what the value is */
9452 if (AOP_TYPE (right) == AOP_LIT)
9454 if (((int) operandLitValue (right)))
9455 aopPut (AOP (result), one, 0);
9457 aopPut (AOP (result), zero, 0);
9462 /* the right is also a bit variable */
9463 if (AOP_TYPE (right) == AOP_CRY)
9465 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9466 aopPut (AOP (result), "c", 0);
9472 aopPut (AOP (result), "a", 0);
9476 /* if they are the same size : or less */
9477 if (AOP_SIZE (result) <= AOP_SIZE (right))
9480 /* if they are in the same place */
9481 if (sameRegs (AOP (right), AOP (result)))
9484 /* if they in different places then copy */
9485 size = AOP_SIZE (result);
9487 _startLazyDPSEvaluation ();
9490 aopPut (AOP (result),
9491 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9495 _endLazyDPSEvaluation ();
9500 /* if the result is of type pointer */
9505 sym_link *type = operandType (right);
9507 /* pointer to generic pointer */
9508 if (IS_GENPTR (ctype))
9514 p_type = DCL_TYPE (type);
9518 #if OLD_CAST_BEHAVIOR
9519 /* KV: we are converting a non-pointer type to
9520 * a generic pointer. This (ifdef'd out) code
9521 * says that the resulting generic pointer
9522 * should have the same class as the storage
9523 * location of the non-pointer variable.
9525 * For example, converting an int (which happens
9526 * to be stored in DATA space) to a pointer results
9527 * in a DATA generic pointer; if the original int
9528 * in XDATA space, so will be the resulting pointer.
9530 * I don't like that behavior, and thus this change:
9531 * all such conversions will be forced to XDATA and
9532 * throw a warning. If you want some non-XDATA
9533 * type, or you want to suppress the warning, you
9534 * must go through an intermediate cast, like so:
9536 * char _generic *gp = (char _xdata *)(intVar);
9538 sym_link *etype = getSpec (type);
9540 /* we have to go by the storage class */
9541 if (SPEC_OCLS (etype) != generic)
9543 p_type = PTR_TYPE (SPEC_OCLS (etype));
9548 /* Converting unknown class (i.e. register variable)
9549 * to generic pointer. This is not good, but
9550 * we'll make a guess (and throw a warning).
9553 werror (W_INT_TO_GEN_PTR_CAST);
9557 /* the first two bytes are known */
9558 size = GPTRSIZE - 1;
9560 _startLazyDPSEvaluation ();
9563 aopPut (AOP (result),
9564 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9568 _endLazyDPSEvaluation ();
9570 /* the last byte depending on type */
9588 /* this should never happen */
9589 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9590 "got unknown pointer type");
9593 aopPut (AOP (result), l, GPTRSIZE - 1);
9597 /* just copy the pointers */
9598 size = AOP_SIZE (result);
9600 _startLazyDPSEvaluation ();
9603 aopPut (AOP (result),
9604 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9608 _endLazyDPSEvaluation ();
9612 /* so we now know that the size of destination is greater
9613 than the size of the source */
9614 /* we move to result for the size of source */
9615 size = AOP_SIZE (right);
9617 _startLazyDPSEvaluation ();
9620 aopPut (AOP (result),
9621 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9625 _endLazyDPSEvaluation ();
9627 /* now depending on the sign of the source && destination */
9628 size = AOP_SIZE (result) - AOP_SIZE (right);
9629 /* if unsigned or not an integral type */
9630 /* also, if the source is a bit, we don't need to sign extend, because
9631 * it can't possibly have set the sign bit.
9633 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9637 aopPut (AOP (result), zero, offset++);
9642 /* we need to extend the sign :{ */
9643 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9644 FALSE, FALSE, TRUE);
9646 emitcode ("rlc", "a");
9647 emitcode ("subb", "a,acc");
9649 aopPut (AOP (result), "a", offset++);
9652 /* we are done hurray !!!! */
9655 freeAsmop (right, NULL, ic, TRUE);
9656 freeAsmop (result, NULL, ic, TRUE);
9660 /*-----------------------------------------------------------------*/
9661 /* genDjnz - generate decrement & jump if not zero instrucion */
9662 /*-----------------------------------------------------------------*/
9664 genDjnz (iCode * ic, iCode * ifx)
9670 /* if the if condition has a false label
9671 then we cannot save */
9675 /* if the minus is not of the form
9677 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9678 !IS_OP_LITERAL (IC_RIGHT (ic)))
9681 if (operandLitValue (IC_RIGHT (ic)) != 1)
9684 /* if the size of this greater than one then no
9686 if (getSize (operandType (IC_RESULT (ic))) > 1)
9689 /* otherwise we can save BIG */
9690 D(emitcode(";", "genDjnz"););
9692 lbl = newiTempLabel (NULL);
9693 lbl1 = newiTempLabel (NULL);
9695 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9697 if (AOP_NEEDSACC(IC_RESULT(ic)))
9699 /* If the result is accessed indirectly via
9700 * the accumulator, we must explicitly write
9701 * it back after the decrement.
9703 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9705 if (strcmp(rByte, "a"))
9707 /* Something is hopelessly wrong */
9708 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9709 __FILE__, __LINE__);
9710 /* We can just give up; the generated code will be inefficient,
9713 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9716 emitcode ("dec", "%s", rByte);
9717 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9718 emitcode ("jnz", "%05d$", lbl->key + 100);
9720 else if (IS_AOP_PREG (IC_RESULT (ic)))
9722 emitcode ("dec", "%s",
9723 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9724 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9725 emitcode ("jnz", "%05d$", lbl->key + 100);
9729 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9732 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9733 emitcode ("", "%05d$:", lbl->key + 100);
9734 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9735 emitcode ("", "%05d$:", lbl1->key + 100);
9737 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9742 /*-----------------------------------------------------------------*/
9743 /* genReceive - generate code for a receive iCode */
9744 /*-----------------------------------------------------------------*/
9746 genReceive (iCode * ic)
9749 D (emitcode (";", "genReceive ");
9752 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9753 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9754 IS_TRUE_SYMOP (IC_RESULT (ic))))
9756 int size = getSize (operandType (IC_RESULT (ic)));
9757 int offset = fReturnSizeDS390 - size;
9760 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9761 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9764 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9765 size = AOP_SIZE (IC_RESULT (ic));
9769 emitcode ("pop", "acc");
9770 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9777 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9779 assignResultValue (IC_RESULT (ic));
9782 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9785 /*-----------------------------------------------------------------*/
9786 /* gen390Code - generate code for Dallas 390 based controllers */
9787 /*-----------------------------------------------------------------*/
9789 gen390Code (iCode * lic)
9794 lineHead = lineCurr = NULL;
9798 /* print the allocation information */
9800 printAllocInfo (currFunc, codeOutFile);
9802 /* if debug information required */
9803 if (options.debug && currFunc)
9805 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9807 if (IS_STATIC (currFunc->etype))
9808 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9810 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9813 /* stack pointer name */
9814 if (options.useXstack)
9820 for (ic = lic; ic; ic = ic->next)
9823 if (cln != ic->lineno)
9828 emitcode ("", "C$%s$%d$%d$%d ==.",
9829 FileBaseName (ic->filename), ic->lineno,
9830 ic->level, ic->block);
9833 emitcode (";", "%s %d", ic->filename, ic->lineno);
9836 /* if the result is marked as
9837 spilt and rematerializable or code for
9838 this has already been generated then
9840 if (resultRemat (ic) || ic->generated)
9843 /* depending on the operation */
9863 /* IPOP happens only when trying to restore a
9864 spilt live range, if there is an ifx statement
9865 following this pop then the if statement might
9866 be using some of the registers being popped which
9867 would destory the contents of the register so
9868 we need to check for this condition and handle it */
9870 ic->next->op == IFX &&
9871 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9872 genIfx (ic->next, ic);
9890 genEndFunction (ic);
9910 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9927 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9931 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9938 /* note these two are xlated by algebraic equivalence
9939 during parsing SDCC.y */
9940 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9941 "got '>=' or '<=' shouldn't have come here");
9945 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9957 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9961 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9965 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9992 case GET_VALUE_AT_ADDRESS:
9997 if (POINTER_SET (ic))
10024 addSet (&_G.sendSet, ic);
10033 /* now we are ready to call the
10034 peep hole optimizer */
10035 if (!options.nopeep)
10036 peepHole (&lineHead);
10038 /* now do the actual printing */
10039 printLine (lineHead, codeOutFile);