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)
7381 int isSameRegs=sameRegs(AOP(left),AOP(result));
7383 if (isSameRegs && offl>1) {
7384 // we are in big trouble, but this shouldn't happen
7385 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7388 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7393 emitcode ("rlc", "a");
7394 emitcode ("subb", "a,acc");
7395 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7397 aopPut (AOP(result), zero, MSB32);
7402 emitcode ("clr", "c");
7404 emitcode ("mov", "c,acc.7");
7407 emitcode ("rrc", "a");
7409 if (isSameRegs && offl==MSB16) {
7410 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7412 aopPut (AOP (result), "a", MSB32);
7413 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7416 emitcode ("rrc", "a");
7417 if (isSameRegs && offl==1) {
7418 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7420 aopPut (AOP (result), "a", MSB24);
7421 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7423 emitcode ("rrc", "a");
7424 aopPut (AOP (result), "a", MSB16 - offl);
7428 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7429 emitcode ("rrc", "a");
7430 aopPut (AOP (result), "a", LSB);
7437 /*-----------------------------------------------------------------*/
7438 /* genrshFour - shift four byte by a known amount != 0 */
7439 /*-----------------------------------------------------------------*/
7441 genrshFour (operand * result, operand * left,
7442 int shCount, int sign)
7444 D (emitcode (";", "genrshFour");
7447 /* if shifting more that 3 bytes */
7452 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7454 movLeft2Result (left, MSB32, result, LSB, sign);
7455 addSign (result, MSB16, sign);
7457 else if (shCount >= 16)
7461 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7464 movLeft2Result (left, MSB24, result, LSB, 0);
7465 movLeft2Result (left, MSB32, result, MSB16, sign);
7467 addSign (result, MSB24, sign);
7469 else if (shCount >= 8)
7473 shiftRLong (left, MSB16, result, sign);
7474 else if (shCount == 0)
7476 movLeft2Result (left, MSB16, result, LSB, 0);
7477 movLeft2Result (left, MSB24, result, MSB16, 0);
7478 movLeft2Result (left, MSB32, result, MSB24, sign);
7479 addSign (result, MSB32, sign);
7483 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7484 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7485 /* the last shift is signed */
7486 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7487 addSign (result, MSB32, sign);
7491 { /* 1 <= shCount <= 7 */
7494 shiftRLong (left, LSB, result, sign);
7496 shiftRLong (result, LSB, result, sign);
7500 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7501 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7502 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7508 #ifdef BETTER_LITERAL_SHIFT
7509 /*-----------------------------------------------------------------*/
7510 /* genRightShiftLiteral - right shifting by known count */
7511 /*-----------------------------------------------------------------*/
7513 genRightShiftLiteral (operand * left,
7519 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7522 size = getSize (operandType (result));
7524 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7526 /* We only handle certain easy cases so far. */
7528 && (shCount < (size * 8))
7532 D(emitcode (";", "genRightShiftLiteral wimping out"););
7536 freeAsmop (right, NULL, ic, TRUE);
7538 aopOp (left, ic, FALSE, FALSE);
7539 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7542 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7546 /* test the LEFT size !!! */
7548 /* I suppose that the left size >= result size */
7551 size = getDataSize (result);
7552 _startLazyDPSEvaluation();
7555 movLeft2Result (left, size, result, size, 0);
7557 _endLazyDPSEvaluation();
7559 else if (shCount >= (size * 8))
7563 /* get sign in acc.7 */
7564 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7566 addSign (result, LSB, sign);
7573 genrshOne (result, left, shCount, sign);
7577 genrshTwo (result, left, shCount, sign);
7581 genrshFour (result, left, shCount, sign);
7588 freeAsmop (left, NULL, ic, TRUE);
7589 freeAsmop (result, NULL, ic, TRUE);
7595 /*-----------------------------------------------------------------*/
7596 /* genSignedRightShift - right shift of signed number */
7597 /*-----------------------------------------------------------------*/
7599 genSignedRightShift (iCode * ic)
7601 operand *right, *left, *result;
7604 symbol *tlbl, *tlbl1;
7606 D (emitcode (";", "genSignedRightShift "););
7608 /* we do it the hard way put the shift count in b
7609 and loop thru preserving the sign */
7611 right = IC_RIGHT (ic);
7612 left = IC_LEFT (ic);
7613 result = IC_RESULT (ic);
7615 aopOp (right, ic, FALSE, FALSE);
7617 #ifdef BETTER_LITERAL_SHIFT
7618 if (AOP_TYPE (right) == AOP_LIT)
7620 if (genRightShiftLiteral (left, right, result, ic, 1))
7626 /* shift count is unknown then we have to form
7627 a loop get the loop count in B : Note: we take
7628 only the lower order byte since shifting
7629 more that 32 bits make no sense anyway, ( the
7630 largest size of an object can be only 32 bits ) */
7632 if (AOP_TYPE (right) == AOP_LIT)
7634 /* Really should be handled by genRightShiftLiteral,
7635 * but since I'm too lazy to fix that today, at least we can make
7636 * some small improvement.
7638 emitcode("mov", "b,#0x%02x",
7639 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7643 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7644 emitcode ("inc", "b");
7646 freeAsmop (right, NULL, ic, TRUE);
7647 aopOp (left, ic, FALSE, FALSE);
7648 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7650 /* now move the left to the result if they are not the
7652 if (!sameRegs (AOP (left), AOP (result)) &&
7653 AOP_SIZE (result) > 1)
7656 size = AOP_SIZE (result);
7658 _startLazyDPSEvaluation ();
7661 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7662 if (*l == '@' && IS_AOP_PREG (result))
7665 emitcode ("mov", "a,%s", l);
7666 aopPut (AOP (result), "a", offset);
7669 aopPut (AOP (result), l, offset);
7672 _endLazyDPSEvaluation ();
7675 /* mov the highest order bit to OVR */
7676 tlbl = newiTempLabel (NULL);
7677 tlbl1 = newiTempLabel (NULL);
7679 size = AOP_SIZE (result);
7681 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7682 emitcode ("rlc", "a");
7683 emitcode ("mov", "ov,c");
7684 /* if it is only one byte then */
7687 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7689 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7690 emitcode ("", "%05d$:", tlbl->key + 100);
7691 emitcode ("mov", "c,ov");
7692 emitcode ("rrc", "a");
7693 emitcode ("", "%05d$:", tlbl1->key + 100);
7694 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7695 aopPut (AOP (result), "a", 0);
7699 reAdjustPreg (AOP (result));
7700 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7701 emitcode ("", "%05d$:", tlbl->key + 100);
7702 emitcode ("mov", "c,ov");
7703 _startLazyDPSEvaluation ();
7706 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7708 emitcode ("rrc", "a");
7709 aopPut (AOP (result), "a", offset--);
7711 _endLazyDPSEvaluation ();
7712 reAdjustPreg (AOP (result));
7713 emitcode ("", "%05d$:", tlbl1->key + 100);
7714 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7717 freeAsmop (left, NULL, ic, TRUE);
7718 freeAsmop (result, NULL, ic, TRUE);
7721 /*-----------------------------------------------------------------*/
7722 /* genRightShift - generate code for right shifting */
7723 /*-----------------------------------------------------------------*/
7725 genRightShift (iCode * ic)
7727 operand *right, *left, *result;
7731 symbol *tlbl, *tlbl1;
7733 D (emitcode (";", "genRightShift "););
7735 /* if signed then we do it the hard way preserve the
7736 sign bit moving it inwards */
7737 retype = getSpec (operandType (IC_RESULT (ic)));
7739 if (!SPEC_USIGN (retype))
7741 genSignedRightShift (ic);
7745 /* signed & unsigned types are treated the same : i.e. the
7746 signed is NOT propagated inwards : quoting from the
7747 ANSI - standard : "for E1 >> E2, is equivalent to division
7748 by 2**E2 if unsigned or if it has a non-negative value,
7749 otherwise the result is implementation defined ", MY definition
7750 is that the sign does not get propagated */
7752 right = IC_RIGHT (ic);
7753 left = IC_LEFT (ic);
7754 result = IC_RESULT (ic);
7756 aopOp (right, ic, FALSE, FALSE);
7758 #ifdef BETTER_LITERAL_SHIFT
7759 /* if the shift count is known then do it
7760 as efficiently as possible */
7761 if (AOP_TYPE (right) == AOP_LIT)
7763 if (genRightShiftLiteral (left, right, result, ic, 0))
7770 /* shift count is unknown then we have to form
7771 a loop get the loop count in B : Note: we take
7772 only the lower order byte since shifting
7773 more that 32 bits make no sense anyway, ( the
7774 largest size of an object can be only 32 bits ) */
7776 if (AOP_TYPE (right) == AOP_LIT)
7778 /* Really should be handled by genRightShiftLiteral,
7779 * but since I'm too lazy to fix that today, at least we can make
7780 * some small improvement.
7782 emitcode("mov", "b,#0x%02x",
7783 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7787 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7788 emitcode ("inc", "b");
7790 freeAsmop (right, NULL, ic, TRUE);
7791 aopOp (left, ic, FALSE, FALSE);
7792 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7794 /* now move the left to the result if they are not the
7796 if (!sameRegs (AOP (left), AOP (result)) &&
7797 AOP_SIZE (result) > 1)
7800 size = AOP_SIZE (result);
7802 _startLazyDPSEvaluation ();
7805 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7806 if (*l == '@' && IS_AOP_PREG (result))
7809 emitcode ("mov", "a,%s", l);
7810 aopPut (AOP (result), "a", offset);
7813 aopPut (AOP (result), l, offset);
7816 _endLazyDPSEvaluation ();
7819 tlbl = newiTempLabel (NULL);
7820 tlbl1 = newiTempLabel (NULL);
7821 size = AOP_SIZE (result);
7824 /* if it is only one byte then */
7827 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7829 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7830 emitcode ("", "%05d$:", tlbl->key + 100);
7832 emitcode ("rrc", "a");
7833 emitcode ("", "%05d$:", tlbl1->key + 100);
7834 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7835 aopPut (AOP (result), "a", 0);
7839 reAdjustPreg (AOP (result));
7840 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7841 emitcode ("", "%05d$:", tlbl->key + 100);
7843 _startLazyDPSEvaluation ();
7846 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7848 emitcode ("rrc", "a");
7849 aopPut (AOP (result), "a", offset--);
7851 _endLazyDPSEvaluation ();
7852 reAdjustPreg (AOP (result));
7854 emitcode ("", "%05d$:", tlbl1->key + 100);
7855 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7858 freeAsmop (left, NULL, ic, TRUE);
7859 freeAsmop (result, NULL, ic, TRUE);
7862 /*-----------------------------------------------------------------*/
7863 /* genUnpackBits - generates code for unpacking bits */
7864 /*-----------------------------------------------------------------*/
7866 genUnpackBits (operand * result, char *rname, int ptype)
7873 D (emitcode (";", "genUnpackBits ");
7876 etype = getSpec (operandType (result));
7878 /* read the first byte */
7884 emitcode ("mov", "a,@%s", rname);
7888 emitcode ("movx", "a,@%s", rname);
7892 emitcode ("movx", "a,@dptr");
7896 emitcode ("clr", "a");
7897 emitcode ("movc", "a", "@a+dptr");
7901 emitcode ("lcall", "__gptrget");
7905 /* if we have bitdisplacement then it fits */
7906 /* into this byte completely or if length is */
7907 /* less than a byte */
7908 if ((shCnt = SPEC_BSTR (etype)) ||
7909 (SPEC_BLEN (etype) <= 8))
7912 /* shift right acc */
7915 emitcode ("anl", "a,#0x%02x",
7916 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7917 aopPut (AOP (result), "a", offset);
7921 /* bit field did not fit in a byte */
7922 rlen = SPEC_BLEN (etype) - 8;
7923 aopPut (AOP (result), "a", offset++);
7932 emitcode ("inc", "%s", rname);
7933 emitcode ("mov", "a,@%s", rname);
7937 emitcode ("inc", "%s", rname);
7938 emitcode ("movx", "a,@%s", rname);
7942 emitcode ("inc", "dptr");
7943 emitcode ("movx", "a,@dptr");
7947 emitcode ("clr", "a");
7948 emitcode ("inc", "dptr");
7949 emitcode ("movc", "a", "@a+dptr");
7953 emitcode ("inc", "dptr");
7954 emitcode ("lcall", "__gptrget");
7959 /* if we are done */
7963 aopPut (AOP (result), "a", offset++);
7969 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7970 aopPut (AOP (result), "a", offset);
7977 /*-----------------------------------------------------------------*/
7978 /* genDataPointerGet - generates code when ptr offset is known */
7979 /*-----------------------------------------------------------------*/
7981 genDataPointerGet (operand * left,
7987 int size, offset = 0;
7988 aopOp (result, ic, TRUE, FALSE);
7990 /* get the string representation of the name */
7991 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7992 size = AOP_SIZE (result);
7993 _startLazyDPSEvaluation ();
7997 sprintf (buffer, "(%s + %d)", l + 1, offset);
7999 sprintf (buffer, "%s", l + 1);
8000 aopPut (AOP (result), buffer, offset++);
8002 _endLazyDPSEvaluation ();
8004 freeAsmop (left, NULL, ic, TRUE);
8005 freeAsmop (result, NULL, ic, TRUE);
8008 /*-----------------------------------------------------------------*/
8009 /* genNearPointerGet - emitcode for near pointer fetch */
8010 /*-----------------------------------------------------------------*/
8012 genNearPointerGet (operand * left,
8019 sym_link *rtype, *retype, *letype;
8020 sym_link *ltype = operandType (left);
8023 rtype = operandType (result);
8024 retype = getSpec (rtype);
8025 letype = getSpec (ltype);
8027 aopOp (left, ic, FALSE, FALSE);
8029 /* if left is rematerialisable and
8030 result is not bit variable type and
8031 the left is pointer to data space i.e
8032 lower 128 bytes of space */
8033 if (AOP_TYPE (left) == AOP_IMMD &&
8034 !IS_BITVAR (retype) &&
8035 !IS_BITVAR (letype) &&
8036 DCL_TYPE (ltype) == POINTER)
8038 genDataPointerGet (left, result, ic);
8042 /* if the value is already in a pointer register
8043 then don't need anything more */
8044 if (!AOP_INPREG (AOP (left)))
8046 /* otherwise get a free pointer register */
8048 preg = getFreePtr (ic, &aop, FALSE);
8049 emitcode ("mov", "%s,%s",
8051 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8055 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8057 freeAsmop (left, NULL, ic, TRUE);
8058 aopOp (result, ic, FALSE, FALSE);
8060 /* if bitfield then unpack the bits */
8061 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8062 genUnpackBits (result, rname, POINTER);
8065 /* we have can just get the values */
8066 int size = AOP_SIZE (result);
8071 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8074 emitcode ("mov", "a,@%s", rname);
8075 aopPut (AOP (result), "a", offset);
8079 sprintf (buffer, "@%s", rname);
8080 aopPut (AOP (result), buffer, offset);
8084 emitcode ("inc", "%s", rname);
8088 /* now some housekeeping stuff */
8091 /* we had to allocate for this iCode */
8092 freeAsmop (NULL, aop, ic, TRUE);
8096 /* we did not allocate which means left
8097 already in a pointer register, then
8098 if size > 0 && this could be used again
8099 we have to point it back to where it
8101 if (AOP_SIZE (result) > 1 &&
8102 !OP_SYMBOL (left)->remat &&
8103 (OP_SYMBOL (left)->liveTo > ic->seq ||
8106 int size = AOP_SIZE (result) - 1;
8108 emitcode ("dec", "%s", rname);
8113 freeAsmop (result, NULL, ic, TRUE);
8117 /*-----------------------------------------------------------------*/
8118 /* genPagedPointerGet - emitcode for paged pointer fetch */
8119 /*-----------------------------------------------------------------*/
8121 genPagedPointerGet (operand * left,
8128 sym_link *rtype, *retype, *letype;
8130 rtype = operandType (result);
8131 retype = getSpec (rtype);
8132 letype = getSpec (operandType (left));
8133 aopOp (left, ic, FALSE, FALSE);
8135 /* if the value is already in a pointer register
8136 then don't need anything more */
8137 if (!AOP_INPREG (AOP (left)))
8139 /* otherwise get a free pointer register */
8141 preg = getFreePtr (ic, &aop, FALSE);
8142 emitcode ("mov", "%s,%s",
8144 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8148 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8150 freeAsmop (left, NULL, ic, TRUE);
8151 aopOp (result, ic, FALSE, FALSE);
8153 /* if bitfield then unpack the bits */
8154 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8155 genUnpackBits (result, rname, PPOINTER);
8158 /* we have can just get the values */
8159 int size = AOP_SIZE (result);
8165 emitcode ("movx", "a,@%s", rname);
8166 aopPut (AOP (result), "a", offset);
8171 emitcode ("inc", "%s", rname);
8175 /* now some housekeeping stuff */
8178 /* we had to allocate for this iCode */
8179 freeAsmop (NULL, aop, ic, TRUE);
8183 /* we did not allocate which means left
8184 already in a pointer register, then
8185 if size > 0 && this could be used again
8186 we have to point it back to where it
8188 if (AOP_SIZE (result) > 1 &&
8189 !OP_SYMBOL (left)->remat &&
8190 (OP_SYMBOL (left)->liveTo > ic->seq ||
8193 int size = AOP_SIZE (result) - 1;
8195 emitcode ("dec", "%s", rname);
8200 freeAsmop (result, NULL, ic, TRUE);
8205 /*-----------------------------------------------------------------*/
8206 /* genFarPointerGet - gget value from far space */
8207 /*-----------------------------------------------------------------*/
8209 genFarPointerGet (operand * left,
8210 operand * result, iCode * ic)
8213 sym_link *retype = getSpec (operandType (result));
8214 sym_link *letype = getSpec (operandType (left));
8215 D (emitcode (";", "genFarPointerGet");
8218 aopOp (left, ic, FALSE, FALSE);
8220 /* if the operand is already in dptr
8221 then we do nothing else we move the value to dptr */
8222 if (AOP_TYPE (left) != AOP_STR)
8224 /* if this is remateriazable */
8225 if (AOP_TYPE (left) == AOP_IMMD)
8227 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8231 /* we need to get it byte by byte */
8232 _startLazyDPSEvaluation ();
8233 if (AOP_TYPE (left) != AOP_DPTR)
8235 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8236 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8237 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8241 /* We need to generate a load to DPTR indirect through DPTR. */
8242 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8244 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8245 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8246 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8247 emitcode ("pop", "dph");
8248 emitcode ("pop", "dpl");
8250 _endLazyDPSEvaluation ();
8253 /* so dptr know contains the address */
8254 freeAsmop (left, NULL, ic, TRUE);
8255 aopOp (result, ic, FALSE, TRUE);
8257 /* if bit then unpack */
8258 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8259 genUnpackBits (result, "dptr", FPOINTER);
8262 size = AOP_SIZE (result);
8265 _startLazyDPSEvaluation ();
8272 emitcode ("movx", "a,@dptr");
8274 emitcode ("inc", "dptr");
8276 aopPut (AOP (result), "a", offset++);
8278 _endLazyDPSEvaluation ();
8281 freeAsmop (result, NULL, ic, TRUE);
8284 /*-----------------------------------------------------------------*/
8285 /* emitcodePointerGet - gget value from code space */
8286 /*-----------------------------------------------------------------*/
8288 emitcodePointerGet (operand * left,
8289 operand * result, iCode * ic)
8292 sym_link *retype = getSpec (operandType (result));
8294 aopOp (left, ic, FALSE, FALSE);
8296 /* if the operand is already in dptr
8297 then we do nothing else we move the value to dptr */
8298 if (AOP_TYPE (left) != AOP_STR)
8300 /* if this is remateriazable */
8301 if (AOP_TYPE (left) == AOP_IMMD)
8303 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8306 { /* we need to get it byte by byte */
8307 _startLazyDPSEvaluation ();
8308 if (AOP_TYPE (left) != AOP_DPTR)
8310 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8311 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8312 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8316 /* We need to generate a load to DPTR indirect through DPTR. */
8317 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8319 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8320 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8321 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8322 emitcode ("pop", "dph");
8323 emitcode ("pop", "dpl");
8325 _endLazyDPSEvaluation ();
8328 /* so dptr know contains the address */
8329 freeAsmop (left, NULL, ic, TRUE);
8330 aopOp (result, ic, FALSE, TRUE);
8332 /* if bit then unpack */
8333 if (IS_BITVAR (retype))
8334 genUnpackBits (result, "dptr", CPOINTER);
8337 size = AOP_SIZE (result);
8340 _startLazyDPSEvaluation ();
8346 emitcode ("clr", "a");
8347 emitcode ("movc", "a,@a+dptr");
8349 emitcode ("inc", "dptr");
8350 aopPut (AOP (result), "a", offset++);
8352 _endLazyDPSEvaluation ();
8355 freeAsmop (result, NULL, ic, TRUE);
8358 /*-----------------------------------------------------------------*/
8359 /* genGenPointerGet - gget value from generic pointer space */
8360 /*-----------------------------------------------------------------*/
8362 genGenPointerGet (operand * left,
8363 operand * result, iCode * ic)
8366 sym_link *retype = getSpec (operandType (result));
8367 sym_link *letype = getSpec (operandType (left));
8369 D (emitcode (";", "genGenPointerGet "); );
8371 aopOp (left, ic, FALSE, TRUE);
8373 /* if the operand is already in dptr
8374 then we do nothing else we move the value to dptr */
8375 if (AOP_TYPE (left) != AOP_STR)
8377 /* if this is remateriazable */
8378 if (AOP_TYPE (left) == AOP_IMMD)
8380 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8381 emitcode ("mov", "b,#%d", pointerCode (retype));
8384 { /* we need to get it byte by byte */
8385 _startLazyDPSEvaluation ();
8386 if (AOP(left)->type==AOP_DPTR2) {
8388 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8391 emitcode ("mov", "dpl,%s", l);
8392 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8395 emitcode ("mov", "dph,%s", l);
8396 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8399 emitcode ("mov", "dpx,%s", l);
8400 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8402 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8403 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8404 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8405 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8407 _endLazyDPSEvaluation ();
8410 /* so dptr know contains the address */
8411 freeAsmop (left, NULL, ic, TRUE);
8412 aopOp (result, ic, FALSE, TRUE);
8414 /* if bit then unpack */
8415 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8416 genUnpackBits (result, "dptr", GPOINTER);
8419 size = AOP_SIZE (result);
8424 emitcode ("lcall", "__gptrget");
8425 aopPut (AOP (result), "a", offset++);
8427 emitcode ("inc", "dptr");
8431 freeAsmop (result, NULL, ic, TRUE);
8434 /*-----------------------------------------------------------------*/
8435 /* genPointerGet - generate code for pointer get */
8436 /*-----------------------------------------------------------------*/
8438 genPointerGet (iCode * ic)
8440 operand *left, *result;
8441 sym_link *type, *etype;
8444 D (emitcode (";", "genPointerGet ");
8447 left = IC_LEFT (ic);
8448 result = IC_RESULT (ic);
8450 /* depending on the type of pointer we need to
8451 move it to the correct pointer register */
8452 type = operandType (left);
8453 etype = getSpec (type);
8454 /* if left is of type of pointer then it is simple */
8455 if (IS_PTR (type) && !IS_FUNC (type->next))
8456 p_type = DCL_TYPE (type);
8459 /* we have to go by the storage class */
8460 p_type = PTR_TYPE (SPEC_OCLS (etype));
8463 /* now that we have the pointer type we assign
8464 the pointer values */
8470 genNearPointerGet (left, result, ic);
8474 genPagedPointerGet (left, result, ic);
8478 genFarPointerGet (left, result, ic);
8482 emitcodePointerGet (left, result, ic);
8486 genGenPointerGet (left, result, ic);
8492 /*-----------------------------------------------------------------*/
8493 /* genPackBits - generates code for packed bit storage */
8494 /*-----------------------------------------------------------------*/
8496 genPackBits (sym_link * etype,
8498 char *rname, int p_type)
8506 blen = SPEC_BLEN (etype);
8507 bstr = SPEC_BSTR (etype);
8509 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8512 /* if the bit lenth is less than or */
8513 /* it exactly fits a byte then */
8514 if (SPEC_BLEN (etype) <= 8)
8516 shCount = SPEC_BSTR (etype);
8518 /* shift left acc */
8521 if (SPEC_BLEN (etype) < 8)
8522 { /* if smaller than a byte */
8528 emitcode ("mov", "b,a");
8529 emitcode ("mov", "a,@%s", rname);
8533 emitcode ("mov", "b,a");
8534 emitcode ("movx", "a,@dptr");
8538 emitcode ("push", "b");
8539 emitcode ("push", "acc");
8540 emitcode ("lcall", "__gptrget");
8541 emitcode ("pop", "b");
8545 emitcode ("anl", "a,#0x%02x", (unsigned char)
8546 ((unsigned char) (0xFF << (blen + bstr)) |
8547 (unsigned char) (0xFF >> (8 - bstr))));
8548 emitcode ("orl", "a,b");
8549 if (p_type == GPOINTER)
8550 emitcode ("pop", "b");
8557 emitcode ("mov", "@%s,a", rname);
8561 emitcode ("movx", "@dptr,a");
8565 emitcode ("lcall", "__gptrput");
8570 if (SPEC_BLEN (etype) <= 8)
8573 emitcode ("inc", "%s", rname);
8574 rLen = SPEC_BLEN (etype);
8576 /* now generate for lengths greater than one byte */
8580 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8592 emitcode ("mov", "@%s,a", rname);
8595 emitcode ("mov", "@%s,%s", rname, l);
8600 emitcode ("movx", "@dptr,a");
8605 emitcode ("lcall", "__gptrput");
8608 emitcode ("inc", "%s", rname);
8613 /* last last was not complete */
8616 /* save the byte & read byte */
8620 emitcode ("mov", "b,a");
8621 emitcode ("mov", "a,@%s", rname);
8625 emitcode ("mov", "b,a");
8626 emitcode ("movx", "a,@dptr");
8630 emitcode ("push", "b");
8631 emitcode ("push", "acc");
8632 emitcode ("lcall", "__gptrget");
8633 emitcode ("pop", "b");
8637 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8638 emitcode ("orl", "a,b");
8641 if (p_type == GPOINTER)
8642 emitcode ("pop", "b");
8648 emitcode ("mov", "@%s,a", rname);
8652 emitcode ("movx", "@dptr,a");
8656 emitcode ("lcall", "__gptrput");
8660 /*-----------------------------------------------------------------*/
8661 /* genDataPointerSet - remat pointer to data space */
8662 /*-----------------------------------------------------------------*/
8664 genDataPointerSet (operand * right,
8668 int size, offset = 0;
8669 char *l, buffer[256];
8671 aopOp (right, ic, FALSE, FALSE);
8673 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8674 size = AOP_SIZE (right);
8678 sprintf (buffer, "(%s + %d)", l + 1, offset);
8680 sprintf (buffer, "%s", l + 1);
8681 emitcode ("mov", "%s,%s", buffer,
8682 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8685 freeAsmop (right, NULL, ic, TRUE);
8686 freeAsmop (result, NULL, ic, TRUE);
8689 /*-----------------------------------------------------------------*/
8690 /* genNearPointerSet - emitcode for near pointer put */
8691 /*-----------------------------------------------------------------*/
8693 genNearPointerSet (operand * right,
8700 sym_link *retype, *letype;
8701 sym_link *ptype = operandType (result);
8703 retype = getSpec (operandType (right));
8704 letype = getSpec (ptype);
8706 aopOp (result, ic, FALSE, FALSE);
8708 /* if the result is rematerializable &
8709 in data space & not a bit variable */
8710 if (AOP_TYPE (result) == AOP_IMMD &&
8711 DCL_TYPE (ptype) == POINTER &&
8712 !IS_BITVAR (retype) &&
8713 !IS_BITVAR (letype))
8715 genDataPointerSet (right, result, ic);
8719 /* if the value is already in a pointer register
8720 then don't need anything more */
8721 if (!AOP_INPREG (AOP (result)))
8723 /* otherwise get a free pointer register */
8725 preg = getFreePtr (ic, &aop, FALSE);
8726 emitcode ("mov", "%s,%s",
8728 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8732 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8734 freeAsmop (result, NULL, ic, TRUE);
8735 aopOp (right, ic, FALSE, FALSE);
8737 /* if bitfield then unpack the bits */
8738 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8739 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8742 /* we have can just get the values */
8743 int size = AOP_SIZE (right);
8748 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8752 emitcode ("mov", "@%s,a", rname);
8755 emitcode ("mov", "@%s,%s", rname, l);
8757 emitcode ("inc", "%s", rname);
8762 /* now some housekeeping stuff */
8765 /* we had to allocate for this iCode */
8766 freeAsmop (NULL, aop, ic, TRUE);
8770 /* we did not allocate which means left
8771 already in a pointer register, then
8772 if size > 0 && this could be used again
8773 we have to point it back to where it
8775 if (AOP_SIZE (right) > 1 &&
8776 !OP_SYMBOL (result)->remat &&
8777 (OP_SYMBOL (result)->liveTo > ic->seq ||
8780 int size = AOP_SIZE (right) - 1;
8782 emitcode ("dec", "%s", rname);
8787 freeAsmop (right, NULL, ic, TRUE);
8792 /*-----------------------------------------------------------------*/
8793 /* genPagedPointerSet - emitcode for Paged pointer put */
8794 /*-----------------------------------------------------------------*/
8796 genPagedPointerSet (operand * right,
8803 sym_link *retype, *letype;
8805 retype = getSpec (operandType (right));
8806 letype = getSpec (operandType (result));
8808 aopOp (result, ic, FALSE, FALSE);
8810 /* if the value is already in a pointer register
8811 then don't need anything more */
8812 if (!AOP_INPREG (AOP (result)))
8814 /* otherwise get a free pointer register */
8816 preg = getFreePtr (ic, &aop, FALSE);
8817 emitcode ("mov", "%s,%s",
8819 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8823 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8825 freeAsmop (result, NULL, ic, TRUE);
8826 aopOp (right, ic, FALSE, FALSE);
8828 /* if bitfield then unpack the bits */
8829 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8830 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8833 /* we have can just get the values */
8834 int size = AOP_SIZE (right);
8839 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8842 emitcode ("movx", "@%s,a", rname);
8845 emitcode ("inc", "%s", rname);
8851 /* now some housekeeping stuff */
8854 /* we had to allocate for this iCode */
8855 freeAsmop (NULL, aop, ic, TRUE);
8859 /* we did not allocate which means left
8860 already in a pointer register, then
8861 if size > 0 && this could be used again
8862 we have to point it back to where it
8864 if (AOP_SIZE (right) > 1 &&
8865 !OP_SYMBOL (result)->remat &&
8866 (OP_SYMBOL (result)->liveTo > ic->seq ||
8869 int size = AOP_SIZE (right) - 1;
8871 emitcode ("dec", "%s", rname);
8876 freeAsmop (right, NULL, ic, TRUE);
8881 /*-----------------------------------------------------------------*/
8882 /* genFarPointerSet - set value from far space */
8883 /*-----------------------------------------------------------------*/
8885 genFarPointerSet (operand * right,
8886 operand * result, iCode * ic)
8889 sym_link *retype = getSpec (operandType (right));
8890 sym_link *letype = getSpec (operandType (result));
8892 aopOp (result, ic, FALSE, FALSE);
8894 /* if the operand is already in dptr
8895 then we do nothing else we move the value to dptr */
8896 if (AOP_TYPE (result) != AOP_STR)
8898 /* if this is remateriazable */
8899 if (AOP_TYPE (result) == AOP_IMMD)
8900 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8903 /* we need to get it byte by byte */
8904 _startLazyDPSEvaluation ();
8905 if (AOP_TYPE (result) != AOP_DPTR)
8907 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8908 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8909 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8913 /* We need to generate a load to DPTR indirect through DPTR. */
8914 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8916 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8917 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8918 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8919 emitcode ("pop", "dph");
8920 emitcode ("pop", "dpl");
8922 _endLazyDPSEvaluation ();
8925 /* so dptr know contains the address */
8926 freeAsmop (result, NULL, ic, TRUE);
8927 aopOp (right, ic, FALSE, TRUE);
8929 /* if bit then unpack */
8930 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8931 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8934 size = AOP_SIZE (right);
8937 _startLazyDPSEvaluation ();
8940 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8946 emitcode ("movx", "@dptr,a");
8948 emitcode ("inc", "dptr");
8950 _endLazyDPSEvaluation ();
8953 freeAsmop (right, NULL, ic, TRUE);
8956 /*-----------------------------------------------------------------*/
8957 /* genGenPointerSet - set value from generic pointer space */
8958 /*-----------------------------------------------------------------*/
8960 genGenPointerSet (operand * right,
8961 operand * result, iCode * ic)
8964 sym_link *retype = getSpec (operandType (right));
8965 sym_link *letype = getSpec (operandType (result));
8967 aopOp (result, ic, FALSE, TRUE);
8969 /* if the operand is already in dptr
8970 then we do nothing else we move the value to dptr */
8971 if (AOP_TYPE (result) != AOP_STR)
8973 _startLazyDPSEvaluation ();
8974 /* if this is remateriazable */
8975 if (AOP_TYPE (result) == AOP_IMMD)
8977 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8978 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8981 { /* we need to get it byte by byte */
8982 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8983 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8984 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8985 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8987 _endLazyDPSEvaluation ();
8989 /* so dptr know contains the address */
8990 freeAsmop (result, NULL, ic, TRUE);
8991 aopOp (right, ic, FALSE, TRUE);
8993 /* if bit then unpack */
8994 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8995 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8998 size = AOP_SIZE (right);
9001 _startLazyDPSEvaluation ();
9004 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9010 emitcode ("lcall", "__gptrput");
9012 emitcode ("inc", "dptr");
9014 _endLazyDPSEvaluation ();
9017 freeAsmop (right, NULL, ic, TRUE);
9020 /*-----------------------------------------------------------------*/
9021 /* genPointerSet - stores the value into a pointer location */
9022 /*-----------------------------------------------------------------*/
9024 genPointerSet (iCode * ic)
9026 operand *right, *result;
9027 sym_link *type, *etype;
9030 D (emitcode (";", "genPointerSet ");
9033 right = IC_RIGHT (ic);
9034 result = IC_RESULT (ic);
9036 /* depending on the type of pointer we need to
9037 move it to the correct pointer register */
9038 type = operandType (result);
9039 etype = getSpec (type);
9040 /* if left is of type of pointer then it is simple */
9041 if (IS_PTR (type) && !IS_FUNC (type->next))
9043 p_type = DCL_TYPE (type);
9047 /* we have to go by the storage class */
9048 p_type = PTR_TYPE (SPEC_OCLS (etype));
9051 /* now that we have the pointer type we assign
9052 the pointer values */
9058 genNearPointerSet (right, result, ic);
9062 genPagedPointerSet (right, result, ic);
9066 genFarPointerSet (right, result, ic);
9070 genGenPointerSet (right, result, ic);
9076 /*-----------------------------------------------------------------*/
9077 /* genIfx - generate code for Ifx statement */
9078 /*-----------------------------------------------------------------*/
9080 genIfx (iCode * ic, iCode * popIc)
9082 operand *cond = IC_COND (ic);
9085 D (emitcode (";", "genIfx "););
9087 aopOp (cond, ic, FALSE, FALSE);
9089 /* get the value into acc */
9090 if (AOP_TYPE (cond) != AOP_CRY)
9094 /* the result is now in the accumulator */
9095 freeAsmop (cond, NULL, ic, TRUE);
9097 /* if there was something to be popped then do it */
9101 /* if the condition is a bit variable */
9102 if (isbit && IS_ITEMP (cond) &&
9104 genIfxJump (ic, SPIL_LOC (cond)->rname);
9105 else if (isbit && !IS_ITEMP (cond))
9106 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9108 genIfxJump (ic, "a");
9113 /*-----------------------------------------------------------------*/
9114 /* genAddrOf - generates code for address of */
9115 /*-----------------------------------------------------------------*/
9117 genAddrOf (iCode * ic)
9119 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9122 D (emitcode (";", "genAddrOf ");
9125 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9127 /* if the operand is on the stack then we
9128 need to get the stack offset of this
9132 /* if it has an offset then we need to compute
9136 emitcode ("mov", "a,_bp");
9137 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9138 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9142 /* we can just move _bp */
9143 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9145 /* fill the result with zero */
9146 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9149 if (options.stack10bit && size < (FPTRSIZE - 1))
9152 "*** warning: pointer to stack var truncated.\n");
9159 if (options.stack10bit && offset == 2)
9161 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9165 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9172 /* object not on stack then we need the name */
9173 size = AOP_SIZE (IC_RESULT (ic));
9178 char s[SDCC_NAME_MAX];
9180 sprintf (s, "#(%s >> %d)",
9184 sprintf (s, "#%s", sym->rname);
9185 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9189 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9193 /*-----------------------------------------------------------------*/
9194 /* genFarFarAssign - assignment when both are in far space */
9195 /*-----------------------------------------------------------------*/
9197 genFarFarAssign (operand * result, operand * right, iCode * ic)
9199 int size = AOP_SIZE (right);
9201 symbol *rSym = NULL;
9205 /* quick & easy case. */
9206 D(emitcode(";","genFarFarAssign (1 byte case)"););
9207 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9208 freeAsmop (right, NULL, ic, FALSE);
9209 /* now assign DPTR to result */
9211 aopOp(result, ic, FALSE, FALSE);
9213 aopPut(AOP(result), "a", 0);
9214 freeAsmop(result, NULL, ic, FALSE);
9218 /* See if we've got an underlying symbol to abuse. */
9219 if (IS_SYMOP(result) && OP_SYMBOL(result))
9221 if (IS_TRUE_SYMOP(result))
9223 rSym = OP_SYMBOL(result);
9225 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9227 rSym = OP_SYMBOL(result)->usl.spillLoc;
9231 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9233 /* We can use the '390 auto-toggle feature to good effect here. */
9235 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9236 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9237 emitcode ("mov", "dptr,#%s", rSym->rname);
9238 /* DP2 = result, DP1 = right, DP1 is current. */
9241 emitcode("movx", "a,@dptr");
9242 emitcode("movx", "@dptr,a");
9245 emitcode("inc", "dptr");
9246 emitcode("inc", "dptr");
9249 emitcode("mov", "dps, #0");
9250 freeAsmop (right, NULL, ic, FALSE);
9254 D (emitcode (";", "genFarFarAssign"););
9255 aopOp (result, ic, TRUE, TRUE);
9257 _startLazyDPSEvaluation ();
9261 aopPut (AOP (result),
9262 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9265 _endLazyDPSEvaluation ();
9266 freeAsmop (result, NULL, ic, FALSE);
9267 freeAsmop (right, NULL, ic, FALSE);
9271 /*-----------------------------------------------------------------*/
9272 /* genAssign - generate code for assignment */
9273 /*-----------------------------------------------------------------*/
9275 genAssign (iCode * ic)
9277 operand *result, *right;
9279 unsigned long lit = 0L;
9281 D (emitcode (";", "genAssign ");
9284 result = IC_RESULT (ic);
9285 right = IC_RIGHT (ic);
9287 /* if they are the same */
9288 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9291 aopOp (right, ic, FALSE, FALSE);
9293 emitcode (";", "genAssign: resultIsFar = %s",
9294 isOperandInFarSpace (result) ?
9297 /* special case both in far space */
9298 if ((AOP_TYPE (right) == AOP_DPTR ||
9299 AOP_TYPE (right) == AOP_DPTR2) &&
9300 /* IS_TRUE_SYMOP(result) && */
9301 isOperandInFarSpace (result))
9303 genFarFarAssign (result, right, ic);
9307 aopOp (result, ic, TRUE, FALSE);
9309 /* if they are the same registers */
9310 if (sameRegs (AOP (right), AOP (result)))
9313 /* if the result is a bit */
9314 if (AOP_TYPE (result) == AOP_CRY)
9317 /* if the right size is a literal then
9318 we know what the value is */
9319 if (AOP_TYPE (right) == AOP_LIT)
9321 if (((int) operandLitValue (right)))
9322 aopPut (AOP (result), one, 0);
9324 aopPut (AOP (result), zero, 0);
9328 /* the right is also a bit variable */
9329 if (AOP_TYPE (right) == AOP_CRY)
9331 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9332 aopPut (AOP (result), "c", 0);
9338 aopPut (AOP (result), "a", 0);
9342 /* bit variables done */
9344 size = AOP_SIZE (result);
9346 if (AOP_TYPE (right) == AOP_LIT)
9347 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9350 (AOP_TYPE (result) != AOP_REG) &&
9351 (AOP_TYPE (right) == AOP_LIT) &&
9352 !IS_FLOAT (operandType (right)))
9354 _startLazyDPSEvaluation ();
9355 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9357 aopPut (AOP (result),
9358 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9363 /* And now fill the rest with zeros. */
9366 emitcode ("clr", "a");
9370 aopPut (AOP (result), "a", offset++);
9372 _endLazyDPSEvaluation ();
9376 _startLazyDPSEvaluation ();
9379 aopPut (AOP (result),
9380 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9384 _endLazyDPSEvaluation ();
9388 freeAsmop (right, NULL, ic, FALSE);
9389 freeAsmop (result, NULL, ic, TRUE);
9392 /*-----------------------------------------------------------------*/
9393 /* genJumpTab - generates code for jump table */
9394 /*-----------------------------------------------------------------*/
9396 genJumpTab (iCode * ic)
9401 D (emitcode (";", "genJumpTab ");
9404 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9405 /* get the condition into accumulator */
9406 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9408 /* multiply by four! */
9409 emitcode ("add", "a,acc");
9410 emitcode ("add", "a,acc");
9411 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9413 jtab = newiTempLabel (NULL);
9414 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9415 emitcode ("jmp", "@a+dptr");
9416 emitcode ("", "%05d$:", jtab->key + 100);
9417 /* now generate the jump labels */
9418 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9419 jtab = setNextItem (IC_JTLABELS (ic)))
9420 emitcode ("ljmp", "%05d$", jtab->key + 100);
9424 /*-----------------------------------------------------------------*/
9425 /* genCast - gen code for casting */
9426 /*-----------------------------------------------------------------*/
9428 genCast (iCode * ic)
9430 operand *result = IC_RESULT (ic);
9431 sym_link *ctype = operandType (IC_LEFT (ic));
9432 sym_link *rtype = operandType (IC_RIGHT (ic));
9433 operand *right = IC_RIGHT (ic);
9436 D (emitcode (";", "genCast ");
9439 /* if they are equivalent then do nothing */
9440 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9443 aopOp (right, ic, FALSE, FALSE);
9444 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9446 /* if the result is a bit */
9447 if (AOP_TYPE (result) == AOP_CRY)
9449 /* if the right size is a literal then
9450 we know what the value is */
9451 if (AOP_TYPE (right) == AOP_LIT)
9453 if (((int) operandLitValue (right)))
9454 aopPut (AOP (result), one, 0);
9456 aopPut (AOP (result), zero, 0);
9461 /* the right is also a bit variable */
9462 if (AOP_TYPE (right) == AOP_CRY)
9464 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9465 aopPut (AOP (result), "c", 0);
9471 aopPut (AOP (result), "a", 0);
9475 /* if they are the same size : or less */
9476 if (AOP_SIZE (result) <= AOP_SIZE (right))
9479 /* if they are in the same place */
9480 if (sameRegs (AOP (right), AOP (result)))
9483 /* if they in different places then copy */
9484 size = AOP_SIZE (result);
9486 _startLazyDPSEvaluation ();
9489 aopPut (AOP (result),
9490 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9494 _endLazyDPSEvaluation ();
9499 /* if the result is of type pointer */
9504 sym_link *type = operandType (right);
9506 /* pointer to generic pointer */
9507 if (IS_GENPTR (ctype))
9513 p_type = DCL_TYPE (type);
9517 #if OLD_CAST_BEHAVIOR
9518 /* KV: we are converting a non-pointer type to
9519 * a generic pointer. This (ifdef'd out) code
9520 * says that the resulting generic pointer
9521 * should have the same class as the storage
9522 * location of the non-pointer variable.
9524 * For example, converting an int (which happens
9525 * to be stored in DATA space) to a pointer results
9526 * in a DATA generic pointer; if the original int
9527 * in XDATA space, so will be the resulting pointer.
9529 * I don't like that behavior, and thus this change:
9530 * all such conversions will be forced to XDATA and
9531 * throw a warning. If you want some non-XDATA
9532 * type, or you want to suppress the warning, you
9533 * must go through an intermediate cast, like so:
9535 * char _generic *gp = (char _xdata *)(intVar);
9537 sym_link *etype = getSpec (type);
9539 /* we have to go by the storage class */
9540 if (SPEC_OCLS (etype) != generic)
9542 p_type = PTR_TYPE (SPEC_OCLS (etype));
9547 /* Converting unknown class (i.e. register variable)
9548 * to generic pointer. This is not good, but
9549 * we'll make a guess (and throw a warning).
9552 werror (W_INT_TO_GEN_PTR_CAST);
9556 /* the first two bytes are known */
9557 size = GPTRSIZE - 1;
9559 _startLazyDPSEvaluation ();
9562 aopPut (AOP (result),
9563 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9567 _endLazyDPSEvaluation ();
9569 /* the last byte depending on type */
9587 /* this should never happen */
9588 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9589 "got unknown pointer type");
9592 aopPut (AOP (result), l, GPTRSIZE - 1);
9596 /* just copy the pointers */
9597 size = AOP_SIZE (result);
9599 _startLazyDPSEvaluation ();
9602 aopPut (AOP (result),
9603 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9607 _endLazyDPSEvaluation ();
9611 /* so we now know that the size of destination is greater
9612 than the size of the source */
9613 /* we move to result for the size of source */
9614 size = AOP_SIZE (right);
9616 _startLazyDPSEvaluation ();
9619 aopPut (AOP (result),
9620 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9624 _endLazyDPSEvaluation ();
9626 /* now depending on the sign of the source && destination */
9627 size = AOP_SIZE (result) - AOP_SIZE (right);
9628 /* if unsigned or not an integral type */
9629 /* also, if the source is a bit, we don't need to sign extend, because
9630 * it can't possibly have set the sign bit.
9632 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9636 aopPut (AOP (result), zero, offset++);
9641 /* we need to extend the sign :{ */
9642 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9643 FALSE, FALSE, TRUE);
9645 emitcode ("rlc", "a");
9646 emitcode ("subb", "a,acc");
9648 aopPut (AOP (result), "a", offset++);
9651 /* we are done hurray !!!! */
9654 freeAsmop (right, NULL, ic, TRUE);
9655 freeAsmop (result, NULL, ic, TRUE);
9659 /*-----------------------------------------------------------------*/
9660 /* genDjnz - generate decrement & jump if not zero instrucion */
9661 /*-----------------------------------------------------------------*/
9663 genDjnz (iCode * ic, iCode * ifx)
9669 /* if the if condition has a false label
9670 then we cannot save */
9674 /* if the minus is not of the form
9676 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9677 !IS_OP_LITERAL (IC_RIGHT (ic)))
9680 if (operandLitValue (IC_RIGHT (ic)) != 1)
9683 /* if the size of this greater than one then no
9685 if (getSize (operandType (IC_RESULT (ic))) > 1)
9688 /* otherwise we can save BIG */
9689 D(emitcode(";", "genDjnz"););
9691 lbl = newiTempLabel (NULL);
9692 lbl1 = newiTempLabel (NULL);
9694 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9696 if (AOP_NEEDSACC(IC_RESULT(ic)))
9698 /* If the result is accessed indirectly via
9699 * the accumulator, we must explicitly write
9700 * it back after the decrement.
9702 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9704 if (strcmp(rByte, "a"))
9706 /* Something is hopelessly wrong */
9707 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9708 __FILE__, __LINE__);
9709 /* We can just give up; the generated code will be inefficient,
9712 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9715 emitcode ("dec", "%s", rByte);
9716 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9717 emitcode ("jnz", "%05d$", lbl->key + 100);
9719 else if (IS_AOP_PREG (IC_RESULT (ic)))
9721 emitcode ("dec", "%s",
9722 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9723 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9724 emitcode ("jnz", "%05d$", lbl->key + 100);
9728 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9731 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9732 emitcode ("", "%05d$:", lbl->key + 100);
9733 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9734 emitcode ("", "%05d$:", lbl1->key + 100);
9736 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9741 /*-----------------------------------------------------------------*/
9742 /* genReceive - generate code for a receive iCode */
9743 /*-----------------------------------------------------------------*/
9745 genReceive (iCode * ic)
9748 D (emitcode (";", "genReceive ");
9751 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9752 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9753 IS_TRUE_SYMOP (IC_RESULT (ic))))
9755 int size = getSize (operandType (IC_RESULT (ic)));
9756 int offset = fReturnSizeDS390 - size;
9759 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9760 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9763 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9764 size = AOP_SIZE (IC_RESULT (ic));
9768 emitcode ("pop", "acc");
9769 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9776 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9778 assignResultValue (IC_RESULT (ic));
9781 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9784 /*-----------------------------------------------------------------*/
9785 /* gen390Code - generate code for Dallas 390 based controllers */
9786 /*-----------------------------------------------------------------*/
9788 gen390Code (iCode * lic)
9793 lineHead = lineCurr = NULL;
9797 /* print the allocation information */
9799 printAllocInfo (currFunc, codeOutFile);
9801 /* if debug information required */
9802 if (options.debug && currFunc)
9804 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9806 if (IS_STATIC (currFunc->etype))
9807 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9809 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9812 /* stack pointer name */
9813 if (options.useXstack)
9819 for (ic = lic; ic; ic = ic->next)
9822 if (cln != ic->lineno)
9827 emitcode ("", "C$%s$%d$%d$%d ==.",
9828 FileBaseName (ic->filename), ic->lineno,
9829 ic->level, ic->block);
9832 emitcode (";", "%s %d", ic->filename, ic->lineno);
9835 /* if the result is marked as
9836 spilt and rematerializable or code for
9837 this has already been generated then
9839 if (resultRemat (ic) || ic->generated)
9842 /* depending on the operation */
9862 /* IPOP happens only when trying to restore a
9863 spilt live range, if there is an ifx statement
9864 following this pop then the if statement might
9865 be using some of the registers being popped which
9866 would destory the contents of the register so
9867 we need to check for this condition and handle it */
9869 ic->next->op == IFX &&
9870 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9871 genIfx (ic->next, ic);
9889 genEndFunction (ic);
9909 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9926 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9930 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9937 /* note these two are xlated by algebraic equivalence
9938 during parsing SDCC.y */
9939 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9940 "got '>=' or '<=' shouldn't have come here");
9944 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9956 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9960 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9964 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9991 case GET_VALUE_AT_ADDRESS:
9996 if (POINTER_SET (ic))
10023 addSet (&_G.sendSet, ic);
10032 /* now we are ready to call the
10033 peep hole optimizer */
10034 if (!options.nopeep)
10035 peepHole (&lineHead);
10037 /* now do the actual printing */
10038 printLine (lineHead, codeOutFile);