1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #define BETTER_LITERAL_SHIFT
53 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
66 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
67 static char *fReturn[] =
68 {"dpl", "dph", "dpx", "b", "a"};
69 static char *accUse[] =
72 static short rbank = -1;
86 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
93 #define MOVA(x) { char *_mova_tmp = strdup(x); \
94 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96 emitcode("mov","a,%s",_mova_tmp); \
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
122 /*-----------------------------------------------------------------*/
123 /* emitcode - writes the code into a file : for now it is simple */
124 /*-----------------------------------------------------------------*/
126 emitcode (char *inst, char *fmt,...)
129 char lb[INITIAL_INLINEASM];
137 sprintf (lb, "%s\t", inst);
139 sprintf (lb, "%s", inst);
140 vsprintf (lb + (strlen (lb)), fmt, ap);
143 vsprintf (lb, fmt, ap);
145 while (isspace (*lbp))
149 lineCurr = (lineCurr ?
150 connectLine (lineCurr, newLineNode (lb)) :
151 (lineHead = newLineNode (lb)));
152 lineCurr->isInline = _G.inLine;
153 lineCurr->isDebug = _G.debugLine;
157 /*-----------------------------------------------------------------*/
158 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
159 /*-----------------------------------------------------------------*/
161 getFreePtr (iCode * ic, asmop ** aopp, bool result)
163 bool r0iu = FALSE, r1iu = FALSE;
164 bool r0ou = FALSE, r1ou = FALSE;
166 /* the logic: if r0 & r1 used in the instruction
167 then we are in trouble otherwise */
169 /* first check if r0 & r1 are used by this
170 instruction, in which case we are in trouble */
171 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
172 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
177 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
178 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
180 /* if no usage of r0 then return it */
183 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
184 (*aopp)->type = AOP_R0;
186 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
189 /* if no usage of r1 then return it */
192 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
193 (*aopp)->type = AOP_R1;
195 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
198 /* now we know they both have usage */
199 /* if r0 not used in this instruction */
202 /* push it if not already pushed */
205 emitcode ("push", "%s",
206 ds390_regWithIdx (R0_IDX)->dname);
210 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
211 (*aopp)->type = AOP_R0;
213 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
216 /* if r1 not used then */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 ds390_regWithIdx (R1_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
229 (*aopp)->type = AOP_R1;
230 return ds390_regWithIdx (R1_IDX);
234 /* I said end of world but not quite end of world yet */
235 /* if this is a result then we can push it on the stack */
238 (*aopp)->type = AOP_STK;
242 /* other wise this is true end of the world */
243 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
244 "getFreePtr should never reach here");
248 /*-----------------------------------------------------------------*/
249 /* newAsmop - creates a new asmOp */
250 /*-----------------------------------------------------------------*/
252 newAsmop (short type)
256 aop = Safe_calloc (1, sizeof (asmop));
261 static int _currentDPS; /* Current processor DPS. */
262 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
263 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
265 /*-----------------------------------------------------------------*/
266 /* genSetDPTR: generate code to select which DPTR is in use (zero */
267 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
268 /* alternate DPTR (DPL1/DPH1/DPX1). */
269 /*-----------------------------------------------------------------*/
274 /* If we are doing lazy evaluation, simply note the desired
275 * change, but don't emit any code yet.
285 emitcode ("mov", "dps, #0x00");
289 emitcode ("mov", "dps, #0x01");
293 /*-----------------------------------------------------------------*/
294 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
296 /* Any code that operates on DPTR (NB: not on the individual */
297 /* components, like DPH) *must* call _flushLazyDPS() before using */
298 /* DPTR within a lazy DPS evaluation block. */
300 /* Note that aopPut and aopGet already contain the proper calls to */
301 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
302 /* DPS evaluation block. */
304 /* Also, _flushLazyDPS must be called before any flow control */
305 /* operations that could potentially branch out of the block. */
307 /* Lazy DPS evaluation is simply an optimization (though an */
308 /* important one), so if in doubt, leave it out. */
309 /*-----------------------------------------------------------------*/
311 _startLazyDPSEvaluation (void)
315 #ifdef BETTER_LITERAL_SHIFT
322 /*-----------------------------------------------------------------*/
323 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
324 /* desired one. Call before using DPTR within a lazy DPS evaluation */
326 /*-----------------------------------------------------------------*/
336 if (_desiredDPS != _currentDPS)
340 emitcode ("inc", "dps");
344 emitcode ("dec", "dps");
346 _currentDPS = _desiredDPS;
350 /*-----------------------------------------------------------------*/
351 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
353 /* Forces us back to the safe state (standard DPTR selected). */
354 /*-----------------------------------------------------------------*/
356 _endLazyDPSEvaluation (void)
358 #ifdef BETTER_LITERAL_SHIFT
377 /*-----------------------------------------------------------------*/
378 /* pointerCode - returns the code for a pointer type */
379 /*-----------------------------------------------------------------*/
381 pointerCode (sym_link * etype)
384 return PTR_TYPE (SPEC_OCLS (etype));
388 /*-----------------------------------------------------------------*/
389 /* aopForSym - for a true symbol */
390 /*-----------------------------------------------------------------*/
392 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
395 memmap *space = SPEC_OCLS (sym->etype);
397 /* if already has one */
401 /* assign depending on the storage class */
402 /* if it is on the stack or indirectly addressable */
403 /* space we need to assign either r0 or r1 to it */
404 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
406 sym->aop = aop = newAsmop (0);
407 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
408 aop->size = getSize (sym->type);
410 /* now assign the address of the variable to
411 the pointer register */
412 if (aop->type != AOP_STK)
418 emitcode ("push", "acc");
420 emitcode ("mov", "a,_bp");
421 emitcode ("add", "a,#0x%02x",
423 ((char) (sym->stack - _G.nRegsSaved)) :
424 ((char) sym->stack)) & 0xff);
425 emitcode ("mov", "%s,a",
426 aop->aopu.aop_ptr->name);
429 emitcode ("pop", "acc");
432 emitcode ("mov", "%s,#%s",
433 aop->aopu.aop_ptr->name,
435 aop->paged = space->paged;
438 aop->aopu.aop_stk = sym->stack;
442 if (sym->onStack && options.stack10bit)
444 /* It's on the 10 bit stack, which is located in
449 emitcode ("push", "acc");
451 emitcode ("mov", "a,_bp");
452 emitcode ("add", "a,#0x%02x",
454 ((char) (sym->stack - _G.nRegsSaved)) :
455 ((char) sym->stack)) & 0xff);
459 emitcode ("mov", "dpx1,#0x40");
460 emitcode ("mov", "dph1,#0x00");
461 emitcode ("mov", "dpl1, a");
465 emitcode ("mov", "dpx,#0x40");
466 emitcode ("mov", "dph,#0x00");
467 emitcode ("mov", "dpl, a");
471 emitcode ("pop", "acc");
473 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
474 aop->size = getSize (sym->type);
478 /* if in bit space */
479 if (IN_BITSPACE (space))
481 sym->aop = aop = newAsmop (AOP_CRY);
482 aop->aopu.aop_dir = sym->rname;
483 aop->size = getSize (sym->type);
486 /* if it is in direct space */
487 if (IN_DIRSPACE (space))
489 sym->aop = aop = newAsmop (AOP_DIR);
490 aop->aopu.aop_dir = sym->rname;
491 aop->size = getSize (sym->type);
495 /* special case for a function */
496 if (IS_FUNC (sym->type))
498 sym->aop = aop = newAsmop (AOP_IMMD);
499 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
500 strcpy (aop->aopu.aop_immd, sym->rname);
501 aop->size = FPTRSIZE;
505 /* only remaining is far space */
506 /* in which case DPTR gets the address */
507 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
512 emitcode ("mov", "dptr,#%s", sym->rname);
517 emitcode ("mov", "dptr,#%s", sym->rname);
519 aop->size = getSize (sym->type);
521 /* if it is in code space */
522 if (IN_CODESPACE (space))
528 /*-----------------------------------------------------------------*/
529 /* aopForRemat - rematerialzes an object */
530 /*-----------------------------------------------------------------*/
532 aopForRemat (symbol * sym)
534 iCode *ic = sym->rematiCode;
535 asmop *aop = newAsmop (AOP_IMMD);
542 val += (int) operandLitValue (IC_RIGHT (ic));
543 else if (ic->op == '-')
544 val -= (int) operandLitValue (IC_RIGHT (ic));
548 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
552 sprintf (buffer, "(%s %c 0x%04x)",
553 OP_SYMBOL (IC_LEFT (ic))->rname,
554 val >= 0 ? '+' : '-',
557 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
559 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
560 strcpy (aop->aopu.aop_immd, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
658 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
665 if (aop1->type != AOP_REG ||
666 aop2->type != AOP_REG)
669 if (aop1->size != aop2->size)
672 for (i = 0; i < aop1->size; i++)
673 if (aop1->aopu.aop_reg[i] !=
674 aop2->aopu.aop_reg[i])
680 /*-----------------------------------------------------------------*/
681 /* aopOp - allocates an asmop for an operand : */
682 /*-----------------------------------------------------------------*/
684 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
693 /* if this a literal */
694 if (IS_OP_LITERAL (op))
696 op->aop = aop = newAsmop (AOP_LIT);
697 aop->aopu.aop_lit = op->operand.valOperand;
698 aop->size = getSize (operandType (op));
702 /* if already has a asmop then continue */
706 /* if the underlying symbol has a aop */
707 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
709 op->aop = OP_SYMBOL (op)->aop;
713 /* if this is a true symbol */
714 if (IS_TRUE_SYMOP (op))
716 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
720 /* this is a temporary : this has
726 e) can be a return use only */
728 sym = OP_SYMBOL (op);
731 /* if the type is a conditional */
732 if (sym->regType == REG_CND)
734 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
739 /* if it is spilt then two situations
741 b) has a spill location */
742 if (sym->isspilt || sym->nRegs == 0)
745 /* rematerialize it NOW */
748 sym->aop = op->aop = aop =
750 aop->size = getSize (sym->type);
757 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
758 aop->size = getSize (sym->type);
759 for (i = 0; i < 2; i++)
760 aop->aopu.aop_str[i] = accUse[i];
770 /* a AOP_STR uses DPTR, but DPTR is already in use;
773 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
776 aop = op->aop = sym->aop = newAsmop (AOP_STR);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < (int) fReturnSizeDS390; i++)
779 aop->aopu.aop_str[i] = fReturn[i];
783 /* else spill location */
784 sym->aop = op->aop = aop =
785 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
786 aop->size = getSize (sym->type);
790 /* must be in a register */
791 sym->aop = op->aop = aop = newAsmop (AOP_REG);
792 aop->size = sym->nRegs;
793 for (i = 0; i < sym->nRegs; i++)
794 aop->aopu.aop_reg[i] = sym->regs[i];
797 /*-----------------------------------------------------------------*/
798 /* freeAsmop - free up the asmop given to an operand */
799 /*----------------------------------------------------------------*/
801 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
818 /* depending on the asmop type only three cases need work AOP_RO
819 , AOP_R1 && AOP_STK */
827 emitcode ("pop", "ar0");
831 bitVectUnSetBit (ic->rUsed, R0_IDX);
839 emitcode ("pop", "ar1");
843 bitVectUnSetBit (ic->rUsed, R1_IDX);
849 int stk = aop->aopu.aop_stk + aop->size;
850 bitVectUnSetBit (ic->rUsed, R0_IDX);
851 bitVectUnSetBit (ic->rUsed, R1_IDX);
853 getFreePtr (ic, &aop, FALSE);
855 if (options.stack10bit)
857 /* I'm not sure what to do here yet... */
860 "*** Warning: probably generating bad code for "
861 "10 bit stack mode.\n");
866 emitcode ("mov", "a,_bp");
867 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
868 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
872 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
877 emitcode ("pop", "acc");
878 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
881 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
884 freeAsmop (op, NULL, ic, TRUE);
887 emitcode ("pop", "ar0");
893 emitcode ("pop", "ar1");
900 /* all other cases just dealloc */
906 OP_SYMBOL (op)->aop = NULL;
907 /* if the symbol has a spill */
909 SPIL_LOC (op)->aop = NULL;
914 /*------------------------------------------------------------------*/
915 /* aopGet - for fetching value of the aop */
917 /* Set canClobberACC if you are sure it is OK to clobber the value */
918 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
919 /* just less efficient. */
920 /*------------------------------------------------------------------*/
932 /* offset is greater than
934 if (offset > (aop->size - 1) &&
935 aop->type != AOP_LIT)
938 /* depending on type */
944 /* if we need to increment it */
945 while (offset > aop->coff)
947 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
951 while (offset < aop->coff)
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
960 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
961 return (dname ? "acc" : "a");
963 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
964 rs = Safe_calloc (1, strlen (s) + 1);
971 if (aop->type == AOP_DPTR2)
976 emitcode ("xch", "a, %s", DP2_RESULT_REG);
982 while (offset > aop->coff)
984 emitcode ("inc", "dptr");
988 while (offset < aop->coff)
990 emitcode ("lcall", "__decdptr");
997 emitcode ("clr", "a");
998 emitcode ("movc", "a,@a+dptr");
1002 emitcode ("movx", "a,@dptr");
1005 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011 return DP2_RESULT_REG;
1014 return (dname ? "acc" : "a");
1018 sprintf (s, "#%s", aop->aopu.aop_immd);
1020 sprintf (s, "#(%s >> %d)",
1025 aop->aopu.aop_immd);
1026 rs = Safe_calloc (1, strlen (s) + 1);
1032 sprintf (s, "(%s + %d)",
1036 sprintf (s, "%s", aop->aopu.aop_dir);
1037 rs = Safe_calloc (1, strlen (s) + 1);
1043 return aop->aopu.aop_reg[offset]->dname;
1045 return aop->aopu.aop_reg[offset]->name;
1048 emitcode ("clr", "a");
1049 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1050 emitcode ("rlc", "a");
1051 return (dname ? "acc" : "a");
1054 if (!offset && dname)
1056 return aop->aopu.aop_str[offset];
1059 return aopLiteral (aop->aopu.aop_lit, offset);
1063 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1067 return aop->aopu.aop_str[offset];
1071 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1072 "aopget got unsupported aop->type");
1075 /*-----------------------------------------------------------------*/
1076 /* aopPut - puts a string for a aop */
1077 /*-----------------------------------------------------------------*/
1079 aopPut (asmop * aop, char *s, int offset)
1083 if (aop->size && offset > (aop->size - 1))
1085 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1086 "aopPut got offset > aop->size");
1090 /* will assign value to value */
1091 /* depending on where it is ofcourse */
1096 sprintf (d, "(%s + %d)",
1097 aop->aopu.aop_dir, offset);
1099 sprintf (d, "%s", aop->aopu.aop_dir);
1102 emitcode ("mov", "%s,%s", d, s);
1107 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1108 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1111 strcmp (s, "r0") == 0 ||
1112 strcmp (s, "r1") == 0 ||
1113 strcmp (s, "r2") == 0 ||
1114 strcmp (s, "r3") == 0 ||
1115 strcmp (s, "r4") == 0 ||
1116 strcmp (s, "r5") == 0 ||
1117 strcmp (s, "r6") == 0 ||
1118 strcmp (s, "r7") == 0)
1119 emitcode ("mov", "%s,%s",
1120 aop->aopu.aop_reg[offset]->dname, s);
1122 emitcode ("mov", "%s,%s",
1123 aop->aopu.aop_reg[offset]->name, s);
1130 if (aop->type == AOP_DPTR2)
1138 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139 "aopPut writting to code space");
1143 while (offset > aop->coff)
1146 emitcode ("inc", "dptr");
1149 while (offset < aop->coff)
1152 emitcode ("lcall", "__decdptr");
1157 /* if not in accumulater */
1160 emitcode ("movx", "@dptr,a");
1162 if (aop->type == AOP_DPTR2)
1170 while (offset > aop->coff)
1173 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1175 while (offset < aop->coff)
1178 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1185 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1191 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1193 else if (strcmp (s, "r0") == 0 ||
1194 strcmp (s, "r1") == 0 ||
1195 strcmp (s, "r2") == 0 ||
1196 strcmp (s, "r3") == 0 ||
1197 strcmp (s, "r4") == 0 ||
1198 strcmp (s, "r5") == 0 ||
1199 strcmp (s, "r6") == 0 ||
1200 strcmp (s, "r7") == 0)
1203 sprintf (buffer, "a%s", s);
1204 emitcode ("mov", "@%s,%s",
1205 aop->aopu.aop_ptr->name, buffer);
1208 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1213 if (strcmp (s, "a") == 0)
1214 emitcode ("push", "acc");
1216 emitcode ("push", "%s", s);
1221 /* if bit variable */
1222 if (!aop->aopu.aop_dir)
1224 emitcode ("clr", "a");
1225 emitcode ("rlc", "a");
1230 emitcode ("clr", "%s", aop->aopu.aop_dir);
1232 emitcode ("setb", "%s", aop->aopu.aop_dir);
1233 else if (!strcmp (s, "c"))
1234 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237 if (strcmp (s, "a"))
1242 symbol *lbl = newiTempLabel (NULL);
1243 emitcode ("clr", "c");
1244 emitcode ("jz", "%05d$", lbl->key + 100);
1245 emitcode ("cpl", "c");
1246 emitcode ("", "%05d$:", lbl->key + 100);
1247 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1255 if (strcmp (aop->aopu.aop_str[offset], s))
1256 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1261 if (!offset && (strcmp (s, "acc") == 0))
1264 if (strcmp (aop->aopu.aop_str[offset], s))
1265 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1270 "aopPut got unsupported aop->type");
1277 /*--------------------------------------------------------------------*/
1278 /* reAdjustPreg - points a register back to where it should (coff==0) */
1279 /*--------------------------------------------------------------------*/
1281 reAdjustPreg (asmop * aop)
1283 if ((aop->coff==0) || (aop->size <= 1)) {
1292 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1296 if (aop->type == AOP_DPTR2)
1303 emitcode ("lcall", "__decdptr");
1306 if (aop->type == AOP_DPTR2)
1316 #define AOP(op) op->aop
1317 #define AOP_TYPE(op) AOP(op)->type
1318 #define AOP_SIZE(op) AOP(op)->size
1319 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1320 AOP_TYPE(x) == AOP_R0))
1322 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1323 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1326 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1327 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1328 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1330 /* Workaround for DS80C390 bug: div ab may return bogus results
1331 * if A is accessed in instruction immediately before the div.
1333 * Will be fixed in B4 rev of processor, Dallas claims.
1336 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1337 if (!AOP_NEEDSACC(RIGHT)) \
1339 /* We can load A first, then B, since \
1340 * B (the RIGHT operand) won't clobber A, \
1341 * thus avoiding touching A right before the div. \
1343 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1344 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1346 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1350 /* Just stuff in a nop after loading A. */ \
1351 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1352 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1354 emitcode("nop", "; workaround for DS80C390 div bug."); \
1357 /*-----------------------------------------------------------------*/
1358 /* genNotFloat - generates not for float operations */
1359 /*-----------------------------------------------------------------*/
1361 genNotFloat (operand * op, operand * res)
1367 D (emitcode (";", "genNotFloat ");
1370 /* we will put 127 in the first byte of
1372 aopPut (AOP (res), "#127", 0);
1373 size = AOP_SIZE (op) - 1;
1376 _startLazyDPSEvaluation ();
1377 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1382 emitcode ("orl", "a,%s",
1384 offset++, FALSE, FALSE, FALSE));
1386 _endLazyDPSEvaluation ();
1388 tlbl = newiTempLabel (NULL);
1389 aopPut (res->aop, one, 1);
1390 emitcode ("jz", "%05d$", (tlbl->key + 100));
1391 aopPut (res->aop, zero, 1);
1392 emitcode ("", "%05d$:", (tlbl->key + 100));
1394 size = res->aop->size - 2;
1396 /* put zeros in the rest */
1398 aopPut (res->aop, zero, offset++);
1401 /*-----------------------------------------------------------------*/
1402 /* opIsGptr: returns non-zero if the passed operand is */
1403 /* a generic pointer type. */
1404 /*-----------------------------------------------------------------*/
1406 opIsGptr (operand * op)
1408 sym_link *type = operandType (op);
1410 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1417 /*-----------------------------------------------------------------*/
1418 /* getDataSize - get the operand data size */
1419 /*-----------------------------------------------------------------*/
1421 getDataSize (operand * op)
1424 size = AOP_SIZE (op);
1425 if (size == GPTRSIZE)
1427 sym_link *type = operandType (op);
1428 if (IS_GENPTR (type))
1430 /* generic pointer; arithmetic operations
1431 * should ignore the high byte (pointer type).
1439 /*-----------------------------------------------------------------*/
1440 /* outAcc - output Acc */
1441 /*-----------------------------------------------------------------*/
1443 outAcc (operand * result)
1446 size = getDataSize (result);
1449 aopPut (AOP (result), "a", 0);
1452 /* unsigned or positive */
1455 aopPut (AOP (result), zero, offset++);
1460 /*-----------------------------------------------------------------*/
1461 /* outBitC - output a bit C */
1462 /*-----------------------------------------------------------------*/
1464 outBitC (operand * result)
1466 /* if the result is bit */
1467 if (AOP_TYPE (result) == AOP_CRY)
1469 aopPut (AOP (result), "c", 0);
1473 emitcode ("clr", "a");
1474 emitcode ("rlc", "a");
1479 /*-----------------------------------------------------------------*/
1480 /* toBoolean - emit code for orl a,operator(sizeop) */
1481 /*-----------------------------------------------------------------*/
1483 toBoolean (operand * oper)
1485 int size = AOP_SIZE (oper) - 1;
1489 /* The generic part of a generic pointer should
1490 * not participate in it's truth value.
1492 * i.e. 0x10000000 is zero.
1494 if (opIsGptr (oper))
1496 D (emitcode (";", "toBoolean: generic ptr special case.");
1501 _startLazyDPSEvaluation ();
1502 if (AOP_NEEDSACC (oper) && size)
1505 emitcode ("push", "b");
1506 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1510 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1516 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1520 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1523 _endLazyDPSEvaluation ();
1527 emitcode ("mov", "a,b");
1528 emitcode ("pop", "b");
1533 /*-----------------------------------------------------------------*/
1534 /* genNot - generate code for ! operation */
1535 /*-----------------------------------------------------------------*/
1540 sym_link *optype = operandType (IC_LEFT (ic));
1542 D (emitcode (";", "genNot ");
1545 /* assign asmOps to operand & result */
1546 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1547 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1549 /* if in bit space then a special case */
1550 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1552 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1553 emitcode ("cpl", "c");
1554 outBitC (IC_RESULT (ic));
1558 /* if type float then do float */
1559 if (IS_FLOAT (optype))
1561 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1565 toBoolean (IC_LEFT (ic));
1567 tlbl = newiTempLabel (NULL);
1568 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1569 emitcode ("", "%05d$:", tlbl->key + 100);
1570 outBitC (IC_RESULT (ic));
1573 /* release the aops */
1574 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1575 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1579 /*-----------------------------------------------------------------*/
1580 /* genCpl - generate code for complement */
1581 /*-----------------------------------------------------------------*/
1588 D (emitcode (";", "genCpl ");
1592 /* assign asmOps to operand & result */
1593 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1594 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1596 /* if both are in bit space then
1598 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1599 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1602 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1603 emitcode ("cpl", "c");
1604 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1608 size = AOP_SIZE (IC_RESULT (ic));
1609 _startLazyDPSEvaluation ();
1612 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1614 emitcode ("cpl", "a");
1615 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1617 _endLazyDPSEvaluation ();
1621 /* release the aops */
1622 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1623 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* genUminusFloat - unary minus for floating points */
1628 /*-----------------------------------------------------------------*/
1630 genUminusFloat (operand * op, operand * result)
1632 int size, offset = 0;
1634 /* for this we just need to flip the
1635 first it then copy the rest in place */
1636 D (emitcode (";", "genUminusFloat");
1639 _startLazyDPSEvaluation ();
1640 size = AOP_SIZE (op) - 1;
1641 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1644 emitcode ("cpl", "acc.7");
1645 aopPut (AOP (result), "a", 3);
1649 aopPut (AOP (result),
1650 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1654 _endLazyDPSEvaluation ();
1657 /*-----------------------------------------------------------------*/
1658 /* genUminus - unary minus code generation */
1659 /*-----------------------------------------------------------------*/
1661 genUminus (iCode * ic)
1664 sym_link *optype, *rtype;
1666 D (emitcode (";", "genUminus ");
1671 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1672 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1674 /* if both in bit space then special
1676 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1677 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1680 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1681 emitcode ("cpl", "c");
1682 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1686 optype = operandType (IC_LEFT (ic));
1687 rtype = operandType (IC_RESULT (ic));
1689 /* if float then do float stuff */
1690 if (IS_FLOAT (optype))
1692 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1696 /* otherwise subtract from zero */
1697 size = AOP_SIZE (IC_LEFT (ic));
1699 _startLazyDPSEvaluation ();
1702 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1703 if (!strcmp (l, "a"))
1707 emitcode ("cpl", "a");
1708 emitcode ("addc", "a,#0");
1714 emitcode ("clr", "a");
1715 emitcode ("subb", "a,%s", l);
1717 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1719 _endLazyDPSEvaluation ();
1721 /* if any remaining bytes in the result */
1722 /* we just need to propagate the sign */
1723 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1725 emitcode ("rlc", "a");
1726 emitcode ("subb", "a,acc");
1728 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1732 /* release the aops */
1733 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1734 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1737 /*-----------------------------------------------------------------*/
1738 /* saveRegisters - will look for a call and save the registers */
1739 /*-----------------------------------------------------------------*/
1741 saveRegisters (iCode * lic)
1749 for (ic = lic; ic; ic = ic->next)
1750 if (ic->op == CALL || ic->op == PCALL)
1755 fprintf (stderr, "found parameter push with no function call\n");
1759 /* if the registers have been saved already then
1761 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1764 /* find the registers in use at this time
1765 and push them away to safety */
1766 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1770 if (options.useXstack)
1772 if (bitVectBitValue (rsave, R0_IDX))
1773 emitcode ("mov", "b,r0");
1774 emitcode ("mov", "r0,%s", spname);
1775 for (i = 0; i < ds390_nRegs; i++)
1777 if (bitVectBitValue (rsave, i))
1780 emitcode ("mov", "a,b");
1782 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1783 emitcode ("movx", "@r0,a");
1784 emitcode ("inc", "r0");
1787 emitcode ("mov", "%s,r0", spname);
1788 if (bitVectBitValue (rsave, R0_IDX))
1789 emitcode ("mov", "r0,b");
1792 for (i = 0; i < ds390_nRegs; i++)
1794 if (bitVectBitValue (rsave, i))
1795 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1798 detype = getSpec (operandType (IC_LEFT (ic)));
1800 #if 0 // why should we do this here??? jwk20011105
1802 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1803 IS_ISR (currFunc->etype) &&
1805 saveRBank (SPEC_BANK (detype), ic, TRUE);
1809 /*-----------------------------------------------------------------*/
1810 /* unsaveRegisters - pop the pushed registers */
1811 /*-----------------------------------------------------------------*/
1813 unsaveRegisters (iCode * ic)
1817 /* find the registers in use at this time
1818 and push them away to safety */
1819 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1822 if (options.useXstack)
1824 emitcode ("mov", "r0,%s", spname);
1825 for (i = ds390_nRegs; i >= 0; i--)
1827 if (bitVectBitValue (rsave, i))
1829 emitcode ("dec", "r0");
1830 emitcode ("movx", "a,@r0");
1832 emitcode ("mov", "b,a");
1834 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1838 emitcode ("mov", "%s,r0", spname);
1839 if (bitVectBitValue (rsave, R0_IDX))
1840 emitcode ("mov", "r0,b");
1843 for (i = ds390_nRegs; i >= 0; i--)
1845 if (bitVectBitValue (rsave, i))
1846 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1852 /*-----------------------------------------------------------------*/
1854 /*-----------------------------------------------------------------*/
1856 pushSide (operand * oper, int size)
1859 _startLazyDPSEvaluation ();
1862 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1863 if (AOP_TYPE (oper) != AOP_REG &&
1864 AOP_TYPE (oper) != AOP_DIR &&
1867 emitcode ("mov", "a,%s", l);
1868 emitcode ("push", "acc");
1871 emitcode ("push", "%s", l);
1873 _endLazyDPSEvaluation ();
1876 /*-----------------------------------------------------------------*/
1877 /* assignResultValue - */
1878 /*-----------------------------------------------------------------*/
1880 assignResultValue (operand * oper)
1883 int size = AOP_SIZE (oper);
1885 _startLazyDPSEvaluation ();
1888 aopPut (AOP (oper), fReturn[offset], offset);
1891 _endLazyDPSEvaluation ();
1895 /*-----------------------------------------------------------------*/
1896 /* genXpush - pushes onto the external stack */
1897 /*-----------------------------------------------------------------*/
1899 genXpush (iCode * ic)
1901 asmop *aop = newAsmop (0);
1903 int size, offset = 0;
1905 D (emitcode (";", "genXpush ");
1908 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1909 r = getFreePtr (ic, &aop, FALSE);
1912 emitcode ("mov", "%s,_spx", r->name);
1914 size = AOP_SIZE (IC_LEFT (ic));
1915 _startLazyDPSEvaluation ();
1919 char *l = aopGet (AOP (IC_LEFT (ic)),
1920 offset++, FALSE, FALSE, TRUE);
1922 emitcode ("movx", "@%s,a", r->name);
1923 emitcode ("inc", "%s", r->name);
1926 _endLazyDPSEvaluation ();
1929 emitcode ("mov", "_spx,%s", r->name);
1931 freeAsmop (NULL, aop, ic, TRUE);
1932 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1935 /*-----------------------------------------------------------------*/
1936 /* genIpush - genrate code for pushing this gets a little complex */
1937 /*-----------------------------------------------------------------*/
1939 genIpush (iCode * ic)
1941 int size, offset = 0;
1944 D (emitcode (";", "genIpush ");
1947 /* if this is not a parm push : ie. it is spill push
1948 and spill push is always done on the local stack */
1952 /* and the item is spilt then do nothing */
1953 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1956 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1957 size = AOP_SIZE (IC_LEFT (ic));
1958 /* push it on the stack */
1959 _startLazyDPSEvaluation ();
1962 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1968 emitcode ("push", "%s", l);
1970 _endLazyDPSEvaluation ();
1974 /* this is a paramter push: in this case we call
1975 the routine to find the call and save those
1976 registers that need to be saved */
1979 /* if use external stack then call the external
1980 stack pushing routine */
1981 if (options.useXstack)
1987 /* then do the push */
1988 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1990 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1991 size = AOP_SIZE (IC_LEFT (ic));
1993 _startLazyDPSEvaluation ();
1996 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1997 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1998 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2001 emitcode ("mov", "a,%s", l);
2002 emitcode ("push", "acc");
2005 emitcode ("push", "%s", l);
2007 _endLazyDPSEvaluation ();
2009 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genIpop - recover the registers: can happen only for spilling */
2014 /*-----------------------------------------------------------------*/
2016 genIpop (iCode * ic)
2020 D (emitcode (";", "genIpop ");
2024 /* if the temp was not pushed then */
2025 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2028 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2029 size = AOP_SIZE (IC_LEFT (ic));
2030 offset = (size - 1);
2031 _startLazyDPSEvaluation ();
2034 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2035 FALSE, TRUE, TRUE));
2037 _endLazyDPSEvaluation ();
2039 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2042 /*-----------------------------------------------------------------*/
2043 /* unsaveRBank - restores the resgister bank from stack */
2044 /*-----------------------------------------------------------------*/
2046 unsaveRBank (int bank, iCode * ic, bool popPsw)
2052 if (options.useXstack)
2056 /* Assume r0 is available for use. */
2057 r = ds390_regWithIdx (R0_IDX);;
2062 r = getFreePtr (ic, &aop, FALSE);
2064 emitcode ("mov", "%s,_spx", r->name);
2069 if (options.useXstack)
2071 emitcode ("movx", "a,@%s", r->name);
2072 emitcode ("mov", "psw,a");
2073 emitcode ("dec", "%s", r->name);
2077 emitcode ("pop", "psw");
2081 for (i = (ds390_nRegs - 1); i >= 0; i--)
2083 if (options.useXstack)
2085 emitcode ("movx", "a,@%s", r->name);
2086 emitcode ("mov", "(%s+%d),a",
2087 regs390[i].base, 8 * bank + regs390[i].offset);
2088 emitcode ("dec", "%s", r->name);
2092 emitcode ("pop", "(%s+%d)",
2093 regs390[i].base, 8 * bank + regs390[i].offset);
2096 if (options.useXstack)
2098 emitcode ("mov", "_spx,%s", r->name);
2103 freeAsmop (NULL, aop, ic, TRUE);
2107 /*-----------------------------------------------------------------*/
2108 /* saveRBank - saves an entire register bank on the stack */
2109 /*-----------------------------------------------------------------*/
2111 saveRBank (int bank, iCode * ic, bool pushPsw)
2117 if (options.useXstack)
2121 /* Assume r0 is available for use. */
2122 r = ds390_regWithIdx (R0_IDX);;
2127 r = getFreePtr (ic, &aop, FALSE);
2129 emitcode ("mov", "%s,_spx", r->name);
2132 for (i = 0; i < ds390_nRegs; i++)
2134 if (options.useXstack)
2136 emitcode ("inc", "%s", r->name);
2137 emitcode ("mov", "a,(%s+%d)",
2138 regs390[i].base, 8 * bank + regs390[i].offset);
2139 emitcode ("movx", "@%s,a", r->name);
2142 emitcode ("push", "(%s+%d)",
2143 regs390[i].base, 8 * bank + regs390[i].offset);
2148 if (options.useXstack)
2150 emitcode ("mov", "a,psw");
2151 emitcode ("movx", "@%s,a", r->name);
2152 emitcode ("inc", "%s", r->name);
2153 emitcode ("mov", "_spx,%s", r->name);
2157 emitcode ("push", "psw");
2160 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2165 freeAsmop (NULL, aop, ic, TRUE);
2174 /*-----------------------------------------------------------------*/
2175 /* genCall - generates a call statement */
2176 /*-----------------------------------------------------------------*/
2178 genCall (iCode * ic)
2181 bool restoreBank = FALSE;
2182 bool swapBanks = FALSE;
2184 D (emitcode (";", "genCall "););
2186 /* if we are calling a function that is not using
2187 the same register bank then we need to save the
2188 destination registers on the stack */
2189 detype = getSpec (operandType (IC_LEFT (ic)));
2191 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2192 IS_ISR (currFunc->etype))
2196 /* This is unexpected; the bank should have been saved in
2199 saveRBank (SPEC_BANK (detype), ic, FALSE);
2205 /* if caller saves & we have not saved then */
2209 /* if send set is not empty the assign */
2210 /* We've saved all the registers we care about;
2211 * therefore, we may clobber any register not used
2212 * in the calling convention (i.e. anything not in
2219 for (sic = setFirstItem (_G.sendSet); sic;
2220 sic = setNextItem (_G.sendSet))
2222 int size, offset = 0;
2224 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2225 size = AOP_SIZE (IC_LEFT (sic));
2227 _startLazyDPSEvaluation ();
2230 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2231 FALSE, FALSE, TRUE);
2232 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2234 emitcode("mov", "%s,%s", regs390[offset].name, l);
2236 else if (strcmp (l, fReturn[offset]))
2238 emitcode ("mov", "%s,%s",
2244 _endLazyDPSEvaluation ();
2245 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2247 size = AOP_SIZE (IC_LEFT (sic));
2255 emitcode("mov", "%s,%s",
2256 fReturn[size], regs390[size].name);
2259 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2266 emitcode ("mov", "psw,#0x%02x",
2267 ((SPEC_BANK(detype)) << 3) & 0xff);
2271 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2272 OP_SYMBOL (IC_LEFT (ic))->rname :
2273 OP_SYMBOL (IC_LEFT (ic))->name));
2277 emitcode ("mov", "psw,#0x%02x",
2278 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
2281 /* if we need assign a result value */
2282 if ((IS_ITEMP (IC_RESULT (ic)) &&
2283 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2284 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2285 IS_TRUE_SYMOP (IC_RESULT (ic)))
2287 if (isOperandInFarSpace (IC_RESULT (ic))
2288 && getSize (operandType (IC_RESULT (ic))) <= 2)
2290 int size = getSize (operandType (IC_RESULT (ic)));
2292 /* Special case for 1 or 2 byte return in far space. */
2296 emitcode ("mov", "b,%s", fReturn[1]);
2299 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2300 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2304 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2311 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2314 assignResultValue (IC_RESULT (ic));
2316 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2320 /* adjust the stack for parameters if
2325 if (ic->parmBytes > 3)
2327 emitcode ("mov", "a,%s", spname);
2328 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2329 emitcode ("mov", "%s,a", spname);
2332 for (i = 0; i < ic->parmBytes; i++)
2333 emitcode ("dec", "%s", spname);
2336 /* if we hade saved some registers then unsave them */
2337 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2338 unsaveRegisters (ic);
2340 /* if register bank was saved then pop them */
2342 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
2345 /*-----------------------------------------------------------------*/
2346 /* genPcall - generates a call by pointer statement */
2347 /*-----------------------------------------------------------------*/
2349 genPcall (iCode * ic)
2352 symbol *rlbl = newiTempLabel (NULL);
2354 D (emitcode (";", "genPcall ");
2358 /* if caller saves & we have not saved then */
2362 /* if we are calling a function that is not using
2363 the same register bank then we need to save the
2364 destination registers on the stack */
2365 detype = getSpec (operandType (IC_LEFT (ic)));
2367 IS_ISR (currFunc->etype) &&
2368 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2369 saveRBank (SPEC_BANK (detype), ic, TRUE);
2372 /* push the return address on to the stack */
2373 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2374 emitcode ("push", "acc");
2375 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2376 emitcode ("push", "acc");
2378 if (options.model == MODEL_FLAT24)
2380 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2381 emitcode ("push", "acc");
2384 /* now push the calling address */
2385 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2387 pushSide (IC_LEFT (ic), FPTRSIZE);
2389 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2391 /* if send set is not empty the assign */
2396 for (sic = setFirstItem (_G.sendSet); sic;
2397 sic = setNextItem (_G.sendSet))
2399 int size, offset = 0;
2401 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2402 size = AOP_SIZE (IC_LEFT (sic));
2403 _startLazyDPSEvaluation ();
2406 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2407 FALSE, FALSE, TRUE);
2408 if (strcmp (l, fReturn[offset]))
2410 emitcode ("mov", "%s,%s",
2416 _endLazyDPSEvaluation ();
2417 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2422 emitcode ("ret", "");
2423 emitcode ("", "%05d$:", (rlbl->key + 100));
2426 /* if we need assign a result value */
2427 if ((IS_ITEMP (IC_RESULT (ic)) &&
2428 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2429 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2430 IS_TRUE_SYMOP (IC_RESULT (ic)))
2434 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2437 assignResultValue (IC_RESULT (ic));
2439 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2442 /* adjust the stack for parameters if
2447 if (ic->parmBytes > 3)
2449 emitcode ("mov", "a,%s", spname);
2450 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2451 emitcode ("mov", "%s,a", spname);
2454 for (i = 0; i < ic->parmBytes; i++)
2455 emitcode ("dec", "%s", spname);
2459 /* if register bank was saved then unsave them */
2461 (SPEC_BANK (currFunc->etype) !=
2462 SPEC_BANK (detype)))
2463 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2465 /* if we hade saved some registers then
2468 unsaveRegisters (ic);
2472 /*-----------------------------------------------------------------*/
2473 /* resultRemat - result is rematerializable */
2474 /*-----------------------------------------------------------------*/
2476 resultRemat (iCode * ic)
2478 if (SKIP_IC (ic) || ic->op == IFX)
2481 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2483 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2484 if (sym->remat && !POINTER_SET (ic))
2491 #if defined(__BORLANDC__) || defined(_MSC_VER)
2492 #define STRCASECMP stricmp
2494 #define STRCASECMP strcasecmp
2497 /*-----------------------------------------------------------------*/
2498 /* inExcludeList - return 1 if the string is in exclude Reg list */
2499 /*-----------------------------------------------------------------*/
2501 inExcludeList (char *s)
2505 if (options.excludeRegs[i] &&
2506 STRCASECMP (options.excludeRegs[i], "none") == 0)
2509 for (i = 0; options.excludeRegs[i]; i++)
2511 if (options.excludeRegs[i] &&
2512 STRCASECMP (s, options.excludeRegs[i]) == 0)
2518 /*-----------------------------------------------------------------*/
2519 /* genFunction - generated code for function entry */
2520 /*-----------------------------------------------------------------*/
2522 genFunction (iCode * ic)
2526 bool switchedPSW = FALSE;
2528 D (emitcode (";", "genFunction "););
2531 /* create the function header */
2532 emitcode (";", "-----------------------------------------");
2533 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2534 emitcode (";", "-----------------------------------------");
2536 emitcode ("", "%s:", sym->rname);
2537 fetype = getSpec (operandType (IC_LEFT (ic)));
2539 /* if critical function then turn interrupts off */
2540 if (SPEC_CRTCL (fetype))
2541 emitcode ("clr", "ea");
2543 /* here we need to generate the equates for the
2544 register bank if required */
2545 if (SPEC_BANK (fetype) != rbank)
2549 rbank = SPEC_BANK (fetype);
2550 for (i = 0; i < ds390_nRegs; i++)
2552 if (strcmp (regs390[i].base, "0") == 0)
2553 emitcode ("", "%s = 0x%02x",
2555 8 * rbank + regs390[i].offset);
2557 emitcode ("", "%s = %s + 0x%02x",
2560 8 * rbank + regs390[i].offset);
2564 /* if this is an interrupt service routine then
2565 save acc, b, dpl, dph */
2566 if (IS_ISR (sym->etype))
2569 if (!inExcludeList ("acc"))
2570 emitcode ("push", "acc");
2571 if (!inExcludeList ("b"))
2572 emitcode ("push", "b");
2573 if (!inExcludeList ("dpl"))
2574 emitcode ("push", "dpl");
2575 if (!inExcludeList ("dph"))
2576 emitcode ("push", "dph");
2577 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2579 emitcode ("push", "dpx");
2580 /* Make sure we're using standard DPTR */
2581 emitcode ("push", "dps");
2582 emitcode ("mov", "dps, #0x00");
2583 if (options.stack10bit)
2585 /* This ISR could conceivably use DPTR2. Better save it. */
2586 emitcode ("push", "dpl1");
2587 emitcode ("push", "dph1");
2588 emitcode ("push", "dpx1");
2589 emitcode ("push", DP2_RESULT_REG);
2592 /* if this isr has no bank i.e. is going to
2593 run with bank 0 , then we need to save more
2595 if (!SPEC_BANK (sym->etype))
2598 /* if this function does not call any other
2599 function then we can be economical and
2600 save only those registers that are used */
2605 /* if any registers used */
2608 /* save the registers used */
2609 for (i = 0; i < sym->regsUsed->size; i++)
2611 if (bitVectBitValue (sym->regsUsed, i) ||
2612 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2613 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2620 /* this function has a function call cannot
2621 determines register usage so we will have to push the
2623 saveRBank (0, ic, FALSE);
2628 /* This ISR uses a non-zero bank.
2630 * We assume that the bank is available for our
2633 * However, if this ISR calls a function which uses some
2634 * other bank, we must save that bank entirely.
2636 unsigned long banksToSave = 0;
2641 #define MAX_REGISTER_BANKS 4
2646 for (i = ic; i; i = i->next)
2648 if (i->op == ENDFUNCTION)
2650 /* we got to the end OK. */
2658 detype = getSpec(operandType (IC_LEFT(i)));
2660 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2662 /* Mark this bank for saving. */
2663 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2665 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2669 banksToSave |= (1 << SPEC_BANK(detype));
2672 /* And note that we don't need to do it in
2680 /* This is a mess; we have no idea what
2681 * register bank the called function might
2684 * The only thing I can think of to do is
2685 * throw a warning and hope.
2687 werror(W_FUNCPTR_IN_USING_ISR);
2691 if (banksToSave && options.useXstack)
2693 /* Since we aren't passing it an ic,
2694 * saveRBank will assume r0 is available to abuse.
2696 * So switch to our (trashable) bank now, so
2697 * the caller's R0 isn't trashed.
2699 emitcode ("push", "psw");
2700 emitcode ("mov", "psw,#0x%02x",
2701 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2705 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2707 if (banksToSave & (1 << ix))
2709 saveRBank(ix, NULL, FALSE);
2713 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2718 /* if callee-save to be used for this function
2719 then save the registers being used in this function */
2720 if (sym->calleeSave)
2724 /* if any registers used */
2727 /* save the registers used */
2728 for (i = 0; i < sym->regsUsed->size; i++)
2730 if (bitVectBitValue (sym->regsUsed, i) ||
2731 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2733 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2741 /* set the register bank to the desired value */
2742 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2745 emitcode ("push", "psw");
2746 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2749 if (IS_RENT (sym->etype) || options.stackAuto)
2752 if (options.useXstack)
2754 emitcode ("mov", "r0,%s", spname);
2755 emitcode ("mov", "a,_bp");
2756 emitcode ("movx", "@r0,a");
2757 emitcode ("inc", "%s", spname);
2761 /* set up the stack */
2762 emitcode ("push", "_bp"); /* save the callers stack */
2764 emitcode ("mov", "_bp,%s", spname);
2767 /* adjust the stack for the function */
2773 werror (W_STACK_OVERFLOW, sym->name);
2775 if (i > 3 && sym->recvSize < 4)
2778 emitcode ("mov", "a,sp");
2779 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2780 emitcode ("mov", "sp,a");
2785 emitcode ("inc", "sp");
2791 emitcode ("mov", "a,_spx");
2792 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2793 emitcode ("mov", "_spx,a");
2798 /*-----------------------------------------------------------------*/
2799 /* genEndFunction - generates epilogue for functions */
2800 /*-----------------------------------------------------------------*/
2802 genEndFunction (iCode * ic)
2804 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2806 D (emitcode (";", "genEndFunction "););
2808 if (IS_RENT (sym->etype) || options.stackAuto)
2810 emitcode ("mov", "%s,_bp", spname);
2813 /* if use external stack but some variables were
2814 added to the local stack then decrement the
2816 if (options.useXstack && sym->stack)
2818 emitcode ("mov", "a,sp");
2819 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2820 emitcode ("mov", "sp,a");
2824 if ((IS_RENT (sym->etype) || options.stackAuto))
2826 if (options.useXstack)
2828 emitcode ("mov", "r0,%s", spname);
2829 emitcode ("movx", "a,@r0");
2830 emitcode ("mov", "_bp,a");
2831 emitcode ("dec", "%s", spname);
2835 emitcode ("pop", "_bp");
2839 /* restore the register bank */
2840 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2842 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2843 || !options.useXstack)
2845 /* Special case of ISR using non-zero bank with useXstack
2848 emitcode ("pop", "psw");
2852 if (IS_ISR (sym->etype))
2855 /* now we need to restore the registers */
2856 /* if this isr has no bank i.e. is going to
2857 run with bank 0 , then we need to save more
2859 if (!SPEC_BANK (sym->etype))
2861 /* if this function does not call any other
2862 function then we can be economical and
2863 save only those registers that are used */
2868 /* if any registers used */
2871 /* save the registers used */
2872 for (i = sym->regsUsed->size; i >= 0; i--)
2874 if (bitVectBitValue (sym->regsUsed, i) ||
2875 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2876 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2883 /* this function has a function call cannot
2884 determines register usage so we will have to pop the
2886 unsaveRBank (0, ic, FALSE);
2891 /* This ISR uses a non-zero bank.
2893 * Restore any register banks saved by genFunction
2896 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2899 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2901 if (savedBanks & (1 << ix))
2903 unsaveRBank(ix, NULL, FALSE);
2907 if (options.useXstack)
2909 /* Restore bank AFTER calling unsaveRBank,
2910 * since it can trash r0.
2912 emitcode ("pop", "psw");
2916 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2918 if (options.stack10bit)
2920 emitcode ("pop", DP2_RESULT_REG);
2921 emitcode ("pop", "dpx1");
2922 emitcode ("pop", "dph1");
2923 emitcode ("pop", "dpl1");
2925 emitcode ("pop", "dps");
2926 emitcode ("pop", "dpx");
2928 if (!inExcludeList ("dph"))
2929 emitcode ("pop", "dph");
2930 if (!inExcludeList ("dpl"))
2931 emitcode ("pop", "dpl");
2932 if (!inExcludeList ("b"))
2933 emitcode ("pop", "b");
2934 if (!inExcludeList ("acc"))
2935 emitcode ("pop", "acc");
2937 if (SPEC_CRTCL (sym->etype))
2938 emitcode ("setb", "ea");
2940 /* if debug then send end of function */
2941 /* if (options.debug && currFunc) { */
2945 emitcode ("", "C$%s$%d$%d$%d ==.",
2946 FileBaseName (ic->filename), currFunc->lastLine,
2947 ic->level, ic->block);
2948 if (IS_STATIC (currFunc->etype))
2949 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2951 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2955 emitcode ("reti", "");
2959 if (SPEC_CRTCL (sym->etype))
2960 emitcode ("setb", "ea");
2962 if (sym->calleeSave)
2966 /* if any registers used */
2969 /* save the registers used */
2970 for (i = sym->regsUsed->size; i >= 0; i--)
2972 if (bitVectBitValue (sym->regsUsed, i) ||
2973 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2974 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2980 /* if debug then send end of function */
2984 emitcode ("", "C$%s$%d$%d$%d ==.",
2985 FileBaseName (ic->filename), currFunc->lastLine,
2986 ic->level, ic->block);
2987 if (IS_STATIC (currFunc->etype))
2988 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2990 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2994 emitcode ("ret", "");
2999 /*-----------------------------------------------------------------*/
3000 /* genRet - generate code for return statement */
3001 /*-----------------------------------------------------------------*/
3005 int size, offset = 0, pushed = 0;
3007 D (emitcode (";", "genRet ");
3010 /* if we have no return value then
3011 just generate the "ret" */
3015 /* we have something to return then
3016 move the return value into place */
3017 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3018 size = AOP_SIZE (IC_LEFT (ic));
3020 _startLazyDPSEvaluation ();
3024 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3026 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3027 FALSE, TRUE, FALSE);
3028 emitcode ("push", "%s", l);
3033 /* Since A is the last element of fReturn,
3034 * is is OK to clobber it in the aopGet.
3036 l = aopGet (AOP (IC_LEFT (ic)), offset,
3037 FALSE, FALSE, TRUE);
3038 if (strcmp (fReturn[offset], l))
3039 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3042 _endLazyDPSEvaluation ();
3049 if (strcmp (fReturn[pushed], "a"))
3050 emitcode ("pop", fReturn[pushed]);
3052 emitcode ("pop", "acc");
3055 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3058 /* generate a jump to the return label
3059 if the next is not the return statement */
3060 if (!(ic->next && ic->next->op == LABEL &&
3061 IC_LABEL (ic->next) == returnLabel))
3063 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3067 /*-----------------------------------------------------------------*/
3068 /* genLabel - generates a label */
3069 /*-----------------------------------------------------------------*/
3071 genLabel (iCode * ic)
3073 /* special case never generate */
3074 if (IC_LABEL (ic) == entryLabel)
3077 D (emitcode (";", "genLabel ");
3080 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3083 /*-----------------------------------------------------------------*/
3084 /* genGoto - generates a ljmp */
3085 /*-----------------------------------------------------------------*/
3087 genGoto (iCode * ic)
3089 D (emitcode (";", "genGoto ");
3091 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3094 /*-----------------------------------------------------------------*/
3095 /* findLabelBackwards: walks back through the iCode chain looking */
3096 /* for the given label. Returns number of iCode instructions */
3097 /* between that label and given ic. */
3098 /* Returns zero if label not found. */
3099 /*-----------------------------------------------------------------*/
3101 findLabelBackwards (iCode * ic, int key)
3110 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3112 /* printf("findLabelBackwards = %d\n", count); */
3120 /*-----------------------------------------------------------------*/
3121 /* genPlusIncr :- does addition with increment if possible */
3122 /*-----------------------------------------------------------------*/
3124 genPlusIncr (iCode * ic)
3126 unsigned int icount;
3127 unsigned int size = getDataSize (IC_RESULT (ic));
3129 /* will try to generate an increment */
3130 /* if the right side is not a literal
3132 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3135 /* if the literal value of the right hand side
3136 is greater than 4 then it is not worth it */
3137 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3140 /* if increment 16 bits in register */
3142 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3143 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3144 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3152 /* If the next instruction is a goto and the goto target
3153 * is <= 5 instructions previous to this, we can generate
3154 * jumps straight to that target.
3156 if (ic->next && ic->next->op == GOTO
3157 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3160 emitcode (";", "tail increment optimized (range %d)", labelRange);
3161 tlbl = IC_LABEL (ic->next);
3166 tlbl = newiTempLabel (NULL);
3169 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3170 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3171 IS_AOP_PREG (IC_RESULT (ic)))
3172 emitcode ("cjne", "%s,#0x00,%05d$"
3173 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3177 emitcode ("clr", "a");
3178 emitcode ("cjne", "a,%s,%05d$"
3179 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3183 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3186 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3187 IS_AOP_PREG (IC_RESULT (ic)))
3188 emitcode ("cjne", "%s,#0x00,%05d$"
3189 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3192 emitcode ("cjne", "a,%s,%05d$"
3193 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3196 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3200 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3201 IS_AOP_PREG (IC_RESULT (ic)))
3202 emitcode ("cjne", "%s,#0x00,%05d$"
3203 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3207 emitcode ("cjne", "a,%s,%05d$"
3208 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3211 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3216 emitcode ("", "%05d$:", tlbl->key + 100);
3221 /* if the sizes are greater than 1 then we cannot */
3222 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3223 AOP_SIZE (IC_LEFT (ic)) > 1)
3226 /* we can if the aops of the left & result match or
3227 if they are in registers and the registers are the
3230 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3231 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3232 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3237 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3238 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3239 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3244 _startLazyDPSEvaluation ();
3247 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3249 _endLazyDPSEvaluation ();
3258 /*-----------------------------------------------------------------*/
3259 /* outBitAcc - output a bit in acc */
3260 /*-----------------------------------------------------------------*/
3262 outBitAcc (operand * result)
3264 symbol *tlbl = newiTempLabel (NULL);
3265 /* if the result is a bit */
3266 if (AOP_TYPE (result) == AOP_CRY)
3268 aopPut (AOP (result), "a", 0);
3272 emitcode ("jz", "%05d$", tlbl->key + 100);
3273 emitcode ("mov", "a,%s", one);
3274 emitcode ("", "%05d$:", tlbl->key + 100);
3279 /*-----------------------------------------------------------------*/
3280 /* genPlusBits - generates code for addition of two bits */
3281 /*-----------------------------------------------------------------*/
3283 genPlusBits (iCode * ic)
3285 D (emitcode (";", "genPlusBits ");
3287 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3289 symbol *lbl = newiTempLabel (NULL);
3290 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3291 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3292 emitcode ("cpl", "c");
3293 emitcode ("", "%05d$:", (lbl->key + 100));
3294 outBitC (IC_RESULT (ic));
3298 emitcode ("clr", "a");
3299 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3300 emitcode ("rlc", "a");
3301 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3302 emitcode ("addc", "a,#0x00");
3303 outAcc (IC_RESULT (ic));
3308 adjustArithmeticResult (iCode * ic)
3310 if (opIsGptr (IC_RESULT (ic)) &&
3311 opIsGptr (IC_LEFT (ic)) &&
3312 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3314 aopPut (AOP (IC_RESULT (ic)),
3315 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3319 if (opIsGptr (IC_RESULT (ic)) &&
3320 opIsGptr (IC_RIGHT (ic)) &&
3321 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3323 aopPut (AOP (IC_RESULT (ic)),
3324 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3328 if (opIsGptr (IC_RESULT (ic)) &&
3329 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3330 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3331 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3332 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3335 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3336 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3340 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3341 // (because all three operands are in far space).
3342 #define AOP_OP_3(ic) \
3343 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3344 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3345 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3346 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3347 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3348 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3350 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3352 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3355 // Macro to aopOp all three operands of an ic. If this cannot be done,
3356 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3357 // will be set TRUE. The caller must then handle the case specially, noting
3358 // that the IC_RESULT operand is not aopOp'd.
3359 #define AOP_OP_3_NOFATAL(ic, rc) \
3360 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3361 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3362 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3363 isOperandInFarSpace(IC_RESULT(ic))) \
3365 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3370 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3371 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3373 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3374 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3376 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3378 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3382 // aopOp the left & right operands of an ic.
3383 #define AOP_OP_2(ic) \
3384 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3385 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3387 // convienience macro.
3388 #define AOP_SET_LOCALS(ic) \
3389 left = IC_LEFT(ic); \
3390 right = IC_RIGHT(ic); \
3391 result = IC_RESULT(ic);
3394 // Given an integer value of pushedSize bytes on the stack,
3395 // adjust it to be resultSize bytes, either by discarding
3396 // the most significant bytes or by zero-padding.
3398 // On exit from this macro, pushedSize will have been adjusted to
3399 // equal resultSize, and ACC may be trashed.
3400 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3401 /* If the pushed data is bigger than the result, \
3402 * simply discard unused bytes. Icky, but works. \
3404 while (pushedSize > resultSize) \
3406 D (emitcode (";", "discarding unused result byte."););\
3407 emitcode ("pop", "acc"); \
3410 if (pushedSize < resultSize) \
3412 emitcode ("clr", "a"); \
3413 /* Conversly, we haven't pushed enough here. \
3414 * just zero-pad, and all is well. \
3416 while (pushedSize < resultSize) \
3418 emitcode("push", "acc"); \
3422 assert(pushedSize == resultSize);
3424 /*-----------------------------------------------------------------*/
3425 /* genPlus - generates code for addition */
3426 /*-----------------------------------------------------------------*/
3428 genPlus (iCode * ic)
3430 int size, offset = 0;
3431 bool pushResult = FALSE;
3434 D (emitcode (";", "genPlus "););
3436 /* special cases :- */
3438 AOP_OP_3_NOFATAL (ic, pushResult);
3441 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3446 /* if literal, literal on the right or
3447 if left requires ACC or right is already
3449 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3450 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3451 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3453 operand *t = IC_RIGHT (ic);
3454 IC_RIGHT (ic) = IC_LEFT (ic);
3456 emitcode (";", "Swapped plus args.");
3459 /* if both left & right are in bit
3461 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3462 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3468 /* if left in bit space & right literal */
3469 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3470 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3472 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3473 /* if result in bit space */
3474 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3476 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3477 emitcode ("cpl", "c");
3478 outBitC (IC_RESULT (ic));
3482 size = getDataSize (IC_RESULT (ic));
3483 _startLazyDPSEvaluation ();
3486 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3487 emitcode ("addc", "a,#00");
3488 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3490 _endLazyDPSEvaluation ();
3495 /* if I can do an increment instead
3496 of add then GOOD for ME */
3497 if (genPlusIncr (ic) == TRUE)
3499 emitcode (";", "did genPlusIncr");
3504 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3506 _startLazyDPSEvaluation ();
3509 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3511 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3513 emitcode ("add", "a,%s",
3514 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3516 emitcode ("addc", "a,%s",
3517 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3521 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3523 /* right is going to use ACC or we would have taken the
3526 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3527 D(emitcode(";", "+ AOP_ACC special case."););
3528 emitcode("xch", "a, %s", DP2_RESULT_REG);
3530 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3533 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3535 emitcode("add", "a, %s", DP2_RESULT_REG);
3539 emitcode ("add", "a,%s",
3540 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3545 emitcode ("addc", "a,%s",
3546 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3551 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3555 emitcode ("push", "acc");
3559 _endLazyDPSEvaluation ();
3563 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3565 size = getDataSize (IC_LEFT (ic));
3566 rSize = getDataSize (IC_RESULT (ic));
3568 ADJUST_PUSHED_RESULT(size, rSize);
3570 _startLazyDPSEvaluation ();
3573 emitcode ("pop", "acc");
3574 aopPut (AOP (IC_RESULT (ic)), "a", size);
3576 _endLazyDPSEvaluation ();
3579 adjustArithmeticResult (ic);
3582 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3583 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3584 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3587 /*-----------------------------------------------------------------*/
3588 /* genMinusDec :- does subtraction with deccrement if possible */
3589 /*-----------------------------------------------------------------*/
3591 genMinusDec (iCode * ic)
3593 unsigned int icount;
3594 unsigned int size = getDataSize (IC_RESULT (ic));
3596 /* will try to generate an increment */
3597 /* if the right side is not a literal
3599 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3602 /* if the literal value of the right hand side
3603 is greater than 4 then it is not worth it */
3604 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3607 /* if decrement 16 bits in register */
3608 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3609 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3610 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3618 /* If the next instruction is a goto and the goto target
3619 * is <= 5 instructions previous to this, we can generate
3620 * jumps straight to that target.
3622 if (ic->next && ic->next->op == GOTO
3623 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3626 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3627 tlbl = IC_LABEL (ic->next);
3632 tlbl = newiTempLabel (NULL);
3636 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3637 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3638 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3639 IS_AOP_PREG (IC_RESULT (ic)))
3640 emitcode ("cjne", "%s,#0xff,%05d$"
3641 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3645 emitcode ("mov", "a,#0xff");
3646 emitcode ("cjne", "a,%s,%05d$"
3647 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3650 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3653 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3654 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3655 IS_AOP_PREG (IC_RESULT (ic)))
3656 emitcode ("cjne", "%s,#0xff,%05d$"
3657 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3661 emitcode ("cjne", "a,%s,%05d$"
3662 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3665 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3669 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3670 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3671 IS_AOP_PREG (IC_RESULT (ic)))
3672 emitcode ("cjne", "%s,#0xff,%05d$"
3673 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3677 emitcode ("cjne", "a,%s,%05d$"
3678 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3681 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3685 emitcode ("", "%05d$:", tlbl->key + 100);
3690 /* if the sizes are greater than 1 then we cannot */
3691 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3692 AOP_SIZE (IC_LEFT (ic)) > 1)
3695 /* we can if the aops of the left & result match or
3696 if they are in registers and the registers are the
3699 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3700 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3701 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3704 _startLazyDPSEvaluation ();
3707 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3709 _endLazyDPSEvaluation ();
3717 /*-----------------------------------------------------------------*/
3718 /* addSign - complete with sign */
3719 /*-----------------------------------------------------------------*/
3721 addSign (operand * result, int offset, int sign)
3723 int size = (getDataSize (result) - offset);
3726 _startLazyDPSEvaluation();
3729 emitcode ("rlc", "a");
3730 emitcode ("subb", "a,acc");
3733 aopPut (AOP (result), "a", offset++);
3740 aopPut (AOP (result), zero, offset++);
3743 _endLazyDPSEvaluation();
3747 /*-----------------------------------------------------------------*/
3748 /* genMinusBits - generates code for subtraction of two bits */
3749 /*-----------------------------------------------------------------*/
3751 genMinusBits (iCode * ic)
3753 symbol *lbl = newiTempLabel (NULL);
3755 D (emitcode (";", "genMinusBits "););
3757 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3759 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3760 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3761 emitcode ("cpl", "c");
3762 emitcode ("", "%05d$:", (lbl->key + 100));
3763 outBitC (IC_RESULT (ic));
3767 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3768 emitcode ("subb", "a,acc");
3769 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3770 emitcode ("inc", "a");
3771 emitcode ("", "%05d$:", (lbl->key + 100));
3772 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3773 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3777 /*-----------------------------------------------------------------*/
3778 /* genMinus - generates code for subtraction */
3779 /*-----------------------------------------------------------------*/
3781 genMinus (iCode * ic)
3783 int size, offset = 0;
3785 unsigned long lit = 0L;
3786 bool pushResult = FALSE;
3788 D (emitcode (";", "genMinus "););
3790 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3791 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3792 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3793 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3799 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3801 /* special cases :- */
3802 /* if both left & right are in bit space */
3803 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3804 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3810 /* if I can do an decrement instead
3811 of subtract then GOOD for ME */
3812 if (genMinusDec (ic) == TRUE)
3817 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3819 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3825 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3830 /* if literal, add a,#-lit, else normal subb */
3831 _startLazyDPSEvaluation ();
3834 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3835 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3836 emitcode ("subb", "a,%s",
3837 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3840 /* first add without previous c */
3842 emitcode ("add", "a,#0x%02x",
3843 (unsigned int) (lit & 0x0FFL));
3845 emitcode ("addc", "a,#0x%02x",
3846 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3851 emitcode ("push", "acc");
3855 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3859 _endLazyDPSEvaluation ();
3863 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3865 size = getDataSize (IC_LEFT (ic));
3866 rSize = getDataSize (IC_RESULT (ic));
3868 ADJUST_PUSHED_RESULT(size, rSize);
3870 _startLazyDPSEvaluation ();
3873 emitcode ("pop", "acc");
3874 aopPut (AOP (IC_RESULT (ic)), "a", size);
3876 _endLazyDPSEvaluation ();
3879 adjustArithmeticResult (ic);
3882 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3883 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3884 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3888 /*-----------------------------------------------------------------*/
3889 /* genMultbits :- multiplication of bits */
3890 /*-----------------------------------------------------------------*/
3892 genMultbits (operand * left,
3896 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3897 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3902 /*-----------------------------------------------------------------*/
3903 /* genMultOneByte : 8*8=8/16 bit multiplication */
3904 /*-----------------------------------------------------------------*/
3906 genMultOneByte (operand * left,
3910 sym_link *opetype = operandType (result);
3912 int size=AOP_SIZE(result);
3914 if (size<1 || size>2) {
3915 // this should never happen
3916 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3917 AOP_SIZE(result), __FILE__, lineno);
3921 /* (if two literals: the value is computed before) */
3922 /* if one literal, literal on the right */
3923 if (AOP_TYPE (left) == AOP_LIT)
3928 emitcode (";", "swapped left and right");
3931 if (SPEC_USIGN(opetype)
3932 // ignore the sign of left and right, what else can we do?
3933 || (SPEC_USIGN(operandType(left)) &&
3934 SPEC_USIGN(operandType(right)))) {
3935 // just an unsigned 8*8=8/16 multiply
3936 //emitcode (";","unsigned");
3937 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3938 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3939 emitcode ("mul", "ab");
3940 aopPut (AOP (result), "a", 0);
3942 aopPut (AOP (result), "b", 1);
3947 // we have to do a signed multiply
3949 emitcode (";", "signed");
3950 emitcode ("clr", "F0"); // reset sign flag
3951 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3952 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3954 lbl=newiTempLabel(NULL);
3955 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3956 // left side is negative, 8-bit two's complement, this fails for -128
3957 emitcode ("setb", "F0"); // set sign flag
3958 emitcode ("cpl", "a");
3959 emitcode ("inc", "a");
3961 emitcode ("", "%05d$:", lbl->key+100);
3962 emitcode ("xch", "a,b");
3965 if (AOP_TYPE(right)==AOP_LIT) {
3966 /* AND literal negative */
3967 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3968 // two's complement for literal<0
3969 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3970 emitcode ("cpl", "a");
3971 emitcode ("inc", "a");
3974 lbl=newiTempLabel(NULL);
3975 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3976 // right side is negative, 8-bit two's complement
3977 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3978 emitcode ("cpl", "a");
3979 emitcode ("inc", "a");
3980 emitcode ("", "%05d$:", lbl->key+100);
3982 emitcode ("mul", "ab");
3984 lbl=newiTempLabel(NULL);
3985 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3986 // only ONE op was negative, we have to do a 8/16-bit two's complement
3987 emitcode ("cpl", "a"); // lsb
3989 emitcode ("inc", "a");
3991 emitcode ("add", "a,#1");
3992 emitcode ("xch", "a,b");
3993 emitcode ("cpl", "a"); // msb
3994 emitcode ("addc", "a,#0");
3995 emitcode ("xch", "a,b");
3998 emitcode ("", "%05d$:", lbl->key+100);
3999 aopPut (AOP (result), "a", 0);
4001 aopPut (AOP (result), "b", 1);
4005 /*-----------------------------------------------------------------*/
4006 /* genMult - generates code for multiplication */
4007 /*-----------------------------------------------------------------*/
4009 genMult (iCode * ic)
4011 operand *left = IC_LEFT (ic);
4012 operand *right = IC_RIGHT (ic);
4013 operand *result = IC_RESULT (ic);
4015 D (emitcode (";", "genMult "););
4017 /* assign the amsops */
4020 /* special cases first */
4022 if (AOP_TYPE (left) == AOP_CRY &&
4023 AOP_TYPE (right) == AOP_CRY)
4025 genMultbits (left, right, result);
4029 /* if both are of size == 1 */
4030 if (AOP_SIZE (left) == 1 &&
4031 AOP_SIZE (right) == 1)
4033 genMultOneByte (left, right, result);
4037 /* should have been converted to function call */
4041 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4042 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4043 freeAsmop (result, NULL, ic, TRUE);
4046 /*-----------------------------------------------------------------*/
4047 /* genDivbits :- division of bits */
4048 /*-----------------------------------------------------------------*/
4050 genDivbits (operand * left,
4057 /* the result must be bit */
4058 LOAD_AB_FOR_DIV (left, right, l);
4059 emitcode ("div", "ab");
4060 emitcode ("rrc", "a");
4061 aopPut (AOP (result), "c", 0);
4064 /*-----------------------------------------------------------------*/
4065 /* genDivOneByte : 8 bit division */
4066 /*-----------------------------------------------------------------*/
4068 genDivOneByte (operand * left,
4072 sym_link *opetype = operandType (result);
4077 size = AOP_SIZE (result) - 1;
4079 /* signed or unsigned */
4080 if (SPEC_USIGN (opetype))
4082 /* unsigned is easy */
4083 LOAD_AB_FOR_DIV (left, right, l);
4084 emitcode ("div", "ab");
4085 aopPut (AOP (result), "a", 0);
4087 aopPut (AOP (result), zero, offset++);
4091 /* signed is a little bit more difficult */
4093 /* save the signs of the operands */
4094 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4096 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4097 emitcode ("push", "acc"); /* save it on the stack */
4099 /* now sign adjust for both left & right */
4100 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4102 lbl = newiTempLabel (NULL);
4103 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4104 emitcode ("cpl", "a");
4105 emitcode ("inc", "a");
4106 emitcode ("", "%05d$:", (lbl->key + 100));
4107 emitcode ("mov", "b,a");
4109 /* sign adjust left side */
4110 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4113 lbl = newiTempLabel (NULL);
4114 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4115 emitcode ("cpl", "a");
4116 emitcode ("inc", "a");
4117 emitcode ("", "%05d$:", (lbl->key + 100));
4119 /* now the division */
4120 emitcode ("nop", "; workaround for DS80C390 div bug.");
4121 emitcode ("div", "ab");
4122 /* we are interested in the lower order
4124 emitcode ("mov", "b,a");
4125 lbl = newiTempLabel (NULL);
4126 emitcode ("pop", "acc");
4127 /* if there was an over flow we don't
4128 adjust the sign of the result */
4129 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4130 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4132 emitcode ("clr", "a");
4133 emitcode ("subb", "a,b");
4134 emitcode ("mov", "b,a");
4135 emitcode ("", "%05d$:", (lbl->key + 100));
4137 /* now we are done */
4138 aopPut (AOP (result), "b", 0);
4141 emitcode ("mov", "c,b.7");
4142 emitcode ("subb", "a,acc");
4145 aopPut (AOP (result), "a", offset++);
4149 /*-----------------------------------------------------------------*/
4150 /* genDiv - generates code for division */
4151 /*-----------------------------------------------------------------*/
4155 operand *left = IC_LEFT (ic);
4156 operand *right = IC_RIGHT (ic);
4157 operand *result = IC_RESULT (ic);
4159 D (emitcode (";", "genDiv ");
4162 /* assign the amsops */
4165 /* special cases first */
4167 if (AOP_TYPE (left) == AOP_CRY &&
4168 AOP_TYPE (right) == AOP_CRY)
4170 genDivbits (left, right, result);
4174 /* if both are of size == 1 */
4175 if (AOP_SIZE (left) == 1 &&
4176 AOP_SIZE (right) == 1)
4178 genDivOneByte (left, right, result);
4182 /* should have been converted to function call */
4185 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4186 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4187 freeAsmop (result, NULL, ic, TRUE);
4190 /*-----------------------------------------------------------------*/
4191 /* genModbits :- modulus of bits */
4192 /*-----------------------------------------------------------------*/
4194 genModbits (operand * left,
4201 /* the result must be bit */
4202 LOAD_AB_FOR_DIV (left, right, l);
4203 emitcode ("div", "ab");
4204 emitcode ("mov", "a,b");
4205 emitcode ("rrc", "a");
4206 aopPut (AOP (result), "c", 0);
4209 /*-----------------------------------------------------------------*/
4210 /* genModOneByte : 8 bit modulus */
4211 /*-----------------------------------------------------------------*/
4213 genModOneByte (operand * left,
4217 sym_link *opetype = operandType (result);
4221 /* signed or unsigned */
4222 if (SPEC_USIGN (opetype))
4224 /* unsigned is easy */
4225 LOAD_AB_FOR_DIV (left, right, l);
4226 emitcode ("div", "ab");
4227 aopPut (AOP (result), "b", 0);
4231 /* signed is a little bit more difficult */
4233 /* save the signs of the operands */
4234 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4237 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4238 emitcode ("push", "acc"); /* save it on the stack */
4240 /* now sign adjust for both left & right */
4241 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4244 lbl = newiTempLabel (NULL);
4245 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4246 emitcode ("cpl", "a");
4247 emitcode ("inc", "a");
4248 emitcode ("", "%05d$:", (lbl->key + 100));
4249 emitcode ("mov", "b,a");
4251 /* sign adjust left side */
4252 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4255 lbl = newiTempLabel (NULL);
4256 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4257 emitcode ("cpl", "a");
4258 emitcode ("inc", "a");
4259 emitcode ("", "%05d$:", (lbl->key + 100));
4261 /* now the multiplication */
4262 emitcode ("nop", "; workaround for DS80C390 div bug.");
4263 emitcode ("div", "ab");
4264 /* we are interested in the lower order
4266 lbl = newiTempLabel (NULL);
4267 emitcode ("pop", "acc");
4268 /* if there was an over flow we don't
4269 adjust the sign of the result */
4270 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4271 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4273 emitcode ("clr", "a");
4274 emitcode ("subb", "a,b");
4275 emitcode ("mov", "b,a");
4276 emitcode ("", "%05d$:", (lbl->key + 100));
4278 /* now we are done */
4279 aopPut (AOP (result), "b", 0);
4283 /*-----------------------------------------------------------------*/
4284 /* genMod - generates code for division */
4285 /*-----------------------------------------------------------------*/
4289 operand *left = IC_LEFT (ic);
4290 operand *right = IC_RIGHT (ic);
4291 operand *result = IC_RESULT (ic);
4293 D (emitcode (";", "genMod ");
4296 /* assign the amsops */
4299 /* special cases first */
4301 if (AOP_TYPE (left) == AOP_CRY &&
4302 AOP_TYPE (right) == AOP_CRY)
4304 genModbits (left, right, result);
4308 /* if both are of size == 1 */
4309 if (AOP_SIZE (left) == 1 &&
4310 AOP_SIZE (right) == 1)
4312 genModOneByte (left, right, result);
4316 /* should have been converted to function call */
4320 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4321 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4322 freeAsmop (result, NULL, ic, TRUE);
4325 /*-----------------------------------------------------------------*/
4326 /* genIfxJump :- will create a jump depending on the ifx */
4327 /*-----------------------------------------------------------------*/
4329 genIfxJump (iCode * ic, char *jval)
4332 symbol *tlbl = newiTempLabel (NULL);
4335 D (emitcode (";", "genIfxJump ");
4338 /* if true label then we jump if condition
4342 jlbl = IC_TRUE (ic);
4343 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4344 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4348 /* false label is present */
4349 jlbl = IC_FALSE (ic);
4350 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4351 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4353 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4354 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4356 emitcode (inst, "%05d$", tlbl->key + 100);
4357 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4358 emitcode ("", "%05d$:", tlbl->key + 100);
4360 /* mark the icode as generated */
4364 /*-----------------------------------------------------------------*/
4365 /* genCmp :- greater or less than comparison */
4366 /*-----------------------------------------------------------------*/
4368 genCmp (operand * left, operand * right,
4369 iCode * ic, iCode * ifx, int sign)
4371 int size, offset = 0;
4372 unsigned long lit = 0L;
4375 D (emitcode (";", "genCmp");
4378 result = IC_RESULT (ic);
4380 /* if left & right are bit variables */
4381 if (AOP_TYPE (left) == AOP_CRY &&
4382 AOP_TYPE (right) == AOP_CRY)
4384 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4385 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4389 /* subtract right from left if at the
4390 end the carry flag is set then we know that
4391 left is greater than right */
4392 size = max (AOP_SIZE (left), AOP_SIZE (right));
4394 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4395 if ((size == 1) && !sign &&
4396 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4398 symbol *lbl = newiTempLabel (NULL);
4399 emitcode ("cjne", "%s,%s,%05d$",
4400 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4401 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4403 emitcode ("", "%05d$:", lbl->key + 100);
4407 if (AOP_TYPE (right) == AOP_LIT)
4409 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4410 /* optimize if(x < 0) or if(x >= 0) */
4419 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4424 aopOp (result, ic, FALSE, FALSE);
4426 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4428 freeAsmop (result, NULL, ic, TRUE);
4429 genIfxJump (ifx, "acc.7");
4434 emitcode ("rlc", "a");
4436 goto release_freedLR;
4444 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4445 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4446 emitcode (";", "genCmp #2");
4447 if (sign && (size == 0))
4449 emitcode (";", "genCmp #3");
4450 emitcode ("xrl", "a,#0x80");
4451 if (AOP_TYPE (right) == AOP_LIT)
4453 unsigned long lit = (unsigned long)
4454 floatFromVal (AOP (right)->aopu.aop_lit);
4455 emitcode (";", "genCmp #3.1");
4456 emitcode ("subb", "a,#0x%02x",
4457 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4461 emitcode (";", "genCmp #3.2");
4462 if (AOP_NEEDSACC (right))
4464 emitcode ("push", "acc");
4466 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4467 FALSE, FALSE, FALSE));
4468 emitcode ("xrl", "b,#0x80");
4469 if (AOP_NEEDSACC (right))
4471 emitcode ("pop", "acc");
4473 emitcode ("subb", "a,b");
4480 emitcode (";", "genCmp #4");
4481 if (AOP_NEEDSACC (right))
4484 emitcode (";", "genCmp #4.1");
4485 emitcode ("xch", "a, b");
4486 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4487 emitcode ("xch", "a, b");
4492 emitcode (";", "genCmp #4.2");
4493 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4496 emitcode ("subb", "a,%s", s);
4503 /* Don't need the left & right operands any more; do need the result. */
4504 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4505 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4507 aopOp (result, ic, FALSE, FALSE);
4511 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4517 /* if the result is used in the next
4518 ifx conditional branch then generate
4519 code a little differently */
4522 genIfxJump (ifx, "c");
4528 /* leave the result in acc */
4530 freeAsmop (result, NULL, ic, TRUE);
4533 /*-----------------------------------------------------------------*/
4534 /* genCmpGt :- greater than comparison */
4535 /*-----------------------------------------------------------------*/
4537 genCmpGt (iCode * ic, iCode * ifx)
4539 operand *left, *right;
4540 sym_link *letype, *retype;
4543 D (emitcode (";", "genCmpGt ");
4546 left = IC_LEFT (ic);
4547 right = IC_RIGHT (ic);
4549 letype = getSpec (operandType (left));
4550 retype = getSpec (operandType (right));
4551 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4553 /* assign the left & right amsops */
4556 genCmp (right, left, ic, ifx, sign);
4559 /*-----------------------------------------------------------------*/
4560 /* genCmpLt - less than comparisons */
4561 /*-----------------------------------------------------------------*/
4563 genCmpLt (iCode * ic, iCode * ifx)
4565 operand *left, *right;
4566 sym_link *letype, *retype;
4569 D (emitcode (";", "genCmpLt "););
4571 left = IC_LEFT (ic);
4572 right = IC_RIGHT (ic);
4574 letype = getSpec (operandType (left));
4575 retype = getSpec (operandType (right));
4576 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4578 /* assign the left & right amsops */
4581 genCmp (left, right, ic, ifx, sign);
4584 /*-----------------------------------------------------------------*/
4585 /* gencjneshort - compare and jump if not equal */
4586 /*-----------------------------------------------------------------*/
4588 gencjneshort (operand * left, operand * right, symbol * lbl)
4590 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4592 unsigned long lit = 0L;
4594 D (emitcode (";", "gencjneshort");
4597 /* if the left side is a literal or
4598 if the right is in a pointer register and left
4600 if ((AOP_TYPE (left) == AOP_LIT) ||
4601 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4608 if (AOP_TYPE (right) == AOP_LIT)
4609 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4611 if (opIsGptr (left) || opIsGptr (right))
4613 /* We are comparing a generic pointer to something.
4614 * Exclude the generic type byte from the comparison.
4617 D (emitcode (";", "cjneshort: generic ptr special case.");
4622 /* if the right side is a literal then anything goes */
4623 if (AOP_TYPE (right) == AOP_LIT &&
4624 AOP_TYPE (left) != AOP_DIR)
4628 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4630 emitcode ("cjne", "a,%s,%05d$",
4631 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4637 /* if the right side is in a register or in direct space or
4638 if the left is a pointer register & right is not */
4639 else if (AOP_TYPE (right) == AOP_REG ||
4640 AOP_TYPE (right) == AOP_DIR ||
4641 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4642 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4646 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4647 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4648 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4649 emitcode ("jnz", "%05d$", lbl->key + 100);
4651 emitcode ("cjne", "a,%s,%05d$",
4652 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4659 /* right is a pointer reg need both a & b */
4662 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4663 if (strcmp (l, "b"))
4664 emitcode ("mov", "b,%s", l);
4665 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4666 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4672 /*-----------------------------------------------------------------*/
4673 /* gencjne - compare and jump if not equal */
4674 /*-----------------------------------------------------------------*/
4676 gencjne (operand * left, operand * right, symbol * lbl)
4678 symbol *tlbl = newiTempLabel (NULL);
4680 D (emitcode (";", "gencjne");
4683 gencjneshort (left, right, lbl);
4685 emitcode ("mov", "a,%s", one);
4686 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4687 emitcode ("", "%05d$:", lbl->key + 100);
4688 emitcode ("clr", "a");
4689 emitcode ("", "%05d$:", tlbl->key + 100);
4692 /*-----------------------------------------------------------------*/
4693 /* genCmpEq - generates code for equal to */
4694 /*-----------------------------------------------------------------*/
4696 genCmpEq (iCode * ic, iCode * ifx)
4698 operand *left, *right, *result;
4700 D (emitcode (";", "genCmpEq ");
4704 AOP_SET_LOCALS (ic);
4706 /* if literal, literal on the right or
4707 if the right is in a pointer register and left
4709 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4710 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4712 operand *t = IC_RIGHT (ic);
4713 IC_RIGHT (ic) = IC_LEFT (ic);
4717 if (ifx && /* !AOP_SIZE(result) */
4718 OP_SYMBOL (result) &&
4719 OP_SYMBOL (result)->regType == REG_CND)
4722 /* if they are both bit variables */
4723 if (AOP_TYPE (left) == AOP_CRY &&
4724 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4726 if (AOP_TYPE (right) == AOP_LIT)
4728 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4731 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4732 emitcode ("cpl", "c");
4736 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4740 emitcode ("clr", "c");
4742 /* AOP_TYPE(right) == AOP_CRY */
4746 symbol *lbl = newiTempLabel (NULL);
4747 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4748 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4749 emitcode ("cpl", "c");
4750 emitcode ("", "%05d$:", (lbl->key + 100));
4752 /* if true label then we jump if condition
4754 tlbl = newiTempLabel (NULL);
4757 emitcode ("jnc", "%05d$", tlbl->key + 100);
4758 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4762 emitcode ("jc", "%05d$", tlbl->key + 100);
4763 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4765 emitcode ("", "%05d$:", tlbl->key + 100);
4769 tlbl = newiTempLabel (NULL);
4770 gencjneshort (left, right, tlbl);
4773 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4774 emitcode ("", "%05d$:", tlbl->key + 100);
4778 symbol *lbl = newiTempLabel (NULL);
4779 emitcode ("sjmp", "%05d$", lbl->key + 100);
4780 emitcode ("", "%05d$:", tlbl->key + 100);
4781 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4782 emitcode ("", "%05d$:", lbl->key + 100);
4785 /* mark the icode as generated */
4788 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4789 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4793 /* if they are both bit variables */
4794 if (AOP_TYPE (left) == AOP_CRY &&
4795 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4797 if (AOP_TYPE (right) == AOP_LIT)
4799 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4803 emitcode ("cpl", "c");
4807 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4811 emitcode ("clr", "c");
4813 /* AOP_TYPE(right) == AOP_CRY */
4817 symbol *lbl = newiTempLabel (NULL);
4818 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4819 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4820 emitcode ("cpl", "c");
4821 emitcode ("", "%05d$:", (lbl->key + 100));
4824 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4825 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4827 aopOp (result, ic, TRUE, FALSE);
4830 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4837 genIfxJump (ifx, "c");
4840 /* if the result is used in an arithmetic operation
4841 then put the result in place */
4846 gencjne (left, right, newiTempLabel (NULL));
4848 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4851 aopOp (result, ic, TRUE, FALSE);
4853 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4855 aopPut (AOP (result), "a", 0);
4860 genIfxJump (ifx, "a");
4863 /* if the result is used in an arithmetic operation
4864 then put the result in place */
4865 if (AOP_TYPE (result) != AOP_CRY)
4867 /* leave the result in acc */
4871 freeAsmop (result, NULL, ic, TRUE);
4874 /*-----------------------------------------------------------------*/
4875 /* ifxForOp - returns the icode containing the ifx for operand */
4876 /*-----------------------------------------------------------------*/
4878 ifxForOp (operand * op, iCode * ic)
4880 /* if true symbol then needs to be assigned */
4881 if (IS_TRUE_SYMOP (op))
4884 /* if this has register type condition and
4885 the next instruction is ifx with the same operand
4886 and live to of the operand is upto the ifx only then */
4888 ic->next->op == IFX &&
4889 IC_COND (ic->next)->key == op->key &&
4890 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4895 /*-----------------------------------------------------------------*/
4896 /* genAndOp - for && operation */
4897 /*-----------------------------------------------------------------*/
4899 genAndOp (iCode * ic)
4901 operand *left, *right, *result;
4904 D (emitcode (";", "genAndOp "););
4906 /* note here that && operations that are in an
4907 if statement are taken away by backPatchLabels
4908 only those used in arthmetic operations remain */
4910 AOP_SET_LOCALS (ic);
4912 /* if both are bit variables */
4913 if (AOP_TYPE (left) == AOP_CRY &&
4914 AOP_TYPE (right) == AOP_CRY)
4916 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4917 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4918 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4919 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4921 aopOp (result,ic,FALSE, FALSE);
4926 tlbl = newiTempLabel (NULL);
4928 emitcode ("jz", "%05d$", tlbl->key + 100);
4930 emitcode ("", "%05d$:", tlbl->key + 100);
4931 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4932 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4934 aopOp (result,ic,FALSE, FALSE);
4937 freeAsmop (result, NULL, ic, TRUE);
4941 /*-----------------------------------------------------------------*/
4942 /* genOrOp - for || operation */
4943 /*-----------------------------------------------------------------*/
4945 genOrOp (iCode * ic)
4947 operand *left, *right, *result;
4950 D (emitcode (";", "genOrOp "););
4952 /* note here that || operations that are in an
4953 if statement are taken away by backPatchLabels
4954 only those used in arthmetic operations remain */
4956 AOP_SET_LOCALS (ic);
4958 /* if both are bit variables */
4959 if (AOP_TYPE (left) == AOP_CRY &&
4960 AOP_TYPE (right) == AOP_CRY)
4962 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4963 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4964 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4965 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4967 aopOp (result,ic,FALSE, FALSE);
4973 tlbl = newiTempLabel (NULL);
4975 emitcode ("jnz", "%05d$", tlbl->key + 100);
4977 emitcode ("", "%05d$:", tlbl->key + 100);
4978 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4979 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4981 aopOp (result,ic,FALSE, FALSE);
4986 freeAsmop (result, NULL, ic, TRUE);
4989 /*-----------------------------------------------------------------*/
4990 /* isLiteralBit - test if lit == 2^n */
4991 /*-----------------------------------------------------------------*/
4993 isLiteralBit (unsigned long lit)
4995 unsigned long pw[32] =
4996 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4997 0x100L, 0x200L, 0x400L, 0x800L,
4998 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4999 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5000 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5001 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5002 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5005 for (idx = 0; idx < 32; idx++)
5011 /*-----------------------------------------------------------------*/
5012 /* continueIfTrue - */
5013 /*-----------------------------------------------------------------*/
5015 continueIfTrue (iCode * ic)
5018 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5022 /*-----------------------------------------------------------------*/
5024 /*-----------------------------------------------------------------*/
5026 jumpIfTrue (iCode * ic)
5029 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5033 /*-----------------------------------------------------------------*/
5034 /* jmpTrueOrFalse - */
5035 /*-----------------------------------------------------------------*/
5037 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5039 // ugly but optimized by peephole
5042 symbol *nlbl = newiTempLabel (NULL);
5043 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5044 emitcode ("", "%05d$:", tlbl->key + 100);
5045 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5046 emitcode ("", "%05d$:", nlbl->key + 100);
5050 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5051 emitcode ("", "%05d$:", tlbl->key + 100);
5056 // Generate code to perform a bit-wise logic operation
5057 // on two operands in far space (assumed to already have been
5058 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5059 // in far space. This requires pushing the result on the stack
5060 // then popping it into the result.
5062 genFarFarLogicOp(iCode *ic, char *logicOp)
5064 int size, resultSize, compSize;
5067 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5068 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5069 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5071 _startLazyDPSEvaluation();
5072 for (size = compSize; (size--); offset++)
5074 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5075 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5076 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5078 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5079 emitcode ("push", "acc");
5081 _endLazyDPSEvaluation();
5083 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5084 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5085 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5087 resultSize = AOP_SIZE(IC_RESULT(ic));
5089 ADJUST_PUSHED_RESULT(compSize, resultSize);
5091 _startLazyDPSEvaluation();
5094 emitcode ("pop", "acc");
5095 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5097 _endLazyDPSEvaluation();
5098 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5102 /*-----------------------------------------------------------------*/
5103 /* genAnd - code for and */
5104 /*-----------------------------------------------------------------*/
5106 genAnd (iCode * ic, iCode * ifx)
5108 operand *left, *right, *result;
5109 int size, offset = 0;
5110 unsigned long lit = 0L;
5115 D (emitcode (";", "genAnd "););
5117 AOP_OP_3_NOFATAL (ic, pushResult);
5118 AOP_SET_LOCALS (ic);
5122 genFarFarLogicOp(ic, "anl");
5127 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5129 AOP_TYPE (left), AOP_TYPE (right));
5130 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5132 AOP_SIZE (left), AOP_SIZE (right));
5135 /* if left is a literal & right is not then exchange them */
5136 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5137 AOP_NEEDSACC (left))
5139 operand *tmp = right;
5144 /* if result = right then exchange them */
5145 if (sameRegs (AOP (result), AOP (right)))
5147 operand *tmp = right;
5152 /* if right is bit then exchange them */
5153 if (AOP_TYPE (right) == AOP_CRY &&
5154 AOP_TYPE (left) != AOP_CRY)
5156 operand *tmp = right;
5160 if (AOP_TYPE (right) == AOP_LIT)
5161 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5163 size = AOP_SIZE (result);
5166 // result = bit & yy;
5167 if (AOP_TYPE (left) == AOP_CRY)
5169 // c = bit & literal;
5170 if (AOP_TYPE (right) == AOP_LIT)
5174 if (size && sameRegs (AOP (result), AOP (left)))
5177 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5182 if (size && (AOP_TYPE (result) == AOP_CRY))
5184 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5187 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5192 emitcode ("clr", "c");
5197 if (AOP_TYPE (right) == AOP_CRY)
5200 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5201 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5206 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5208 emitcode ("rrc", "a");
5209 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5217 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5218 genIfxJump (ifx, "c");
5222 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5223 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5224 if ((AOP_TYPE (right) == AOP_LIT) &&
5225 (AOP_TYPE (result) == AOP_CRY) &&
5226 (AOP_TYPE (left) != AOP_CRY))
5228 int posbit = isLiteralBit (lit);
5233 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5236 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5242 sprintf (buffer, "acc.%d", posbit & 0x07);
5243 genIfxJump (ifx, buffer);
5250 symbol *tlbl = newiTempLabel (NULL);
5251 int sizel = AOP_SIZE (left);
5253 emitcode ("setb", "c");
5256 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5258 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5260 if ((posbit = isLiteralBit (bytelit)) != 0)
5261 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5264 if (bytelit != 0x0FFL)
5265 emitcode ("anl", "a,%s",
5266 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5267 emitcode ("jnz", "%05d$", tlbl->key + 100);
5272 // bit = left & literal
5275 emitcode ("clr", "c");
5276 emitcode ("", "%05d$:", tlbl->key + 100);
5278 // if(left & literal)
5282 jmpTrueOrFalse (ifx, tlbl);
5290 /* if left is same as result */
5291 if (sameRegs (AOP (result), AOP (left)))
5293 for (; size--; offset++)
5295 if (AOP_TYPE (right) == AOP_LIT)
5297 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5299 else if (bytelit == 0)
5300 aopPut (AOP (result), zero, offset);
5301 else if (IS_AOP_PREG (result))
5303 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5304 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5305 aopPut (AOP (result), "a", offset);
5308 emitcode ("anl", "%s,%s",
5309 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5310 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5314 if (AOP_TYPE (left) == AOP_ACC)
5315 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5318 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5319 if (IS_AOP_PREG (result))
5321 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5322 aopPut (AOP (result), "a", offset);
5326 emitcode ("anl", "%s,a",
5327 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5334 // left & result in different registers
5335 if (AOP_TYPE (result) == AOP_CRY)
5338 // if(size), result in bit
5339 // if(!size && ifx), conditional oper: if(left & right)
5340 symbol *tlbl = newiTempLabel (NULL);
5341 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5343 emitcode ("setb", "c");
5346 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5347 emitcode ("anl", "a,%s",
5348 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5349 emitcode ("jnz", "%05d$", tlbl->key + 100);
5355 emitcode ("", "%05d$:", tlbl->key + 100);
5359 jmpTrueOrFalse (ifx, tlbl);
5363 for (; (size--); offset++)
5366 // result = left & right
5367 if (AOP_TYPE (right) == AOP_LIT)
5369 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5371 aopPut (AOP (result),
5372 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5376 else if (bytelit == 0)
5378 aopPut (AOP (result), zero, offset);
5381 D (emitcode (";", "better literal AND.");
5383 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5384 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5385 FALSE, FALSE, FALSE));
5390 // faster than result <- left, anl result,right
5391 // and better if result is SFR
5392 if (AOP_TYPE (left) == AOP_ACC)
5394 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5395 FALSE, FALSE, FALSE));
5399 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5400 emitcode ("anl", "a,%s",
5401 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5404 aopPut (AOP (result), "a", offset);
5410 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5411 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5412 freeAsmop (result, NULL, ic, TRUE);
5416 /*-----------------------------------------------------------------*/
5417 /* genOr - code for or */
5418 /*-----------------------------------------------------------------*/
5420 genOr (iCode * ic, iCode * ifx)
5422 operand *left, *right, *result;
5423 int size, offset = 0;
5424 unsigned long lit = 0L;
5427 D (emitcode (";", "genOr "););
5429 AOP_OP_3_NOFATAL (ic, pushResult);
5430 AOP_SET_LOCALS (ic);
5434 genFarFarLogicOp(ic, "orl");
5440 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5442 AOP_TYPE (left), AOP_TYPE (right));
5443 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5445 AOP_SIZE (left), AOP_SIZE (right));
5448 /* if left is a literal & right is not then exchange them */
5449 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5450 AOP_NEEDSACC (left))
5452 operand *tmp = right;
5457 /* if result = right then exchange them */
5458 if (sameRegs (AOP (result), AOP (right)))
5460 operand *tmp = right;
5465 /* if right is bit then exchange them */
5466 if (AOP_TYPE (right) == AOP_CRY &&
5467 AOP_TYPE (left) != AOP_CRY)
5469 operand *tmp = right;
5473 if (AOP_TYPE (right) == AOP_LIT)
5474 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5476 size = AOP_SIZE (result);
5480 if (AOP_TYPE (left) == AOP_CRY)
5482 if (AOP_TYPE (right) == AOP_LIT)
5484 // c = bit & literal;
5487 // lit != 0 => result = 1
5488 if (AOP_TYPE (result) == AOP_CRY)
5491 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5493 continueIfTrue (ifx);
5496 emitcode ("setb", "c");
5500 // lit == 0 => result = left
5501 if (size && sameRegs (AOP (result), AOP (left)))
5503 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5508 if (AOP_TYPE (right) == AOP_CRY)
5511 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5512 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5517 symbol *tlbl = newiTempLabel (NULL);
5518 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5519 emitcode ("setb", "c");
5520 emitcode ("jb", "%s,%05d$",
5521 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5523 emitcode ("jnz", "%05d$", tlbl->key + 100);
5524 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5526 jmpTrueOrFalse (ifx, tlbl);
5532 emitcode ("", "%05d$:", tlbl->key + 100);
5541 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5542 genIfxJump (ifx, "c");
5546 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5547 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5548 if ((AOP_TYPE (right) == AOP_LIT) &&
5549 (AOP_TYPE (result) == AOP_CRY) &&
5550 (AOP_TYPE (left) != AOP_CRY))
5556 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5558 continueIfTrue (ifx);
5563 // lit = 0, result = boolean(left)
5565 emitcode ("setb", "c");
5569 symbol *tlbl = newiTempLabel (NULL);
5570 emitcode ("jnz", "%05d$", tlbl->key + 100);
5572 emitcode ("", "%05d$:", tlbl->key + 100);
5576 genIfxJump (ifx, "a");
5584 /* if left is same as result */
5585 if (sameRegs (AOP (result), AOP (left)))
5587 for (; size--; offset++)
5589 if (AOP_TYPE (right) == AOP_LIT)
5591 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5597 if (IS_AOP_PREG (left))
5599 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5600 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5601 aopPut (AOP (result), "a", offset);
5605 emitcode ("orl", "%s,%s",
5606 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5607 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5613 if (AOP_TYPE (left) == AOP_ACC)
5615 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5619 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5620 if (IS_AOP_PREG (left))
5622 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5623 aopPut (AOP (result), "a", offset);
5627 emitcode ("orl", "%s,a",
5628 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5636 // left & result in different registers
5637 if (AOP_TYPE (result) == AOP_CRY)
5640 // if(size), result in bit
5641 // if(!size && ifx), conditional oper: if(left | right)
5642 symbol *tlbl = newiTempLabel (NULL);
5643 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5645 emitcode ("setb", "c");
5648 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5649 emitcode ("orl", "a,%s",
5650 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5651 emitcode ("jnz", "%05d$", tlbl->key + 100);
5657 emitcode ("", "%05d$:", tlbl->key + 100);
5661 jmpTrueOrFalse (ifx, tlbl);
5665 for (; (size--); offset++)
5668 // result = left & right
5669 if (AOP_TYPE (right) == AOP_LIT)
5671 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5673 aopPut (AOP (result),
5674 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5678 D (emitcode (";", "better literal OR.");
5680 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5681 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5682 FALSE, FALSE, FALSE));
5687 // faster than result <- left, anl result,right
5688 // and better if result is SFR
5689 if (AOP_TYPE (left) == AOP_ACC)
5691 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5692 FALSE, FALSE, FALSE));
5696 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5697 emitcode ("orl", "a,%s",
5698 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5701 aopPut (AOP (result), "a", offset);
5707 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5708 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709 freeAsmop (result, NULL, ic, TRUE);
5712 /*-----------------------------------------------------------------*/
5713 /* genXor - code for xclusive or */
5714 /*-----------------------------------------------------------------*/
5716 genXor (iCode * ic, iCode * ifx)
5718 operand *left, *right, *result;
5719 int size, offset = 0;
5720 unsigned long lit = 0L;
5723 D (emitcode (";", "genXor "););
5725 AOP_OP_3_NOFATAL (ic, pushResult);
5726 AOP_SET_LOCALS (ic);
5730 genFarFarLogicOp(ic, "xrl");
5735 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5737 AOP_TYPE (left), AOP_TYPE (right));
5738 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5740 AOP_SIZE (left), AOP_SIZE (right));
5743 /* if left is a literal & right is not ||
5744 if left needs acc & right does not */
5745 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5746 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5748 operand *tmp = right;
5753 /* if result = right then exchange them */
5754 if (sameRegs (AOP (result), AOP (right)))
5756 operand *tmp = right;
5761 /* if right is bit then exchange them */
5762 if (AOP_TYPE (right) == AOP_CRY &&
5763 AOP_TYPE (left) != AOP_CRY)
5765 operand *tmp = right;
5769 if (AOP_TYPE (right) == AOP_LIT)
5770 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5772 size = AOP_SIZE (result);
5776 if (AOP_TYPE (left) == AOP_CRY)
5778 if (AOP_TYPE (right) == AOP_LIT)
5780 // c = bit & literal;
5783 // lit>>1 != 0 => result = 1
5784 if (AOP_TYPE (result) == AOP_CRY)
5787 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5789 continueIfTrue (ifx);
5792 emitcode ("setb", "c");
5799 // lit == 0, result = left
5800 if (size && sameRegs (AOP (result), AOP (left)))
5802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5806 // lit == 1, result = not(left)
5807 if (size && sameRegs (AOP (result), AOP (left)))
5809 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5814 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5815 emitcode ("cpl", "c");
5824 symbol *tlbl = newiTempLabel (NULL);
5825 if (AOP_TYPE (right) == AOP_CRY)
5828 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5832 int sizer = AOP_SIZE (right);
5834 // if val>>1 != 0, result = 1
5835 emitcode ("setb", "c");
5838 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5840 // test the msb of the lsb
5841 emitcode ("anl", "a,#0xfe");
5842 emitcode ("jnz", "%05d$", tlbl->key + 100);
5846 emitcode ("rrc", "a");
5848 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5849 emitcode ("cpl", "c");
5850 emitcode ("", "%05d$:", (tlbl->key + 100));
5857 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5858 genIfxJump (ifx, "c");
5862 if (sameRegs (AOP (result), AOP (left)))
5864 /* if left is same as result */
5865 for (; size--; offset++)
5867 if (AOP_TYPE (right) == AOP_LIT)
5869 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5871 else if (IS_AOP_PREG (left))
5873 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5874 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5875 aopPut (AOP (result), "a", offset);
5878 emitcode ("xrl", "%s,%s",
5879 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5880 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5884 if (AOP_TYPE (left) == AOP_ACC)
5885 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5888 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5889 if (IS_AOP_PREG (left))
5891 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5892 aopPut (AOP (result), "a", offset);
5895 emitcode ("xrl", "%s,a",
5896 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5903 // left & result in different registers
5904 if (AOP_TYPE (result) == AOP_CRY)
5907 // if(size), result in bit
5908 // if(!size && ifx), conditional oper: if(left ^ right)
5909 symbol *tlbl = newiTempLabel (NULL);
5910 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5912 emitcode ("setb", "c");
5915 if ((AOP_TYPE (right) == AOP_LIT) &&
5916 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5918 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5922 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5923 emitcode ("xrl", "a,%s",
5924 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5926 emitcode ("jnz", "%05d$", tlbl->key + 100);
5932 emitcode ("", "%05d$:", tlbl->key + 100);
5936 jmpTrueOrFalse (ifx, tlbl);
5939 for (; (size--); offset++)
5942 // result = left & right
5943 if (AOP_TYPE (right) == AOP_LIT)
5945 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5947 aopPut (AOP (result),
5948 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5952 D (emitcode (";", "better literal XOR.");
5954 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5955 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5956 FALSE, FALSE, FALSE));
5960 // faster than result <- left, anl result,right
5961 // and better if result is SFR
5962 if (AOP_TYPE (left) == AOP_ACC)
5964 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5965 FALSE, FALSE, FALSE));
5969 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5970 emitcode ("xrl", "a,%s",
5971 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5974 aopPut (AOP (result), "a", offset);
5979 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5980 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5981 freeAsmop (result, NULL, ic, TRUE);
5984 /*-----------------------------------------------------------------*/
5985 /* genInline - write the inline code out */
5986 /*-----------------------------------------------------------------*/
5988 genInline (iCode * ic)
5990 char *buffer, *bp, *bp1;
5992 D (emitcode (";", "genInline ");
5995 _G.inLine += (!options.asmpeep);
5997 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5998 strcpy (buffer, IC_INLINE (ic));
6000 /* emit each line as a code */
6025 /* emitcode("",buffer); */
6026 _G.inLine -= (!options.asmpeep);
6029 /*-----------------------------------------------------------------*/
6030 /* genRRC - rotate right with carry */
6031 /*-----------------------------------------------------------------*/
6035 operand *left, *result;
6036 int size, offset = 0;
6039 D (emitcode (";", "genRRC ");
6042 /* rotate right with carry */
6043 left = IC_LEFT (ic);
6044 result = IC_RESULT (ic);
6045 aopOp (left, ic, FALSE, FALSE);
6046 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6048 /* move it to the result */
6049 size = AOP_SIZE (result);
6053 _startLazyDPSEvaluation ();
6056 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6058 emitcode ("rrc", "a");
6059 if (AOP_SIZE (result) > 1)
6060 aopPut (AOP (result), "a", offset--);
6062 _endLazyDPSEvaluation ();
6064 /* now we need to put the carry into the
6065 highest order byte of the result */
6066 if (AOP_SIZE (result) > 1)
6068 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6071 emitcode ("mov", "acc.7,c");
6072 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6073 freeAsmop (left, NULL, ic, TRUE);
6074 freeAsmop (result, NULL, ic, TRUE);
6077 /*-----------------------------------------------------------------*/
6078 /* genRLC - generate code for rotate left with carry */
6079 /*-----------------------------------------------------------------*/
6083 operand *left, *result;
6084 int size, offset = 0;
6087 D (emitcode (";", "genRLC ");
6090 /* rotate right with carry */
6091 left = IC_LEFT (ic);
6092 result = IC_RESULT (ic);
6093 aopOp (left, ic, FALSE, FALSE);
6094 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6096 /* move it to the result */
6097 size = AOP_SIZE (result);
6101 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6103 emitcode ("add", "a,acc");
6104 if (AOP_SIZE (result) > 1)
6106 aopPut (AOP (result), "a", offset++);
6109 _startLazyDPSEvaluation ();
6112 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6114 emitcode ("rlc", "a");
6115 if (AOP_SIZE (result) > 1)
6116 aopPut (AOP (result), "a", offset++);
6118 _endLazyDPSEvaluation ();
6120 /* now we need to put the carry into the
6121 highest order byte of the result */
6122 if (AOP_SIZE (result) > 1)
6124 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6127 emitcode ("mov", "acc.0,c");
6128 aopPut (AOP (result), "a", 0);
6129 freeAsmop (left, NULL, ic, TRUE);
6130 freeAsmop (result, NULL, ic, TRUE);
6133 /*-----------------------------------------------------------------*/
6134 /* genGetHbit - generates code get highest order bit */
6135 /*-----------------------------------------------------------------*/
6137 genGetHbit (iCode * ic)
6139 operand *left, *result;
6140 left = IC_LEFT (ic);
6141 result = IC_RESULT (ic);
6142 aopOp (left, ic, FALSE, FALSE);
6143 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6145 D (emitcode (";", "genGetHbit ");
6148 /* get the highest order byte into a */
6149 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6150 if (AOP_TYPE (result) == AOP_CRY)
6152 emitcode ("rlc", "a");
6157 emitcode ("rl", "a");
6158 emitcode ("anl", "a,#0x01");
6163 freeAsmop (left, NULL, ic, TRUE);
6164 freeAsmop (result, NULL, ic, TRUE);
6167 /*-----------------------------------------------------------------*/
6168 /* AccRol - rotate left accumulator by known count */
6169 /*-----------------------------------------------------------------*/
6171 AccRol (int shCount)
6173 shCount &= 0x0007; // shCount : 0..7
6180 emitcode ("rl", "a");
6183 emitcode ("rl", "a");
6184 emitcode ("rl", "a");
6187 emitcode ("swap", "a");
6188 emitcode ("rr", "a");
6191 emitcode ("swap", "a");
6194 emitcode ("swap", "a");
6195 emitcode ("rl", "a");
6198 emitcode ("rr", "a");
6199 emitcode ("rr", "a");
6202 emitcode ("rr", "a");
6207 /*-----------------------------------------------------------------*/
6208 /* AccLsh - left shift accumulator by known count */
6209 /*-----------------------------------------------------------------*/
6211 AccLsh (int shCount)
6216 emitcode ("add", "a,acc");
6217 else if (shCount == 2)
6219 emitcode ("add", "a,acc");
6220 emitcode ("add", "a,acc");
6224 /* rotate left accumulator */
6226 /* and kill the lower order bits */
6227 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6232 /*-----------------------------------------------------------------*/
6233 /* AccRsh - right shift accumulator by known count */
6234 /*-----------------------------------------------------------------*/
6236 AccRsh (int shCount)
6243 emitcode ("rrc", "a");
6247 /* rotate right accumulator */
6248 AccRol (8 - shCount);
6249 /* and kill the higher order bits */
6250 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6255 #ifdef BETTER_LITERAL_SHIFT
6256 /*-----------------------------------------------------------------*/
6257 /* AccSRsh - signed right shift accumulator by known count */
6258 /*-----------------------------------------------------------------*/
6260 AccSRsh (int shCount)
6267 emitcode ("mov", "c,acc.7");
6268 emitcode ("rrc", "a");
6270 else if (shCount == 2)
6272 emitcode ("mov", "c,acc.7");
6273 emitcode ("rrc", "a");
6274 emitcode ("mov", "c,acc.7");
6275 emitcode ("rrc", "a");
6279 tlbl = newiTempLabel (NULL);
6280 /* rotate right accumulator */
6281 AccRol (8 - shCount);
6282 /* and kill the higher order bits */
6283 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6284 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6285 emitcode ("orl", "a,#0x%02x",
6286 (unsigned char) ~SRMask[shCount]);
6287 emitcode ("", "%05d$:", tlbl->key + 100);
6293 #ifdef BETTER_LITERAL_SHIFT
6294 /*-----------------------------------------------------------------*/
6295 /* shiftR1Left2Result - shift right one byte from left to result */
6296 /*-----------------------------------------------------------------*/
6298 shiftR1Left2Result (operand * left, int offl,
6299 operand * result, int offr,
6300 int shCount, int sign)
6302 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6303 /* shift right accumulator */
6308 aopPut (AOP (result), "a", offr);
6312 #ifdef BETTER_LITERAL_SHIFT
6313 /*-----------------------------------------------------------------*/
6314 /* shiftL1Left2Result - shift left one byte from left to result */
6315 /*-----------------------------------------------------------------*/
6317 shiftL1Left2Result (operand * left, int offl,
6318 operand * result, int offr, int shCount)
6320 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6321 /* shift left accumulator */
6323 aopPut (AOP (result), "a", offr);
6327 #ifdef BETTER_LITERAL_SHIFT
6328 /*-----------------------------------------------------------------*/
6329 /* movLeft2Result - move byte from left to result */
6330 /*-----------------------------------------------------------------*/
6332 movLeft2Result (operand * left, int offl,
6333 operand * result, int offr, int sign)
6336 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6338 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6340 if (*l == '@' && (IS_AOP_PREG (result)))
6342 emitcode ("mov", "a,%s", l);
6343 aopPut (AOP (result), "a", offr);
6349 aopPut (AOP (result), l, offr);
6353 /* MSB sign in acc.7 ! */
6354 if (getDataSize (left) == offl + 1)
6356 emitcode ("mov", "a,%s", l);
6357 aopPut (AOP (result), "a", offr);
6365 #ifdef BETTER_LITERAL_SHIFT
6366 /*-----------------------------------------------------------------*/
6367 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6368 /*-----------------------------------------------------------------*/
6372 emitcode ("rrc", "a");
6373 emitcode ("xch", "a,%s", x);
6374 emitcode ("rrc", "a");
6375 emitcode ("xch", "a,%s", x);
6379 #ifdef BETTER_LITERAL_SHIFT
6381 /*-----------------------------------------------------------------*/
6382 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6383 /*-----------------------------------------------------------------*/
6387 emitcode ("xch", "a,%s", x);
6388 emitcode ("rlc", "a");
6389 emitcode ("xch", "a,%s", x);
6390 emitcode ("rlc", "a");
6394 #ifdef BETTER_LITERAL_SHIFT
6395 /*-----------------------------------------------------------------*/
6396 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6397 /*-----------------------------------------------------------------*/
6401 emitcode ("xch", "a,%s", x);
6402 emitcode ("add", "a,acc");
6403 emitcode ("xch", "a,%s", x);
6404 emitcode ("rlc", "a");
6408 #ifdef BETTER_LITERAL_SHIFT
6409 /*-----------------------------------------------------------------*/
6410 /* AccAXLsh - left shift a:x by known count (0..7) */
6411 /*-----------------------------------------------------------------*/
6413 AccAXLsh (char *x, int shCount)
6428 case 5: // AAAAABBB:CCCCCDDD
6430 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6432 emitcode ("anl", "a,#0x%02x",
6433 SLMask[shCount]); // BBB00000:CCCCCDDD
6435 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6437 AccRol (shCount); // DDDCCCCC:BBB00000
6439 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6441 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6443 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6445 emitcode ("anl", "a,#0x%02x",
6446 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6448 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6450 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6453 case 6: // AAAAAABB:CCCCCCDD
6454 emitcode ("anl", "a,#0x%02x",
6455 SRMask[shCount]); // 000000BB:CCCCCCDD
6456 emitcode ("mov", "c,acc.0"); // c = B
6457 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6459 AccAXRrl1 (x); // BCCCCCCD:D000000B
6460 AccAXRrl1 (x); // BBCCCCCC:DD000000
6462 emitcode("rrc","a");
6463 emitcode("xch","a,%s", x);
6464 emitcode("rrc","a");
6465 emitcode("mov","c,acc.0"); //<< get correct bit
6466 emitcode("xch","a,%s", x);
6468 emitcode("rrc","a");
6469 emitcode("xch","a,%s", x);
6470 emitcode("rrc","a");
6471 emitcode("xch","a,%s", x);
6474 case 7: // a:x <<= 7
6476 emitcode ("anl", "a,#0x%02x",
6477 SRMask[shCount]); // 0000000B:CCCCCCCD
6479 emitcode ("mov", "c,acc.0"); // c = B
6481 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6483 AccAXRrl1 (x); // BCCCCCCC:D0000000
6492 #ifdef BETTER_LITERAL_SHIFT
6494 /*-----------------------------------------------------------------*/
6495 /* AccAXRsh - right shift a:x known count (0..7) */
6496 /*-----------------------------------------------------------------*/
6498 AccAXRsh (char *x, int shCount)
6506 AccAXRrl1 (x); // 0->a:x
6511 AccAXRrl1 (x); // 0->a:x
6514 AccAXRrl1 (x); // 0->a:x
6519 case 5: // AAAAABBB:CCCCCDDD = a:x
6521 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6523 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6525 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6527 emitcode ("anl", "a,#0x%02x",
6528 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6530 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6532 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6534 emitcode ("anl", "a,#0x%02x",
6535 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6537 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6539 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6541 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6544 case 6: // AABBBBBB:CCDDDDDD
6546 emitcode ("mov", "c,acc.7");
6547 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6549 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6551 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6553 emitcode ("anl", "a,#0x%02x",
6554 SRMask[shCount]); // 000000AA:BBBBBBCC
6557 case 7: // ABBBBBBB:CDDDDDDD
6559 emitcode ("mov", "c,acc.7"); // c = A
6561 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6563 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6565 emitcode ("anl", "a,#0x%02x",
6566 SRMask[shCount]); // 0000000A:BBBBBBBC
6575 #ifdef BETTER_LITERAL_SHIFT
6577 /*-----------------------------------------------------------------*/
6578 /* AccAXRshS - right shift signed a:x known count (0..7) */
6579 /*-----------------------------------------------------------------*/
6581 AccAXRshS (char *x, int shCount)
6589 emitcode ("mov", "c,acc.7");
6590 AccAXRrl1 (x); // s->a:x
6594 emitcode ("mov", "c,acc.7");
6595 AccAXRrl1 (x); // s->a:x
6597 emitcode ("mov", "c,acc.7");
6598 AccAXRrl1 (x); // s->a:x
6603 case 5: // AAAAABBB:CCCCCDDD = a:x
6605 tlbl = newiTempLabel (NULL);
6606 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6608 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6610 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6612 emitcode ("anl", "a,#0x%02x",
6613 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6615 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6617 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6619 emitcode ("anl", "a,#0x%02x",
6620 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6622 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6624 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6626 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6628 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6629 emitcode ("orl", "a,#0x%02x",
6630 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6632 emitcode ("", "%05d$:", tlbl->key + 100);
6633 break; // SSSSAAAA:BBBCCCCC
6635 case 6: // AABBBBBB:CCDDDDDD
6637 tlbl = newiTempLabel (NULL);
6638 emitcode ("mov", "c,acc.7");
6639 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6641 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6643 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6645 emitcode ("anl", "a,#0x%02x",
6646 SRMask[shCount]); // 000000AA:BBBBBBCC
6648 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6649 emitcode ("orl", "a,#0x%02x",
6650 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6652 emitcode ("", "%05d$:", tlbl->key + 100);
6654 case 7: // ABBBBBBB:CDDDDDDD
6656 tlbl = newiTempLabel (NULL);
6657 emitcode ("mov", "c,acc.7"); // c = A
6659 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6661 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6663 emitcode ("anl", "a,#0x%02x",
6664 SRMask[shCount]); // 0000000A:BBBBBBBC
6666 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6667 emitcode ("orl", "a,#0x%02x",
6668 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6670 emitcode ("", "%05d$:", tlbl->key + 100);
6678 #ifdef BETTER_LITERAL_SHIFT
6680 _loadLeftIntoAx(char **lsb,
6686 // Get the initial value from left into a pair of registers.
6687 // MSB must be in A, LSB can be any register.
6689 // If the result is held in registers, it is an optimization
6690 // if the LSB can be held in the register which will hold the,
6691 // result LSB since this saves us from having to copy it into
6692 // the result following AccAXLsh.
6694 // If the result is addressed indirectly, this is not a gain.
6695 if (AOP_NEEDSACC(result))
6699 _startLazyDPSEvaluation();
6700 if (AOP_TYPE(left) == AOP_DPTR2)
6703 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6704 // get LSB in DP2_RESULT_REG.
6705 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6706 assert(!strcmp(leftByte, DP2_RESULT_REG));
6710 // get LSB into DP2_RESULT_REG
6711 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6712 if (strcmp(leftByte, DP2_RESULT_REG))
6714 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6717 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6718 assert(strcmp(leftByte, DP2_RESULT_REG));
6721 _endLazyDPSEvaluation();
6722 *lsb = DP2_RESULT_REG;
6726 if (sameRegs (AOP (result), AOP (left)) &&
6727 ((offl + MSB16) == offr))
6729 /* don't crash result[offr] */
6730 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6731 emitcode ("xch", "a,%s",
6732 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6736 movLeft2Result (left, offl, result, offr, 0);
6737 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6739 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6740 assert(strcmp(*lsb,"a"));
6745 _storeAxResults(char *lsb,
6749 _startLazyDPSEvaluation();
6750 if (AOP_NEEDSACC(result))
6752 /* We have to explicitly update the result LSB.
6754 emitcode("xch","a,%s", lsb);
6755 aopPut(AOP(result), "a", offr);
6756 emitcode("mov","a,%s", lsb);
6758 if (getDataSize (result) > 1)
6760 aopPut (AOP (result), "a", offr + MSB16);
6762 _endLazyDPSEvaluation();
6765 /*-----------------------------------------------------------------*/
6766 /* shiftL2Left2Result - shift left two bytes from left to result */
6767 /*-----------------------------------------------------------------*/
6769 shiftL2Left2Result (operand * left, int offl,
6770 operand * result, int offr, int shCount)
6774 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6776 AccAXLsh (lsb, shCount);
6778 _storeAxResults(lsb, result, offr);
6782 #ifdef BETTER_LITERAL_SHIFT
6783 /*-----------------------------------------------------------------*/
6784 /* shiftR2Left2Result - shift right two bytes from left to result */
6785 /*-----------------------------------------------------------------*/
6787 shiftR2Left2Result (operand * left, int offl,
6788 operand * result, int offr,
6789 int shCount, int sign)
6793 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6795 /* a:x >> shCount (x = lsb(result)) */
6798 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6802 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6805 _storeAxResults(lsb, result, offr);
6811 /*-----------------------------------------------------------------*/
6812 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6813 /*-----------------------------------------------------------------*/
6815 shiftLLeftOrResult (operand * left, int offl,
6816 operand * result, int offr, int shCount)
6818 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6819 /* shift left accumulator */
6821 /* or with result */
6822 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6823 /* back to result */
6824 aopPut (AOP (result), "a", offr);
6830 /*-----------------------------------------------------------------*/
6831 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6832 /*-----------------------------------------------------------------*/
6834 shiftRLeftOrResult (operand * left, int offl,
6835 operand * result, int offr, int shCount)
6837 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6838 /* shift right accumulator */
6840 /* or with result */
6841 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6842 /* back to result */
6843 aopPut (AOP (result), "a", offr);
6847 #ifdef BETTER_LITERAL_SHIFT
6848 /*-----------------------------------------------------------------*/
6849 /* genlshOne - left shift a one byte quantity by known count */
6850 /*-----------------------------------------------------------------*/
6852 genlshOne (operand * result, operand * left, int shCount)
6854 D (emitcode (";", "genlshOne "););
6855 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6859 #ifdef BETTER_LITERAL_SHIFT
6860 /*-----------------------------------------------------------------*/
6861 /* genlshTwo - left shift two bytes by known amount != 0 */
6862 /*-----------------------------------------------------------------*/
6864 genlshTwo (operand * result, operand * left, int shCount)
6868 D (emitcode (";", "genlshTwo "););
6870 size = getDataSize (result);
6872 /* if shCount >= 8 */
6877 _startLazyDPSEvaluation();
6883 _endLazyDPSEvaluation();
6884 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6885 aopPut (AOP (result), zero, LSB);
6889 movLeft2Result (left, LSB, result, MSB16, 0);
6890 aopPut (AOP (result), zero, LSB);
6891 _endLazyDPSEvaluation();
6896 aopPut (AOP (result), zero, LSB);
6897 _endLazyDPSEvaluation();
6901 /* 1 <= shCount <= 7 */
6906 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6910 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6918 /*-----------------------------------------------------------------*/
6919 /* shiftLLong - shift left one long from left to result */
6920 /* offl = LSB or MSB16 */
6921 /*-----------------------------------------------------------------*/
6923 shiftLLong (operand * left, operand * result, int offr)
6926 int size = AOP_SIZE (result);
6928 if (size >= LSB + offr)
6930 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6932 emitcode ("add", "a,acc");
6933 if (sameRegs (AOP (left), AOP (result)) &&
6934 size >= MSB16 + offr && offr != LSB)
6935 emitcode ("xch", "a,%s",
6936 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6938 aopPut (AOP (result), "a", LSB + offr);
6941 if (size >= MSB16 + offr)
6943 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6945 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6948 emitcode ("rlc", "a");
6949 if (sameRegs (AOP (left), AOP (result)) &&
6950 size >= MSB24 + offr && offr != LSB)
6951 emitcode ("xch", "a,%s",
6952 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6954 aopPut (AOP (result), "a", MSB16 + offr);
6957 if (size >= MSB24 + offr)
6959 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6961 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6964 emitcode ("rlc", "a");
6965 if (sameRegs (AOP (left), AOP (result)) &&
6966 size >= MSB32 + offr && offr != LSB)
6967 emitcode ("xch", "a,%s",
6968 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6970 aopPut (AOP (result), "a", MSB24 + offr);
6973 if (size > MSB32 + offr)
6975 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6977 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6980 emitcode ("rlc", "a");
6981 aopPut (AOP (result), "a", MSB32 + offr);
6984 aopPut (AOP (result), zero, LSB);
6990 /*-----------------------------------------------------------------*/
6991 /* genlshFour - shift four byte by a known amount != 0 */
6992 /*-----------------------------------------------------------------*/
6994 genlshFour (operand * result, operand * left, int shCount)
6998 D (emitcode (";", "genlshFour ");
7001 size = AOP_SIZE (result);
7003 /* if shifting more that 3 bytes */
7008 /* lowest order of left goes to the highest
7009 order of the destination */
7010 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7012 movLeft2Result (left, LSB, result, MSB32, 0);
7013 aopPut (AOP (result), zero, LSB);
7014 aopPut (AOP (result), zero, MSB16);
7015 aopPut (AOP (result), zero, MSB24);
7019 /* more than two bytes */
7020 else if (shCount >= 16)
7022 /* lower order two bytes goes to higher order two bytes */
7024 /* if some more remaining */
7026 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7029 movLeft2Result (left, MSB16, result, MSB32, 0);
7030 movLeft2Result (left, LSB, result, MSB24, 0);
7032 aopPut (AOP (result), zero, MSB16);
7033 aopPut (AOP (result), zero, LSB);
7037 /* if more than 1 byte */
7038 else if (shCount >= 8)
7040 /* lower order three bytes goes to higher order three bytes */
7045 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7047 movLeft2Result (left, LSB, result, MSB16, 0);
7053 movLeft2Result (left, MSB24, result, MSB32, 0);
7054 movLeft2Result (left, MSB16, result, MSB24, 0);
7055 movLeft2Result (left, LSB, result, MSB16, 0);
7056 aopPut (AOP (result), zero, LSB);
7058 else if (shCount == 1)
7059 shiftLLong (left, result, MSB16);
7062 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7063 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7064 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7065 aopPut (AOP (result), zero, LSB);
7070 /* 1 <= shCount <= 7 */
7071 else if (shCount <= 2)
7073 shiftLLong (left, result, LSB);
7075 shiftLLong (result, result, LSB);
7077 /* 3 <= shCount <= 7, optimize */
7080 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7081 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7082 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7087 #ifdef BETTER_LITERAL_SHIFT
7088 /*-----------------------------------------------------------------*/
7089 /* genLeftShiftLiteral - left shifting by known count */
7090 /*-----------------------------------------------------------------*/
7092 genLeftShiftLiteral (operand * left,
7097 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7100 size = getSize (operandType (result));
7102 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7104 /* We only handle certain easy cases so far. */
7106 && (shCount < (size * 8))
7110 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7114 freeAsmop (right, NULL, ic, TRUE);
7116 aopOp(left, ic, FALSE, FALSE);
7117 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7120 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7122 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7123 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7125 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7128 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7130 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7131 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7133 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7139 emitcode ("; shift left ", "result %d, left %d", size,
7143 /* I suppose that the left size >= result size */
7146 _startLazyDPSEvaluation();
7149 movLeft2Result (left, size, result, size, 0);
7151 _endLazyDPSEvaluation();
7153 else if (shCount >= (size * 8))
7155 _startLazyDPSEvaluation();
7158 aopPut (AOP (result), zero, size);
7160 _endLazyDPSEvaluation();
7167 genlshOne (result, left, shCount);
7171 genlshTwo (result, left, shCount);
7175 genlshFour (result, left, shCount);
7179 fprintf(stderr, "*** ack! mystery literal shift!\n");
7183 freeAsmop (left, NULL, ic, TRUE);
7184 freeAsmop (result, NULL, ic, TRUE);
7189 /*-----------------------------------------------------------------*/
7190 /* genLeftShift - generates code for left shifting */
7191 /*-----------------------------------------------------------------*/
7193 genLeftShift (iCode * ic)
7195 operand *left, *right, *result;
7198 symbol *tlbl, *tlbl1;
7200 D (emitcode (";", "genLeftShift "););
7202 right = IC_RIGHT (ic);
7203 left = IC_LEFT (ic);
7204 result = IC_RESULT (ic);
7206 aopOp (right, ic, FALSE, FALSE);
7209 #ifdef BETTER_LITERAL_SHIFT
7210 /* if the shift count is known then do it
7211 as efficiently as possible */
7212 if (AOP_TYPE (right) == AOP_LIT)
7214 if (genLeftShiftLiteral (left, right, result, ic))
7221 /* shift count is unknown then we have to form
7222 a loop get the loop count in B : Note: we take
7223 only the lower order byte since shifting
7224 more that 32 bits make no sense anyway, ( the
7225 largest size of an object can be only 32 bits ) */
7227 if (AOP_TYPE (right) == AOP_LIT)
7229 /* Really should be handled by genLeftShiftLiteral,
7230 * but since I'm too lazy to fix that today, at least we can make
7231 * some small improvement.
7233 emitcode("mov", "b,#0x%02x",
7234 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7238 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7239 emitcode ("inc", "b");
7241 freeAsmop (right, NULL, ic, TRUE);
7242 aopOp (left, ic, FALSE, FALSE);
7243 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7245 /* now move the left to the result if they are not the
7247 if (!sameRegs (AOP (left), AOP (result)) &&
7248 AOP_SIZE (result) > 1)
7251 size = AOP_SIZE (result);
7253 _startLazyDPSEvaluation ();
7256 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7257 if (*l == '@' && (IS_AOP_PREG (result)))
7260 emitcode ("mov", "a,%s", l);
7261 aopPut (AOP (result), "a", offset);
7264 aopPut (AOP (result), l, offset);
7267 _endLazyDPSEvaluation ();
7270 tlbl = newiTempLabel (NULL);
7271 size = AOP_SIZE (result);
7273 tlbl1 = newiTempLabel (NULL);
7275 /* if it is only one byte then */
7278 symbol *tlbl1 = newiTempLabel (NULL);
7280 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7282 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7283 emitcode ("", "%05d$:", tlbl->key + 100);
7284 emitcode ("add", "a,acc");
7285 emitcode ("", "%05d$:", tlbl1->key + 100);
7286 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7287 aopPut (AOP (result), "a", 0);
7291 reAdjustPreg (AOP (result));
7293 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7294 emitcode ("", "%05d$:", tlbl->key + 100);
7295 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7297 emitcode ("add", "a,acc");
7298 aopPut (AOP (result), "a", offset++);
7299 _startLazyDPSEvaluation ();
7302 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7304 emitcode ("rlc", "a");
7305 aopPut (AOP (result), "a", offset++);
7307 _endLazyDPSEvaluation ();
7308 reAdjustPreg (AOP (result));
7310 emitcode ("", "%05d$:", tlbl1->key + 100);
7311 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7313 freeAsmop (left, NULL, ic, TRUE);
7314 freeAsmop (result, NULL, ic, TRUE);
7317 #ifdef BETTER_LITERAL_SHIFT
7318 /*-----------------------------------------------------------------*/
7319 /* genrshOne - right shift a one byte quantity by known count */
7320 /*-----------------------------------------------------------------*/
7322 genrshOne (operand * result, operand * left,
7323 int shCount, int sign)
7325 D (emitcode (";", "genrshOne"););
7326 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7330 #ifdef BETTER_LITERAL_SHIFT
7331 /*-----------------------------------------------------------------*/
7332 /* genrshTwo - right shift two bytes by known amount != 0 */
7333 /*-----------------------------------------------------------------*/
7335 genrshTwo (operand * result, operand * left,
7336 int shCount, int sign)
7338 D (emitcode (";", "genrshTwo"););
7340 /* if shCount >= 8 */
7344 _startLazyDPSEvaluation();
7347 shiftR1Left2Result (left, MSB16, result, LSB,
7352 movLeft2Result (left, MSB16, result, LSB, sign);
7354 addSign (result, MSB16, sign);
7355 _endLazyDPSEvaluation();
7358 /* 1 <= shCount <= 7 */
7361 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7368 /*-----------------------------------------------------------------*/
7369 /* shiftRLong - shift right one long from left to result */
7370 /* offl = LSB or MSB16 */
7371 /*-----------------------------------------------------------------*/
7373 shiftRLong (operand * left, int offl,
7374 operand * result, int sign)
7377 emitcode ("clr", "c");
7378 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7380 emitcode ("mov", "c,acc.7");
7381 emitcode ("rrc", "a");
7382 aopPut (AOP (result), "a", MSB32 - offl);
7384 /* add sign of "a" */
7385 addSign (result, MSB32, sign);
7387 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7388 emitcode ("rrc", "a");
7389 aopPut (AOP (result), "a", MSB24 - offl);
7391 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7392 emitcode ("rrc", "a");
7393 aopPut (AOP (result), "a", MSB16 - offl);
7397 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7398 emitcode ("rrc", "a");
7399 aopPut (AOP (result), "a", LSB);
7406 /*-----------------------------------------------------------------*/
7407 /* genrshFour - shift four byte by a known amount != 0 */
7408 /*-----------------------------------------------------------------*/
7410 genrshFour (operand * result, operand * left,
7411 int shCount, int sign)
7413 D (emitcode (";", "genrshFour");
7416 /* if shifting more that 3 bytes */
7421 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7423 movLeft2Result (left, MSB32, result, LSB, sign);
7424 addSign (result, MSB16, sign);
7426 else if (shCount >= 16)
7430 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7433 movLeft2Result (left, MSB24, result, LSB, 0);
7434 movLeft2Result (left, MSB32, result, MSB16, sign);
7436 addSign (result, MSB24, sign);
7438 else if (shCount >= 8)
7442 shiftRLong (left, MSB16, result, sign);
7443 else if (shCount == 0)
7445 movLeft2Result (left, MSB16, result, LSB, 0);
7446 movLeft2Result (left, MSB24, result, MSB16, 0);
7447 movLeft2Result (left, MSB32, result, MSB24, sign);
7448 addSign (result, MSB32, sign);
7452 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7453 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7454 /* the last shift is signed */
7455 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7456 addSign (result, MSB32, sign);
7460 { /* 1 <= shCount <= 7 */
7463 shiftRLong (left, LSB, result, sign);
7465 shiftRLong (result, LSB, result, sign);
7469 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7470 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7471 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7477 #ifdef BETTER_LITERAL_SHIFT
7478 /*-----------------------------------------------------------------*/
7479 /* genRightShiftLiteral - right shifting by known count */
7480 /*-----------------------------------------------------------------*/
7482 genRightShiftLiteral (operand * left,
7488 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7491 size = getSize (operandType (result));
7493 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7495 /* We only handle certain easy cases so far. */
7497 && (shCount < (size * 8))
7501 D(emitcode (";", "genRightShiftLiteral wimping out"););
7505 freeAsmop (right, NULL, ic, TRUE);
7507 aopOp (left, ic, FALSE, FALSE);
7508 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7511 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7515 /* test the LEFT size !!! */
7517 /* I suppose that the left size >= result size */
7520 size = getDataSize (result);
7521 _startLazyDPSEvaluation();
7524 movLeft2Result (left, size, result, size, 0);
7526 _endLazyDPSEvaluation();
7528 else if (shCount >= (size * 8))
7532 /* get sign in acc.7 */
7533 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7535 addSign (result, LSB, sign);
7542 genrshOne (result, left, shCount, sign);
7546 genrshTwo (result, left, shCount, sign);
7550 genrshFour (result, left, shCount, sign);
7557 freeAsmop (left, NULL, ic, TRUE);
7558 freeAsmop (result, NULL, ic, TRUE);
7564 /*-----------------------------------------------------------------*/
7565 /* genSignedRightShift - right shift of signed number */
7566 /*-----------------------------------------------------------------*/
7568 genSignedRightShift (iCode * ic)
7570 operand *right, *left, *result;
7573 symbol *tlbl, *tlbl1;
7575 D (emitcode (";", "genSignedRightShift "););
7577 /* we do it the hard way put the shift count in b
7578 and loop thru preserving the sign */
7580 right = IC_RIGHT (ic);
7581 left = IC_LEFT (ic);
7582 result = IC_RESULT (ic);
7584 aopOp (right, ic, FALSE, FALSE);
7586 #ifdef BETTER_LITERAL_SHIFT
7587 if (AOP_TYPE (right) == AOP_LIT)
7589 if (genRightShiftLiteral (left, right, result, ic, 1))
7595 /* shift count is unknown then we have to form
7596 a loop get the loop count in B : Note: we take
7597 only the lower order byte since shifting
7598 more that 32 bits make no sense anyway, ( the
7599 largest size of an object can be only 32 bits ) */
7601 if (AOP_TYPE (right) == AOP_LIT)
7603 /* Really should be handled by genRightShiftLiteral,
7604 * but since I'm too lazy to fix that today, at least we can make
7605 * some small improvement.
7607 emitcode("mov", "b,#0x%02x",
7608 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7612 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7613 emitcode ("inc", "b");
7615 freeAsmop (right, NULL, ic, TRUE);
7616 aopOp (left, ic, FALSE, FALSE);
7617 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7619 /* now move the left to the result if they are not the
7621 if (!sameRegs (AOP (left), AOP (result)) &&
7622 AOP_SIZE (result) > 1)
7625 size = AOP_SIZE (result);
7627 _startLazyDPSEvaluation ();
7630 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7631 if (*l == '@' && IS_AOP_PREG (result))
7634 emitcode ("mov", "a,%s", l);
7635 aopPut (AOP (result), "a", offset);
7638 aopPut (AOP (result), l, offset);
7641 _endLazyDPSEvaluation ();
7644 /* mov the highest order bit to OVR */
7645 tlbl = newiTempLabel (NULL);
7646 tlbl1 = newiTempLabel (NULL);
7648 size = AOP_SIZE (result);
7650 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7651 emitcode ("rlc", "a");
7652 emitcode ("mov", "ov,c");
7653 /* if it is only one byte then */
7656 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7658 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7659 emitcode ("", "%05d$:", tlbl->key + 100);
7660 emitcode ("mov", "c,ov");
7661 emitcode ("rrc", "a");
7662 emitcode ("", "%05d$:", tlbl1->key + 100);
7663 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7664 aopPut (AOP (result), "a", 0);
7668 reAdjustPreg (AOP (result));
7669 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7670 emitcode ("", "%05d$:", tlbl->key + 100);
7671 emitcode ("mov", "c,ov");
7672 _startLazyDPSEvaluation ();
7675 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7677 emitcode ("rrc", "a");
7678 aopPut (AOP (result), "a", offset--);
7680 _endLazyDPSEvaluation ();
7681 reAdjustPreg (AOP (result));
7682 emitcode ("", "%05d$:", tlbl1->key + 100);
7683 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7686 freeAsmop (left, NULL, ic, TRUE);
7687 freeAsmop (result, NULL, ic, TRUE);
7690 /*-----------------------------------------------------------------*/
7691 /* genRightShift - generate code for right shifting */
7692 /*-----------------------------------------------------------------*/
7694 genRightShift (iCode * ic)
7696 operand *right, *left, *result;
7700 symbol *tlbl, *tlbl1;
7702 D (emitcode (";", "genRightShift "););
7704 /* if signed then we do it the hard way preserve the
7705 sign bit moving it inwards */
7706 retype = getSpec (operandType (IC_RESULT (ic)));
7708 if (!SPEC_USIGN (retype))
7710 genSignedRightShift (ic);
7714 /* signed & unsigned types are treated the same : i.e. the
7715 signed is NOT propagated inwards : quoting from the
7716 ANSI - standard : "for E1 >> E2, is equivalent to division
7717 by 2**E2 if unsigned or if it has a non-negative value,
7718 otherwise the result is implementation defined ", MY definition
7719 is that the sign does not get propagated */
7721 right = IC_RIGHT (ic);
7722 left = IC_LEFT (ic);
7723 result = IC_RESULT (ic);
7725 aopOp (right, ic, FALSE, FALSE);
7727 #ifdef BETTER_LITERAL_SHIFT
7728 /* if the shift count is known then do it
7729 as efficiently as possible */
7730 if (AOP_TYPE (right) == AOP_LIT)
7732 if (genRightShiftLiteral (left, right, result, ic, 0))
7739 /* shift count is unknown then we have to form
7740 a loop get the loop count in B : Note: we take
7741 only the lower order byte since shifting
7742 more that 32 bits make no sense anyway, ( the
7743 largest size of an object can be only 32 bits ) */
7745 if (AOP_TYPE (right) == AOP_LIT)
7747 /* Really should be handled by genRightShiftLiteral,
7748 * but since I'm too lazy to fix that today, at least we can make
7749 * some small improvement.
7751 emitcode("mov", "b,#0x%02x",
7752 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7756 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7757 emitcode ("inc", "b");
7759 freeAsmop (right, NULL, ic, TRUE);
7760 aopOp (left, ic, FALSE, FALSE);
7761 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7763 /* now move the left to the result if they are not the
7765 if (!sameRegs (AOP (left), AOP (result)) &&
7766 AOP_SIZE (result) > 1)
7769 size = AOP_SIZE (result);
7771 _startLazyDPSEvaluation ();
7774 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7775 if (*l == '@' && IS_AOP_PREG (result))
7778 emitcode ("mov", "a,%s", l);
7779 aopPut (AOP (result), "a", offset);
7782 aopPut (AOP (result), l, offset);
7785 _endLazyDPSEvaluation ();
7788 tlbl = newiTempLabel (NULL);
7789 tlbl1 = newiTempLabel (NULL);
7790 size = AOP_SIZE (result);
7793 /* if it is only one byte then */
7796 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7798 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7799 emitcode ("", "%05d$:", tlbl->key + 100);
7801 emitcode ("rrc", "a");
7802 emitcode ("", "%05d$:", tlbl1->key + 100);
7803 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7804 aopPut (AOP (result), "a", 0);
7808 reAdjustPreg (AOP (result));
7809 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7810 emitcode ("", "%05d$:", tlbl->key + 100);
7812 _startLazyDPSEvaluation ();
7815 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7817 emitcode ("rrc", "a");
7818 aopPut (AOP (result), "a", offset--);
7820 _endLazyDPSEvaluation ();
7821 reAdjustPreg (AOP (result));
7823 emitcode ("", "%05d$:", tlbl1->key + 100);
7824 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7827 freeAsmop (left, NULL, ic, TRUE);
7828 freeAsmop (result, NULL, ic, TRUE);
7831 /*-----------------------------------------------------------------*/
7832 /* genUnpackBits - generates code for unpacking bits */
7833 /*-----------------------------------------------------------------*/
7835 genUnpackBits (operand * result, char *rname, int ptype)
7842 D (emitcode (";", "genUnpackBits ");
7845 etype = getSpec (operandType (result));
7847 /* read the first byte */
7853 emitcode ("mov", "a,@%s", rname);
7857 emitcode ("movx", "a,@%s", rname);
7861 emitcode ("movx", "a,@dptr");
7865 emitcode ("clr", "a");
7866 emitcode ("movc", "a", "@a+dptr");
7870 emitcode ("lcall", "__gptrget");
7874 /* if we have bitdisplacement then it fits */
7875 /* into this byte completely or if length is */
7876 /* less than a byte */
7877 if ((shCnt = SPEC_BSTR (etype)) ||
7878 (SPEC_BLEN (etype) <= 8))
7881 /* shift right acc */
7884 emitcode ("anl", "a,#0x%02x",
7885 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7886 aopPut (AOP (result), "a", offset);
7890 /* bit field did not fit in a byte */
7891 rlen = SPEC_BLEN (etype) - 8;
7892 aopPut (AOP (result), "a", offset++);
7901 emitcode ("inc", "%s", rname);
7902 emitcode ("mov", "a,@%s", rname);
7906 emitcode ("inc", "%s", rname);
7907 emitcode ("movx", "a,@%s", rname);
7911 emitcode ("inc", "dptr");
7912 emitcode ("movx", "a,@dptr");
7916 emitcode ("clr", "a");
7917 emitcode ("inc", "dptr");
7918 emitcode ("movc", "a", "@a+dptr");
7922 emitcode ("inc", "dptr");
7923 emitcode ("lcall", "__gptrget");
7928 /* if we are done */
7932 aopPut (AOP (result), "a", offset++);
7938 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7939 aopPut (AOP (result), "a", offset);
7946 /*-----------------------------------------------------------------*/
7947 /* genDataPointerGet - generates code when ptr offset is known */
7948 /*-----------------------------------------------------------------*/
7950 genDataPointerGet (operand * left,
7956 int size, offset = 0;
7957 aopOp (result, ic, TRUE, FALSE);
7959 /* get the string representation of the name */
7960 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7961 size = AOP_SIZE (result);
7962 _startLazyDPSEvaluation ();
7966 sprintf (buffer, "(%s + %d)", l + 1, offset);
7968 sprintf (buffer, "%s", l + 1);
7969 aopPut (AOP (result), buffer, offset++);
7971 _endLazyDPSEvaluation ();
7973 freeAsmop (left, NULL, ic, TRUE);
7974 freeAsmop (result, NULL, ic, TRUE);
7977 /*-----------------------------------------------------------------*/
7978 /* genNearPointerGet - emitcode for near pointer fetch */
7979 /*-----------------------------------------------------------------*/
7981 genNearPointerGet (operand * left,
7988 sym_link *rtype, *retype, *letype;
7989 sym_link *ltype = operandType (left);
7992 rtype = operandType (result);
7993 retype = getSpec (rtype);
7994 letype = getSpec (ltype);
7996 aopOp (left, ic, FALSE, FALSE);
7998 /* if left is rematerialisable and
7999 result is not bit variable type and
8000 the left is pointer to data space i.e
8001 lower 128 bytes of space */
8002 if (AOP_TYPE (left) == AOP_IMMD &&
8003 !IS_BITVAR (retype) &&
8004 !IS_BITVAR (letype) &&
8005 DCL_TYPE (ltype) == POINTER)
8007 genDataPointerGet (left, result, ic);
8011 /* if the value is already in a pointer register
8012 then don't need anything more */
8013 if (!AOP_INPREG (AOP (left)))
8015 /* otherwise get a free pointer register */
8017 preg = getFreePtr (ic, &aop, FALSE);
8018 emitcode ("mov", "%s,%s",
8020 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8024 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8026 freeAsmop (left, NULL, ic, TRUE);
8027 aopOp (result, ic, FALSE, FALSE);
8029 /* if bitfield then unpack the bits */
8030 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8031 genUnpackBits (result, rname, POINTER);
8034 /* we have can just get the values */
8035 int size = AOP_SIZE (result);
8040 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8043 emitcode ("mov", "a,@%s", rname);
8044 aopPut (AOP (result), "a", offset);
8048 sprintf (buffer, "@%s", rname);
8049 aopPut (AOP (result), buffer, offset);
8053 emitcode ("inc", "%s", rname);
8057 /* now some housekeeping stuff */
8060 /* we had to allocate for this iCode */
8061 freeAsmop (NULL, aop, ic, TRUE);
8065 /* we did not allocate which means left
8066 already in a pointer register, then
8067 if size > 0 && this could be used again
8068 we have to point it back to where it
8070 if (AOP_SIZE (result) > 1 &&
8071 !OP_SYMBOL (left)->remat &&
8072 (OP_SYMBOL (left)->liveTo > ic->seq ||
8075 int size = AOP_SIZE (result) - 1;
8077 emitcode ("dec", "%s", rname);
8082 freeAsmop (result, NULL, ic, TRUE);
8086 /*-----------------------------------------------------------------*/
8087 /* genPagedPointerGet - emitcode for paged pointer fetch */
8088 /*-----------------------------------------------------------------*/
8090 genPagedPointerGet (operand * left,
8097 sym_link *rtype, *retype, *letype;
8099 rtype = operandType (result);
8100 retype = getSpec (rtype);
8101 letype = getSpec (operandType (left));
8102 aopOp (left, ic, FALSE, FALSE);
8104 /* if the value is already in a pointer register
8105 then don't need anything more */
8106 if (!AOP_INPREG (AOP (left)))
8108 /* otherwise get a free pointer register */
8110 preg = getFreePtr (ic, &aop, FALSE);
8111 emitcode ("mov", "%s,%s",
8113 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8117 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8119 freeAsmop (left, NULL, ic, TRUE);
8120 aopOp (result, ic, FALSE, FALSE);
8122 /* if bitfield then unpack the bits */
8123 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8124 genUnpackBits (result, rname, PPOINTER);
8127 /* we have can just get the values */
8128 int size = AOP_SIZE (result);
8134 emitcode ("movx", "a,@%s", rname);
8135 aopPut (AOP (result), "a", offset);
8140 emitcode ("inc", "%s", rname);
8144 /* now some housekeeping stuff */
8147 /* we had to allocate for this iCode */
8148 freeAsmop (NULL, aop, ic, TRUE);
8152 /* we did not allocate which means left
8153 already in a pointer register, then
8154 if size > 0 && this could be used again
8155 we have to point it back to where it
8157 if (AOP_SIZE (result) > 1 &&
8158 !OP_SYMBOL (left)->remat &&
8159 (OP_SYMBOL (left)->liveTo > ic->seq ||
8162 int size = AOP_SIZE (result) - 1;
8164 emitcode ("dec", "%s", rname);
8169 freeAsmop (result, NULL, ic, TRUE);
8174 /*-----------------------------------------------------------------*/
8175 /* genFarPointerGet - gget value from far space */
8176 /*-----------------------------------------------------------------*/
8178 genFarPointerGet (operand * left,
8179 operand * result, iCode * ic)
8182 sym_link *retype = getSpec (operandType (result));
8183 sym_link *letype = getSpec (operandType (left));
8184 D (emitcode (";", "genFarPointerGet");
8187 aopOp (left, ic, FALSE, FALSE);
8189 /* if the operand is already in dptr
8190 then we do nothing else we move the value to dptr */
8191 if (AOP_TYPE (left) != AOP_STR)
8193 /* if this is remateriazable */
8194 if (AOP_TYPE (left) == AOP_IMMD)
8196 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8200 /* we need to get it byte by byte */
8201 _startLazyDPSEvaluation ();
8202 if (AOP_TYPE (left) != AOP_DPTR)
8204 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8205 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8206 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8210 /* We need to generate a load to DPTR indirect through DPTR. */
8211 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8213 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8214 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8215 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8216 emitcode ("pop", "dph");
8217 emitcode ("pop", "dpl");
8219 _endLazyDPSEvaluation ();
8222 /* so dptr know contains the address */
8223 freeAsmop (left, NULL, ic, TRUE);
8224 aopOp (result, ic, FALSE, TRUE);
8226 /* if bit then unpack */
8227 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8228 genUnpackBits (result, "dptr", FPOINTER);
8231 size = AOP_SIZE (result);
8234 _startLazyDPSEvaluation ();
8241 emitcode ("movx", "a,@dptr");
8243 emitcode ("inc", "dptr");
8245 aopPut (AOP (result), "a", offset++);
8247 _endLazyDPSEvaluation ();
8250 freeAsmop (result, NULL, ic, TRUE);
8253 /*-----------------------------------------------------------------*/
8254 /* emitcodePointerGet - gget value from code space */
8255 /*-----------------------------------------------------------------*/
8257 emitcodePointerGet (operand * left,
8258 operand * result, iCode * ic)
8261 sym_link *retype = getSpec (operandType (result));
8263 aopOp (left, ic, FALSE, FALSE);
8265 /* if the operand is already in dptr
8266 then we do nothing else we move the value to dptr */
8267 if (AOP_TYPE (left) != AOP_STR)
8269 /* if this is remateriazable */
8270 if (AOP_TYPE (left) == AOP_IMMD)
8272 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8275 { /* we need to get it byte by byte */
8276 _startLazyDPSEvaluation ();
8277 if (AOP_TYPE (left) != AOP_DPTR)
8279 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8280 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8281 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8285 /* We need to generate a load to DPTR indirect through DPTR. */
8286 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8288 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8289 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8290 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8291 emitcode ("pop", "dph");
8292 emitcode ("pop", "dpl");
8294 _endLazyDPSEvaluation ();
8297 /* so dptr know contains the address */
8298 freeAsmop (left, NULL, ic, TRUE);
8299 aopOp (result, ic, FALSE, TRUE);
8301 /* if bit then unpack */
8302 if (IS_BITVAR (retype))
8303 genUnpackBits (result, "dptr", CPOINTER);
8306 size = AOP_SIZE (result);
8309 _startLazyDPSEvaluation ();
8315 emitcode ("clr", "a");
8316 emitcode ("movc", "a,@a+dptr");
8318 emitcode ("inc", "dptr");
8319 aopPut (AOP (result), "a", offset++);
8321 _endLazyDPSEvaluation ();
8324 freeAsmop (result, NULL, ic, TRUE);
8327 /*-----------------------------------------------------------------*/
8328 /* genGenPointerGet - gget value from generic pointer space */
8329 /*-----------------------------------------------------------------*/
8331 genGenPointerGet (operand * left,
8332 operand * result, iCode * ic)
8335 sym_link *retype = getSpec (operandType (result));
8336 sym_link *letype = getSpec (operandType (left));
8338 D (emitcode (";", "genGenPointerGet "); );
8340 aopOp (left, ic, FALSE, TRUE);
8342 /* if the operand is already in dptr
8343 then we do nothing else we move the value to dptr */
8344 if (AOP_TYPE (left) != AOP_STR)
8346 /* if this is remateriazable */
8347 if (AOP_TYPE (left) == AOP_IMMD)
8349 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8350 emitcode ("mov", "b,#%d", pointerCode (retype));
8353 { /* we need to get it byte by byte */
8354 _startLazyDPSEvaluation ();
8355 if (AOP(left)->type==AOP_DPTR2) {
8357 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8360 emitcode ("mov", "dpl,%s", l);
8361 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8364 emitcode ("mov", "dph,%s", l);
8365 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8368 emitcode ("mov", "dpx,%s", l);
8369 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8371 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8372 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8373 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8374 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8376 _endLazyDPSEvaluation ();
8379 /* so dptr know contains the address */
8380 freeAsmop (left, NULL, ic, TRUE);
8381 aopOp (result, ic, FALSE, TRUE);
8383 /* if bit then unpack */
8384 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8385 genUnpackBits (result, "dptr", GPOINTER);
8388 size = AOP_SIZE (result);
8393 emitcode ("lcall", "__gptrget");
8394 aopPut (AOP (result), "a", offset++);
8396 emitcode ("inc", "dptr");
8400 freeAsmop (result, NULL, ic, TRUE);
8403 /*-----------------------------------------------------------------*/
8404 /* genPointerGet - generate code for pointer get */
8405 /*-----------------------------------------------------------------*/
8407 genPointerGet (iCode * ic)
8409 operand *left, *result;
8410 sym_link *type, *etype;
8413 D (emitcode (";", "genPointerGet ");
8416 left = IC_LEFT (ic);
8417 result = IC_RESULT (ic);
8419 /* depending on the type of pointer we need to
8420 move it to the correct pointer register */
8421 type = operandType (left);
8422 etype = getSpec (type);
8423 /* if left is of type of pointer then it is simple */
8424 if (IS_PTR (type) && !IS_FUNC (type->next))
8425 p_type = DCL_TYPE (type);
8428 /* we have to go by the storage class */
8429 p_type = PTR_TYPE (SPEC_OCLS (etype));
8432 /* now that we have the pointer type we assign
8433 the pointer values */
8439 genNearPointerGet (left, result, ic);
8443 genPagedPointerGet (left, result, ic);
8447 genFarPointerGet (left, result, ic);
8451 emitcodePointerGet (left, result, ic);
8455 genGenPointerGet (left, result, ic);
8461 /*-----------------------------------------------------------------*/
8462 /* genPackBits - generates code for packed bit storage */
8463 /*-----------------------------------------------------------------*/
8465 genPackBits (sym_link * etype,
8467 char *rname, int p_type)
8475 blen = SPEC_BLEN (etype);
8476 bstr = SPEC_BSTR (etype);
8478 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8481 /* if the bit lenth is less than or */
8482 /* it exactly fits a byte then */
8483 if (SPEC_BLEN (etype) <= 8)
8485 shCount = SPEC_BSTR (etype);
8487 /* shift left acc */
8490 if (SPEC_BLEN (etype) < 8)
8491 { /* if smaller than a byte */
8497 emitcode ("mov", "b,a");
8498 emitcode ("mov", "a,@%s", rname);
8502 emitcode ("mov", "b,a");
8503 emitcode ("movx", "a,@dptr");
8507 emitcode ("push", "b");
8508 emitcode ("push", "acc");
8509 emitcode ("lcall", "__gptrget");
8510 emitcode ("pop", "b");
8514 emitcode ("anl", "a,#0x%02x", (unsigned char)
8515 ((unsigned char) (0xFF << (blen + bstr)) |
8516 (unsigned char) (0xFF >> (8 - bstr))));
8517 emitcode ("orl", "a,b");
8518 if (p_type == GPOINTER)
8519 emitcode ("pop", "b");
8526 emitcode ("mov", "@%s,a", rname);
8530 emitcode ("movx", "@dptr,a");
8534 emitcode ("lcall", "__gptrput");
8539 if (SPEC_BLEN (etype) <= 8)
8542 emitcode ("inc", "%s", rname);
8543 rLen = SPEC_BLEN (etype);
8545 /* now generate for lengths greater than one byte */
8549 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8561 emitcode ("mov", "@%s,a", rname);
8564 emitcode ("mov", "@%s,%s", rname, l);
8569 emitcode ("movx", "@dptr,a");
8574 emitcode ("lcall", "__gptrput");
8577 emitcode ("inc", "%s", rname);
8582 /* last last was not complete */
8585 /* save the byte & read byte */
8589 emitcode ("mov", "b,a");
8590 emitcode ("mov", "a,@%s", rname);
8594 emitcode ("mov", "b,a");
8595 emitcode ("movx", "a,@dptr");
8599 emitcode ("push", "b");
8600 emitcode ("push", "acc");
8601 emitcode ("lcall", "__gptrget");
8602 emitcode ("pop", "b");
8606 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8607 emitcode ("orl", "a,b");
8610 if (p_type == GPOINTER)
8611 emitcode ("pop", "b");
8617 emitcode ("mov", "@%s,a", rname);
8621 emitcode ("movx", "@dptr,a");
8625 emitcode ("lcall", "__gptrput");
8629 /*-----------------------------------------------------------------*/
8630 /* genDataPointerSet - remat pointer to data space */
8631 /*-----------------------------------------------------------------*/
8633 genDataPointerSet (operand * right,
8637 int size, offset = 0;
8638 char *l, buffer[256];
8640 aopOp (right, ic, FALSE, FALSE);
8642 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8643 size = AOP_SIZE (right);
8647 sprintf (buffer, "(%s + %d)", l + 1, offset);
8649 sprintf (buffer, "%s", l + 1);
8650 emitcode ("mov", "%s,%s", buffer,
8651 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8654 freeAsmop (right, NULL, ic, TRUE);
8655 freeAsmop (result, NULL, ic, TRUE);
8658 /*-----------------------------------------------------------------*/
8659 /* genNearPointerSet - emitcode for near pointer put */
8660 /*-----------------------------------------------------------------*/
8662 genNearPointerSet (operand * right,
8669 sym_link *retype, *letype;
8670 sym_link *ptype = operandType (result);
8672 retype = getSpec (operandType (right));
8673 letype = getSpec (ptype);
8675 aopOp (result, ic, FALSE, FALSE);
8677 /* if the result is rematerializable &
8678 in data space & not a bit variable */
8679 if (AOP_TYPE (result) == AOP_IMMD &&
8680 DCL_TYPE (ptype) == POINTER &&
8681 !IS_BITVAR (retype) &&
8682 !IS_BITVAR (letype))
8684 genDataPointerSet (right, result, ic);
8688 /* if the value is already in a pointer register
8689 then don't need anything more */
8690 if (!AOP_INPREG (AOP (result)))
8692 /* otherwise get a free pointer register */
8694 preg = getFreePtr (ic, &aop, FALSE);
8695 emitcode ("mov", "%s,%s",
8697 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8701 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8703 freeAsmop (result, NULL, ic, TRUE);
8704 aopOp (right, ic, FALSE, FALSE);
8706 /* if bitfield then unpack the bits */
8707 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8708 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8711 /* we have can just get the values */
8712 int size = AOP_SIZE (right);
8717 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8721 emitcode ("mov", "@%s,a", rname);
8724 emitcode ("mov", "@%s,%s", rname, l);
8726 emitcode ("inc", "%s", rname);
8731 /* now some housekeeping stuff */
8734 /* we had to allocate for this iCode */
8735 freeAsmop (NULL, aop, ic, TRUE);
8739 /* we did not allocate which means left
8740 already in a pointer register, then
8741 if size > 0 && this could be used again
8742 we have to point it back to where it
8744 if (AOP_SIZE (right) > 1 &&
8745 !OP_SYMBOL (result)->remat &&
8746 (OP_SYMBOL (result)->liveTo > ic->seq ||
8749 int size = AOP_SIZE (right) - 1;
8751 emitcode ("dec", "%s", rname);
8756 freeAsmop (right, NULL, ic, TRUE);
8761 /*-----------------------------------------------------------------*/
8762 /* genPagedPointerSet - emitcode for Paged pointer put */
8763 /*-----------------------------------------------------------------*/
8765 genPagedPointerSet (operand * right,
8772 sym_link *retype, *letype;
8774 retype = getSpec (operandType (right));
8775 letype = getSpec (operandType (result));
8777 aopOp (result, ic, FALSE, FALSE);
8779 /* if the value is already in a pointer register
8780 then don't need anything more */
8781 if (!AOP_INPREG (AOP (result)))
8783 /* otherwise get a free pointer register */
8785 preg = getFreePtr (ic, &aop, FALSE);
8786 emitcode ("mov", "%s,%s",
8788 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8792 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8794 freeAsmop (result, NULL, ic, TRUE);
8795 aopOp (right, ic, FALSE, FALSE);
8797 /* if bitfield then unpack the bits */
8798 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8799 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8802 /* we have can just get the values */
8803 int size = AOP_SIZE (right);
8808 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8811 emitcode ("movx", "@%s,a", rname);
8814 emitcode ("inc", "%s", rname);
8820 /* now some housekeeping stuff */
8823 /* we had to allocate for this iCode */
8824 freeAsmop (NULL, aop, ic, TRUE);
8828 /* we did not allocate which means left
8829 already in a pointer register, then
8830 if size > 0 && this could be used again
8831 we have to point it back to where it
8833 if (AOP_SIZE (right) > 1 &&
8834 !OP_SYMBOL (result)->remat &&
8835 (OP_SYMBOL (result)->liveTo > ic->seq ||
8838 int size = AOP_SIZE (right) - 1;
8840 emitcode ("dec", "%s", rname);
8845 freeAsmop (right, NULL, ic, TRUE);
8850 /*-----------------------------------------------------------------*/
8851 /* genFarPointerSet - set value from far space */
8852 /*-----------------------------------------------------------------*/
8854 genFarPointerSet (operand * right,
8855 operand * result, iCode * ic)
8858 sym_link *retype = getSpec (operandType (right));
8859 sym_link *letype = getSpec (operandType (result));
8861 aopOp (result, ic, FALSE, FALSE);
8863 /* if the operand is already in dptr
8864 then we do nothing else we move the value to dptr */
8865 if (AOP_TYPE (result) != AOP_STR)
8867 /* if this is remateriazable */
8868 if (AOP_TYPE (result) == AOP_IMMD)
8869 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8872 /* we need to get it byte by byte */
8873 _startLazyDPSEvaluation ();
8874 if (AOP_TYPE (result) != AOP_DPTR)
8876 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8877 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8878 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8882 /* We need to generate a load to DPTR indirect through DPTR. */
8883 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8885 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8886 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8887 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8888 emitcode ("pop", "dph");
8889 emitcode ("pop", "dpl");
8891 _endLazyDPSEvaluation ();
8894 /* so dptr know contains the address */
8895 freeAsmop (result, NULL, ic, TRUE);
8896 aopOp (right, ic, FALSE, TRUE);
8898 /* if bit then unpack */
8899 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8900 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8903 size = AOP_SIZE (right);
8906 _startLazyDPSEvaluation ();
8909 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8915 emitcode ("movx", "@dptr,a");
8917 emitcode ("inc", "dptr");
8919 _endLazyDPSEvaluation ();
8922 freeAsmop (right, NULL, ic, TRUE);
8925 /*-----------------------------------------------------------------*/
8926 /* genGenPointerSet - set value from generic pointer space */
8927 /*-----------------------------------------------------------------*/
8929 genGenPointerSet (operand * right,
8930 operand * result, iCode * ic)
8933 sym_link *retype = getSpec (operandType (right));
8934 sym_link *letype = getSpec (operandType (result));
8936 aopOp (result, ic, FALSE, TRUE);
8938 /* if the operand is already in dptr
8939 then we do nothing else we move the value to dptr */
8940 if (AOP_TYPE (result) != AOP_STR)
8942 _startLazyDPSEvaluation ();
8943 /* if this is remateriazable */
8944 if (AOP_TYPE (result) == AOP_IMMD)
8946 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8947 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8950 { /* we need to get it byte by byte */
8951 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8952 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8953 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8954 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8956 _endLazyDPSEvaluation ();
8958 /* so dptr know contains the address */
8959 freeAsmop (result, NULL, ic, TRUE);
8960 aopOp (right, ic, FALSE, TRUE);
8962 /* if bit then unpack */
8963 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8964 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8967 size = AOP_SIZE (right);
8970 _startLazyDPSEvaluation ();
8973 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8979 emitcode ("lcall", "__gptrput");
8981 emitcode ("inc", "dptr");
8983 _endLazyDPSEvaluation ();
8986 freeAsmop (right, NULL, ic, TRUE);
8989 /*-----------------------------------------------------------------*/
8990 /* genPointerSet - stores the value into a pointer location */
8991 /*-----------------------------------------------------------------*/
8993 genPointerSet (iCode * ic)
8995 operand *right, *result;
8996 sym_link *type, *etype;
8999 D (emitcode (";", "genPointerSet ");
9002 right = IC_RIGHT (ic);
9003 result = IC_RESULT (ic);
9005 /* depending on the type of pointer we need to
9006 move it to the correct pointer register */
9007 type = operandType (result);
9008 etype = getSpec (type);
9009 /* if left is of type of pointer then it is simple */
9010 if (IS_PTR (type) && !IS_FUNC (type->next))
9012 p_type = DCL_TYPE (type);
9016 /* we have to go by the storage class */
9017 p_type = PTR_TYPE (SPEC_OCLS (etype));
9020 /* now that we have the pointer type we assign
9021 the pointer values */
9027 genNearPointerSet (right, result, ic);
9031 genPagedPointerSet (right, result, ic);
9035 genFarPointerSet (right, result, ic);
9039 genGenPointerSet (right, result, ic);
9045 /*-----------------------------------------------------------------*/
9046 /* genIfx - generate code for Ifx statement */
9047 /*-----------------------------------------------------------------*/
9049 genIfx (iCode * ic, iCode * popIc)
9051 operand *cond = IC_COND (ic);
9054 D (emitcode (";", "genIfx "););
9056 aopOp (cond, ic, FALSE, FALSE);
9058 /* get the value into acc */
9059 if (AOP_TYPE (cond) != AOP_CRY)
9063 /* the result is now in the accumulator */
9064 freeAsmop (cond, NULL, ic, TRUE);
9066 /* if there was something to be popped then do it */
9070 /* if the condition is a bit variable */
9071 if (isbit && IS_ITEMP (cond) &&
9073 genIfxJump (ic, SPIL_LOC (cond)->rname);
9074 else if (isbit && !IS_ITEMP (cond))
9075 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9077 genIfxJump (ic, "a");
9082 /*-----------------------------------------------------------------*/
9083 /* genAddrOf - generates code for address of */
9084 /*-----------------------------------------------------------------*/
9086 genAddrOf (iCode * ic)
9088 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9091 D (emitcode (";", "genAddrOf ");
9094 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9096 /* if the operand is on the stack then we
9097 need to get the stack offset of this
9101 /* if it has an offset then we need to compute
9105 emitcode ("mov", "a,_bp");
9106 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9107 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9111 /* we can just move _bp */
9112 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9114 /* fill the result with zero */
9115 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9118 if (options.stack10bit && size < (FPTRSIZE - 1))
9121 "*** warning: pointer to stack var truncated.\n");
9128 if (options.stack10bit && offset == 2)
9130 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9134 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9141 /* object not on stack then we need the name */
9142 size = AOP_SIZE (IC_RESULT (ic));
9147 char s[SDCC_NAME_MAX];
9149 sprintf (s, "#(%s >> %d)",
9153 sprintf (s, "#%s", sym->rname);
9154 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9158 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9162 /*-----------------------------------------------------------------*/
9163 /* genFarFarAssign - assignment when both are in far space */
9164 /*-----------------------------------------------------------------*/
9166 genFarFarAssign (operand * result, operand * right, iCode * ic)
9168 int size = AOP_SIZE (right);
9170 symbol *rSym = NULL;
9174 /* quick & easy case. */
9175 D(emitcode(";","genFarFarAssign (1 byte case)"););
9176 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9177 freeAsmop (right, NULL, ic, FALSE);
9178 /* now assign DPTR to result */
9180 aopOp(result, ic, FALSE, FALSE);
9182 aopPut(AOP(result), "a", 0);
9183 freeAsmop(result, NULL, ic, FALSE);
9187 /* See if we've got an underlying symbol to abuse. */
9188 if (IS_SYMOP(result) && OP_SYMBOL(result))
9190 if (IS_TRUE_SYMOP(result))
9192 rSym = OP_SYMBOL(result);
9194 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9196 rSym = OP_SYMBOL(result)->usl.spillLoc;
9200 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9202 /* We can use the '390 auto-toggle feature to good effect here. */
9204 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9205 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9206 emitcode ("mov", "dptr,#%s", rSym->rname);
9207 /* DP2 = result, DP1 = right, DP1 is current. */
9210 emitcode("movx", "a,@dptr");
9211 emitcode("movx", "@dptr,a");
9214 emitcode("inc", "dptr");
9215 emitcode("inc", "dptr");
9218 emitcode("mov", "dps, #0");
9219 freeAsmop (right, NULL, ic, FALSE);
9223 D (emitcode (";", "genFarFarAssign"););
9224 aopOp (result, ic, TRUE, TRUE);
9226 _startLazyDPSEvaluation ();
9230 aopPut (AOP (result),
9231 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9234 _endLazyDPSEvaluation ();
9235 freeAsmop (result, NULL, ic, FALSE);
9236 freeAsmop (right, NULL, ic, FALSE);
9240 /*-----------------------------------------------------------------*/
9241 /* genAssign - generate code for assignment */
9242 /*-----------------------------------------------------------------*/
9244 genAssign (iCode * ic)
9246 operand *result, *right;
9248 unsigned long lit = 0L;
9250 D (emitcode (";", "genAssign ");
9253 result = IC_RESULT (ic);
9254 right = IC_RIGHT (ic);
9256 /* if they are the same */
9257 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9260 aopOp (right, ic, FALSE, FALSE);
9262 emitcode (";", "genAssign: resultIsFar = %s",
9263 isOperandInFarSpace (result) ?
9266 /* special case both in far space */
9267 if ((AOP_TYPE (right) == AOP_DPTR ||
9268 AOP_TYPE (right) == AOP_DPTR2) &&
9269 /* IS_TRUE_SYMOP(result) && */
9270 isOperandInFarSpace (result))
9272 genFarFarAssign (result, right, ic);
9276 aopOp (result, ic, TRUE, FALSE);
9278 /* if they are the same registers */
9279 if (sameRegs (AOP (right), AOP (result)))
9282 /* if the result is a bit */
9283 if (AOP_TYPE (result) == AOP_CRY)
9286 /* if the right size is a literal then
9287 we know what the value is */
9288 if (AOP_TYPE (right) == AOP_LIT)
9290 if (((int) operandLitValue (right)))
9291 aopPut (AOP (result), one, 0);
9293 aopPut (AOP (result), zero, 0);
9297 /* the right is also a bit variable */
9298 if (AOP_TYPE (right) == AOP_CRY)
9300 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9301 aopPut (AOP (result), "c", 0);
9307 aopPut (AOP (result), "a", 0);
9311 /* bit variables done */
9313 size = AOP_SIZE (result);
9315 if (AOP_TYPE (right) == AOP_LIT)
9316 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9319 (AOP_TYPE (result) != AOP_REG) &&
9320 (AOP_TYPE (right) == AOP_LIT) &&
9321 !IS_FLOAT (operandType (right)))
9323 _startLazyDPSEvaluation ();
9324 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9326 aopPut (AOP (result),
9327 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9332 /* And now fill the rest with zeros. */
9335 emitcode ("clr", "a");
9339 aopPut (AOP (result), "a", offset++);
9341 _endLazyDPSEvaluation ();
9345 _startLazyDPSEvaluation ();
9348 aopPut (AOP (result),
9349 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9353 _endLazyDPSEvaluation ();
9357 freeAsmop (right, NULL, ic, FALSE);
9358 freeAsmop (result, NULL, ic, TRUE);
9361 /*-----------------------------------------------------------------*/
9362 /* genJumpTab - generates code for jump table */
9363 /*-----------------------------------------------------------------*/
9365 genJumpTab (iCode * ic)
9370 D (emitcode (";", "genJumpTab ");
9373 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9374 /* get the condition into accumulator */
9375 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9377 /* multiply by four! */
9378 emitcode ("add", "a,acc");
9379 emitcode ("add", "a,acc");
9380 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9382 jtab = newiTempLabel (NULL);
9383 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9384 emitcode ("jmp", "@a+dptr");
9385 emitcode ("", "%05d$:", jtab->key + 100);
9386 /* now generate the jump labels */
9387 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9388 jtab = setNextItem (IC_JTLABELS (ic)))
9389 emitcode ("ljmp", "%05d$", jtab->key + 100);
9393 /*-----------------------------------------------------------------*/
9394 /* genCast - gen code for casting */
9395 /*-----------------------------------------------------------------*/
9397 genCast (iCode * ic)
9399 operand *result = IC_RESULT (ic);
9400 sym_link *ctype = operandType (IC_LEFT (ic));
9401 sym_link *rtype = operandType (IC_RIGHT (ic));
9402 operand *right = IC_RIGHT (ic);
9405 D (emitcode (";", "genCast ");
9408 /* if they are equivalent then do nothing */
9409 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9412 aopOp (right, ic, FALSE, FALSE);
9413 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9415 /* if the result is a bit */
9416 if (AOP_TYPE (result) == AOP_CRY)
9418 /* if the right size is a literal then
9419 we know what the value is */
9420 if (AOP_TYPE (right) == AOP_LIT)
9422 if (((int) operandLitValue (right)))
9423 aopPut (AOP (result), one, 0);
9425 aopPut (AOP (result), zero, 0);
9430 /* the right is also a bit variable */
9431 if (AOP_TYPE (right) == AOP_CRY)
9433 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9434 aopPut (AOP (result), "c", 0);
9440 aopPut (AOP (result), "a", 0);
9444 /* if they are the same size : or less */
9445 if (AOP_SIZE (result) <= AOP_SIZE (right))
9448 /* if they are in the same place */
9449 if (sameRegs (AOP (right), AOP (result)))
9452 /* if they in different places then copy */
9453 size = AOP_SIZE (result);
9455 _startLazyDPSEvaluation ();
9458 aopPut (AOP (result),
9459 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9463 _endLazyDPSEvaluation ();
9468 /* if the result is of type pointer */
9473 sym_link *type = operandType (right);
9475 /* pointer to generic pointer */
9476 if (IS_GENPTR (ctype))
9482 p_type = DCL_TYPE (type);
9486 #if OLD_CAST_BEHAVIOR
9487 /* KV: we are converting a non-pointer type to
9488 * a generic pointer. This (ifdef'd out) code
9489 * says that the resulting generic pointer
9490 * should have the same class as the storage
9491 * location of the non-pointer variable.
9493 * For example, converting an int (which happens
9494 * to be stored in DATA space) to a pointer results
9495 * in a DATA generic pointer; if the original int
9496 * in XDATA space, so will be the resulting pointer.
9498 * I don't like that behavior, and thus this change:
9499 * all such conversions will be forced to XDATA and
9500 * throw a warning. If you want some non-XDATA
9501 * type, or you want to suppress the warning, you
9502 * must go through an intermediate cast, like so:
9504 * char _generic *gp = (char _xdata *)(intVar);
9506 sym_link *etype = getSpec (type);
9508 /* we have to go by the storage class */
9509 if (SPEC_OCLS (etype) != generic)
9511 p_type = PTR_TYPE (SPEC_OCLS (etype));
9516 /* Converting unknown class (i.e. register variable)
9517 * to generic pointer. This is not good, but
9518 * we'll make a guess (and throw a warning).
9521 werror (W_INT_TO_GEN_PTR_CAST);
9525 /* the first two bytes are known */
9526 size = GPTRSIZE - 1;
9528 _startLazyDPSEvaluation ();
9531 aopPut (AOP (result),
9532 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9536 _endLazyDPSEvaluation ();
9538 /* the last byte depending on type */
9556 /* this should never happen */
9557 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9558 "got unknown pointer type");
9561 aopPut (AOP (result), l, GPTRSIZE - 1);
9565 /* just copy the pointers */
9566 size = AOP_SIZE (result);
9568 _startLazyDPSEvaluation ();
9571 aopPut (AOP (result),
9572 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9576 _endLazyDPSEvaluation ();
9580 /* so we now know that the size of destination is greater
9581 than the size of the source */
9582 /* we move to result for the size of source */
9583 size = AOP_SIZE (right);
9585 _startLazyDPSEvaluation ();
9588 aopPut (AOP (result),
9589 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9593 _endLazyDPSEvaluation ();
9595 /* now depending on the sign of the source && destination */
9596 size = AOP_SIZE (result) - AOP_SIZE (right);
9597 /* if unsigned or not an integral type */
9598 /* also, if the source is a bit, we don't need to sign extend, because
9599 * it can't possibly have set the sign bit.
9601 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9605 aopPut (AOP (result), zero, offset++);
9610 /* we need to extend the sign :{ */
9611 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9612 FALSE, FALSE, TRUE);
9614 emitcode ("rlc", "a");
9615 emitcode ("subb", "a,acc");
9617 aopPut (AOP (result), "a", offset++);
9620 /* we are done hurray !!!! */
9623 freeAsmop (right, NULL, ic, TRUE);
9624 freeAsmop (result, NULL, ic, TRUE);
9628 /*-----------------------------------------------------------------*/
9629 /* genDjnz - generate decrement & jump if not zero instrucion */
9630 /*-----------------------------------------------------------------*/
9632 genDjnz (iCode * ic, iCode * ifx)
9638 /* if the if condition has a false label
9639 then we cannot save */
9643 /* if the minus is not of the form
9645 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9646 !IS_OP_LITERAL (IC_RIGHT (ic)))
9649 if (operandLitValue (IC_RIGHT (ic)) != 1)
9652 /* if the size of this greater than one then no
9654 if (getSize (operandType (IC_RESULT (ic))) > 1)
9657 /* otherwise we can save BIG */
9658 D(emitcode(";", "genDjnz"););
9660 lbl = newiTempLabel (NULL);
9661 lbl1 = newiTempLabel (NULL);
9663 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9665 if (AOP_NEEDSACC(IC_RESULT(ic)))
9667 /* If the result is accessed indirectly via
9668 * the accumulator, we must explicitly write
9669 * it back after the decrement.
9671 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9673 if (strcmp(rByte, "a"))
9675 /* Something is hopelessly wrong */
9676 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9677 __FILE__, __LINE__);
9678 /* We can just give up; the generated code will be inefficient,
9681 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9684 emitcode ("dec", "%s", rByte);
9685 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9686 emitcode ("jnz", "%05d$", lbl->key + 100);
9688 else if (IS_AOP_PREG (IC_RESULT (ic)))
9690 emitcode ("dec", "%s",
9691 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9692 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9693 emitcode ("jnz", "%05d$", lbl->key + 100);
9697 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9700 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9701 emitcode ("", "%05d$:", lbl->key + 100);
9702 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9703 emitcode ("", "%05d$:", lbl1->key + 100);
9705 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9710 /*-----------------------------------------------------------------*/
9711 /* genReceive - generate code for a receive iCode */
9712 /*-----------------------------------------------------------------*/
9714 genReceive (iCode * ic)
9717 D (emitcode (";", "genReceive ");
9720 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9721 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9722 IS_TRUE_SYMOP (IC_RESULT (ic))))
9724 int size = getSize (operandType (IC_RESULT (ic)));
9725 int offset = fReturnSizeDS390 - size;
9728 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9729 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9732 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9733 size = AOP_SIZE (IC_RESULT (ic));
9737 emitcode ("pop", "acc");
9738 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9745 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9747 assignResultValue (IC_RESULT (ic));
9750 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9753 /*-----------------------------------------------------------------*/
9754 /* gen390Code - generate code for Dallas 390 based controllers */
9755 /*-----------------------------------------------------------------*/
9757 gen390Code (iCode * lic)
9762 lineHead = lineCurr = NULL;
9766 /* print the allocation information */
9768 printAllocInfo (currFunc, codeOutFile);
9770 /* if debug information required */
9771 if (options.debug && currFunc)
9773 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9775 if (IS_STATIC (currFunc->etype))
9776 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9778 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9781 /* stack pointer name */
9782 if (options.useXstack)
9788 for (ic = lic; ic; ic = ic->next)
9791 if (cln != ic->lineno)
9796 emitcode ("", "C$%s$%d$%d$%d ==.",
9797 FileBaseName (ic->filename), ic->lineno,
9798 ic->level, ic->block);
9801 emitcode (";", "%s %d", ic->filename, ic->lineno);
9804 /* if the result is marked as
9805 spilt and rematerializable or code for
9806 this has already been generated then
9808 if (resultRemat (ic) || ic->generated)
9811 /* depending on the operation */
9831 /* IPOP happens only when trying to restore a
9832 spilt live range, if there is an ifx statement
9833 following this pop then the if statement might
9834 be using some of the registers being popped which
9835 would destory the contents of the register so
9836 we need to check for this condition and handle it */
9838 ic->next->op == IFX &&
9839 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9840 genIfx (ic->next, ic);
9858 genEndFunction (ic);
9878 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9895 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9899 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9906 /* note these two are xlated by algebraic equivalence
9907 during parsing SDCC.y */
9908 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9909 "got '>=' or '<=' shouldn't have come here");
9913 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9925 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9929 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9933 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9960 case GET_VALUE_AT_ADDRESS:
9965 if (POINTER_SET (ic))
9992 addSet (&_G.sendSet, ic);
10001 /* now we are ready to call the
10002 peep hole optimizer */
10003 if (!options.nopeep)
10004 peepHole (&lineHead);
10006 /* now do the actual printing */
10007 printLine (lineHead, codeOutFile);