1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #define BETTER_LITERAL_SHIFT
53 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
66 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
67 static char *fReturn[] =
68 {"dpl", "dph", "dpx", "b", "a"};
69 static char *accUse[] =
72 static short rbank = -1;
86 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
93 #define MOVA(x) { char *_mova_tmp = strdup(x); \
94 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96 emitcode("mov","a,%s",_mova_tmp); \
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
122 /*-----------------------------------------------------------------*/
123 /* emitcode - writes the code into a file : for now it is simple */
124 /*-----------------------------------------------------------------*/
126 emitcode (char *inst, char *fmt,...)
129 char lb[INITIAL_INLINEASM];
137 sprintf (lb, "%s\t", inst);
139 sprintf (lb, "%s", inst);
140 vsprintf (lb + (strlen (lb)), fmt, ap);
143 vsprintf (lb, fmt, ap);
145 while (isspace (*lbp))
149 lineCurr = (lineCurr ?
150 connectLine (lineCurr, newLineNode (lb)) :
151 (lineHead = newLineNode (lb)));
152 lineCurr->isInline = _G.inLine;
153 lineCurr->isDebug = _G.debugLine;
157 /*-----------------------------------------------------------------*/
158 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
159 /*-----------------------------------------------------------------*/
161 getFreePtr (iCode * ic, asmop ** aopp, bool result)
163 bool r0iu = FALSE, r1iu = FALSE;
164 bool r0ou = FALSE, r1ou = FALSE;
166 /* the logic: if r0 & r1 used in the instruction
167 then we are in trouble otherwise */
169 /* first check if r0 & r1 are used by this
170 instruction, in which case we are in trouble */
171 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
172 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
177 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
178 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
180 /* if no usage of r0 then return it */
183 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
184 (*aopp)->type = AOP_R0;
186 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
189 /* if no usage of r1 then return it */
192 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
193 (*aopp)->type = AOP_R1;
195 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
198 /* now we know they both have usage */
199 /* if r0 not used in this instruction */
202 /* push it if not already pushed */
205 emitcode ("push", "%s",
206 ds390_regWithIdx (R0_IDX)->dname);
210 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
211 (*aopp)->type = AOP_R0;
213 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
216 /* if r1 not used then */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 ds390_regWithIdx (R1_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
229 (*aopp)->type = AOP_R1;
230 return ds390_regWithIdx (R1_IDX);
234 /* I said end of world but not quite end of world yet */
235 /* if this is a result then we can push it on the stack */
238 (*aopp)->type = AOP_STK;
242 /* other wise this is true end of the world */
243 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
244 "getFreePtr should never reach here");
248 /*-----------------------------------------------------------------*/
249 /* newAsmop - creates a new asmOp */
250 /*-----------------------------------------------------------------*/
252 newAsmop (short type)
256 aop = Safe_calloc (1, sizeof (asmop));
261 static int _currentDPS; /* Current processor DPS. */
262 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
263 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
265 /*-----------------------------------------------------------------*/
266 /* genSetDPTR: generate code to select which DPTR is in use (zero */
267 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
268 /* alternate DPTR (DPL1/DPH1/DPX1). */
269 /*-----------------------------------------------------------------*/
274 /* If we are doing lazy evaluation, simply note the desired
275 * change, but don't emit any code yet.
285 emitcode ("mov", "dps, #0x00");
289 emitcode ("mov", "dps, #0x01");
293 /*-----------------------------------------------------------------*/
294 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
296 /* Any code that operates on DPTR (NB: not on the individual */
297 /* components, like DPH) *must* call _flushLazyDPS() before using */
298 /* DPTR within a lazy DPS evaluation block. */
300 /* Note that aopPut and aopGet already contain the proper calls to */
301 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
302 /* DPS evaluation block. */
304 /* Also, _flushLazyDPS must be called before any flow control */
305 /* operations that could potentially branch out of the block. */
307 /* Lazy DPS evaluation is simply an optimization (though an */
308 /* important one), so if in doubt, leave it out. */
309 /*-----------------------------------------------------------------*/
311 _startLazyDPSEvaluation (void)
315 #ifdef BETTER_LITERAL_SHIFT
322 /*-----------------------------------------------------------------*/
323 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
324 /* desired one. Call before using DPTR within a lazy DPS evaluation */
326 /*-----------------------------------------------------------------*/
336 if (_desiredDPS != _currentDPS)
340 emitcode ("inc", "dps");
344 emitcode ("dec", "dps");
346 _currentDPS = _desiredDPS;
350 /*-----------------------------------------------------------------*/
351 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
353 /* Forces us back to the safe state (standard DPTR selected). */
354 /*-----------------------------------------------------------------*/
356 _endLazyDPSEvaluation (void)
358 #ifdef BETTER_LITERAL_SHIFT
377 /*-----------------------------------------------------------------*/
378 /* pointerCode - returns the code for a pointer type */
379 /*-----------------------------------------------------------------*/
381 pointerCode (sym_link * etype)
384 return PTR_TYPE (SPEC_OCLS (etype));
388 /*-----------------------------------------------------------------*/
389 /* aopForSym - for a true symbol */
390 /*-----------------------------------------------------------------*/
392 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
395 memmap *space = SPEC_OCLS (sym->etype);
397 /* if already has one */
401 /* assign depending on the storage class */
402 /* if it is on the stack or indirectly addressable */
403 /* space we need to assign either r0 or r1 to it */
404 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
406 sym->aop = aop = newAsmop (0);
407 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
408 aop->size = getSize (sym->type);
410 /* now assign the address of the variable to
411 the pointer register */
412 if (aop->type != AOP_STK)
418 emitcode ("push", "acc");
420 emitcode ("mov", "a,_bp");
421 emitcode ("add", "a,#0x%02x",
423 ((char) (sym->stack - _G.nRegsSaved)) :
424 ((char) sym->stack)) & 0xff);
425 emitcode ("mov", "%s,a",
426 aop->aopu.aop_ptr->name);
429 emitcode ("pop", "acc");
432 emitcode ("mov", "%s,#%s",
433 aop->aopu.aop_ptr->name,
435 aop->paged = space->paged;
438 aop->aopu.aop_stk = sym->stack;
442 if (sym->onStack && options.stack10bit)
444 /* It's on the 10 bit stack, which is located in
449 emitcode ("push", "acc");
451 emitcode ("mov", "a,_bp");
452 emitcode ("add", "a,#0x%02x",
454 ((char) (sym->stack - _G.nRegsSaved)) :
455 ((char) sym->stack)) & 0xff);
459 emitcode ("mov", "dpx1,#0x40");
460 emitcode ("mov", "dph1,#0x00");
461 emitcode ("mov", "dpl1, a");
465 emitcode ("mov", "dpx,#0x40");
466 emitcode ("mov", "dph,#0x00");
467 emitcode ("mov", "dpl, a");
471 emitcode ("pop", "acc");
473 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
474 aop->size = getSize (sym->type);
478 /* if in bit space */
479 if (IN_BITSPACE (space))
481 sym->aop = aop = newAsmop (AOP_CRY);
482 aop->aopu.aop_dir = sym->rname;
483 aop->size = getSize (sym->type);
486 /* if it is in direct space */
487 if (IN_DIRSPACE (space))
489 sym->aop = aop = newAsmop (AOP_DIR);
490 aop->aopu.aop_dir = sym->rname;
491 aop->size = getSize (sym->type);
495 /* special case for a function */
496 if (IS_FUNC (sym->type))
498 sym->aop = aop = newAsmop (AOP_IMMD);
499 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
500 strcpy (aop->aopu.aop_immd, sym->rname);
501 aop->size = FPTRSIZE;
505 /* only remaining is far space */
506 /* in which case DPTR gets the address */
507 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
512 emitcode ("mov", "dptr,#%s", sym->rname);
517 emitcode ("mov", "dptr,#%s", sym->rname);
519 aop->size = getSize (sym->type);
521 /* if it is in code space */
522 if (IN_CODESPACE (space))
528 /*-----------------------------------------------------------------*/
529 /* aopForRemat - rematerialzes an object */
530 /*-----------------------------------------------------------------*/
532 aopForRemat (symbol * sym)
534 iCode *ic = sym->rematiCode;
535 asmop *aop = newAsmop (AOP_IMMD);
542 val += (int) operandLitValue (IC_RIGHT (ic));
543 else if (ic->op == '-')
544 val -= (int) operandLitValue (IC_RIGHT (ic));
548 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
552 sprintf (buffer, "(%s %c 0x%04x)",
553 OP_SYMBOL (IC_LEFT (ic))->rname,
554 val >= 0 ? '+' : '-',
557 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
559 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
560 strcpy (aop->aopu.aop_immd, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
658 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
665 if (aop1->type != AOP_REG ||
666 aop2->type != AOP_REG)
669 if (aop1->size != aop2->size)
672 for (i = 0; i < aop1->size; i++)
673 if (aop1->aopu.aop_reg[i] !=
674 aop2->aopu.aop_reg[i])
680 /*-----------------------------------------------------------------*/
681 /* aopOp - allocates an asmop for an operand : */
682 /*-----------------------------------------------------------------*/
684 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
693 /* if this a literal */
694 if (IS_OP_LITERAL (op))
696 op->aop = aop = newAsmop (AOP_LIT);
697 aop->aopu.aop_lit = op->operand.valOperand;
698 aop->size = getSize (operandType (op));
702 /* if already has a asmop then continue */
706 /* if the underlying symbol has a aop */
707 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
709 op->aop = OP_SYMBOL (op)->aop;
713 /* if this is a true symbol */
714 if (IS_TRUE_SYMOP (op))
716 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
720 /* this is a temporary : this has
726 e) can be a return use only */
728 sym = OP_SYMBOL (op);
731 /* if the type is a conditional */
732 if (sym->regType == REG_CND)
734 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
739 /* if it is spilt then two situations
741 b) has a spill location */
742 if (sym->isspilt || sym->nRegs == 0)
745 /* rematerialize it NOW */
748 sym->aop = op->aop = aop =
750 aop->size = getSize (sym->type);
757 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
758 aop->size = getSize (sym->type);
759 for (i = 0; i < 2; i++)
760 aop->aopu.aop_str[i] = accUse[i];
770 /* a AOP_STR uses DPTR, but DPTR is already in use;
773 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
776 aop = op->aop = sym->aop = newAsmop (AOP_STR);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < (int) fReturnSizeDS390; i++)
779 aop->aopu.aop_str[i] = fReturn[i];
783 /* else spill location */
784 sym->aop = op->aop = aop =
785 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
786 aop->size = getSize (sym->type);
790 /* must be in a register */
791 sym->aop = op->aop = aop = newAsmop (AOP_REG);
792 aop->size = sym->nRegs;
793 for (i = 0; i < sym->nRegs; i++)
794 aop->aopu.aop_reg[i] = sym->regs[i];
797 /*-----------------------------------------------------------------*/
798 /* freeAsmop - free up the asmop given to an operand */
799 /*----------------------------------------------------------------*/
801 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
818 /* depending on the asmop type only three cases need work AOP_RO
819 , AOP_R1 && AOP_STK */
827 emitcode ("pop", "ar0");
831 bitVectUnSetBit (ic->rUsed, R0_IDX);
839 emitcode ("pop", "ar1");
843 bitVectUnSetBit (ic->rUsed, R1_IDX);
849 int stk = aop->aopu.aop_stk + aop->size;
850 bitVectUnSetBit (ic->rUsed, R0_IDX);
851 bitVectUnSetBit (ic->rUsed, R1_IDX);
853 getFreePtr (ic, &aop, FALSE);
855 if (options.stack10bit)
857 /* I'm not sure what to do here yet... */
860 "*** Warning: probably generating bad code for "
861 "10 bit stack mode.\n");
866 emitcode ("mov", "a,_bp");
867 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
868 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
872 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
877 emitcode ("pop", "acc");
878 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
881 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
884 freeAsmop (op, NULL, ic, TRUE);
887 emitcode ("pop", "ar0");
893 emitcode ("pop", "ar1");
900 /* all other cases just dealloc */
906 OP_SYMBOL (op)->aop = NULL;
907 /* if the symbol has a spill */
909 SPIL_LOC (op)->aop = NULL;
914 /*------------------------------------------------------------------*/
915 /* aopGet - for fetching value of the aop */
917 /* Set canClobberACC if you are sure it is OK to clobber the value */
918 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
919 /* just less efficient. */
920 /*------------------------------------------------------------------*/
932 /* offset is greater than
934 if (offset > (aop->size - 1) &&
935 aop->type != AOP_LIT)
938 /* depending on type */
944 /* if we need to increment it */
945 while (offset > aop->coff)
947 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
951 while (offset < aop->coff)
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
960 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
961 return (dname ? "acc" : "a");
963 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
964 rs = Safe_calloc (1, strlen (s) + 1);
971 if (aop->type == AOP_DPTR2)
976 emitcode ("xch", "a, %s", DP2_RESULT_REG);
982 while (offset > aop->coff)
984 emitcode ("inc", "dptr");
988 while (offset < aop->coff)
990 emitcode ("lcall", "__decdptr");
997 emitcode ("clr", "a");
998 emitcode ("movc", "a,@a+dptr");
1002 emitcode ("movx", "a,@dptr");
1005 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011 return DP2_RESULT_REG;
1014 return (dname ? "acc" : "a");
1018 sprintf (s, "#%s", aop->aopu.aop_immd);
1020 sprintf (s, "#(%s >> %d)",
1025 aop->aopu.aop_immd);
1026 rs = Safe_calloc (1, strlen (s) + 1);
1032 sprintf (s, "(%s + %d)",
1036 sprintf (s, "%s", aop->aopu.aop_dir);
1037 rs = Safe_calloc (1, strlen (s) + 1);
1043 return aop->aopu.aop_reg[offset]->dname;
1045 return aop->aopu.aop_reg[offset]->name;
1048 emitcode ("clr", "a");
1049 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1050 emitcode ("rlc", "a");
1051 return (dname ? "acc" : "a");
1054 if (!offset && dname)
1056 return aop->aopu.aop_str[offset];
1059 return aopLiteral (aop->aopu.aop_lit, offset);
1063 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1067 return aop->aopu.aop_str[offset];
1071 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1072 "aopget got unsupported aop->type");
1075 /*-----------------------------------------------------------------*/
1076 /* aopPut - puts a string for a aop */
1077 /*-----------------------------------------------------------------*/
1079 aopPut (asmop * aop, char *s, int offset)
1083 if (aop->size && offset > (aop->size - 1))
1085 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1086 "aopPut got offset > aop->size");
1090 /* will assign value to value */
1091 /* depending on where it is ofcourse */
1096 sprintf (d, "(%s + %d)",
1097 aop->aopu.aop_dir, offset);
1099 sprintf (d, "%s", aop->aopu.aop_dir);
1102 emitcode ("mov", "%s,%s", d, s);
1107 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1108 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1111 strcmp (s, "r0") == 0 ||
1112 strcmp (s, "r1") == 0 ||
1113 strcmp (s, "r2") == 0 ||
1114 strcmp (s, "r3") == 0 ||
1115 strcmp (s, "r4") == 0 ||
1116 strcmp (s, "r5") == 0 ||
1117 strcmp (s, "r6") == 0 ||
1118 strcmp (s, "r7") == 0)
1119 emitcode ("mov", "%s,%s",
1120 aop->aopu.aop_reg[offset]->dname, s);
1122 emitcode ("mov", "%s,%s",
1123 aop->aopu.aop_reg[offset]->name, s);
1130 if (aop->type == AOP_DPTR2)
1138 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139 "aopPut writting to code space");
1143 while (offset > aop->coff)
1146 emitcode ("inc", "dptr");
1149 while (offset < aop->coff)
1152 emitcode ("lcall", "__decdptr");
1157 /* if not in accumulater */
1160 emitcode ("movx", "@dptr,a");
1162 if (aop->type == AOP_DPTR2)
1170 while (offset > aop->coff)
1173 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1175 while (offset < aop->coff)
1178 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1185 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1191 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1193 else if (strcmp (s, "r0") == 0 ||
1194 strcmp (s, "r1") == 0 ||
1195 strcmp (s, "r2") == 0 ||
1196 strcmp (s, "r3") == 0 ||
1197 strcmp (s, "r4") == 0 ||
1198 strcmp (s, "r5") == 0 ||
1199 strcmp (s, "r6") == 0 ||
1200 strcmp (s, "r7") == 0)
1203 sprintf (buffer, "a%s", s);
1204 emitcode ("mov", "@%s,%s",
1205 aop->aopu.aop_ptr->name, buffer);
1208 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1213 if (strcmp (s, "a") == 0)
1214 emitcode ("push", "acc");
1216 emitcode ("push", "%s", s);
1221 /* if bit variable */
1222 if (!aop->aopu.aop_dir)
1224 emitcode ("clr", "a");
1225 emitcode ("rlc", "a");
1230 emitcode ("clr", "%s", aop->aopu.aop_dir);
1232 emitcode ("setb", "%s", aop->aopu.aop_dir);
1233 else if (!strcmp (s, "c"))
1234 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237 if (strcmp (s, "a"))
1242 symbol *lbl = newiTempLabel (NULL);
1243 emitcode ("clr", "c");
1244 emitcode ("jz", "%05d$", lbl->key + 100);
1245 emitcode ("cpl", "c");
1246 emitcode ("", "%05d$:", lbl->key + 100);
1247 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1255 if (strcmp (aop->aopu.aop_str[offset], s))
1256 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1261 if (!offset && (strcmp (s, "acc") == 0))
1264 if (strcmp (aop->aopu.aop_str[offset], s))
1265 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1270 "aopPut got unsupported aop->type");
1277 /*--------------------------------------------------------------------*/
1278 /* reAdjustPreg - points a register back to where it should (coff==0) */
1279 /*--------------------------------------------------------------------*/
1281 reAdjustPreg (asmop * aop)
1283 if ((aop->coff==0) || (aop->size <= 1)) {
1292 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1296 if (aop->type == AOP_DPTR2)
1303 emitcode ("lcall", "__decdptr");
1306 if (aop->type == AOP_DPTR2)
1316 #define AOP(op) op->aop
1317 #define AOP_TYPE(op) AOP(op)->type
1318 #define AOP_SIZE(op) AOP(op)->size
1319 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1320 AOP_TYPE(x) == AOP_R0))
1322 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1323 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1326 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1327 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1328 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1330 /* Workaround for DS80C390 bug: div ab may return bogus results
1331 * if A is accessed in instruction immediately before the div.
1333 * Will be fixed in B4 rev of processor, Dallas claims.
1336 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1337 if (!AOP_NEEDSACC(RIGHT)) \
1339 /* We can load A first, then B, since \
1340 * B (the RIGHT operand) won't clobber A, \
1341 * thus avoiding touching A right before the div. \
1343 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1344 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1346 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1350 /* Just stuff in a nop after loading A. */ \
1351 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1352 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1354 emitcode("nop", "; workaround for DS80C390 div bug."); \
1357 /*-----------------------------------------------------------------*/
1358 /* genNotFloat - generates not for float operations */
1359 /*-----------------------------------------------------------------*/
1361 genNotFloat (operand * op, operand * res)
1367 D (emitcode (";", "genNotFloat ");
1370 /* we will put 127 in the first byte of
1372 aopPut (AOP (res), "#127", 0);
1373 size = AOP_SIZE (op) - 1;
1376 _startLazyDPSEvaluation ();
1377 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1382 emitcode ("orl", "a,%s",
1384 offset++, FALSE, FALSE, FALSE));
1386 _endLazyDPSEvaluation ();
1388 tlbl = newiTempLabel (NULL);
1389 aopPut (res->aop, one, 1);
1390 emitcode ("jz", "%05d$", (tlbl->key + 100));
1391 aopPut (res->aop, zero, 1);
1392 emitcode ("", "%05d$:", (tlbl->key + 100));
1394 size = res->aop->size - 2;
1396 /* put zeros in the rest */
1398 aopPut (res->aop, zero, offset++);
1401 /*-----------------------------------------------------------------*/
1402 /* opIsGptr: returns non-zero if the passed operand is */
1403 /* a generic pointer type. */
1404 /*-----------------------------------------------------------------*/
1406 opIsGptr (operand * op)
1408 sym_link *type = operandType (op);
1410 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1417 /*-----------------------------------------------------------------*/
1418 /* getDataSize - get the operand data size */
1419 /*-----------------------------------------------------------------*/
1421 getDataSize (operand * op)
1424 size = AOP_SIZE (op);
1425 if (size == GPTRSIZE)
1427 sym_link *type = operandType (op);
1428 if (IS_GENPTR (type))
1430 /* generic pointer; arithmetic operations
1431 * should ignore the high byte (pointer type).
1439 /*-----------------------------------------------------------------*/
1440 /* outAcc - output Acc */
1441 /*-----------------------------------------------------------------*/
1443 outAcc (operand * result)
1446 size = getDataSize (result);
1449 aopPut (AOP (result), "a", 0);
1452 /* unsigned or positive */
1455 aopPut (AOP (result), zero, offset++);
1460 /*-----------------------------------------------------------------*/
1461 /* outBitC - output a bit C */
1462 /*-----------------------------------------------------------------*/
1464 outBitC (operand * result)
1466 /* if the result is bit */
1467 if (AOP_TYPE (result) == AOP_CRY)
1469 aopPut (AOP (result), "c", 0);
1473 emitcode ("clr", "a");
1474 emitcode ("rlc", "a");
1479 /*-----------------------------------------------------------------*/
1480 /* toBoolean - emit code for orl a,operator(sizeop) */
1481 /*-----------------------------------------------------------------*/
1483 toBoolean (operand * oper)
1485 int size = AOP_SIZE (oper) - 1;
1489 /* The generic part of a generic pointer should
1490 * not participate in it's truth value.
1492 * i.e. 0x10000000 is zero.
1494 if (opIsGptr (oper))
1496 D (emitcode (";", "toBoolean: generic ptr special case.");
1501 _startLazyDPSEvaluation ();
1502 if (AOP_NEEDSACC (oper) && size)
1505 emitcode ("push", "b");
1506 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1510 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1516 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1520 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1523 _endLazyDPSEvaluation ();
1527 emitcode ("mov", "a,b");
1528 emitcode ("pop", "b");
1533 /*-----------------------------------------------------------------*/
1534 /* genNot - generate code for ! operation */
1535 /*-----------------------------------------------------------------*/
1540 sym_link *optype = operandType (IC_LEFT (ic));
1542 D (emitcode (";", "genNot ");
1545 /* assign asmOps to operand & result */
1546 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1547 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1549 /* if in bit space then a special case */
1550 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1552 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1553 emitcode ("cpl", "c");
1554 outBitC (IC_RESULT (ic));
1558 /* if type float then do float */
1559 if (IS_FLOAT (optype))
1561 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1565 toBoolean (IC_LEFT (ic));
1567 tlbl = newiTempLabel (NULL);
1568 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1569 emitcode ("", "%05d$:", tlbl->key + 100);
1570 outBitC (IC_RESULT (ic));
1573 /* release the aops */
1574 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1575 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1579 /*-----------------------------------------------------------------*/
1580 /* genCpl - generate code for complement */
1581 /*-----------------------------------------------------------------*/
1588 D (emitcode (";", "genCpl ");
1592 /* assign asmOps to operand & result */
1593 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1594 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1596 /* if both are in bit space then
1598 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1599 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1602 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1603 emitcode ("cpl", "c");
1604 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1608 size = AOP_SIZE (IC_RESULT (ic));
1609 _startLazyDPSEvaluation ();
1612 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1614 emitcode ("cpl", "a");
1615 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1617 _endLazyDPSEvaluation ();
1621 /* release the aops */
1622 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1623 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* genUminusFloat - unary minus for floating points */
1628 /*-----------------------------------------------------------------*/
1630 genUminusFloat (operand * op, operand * result)
1632 int size, offset = 0;
1634 /* for this we just need to flip the
1635 first it then copy the rest in place */
1636 D (emitcode (";", "genUminusFloat");
1639 _startLazyDPSEvaluation ();
1640 size = AOP_SIZE (op) - 1;
1641 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1644 emitcode ("cpl", "acc.7");
1645 aopPut (AOP (result), "a", 3);
1649 aopPut (AOP (result),
1650 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1654 _endLazyDPSEvaluation ();
1657 /*-----------------------------------------------------------------*/
1658 /* genUminus - unary minus code generation */
1659 /*-----------------------------------------------------------------*/
1661 genUminus (iCode * ic)
1664 sym_link *optype, *rtype;
1666 D (emitcode (";", "genUminus ");
1671 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1672 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1674 /* if both in bit space then special
1676 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1677 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1680 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1681 emitcode ("cpl", "c");
1682 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1686 optype = operandType (IC_LEFT (ic));
1687 rtype = operandType (IC_RESULT (ic));
1689 /* if float then do float stuff */
1690 if (IS_FLOAT (optype))
1692 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1696 /* otherwise subtract from zero */
1697 size = AOP_SIZE (IC_LEFT (ic));
1699 _startLazyDPSEvaluation ();
1702 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1703 if (!strcmp (l, "a"))
1707 emitcode ("cpl", "a");
1708 emitcode ("addc", "a,#0");
1714 emitcode ("clr", "a");
1715 emitcode ("subb", "a,%s", l);
1717 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1719 _endLazyDPSEvaluation ();
1721 /* if any remaining bytes in the result */
1722 /* we just need to propagate the sign */
1723 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1725 emitcode ("rlc", "a");
1726 emitcode ("subb", "a,acc");
1728 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1732 /* release the aops */
1733 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1734 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1737 /*-----------------------------------------------------------------*/
1738 /* saveRegisters - will look for a call and save the registers */
1739 /*-----------------------------------------------------------------*/
1741 saveRegisters (iCode * lic)
1749 for (ic = lic; ic; ic = ic->next)
1750 if (ic->op == CALL || ic->op == PCALL)
1755 fprintf (stderr, "found parameter push with no function call\n");
1759 /* if the registers have been saved already then
1761 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
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 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3957 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3959 lbl=newiTempLabel(NULL);
3960 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3961 // left side is negative, 8-bit two's complement, this fails for -128
3962 emitcode ("setb", "F0"); // set sign flag
3963 emitcode ("cpl", "a");
3964 emitcode ("inc", "a");
3966 emitcode ("", "%05d$:", lbl->key+100);
3967 emitcode ("xch", "a,b");
3970 if (AOP_TYPE(right)==AOP_LIT) {
3971 /* AND literal negative */
3972 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3973 // two's complement for literal<0
3974 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3975 emitcode ("cpl", "a");
3976 emitcode ("inc", "a");
3979 lbl=newiTempLabel(NULL);
3980 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3981 // right side is negative, 8-bit two's complement
3982 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3983 emitcode ("cpl", "a");
3984 emitcode ("inc", "a");
3985 emitcode ("", "%05d$:", lbl->key+100);
3987 emitcode ("mul", "ab");
3989 lbl=newiTempLabel(NULL);
3990 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3991 // only ONE op was negative, we have to do a 8/16-bit two's complement
3992 emitcode ("cpl", "a"); // lsb
3994 emitcode ("inc", "a");
3996 emitcode ("add", "a,#1");
3997 emitcode ("xch", "a,b");
3998 emitcode ("cpl", "a"); // msb
3999 emitcode ("addc", "a,#0");
4000 emitcode ("xch", "a,b");
4003 emitcode ("", "%05d$:", lbl->key+100);
4004 aopPut (AOP (result), "a", 0);
4006 aopPut (AOP (result), "b", 1);
4010 /*-----------------------------------------------------------------*/
4011 /* genMult - generates code for multiplication */
4012 /*-----------------------------------------------------------------*/
4014 genMult (iCode * ic)
4016 operand *left = IC_LEFT (ic);
4017 operand *right = IC_RIGHT (ic);
4018 operand *result = IC_RESULT (ic);
4020 D (emitcode (";", "genMult "););
4022 /* assign the amsops */
4025 /* special cases first */
4027 if (AOP_TYPE (left) == AOP_CRY &&
4028 AOP_TYPE (right) == AOP_CRY)
4030 genMultbits (left, right, result);
4034 /* if both are of size == 1 */
4035 if (AOP_SIZE (left) == 1 &&
4036 AOP_SIZE (right) == 1)
4038 genMultOneByte (left, right, result);
4042 /* should have been converted to function call */
4046 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4047 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4048 freeAsmop (result, NULL, ic, TRUE);
4051 /*-----------------------------------------------------------------*/
4052 /* genDivbits :- division of bits */
4053 /*-----------------------------------------------------------------*/
4055 genDivbits (operand * left,
4062 /* the result must be bit */
4063 LOAD_AB_FOR_DIV (left, right, l);
4064 emitcode ("div", "ab");
4065 emitcode ("rrc", "a");
4066 aopPut (AOP (result), "c", 0);
4069 /*-----------------------------------------------------------------*/
4070 /* genDivOneByte : 8 bit division */
4071 /*-----------------------------------------------------------------*/
4073 genDivOneByte (operand * left,
4077 sym_link *opetype = operandType (result);
4082 size = AOP_SIZE (result) - 1;
4084 /* signed or unsigned */
4085 if (SPEC_USIGN (opetype))
4087 /* unsigned is easy */
4088 LOAD_AB_FOR_DIV (left, right, l);
4089 emitcode ("div", "ab");
4090 aopPut (AOP (result), "a", 0);
4092 aopPut (AOP (result), zero, offset++);
4096 /* signed is a little bit more difficult */
4098 /* save the signs of the operands */
4099 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4101 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4102 emitcode ("push", "acc"); /* save it on the stack */
4104 /* now sign adjust for both left & right */
4105 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4107 lbl = newiTempLabel (NULL);
4108 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4109 emitcode ("cpl", "a");
4110 emitcode ("inc", "a");
4111 emitcode ("", "%05d$:", (lbl->key + 100));
4112 emitcode ("mov", "b,a");
4114 /* sign adjust left side */
4115 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4118 lbl = newiTempLabel (NULL);
4119 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4120 emitcode ("cpl", "a");
4121 emitcode ("inc", "a");
4122 emitcode ("", "%05d$:", (lbl->key + 100));
4124 /* now the division */
4125 emitcode ("nop", "; workaround for DS80C390 div bug.");
4126 emitcode ("div", "ab");
4127 /* we are interested in the lower order
4129 emitcode ("mov", "b,a");
4130 lbl = newiTempLabel (NULL);
4131 emitcode ("pop", "acc");
4132 /* if there was an over flow we don't
4133 adjust the sign of the result */
4134 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4135 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4137 emitcode ("clr", "a");
4138 emitcode ("subb", "a,b");
4139 emitcode ("mov", "b,a");
4140 emitcode ("", "%05d$:", (lbl->key + 100));
4142 /* now we are done */
4143 aopPut (AOP (result), "b", 0);
4146 emitcode ("mov", "c,b.7");
4147 emitcode ("subb", "a,acc");
4150 aopPut (AOP (result), "a", offset++);
4154 /*-----------------------------------------------------------------*/
4155 /* genDiv - generates code for division */
4156 /*-----------------------------------------------------------------*/
4160 operand *left = IC_LEFT (ic);
4161 operand *right = IC_RIGHT (ic);
4162 operand *result = IC_RESULT (ic);
4164 D (emitcode (";", "genDiv ");
4167 /* assign the amsops */
4170 /* special cases first */
4172 if (AOP_TYPE (left) == AOP_CRY &&
4173 AOP_TYPE (right) == AOP_CRY)
4175 genDivbits (left, right, result);
4179 /* if both are of size == 1 */
4180 if (AOP_SIZE (left) == 1 &&
4181 AOP_SIZE (right) == 1)
4183 genDivOneByte (left, right, result);
4187 /* should have been converted to function call */
4190 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4192 freeAsmop (result, NULL, ic, TRUE);
4195 /*-----------------------------------------------------------------*/
4196 /* genModbits :- modulus of bits */
4197 /*-----------------------------------------------------------------*/
4199 genModbits (operand * left,
4206 /* the result must be bit */
4207 LOAD_AB_FOR_DIV (left, right, l);
4208 emitcode ("div", "ab");
4209 emitcode ("mov", "a,b");
4210 emitcode ("rrc", "a");
4211 aopPut (AOP (result), "c", 0);
4214 /*-----------------------------------------------------------------*/
4215 /* genModOneByte : 8 bit modulus */
4216 /*-----------------------------------------------------------------*/
4218 genModOneByte (operand * left,
4222 sym_link *opetype = operandType (result);
4226 /* signed or unsigned */
4227 if (SPEC_USIGN (opetype))
4229 /* unsigned is easy */
4230 LOAD_AB_FOR_DIV (left, right, l);
4231 emitcode ("div", "ab");
4232 aopPut (AOP (result), "b", 0);
4236 /* signed is a little bit more difficult */
4238 /* save the signs of the operands */
4239 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4242 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4243 emitcode ("push", "acc"); /* save it on the stack */
4245 /* now sign adjust for both left & right */
4246 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4249 lbl = newiTempLabel (NULL);
4250 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4251 emitcode ("cpl", "a");
4252 emitcode ("inc", "a");
4253 emitcode ("", "%05d$:", (lbl->key + 100));
4254 emitcode ("mov", "b,a");
4256 /* sign adjust left side */
4257 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4260 lbl = newiTempLabel (NULL);
4261 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4262 emitcode ("cpl", "a");
4263 emitcode ("inc", "a");
4264 emitcode ("", "%05d$:", (lbl->key + 100));
4266 /* now the multiplication */
4267 emitcode ("nop", "; workaround for DS80C390 div bug.");
4268 emitcode ("div", "ab");
4269 /* we are interested in the lower order
4271 lbl = newiTempLabel (NULL);
4272 emitcode ("pop", "acc");
4273 /* if there was an over flow we don't
4274 adjust the sign of the result */
4275 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4276 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4278 emitcode ("clr", "a");
4279 emitcode ("subb", "a,b");
4280 emitcode ("mov", "b,a");
4281 emitcode ("", "%05d$:", (lbl->key + 100));
4283 /* now we are done */
4284 aopPut (AOP (result), "b", 0);
4288 /*-----------------------------------------------------------------*/
4289 /* genMod - generates code for division */
4290 /*-----------------------------------------------------------------*/
4294 operand *left = IC_LEFT (ic);
4295 operand *right = IC_RIGHT (ic);
4296 operand *result = IC_RESULT (ic);
4298 D (emitcode (";", "genMod ");
4301 /* assign the amsops */
4304 /* special cases first */
4306 if (AOP_TYPE (left) == AOP_CRY &&
4307 AOP_TYPE (right) == AOP_CRY)
4309 genModbits (left, right, result);
4313 /* if both are of size == 1 */
4314 if (AOP_SIZE (left) == 1 &&
4315 AOP_SIZE (right) == 1)
4317 genModOneByte (left, right, result);
4321 /* should have been converted to function call */
4325 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4326 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4327 freeAsmop (result, NULL, ic, TRUE);
4330 /*-----------------------------------------------------------------*/
4331 /* genIfxJump :- will create a jump depending on the ifx */
4332 /*-----------------------------------------------------------------*/
4334 genIfxJump (iCode * ic, char *jval)
4337 symbol *tlbl = newiTempLabel (NULL);
4340 D (emitcode (";", "genIfxJump ");
4343 /* if true label then we jump if condition
4347 jlbl = IC_TRUE (ic);
4348 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4349 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4353 /* false label is present */
4354 jlbl = IC_FALSE (ic);
4355 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4356 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4358 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4359 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4361 emitcode (inst, "%05d$", tlbl->key + 100);
4362 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4363 emitcode ("", "%05d$:", tlbl->key + 100);
4365 /* mark the icode as generated */
4369 /*-----------------------------------------------------------------*/
4370 /* genCmp :- greater or less than comparison */
4371 /*-----------------------------------------------------------------*/
4373 genCmp (operand * left, operand * right,
4374 iCode * ic, iCode * ifx, int sign)
4376 int size, offset = 0;
4377 unsigned long lit = 0L;
4380 D (emitcode (";", "genCmp");
4383 result = IC_RESULT (ic);
4385 /* if left & right are bit variables */
4386 if (AOP_TYPE (left) == AOP_CRY &&
4387 AOP_TYPE (right) == AOP_CRY)
4389 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4390 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4394 /* subtract right from left if at the
4395 end the carry flag is set then we know that
4396 left is greater than right */
4397 size = max (AOP_SIZE (left), AOP_SIZE (right));
4399 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4400 if ((size == 1) && !sign &&
4401 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4403 symbol *lbl = newiTempLabel (NULL);
4404 emitcode ("cjne", "%s,%s,%05d$",
4405 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4406 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4408 emitcode ("", "%05d$:", lbl->key + 100);
4412 if (AOP_TYPE (right) == AOP_LIT)
4414 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4415 /* optimize if(x < 0) or if(x >= 0) */
4424 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4426 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4427 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4429 aopOp (result, ic, FALSE, FALSE);
4431 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4433 freeAsmop (result, NULL, ic, TRUE);
4434 genIfxJump (ifx, "acc.7");
4439 emitcode ("rlc", "a");
4441 goto release_freedLR;
4449 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4450 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4451 emitcode (";", "genCmp #2");
4452 if (sign && (size == 0))
4454 emitcode (";", "genCmp #3");
4455 emitcode ("xrl", "a,#0x80");
4456 if (AOP_TYPE (right) == AOP_LIT)
4458 unsigned long lit = (unsigned long)
4459 floatFromVal (AOP (right)->aopu.aop_lit);
4460 emitcode (";", "genCmp #3.1");
4461 emitcode ("subb", "a,#0x%02x",
4462 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4466 emitcode (";", "genCmp #3.2");
4467 if (AOP_NEEDSACC (right))
4469 emitcode ("push", "acc");
4471 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4472 FALSE, FALSE, FALSE));
4473 emitcode ("xrl", "b,#0x80");
4474 if (AOP_NEEDSACC (right))
4476 emitcode ("pop", "acc");
4478 emitcode ("subb", "a,b");
4485 emitcode (";", "genCmp #4");
4486 if (AOP_NEEDSACC (right))
4489 emitcode (";", "genCmp #4.1");
4490 emitcode ("xch", "a, b");
4491 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4492 emitcode ("xch", "a, b");
4497 emitcode (";", "genCmp #4.2");
4498 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4501 emitcode ("subb", "a,%s", s);
4508 /* Don't need the left & right operands any more; do need the result. */
4509 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4510 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4512 aopOp (result, ic, FALSE, FALSE);
4516 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4522 /* if the result is used in the next
4523 ifx conditional branch then generate
4524 code a little differently */
4527 genIfxJump (ifx, "c");
4533 /* leave the result in acc */
4535 freeAsmop (result, NULL, ic, TRUE);
4538 /*-----------------------------------------------------------------*/
4539 /* genCmpGt :- greater than comparison */
4540 /*-----------------------------------------------------------------*/
4542 genCmpGt (iCode * ic, iCode * ifx)
4544 operand *left, *right;
4545 sym_link *letype, *retype;
4548 D (emitcode (";", "genCmpGt ");
4551 left = IC_LEFT (ic);
4552 right = IC_RIGHT (ic);
4554 letype = getSpec (operandType (left));
4555 retype = getSpec (operandType (right));
4556 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4558 /* assign the left & right amsops */
4561 genCmp (right, left, ic, ifx, sign);
4564 /*-----------------------------------------------------------------*/
4565 /* genCmpLt - less than comparisons */
4566 /*-----------------------------------------------------------------*/
4568 genCmpLt (iCode * ic, iCode * ifx)
4570 operand *left, *right;
4571 sym_link *letype, *retype;
4574 D (emitcode (";", "genCmpLt "););
4576 left = IC_LEFT (ic);
4577 right = IC_RIGHT (ic);
4579 letype = getSpec (operandType (left));
4580 retype = getSpec (operandType (right));
4581 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4583 /* assign the left & right amsops */
4586 genCmp (left, right, ic, ifx, sign);
4589 /*-----------------------------------------------------------------*/
4590 /* gencjneshort - compare and jump if not equal */
4591 /*-----------------------------------------------------------------*/
4593 gencjneshort (operand * left, operand * right, symbol * lbl)
4595 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4597 unsigned long lit = 0L;
4599 D (emitcode (";", "gencjneshort");
4602 /* if the left side is a literal or
4603 if the right is in a pointer register and left
4605 if ((AOP_TYPE (left) == AOP_LIT) ||
4606 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4613 if (AOP_TYPE (right) == AOP_LIT)
4614 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4616 if (opIsGptr (left) || opIsGptr (right))
4618 /* We are comparing a generic pointer to something.
4619 * Exclude the generic type byte from the comparison.
4622 D (emitcode (";", "cjneshort: generic ptr special case.");
4627 /* if the right side is a literal then anything goes */
4628 if (AOP_TYPE (right) == AOP_LIT &&
4629 AOP_TYPE (left) != AOP_DIR)
4633 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4635 emitcode ("cjne", "a,%s,%05d$",
4636 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4642 /* if the right side is in a register or in direct space or
4643 if the left is a pointer register & right is not */
4644 else if (AOP_TYPE (right) == AOP_REG ||
4645 AOP_TYPE (right) == AOP_DIR ||
4646 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4647 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4651 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4652 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4653 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4654 emitcode ("jnz", "%05d$", lbl->key + 100);
4656 emitcode ("cjne", "a,%s,%05d$",
4657 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4664 /* right is a pointer reg need both a & b */
4667 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4668 if (strcmp (l, "b"))
4669 emitcode ("mov", "b,%s", l);
4670 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4671 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4677 /*-----------------------------------------------------------------*/
4678 /* gencjne - compare and jump if not equal */
4679 /*-----------------------------------------------------------------*/
4681 gencjne (operand * left, operand * right, symbol * lbl)
4683 symbol *tlbl = newiTempLabel (NULL);
4685 D (emitcode (";", "gencjne");
4688 gencjneshort (left, right, lbl);
4690 emitcode ("mov", "a,%s", one);
4691 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4692 emitcode ("", "%05d$:", lbl->key + 100);
4693 emitcode ("clr", "a");
4694 emitcode ("", "%05d$:", tlbl->key + 100);
4697 /*-----------------------------------------------------------------*/
4698 /* genCmpEq - generates code for equal to */
4699 /*-----------------------------------------------------------------*/
4701 genCmpEq (iCode * ic, iCode * ifx)
4703 operand *left, *right, *result;
4705 D (emitcode (";", "genCmpEq ");
4709 AOP_SET_LOCALS (ic);
4711 /* if literal, literal on the right or
4712 if the right is in a pointer register and left
4714 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4715 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4717 operand *t = IC_RIGHT (ic);
4718 IC_RIGHT (ic) = IC_LEFT (ic);
4722 if (ifx && /* !AOP_SIZE(result) */
4723 OP_SYMBOL (result) &&
4724 OP_SYMBOL (result)->regType == REG_CND)
4727 /* if they are both bit variables */
4728 if (AOP_TYPE (left) == AOP_CRY &&
4729 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4731 if (AOP_TYPE (right) == AOP_LIT)
4733 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4736 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4737 emitcode ("cpl", "c");
4741 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4745 emitcode ("clr", "c");
4747 /* AOP_TYPE(right) == AOP_CRY */
4751 symbol *lbl = newiTempLabel (NULL);
4752 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4753 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4754 emitcode ("cpl", "c");
4755 emitcode ("", "%05d$:", (lbl->key + 100));
4757 /* if true label then we jump if condition
4759 tlbl = newiTempLabel (NULL);
4762 emitcode ("jnc", "%05d$", tlbl->key + 100);
4763 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4767 emitcode ("jc", "%05d$", tlbl->key + 100);
4768 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4770 emitcode ("", "%05d$:", tlbl->key + 100);
4774 tlbl = newiTempLabel (NULL);
4775 gencjneshort (left, right, tlbl);
4778 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4779 emitcode ("", "%05d$:", tlbl->key + 100);
4783 symbol *lbl = newiTempLabel (NULL);
4784 emitcode ("sjmp", "%05d$", lbl->key + 100);
4785 emitcode ("", "%05d$:", tlbl->key + 100);
4786 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4787 emitcode ("", "%05d$:", lbl->key + 100);
4790 /* mark the icode as generated */
4793 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4794 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4798 /* if they are both bit variables */
4799 if (AOP_TYPE (left) == AOP_CRY &&
4800 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4802 if (AOP_TYPE (right) == AOP_LIT)
4804 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4807 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4808 emitcode ("cpl", "c");
4812 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4816 emitcode ("clr", "c");
4818 /* AOP_TYPE(right) == AOP_CRY */
4822 symbol *lbl = newiTempLabel (NULL);
4823 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4824 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4825 emitcode ("cpl", "c");
4826 emitcode ("", "%05d$:", (lbl->key + 100));
4829 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4830 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4832 aopOp (result, ic, TRUE, FALSE);
4835 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4842 genIfxJump (ifx, "c");
4845 /* if the result is used in an arithmetic operation
4846 then put the result in place */
4851 gencjne (left, right, newiTempLabel (NULL));
4853 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4854 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4856 aopOp (result, ic, TRUE, FALSE);
4858 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4860 aopPut (AOP (result), "a", 0);
4865 genIfxJump (ifx, "a");
4868 /* if the result is used in an arithmetic operation
4869 then put the result in place */
4870 if (AOP_TYPE (result) != AOP_CRY)
4872 /* leave the result in acc */
4876 freeAsmop (result, NULL, ic, TRUE);
4879 /*-----------------------------------------------------------------*/
4880 /* ifxForOp - returns the icode containing the ifx for operand */
4881 /*-----------------------------------------------------------------*/
4883 ifxForOp (operand * op, iCode * ic)
4885 /* if true symbol then needs to be assigned */
4886 if (IS_TRUE_SYMOP (op))
4889 /* if this has register type condition and
4890 the next instruction is ifx with the same operand
4891 and live to of the operand is upto the ifx only then */
4893 ic->next->op == IFX &&
4894 IC_COND (ic->next)->key == op->key &&
4895 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4900 /*-----------------------------------------------------------------*/
4901 /* genAndOp - for && operation */
4902 /*-----------------------------------------------------------------*/
4904 genAndOp (iCode * ic)
4906 operand *left, *right, *result;
4909 D (emitcode (";", "genAndOp "););
4911 /* note here that && operations that are in an
4912 if statement are taken away by backPatchLabels
4913 only those used in arthmetic operations remain */
4915 AOP_SET_LOCALS (ic);
4917 /* if both are bit variables */
4918 if (AOP_TYPE (left) == AOP_CRY &&
4919 AOP_TYPE (right) == AOP_CRY)
4921 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4922 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4923 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4924 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4926 aopOp (result,ic,FALSE, FALSE);
4931 tlbl = newiTempLabel (NULL);
4933 emitcode ("jz", "%05d$", tlbl->key + 100);
4935 emitcode ("", "%05d$:", tlbl->key + 100);
4936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4939 aopOp (result,ic,FALSE, FALSE);
4942 freeAsmop (result, NULL, ic, TRUE);
4946 /*-----------------------------------------------------------------*/
4947 /* genOrOp - for || operation */
4948 /*-----------------------------------------------------------------*/
4950 genOrOp (iCode * ic)
4952 operand *left, *right, *result;
4955 D (emitcode (";", "genOrOp "););
4957 /* note here that || operations that are in an
4958 if statement are taken away by backPatchLabels
4959 only those used in arthmetic operations remain */
4961 AOP_SET_LOCALS (ic);
4963 /* if both are bit variables */
4964 if (AOP_TYPE (left) == AOP_CRY &&
4965 AOP_TYPE (right) == AOP_CRY)
4967 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4968 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4969 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4970 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4972 aopOp (result,ic,FALSE, FALSE);
4978 tlbl = newiTempLabel (NULL);
4980 emitcode ("jnz", "%05d$", tlbl->key + 100);
4982 emitcode ("", "%05d$:", tlbl->key + 100);
4983 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4984 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4986 aopOp (result,ic,FALSE, FALSE);
4991 freeAsmop (result, NULL, ic, TRUE);
4994 /*-----------------------------------------------------------------*/
4995 /* isLiteralBit - test if lit == 2^n */
4996 /*-----------------------------------------------------------------*/
4998 isLiteralBit (unsigned long lit)
5000 unsigned long pw[32] =
5001 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5002 0x100L, 0x200L, 0x400L, 0x800L,
5003 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5004 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5005 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5006 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5007 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5010 for (idx = 0; idx < 32; idx++)
5016 /*-----------------------------------------------------------------*/
5017 /* continueIfTrue - */
5018 /*-----------------------------------------------------------------*/
5020 continueIfTrue (iCode * ic)
5023 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5027 /*-----------------------------------------------------------------*/
5029 /*-----------------------------------------------------------------*/
5031 jumpIfTrue (iCode * ic)
5034 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5038 /*-----------------------------------------------------------------*/
5039 /* jmpTrueOrFalse - */
5040 /*-----------------------------------------------------------------*/
5042 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5044 // ugly but optimized by peephole
5047 symbol *nlbl = newiTempLabel (NULL);
5048 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5049 emitcode ("", "%05d$:", tlbl->key + 100);
5050 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5051 emitcode ("", "%05d$:", nlbl->key + 100);
5055 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5056 emitcode ("", "%05d$:", tlbl->key + 100);
5061 // Generate code to perform a bit-wise logic operation
5062 // on two operands in far space (assumed to already have been
5063 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5064 // in far space. This requires pushing the result on the stack
5065 // then popping it into the result.
5067 genFarFarLogicOp(iCode *ic, char *logicOp)
5069 int size, resultSize, compSize;
5072 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5073 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5074 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5076 _startLazyDPSEvaluation();
5077 for (size = compSize; (size--); offset++)
5079 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5080 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5081 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5083 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5084 emitcode ("push", "acc");
5086 _endLazyDPSEvaluation();
5088 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5089 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5090 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5092 resultSize = AOP_SIZE(IC_RESULT(ic));
5094 ADJUST_PUSHED_RESULT(compSize, resultSize);
5096 _startLazyDPSEvaluation();
5099 emitcode ("pop", "acc");
5100 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5102 _endLazyDPSEvaluation();
5103 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5107 /*-----------------------------------------------------------------*/
5108 /* genAnd - code for and */
5109 /*-----------------------------------------------------------------*/
5111 genAnd (iCode * ic, iCode * ifx)
5113 operand *left, *right, *result;
5114 int size, offset = 0;
5115 unsigned long lit = 0L;
5120 D (emitcode (";", "genAnd "););
5122 AOP_OP_3_NOFATAL (ic, pushResult);
5123 AOP_SET_LOCALS (ic);
5127 genFarFarLogicOp(ic, "anl");
5132 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5134 AOP_TYPE (left), AOP_TYPE (right));
5135 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5137 AOP_SIZE (left), AOP_SIZE (right));
5140 /* if left is a literal & right is not then exchange them */
5141 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5142 AOP_NEEDSACC (left))
5144 operand *tmp = right;
5149 /* if result = right then exchange them */
5150 if (sameRegs (AOP (result), AOP (right)))
5152 operand *tmp = right;
5157 /* if right is bit then exchange them */
5158 if (AOP_TYPE (right) == AOP_CRY &&
5159 AOP_TYPE (left) != AOP_CRY)
5161 operand *tmp = right;
5165 if (AOP_TYPE (right) == AOP_LIT)
5166 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5168 size = AOP_SIZE (result);
5171 // result = bit & yy;
5172 if (AOP_TYPE (left) == AOP_CRY)
5174 // c = bit & literal;
5175 if (AOP_TYPE (right) == AOP_LIT)
5179 if (size && sameRegs (AOP (result), AOP (left)))
5182 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5187 if (size && (AOP_TYPE (result) == AOP_CRY))
5189 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5192 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5197 emitcode ("clr", "c");
5202 if (AOP_TYPE (right) == AOP_CRY)
5205 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5206 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5211 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5213 emitcode ("rrc", "a");
5214 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5222 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5223 genIfxJump (ifx, "c");
5227 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5228 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5229 if ((AOP_TYPE (right) == AOP_LIT) &&
5230 (AOP_TYPE (result) == AOP_CRY) &&
5231 (AOP_TYPE (left) != AOP_CRY))
5233 int posbit = isLiteralBit (lit);
5238 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5241 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5247 sprintf (buffer, "acc.%d", posbit & 0x07);
5248 genIfxJump (ifx, buffer);
5255 symbol *tlbl = newiTempLabel (NULL);
5256 int sizel = AOP_SIZE (left);
5258 emitcode ("setb", "c");
5261 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5263 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5265 if ((posbit = isLiteralBit (bytelit)) != 0)
5266 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5269 if (bytelit != 0x0FFL)
5270 emitcode ("anl", "a,%s",
5271 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5272 emitcode ("jnz", "%05d$", tlbl->key + 100);
5277 // bit = left & literal
5280 emitcode ("clr", "c");
5281 emitcode ("", "%05d$:", tlbl->key + 100);
5283 // if(left & literal)
5287 jmpTrueOrFalse (ifx, tlbl);
5295 /* if left is same as result */
5296 if (sameRegs (AOP (result), AOP (left)))
5298 for (; size--; offset++)
5300 if (AOP_TYPE (right) == AOP_LIT)
5302 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5304 else if (bytelit == 0)
5305 aopPut (AOP (result), zero, offset);
5306 else if (IS_AOP_PREG (result))
5308 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5309 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5310 aopPut (AOP (result), "a", offset);
5313 emitcode ("anl", "%s,%s",
5314 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5315 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5319 if (AOP_TYPE (left) == AOP_ACC)
5320 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5323 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5324 if (IS_AOP_PREG (result))
5326 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5327 aopPut (AOP (result), "a", offset);
5331 emitcode ("anl", "%s,a",
5332 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5339 // left & result in different registers
5340 if (AOP_TYPE (result) == AOP_CRY)
5343 // if(size), result in bit
5344 // if(!size && ifx), conditional oper: if(left & right)
5345 symbol *tlbl = newiTempLabel (NULL);
5346 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5348 emitcode ("setb", "c");
5351 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5352 emitcode ("anl", "a,%s",
5353 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5354 emitcode ("jnz", "%05d$", tlbl->key + 100);
5360 emitcode ("", "%05d$:", tlbl->key + 100);
5364 jmpTrueOrFalse (ifx, tlbl);
5368 for (; (size--); offset++)
5371 // result = left & right
5372 if (AOP_TYPE (right) == AOP_LIT)
5374 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5376 aopPut (AOP (result),
5377 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5381 else if (bytelit == 0)
5383 aopPut (AOP (result), zero, offset);
5386 D (emitcode (";", "better literal AND.");
5388 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5389 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5390 FALSE, FALSE, FALSE));
5395 // faster than result <- left, anl result,right
5396 // and better if result is SFR
5397 if (AOP_TYPE (left) == AOP_ACC)
5399 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5400 FALSE, FALSE, FALSE));
5404 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5405 emitcode ("anl", "a,%s",
5406 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5409 aopPut (AOP (result), "a", offset);
5415 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5416 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417 freeAsmop (result, NULL, ic, TRUE);
5421 /*-----------------------------------------------------------------*/
5422 /* genOr - code for or */
5423 /*-----------------------------------------------------------------*/
5425 genOr (iCode * ic, iCode * ifx)
5427 operand *left, *right, *result;
5428 int size, offset = 0;
5429 unsigned long lit = 0L;
5432 D (emitcode (";", "genOr "););
5434 AOP_OP_3_NOFATAL (ic, pushResult);
5435 AOP_SET_LOCALS (ic);
5439 genFarFarLogicOp(ic, "orl");
5445 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5447 AOP_TYPE (left), AOP_TYPE (right));
5448 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5450 AOP_SIZE (left), AOP_SIZE (right));
5453 /* if left is a literal & right is not then exchange them */
5454 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5455 AOP_NEEDSACC (left))
5457 operand *tmp = right;
5462 /* if result = right then exchange them */
5463 if (sameRegs (AOP (result), AOP (right)))
5465 operand *tmp = right;
5470 /* if right is bit then exchange them */
5471 if (AOP_TYPE (right) == AOP_CRY &&
5472 AOP_TYPE (left) != AOP_CRY)
5474 operand *tmp = right;
5478 if (AOP_TYPE (right) == AOP_LIT)
5479 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5481 size = AOP_SIZE (result);
5485 if (AOP_TYPE (left) == AOP_CRY)
5487 if (AOP_TYPE (right) == AOP_LIT)
5489 // c = bit & literal;
5492 // lit != 0 => result = 1
5493 if (AOP_TYPE (result) == AOP_CRY)
5496 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5498 continueIfTrue (ifx);
5501 emitcode ("setb", "c");
5505 // lit == 0 => result = left
5506 if (size && sameRegs (AOP (result), AOP (left)))
5508 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5513 if (AOP_TYPE (right) == AOP_CRY)
5516 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5517 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5522 symbol *tlbl = newiTempLabel (NULL);
5523 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5524 emitcode ("setb", "c");
5525 emitcode ("jb", "%s,%05d$",
5526 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5528 emitcode ("jnz", "%05d$", tlbl->key + 100);
5529 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5531 jmpTrueOrFalse (ifx, tlbl);
5537 emitcode ("", "%05d$:", tlbl->key + 100);
5546 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5547 genIfxJump (ifx, "c");
5551 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5552 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5553 if ((AOP_TYPE (right) == AOP_LIT) &&
5554 (AOP_TYPE (result) == AOP_CRY) &&
5555 (AOP_TYPE (left) != AOP_CRY))
5561 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5563 continueIfTrue (ifx);
5568 // lit = 0, result = boolean(left)
5570 emitcode ("setb", "c");
5574 symbol *tlbl = newiTempLabel (NULL);
5575 emitcode ("jnz", "%05d$", tlbl->key + 100);
5577 emitcode ("", "%05d$:", tlbl->key + 100);
5581 genIfxJump (ifx, "a");
5589 /* if left is same as result */
5590 if (sameRegs (AOP (result), AOP (left)))
5592 for (; size--; offset++)
5594 if (AOP_TYPE (right) == AOP_LIT)
5596 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5602 if (IS_AOP_PREG (left))
5604 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5605 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5606 aopPut (AOP (result), "a", offset);
5610 emitcode ("orl", "%s,%s",
5611 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5612 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5618 if (AOP_TYPE (left) == AOP_ACC)
5620 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5624 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5625 if (IS_AOP_PREG (left))
5627 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5628 aopPut (AOP (result), "a", offset);
5632 emitcode ("orl", "%s,a",
5633 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5641 // left & result in different registers
5642 if (AOP_TYPE (result) == AOP_CRY)
5645 // if(size), result in bit
5646 // if(!size && ifx), conditional oper: if(left | right)
5647 symbol *tlbl = newiTempLabel (NULL);
5648 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5650 emitcode ("setb", "c");
5653 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5654 emitcode ("orl", "a,%s",
5655 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5656 emitcode ("jnz", "%05d$", tlbl->key + 100);
5662 emitcode ("", "%05d$:", tlbl->key + 100);
5666 jmpTrueOrFalse (ifx, tlbl);
5670 for (; (size--); offset++)
5673 // result = left & right
5674 if (AOP_TYPE (right) == AOP_LIT)
5676 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5678 aopPut (AOP (result),
5679 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5683 D (emitcode (";", "better literal OR.");
5685 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5686 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5687 FALSE, FALSE, FALSE));
5692 // faster than result <- left, anl result,right
5693 // and better if result is SFR
5694 if (AOP_TYPE (left) == AOP_ACC)
5696 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5697 FALSE, FALSE, FALSE));
5701 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5702 emitcode ("orl", "a,%s",
5703 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5706 aopPut (AOP (result), "a", offset);
5712 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5713 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5714 freeAsmop (result, NULL, ic, TRUE);
5717 /*-----------------------------------------------------------------*/
5718 /* genXor - code for xclusive or */
5719 /*-----------------------------------------------------------------*/
5721 genXor (iCode * ic, iCode * ifx)
5723 operand *left, *right, *result;
5724 int size, offset = 0;
5725 unsigned long lit = 0L;
5728 D (emitcode (";", "genXor "););
5730 AOP_OP_3_NOFATAL (ic, pushResult);
5731 AOP_SET_LOCALS (ic);
5735 genFarFarLogicOp(ic, "xrl");
5740 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5742 AOP_TYPE (left), AOP_TYPE (right));
5743 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5745 AOP_SIZE (left), AOP_SIZE (right));
5748 /* if left is a literal & right is not ||
5749 if left needs acc & right does not */
5750 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5751 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5753 operand *tmp = right;
5758 /* if result = right then exchange them */
5759 if (sameRegs (AOP (result), AOP (right)))
5761 operand *tmp = right;
5766 /* if right is bit then exchange them */
5767 if (AOP_TYPE (right) == AOP_CRY &&
5768 AOP_TYPE (left) != AOP_CRY)
5770 operand *tmp = right;
5774 if (AOP_TYPE (right) == AOP_LIT)
5775 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5777 size = AOP_SIZE (result);
5781 if (AOP_TYPE (left) == AOP_CRY)
5783 if (AOP_TYPE (right) == AOP_LIT)
5785 // c = bit & literal;
5788 // lit>>1 != 0 => result = 1
5789 if (AOP_TYPE (result) == AOP_CRY)
5792 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5794 continueIfTrue (ifx);
5797 emitcode ("setb", "c");
5804 // lit == 0, result = left
5805 if (size && sameRegs (AOP (result), AOP (left)))
5807 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5811 // lit == 1, result = not(left)
5812 if (size && sameRegs (AOP (result), AOP (left)))
5814 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5819 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5820 emitcode ("cpl", "c");
5829 symbol *tlbl = newiTempLabel (NULL);
5830 if (AOP_TYPE (right) == AOP_CRY)
5833 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5837 int sizer = AOP_SIZE (right);
5839 // if val>>1 != 0, result = 1
5840 emitcode ("setb", "c");
5843 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5845 // test the msb of the lsb
5846 emitcode ("anl", "a,#0xfe");
5847 emitcode ("jnz", "%05d$", tlbl->key + 100);
5851 emitcode ("rrc", "a");
5853 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5854 emitcode ("cpl", "c");
5855 emitcode ("", "%05d$:", (tlbl->key + 100));
5862 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5863 genIfxJump (ifx, "c");
5867 if (sameRegs (AOP (result), AOP (left)))
5869 /* if left is same as result */
5870 for (; size--; offset++)
5872 if (AOP_TYPE (right) == AOP_LIT)
5874 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5876 else if (IS_AOP_PREG (left))
5878 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5879 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5880 aopPut (AOP (result), "a", offset);
5883 emitcode ("xrl", "%s,%s",
5884 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5885 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5889 if (AOP_TYPE (left) == AOP_ACC)
5890 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5893 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5894 if (IS_AOP_PREG (left))
5896 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5897 aopPut (AOP (result), "a", offset);
5900 emitcode ("xrl", "%s,a",
5901 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5908 // left & result in different registers
5909 if (AOP_TYPE (result) == AOP_CRY)
5912 // if(size), result in bit
5913 // if(!size && ifx), conditional oper: if(left ^ right)
5914 symbol *tlbl = newiTempLabel (NULL);
5915 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5917 emitcode ("setb", "c");
5920 if ((AOP_TYPE (right) == AOP_LIT) &&
5921 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5923 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5927 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5928 emitcode ("xrl", "a,%s",
5929 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5931 emitcode ("jnz", "%05d$", tlbl->key + 100);
5937 emitcode ("", "%05d$:", tlbl->key + 100);
5941 jmpTrueOrFalse (ifx, tlbl);
5944 for (; (size--); offset++)
5947 // result = left & right
5948 if (AOP_TYPE (right) == AOP_LIT)
5950 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5952 aopPut (AOP (result),
5953 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5957 D (emitcode (";", "better literal XOR.");
5959 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5960 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5961 FALSE, FALSE, FALSE));
5965 // faster than result <- left, anl result,right
5966 // and better if result is SFR
5967 if (AOP_TYPE (left) == AOP_ACC)
5969 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5970 FALSE, FALSE, FALSE));
5974 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5975 emitcode ("xrl", "a,%s",
5976 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5979 aopPut (AOP (result), "a", offset);
5984 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5985 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 freeAsmop (result, NULL, ic, TRUE);
5989 /*-----------------------------------------------------------------*/
5990 /* genInline - write the inline code out */
5991 /*-----------------------------------------------------------------*/
5993 genInline (iCode * ic)
5995 char *buffer, *bp, *bp1;
5997 D (emitcode (";", "genInline ");
6000 _G.inLine += (!options.asmpeep);
6002 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6003 strcpy (buffer, IC_INLINE (ic));
6005 /* emit each line as a code */
6030 /* emitcode("",buffer); */
6031 _G.inLine -= (!options.asmpeep);
6034 /*-----------------------------------------------------------------*/
6035 /* genRRC - rotate right with carry */
6036 /*-----------------------------------------------------------------*/
6040 operand *left, *result;
6041 int size, offset = 0;
6044 D (emitcode (";", "genRRC ");
6047 /* rotate right with carry */
6048 left = IC_LEFT (ic);
6049 result = IC_RESULT (ic);
6050 aopOp (left, ic, FALSE, FALSE);
6051 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6053 /* move it to the result */
6054 size = AOP_SIZE (result);
6058 _startLazyDPSEvaluation ();
6061 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6063 emitcode ("rrc", "a");
6064 if (AOP_SIZE (result) > 1)
6065 aopPut (AOP (result), "a", offset--);
6067 _endLazyDPSEvaluation ();
6069 /* now we need to put the carry into the
6070 highest order byte of the result */
6071 if (AOP_SIZE (result) > 1)
6073 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6076 emitcode ("mov", "acc.7,c");
6077 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6078 freeAsmop (left, NULL, ic, TRUE);
6079 freeAsmop (result, NULL, ic, TRUE);
6082 /*-----------------------------------------------------------------*/
6083 /* genRLC - generate code for rotate left with carry */
6084 /*-----------------------------------------------------------------*/
6088 operand *left, *result;
6089 int size, offset = 0;
6092 D (emitcode (";", "genRLC ");
6095 /* rotate right with carry */
6096 left = IC_LEFT (ic);
6097 result = IC_RESULT (ic);
6098 aopOp (left, ic, FALSE, FALSE);
6099 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6101 /* move it to the result */
6102 size = AOP_SIZE (result);
6106 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6108 emitcode ("add", "a,acc");
6109 if (AOP_SIZE (result) > 1)
6111 aopPut (AOP (result), "a", offset++);
6114 _startLazyDPSEvaluation ();
6117 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6119 emitcode ("rlc", "a");
6120 if (AOP_SIZE (result) > 1)
6121 aopPut (AOP (result), "a", offset++);
6123 _endLazyDPSEvaluation ();
6125 /* now we need to put the carry into the
6126 highest order byte of the result */
6127 if (AOP_SIZE (result) > 1)
6129 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6132 emitcode ("mov", "acc.0,c");
6133 aopPut (AOP (result), "a", 0);
6134 freeAsmop (left, NULL, ic, TRUE);
6135 freeAsmop (result, NULL, ic, TRUE);
6138 /*-----------------------------------------------------------------*/
6139 /* genGetHbit - generates code get highest order bit */
6140 /*-----------------------------------------------------------------*/
6142 genGetHbit (iCode * ic)
6144 operand *left, *result;
6145 left = IC_LEFT (ic);
6146 result = IC_RESULT (ic);
6147 aopOp (left, ic, FALSE, FALSE);
6148 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6150 D (emitcode (";", "genGetHbit ");
6153 /* get the highest order byte into a */
6154 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6155 if (AOP_TYPE (result) == AOP_CRY)
6157 emitcode ("rlc", "a");
6162 emitcode ("rl", "a");
6163 emitcode ("anl", "a,#0x01");
6168 freeAsmop (left, NULL, ic, TRUE);
6169 freeAsmop (result, NULL, ic, TRUE);
6172 /*-----------------------------------------------------------------*/
6173 /* AccRol - rotate left accumulator by known count */
6174 /*-----------------------------------------------------------------*/
6176 AccRol (int shCount)
6178 shCount &= 0x0007; // shCount : 0..7
6185 emitcode ("rl", "a");
6188 emitcode ("rl", "a");
6189 emitcode ("rl", "a");
6192 emitcode ("swap", "a");
6193 emitcode ("rr", "a");
6196 emitcode ("swap", "a");
6199 emitcode ("swap", "a");
6200 emitcode ("rl", "a");
6203 emitcode ("rr", "a");
6204 emitcode ("rr", "a");
6207 emitcode ("rr", "a");
6212 /*-----------------------------------------------------------------*/
6213 /* AccLsh - left shift accumulator by known count */
6214 /*-----------------------------------------------------------------*/
6216 AccLsh (int shCount)
6221 emitcode ("add", "a,acc");
6222 else if (shCount == 2)
6224 emitcode ("add", "a,acc");
6225 emitcode ("add", "a,acc");
6229 /* rotate left accumulator */
6231 /* and kill the lower order bits */
6232 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6237 /*-----------------------------------------------------------------*/
6238 /* AccRsh - right shift accumulator by known count */
6239 /*-----------------------------------------------------------------*/
6241 AccRsh (int shCount)
6248 emitcode ("rrc", "a");
6252 /* rotate right accumulator */
6253 AccRol (8 - shCount);
6254 /* and kill the higher order bits */
6255 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6260 #ifdef BETTER_LITERAL_SHIFT
6261 /*-----------------------------------------------------------------*/
6262 /* AccSRsh - signed right shift accumulator by known count */
6263 /*-----------------------------------------------------------------*/
6265 AccSRsh (int shCount)
6272 emitcode ("mov", "c,acc.7");
6273 emitcode ("rrc", "a");
6275 else if (shCount == 2)
6277 emitcode ("mov", "c,acc.7");
6278 emitcode ("rrc", "a");
6279 emitcode ("mov", "c,acc.7");
6280 emitcode ("rrc", "a");
6284 tlbl = newiTempLabel (NULL);
6285 /* rotate right accumulator */
6286 AccRol (8 - shCount);
6287 /* and kill the higher order bits */
6288 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6289 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6290 emitcode ("orl", "a,#0x%02x",
6291 (unsigned char) ~SRMask[shCount]);
6292 emitcode ("", "%05d$:", tlbl->key + 100);
6298 #ifdef BETTER_LITERAL_SHIFT
6299 /*-----------------------------------------------------------------*/
6300 /* shiftR1Left2Result - shift right one byte from left to result */
6301 /*-----------------------------------------------------------------*/
6303 shiftR1Left2Result (operand * left, int offl,
6304 operand * result, int offr,
6305 int shCount, int sign)
6307 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6308 /* shift right accumulator */
6313 aopPut (AOP (result), "a", offr);
6317 #ifdef BETTER_LITERAL_SHIFT
6318 /*-----------------------------------------------------------------*/
6319 /* shiftL1Left2Result - shift left one byte from left to result */
6320 /*-----------------------------------------------------------------*/
6322 shiftL1Left2Result (operand * left, int offl,
6323 operand * result, int offr, int shCount)
6325 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6326 /* shift left accumulator */
6328 aopPut (AOP (result), "a", offr);
6332 #ifdef BETTER_LITERAL_SHIFT
6333 /*-----------------------------------------------------------------*/
6334 /* movLeft2Result - move byte from left to result */
6335 /*-----------------------------------------------------------------*/
6337 movLeft2Result (operand * left, int offl,
6338 operand * result, int offr, int sign)
6341 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6343 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6345 if (*l == '@' && (IS_AOP_PREG (result)))
6347 emitcode ("mov", "a,%s", l);
6348 aopPut (AOP (result), "a", offr);
6354 aopPut (AOP (result), l, offr);
6358 /* MSB sign in acc.7 ! */
6359 if (getDataSize (left) == offl + 1)
6361 emitcode ("mov", "a,%s", l);
6362 aopPut (AOP (result), "a", offr);
6370 #ifdef BETTER_LITERAL_SHIFT
6371 /*-----------------------------------------------------------------*/
6372 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6373 /*-----------------------------------------------------------------*/
6377 emitcode ("rrc", "a");
6378 emitcode ("xch", "a,%s", x);
6379 emitcode ("rrc", "a");
6380 emitcode ("xch", "a,%s", x);
6384 #ifdef BETTER_LITERAL_SHIFT
6386 /*-----------------------------------------------------------------*/
6387 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6388 /*-----------------------------------------------------------------*/
6392 emitcode ("xch", "a,%s", x);
6393 emitcode ("rlc", "a");
6394 emitcode ("xch", "a,%s", x);
6395 emitcode ("rlc", "a");
6399 #ifdef BETTER_LITERAL_SHIFT
6400 /*-----------------------------------------------------------------*/
6401 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6402 /*-----------------------------------------------------------------*/
6406 emitcode ("xch", "a,%s", x);
6407 emitcode ("add", "a,acc");
6408 emitcode ("xch", "a,%s", x);
6409 emitcode ("rlc", "a");
6413 #ifdef BETTER_LITERAL_SHIFT
6414 /*-----------------------------------------------------------------*/
6415 /* AccAXLsh - left shift a:x by known count (0..7) */
6416 /*-----------------------------------------------------------------*/
6418 AccAXLsh (char *x, int shCount)
6433 case 5: // AAAAABBB:CCCCCDDD
6435 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6437 emitcode ("anl", "a,#0x%02x",
6438 SLMask[shCount]); // BBB00000:CCCCCDDD
6440 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6442 AccRol (shCount); // DDDCCCCC:BBB00000
6444 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6446 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6448 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6450 emitcode ("anl", "a,#0x%02x",
6451 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6453 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6455 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6458 case 6: // AAAAAABB:CCCCCCDD
6459 emitcode ("anl", "a,#0x%02x",
6460 SRMask[shCount]); // 000000BB:CCCCCCDD
6461 emitcode ("mov", "c,acc.0"); // c = B
6462 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6464 AccAXRrl1 (x); // BCCCCCCD:D000000B
6465 AccAXRrl1 (x); // BBCCCCCC:DD000000
6467 emitcode("rrc","a");
6468 emitcode("xch","a,%s", x);
6469 emitcode("rrc","a");
6470 emitcode("mov","c,acc.0"); //<< get correct bit
6471 emitcode("xch","a,%s", x);
6473 emitcode("rrc","a");
6474 emitcode("xch","a,%s", x);
6475 emitcode("rrc","a");
6476 emitcode("xch","a,%s", x);
6479 case 7: // a:x <<= 7
6481 emitcode ("anl", "a,#0x%02x",
6482 SRMask[shCount]); // 0000000B:CCCCCCCD
6484 emitcode ("mov", "c,acc.0"); // c = B
6486 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6488 AccAXRrl1 (x); // BCCCCCCC:D0000000
6497 #ifdef BETTER_LITERAL_SHIFT
6499 /*-----------------------------------------------------------------*/
6500 /* AccAXRsh - right shift a:x known count (0..7) */
6501 /*-----------------------------------------------------------------*/
6503 AccAXRsh (char *x, int shCount)
6511 AccAXRrl1 (x); // 0->a:x
6516 AccAXRrl1 (x); // 0->a:x
6519 AccAXRrl1 (x); // 0->a:x
6524 case 5: // AAAAABBB:CCCCCDDD = a:x
6526 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6528 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6530 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6532 emitcode ("anl", "a,#0x%02x",
6533 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6535 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6537 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6539 emitcode ("anl", "a,#0x%02x",
6540 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6542 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6544 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6546 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6549 case 6: // AABBBBBB:CCDDDDDD
6551 emitcode ("mov", "c,acc.7");
6552 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6554 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6556 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6558 emitcode ("anl", "a,#0x%02x",
6559 SRMask[shCount]); // 000000AA:BBBBBBCC
6562 case 7: // ABBBBBBB:CDDDDDDD
6564 emitcode ("mov", "c,acc.7"); // c = A
6566 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6568 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6570 emitcode ("anl", "a,#0x%02x",
6571 SRMask[shCount]); // 0000000A:BBBBBBBC
6580 #ifdef BETTER_LITERAL_SHIFT
6582 /*-----------------------------------------------------------------*/
6583 /* AccAXRshS - right shift signed a:x known count (0..7) */
6584 /*-----------------------------------------------------------------*/
6586 AccAXRshS (char *x, int shCount)
6594 emitcode ("mov", "c,acc.7");
6595 AccAXRrl1 (x); // s->a:x
6599 emitcode ("mov", "c,acc.7");
6600 AccAXRrl1 (x); // s->a:x
6602 emitcode ("mov", "c,acc.7");
6603 AccAXRrl1 (x); // s->a:x
6608 case 5: // AAAAABBB:CCCCCDDD = a:x
6610 tlbl = newiTempLabel (NULL);
6611 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6613 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6615 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6617 emitcode ("anl", "a,#0x%02x",
6618 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6620 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6622 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6624 emitcode ("anl", "a,#0x%02x",
6625 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6627 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6629 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6631 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6633 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6634 emitcode ("orl", "a,#0x%02x",
6635 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6637 emitcode ("", "%05d$:", tlbl->key + 100);
6638 break; // SSSSAAAA:BBBCCCCC
6640 case 6: // AABBBBBB:CCDDDDDD
6642 tlbl = newiTempLabel (NULL);
6643 emitcode ("mov", "c,acc.7");
6644 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6646 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6648 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6650 emitcode ("anl", "a,#0x%02x",
6651 SRMask[shCount]); // 000000AA:BBBBBBCC
6653 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6654 emitcode ("orl", "a,#0x%02x",
6655 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6657 emitcode ("", "%05d$:", tlbl->key + 100);
6659 case 7: // ABBBBBBB:CDDDDDDD
6661 tlbl = newiTempLabel (NULL);
6662 emitcode ("mov", "c,acc.7"); // c = A
6664 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6666 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6668 emitcode ("anl", "a,#0x%02x",
6669 SRMask[shCount]); // 0000000A:BBBBBBBC
6671 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6672 emitcode ("orl", "a,#0x%02x",
6673 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6675 emitcode ("", "%05d$:", tlbl->key + 100);
6683 #ifdef BETTER_LITERAL_SHIFT
6685 _loadLeftIntoAx(char **lsb,
6691 // Get the initial value from left into a pair of registers.
6692 // MSB must be in A, LSB can be any register.
6694 // If the result is held in registers, it is an optimization
6695 // if the LSB can be held in the register which will hold the,
6696 // result LSB since this saves us from having to copy it into
6697 // the result following AccAXLsh.
6699 // If the result is addressed indirectly, this is not a gain.
6700 if (AOP_NEEDSACC(result))
6704 _startLazyDPSEvaluation();
6705 if (AOP_TYPE(left) == AOP_DPTR2)
6708 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6709 // get LSB in DP2_RESULT_REG.
6710 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6711 assert(!strcmp(leftByte, DP2_RESULT_REG));
6715 // get LSB into DP2_RESULT_REG
6716 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6717 if (strcmp(leftByte, DP2_RESULT_REG))
6719 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6722 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6723 assert(strcmp(leftByte, DP2_RESULT_REG));
6726 _endLazyDPSEvaluation();
6727 *lsb = DP2_RESULT_REG;
6731 if (sameRegs (AOP (result), AOP (left)) &&
6732 ((offl + MSB16) == offr))
6734 /* don't crash result[offr] */
6735 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6736 emitcode ("xch", "a,%s",
6737 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6741 movLeft2Result (left, offl, result, offr, 0);
6742 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6744 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6745 assert(strcmp(*lsb,"a"));
6750 _storeAxResults(char *lsb,
6754 _startLazyDPSEvaluation();
6755 if (AOP_NEEDSACC(result))
6757 /* We have to explicitly update the result LSB.
6759 emitcode("xch","a,%s", lsb);
6760 aopPut(AOP(result), "a", offr);
6761 emitcode("mov","a,%s", lsb);
6763 if (getDataSize (result) > 1)
6765 aopPut (AOP (result), "a", offr + MSB16);
6767 _endLazyDPSEvaluation();
6770 /*-----------------------------------------------------------------*/
6771 /* shiftL2Left2Result - shift left two bytes from left to result */
6772 /*-----------------------------------------------------------------*/
6774 shiftL2Left2Result (operand * left, int offl,
6775 operand * result, int offr, int shCount)
6779 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6781 AccAXLsh (lsb, shCount);
6783 _storeAxResults(lsb, result, offr);
6787 #ifdef BETTER_LITERAL_SHIFT
6788 /*-----------------------------------------------------------------*/
6789 /* shiftR2Left2Result - shift right two bytes from left to result */
6790 /*-----------------------------------------------------------------*/
6792 shiftR2Left2Result (operand * left, int offl,
6793 operand * result, int offr,
6794 int shCount, int sign)
6798 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6800 /* a:x >> shCount (x = lsb(result)) */
6803 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6807 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6810 _storeAxResults(lsb, result, offr);
6816 /*-----------------------------------------------------------------*/
6817 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6818 /*-----------------------------------------------------------------*/
6820 shiftLLeftOrResult (operand * left, int offl,
6821 operand * result, int offr, int shCount)
6823 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6824 /* shift left accumulator */
6826 /* or with result */
6827 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6828 /* back to result */
6829 aopPut (AOP (result), "a", offr);
6835 /*-----------------------------------------------------------------*/
6836 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6837 /*-----------------------------------------------------------------*/
6839 shiftRLeftOrResult (operand * left, int offl,
6840 operand * result, int offr, int shCount)
6842 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6843 /* shift right accumulator */
6845 /* or with result */
6846 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6847 /* back to result */
6848 aopPut (AOP (result), "a", offr);
6852 #ifdef BETTER_LITERAL_SHIFT
6853 /*-----------------------------------------------------------------*/
6854 /* genlshOne - left shift a one byte quantity by known count */
6855 /*-----------------------------------------------------------------*/
6857 genlshOne (operand * result, operand * left, int shCount)
6859 D (emitcode (";", "genlshOne "););
6860 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6864 #ifdef BETTER_LITERAL_SHIFT
6865 /*-----------------------------------------------------------------*/
6866 /* genlshTwo - left shift two bytes by known amount != 0 */
6867 /*-----------------------------------------------------------------*/
6869 genlshTwo (operand * result, operand * left, int shCount)
6873 D (emitcode (";", "genlshTwo "););
6875 size = getDataSize (result);
6877 /* if shCount >= 8 */
6882 _startLazyDPSEvaluation();
6888 _endLazyDPSEvaluation();
6889 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6890 aopPut (AOP (result), zero, LSB);
6894 movLeft2Result (left, LSB, result, MSB16, 0);
6895 aopPut (AOP (result), zero, LSB);
6896 _endLazyDPSEvaluation();
6901 aopPut (AOP (result), zero, LSB);
6902 _endLazyDPSEvaluation();
6906 /* 1 <= shCount <= 7 */
6911 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6915 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6923 /*-----------------------------------------------------------------*/
6924 /* shiftLLong - shift left one long from left to result */
6925 /* offl = LSB or MSB16 */
6926 /*-----------------------------------------------------------------*/
6928 shiftLLong (operand * left, operand * result, int offr)
6931 int size = AOP_SIZE (result);
6933 if (size >= LSB + offr)
6935 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6937 emitcode ("add", "a,acc");
6938 if (sameRegs (AOP (left), AOP (result)) &&
6939 size >= MSB16 + offr && offr != LSB)
6940 emitcode ("xch", "a,%s",
6941 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6943 aopPut (AOP (result), "a", LSB + offr);
6946 if (size >= MSB16 + offr)
6948 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6950 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6953 emitcode ("rlc", "a");
6954 if (sameRegs (AOP (left), AOP (result)) &&
6955 size >= MSB24 + offr && offr != LSB)
6956 emitcode ("xch", "a,%s",
6957 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6959 aopPut (AOP (result), "a", MSB16 + offr);
6962 if (size >= MSB24 + offr)
6964 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6966 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6969 emitcode ("rlc", "a");
6970 if (sameRegs (AOP (left), AOP (result)) &&
6971 size >= MSB32 + offr && offr != LSB)
6972 emitcode ("xch", "a,%s",
6973 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6975 aopPut (AOP (result), "a", MSB24 + offr);
6978 if (size > MSB32 + offr)
6980 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6982 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6985 emitcode ("rlc", "a");
6986 aopPut (AOP (result), "a", MSB32 + offr);
6989 aopPut (AOP (result), zero, LSB);
6995 /*-----------------------------------------------------------------*/
6996 /* genlshFour - shift four byte by a known amount != 0 */
6997 /*-----------------------------------------------------------------*/
6999 genlshFour (operand * result, operand * left, int shCount)
7003 D (emitcode (";", "genlshFour ");
7006 size = AOP_SIZE (result);
7008 /* if shifting more that 3 bytes */
7013 /* lowest order of left goes to the highest
7014 order of the destination */
7015 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7017 movLeft2Result (left, LSB, result, MSB32, 0);
7018 aopPut (AOP (result), zero, LSB);
7019 aopPut (AOP (result), zero, MSB16);
7020 aopPut (AOP (result), zero, MSB24);
7024 /* more than two bytes */
7025 else if (shCount >= 16)
7027 /* lower order two bytes goes to higher order two bytes */
7029 /* if some more remaining */
7031 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7034 movLeft2Result (left, MSB16, result, MSB32, 0);
7035 movLeft2Result (left, LSB, result, MSB24, 0);
7037 aopPut (AOP (result), zero, MSB16);
7038 aopPut (AOP (result), zero, LSB);
7042 /* if more than 1 byte */
7043 else if (shCount >= 8)
7045 /* lower order three bytes goes to higher order three bytes */
7050 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7052 movLeft2Result (left, LSB, result, MSB16, 0);
7058 movLeft2Result (left, MSB24, result, MSB32, 0);
7059 movLeft2Result (left, MSB16, result, MSB24, 0);
7060 movLeft2Result (left, LSB, result, MSB16, 0);
7061 aopPut (AOP (result), zero, LSB);
7063 else if (shCount == 1)
7064 shiftLLong (left, result, MSB16);
7067 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7068 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7069 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7070 aopPut (AOP (result), zero, LSB);
7075 /* 1 <= shCount <= 7 */
7076 else if (shCount <= 2)
7078 shiftLLong (left, result, LSB);
7080 shiftLLong (result, result, LSB);
7082 /* 3 <= shCount <= 7, optimize */
7085 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7086 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7087 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7092 #ifdef BETTER_LITERAL_SHIFT
7093 /*-----------------------------------------------------------------*/
7094 /* genLeftShiftLiteral - left shifting by known count */
7095 /*-----------------------------------------------------------------*/
7097 genLeftShiftLiteral (operand * left,
7102 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7105 size = getSize (operandType (result));
7107 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7109 /* We only handle certain easy cases so far. */
7111 && (shCount < (size * 8))
7115 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7119 freeAsmop (right, NULL, ic, TRUE);
7121 aopOp(left, ic, FALSE, FALSE);
7122 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7125 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7127 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7128 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7130 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7133 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7135 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7136 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7138 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7144 emitcode ("; shift left ", "result %d, left %d", size,
7148 /* I suppose that the left size >= result size */
7151 _startLazyDPSEvaluation();
7154 movLeft2Result (left, size, result, size, 0);
7156 _endLazyDPSEvaluation();
7158 else if (shCount >= (size * 8))
7160 _startLazyDPSEvaluation();
7163 aopPut (AOP (result), zero, size);
7165 _endLazyDPSEvaluation();
7172 genlshOne (result, left, shCount);
7176 genlshTwo (result, left, shCount);
7180 genlshFour (result, left, shCount);
7184 fprintf(stderr, "*** ack! mystery literal shift!\n");
7188 freeAsmop (left, NULL, ic, TRUE);
7189 freeAsmop (result, NULL, ic, TRUE);
7194 /*-----------------------------------------------------------------*/
7195 /* genLeftShift - generates code for left shifting */
7196 /*-----------------------------------------------------------------*/
7198 genLeftShift (iCode * ic)
7200 operand *left, *right, *result;
7203 symbol *tlbl, *tlbl1;
7205 D (emitcode (";", "genLeftShift "););
7207 right = IC_RIGHT (ic);
7208 left = IC_LEFT (ic);
7209 result = IC_RESULT (ic);
7211 aopOp (right, ic, FALSE, FALSE);
7214 #ifdef BETTER_LITERAL_SHIFT
7215 /* if the shift count is known then do it
7216 as efficiently as possible */
7217 if (AOP_TYPE (right) == AOP_LIT)
7219 if (genLeftShiftLiteral (left, right, result, ic))
7226 /* shift count is unknown then we have to form
7227 a loop get the loop count in B : Note: we take
7228 only the lower order byte since shifting
7229 more that 32 bits make no sense anyway, ( the
7230 largest size of an object can be only 32 bits ) */
7232 if (AOP_TYPE (right) == AOP_LIT)
7234 /* Really should be handled by genLeftShiftLiteral,
7235 * but since I'm too lazy to fix that today, at least we can make
7236 * some small improvement.
7238 emitcode("mov", "b,#0x%02x",
7239 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7243 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7244 emitcode ("inc", "b");
7246 freeAsmop (right, NULL, ic, TRUE);
7247 aopOp (left, ic, FALSE, FALSE);
7248 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7250 /* now move the left to the result if they are not the
7252 if (!sameRegs (AOP (left), AOP (result)) &&
7253 AOP_SIZE (result) > 1)
7256 size = AOP_SIZE (result);
7258 _startLazyDPSEvaluation ();
7261 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7262 if (*l == '@' && (IS_AOP_PREG (result)))
7265 emitcode ("mov", "a,%s", l);
7266 aopPut (AOP (result), "a", offset);
7269 aopPut (AOP (result), l, offset);
7272 _endLazyDPSEvaluation ();
7275 tlbl = newiTempLabel (NULL);
7276 size = AOP_SIZE (result);
7278 tlbl1 = newiTempLabel (NULL);
7280 /* if it is only one byte then */
7283 symbol *tlbl1 = newiTempLabel (NULL);
7285 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7287 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7288 emitcode ("", "%05d$:", tlbl->key + 100);
7289 emitcode ("add", "a,acc");
7290 emitcode ("", "%05d$:", tlbl1->key + 100);
7291 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7292 aopPut (AOP (result), "a", 0);
7296 reAdjustPreg (AOP (result));
7298 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7299 emitcode ("", "%05d$:", tlbl->key + 100);
7300 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7302 emitcode ("add", "a,acc");
7303 aopPut (AOP (result), "a", offset++);
7304 _startLazyDPSEvaluation ();
7307 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7309 emitcode ("rlc", "a");
7310 aopPut (AOP (result), "a", offset++);
7312 _endLazyDPSEvaluation ();
7313 reAdjustPreg (AOP (result));
7315 emitcode ("", "%05d$:", tlbl1->key + 100);
7316 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7318 freeAsmop (left, NULL, ic, TRUE);
7319 freeAsmop (result, NULL, ic, TRUE);
7322 #ifdef BETTER_LITERAL_SHIFT
7323 /*-----------------------------------------------------------------*/
7324 /* genrshOne - right shift a one byte quantity by known count */
7325 /*-----------------------------------------------------------------*/
7327 genrshOne (operand * result, operand * left,
7328 int shCount, int sign)
7330 D (emitcode (";", "genrshOne"););
7331 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7335 #ifdef BETTER_LITERAL_SHIFT
7336 /*-----------------------------------------------------------------*/
7337 /* genrshTwo - right shift two bytes by known amount != 0 */
7338 /*-----------------------------------------------------------------*/
7340 genrshTwo (operand * result, operand * left,
7341 int shCount, int sign)
7343 D (emitcode (";", "genrshTwo"););
7345 /* if shCount >= 8 */
7349 _startLazyDPSEvaluation();
7352 shiftR1Left2Result (left, MSB16, result, LSB,
7357 movLeft2Result (left, MSB16, result, LSB, sign);
7359 addSign (result, MSB16, sign);
7360 _endLazyDPSEvaluation();
7363 /* 1 <= shCount <= 7 */
7366 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7373 /*-----------------------------------------------------------------*/
7374 /* shiftRLong - shift right one long from left to result */
7375 /* offl = LSB or MSB16 */
7376 /*-----------------------------------------------------------------*/
7378 shiftRLong (operand * left, int offl,
7379 operand * result, int sign)
7382 emitcode ("clr", "c");
7383 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7385 emitcode ("mov", "c,acc.7");
7386 emitcode ("rrc", "a");
7387 aopPut (AOP (result), "a", MSB32 - offl);
7389 /* add sign of "a" */
7390 addSign (result, MSB32, sign);
7392 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7393 emitcode ("rrc", "a");
7394 aopPut (AOP (result), "a", MSB24 - offl);
7396 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7397 emitcode ("rrc", "a");
7398 aopPut (AOP (result), "a", MSB16 - offl);
7402 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7403 emitcode ("rrc", "a");
7404 aopPut (AOP (result), "a", LSB);
7411 /*-----------------------------------------------------------------*/
7412 /* genrshFour - shift four byte by a known amount != 0 */
7413 /*-----------------------------------------------------------------*/
7415 genrshFour (operand * result, operand * left,
7416 int shCount, int sign)
7418 D (emitcode (";", "genrshFour");
7421 /* if shifting more that 3 bytes */
7426 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7428 movLeft2Result (left, MSB32, result, LSB, sign);
7429 addSign (result, MSB16, sign);
7431 else if (shCount >= 16)
7435 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7438 movLeft2Result (left, MSB24, result, LSB, 0);
7439 movLeft2Result (left, MSB32, result, MSB16, sign);
7441 addSign (result, MSB24, sign);
7443 else if (shCount >= 8)
7447 shiftRLong (left, MSB16, result, sign);
7448 else if (shCount == 0)
7450 movLeft2Result (left, MSB16, result, LSB, 0);
7451 movLeft2Result (left, MSB24, result, MSB16, 0);
7452 movLeft2Result (left, MSB32, result, MSB24, sign);
7453 addSign (result, MSB32, sign);
7457 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7458 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7459 /* the last shift is signed */
7460 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7461 addSign (result, MSB32, sign);
7465 { /* 1 <= shCount <= 7 */
7468 shiftRLong (left, LSB, result, sign);
7470 shiftRLong (result, LSB, result, sign);
7474 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7475 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7476 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7482 #ifdef BETTER_LITERAL_SHIFT
7483 /*-----------------------------------------------------------------*/
7484 /* genRightShiftLiteral - right shifting by known count */
7485 /*-----------------------------------------------------------------*/
7487 genRightShiftLiteral (operand * left,
7493 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7496 size = getSize (operandType (result));
7498 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7500 /* We only handle certain easy cases so far. */
7502 && (shCount < (size * 8))
7506 D(emitcode (";", "genRightShiftLiteral wimping out"););
7510 freeAsmop (right, NULL, ic, TRUE);
7512 aopOp (left, ic, FALSE, FALSE);
7513 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7516 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7520 /* test the LEFT size !!! */
7522 /* I suppose that the left size >= result size */
7525 size = getDataSize (result);
7526 _startLazyDPSEvaluation();
7529 movLeft2Result (left, size, result, size, 0);
7531 _endLazyDPSEvaluation();
7533 else if (shCount >= (size * 8))
7537 /* get sign in acc.7 */
7538 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7540 addSign (result, LSB, sign);
7547 genrshOne (result, left, shCount, sign);
7551 genrshTwo (result, left, shCount, sign);
7555 genrshFour (result, left, shCount, sign);
7562 freeAsmop (left, NULL, ic, TRUE);
7563 freeAsmop (result, NULL, ic, TRUE);
7569 /*-----------------------------------------------------------------*/
7570 /* genSignedRightShift - right shift of signed number */
7571 /*-----------------------------------------------------------------*/
7573 genSignedRightShift (iCode * ic)
7575 operand *right, *left, *result;
7578 symbol *tlbl, *tlbl1;
7580 D (emitcode (";", "genSignedRightShift "););
7582 /* we do it the hard way put the shift count in b
7583 and loop thru preserving the sign */
7585 right = IC_RIGHT (ic);
7586 left = IC_LEFT (ic);
7587 result = IC_RESULT (ic);
7589 aopOp (right, ic, FALSE, FALSE);
7591 #ifdef BETTER_LITERAL_SHIFT
7592 if (AOP_TYPE (right) == AOP_LIT)
7594 if (genRightShiftLiteral (left, right, result, ic, 1))
7600 /* shift count is unknown then we have to form
7601 a loop get the loop count in B : Note: we take
7602 only the lower order byte since shifting
7603 more that 32 bits make no sense anyway, ( the
7604 largest size of an object can be only 32 bits ) */
7606 if (AOP_TYPE (right) == AOP_LIT)
7608 /* Really should be handled by genRightShiftLiteral,
7609 * but since I'm too lazy to fix that today, at least we can make
7610 * some small improvement.
7612 emitcode("mov", "b,#0x%02x",
7613 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7617 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7618 emitcode ("inc", "b");
7620 freeAsmop (right, NULL, ic, TRUE);
7621 aopOp (left, ic, FALSE, FALSE);
7622 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7624 /* now move the left to the result if they are not the
7626 if (!sameRegs (AOP (left), AOP (result)) &&
7627 AOP_SIZE (result) > 1)
7630 size = AOP_SIZE (result);
7632 _startLazyDPSEvaluation ();
7635 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7636 if (*l == '@' && IS_AOP_PREG (result))
7639 emitcode ("mov", "a,%s", l);
7640 aopPut (AOP (result), "a", offset);
7643 aopPut (AOP (result), l, offset);
7646 _endLazyDPSEvaluation ();
7649 /* mov the highest order bit to OVR */
7650 tlbl = newiTempLabel (NULL);
7651 tlbl1 = newiTempLabel (NULL);
7653 size = AOP_SIZE (result);
7655 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7656 emitcode ("rlc", "a");
7657 emitcode ("mov", "ov,c");
7658 /* if it is only one byte then */
7661 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7663 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7664 emitcode ("", "%05d$:", tlbl->key + 100);
7665 emitcode ("mov", "c,ov");
7666 emitcode ("rrc", "a");
7667 emitcode ("", "%05d$:", tlbl1->key + 100);
7668 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7669 aopPut (AOP (result), "a", 0);
7673 reAdjustPreg (AOP (result));
7674 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7675 emitcode ("", "%05d$:", tlbl->key + 100);
7676 emitcode ("mov", "c,ov");
7677 _startLazyDPSEvaluation ();
7680 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7682 emitcode ("rrc", "a");
7683 aopPut (AOP (result), "a", offset--);
7685 _endLazyDPSEvaluation ();
7686 reAdjustPreg (AOP (result));
7687 emitcode ("", "%05d$:", tlbl1->key + 100);
7688 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7691 freeAsmop (left, NULL, ic, TRUE);
7692 freeAsmop (result, NULL, ic, TRUE);
7695 /*-----------------------------------------------------------------*/
7696 /* genRightShift - generate code for right shifting */
7697 /*-----------------------------------------------------------------*/
7699 genRightShift (iCode * ic)
7701 operand *right, *left, *result;
7705 symbol *tlbl, *tlbl1;
7707 D (emitcode (";", "genRightShift "););
7709 /* if signed then we do it the hard way preserve the
7710 sign bit moving it inwards */
7711 retype = getSpec (operandType (IC_RESULT (ic)));
7713 if (!SPEC_USIGN (retype))
7715 genSignedRightShift (ic);
7719 /* signed & unsigned types are treated the same : i.e. the
7720 signed is NOT propagated inwards : quoting from the
7721 ANSI - standard : "for E1 >> E2, is equivalent to division
7722 by 2**E2 if unsigned or if it has a non-negative value,
7723 otherwise the result is implementation defined ", MY definition
7724 is that the sign does not get propagated */
7726 right = IC_RIGHT (ic);
7727 left = IC_LEFT (ic);
7728 result = IC_RESULT (ic);
7730 aopOp (right, ic, FALSE, FALSE);
7732 #ifdef BETTER_LITERAL_SHIFT
7733 /* if the shift count is known then do it
7734 as efficiently as possible */
7735 if (AOP_TYPE (right) == AOP_LIT)
7737 if (genRightShiftLiteral (left, right, result, ic, 0))
7744 /* shift count is unknown then we have to form
7745 a loop get the loop count in B : Note: we take
7746 only the lower order byte since shifting
7747 more that 32 bits make no sense anyway, ( the
7748 largest size of an object can be only 32 bits ) */
7750 if (AOP_TYPE (right) == AOP_LIT)
7752 /* Really should be handled by genRightShiftLiteral,
7753 * but since I'm too lazy to fix that today, at least we can make
7754 * some small improvement.
7756 emitcode("mov", "b,#0x%02x",
7757 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7761 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7762 emitcode ("inc", "b");
7764 freeAsmop (right, NULL, ic, TRUE);
7765 aopOp (left, ic, FALSE, FALSE);
7766 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7768 /* now move the left to the result if they are not the
7770 if (!sameRegs (AOP (left), AOP (result)) &&
7771 AOP_SIZE (result) > 1)
7774 size = AOP_SIZE (result);
7776 _startLazyDPSEvaluation ();
7779 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7780 if (*l == '@' && IS_AOP_PREG (result))
7783 emitcode ("mov", "a,%s", l);
7784 aopPut (AOP (result), "a", offset);
7787 aopPut (AOP (result), l, offset);
7790 _endLazyDPSEvaluation ();
7793 tlbl = newiTempLabel (NULL);
7794 tlbl1 = newiTempLabel (NULL);
7795 size = AOP_SIZE (result);
7798 /* if it is only one byte then */
7801 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7803 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7804 emitcode ("", "%05d$:", tlbl->key + 100);
7806 emitcode ("rrc", "a");
7807 emitcode ("", "%05d$:", tlbl1->key + 100);
7808 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7809 aopPut (AOP (result), "a", 0);
7813 reAdjustPreg (AOP (result));
7814 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7815 emitcode ("", "%05d$:", tlbl->key + 100);
7817 _startLazyDPSEvaluation ();
7820 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7822 emitcode ("rrc", "a");
7823 aopPut (AOP (result), "a", offset--);
7825 _endLazyDPSEvaluation ();
7826 reAdjustPreg (AOP (result));
7828 emitcode ("", "%05d$:", tlbl1->key + 100);
7829 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7832 freeAsmop (left, NULL, ic, TRUE);
7833 freeAsmop (result, NULL, ic, TRUE);
7836 /*-----------------------------------------------------------------*/
7837 /* genUnpackBits - generates code for unpacking bits */
7838 /*-----------------------------------------------------------------*/
7840 genUnpackBits (operand * result, char *rname, int ptype)
7847 D (emitcode (";", "genUnpackBits ");
7850 etype = getSpec (operandType (result));
7852 /* read the first byte */
7858 emitcode ("mov", "a,@%s", rname);
7862 emitcode ("movx", "a,@%s", rname);
7866 emitcode ("movx", "a,@dptr");
7870 emitcode ("clr", "a");
7871 emitcode ("movc", "a", "@a+dptr");
7875 emitcode ("lcall", "__gptrget");
7879 /* if we have bitdisplacement then it fits */
7880 /* into this byte completely or if length is */
7881 /* less than a byte */
7882 if ((shCnt = SPEC_BSTR (etype)) ||
7883 (SPEC_BLEN (etype) <= 8))
7886 /* shift right acc */
7889 emitcode ("anl", "a,#0x%02x",
7890 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7891 aopPut (AOP (result), "a", offset);
7895 /* bit field did not fit in a byte */
7896 rlen = SPEC_BLEN (etype) - 8;
7897 aopPut (AOP (result), "a", offset++);
7906 emitcode ("inc", "%s", rname);
7907 emitcode ("mov", "a,@%s", rname);
7911 emitcode ("inc", "%s", rname);
7912 emitcode ("movx", "a,@%s", rname);
7916 emitcode ("inc", "dptr");
7917 emitcode ("movx", "a,@dptr");
7921 emitcode ("clr", "a");
7922 emitcode ("inc", "dptr");
7923 emitcode ("movc", "a", "@a+dptr");
7927 emitcode ("inc", "dptr");
7928 emitcode ("lcall", "__gptrget");
7933 /* if we are done */
7937 aopPut (AOP (result), "a", offset++);
7943 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7944 aopPut (AOP (result), "a", offset);
7951 /*-----------------------------------------------------------------*/
7952 /* genDataPointerGet - generates code when ptr offset is known */
7953 /*-----------------------------------------------------------------*/
7955 genDataPointerGet (operand * left,
7961 int size, offset = 0;
7962 aopOp (result, ic, TRUE, FALSE);
7964 /* get the string representation of the name */
7965 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7966 size = AOP_SIZE (result);
7967 _startLazyDPSEvaluation ();
7971 sprintf (buffer, "(%s + %d)", l + 1, offset);
7973 sprintf (buffer, "%s", l + 1);
7974 aopPut (AOP (result), buffer, offset++);
7976 _endLazyDPSEvaluation ();
7978 freeAsmop (left, NULL, ic, TRUE);
7979 freeAsmop (result, NULL, ic, TRUE);
7982 /*-----------------------------------------------------------------*/
7983 /* genNearPointerGet - emitcode for near pointer fetch */
7984 /*-----------------------------------------------------------------*/
7986 genNearPointerGet (operand * left,
7993 sym_link *rtype, *retype, *letype;
7994 sym_link *ltype = operandType (left);
7997 rtype = operandType (result);
7998 retype = getSpec (rtype);
7999 letype = getSpec (ltype);
8001 aopOp (left, ic, FALSE, FALSE);
8003 /* if left is rematerialisable and
8004 result is not bit variable type and
8005 the left is pointer to data space i.e
8006 lower 128 bytes of space */
8007 if (AOP_TYPE (left) == AOP_IMMD &&
8008 !IS_BITVAR (retype) &&
8009 !IS_BITVAR (letype) &&
8010 DCL_TYPE (ltype) == POINTER)
8012 genDataPointerGet (left, result, ic);
8016 /* if the value is already in a pointer register
8017 then don't need anything more */
8018 if (!AOP_INPREG (AOP (left)))
8020 /* otherwise get a free pointer register */
8022 preg = getFreePtr (ic, &aop, FALSE);
8023 emitcode ("mov", "%s,%s",
8025 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8029 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8031 freeAsmop (left, NULL, ic, TRUE);
8032 aopOp (result, ic, FALSE, FALSE);
8034 /* if bitfield then unpack the bits */
8035 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8036 genUnpackBits (result, rname, POINTER);
8039 /* we have can just get the values */
8040 int size = AOP_SIZE (result);
8045 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8048 emitcode ("mov", "a,@%s", rname);
8049 aopPut (AOP (result), "a", offset);
8053 sprintf (buffer, "@%s", rname);
8054 aopPut (AOP (result), buffer, offset);
8058 emitcode ("inc", "%s", rname);
8062 /* now some housekeeping stuff */
8065 /* we had to allocate for this iCode */
8066 freeAsmop (NULL, aop, ic, TRUE);
8070 /* we did not allocate which means left
8071 already in a pointer register, then
8072 if size > 0 && this could be used again
8073 we have to point it back to where it
8075 if (AOP_SIZE (result) > 1 &&
8076 !OP_SYMBOL (left)->remat &&
8077 (OP_SYMBOL (left)->liveTo > ic->seq ||
8080 int size = AOP_SIZE (result) - 1;
8082 emitcode ("dec", "%s", rname);
8087 freeAsmop (result, NULL, ic, TRUE);
8091 /*-----------------------------------------------------------------*/
8092 /* genPagedPointerGet - emitcode for paged pointer fetch */
8093 /*-----------------------------------------------------------------*/
8095 genPagedPointerGet (operand * left,
8102 sym_link *rtype, *retype, *letype;
8104 rtype = operandType (result);
8105 retype = getSpec (rtype);
8106 letype = getSpec (operandType (left));
8107 aopOp (left, ic, FALSE, FALSE);
8109 /* if the value is already in a pointer register
8110 then don't need anything more */
8111 if (!AOP_INPREG (AOP (left)))
8113 /* otherwise get a free pointer register */
8115 preg = getFreePtr (ic, &aop, FALSE);
8116 emitcode ("mov", "%s,%s",
8118 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8122 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8124 freeAsmop (left, NULL, ic, TRUE);
8125 aopOp (result, ic, FALSE, FALSE);
8127 /* if bitfield then unpack the bits */
8128 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8129 genUnpackBits (result, rname, PPOINTER);
8132 /* we have can just get the values */
8133 int size = AOP_SIZE (result);
8139 emitcode ("movx", "a,@%s", rname);
8140 aopPut (AOP (result), "a", offset);
8145 emitcode ("inc", "%s", rname);
8149 /* now some housekeeping stuff */
8152 /* we had to allocate for this iCode */
8153 freeAsmop (NULL, aop, ic, TRUE);
8157 /* we did not allocate which means left
8158 already in a pointer register, then
8159 if size > 0 && this could be used again
8160 we have to point it back to where it
8162 if (AOP_SIZE (result) > 1 &&
8163 !OP_SYMBOL (left)->remat &&
8164 (OP_SYMBOL (left)->liveTo > ic->seq ||
8167 int size = AOP_SIZE (result) - 1;
8169 emitcode ("dec", "%s", rname);
8174 freeAsmop (result, NULL, ic, TRUE);
8179 /*-----------------------------------------------------------------*/
8180 /* genFarPointerGet - gget value from far space */
8181 /*-----------------------------------------------------------------*/
8183 genFarPointerGet (operand * left,
8184 operand * result, iCode * ic)
8187 sym_link *retype = getSpec (operandType (result));
8188 sym_link *letype = getSpec (operandType (left));
8189 D (emitcode (";", "genFarPointerGet");
8192 aopOp (left, ic, FALSE, FALSE);
8194 /* if the operand is already in dptr
8195 then we do nothing else we move the value to dptr */
8196 if (AOP_TYPE (left) != AOP_STR)
8198 /* if this is remateriazable */
8199 if (AOP_TYPE (left) == AOP_IMMD)
8201 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8205 /* we need to get it byte by byte */
8206 _startLazyDPSEvaluation ();
8207 if (AOP_TYPE (left) != AOP_DPTR)
8209 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8210 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8211 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8215 /* We need to generate a load to DPTR indirect through DPTR. */
8216 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8218 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8219 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8220 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8221 emitcode ("pop", "dph");
8222 emitcode ("pop", "dpl");
8224 _endLazyDPSEvaluation ();
8227 /* so dptr know contains the address */
8228 freeAsmop (left, NULL, ic, TRUE);
8229 aopOp (result, ic, FALSE, TRUE);
8231 /* if bit then unpack */
8232 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8233 genUnpackBits (result, "dptr", FPOINTER);
8236 size = AOP_SIZE (result);
8239 _startLazyDPSEvaluation ();
8246 emitcode ("movx", "a,@dptr");
8248 emitcode ("inc", "dptr");
8250 aopPut (AOP (result), "a", offset++);
8252 _endLazyDPSEvaluation ();
8255 freeAsmop (result, NULL, ic, TRUE);
8258 /*-----------------------------------------------------------------*/
8259 /* emitcodePointerGet - gget value from code space */
8260 /*-----------------------------------------------------------------*/
8262 emitcodePointerGet (operand * left,
8263 operand * result, iCode * ic)
8266 sym_link *retype = getSpec (operandType (result));
8268 aopOp (left, ic, FALSE, FALSE);
8270 /* if the operand is already in dptr
8271 then we do nothing else we move the value to dptr */
8272 if (AOP_TYPE (left) != AOP_STR)
8274 /* if this is remateriazable */
8275 if (AOP_TYPE (left) == AOP_IMMD)
8277 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8280 { /* we need to get it byte by byte */
8281 _startLazyDPSEvaluation ();
8282 if (AOP_TYPE (left) != AOP_DPTR)
8284 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8285 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8286 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8290 /* We need to generate a load to DPTR indirect through DPTR. */
8291 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8293 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8294 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8295 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8296 emitcode ("pop", "dph");
8297 emitcode ("pop", "dpl");
8299 _endLazyDPSEvaluation ();
8302 /* so dptr know contains the address */
8303 freeAsmop (left, NULL, ic, TRUE);
8304 aopOp (result, ic, FALSE, TRUE);
8306 /* if bit then unpack */
8307 if (IS_BITVAR (retype))
8308 genUnpackBits (result, "dptr", CPOINTER);
8311 size = AOP_SIZE (result);
8314 _startLazyDPSEvaluation ();
8320 emitcode ("clr", "a");
8321 emitcode ("movc", "a,@a+dptr");
8323 emitcode ("inc", "dptr");
8324 aopPut (AOP (result), "a", offset++);
8326 _endLazyDPSEvaluation ();
8329 freeAsmop (result, NULL, ic, TRUE);
8332 /*-----------------------------------------------------------------*/
8333 /* genGenPointerGet - gget value from generic pointer space */
8334 /*-----------------------------------------------------------------*/
8336 genGenPointerGet (operand * left,
8337 operand * result, iCode * ic)
8340 sym_link *retype = getSpec (operandType (result));
8341 sym_link *letype = getSpec (operandType (left));
8343 D (emitcode (";", "genGenPointerGet "); );
8345 aopOp (left, ic, FALSE, TRUE);
8347 /* if the operand is already in dptr
8348 then we do nothing else we move the value to dptr */
8349 if (AOP_TYPE (left) != AOP_STR)
8351 /* if this is remateriazable */
8352 if (AOP_TYPE (left) == AOP_IMMD)
8354 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8355 emitcode ("mov", "b,#%d", pointerCode (retype));
8358 { /* we need to get it byte by byte */
8359 _startLazyDPSEvaluation ();
8360 if (AOP(left)->type==AOP_DPTR2) {
8362 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8365 emitcode ("mov", "dpl,%s", l);
8366 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8369 emitcode ("mov", "dph,%s", l);
8370 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8373 emitcode ("mov", "dpx,%s", l);
8374 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8376 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8377 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8378 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8379 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8381 _endLazyDPSEvaluation ();
8384 /* so dptr know contains the address */
8385 freeAsmop (left, NULL, ic, TRUE);
8386 aopOp (result, ic, FALSE, TRUE);
8388 /* if bit then unpack */
8389 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8390 genUnpackBits (result, "dptr", GPOINTER);
8393 size = AOP_SIZE (result);
8398 emitcode ("lcall", "__gptrget");
8399 aopPut (AOP (result), "a", offset++);
8401 emitcode ("inc", "dptr");
8405 freeAsmop (result, NULL, ic, TRUE);
8408 /*-----------------------------------------------------------------*/
8409 /* genPointerGet - generate code for pointer get */
8410 /*-----------------------------------------------------------------*/
8412 genPointerGet (iCode * ic)
8414 operand *left, *result;
8415 sym_link *type, *etype;
8418 D (emitcode (";", "genPointerGet ");
8421 left = IC_LEFT (ic);
8422 result = IC_RESULT (ic);
8424 /* depending on the type of pointer we need to
8425 move it to the correct pointer register */
8426 type = operandType (left);
8427 etype = getSpec (type);
8428 /* if left is of type of pointer then it is simple */
8429 if (IS_PTR (type) && !IS_FUNC (type->next))
8430 p_type = DCL_TYPE (type);
8433 /* we have to go by the storage class */
8434 p_type = PTR_TYPE (SPEC_OCLS (etype));
8437 /* now that we have the pointer type we assign
8438 the pointer values */
8444 genNearPointerGet (left, result, ic);
8448 genPagedPointerGet (left, result, ic);
8452 genFarPointerGet (left, result, ic);
8456 emitcodePointerGet (left, result, ic);
8460 genGenPointerGet (left, result, ic);
8466 /*-----------------------------------------------------------------*/
8467 /* genPackBits - generates code for packed bit storage */
8468 /*-----------------------------------------------------------------*/
8470 genPackBits (sym_link * etype,
8472 char *rname, int p_type)
8480 blen = SPEC_BLEN (etype);
8481 bstr = SPEC_BSTR (etype);
8483 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8486 /* if the bit lenth is less than or */
8487 /* it exactly fits a byte then */
8488 if (SPEC_BLEN (etype) <= 8)
8490 shCount = SPEC_BSTR (etype);
8492 /* shift left acc */
8495 if (SPEC_BLEN (etype) < 8)
8496 { /* if smaller than a byte */
8502 emitcode ("mov", "b,a");
8503 emitcode ("mov", "a,@%s", rname);
8507 emitcode ("mov", "b,a");
8508 emitcode ("movx", "a,@dptr");
8512 emitcode ("push", "b");
8513 emitcode ("push", "acc");
8514 emitcode ("lcall", "__gptrget");
8515 emitcode ("pop", "b");
8519 emitcode ("anl", "a,#0x%02x", (unsigned char)
8520 ((unsigned char) (0xFF << (blen + bstr)) |
8521 (unsigned char) (0xFF >> (8 - bstr))));
8522 emitcode ("orl", "a,b");
8523 if (p_type == GPOINTER)
8524 emitcode ("pop", "b");
8531 emitcode ("mov", "@%s,a", rname);
8535 emitcode ("movx", "@dptr,a");
8539 emitcode ("lcall", "__gptrput");
8544 if (SPEC_BLEN (etype) <= 8)
8547 emitcode ("inc", "%s", rname);
8548 rLen = SPEC_BLEN (etype);
8550 /* now generate for lengths greater than one byte */
8554 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8566 emitcode ("mov", "@%s,a", rname);
8569 emitcode ("mov", "@%s,%s", rname, l);
8574 emitcode ("movx", "@dptr,a");
8579 emitcode ("lcall", "__gptrput");
8582 emitcode ("inc", "%s", rname);
8587 /* last last was not complete */
8590 /* save the byte & read byte */
8594 emitcode ("mov", "b,a");
8595 emitcode ("mov", "a,@%s", rname);
8599 emitcode ("mov", "b,a");
8600 emitcode ("movx", "a,@dptr");
8604 emitcode ("push", "b");
8605 emitcode ("push", "acc");
8606 emitcode ("lcall", "__gptrget");
8607 emitcode ("pop", "b");
8611 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8612 emitcode ("orl", "a,b");
8615 if (p_type == GPOINTER)
8616 emitcode ("pop", "b");
8622 emitcode ("mov", "@%s,a", rname);
8626 emitcode ("movx", "@dptr,a");
8630 emitcode ("lcall", "__gptrput");
8634 /*-----------------------------------------------------------------*/
8635 /* genDataPointerSet - remat pointer to data space */
8636 /*-----------------------------------------------------------------*/
8638 genDataPointerSet (operand * right,
8642 int size, offset = 0;
8643 char *l, buffer[256];
8645 aopOp (right, ic, FALSE, FALSE);
8647 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8648 size = AOP_SIZE (right);
8652 sprintf (buffer, "(%s + %d)", l + 1, offset);
8654 sprintf (buffer, "%s", l + 1);
8655 emitcode ("mov", "%s,%s", buffer,
8656 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8659 freeAsmop (right, NULL, ic, TRUE);
8660 freeAsmop (result, NULL, ic, TRUE);
8663 /*-----------------------------------------------------------------*/
8664 /* genNearPointerSet - emitcode for near pointer put */
8665 /*-----------------------------------------------------------------*/
8667 genNearPointerSet (operand * right,
8674 sym_link *retype, *letype;
8675 sym_link *ptype = operandType (result);
8677 retype = getSpec (operandType (right));
8678 letype = getSpec (ptype);
8680 aopOp (result, ic, FALSE, FALSE);
8682 /* if the result is rematerializable &
8683 in data space & not a bit variable */
8684 if (AOP_TYPE (result) == AOP_IMMD &&
8685 DCL_TYPE (ptype) == POINTER &&
8686 !IS_BITVAR (retype) &&
8687 !IS_BITVAR (letype))
8689 genDataPointerSet (right, result, ic);
8693 /* if the value is already in a pointer register
8694 then don't need anything more */
8695 if (!AOP_INPREG (AOP (result)))
8697 /* otherwise get a free pointer register */
8699 preg = getFreePtr (ic, &aop, FALSE);
8700 emitcode ("mov", "%s,%s",
8702 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8706 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8708 freeAsmop (result, NULL, ic, TRUE);
8709 aopOp (right, ic, FALSE, FALSE);
8711 /* if bitfield then unpack the bits */
8712 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8713 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8716 /* we have can just get the values */
8717 int size = AOP_SIZE (right);
8722 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8726 emitcode ("mov", "@%s,a", rname);
8729 emitcode ("mov", "@%s,%s", rname, l);
8731 emitcode ("inc", "%s", rname);
8736 /* now some housekeeping stuff */
8739 /* we had to allocate for this iCode */
8740 freeAsmop (NULL, aop, ic, TRUE);
8744 /* we did not allocate which means left
8745 already in a pointer register, then
8746 if size > 0 && this could be used again
8747 we have to point it back to where it
8749 if (AOP_SIZE (right) > 1 &&
8750 !OP_SYMBOL (result)->remat &&
8751 (OP_SYMBOL (result)->liveTo > ic->seq ||
8754 int size = AOP_SIZE (right) - 1;
8756 emitcode ("dec", "%s", rname);
8761 freeAsmop (right, NULL, ic, TRUE);
8766 /*-----------------------------------------------------------------*/
8767 /* genPagedPointerSet - emitcode for Paged pointer put */
8768 /*-----------------------------------------------------------------*/
8770 genPagedPointerSet (operand * right,
8777 sym_link *retype, *letype;
8779 retype = getSpec (operandType (right));
8780 letype = getSpec (operandType (result));
8782 aopOp (result, ic, FALSE, FALSE);
8784 /* if the value is already in a pointer register
8785 then don't need anything more */
8786 if (!AOP_INPREG (AOP (result)))
8788 /* otherwise get a free pointer register */
8790 preg = getFreePtr (ic, &aop, FALSE);
8791 emitcode ("mov", "%s,%s",
8793 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8797 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8799 freeAsmop (result, NULL, ic, TRUE);
8800 aopOp (right, ic, FALSE, FALSE);
8802 /* if bitfield then unpack the bits */
8803 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8804 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8807 /* we have can just get the values */
8808 int size = AOP_SIZE (right);
8813 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8816 emitcode ("movx", "@%s,a", rname);
8819 emitcode ("inc", "%s", rname);
8825 /* now some housekeeping stuff */
8828 /* we had to allocate for this iCode */
8829 freeAsmop (NULL, aop, ic, TRUE);
8833 /* we did not allocate which means left
8834 already in a pointer register, then
8835 if size > 0 && this could be used again
8836 we have to point it back to where it
8838 if (AOP_SIZE (right) > 1 &&
8839 !OP_SYMBOL (result)->remat &&
8840 (OP_SYMBOL (result)->liveTo > ic->seq ||
8843 int size = AOP_SIZE (right) - 1;
8845 emitcode ("dec", "%s", rname);
8850 freeAsmop (right, NULL, ic, TRUE);
8855 /*-----------------------------------------------------------------*/
8856 /* genFarPointerSet - set value from far space */
8857 /*-----------------------------------------------------------------*/
8859 genFarPointerSet (operand * right,
8860 operand * result, iCode * ic)
8863 sym_link *retype = getSpec (operandType (right));
8864 sym_link *letype = getSpec (operandType (result));
8866 aopOp (result, ic, FALSE, FALSE);
8868 /* if the operand is already in dptr
8869 then we do nothing else we move the value to dptr */
8870 if (AOP_TYPE (result) != AOP_STR)
8872 /* if this is remateriazable */
8873 if (AOP_TYPE (result) == AOP_IMMD)
8874 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8877 /* we need to get it byte by byte */
8878 _startLazyDPSEvaluation ();
8879 if (AOP_TYPE (result) != AOP_DPTR)
8881 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8882 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8883 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8887 /* We need to generate a load to DPTR indirect through DPTR. */
8888 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8890 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8891 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8892 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8893 emitcode ("pop", "dph");
8894 emitcode ("pop", "dpl");
8896 _endLazyDPSEvaluation ();
8899 /* so dptr know contains the address */
8900 freeAsmop (result, NULL, ic, TRUE);
8901 aopOp (right, ic, FALSE, TRUE);
8903 /* if bit then unpack */
8904 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8905 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8908 size = AOP_SIZE (right);
8911 _startLazyDPSEvaluation ();
8914 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8920 emitcode ("movx", "@dptr,a");
8922 emitcode ("inc", "dptr");
8924 _endLazyDPSEvaluation ();
8927 freeAsmop (right, NULL, ic, TRUE);
8930 /*-----------------------------------------------------------------*/
8931 /* genGenPointerSet - set value from generic pointer space */
8932 /*-----------------------------------------------------------------*/
8934 genGenPointerSet (operand * right,
8935 operand * result, iCode * ic)
8938 sym_link *retype = getSpec (operandType (right));
8939 sym_link *letype = getSpec (operandType (result));
8941 aopOp (result, ic, FALSE, TRUE);
8943 /* if the operand is already in dptr
8944 then we do nothing else we move the value to dptr */
8945 if (AOP_TYPE (result) != AOP_STR)
8947 _startLazyDPSEvaluation ();
8948 /* if this is remateriazable */
8949 if (AOP_TYPE (result) == AOP_IMMD)
8951 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8952 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8955 { /* we need to get it byte by byte */
8956 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8957 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8958 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8959 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8961 _endLazyDPSEvaluation ();
8963 /* so dptr know contains the address */
8964 freeAsmop (result, NULL, ic, TRUE);
8965 aopOp (right, ic, FALSE, TRUE);
8967 /* if bit then unpack */
8968 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8969 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8972 size = AOP_SIZE (right);
8975 _startLazyDPSEvaluation ();
8978 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8984 emitcode ("lcall", "__gptrput");
8986 emitcode ("inc", "dptr");
8988 _endLazyDPSEvaluation ();
8991 freeAsmop (right, NULL, ic, TRUE);
8994 /*-----------------------------------------------------------------*/
8995 /* genPointerSet - stores the value into a pointer location */
8996 /*-----------------------------------------------------------------*/
8998 genPointerSet (iCode * ic)
9000 operand *right, *result;
9001 sym_link *type, *etype;
9004 D (emitcode (";", "genPointerSet ");
9007 right = IC_RIGHT (ic);
9008 result = IC_RESULT (ic);
9010 /* depending on the type of pointer we need to
9011 move it to the correct pointer register */
9012 type = operandType (result);
9013 etype = getSpec (type);
9014 /* if left is of type of pointer then it is simple */
9015 if (IS_PTR (type) && !IS_FUNC (type->next))
9017 p_type = DCL_TYPE (type);
9021 /* we have to go by the storage class */
9022 p_type = PTR_TYPE (SPEC_OCLS (etype));
9025 /* now that we have the pointer type we assign
9026 the pointer values */
9032 genNearPointerSet (right, result, ic);
9036 genPagedPointerSet (right, result, ic);
9040 genFarPointerSet (right, result, ic);
9044 genGenPointerSet (right, result, ic);
9050 /*-----------------------------------------------------------------*/
9051 /* genIfx - generate code for Ifx statement */
9052 /*-----------------------------------------------------------------*/
9054 genIfx (iCode * ic, iCode * popIc)
9056 operand *cond = IC_COND (ic);
9059 D (emitcode (";", "genIfx "););
9061 aopOp (cond, ic, FALSE, FALSE);
9063 /* get the value into acc */
9064 if (AOP_TYPE (cond) != AOP_CRY)
9068 /* the result is now in the accumulator */
9069 freeAsmop (cond, NULL, ic, TRUE);
9071 /* if there was something to be popped then do it */
9075 /* if the condition is a bit variable */
9076 if (isbit && IS_ITEMP (cond) &&
9078 genIfxJump (ic, SPIL_LOC (cond)->rname);
9079 else if (isbit && !IS_ITEMP (cond))
9080 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9082 genIfxJump (ic, "a");
9087 /*-----------------------------------------------------------------*/
9088 /* genAddrOf - generates code for address of */
9089 /*-----------------------------------------------------------------*/
9091 genAddrOf (iCode * ic)
9093 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9096 D (emitcode (";", "genAddrOf ");
9099 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9101 /* if the operand is on the stack then we
9102 need to get the stack offset of this
9106 /* if it has an offset then we need to compute
9110 emitcode ("mov", "a,_bp");
9111 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9112 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9116 /* we can just move _bp */
9117 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9119 /* fill the result with zero */
9120 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9123 if (options.stack10bit && size < (FPTRSIZE - 1))
9126 "*** warning: pointer to stack var truncated.\n");
9133 if (options.stack10bit && offset == 2)
9135 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9139 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9146 /* object not on stack then we need the name */
9147 size = AOP_SIZE (IC_RESULT (ic));
9152 char s[SDCC_NAME_MAX];
9154 sprintf (s, "#(%s >> %d)",
9158 sprintf (s, "#%s", sym->rname);
9159 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9163 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9167 /*-----------------------------------------------------------------*/
9168 /* genFarFarAssign - assignment when both are in far space */
9169 /*-----------------------------------------------------------------*/
9171 genFarFarAssign (operand * result, operand * right, iCode * ic)
9173 int size = AOP_SIZE (right);
9175 symbol *rSym = NULL;
9179 /* quick & easy case. */
9180 D(emitcode(";","genFarFarAssign (1 byte case)"););
9181 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9182 freeAsmop (right, NULL, ic, FALSE);
9183 /* now assign DPTR to result */
9185 aopOp(result, ic, FALSE, FALSE);
9187 aopPut(AOP(result), "a", 0);
9188 freeAsmop(result, NULL, ic, FALSE);
9192 /* See if we've got an underlying symbol to abuse. */
9193 if (IS_SYMOP(result) && OP_SYMBOL(result))
9195 if (IS_TRUE_SYMOP(result))
9197 rSym = OP_SYMBOL(result);
9199 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9201 rSym = OP_SYMBOL(result)->usl.spillLoc;
9205 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9207 /* We can use the '390 auto-toggle feature to good effect here. */
9209 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9210 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9211 emitcode ("mov", "dptr,#%s", rSym->rname);
9212 /* DP2 = result, DP1 = right, DP1 is current. */
9215 emitcode("movx", "a,@dptr");
9216 emitcode("movx", "@dptr,a");
9219 emitcode("inc", "dptr");
9220 emitcode("inc", "dptr");
9223 emitcode("mov", "dps, #0");
9224 freeAsmop (right, NULL, ic, FALSE);
9228 D (emitcode (";", "genFarFarAssign"););
9229 aopOp (result, ic, TRUE, TRUE);
9231 _startLazyDPSEvaluation ();
9235 aopPut (AOP (result),
9236 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9239 _endLazyDPSEvaluation ();
9240 freeAsmop (result, NULL, ic, FALSE);
9241 freeAsmop (right, NULL, ic, FALSE);
9245 /*-----------------------------------------------------------------*/
9246 /* genAssign - generate code for assignment */
9247 /*-----------------------------------------------------------------*/
9249 genAssign (iCode * ic)
9251 operand *result, *right;
9253 unsigned long lit = 0L;
9255 D (emitcode (";", "genAssign ");
9258 result = IC_RESULT (ic);
9259 right = IC_RIGHT (ic);
9261 /* if they are the same */
9262 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9265 aopOp (right, ic, FALSE, FALSE);
9267 emitcode (";", "genAssign: resultIsFar = %s",
9268 isOperandInFarSpace (result) ?
9271 /* special case both in far space */
9272 if ((AOP_TYPE (right) == AOP_DPTR ||
9273 AOP_TYPE (right) == AOP_DPTR2) &&
9274 /* IS_TRUE_SYMOP(result) && */
9275 isOperandInFarSpace (result))
9277 genFarFarAssign (result, right, ic);
9281 aopOp (result, ic, TRUE, FALSE);
9283 /* if they are the same registers */
9284 if (sameRegs (AOP (right), AOP (result)))
9287 /* if the result is a bit */
9288 if (AOP_TYPE (result) == AOP_CRY)
9291 /* if the right size is a literal then
9292 we know what the value is */
9293 if (AOP_TYPE (right) == AOP_LIT)
9295 if (((int) operandLitValue (right)))
9296 aopPut (AOP (result), one, 0);
9298 aopPut (AOP (result), zero, 0);
9302 /* the right is also a bit variable */
9303 if (AOP_TYPE (right) == AOP_CRY)
9305 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9306 aopPut (AOP (result), "c", 0);
9312 aopPut (AOP (result), "a", 0);
9316 /* bit variables done */
9318 size = AOP_SIZE (result);
9320 if (AOP_TYPE (right) == AOP_LIT)
9321 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9324 (AOP_TYPE (result) != AOP_REG) &&
9325 (AOP_TYPE (right) == AOP_LIT) &&
9326 !IS_FLOAT (operandType (right)))
9328 _startLazyDPSEvaluation ();
9329 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9331 aopPut (AOP (result),
9332 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9337 /* And now fill the rest with zeros. */
9340 emitcode ("clr", "a");
9344 aopPut (AOP (result), "a", offset++);
9346 _endLazyDPSEvaluation ();
9350 _startLazyDPSEvaluation ();
9353 aopPut (AOP (result),
9354 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9358 _endLazyDPSEvaluation ();
9362 freeAsmop (right, NULL, ic, FALSE);
9363 freeAsmop (result, NULL, ic, TRUE);
9366 /*-----------------------------------------------------------------*/
9367 /* genJumpTab - generates code for jump table */
9368 /*-----------------------------------------------------------------*/
9370 genJumpTab (iCode * ic)
9375 D (emitcode (";", "genJumpTab ");
9378 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9379 /* get the condition into accumulator */
9380 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9382 /* multiply by four! */
9383 emitcode ("add", "a,acc");
9384 emitcode ("add", "a,acc");
9385 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9387 jtab = newiTempLabel (NULL);
9388 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9389 emitcode ("jmp", "@a+dptr");
9390 emitcode ("", "%05d$:", jtab->key + 100);
9391 /* now generate the jump labels */
9392 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9393 jtab = setNextItem (IC_JTLABELS (ic)))
9394 emitcode ("ljmp", "%05d$", jtab->key + 100);
9398 /*-----------------------------------------------------------------*/
9399 /* genCast - gen code for casting */
9400 /*-----------------------------------------------------------------*/
9402 genCast (iCode * ic)
9404 operand *result = IC_RESULT (ic);
9405 sym_link *ctype = operandType (IC_LEFT (ic));
9406 sym_link *rtype = operandType (IC_RIGHT (ic));
9407 operand *right = IC_RIGHT (ic);
9410 D (emitcode (";", "genCast ");
9413 /* if they are equivalent then do nothing */
9414 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9417 aopOp (right, ic, FALSE, FALSE);
9418 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9420 /* if the result is a bit */
9421 if (AOP_TYPE (result) == AOP_CRY)
9423 /* if the right size is a literal then
9424 we know what the value is */
9425 if (AOP_TYPE (right) == AOP_LIT)
9427 if (((int) operandLitValue (right)))
9428 aopPut (AOP (result), one, 0);
9430 aopPut (AOP (result), zero, 0);
9435 /* the right is also a bit variable */
9436 if (AOP_TYPE (right) == AOP_CRY)
9438 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9439 aopPut (AOP (result), "c", 0);
9445 aopPut (AOP (result), "a", 0);
9449 /* if they are the same size : or less */
9450 if (AOP_SIZE (result) <= AOP_SIZE (right))
9453 /* if they are in the same place */
9454 if (sameRegs (AOP (right), AOP (result)))
9457 /* if they in different places then copy */
9458 size = AOP_SIZE (result);
9460 _startLazyDPSEvaluation ();
9463 aopPut (AOP (result),
9464 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9468 _endLazyDPSEvaluation ();
9473 /* if the result is of type pointer */
9478 sym_link *type = operandType (right);
9480 /* pointer to generic pointer */
9481 if (IS_GENPTR (ctype))
9487 p_type = DCL_TYPE (type);
9491 #if OLD_CAST_BEHAVIOR
9492 /* KV: we are converting a non-pointer type to
9493 * a generic pointer. This (ifdef'd out) code
9494 * says that the resulting generic pointer
9495 * should have the same class as the storage
9496 * location of the non-pointer variable.
9498 * For example, converting an int (which happens
9499 * to be stored in DATA space) to a pointer results
9500 * in a DATA generic pointer; if the original int
9501 * in XDATA space, so will be the resulting pointer.
9503 * I don't like that behavior, and thus this change:
9504 * all such conversions will be forced to XDATA and
9505 * throw a warning. If you want some non-XDATA
9506 * type, or you want to suppress the warning, you
9507 * must go through an intermediate cast, like so:
9509 * char _generic *gp = (char _xdata *)(intVar);
9511 sym_link *etype = getSpec (type);
9513 /* we have to go by the storage class */
9514 if (SPEC_OCLS (etype) != generic)
9516 p_type = PTR_TYPE (SPEC_OCLS (etype));
9521 /* Converting unknown class (i.e. register variable)
9522 * to generic pointer. This is not good, but
9523 * we'll make a guess (and throw a warning).
9526 werror (W_INT_TO_GEN_PTR_CAST);
9530 /* the first two bytes are known */
9531 size = GPTRSIZE - 1;
9533 _startLazyDPSEvaluation ();
9536 aopPut (AOP (result),
9537 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9541 _endLazyDPSEvaluation ();
9543 /* the last byte depending on type */
9561 /* this should never happen */
9562 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9563 "got unknown pointer type");
9566 aopPut (AOP (result), l, GPTRSIZE - 1);
9570 /* just copy the pointers */
9571 size = AOP_SIZE (result);
9573 _startLazyDPSEvaluation ();
9576 aopPut (AOP (result),
9577 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9581 _endLazyDPSEvaluation ();
9585 /* so we now know that the size of destination is greater
9586 than the size of the source */
9587 /* we move to result for the size of source */
9588 size = AOP_SIZE (right);
9590 _startLazyDPSEvaluation ();
9593 aopPut (AOP (result),
9594 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9598 _endLazyDPSEvaluation ();
9600 /* now depending on the sign of the source && destination */
9601 size = AOP_SIZE (result) - AOP_SIZE (right);
9602 /* if unsigned or not an integral type */
9603 /* also, if the source is a bit, we don't need to sign extend, because
9604 * it can't possibly have set the sign bit.
9606 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9610 aopPut (AOP (result), zero, offset++);
9615 /* we need to extend the sign :{ */
9616 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9617 FALSE, FALSE, TRUE);
9619 emitcode ("rlc", "a");
9620 emitcode ("subb", "a,acc");
9622 aopPut (AOP (result), "a", offset++);
9625 /* we are done hurray !!!! */
9628 freeAsmop (right, NULL, ic, TRUE);
9629 freeAsmop (result, NULL, ic, TRUE);
9633 /*-----------------------------------------------------------------*/
9634 /* genDjnz - generate decrement & jump if not zero instrucion */
9635 /*-----------------------------------------------------------------*/
9637 genDjnz (iCode * ic, iCode * ifx)
9643 /* if the if condition has a false label
9644 then we cannot save */
9648 /* if the minus is not of the form
9650 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9651 !IS_OP_LITERAL (IC_RIGHT (ic)))
9654 if (operandLitValue (IC_RIGHT (ic)) != 1)
9657 /* if the size of this greater than one then no
9659 if (getSize (operandType (IC_RESULT (ic))) > 1)
9662 /* otherwise we can save BIG */
9663 D(emitcode(";", "genDjnz"););
9665 lbl = newiTempLabel (NULL);
9666 lbl1 = newiTempLabel (NULL);
9668 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9670 if (AOP_NEEDSACC(IC_RESULT(ic)))
9672 /* If the result is accessed indirectly via
9673 * the accumulator, we must explicitly write
9674 * it back after the decrement.
9676 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9678 if (strcmp(rByte, "a"))
9680 /* Something is hopelessly wrong */
9681 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9682 __FILE__, __LINE__);
9683 /* We can just give up; the generated code will be inefficient,
9686 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9689 emitcode ("dec", "%s", rByte);
9690 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9691 emitcode ("jnz", "%05d$", lbl->key + 100);
9693 else if (IS_AOP_PREG (IC_RESULT (ic)))
9695 emitcode ("dec", "%s",
9696 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9697 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9698 emitcode ("jnz", "%05d$", lbl->key + 100);
9702 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9705 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9706 emitcode ("", "%05d$:", lbl->key + 100);
9707 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9708 emitcode ("", "%05d$:", lbl1->key + 100);
9710 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9715 /*-----------------------------------------------------------------*/
9716 /* genReceive - generate code for a receive iCode */
9717 /*-----------------------------------------------------------------*/
9719 genReceive (iCode * ic)
9722 D (emitcode (";", "genReceive ");
9725 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9726 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9727 IS_TRUE_SYMOP (IC_RESULT (ic))))
9729 int size = getSize (operandType (IC_RESULT (ic)));
9730 int offset = fReturnSizeDS390 - size;
9733 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9734 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9737 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9738 size = AOP_SIZE (IC_RESULT (ic));
9742 emitcode ("pop", "acc");
9743 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9750 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9752 assignResultValue (IC_RESULT (ic));
9755 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9758 /*-----------------------------------------------------------------*/
9759 /* gen390Code - generate code for Dallas 390 based controllers */
9760 /*-----------------------------------------------------------------*/
9762 gen390Code (iCode * lic)
9767 lineHead = lineCurr = NULL;
9771 /* print the allocation information */
9773 printAllocInfo (currFunc, codeOutFile);
9775 /* if debug information required */
9776 if (options.debug && currFunc)
9778 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9780 if (IS_STATIC (currFunc->etype))
9781 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9783 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9786 /* stack pointer name */
9787 if (options.useXstack)
9793 for (ic = lic; ic; ic = ic->next)
9796 if (cln != ic->lineno)
9801 emitcode ("", "C$%s$%d$%d$%d ==.",
9802 FileBaseName (ic->filename), ic->lineno,
9803 ic->level, ic->block);
9806 emitcode (";", "%s %d", ic->filename, ic->lineno);
9809 /* if the result is marked as
9810 spilt and rematerializable or code for
9811 this has already been generated then
9813 if (resultRemat (ic) || ic->generated)
9816 /* depending on the operation */
9836 /* IPOP happens only when trying to restore a
9837 spilt live range, if there is an ifx statement
9838 following this pop then the if statement might
9839 be using some of the registers being popped which
9840 would destory the contents of the register so
9841 we need to check for this condition and handle it */
9843 ic->next->op == IFX &&
9844 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9845 genIfx (ic->next, ic);
9863 genEndFunction (ic);
9883 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9900 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9904 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9911 /* note these two are xlated by algebraic equivalence
9912 during parsing SDCC.y */
9913 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9914 "got '>=' or '<=' shouldn't have come here");
9918 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9930 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9934 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9938 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9965 case GET_VALUE_AT_ADDRESS:
9970 if (POINTER_SET (ic))
9997 addSet (&_G.sendSet, ic);
10006 /* now we are ready to call the
10007 peep hole optimizer */
10008 if (!options.nopeep)
10009 peepHole (&lineHead);
10011 /* now do the actual printing */
10012 printLine (lineHead, codeOutFile);