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 (SPEC_NAKED(fetype))
2541 emitcode(";", "naked function: no prologue.");
2545 /* if critical function then turn interrupts off */
2546 if (SPEC_CRTCL (fetype))
2547 emitcode ("clr", "ea");
2549 /* here we need to generate the equates for the
2550 register bank if required */
2551 if (SPEC_BANK (fetype) != rbank)
2555 rbank = SPEC_BANK (fetype);
2556 for (i = 0; i < ds390_nRegs; i++)
2558 if (strcmp (regs390[i].base, "0") == 0)
2559 emitcode ("", "%s = 0x%02x",
2561 8 * rbank + regs390[i].offset);
2563 emitcode ("", "%s = %s + 0x%02x",
2566 8 * rbank + regs390[i].offset);
2570 /* if this is an interrupt service routine then
2571 save acc, b, dpl, dph */
2572 if (IS_ISR (sym->etype))
2575 if (!inExcludeList ("acc"))
2576 emitcode ("push", "acc");
2577 if (!inExcludeList ("b"))
2578 emitcode ("push", "b");
2579 if (!inExcludeList ("dpl"))
2580 emitcode ("push", "dpl");
2581 if (!inExcludeList ("dph"))
2582 emitcode ("push", "dph");
2583 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2585 emitcode ("push", "dpx");
2586 /* Make sure we're using standard DPTR */
2587 emitcode ("push", "dps");
2588 emitcode ("mov", "dps, #0x00");
2589 if (options.stack10bit)
2591 /* This ISR could conceivably use DPTR2. Better save it. */
2592 emitcode ("push", "dpl1");
2593 emitcode ("push", "dph1");
2594 emitcode ("push", "dpx1");
2595 emitcode ("push", DP2_RESULT_REG);
2598 /* if this isr has no bank i.e. is going to
2599 run with bank 0 , then we need to save more
2601 if (!SPEC_BANK (sym->etype))
2604 /* if this function does not call any other
2605 function then we can be economical and
2606 save only those registers that are used */
2611 /* if any registers used */
2614 /* save the registers used */
2615 for (i = 0; i < sym->regsUsed->size; i++)
2617 if (bitVectBitValue (sym->regsUsed, i) ||
2618 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2619 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2626 /* this function has a function call cannot
2627 determines register usage so we will have to push the
2629 saveRBank (0, ic, FALSE);
2634 /* This ISR uses a non-zero bank.
2636 * We assume that the bank is available for our
2639 * However, if this ISR calls a function which uses some
2640 * other bank, we must save that bank entirely.
2642 unsigned long banksToSave = 0;
2647 #define MAX_REGISTER_BANKS 4
2652 for (i = ic; i; i = i->next)
2654 if (i->op == ENDFUNCTION)
2656 /* we got to the end OK. */
2664 detype = getSpec(operandType (IC_LEFT(i)));
2666 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2668 /* Mark this bank for saving. */
2669 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2671 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2675 banksToSave |= (1 << SPEC_BANK(detype));
2678 /* And note that we don't need to do it in
2686 /* This is a mess; we have no idea what
2687 * register bank the called function might
2690 * The only thing I can think of to do is
2691 * throw a warning and hope.
2693 werror(W_FUNCPTR_IN_USING_ISR);
2697 if (banksToSave && options.useXstack)
2699 /* Since we aren't passing it an ic,
2700 * saveRBank will assume r0 is available to abuse.
2702 * So switch to our (trashable) bank now, so
2703 * the caller's R0 isn't trashed.
2705 emitcode ("push", "psw");
2706 emitcode ("mov", "psw,#0x%02x",
2707 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2711 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2713 if (banksToSave & (1 << ix))
2715 saveRBank(ix, NULL, FALSE);
2719 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2724 /* if callee-save to be used for this function
2725 then save the registers being used in this function */
2726 if (sym->calleeSave)
2730 /* if any registers used */
2733 /* save the registers used */
2734 for (i = 0; i < sym->regsUsed->size; i++)
2736 if (bitVectBitValue (sym->regsUsed, i) ||
2737 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2739 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2747 /* set the register bank to the desired value */
2748 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2751 emitcode ("push", "psw");
2752 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2755 if (IS_RENT (sym->etype) || options.stackAuto)
2758 if (options.useXstack)
2760 emitcode ("mov", "r0,%s", spname);
2761 emitcode ("mov", "a,_bp");
2762 emitcode ("movx", "@r0,a");
2763 emitcode ("inc", "%s", spname);
2767 /* set up the stack */
2768 emitcode ("push", "_bp"); /* save the callers stack */
2770 emitcode ("mov", "_bp,%s", spname);
2773 /* adjust the stack for the function */
2779 werror (W_STACK_OVERFLOW, sym->name);
2781 if (i > 3 && sym->recvSize < 4)
2784 emitcode ("mov", "a,sp");
2785 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2786 emitcode ("mov", "sp,a");
2791 emitcode ("inc", "sp");
2797 emitcode ("mov", "a,_spx");
2798 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2799 emitcode ("mov", "_spx,a");
2804 /*-----------------------------------------------------------------*/
2805 /* genEndFunction - generates epilogue for functions */
2806 /*-----------------------------------------------------------------*/
2808 genEndFunction (iCode * ic)
2810 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2812 D (emitcode (";", "genEndFunction "););
2814 if (SPEC_NAKED(sym->etype))
2816 emitcode(";", "naked function: no epilogue.");
2820 if (IS_RENT (sym->etype) || options.stackAuto)
2822 emitcode ("mov", "%s,_bp", spname);
2825 /* if use external stack but some variables were
2826 added to the local stack then decrement the
2828 if (options.useXstack && sym->stack)
2830 emitcode ("mov", "a,sp");
2831 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2832 emitcode ("mov", "sp,a");
2836 if ((IS_RENT (sym->etype) || options.stackAuto))
2838 if (options.useXstack)
2840 emitcode ("mov", "r0,%s", spname);
2841 emitcode ("movx", "a,@r0");
2842 emitcode ("mov", "_bp,a");
2843 emitcode ("dec", "%s", spname);
2847 emitcode ("pop", "_bp");
2851 /* restore the register bank */
2852 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2854 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2855 || !options.useXstack)
2857 /* Special case of ISR using non-zero bank with useXstack
2860 emitcode ("pop", "psw");
2864 if (IS_ISR (sym->etype))
2867 /* now we need to restore the registers */
2868 /* if this isr has no bank i.e. is going to
2869 run with bank 0 , then we need to save more
2871 if (!SPEC_BANK (sym->etype))
2873 /* if this function does not call any other
2874 function then we can be economical and
2875 save only those registers that are used */
2880 /* if any registers used */
2883 /* save the registers used */
2884 for (i = sym->regsUsed->size; i >= 0; i--)
2886 if (bitVectBitValue (sym->regsUsed, i) ||
2887 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2888 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2895 /* this function has a function call cannot
2896 determines register usage so we will have to pop the
2898 unsaveRBank (0, ic, FALSE);
2903 /* This ISR uses a non-zero bank.
2905 * Restore any register banks saved by genFunction
2908 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2911 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2913 if (savedBanks & (1 << ix))
2915 unsaveRBank(ix, NULL, FALSE);
2919 if (options.useXstack)
2921 /* Restore bank AFTER calling unsaveRBank,
2922 * since it can trash r0.
2924 emitcode ("pop", "psw");
2928 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2930 if (options.stack10bit)
2932 emitcode ("pop", DP2_RESULT_REG);
2933 emitcode ("pop", "dpx1");
2934 emitcode ("pop", "dph1");
2935 emitcode ("pop", "dpl1");
2937 emitcode ("pop", "dps");
2938 emitcode ("pop", "dpx");
2940 if (!inExcludeList ("dph"))
2941 emitcode ("pop", "dph");
2942 if (!inExcludeList ("dpl"))
2943 emitcode ("pop", "dpl");
2944 if (!inExcludeList ("b"))
2945 emitcode ("pop", "b");
2946 if (!inExcludeList ("acc"))
2947 emitcode ("pop", "acc");
2949 if (SPEC_CRTCL (sym->etype))
2950 emitcode ("setb", "ea");
2952 /* if debug then send end of function */
2953 /* if (options.debug && currFunc) */
2957 emitcode ("", "C$%s$%d$%d$%d ==.",
2958 FileBaseName (ic->filename), currFunc->lastLine,
2959 ic->level, ic->block);
2960 if (IS_STATIC (currFunc->etype))
2961 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2963 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2967 emitcode ("reti", "");
2971 if (SPEC_CRTCL (sym->etype))
2972 emitcode ("setb", "ea");
2974 if (sym->calleeSave)
2978 /* if any registers used */
2981 /* save the registers used */
2982 for (i = sym->regsUsed->size; i >= 0; i--)
2984 if (bitVectBitValue (sym->regsUsed, i) ||
2985 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2986 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2992 /* if debug then send end of function */
2996 emitcode ("", "C$%s$%d$%d$%d ==.",
2997 FileBaseName (ic->filename), currFunc->lastLine,
2998 ic->level, ic->block);
2999 if (IS_STATIC (currFunc->etype))
3000 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3002 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3006 emitcode ("ret", "");
3011 /*-----------------------------------------------------------------*/
3012 /* genRet - generate code for return statement */
3013 /*-----------------------------------------------------------------*/
3017 int size, offset = 0, pushed = 0;
3019 D (emitcode (";", "genRet ");
3022 /* if we have no return value then
3023 just generate the "ret" */
3027 /* we have something to return then
3028 move the return value into place */
3029 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3030 size = AOP_SIZE (IC_LEFT (ic));
3032 _startLazyDPSEvaluation ();
3036 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3038 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3039 FALSE, TRUE, FALSE);
3040 emitcode ("push", "%s", l);
3045 /* Since A is the last element of fReturn,
3046 * is is OK to clobber it in the aopGet.
3048 l = aopGet (AOP (IC_LEFT (ic)), offset,
3049 FALSE, FALSE, TRUE);
3050 if (strcmp (fReturn[offset], l))
3051 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3054 _endLazyDPSEvaluation ();
3061 if (strcmp (fReturn[pushed], "a"))
3062 emitcode ("pop", fReturn[pushed]);
3064 emitcode ("pop", "acc");
3067 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3070 /* generate a jump to the return label
3071 if the next is not the return statement */
3072 if (!(ic->next && ic->next->op == LABEL &&
3073 IC_LABEL (ic->next) == returnLabel))
3075 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3079 /*-----------------------------------------------------------------*/
3080 /* genLabel - generates a label */
3081 /*-----------------------------------------------------------------*/
3083 genLabel (iCode * ic)
3085 /* special case never generate */
3086 if (IC_LABEL (ic) == entryLabel)
3089 D (emitcode (";", "genLabel ");
3092 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3095 /*-----------------------------------------------------------------*/
3096 /* genGoto - generates a ljmp */
3097 /*-----------------------------------------------------------------*/
3099 genGoto (iCode * ic)
3101 D (emitcode (";", "genGoto ");
3103 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3106 /*-----------------------------------------------------------------*/
3107 /* findLabelBackwards: walks back through the iCode chain looking */
3108 /* for the given label. Returns number of iCode instructions */
3109 /* between that label and given ic. */
3110 /* Returns zero if label not found. */
3111 /*-----------------------------------------------------------------*/
3113 findLabelBackwards (iCode * ic, int key)
3122 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3124 /* printf("findLabelBackwards = %d\n", count); */
3132 /*-----------------------------------------------------------------*/
3133 /* genPlusIncr :- does addition with increment if possible */
3134 /*-----------------------------------------------------------------*/
3136 genPlusIncr (iCode * ic)
3138 unsigned int icount;
3139 unsigned int size = getDataSize (IC_RESULT (ic));
3141 /* will try to generate an increment */
3142 /* if the right side is not a literal
3144 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3147 /* if the literal value of the right hand side
3148 is greater than 4 then it is not worth it */
3149 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3152 /* if increment 16 bits in register */
3154 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3155 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3156 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3164 /* If the next instruction is a goto and the goto target
3165 * is <= 5 instructions previous to this, we can generate
3166 * jumps straight to that target.
3168 if (ic->next && ic->next->op == GOTO
3169 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3172 emitcode (";", "tail increment optimized (range %d)", labelRange);
3173 tlbl = IC_LABEL (ic->next);
3178 tlbl = newiTempLabel (NULL);
3181 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3182 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3183 IS_AOP_PREG (IC_RESULT (ic)))
3184 emitcode ("cjne", "%s,#0x00,%05d$"
3185 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3189 emitcode ("clr", "a");
3190 emitcode ("cjne", "a,%s,%05d$"
3191 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3195 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3198 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3199 IS_AOP_PREG (IC_RESULT (ic)))
3200 emitcode ("cjne", "%s,#0x00,%05d$"
3201 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3204 emitcode ("cjne", "a,%s,%05d$"
3205 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3208 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3212 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3213 IS_AOP_PREG (IC_RESULT (ic)))
3214 emitcode ("cjne", "%s,#0x00,%05d$"
3215 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3219 emitcode ("cjne", "a,%s,%05d$"
3220 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3223 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3228 emitcode ("", "%05d$:", tlbl->key + 100);
3233 /* if the sizes are greater than 1 then we cannot */
3234 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3235 AOP_SIZE (IC_LEFT (ic)) > 1)
3238 /* we can if the aops of the left & result match or
3239 if they are in registers and the registers are the
3242 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3243 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3244 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3249 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3250 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3251 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3256 _startLazyDPSEvaluation ();
3259 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3261 _endLazyDPSEvaluation ();
3270 /*-----------------------------------------------------------------*/
3271 /* outBitAcc - output a bit in acc */
3272 /*-----------------------------------------------------------------*/
3274 outBitAcc (operand * result)
3276 symbol *tlbl = newiTempLabel (NULL);
3277 /* if the result is a bit */
3278 if (AOP_TYPE (result) == AOP_CRY)
3280 aopPut (AOP (result), "a", 0);
3284 emitcode ("jz", "%05d$", tlbl->key + 100);
3285 emitcode ("mov", "a,%s", one);
3286 emitcode ("", "%05d$:", tlbl->key + 100);
3291 /*-----------------------------------------------------------------*/
3292 /* genPlusBits - generates code for addition of two bits */
3293 /*-----------------------------------------------------------------*/
3295 genPlusBits (iCode * ic)
3297 D (emitcode (";", "genPlusBits ");
3299 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3301 symbol *lbl = newiTempLabel (NULL);
3302 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3303 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3304 emitcode ("cpl", "c");
3305 emitcode ("", "%05d$:", (lbl->key + 100));
3306 outBitC (IC_RESULT (ic));
3310 emitcode ("clr", "a");
3311 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3312 emitcode ("rlc", "a");
3313 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3314 emitcode ("addc", "a,#0x00");
3315 outAcc (IC_RESULT (ic));
3320 adjustArithmeticResult (iCode * ic)
3322 if (opIsGptr (IC_RESULT (ic)) &&
3323 opIsGptr (IC_LEFT (ic)) &&
3324 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3326 aopPut (AOP (IC_RESULT (ic)),
3327 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3331 if (opIsGptr (IC_RESULT (ic)) &&
3332 opIsGptr (IC_RIGHT (ic)) &&
3333 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3335 aopPut (AOP (IC_RESULT (ic)),
3336 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3340 if (opIsGptr (IC_RESULT (ic)) &&
3341 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3342 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3343 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3344 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3347 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3348 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3352 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3353 // (because all three operands are in far space).
3354 #define AOP_OP_3(ic) \
3355 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3356 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3357 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3358 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3359 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3360 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3362 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3364 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3367 // Macro to aopOp all three operands of an ic. If this cannot be done,
3368 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3369 // will be set TRUE. The caller must then handle the case specially, noting
3370 // that the IC_RESULT operand is not aopOp'd.
3371 #define AOP_OP_3_NOFATAL(ic, rc) \
3372 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3373 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3374 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3375 isOperandInFarSpace(IC_RESULT(ic))) \
3377 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3382 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3383 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3385 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3386 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3388 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3390 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3394 // aopOp the left & right operands of an ic.
3395 #define AOP_OP_2(ic) \
3396 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3397 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3399 // convienience macro.
3400 #define AOP_SET_LOCALS(ic) \
3401 left = IC_LEFT(ic); \
3402 right = IC_RIGHT(ic); \
3403 result = IC_RESULT(ic);
3406 // Given an integer value of pushedSize bytes on the stack,
3407 // adjust it to be resultSize bytes, either by discarding
3408 // the most significant bytes or by zero-padding.
3410 // On exit from this macro, pushedSize will have been adjusted to
3411 // equal resultSize, and ACC may be trashed.
3412 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3413 /* If the pushed data is bigger than the result, \
3414 * simply discard unused bytes. Icky, but works. \
3416 while (pushedSize > resultSize) \
3418 D (emitcode (";", "discarding unused result byte."););\
3419 emitcode ("pop", "acc"); \
3422 if (pushedSize < resultSize) \
3424 emitcode ("clr", "a"); \
3425 /* Conversly, we haven't pushed enough here. \
3426 * just zero-pad, and all is well. \
3428 while (pushedSize < resultSize) \
3430 emitcode("push", "acc"); \
3434 assert(pushedSize == resultSize);
3436 /*-----------------------------------------------------------------*/
3437 /* genPlus - generates code for addition */
3438 /*-----------------------------------------------------------------*/
3440 genPlus (iCode * ic)
3442 int size, offset = 0;
3443 bool pushResult = FALSE;
3446 D (emitcode (";", "genPlus "););
3448 /* special cases :- */
3450 AOP_OP_3_NOFATAL (ic, pushResult);
3453 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3458 /* if literal, literal on the right or
3459 if left requires ACC or right is already
3461 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3462 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3463 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3465 operand *t = IC_RIGHT (ic);
3466 IC_RIGHT (ic) = IC_LEFT (ic);
3468 emitcode (";", "Swapped plus args.");
3471 /* if both left & right are in bit
3473 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3474 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3480 /* if left in bit space & right literal */
3481 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3482 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3484 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3485 /* if result in bit space */
3486 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3488 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3489 emitcode ("cpl", "c");
3490 outBitC (IC_RESULT (ic));
3494 size = getDataSize (IC_RESULT (ic));
3495 _startLazyDPSEvaluation ();
3498 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3499 emitcode ("addc", "a,#00");
3500 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3502 _endLazyDPSEvaluation ();
3507 /* if I can do an increment instead
3508 of add then GOOD for ME */
3509 if (genPlusIncr (ic) == TRUE)
3511 emitcode (";", "did genPlusIncr");
3516 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3518 _startLazyDPSEvaluation ();
3521 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3523 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3525 emitcode ("add", "a,%s",
3526 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3528 emitcode ("addc", "a,%s",
3529 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3533 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3535 /* right is going to use ACC or we would have taken the
3538 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3539 D(emitcode(";", "+ AOP_ACC special case."););
3540 emitcode("xch", "a, %s", DP2_RESULT_REG);
3542 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3545 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3547 emitcode("add", "a, %s", DP2_RESULT_REG);
3551 emitcode ("add", "a,%s",
3552 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3557 emitcode ("addc", "a,%s",
3558 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3563 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3567 emitcode ("push", "acc");
3571 _endLazyDPSEvaluation ();
3575 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3577 size = getDataSize (IC_LEFT (ic));
3578 rSize = getDataSize (IC_RESULT (ic));
3580 ADJUST_PUSHED_RESULT(size, rSize);
3582 _startLazyDPSEvaluation ();
3585 emitcode ("pop", "acc");
3586 aopPut (AOP (IC_RESULT (ic)), "a", size);
3588 _endLazyDPSEvaluation ();
3591 adjustArithmeticResult (ic);
3594 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3595 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3596 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3599 /*-----------------------------------------------------------------*/
3600 /* genMinusDec :- does subtraction with deccrement if possible */
3601 /*-----------------------------------------------------------------*/
3603 genMinusDec (iCode * ic)
3605 unsigned int icount;
3606 unsigned int size = getDataSize (IC_RESULT (ic));
3608 /* will try to generate an increment */
3609 /* if the right side is not a literal
3611 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3614 /* if the literal value of the right hand side
3615 is greater than 4 then it is not worth it */
3616 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3619 /* if decrement 16 bits in register */
3620 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3621 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3622 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3630 /* If the next instruction is a goto and the goto target
3631 * is <= 5 instructions previous to this, we can generate
3632 * jumps straight to that target.
3634 if (ic->next && ic->next->op == GOTO
3635 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3638 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3639 tlbl = IC_LABEL (ic->next);
3644 tlbl = newiTempLabel (NULL);
3648 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3649 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3650 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3651 IS_AOP_PREG (IC_RESULT (ic)))
3652 emitcode ("cjne", "%s,#0xff,%05d$"
3653 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3657 emitcode ("mov", "a,#0xff");
3658 emitcode ("cjne", "a,%s,%05d$"
3659 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3662 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3665 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3666 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3667 IS_AOP_PREG (IC_RESULT (ic)))
3668 emitcode ("cjne", "%s,#0xff,%05d$"
3669 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3673 emitcode ("cjne", "a,%s,%05d$"
3674 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3677 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3681 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3682 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3683 IS_AOP_PREG (IC_RESULT (ic)))
3684 emitcode ("cjne", "%s,#0xff,%05d$"
3685 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3689 emitcode ("cjne", "a,%s,%05d$"
3690 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3693 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3697 emitcode ("", "%05d$:", tlbl->key + 100);
3702 /* if the sizes are greater than 1 then we cannot */
3703 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3704 AOP_SIZE (IC_LEFT (ic)) > 1)
3707 /* we can if the aops of the left & result match or
3708 if they are in registers and the registers are the
3711 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3712 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3713 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3716 _startLazyDPSEvaluation ();
3719 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3721 _endLazyDPSEvaluation ();
3729 /*-----------------------------------------------------------------*/
3730 /* addSign - complete with sign */
3731 /*-----------------------------------------------------------------*/
3733 addSign (operand * result, int offset, int sign)
3735 int size = (getDataSize (result) - offset);
3738 _startLazyDPSEvaluation();
3741 emitcode ("rlc", "a");
3742 emitcode ("subb", "a,acc");
3745 aopPut (AOP (result), "a", offset++);
3752 aopPut (AOP (result), zero, offset++);
3755 _endLazyDPSEvaluation();
3759 /*-----------------------------------------------------------------*/
3760 /* genMinusBits - generates code for subtraction of two bits */
3761 /*-----------------------------------------------------------------*/
3763 genMinusBits (iCode * ic)
3765 symbol *lbl = newiTempLabel (NULL);
3767 D (emitcode (";", "genMinusBits "););
3769 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3771 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3772 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3773 emitcode ("cpl", "c");
3774 emitcode ("", "%05d$:", (lbl->key + 100));
3775 outBitC (IC_RESULT (ic));
3779 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3780 emitcode ("subb", "a,acc");
3781 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3782 emitcode ("inc", "a");
3783 emitcode ("", "%05d$:", (lbl->key + 100));
3784 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3785 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3789 /*-----------------------------------------------------------------*/
3790 /* genMinus - generates code for subtraction */
3791 /*-----------------------------------------------------------------*/
3793 genMinus (iCode * ic)
3795 int size, offset = 0;
3797 unsigned long lit = 0L;
3798 bool pushResult = FALSE;
3800 D (emitcode (";", "genMinus "););
3802 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3803 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3804 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3805 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3811 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3813 /* special cases :- */
3814 /* if both left & right are in bit space */
3815 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3816 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3822 /* if I can do an decrement instead
3823 of subtract then GOOD for ME */
3824 if (genMinusDec (ic) == TRUE)
3829 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3831 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3837 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3842 /* if literal, add a,#-lit, else normal subb */
3843 _startLazyDPSEvaluation ();
3846 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3847 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3848 emitcode ("subb", "a,%s",
3849 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3852 /* first add without previous c */
3854 emitcode ("add", "a,#0x%02x",
3855 (unsigned int) (lit & 0x0FFL));
3857 emitcode ("addc", "a,#0x%02x",
3858 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3863 emitcode ("push", "acc");
3867 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3871 _endLazyDPSEvaluation ();
3875 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3877 size = getDataSize (IC_LEFT (ic));
3878 rSize = getDataSize (IC_RESULT (ic));
3880 ADJUST_PUSHED_RESULT(size, rSize);
3882 _startLazyDPSEvaluation ();
3885 emitcode ("pop", "acc");
3886 aopPut (AOP (IC_RESULT (ic)), "a", size);
3888 _endLazyDPSEvaluation ();
3891 adjustArithmeticResult (ic);
3894 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3895 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3896 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3900 /*-----------------------------------------------------------------*/
3901 /* genMultbits :- multiplication of bits */
3902 /*-----------------------------------------------------------------*/
3904 genMultbits (operand * left,
3908 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3909 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3914 /*-----------------------------------------------------------------*/
3915 /* genMultOneByte : 8*8=8/16 bit multiplication */
3916 /*-----------------------------------------------------------------*/
3918 genMultOneByte (operand * left,
3922 sym_link *opetype = operandType (result);
3924 int size=AOP_SIZE(result);
3926 if (size<1 || size>2) {
3927 // this should never happen
3928 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3929 AOP_SIZE(result), __FILE__, lineno);
3933 /* (if two literals: the value is computed before) */
3934 /* if one literal, literal on the right */
3935 if (AOP_TYPE (left) == AOP_LIT)
3940 emitcode (";", "swapped left and right");
3943 if (SPEC_USIGN(opetype)
3944 // ignore the sign of left and right, what else can we do?
3945 || (SPEC_USIGN(operandType(left)) &&
3946 SPEC_USIGN(operandType(right)))) {
3947 // just an unsigned 8*8=8/16 multiply
3948 //emitcode (";","unsigned");
3949 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3950 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3951 emitcode ("mul", "ab");
3952 aopPut (AOP (result), "a", 0);
3954 aopPut (AOP (result), "b", 1);
3959 // we have to do a signed multiply
3961 emitcode (";", "signed");
3962 emitcode ("clr", "F0"); // reset sign flag
3963 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3964 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3966 lbl=newiTempLabel(NULL);
3967 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3968 // left side is negative, 8-bit two's complement, this fails for -128
3969 emitcode ("setb", "F0"); // set sign flag
3970 emitcode ("cpl", "a");
3971 emitcode ("inc", "a");
3973 emitcode ("", "%05d$:", lbl->key+100);
3974 emitcode ("xch", "a,b");
3977 if (AOP_TYPE(right)==AOP_LIT) {
3978 /* AND literal negative */
3979 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3980 // two's complement for literal<0
3981 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3982 emitcode ("cpl", "a");
3983 emitcode ("inc", "a");
3986 lbl=newiTempLabel(NULL);
3987 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3988 // right side is negative, 8-bit two's complement
3989 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3990 emitcode ("cpl", "a");
3991 emitcode ("inc", "a");
3992 emitcode ("", "%05d$:", lbl->key+100);
3994 emitcode ("mul", "ab");
3996 lbl=newiTempLabel(NULL);
3997 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3998 // only ONE op was negative, we have to do a 8/16-bit two's complement
3999 emitcode ("cpl", "a"); // lsb
4001 emitcode ("inc", "a");
4003 emitcode ("add", "a,#1");
4004 emitcode ("xch", "a,b");
4005 emitcode ("cpl", "a"); // msb
4006 emitcode ("addc", "a,#0");
4007 emitcode ("xch", "a,b");
4010 emitcode ("", "%05d$:", lbl->key+100);
4011 aopPut (AOP (result), "a", 0);
4013 aopPut (AOP (result), "b", 1);
4017 /*-----------------------------------------------------------------*/
4018 /* genMult - generates code for multiplication */
4019 /*-----------------------------------------------------------------*/
4021 genMult (iCode * ic)
4023 operand *left = IC_LEFT (ic);
4024 operand *right = IC_RIGHT (ic);
4025 operand *result = IC_RESULT (ic);
4027 D (emitcode (";", "genMult "););
4029 /* assign the amsops */
4032 /* special cases first */
4034 if (AOP_TYPE (left) == AOP_CRY &&
4035 AOP_TYPE (right) == AOP_CRY)
4037 genMultbits (left, right, result);
4041 /* if both are of size == 1 */
4042 if (AOP_SIZE (left) == 1 &&
4043 AOP_SIZE (right) == 1)
4045 genMultOneByte (left, right, result);
4049 /* should have been converted to function call */
4053 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4054 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4055 freeAsmop (result, NULL, ic, TRUE);
4058 /*-----------------------------------------------------------------*/
4059 /* genDivbits :- division of bits */
4060 /*-----------------------------------------------------------------*/
4062 genDivbits (operand * left,
4069 /* the result must be bit */
4070 LOAD_AB_FOR_DIV (left, right, l);
4071 emitcode ("div", "ab");
4072 emitcode ("rrc", "a");
4073 aopPut (AOP (result), "c", 0);
4076 /*-----------------------------------------------------------------*/
4077 /* genDivOneByte : 8 bit division */
4078 /*-----------------------------------------------------------------*/
4080 genDivOneByte (operand * left,
4084 sym_link *opetype = operandType (result);
4089 size = AOP_SIZE (result) - 1;
4091 /* signed or unsigned */
4092 if (SPEC_USIGN (opetype))
4094 /* unsigned is easy */
4095 LOAD_AB_FOR_DIV (left, right, l);
4096 emitcode ("div", "ab");
4097 aopPut (AOP (result), "a", 0);
4099 aopPut (AOP (result), zero, offset++);
4103 /* signed is a little bit more difficult */
4105 /* save the signs of the operands */
4106 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4108 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4109 emitcode ("push", "acc"); /* save it on the stack */
4111 /* now sign adjust for both left & right */
4112 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4114 lbl = newiTempLabel (NULL);
4115 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4116 emitcode ("cpl", "a");
4117 emitcode ("inc", "a");
4118 emitcode ("", "%05d$:", (lbl->key + 100));
4119 emitcode ("mov", "b,a");
4121 /* sign adjust left side */
4122 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4125 lbl = newiTempLabel (NULL);
4126 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4127 emitcode ("cpl", "a");
4128 emitcode ("inc", "a");
4129 emitcode ("", "%05d$:", (lbl->key + 100));
4131 /* now the division */
4132 emitcode ("nop", "; workaround for DS80C390 div bug.");
4133 emitcode ("div", "ab");
4134 /* we are interested in the lower order
4136 emitcode ("mov", "b,a");
4137 lbl = newiTempLabel (NULL);
4138 emitcode ("pop", "acc");
4139 /* if there was an over flow we don't
4140 adjust the sign of the result */
4141 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4142 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4144 emitcode ("clr", "a");
4145 emitcode ("subb", "a,b");
4146 emitcode ("mov", "b,a");
4147 emitcode ("", "%05d$:", (lbl->key + 100));
4149 /* now we are done */
4150 aopPut (AOP (result), "b", 0);
4153 emitcode ("mov", "c,b.7");
4154 emitcode ("subb", "a,acc");
4157 aopPut (AOP (result), "a", offset++);
4161 /*-----------------------------------------------------------------*/
4162 /* genDiv - generates code for division */
4163 /*-----------------------------------------------------------------*/
4167 operand *left = IC_LEFT (ic);
4168 operand *right = IC_RIGHT (ic);
4169 operand *result = IC_RESULT (ic);
4171 D (emitcode (";", "genDiv ");
4174 /* assign the amsops */
4177 /* special cases first */
4179 if (AOP_TYPE (left) == AOP_CRY &&
4180 AOP_TYPE (right) == AOP_CRY)
4182 genDivbits (left, right, result);
4186 /* if both are of size == 1 */
4187 if (AOP_SIZE (left) == 1 &&
4188 AOP_SIZE (right) == 1)
4190 genDivOneByte (left, right, result);
4194 /* should have been converted to function call */
4197 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4198 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4199 freeAsmop (result, NULL, ic, TRUE);
4202 /*-----------------------------------------------------------------*/
4203 /* genModbits :- modulus of bits */
4204 /*-----------------------------------------------------------------*/
4206 genModbits (operand * left,
4213 /* the result must be bit */
4214 LOAD_AB_FOR_DIV (left, right, l);
4215 emitcode ("div", "ab");
4216 emitcode ("mov", "a,b");
4217 emitcode ("rrc", "a");
4218 aopPut (AOP (result), "c", 0);
4221 /*-----------------------------------------------------------------*/
4222 /* genModOneByte : 8 bit modulus */
4223 /*-----------------------------------------------------------------*/
4225 genModOneByte (operand * left,
4229 sym_link *opetype = operandType (result);
4233 /* signed or unsigned */
4234 if (SPEC_USIGN (opetype))
4236 /* unsigned is easy */
4237 LOAD_AB_FOR_DIV (left, right, l);
4238 emitcode ("div", "ab");
4239 aopPut (AOP (result), "b", 0);
4243 /* signed is a little bit more difficult */
4245 /* save the signs of the operands */
4246 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4249 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4250 emitcode ("push", "acc"); /* save it on the stack */
4252 /* now sign adjust for both left & right */
4253 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4256 lbl = newiTempLabel (NULL);
4257 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4258 emitcode ("cpl", "a");
4259 emitcode ("inc", "a");
4260 emitcode ("", "%05d$:", (lbl->key + 100));
4261 emitcode ("mov", "b,a");
4263 /* sign adjust left side */
4264 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4267 lbl = newiTempLabel (NULL);
4268 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4269 emitcode ("cpl", "a");
4270 emitcode ("inc", "a");
4271 emitcode ("", "%05d$:", (lbl->key + 100));
4273 /* now the multiplication */
4274 emitcode ("nop", "; workaround for DS80C390 div bug.");
4275 emitcode ("div", "ab");
4276 /* we are interested in the lower order
4278 lbl = newiTempLabel (NULL);
4279 emitcode ("pop", "acc");
4280 /* if there was an over flow we don't
4281 adjust the sign of the result */
4282 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4283 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4285 emitcode ("clr", "a");
4286 emitcode ("subb", "a,b");
4287 emitcode ("mov", "b,a");
4288 emitcode ("", "%05d$:", (lbl->key + 100));
4290 /* now we are done */
4291 aopPut (AOP (result), "b", 0);
4295 /*-----------------------------------------------------------------*/
4296 /* genMod - generates code for division */
4297 /*-----------------------------------------------------------------*/
4301 operand *left = IC_LEFT (ic);
4302 operand *right = IC_RIGHT (ic);
4303 operand *result = IC_RESULT (ic);
4305 D (emitcode (";", "genMod ");
4308 /* assign the amsops */
4311 /* special cases first */
4313 if (AOP_TYPE (left) == AOP_CRY &&
4314 AOP_TYPE (right) == AOP_CRY)
4316 genModbits (left, right, result);
4320 /* if both are of size == 1 */
4321 if (AOP_SIZE (left) == 1 &&
4322 AOP_SIZE (right) == 1)
4324 genModOneByte (left, right, result);
4328 /* should have been converted to function call */
4332 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4333 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4334 freeAsmop (result, NULL, ic, TRUE);
4337 /*-----------------------------------------------------------------*/
4338 /* genIfxJump :- will create a jump depending on the ifx */
4339 /*-----------------------------------------------------------------*/
4341 genIfxJump (iCode * ic, char *jval)
4344 symbol *tlbl = newiTempLabel (NULL);
4347 D (emitcode (";", "genIfxJump ");
4350 /* if true label then we jump if condition
4354 jlbl = IC_TRUE (ic);
4355 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4356 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4360 /* false label is present */
4361 jlbl = IC_FALSE (ic);
4362 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4363 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4365 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4366 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4368 emitcode (inst, "%05d$", tlbl->key + 100);
4369 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4370 emitcode ("", "%05d$:", tlbl->key + 100);
4372 /* mark the icode as generated */
4376 /*-----------------------------------------------------------------*/
4377 /* genCmp :- greater or less than comparison */
4378 /*-----------------------------------------------------------------*/
4380 genCmp (operand * left, operand * right,
4381 iCode * ic, iCode * ifx, int sign)
4383 int size, offset = 0;
4384 unsigned long lit = 0L;
4387 D (emitcode (";", "genCmp");
4390 result = IC_RESULT (ic);
4392 /* if left & right are bit variables */
4393 if (AOP_TYPE (left) == AOP_CRY &&
4394 AOP_TYPE (right) == AOP_CRY)
4396 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4397 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4401 /* subtract right from left if at the
4402 end the carry flag is set then we know that
4403 left is greater than right */
4404 size = max (AOP_SIZE (left), AOP_SIZE (right));
4406 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4407 if ((size == 1) && !sign &&
4408 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4410 symbol *lbl = newiTempLabel (NULL);
4411 emitcode ("cjne", "%s,%s,%05d$",
4412 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4413 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4415 emitcode ("", "%05d$:", lbl->key + 100);
4419 if (AOP_TYPE (right) == AOP_LIT)
4421 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4422 /* optimize if(x < 0) or if(x >= 0) */
4431 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4433 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4434 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4436 aopOp (result, ic, FALSE, FALSE);
4438 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4440 freeAsmop (result, NULL, ic, TRUE);
4441 genIfxJump (ifx, "acc.7");
4446 emitcode ("rlc", "a");
4448 goto release_freedLR;
4456 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4457 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4458 emitcode (";", "genCmp #2");
4459 if (sign && (size == 0))
4461 emitcode (";", "genCmp #3");
4462 emitcode ("xrl", "a,#0x80");
4463 if (AOP_TYPE (right) == AOP_LIT)
4465 unsigned long lit = (unsigned long)
4466 floatFromVal (AOP (right)->aopu.aop_lit);
4467 emitcode (";", "genCmp #3.1");
4468 emitcode ("subb", "a,#0x%02x",
4469 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4473 emitcode (";", "genCmp #3.2");
4474 if (AOP_NEEDSACC (right))
4476 emitcode ("push", "acc");
4478 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4479 FALSE, FALSE, FALSE));
4480 emitcode ("xrl", "b,#0x80");
4481 if (AOP_NEEDSACC (right))
4483 emitcode ("pop", "acc");
4485 emitcode ("subb", "a,b");
4492 emitcode (";", "genCmp #4");
4493 if (AOP_NEEDSACC (right))
4496 emitcode (";", "genCmp #4.1");
4497 emitcode ("xch", "a, b");
4498 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4499 emitcode ("xch", "a, b");
4504 emitcode (";", "genCmp #4.2");
4505 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4508 emitcode ("subb", "a,%s", s);
4515 /* Don't need the left & right operands any more; do need the result. */
4516 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4519 aopOp (result, ic, FALSE, FALSE);
4523 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4529 /* if the result is used in the next
4530 ifx conditional branch then generate
4531 code a little differently */
4534 genIfxJump (ifx, "c");
4540 /* leave the result in acc */
4542 freeAsmop (result, NULL, ic, TRUE);
4545 /*-----------------------------------------------------------------*/
4546 /* genCmpGt :- greater than comparison */
4547 /*-----------------------------------------------------------------*/
4549 genCmpGt (iCode * ic, iCode * ifx)
4551 operand *left, *right;
4552 sym_link *letype, *retype;
4555 D (emitcode (";", "genCmpGt ");
4558 left = IC_LEFT (ic);
4559 right = IC_RIGHT (ic);
4561 letype = getSpec (operandType (left));
4562 retype = getSpec (operandType (right));
4563 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4565 /* assign the left & right amsops */
4568 genCmp (right, left, ic, ifx, sign);
4571 /*-----------------------------------------------------------------*/
4572 /* genCmpLt - less than comparisons */
4573 /*-----------------------------------------------------------------*/
4575 genCmpLt (iCode * ic, iCode * ifx)
4577 operand *left, *right;
4578 sym_link *letype, *retype;
4581 D (emitcode (";", "genCmpLt "););
4583 left = IC_LEFT (ic);
4584 right = IC_RIGHT (ic);
4586 letype = getSpec (operandType (left));
4587 retype = getSpec (operandType (right));
4588 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4590 /* assign the left & right amsops */
4593 genCmp (left, right, ic, ifx, sign);
4596 /*-----------------------------------------------------------------*/
4597 /* gencjneshort - compare and jump if not equal */
4598 /*-----------------------------------------------------------------*/
4600 gencjneshort (operand * left, operand * right, symbol * lbl)
4602 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4604 unsigned long lit = 0L;
4606 D (emitcode (";", "gencjneshort");
4609 /* if the left side is a literal or
4610 if the right is in a pointer register and left
4612 if ((AOP_TYPE (left) == AOP_LIT) ||
4613 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4620 if (AOP_TYPE (right) == AOP_LIT)
4621 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4623 if (opIsGptr (left) || opIsGptr (right))
4625 /* We are comparing a generic pointer to something.
4626 * Exclude the generic type byte from the comparison.
4629 D (emitcode (";", "cjneshort: generic ptr special case.");
4634 /* if the right side is a literal then anything goes */
4635 if (AOP_TYPE (right) == AOP_LIT &&
4636 AOP_TYPE (left) != AOP_DIR)
4640 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4642 emitcode ("cjne", "a,%s,%05d$",
4643 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4649 /* if the right side is in a register or in direct space or
4650 if the left is a pointer register & right is not */
4651 else if (AOP_TYPE (right) == AOP_REG ||
4652 AOP_TYPE (right) == AOP_DIR ||
4653 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4654 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4658 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4659 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4660 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4661 emitcode ("jnz", "%05d$", lbl->key + 100);
4663 emitcode ("cjne", "a,%s,%05d$",
4664 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4671 /* right is a pointer reg need both a & b */
4674 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4675 if (strcmp (l, "b"))
4676 emitcode ("mov", "b,%s", l);
4677 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4678 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4684 /*-----------------------------------------------------------------*/
4685 /* gencjne - compare and jump if not equal */
4686 /*-----------------------------------------------------------------*/
4688 gencjne (operand * left, operand * right, symbol * lbl)
4690 symbol *tlbl = newiTempLabel (NULL);
4692 D (emitcode (";", "gencjne");
4695 gencjneshort (left, right, lbl);
4697 emitcode ("mov", "a,%s", one);
4698 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4699 emitcode ("", "%05d$:", lbl->key + 100);
4700 emitcode ("clr", "a");
4701 emitcode ("", "%05d$:", tlbl->key + 100);
4704 /*-----------------------------------------------------------------*/
4705 /* genCmpEq - generates code for equal to */
4706 /*-----------------------------------------------------------------*/
4708 genCmpEq (iCode * ic, iCode * ifx)
4710 operand *left, *right, *result;
4712 D (emitcode (";", "genCmpEq ");
4716 AOP_SET_LOCALS (ic);
4718 /* if literal, literal on the right or
4719 if the right is in a pointer register and left
4721 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4722 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4724 operand *t = IC_RIGHT (ic);
4725 IC_RIGHT (ic) = IC_LEFT (ic);
4729 if (ifx && /* !AOP_SIZE(result) */
4730 OP_SYMBOL (result) &&
4731 OP_SYMBOL (result)->regType == REG_CND)
4734 /* if they are both bit variables */
4735 if (AOP_TYPE (left) == AOP_CRY &&
4736 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4738 if (AOP_TYPE (right) == AOP_LIT)
4740 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4743 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4744 emitcode ("cpl", "c");
4748 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4752 emitcode ("clr", "c");
4754 /* AOP_TYPE(right) == AOP_CRY */
4758 symbol *lbl = newiTempLabel (NULL);
4759 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4760 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4761 emitcode ("cpl", "c");
4762 emitcode ("", "%05d$:", (lbl->key + 100));
4764 /* if true label then we jump if condition
4766 tlbl = newiTempLabel (NULL);
4769 emitcode ("jnc", "%05d$", tlbl->key + 100);
4770 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4774 emitcode ("jc", "%05d$", tlbl->key + 100);
4775 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4777 emitcode ("", "%05d$:", tlbl->key + 100);
4781 tlbl = newiTempLabel (NULL);
4782 gencjneshort (left, right, tlbl);
4785 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4786 emitcode ("", "%05d$:", tlbl->key + 100);
4790 symbol *lbl = newiTempLabel (NULL);
4791 emitcode ("sjmp", "%05d$", lbl->key + 100);
4792 emitcode ("", "%05d$:", tlbl->key + 100);
4793 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4794 emitcode ("", "%05d$:", lbl->key + 100);
4797 /* mark the icode as generated */
4800 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4801 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4805 /* if they are both bit variables */
4806 if (AOP_TYPE (left) == AOP_CRY &&
4807 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4809 if (AOP_TYPE (right) == AOP_LIT)
4811 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4814 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4815 emitcode ("cpl", "c");
4819 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4823 emitcode ("clr", "c");
4825 /* AOP_TYPE(right) == AOP_CRY */
4829 symbol *lbl = newiTempLabel (NULL);
4830 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4831 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4832 emitcode ("cpl", "c");
4833 emitcode ("", "%05d$:", (lbl->key + 100));
4836 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4837 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4839 aopOp (result, ic, TRUE, FALSE);
4842 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4849 genIfxJump (ifx, "c");
4852 /* if the result is used in an arithmetic operation
4853 then put the result in place */
4858 gencjne (left, right, newiTempLabel (NULL));
4860 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4861 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863 aopOp (result, ic, TRUE, FALSE);
4865 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4867 aopPut (AOP (result), "a", 0);
4872 genIfxJump (ifx, "a");
4875 /* if the result is used in an arithmetic operation
4876 then put the result in place */
4877 if (AOP_TYPE (result) != AOP_CRY)
4879 /* leave the result in acc */
4883 freeAsmop (result, NULL, ic, TRUE);
4886 /*-----------------------------------------------------------------*/
4887 /* ifxForOp - returns the icode containing the ifx for operand */
4888 /*-----------------------------------------------------------------*/
4890 ifxForOp (operand * op, iCode * ic)
4892 /* if true symbol then needs to be assigned */
4893 if (IS_TRUE_SYMOP (op))
4896 /* if this has register type condition and
4897 the next instruction is ifx with the same operand
4898 and live to of the operand is upto the ifx only then */
4900 ic->next->op == IFX &&
4901 IC_COND (ic->next)->key == op->key &&
4902 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4907 /*-----------------------------------------------------------------*/
4908 /* genAndOp - for && operation */
4909 /*-----------------------------------------------------------------*/
4911 genAndOp (iCode * ic)
4913 operand *left, *right, *result;
4916 D (emitcode (";", "genAndOp "););
4918 /* note here that && operations that are in an
4919 if statement are taken away by backPatchLabels
4920 only those used in arthmetic operations remain */
4922 AOP_SET_LOCALS (ic);
4924 /* if both are bit variables */
4925 if (AOP_TYPE (left) == AOP_CRY &&
4926 AOP_TYPE (right) == AOP_CRY)
4928 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4929 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4930 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4931 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4933 aopOp (result,ic,FALSE, FALSE);
4938 tlbl = newiTempLabel (NULL);
4940 emitcode ("jz", "%05d$", tlbl->key + 100);
4942 emitcode ("", "%05d$:", tlbl->key + 100);
4943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4946 aopOp (result,ic,FALSE, FALSE);
4949 freeAsmop (result, NULL, ic, TRUE);
4953 /*-----------------------------------------------------------------*/
4954 /* genOrOp - for || operation */
4955 /*-----------------------------------------------------------------*/
4957 genOrOp (iCode * ic)
4959 operand *left, *right, *result;
4962 D (emitcode (";", "genOrOp "););
4964 /* note here that || operations that are in an
4965 if statement are taken away by backPatchLabels
4966 only those used in arthmetic operations remain */
4968 AOP_SET_LOCALS (ic);
4970 /* if both are bit variables */
4971 if (AOP_TYPE (left) == AOP_CRY &&
4972 AOP_TYPE (right) == AOP_CRY)
4974 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4975 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4976 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4977 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4979 aopOp (result,ic,FALSE, FALSE);
4985 tlbl = newiTempLabel (NULL);
4987 emitcode ("jnz", "%05d$", tlbl->key + 100);
4989 emitcode ("", "%05d$:", tlbl->key + 100);
4990 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4991 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4993 aopOp (result,ic,FALSE, FALSE);
4998 freeAsmop (result, NULL, ic, TRUE);
5001 /*-----------------------------------------------------------------*/
5002 /* isLiteralBit - test if lit == 2^n */
5003 /*-----------------------------------------------------------------*/
5005 isLiteralBit (unsigned long lit)
5007 unsigned long pw[32] =
5008 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5009 0x100L, 0x200L, 0x400L, 0x800L,
5010 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5011 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5012 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5013 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5014 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5017 for (idx = 0; idx < 32; idx++)
5023 /*-----------------------------------------------------------------*/
5024 /* continueIfTrue - */
5025 /*-----------------------------------------------------------------*/
5027 continueIfTrue (iCode * ic)
5030 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5034 /*-----------------------------------------------------------------*/
5036 /*-----------------------------------------------------------------*/
5038 jumpIfTrue (iCode * ic)
5041 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5045 /*-----------------------------------------------------------------*/
5046 /* jmpTrueOrFalse - */
5047 /*-----------------------------------------------------------------*/
5049 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5051 // ugly but optimized by peephole
5054 symbol *nlbl = newiTempLabel (NULL);
5055 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5056 emitcode ("", "%05d$:", tlbl->key + 100);
5057 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5058 emitcode ("", "%05d$:", nlbl->key + 100);
5062 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5063 emitcode ("", "%05d$:", tlbl->key + 100);
5068 // Generate code to perform a bit-wise logic operation
5069 // on two operands in far space (assumed to already have been
5070 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5071 // in far space. This requires pushing the result on the stack
5072 // then popping it into the result.
5074 genFarFarLogicOp(iCode *ic, char *logicOp)
5076 int size, resultSize, compSize;
5079 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5080 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5081 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5083 _startLazyDPSEvaluation();
5084 for (size = compSize; (size--); offset++)
5086 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5087 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5088 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5090 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5091 emitcode ("push", "acc");
5093 _endLazyDPSEvaluation();
5095 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5096 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5097 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5099 resultSize = AOP_SIZE(IC_RESULT(ic));
5101 ADJUST_PUSHED_RESULT(compSize, resultSize);
5103 _startLazyDPSEvaluation();
5106 emitcode ("pop", "acc");
5107 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5109 _endLazyDPSEvaluation();
5110 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5114 /*-----------------------------------------------------------------*/
5115 /* genAnd - code for and */
5116 /*-----------------------------------------------------------------*/
5118 genAnd (iCode * ic, iCode * ifx)
5120 operand *left, *right, *result;
5121 int size, offset = 0;
5122 unsigned long lit = 0L;
5127 D (emitcode (";", "genAnd "););
5129 AOP_OP_3_NOFATAL (ic, pushResult);
5130 AOP_SET_LOCALS (ic);
5134 genFarFarLogicOp(ic, "anl");
5139 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5141 AOP_TYPE (left), AOP_TYPE (right));
5142 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5144 AOP_SIZE (left), AOP_SIZE (right));
5147 /* if left is a literal & right is not then exchange them */
5148 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5149 AOP_NEEDSACC (left))
5151 operand *tmp = right;
5156 /* if result = right then exchange them */
5157 if (sameRegs (AOP (result), AOP (right)))
5159 operand *tmp = right;
5164 /* if right is bit then exchange them */
5165 if (AOP_TYPE (right) == AOP_CRY &&
5166 AOP_TYPE (left) != AOP_CRY)
5168 operand *tmp = right;
5172 if (AOP_TYPE (right) == AOP_LIT)
5173 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5175 size = AOP_SIZE (result);
5178 // result = bit & yy;
5179 if (AOP_TYPE (left) == AOP_CRY)
5181 // c = bit & literal;
5182 if (AOP_TYPE (right) == AOP_LIT)
5186 if (size && sameRegs (AOP (result), AOP (left)))
5189 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5194 if (size && (AOP_TYPE (result) == AOP_CRY))
5196 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5199 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5204 emitcode ("clr", "c");
5209 if (AOP_TYPE (right) == AOP_CRY)
5212 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5213 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5218 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5220 emitcode ("rrc", "a");
5221 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5229 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5230 genIfxJump (ifx, "c");
5234 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5235 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5236 if ((AOP_TYPE (right) == AOP_LIT) &&
5237 (AOP_TYPE (result) == AOP_CRY) &&
5238 (AOP_TYPE (left) != AOP_CRY))
5240 int posbit = isLiteralBit (lit);
5245 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5248 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5254 sprintf (buffer, "acc.%d", posbit & 0x07);
5255 genIfxJump (ifx, buffer);
5262 symbol *tlbl = newiTempLabel (NULL);
5263 int sizel = AOP_SIZE (left);
5265 emitcode ("setb", "c");
5268 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5270 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5272 if ((posbit = isLiteralBit (bytelit)) != 0)
5273 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5276 if (bytelit != 0x0FFL)
5277 emitcode ("anl", "a,%s",
5278 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5279 emitcode ("jnz", "%05d$", tlbl->key + 100);
5284 // bit = left & literal
5287 emitcode ("clr", "c");
5288 emitcode ("", "%05d$:", tlbl->key + 100);
5290 // if(left & literal)
5294 jmpTrueOrFalse (ifx, tlbl);
5302 /* if left is same as result */
5303 if (sameRegs (AOP (result), AOP (left)))
5305 for (; size--; offset++)
5307 if (AOP_TYPE (right) == AOP_LIT)
5309 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5311 else if (bytelit == 0)
5312 aopPut (AOP (result), zero, offset);
5313 else if (IS_AOP_PREG (result))
5315 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5316 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5317 aopPut (AOP (result), "a", offset);
5320 emitcode ("anl", "%s,%s",
5321 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5322 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5326 if (AOP_TYPE (left) == AOP_ACC)
5327 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5330 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5331 if (IS_AOP_PREG (result))
5333 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5334 aopPut (AOP (result), "a", offset);
5338 emitcode ("anl", "%s,a",
5339 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5346 // left & result in different registers
5347 if (AOP_TYPE (result) == AOP_CRY)
5350 // if(size), result in bit
5351 // if(!size && ifx), conditional oper: if(left & right)
5352 symbol *tlbl = newiTempLabel (NULL);
5353 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5355 emitcode ("setb", "c");
5358 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5359 emitcode ("anl", "a,%s",
5360 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5361 emitcode ("jnz", "%05d$", tlbl->key + 100);
5367 emitcode ("", "%05d$:", tlbl->key + 100);
5371 jmpTrueOrFalse (ifx, tlbl);
5375 for (; (size--); offset++)
5378 // result = left & right
5379 if (AOP_TYPE (right) == AOP_LIT)
5381 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5383 aopPut (AOP (result),
5384 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5388 else if (bytelit == 0)
5390 aopPut (AOP (result), zero, offset);
5393 D (emitcode (";", "better literal AND.");
5395 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5396 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5397 FALSE, FALSE, FALSE));
5402 // faster than result <- left, anl result,right
5403 // and better if result is SFR
5404 if (AOP_TYPE (left) == AOP_ACC)
5406 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5407 FALSE, FALSE, FALSE));
5411 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5412 emitcode ("anl", "a,%s",
5413 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5416 aopPut (AOP (result), "a", offset);
5422 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5423 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5424 freeAsmop (result, NULL, ic, TRUE);
5428 /*-----------------------------------------------------------------*/
5429 /* genOr - code for or */
5430 /*-----------------------------------------------------------------*/
5432 genOr (iCode * ic, iCode * ifx)
5434 operand *left, *right, *result;
5435 int size, offset = 0;
5436 unsigned long lit = 0L;
5439 D (emitcode (";", "genOr "););
5441 AOP_OP_3_NOFATAL (ic, pushResult);
5442 AOP_SET_LOCALS (ic);
5446 genFarFarLogicOp(ic, "orl");
5452 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5454 AOP_TYPE (left), AOP_TYPE (right));
5455 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5457 AOP_SIZE (left), AOP_SIZE (right));
5460 /* if left is a literal & right is not then exchange them */
5461 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5462 AOP_NEEDSACC (left))
5464 operand *tmp = right;
5469 /* if result = right then exchange them */
5470 if (sameRegs (AOP (result), AOP (right)))
5472 operand *tmp = right;
5477 /* if right is bit then exchange them */
5478 if (AOP_TYPE (right) == AOP_CRY &&
5479 AOP_TYPE (left) != AOP_CRY)
5481 operand *tmp = right;
5485 if (AOP_TYPE (right) == AOP_LIT)
5486 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5488 size = AOP_SIZE (result);
5492 if (AOP_TYPE (left) == AOP_CRY)
5494 if (AOP_TYPE (right) == AOP_LIT)
5496 // c = bit & literal;
5499 // lit != 0 => result = 1
5500 if (AOP_TYPE (result) == AOP_CRY)
5503 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5505 continueIfTrue (ifx);
5508 emitcode ("setb", "c");
5512 // lit == 0 => result = left
5513 if (size && sameRegs (AOP (result), AOP (left)))
5515 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5520 if (AOP_TYPE (right) == AOP_CRY)
5523 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5524 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5529 symbol *tlbl = newiTempLabel (NULL);
5530 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5531 emitcode ("setb", "c");
5532 emitcode ("jb", "%s,%05d$",
5533 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5535 emitcode ("jnz", "%05d$", tlbl->key + 100);
5536 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5538 jmpTrueOrFalse (ifx, tlbl);
5544 emitcode ("", "%05d$:", tlbl->key + 100);
5553 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5554 genIfxJump (ifx, "c");
5558 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5559 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5560 if ((AOP_TYPE (right) == AOP_LIT) &&
5561 (AOP_TYPE (result) == AOP_CRY) &&
5562 (AOP_TYPE (left) != AOP_CRY))
5568 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5570 continueIfTrue (ifx);
5575 // lit = 0, result = boolean(left)
5577 emitcode ("setb", "c");
5581 symbol *tlbl = newiTempLabel (NULL);
5582 emitcode ("jnz", "%05d$", tlbl->key + 100);
5584 emitcode ("", "%05d$:", tlbl->key + 100);
5588 genIfxJump (ifx, "a");
5596 /* if left is same as result */
5597 if (sameRegs (AOP (result), AOP (left)))
5599 for (; size--; offset++)
5601 if (AOP_TYPE (right) == AOP_LIT)
5603 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5609 if (IS_AOP_PREG (left))
5611 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5612 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5613 aopPut (AOP (result), "a", offset);
5617 emitcode ("orl", "%s,%s",
5618 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5619 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5625 if (AOP_TYPE (left) == AOP_ACC)
5627 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5631 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5632 if (IS_AOP_PREG (left))
5634 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5635 aopPut (AOP (result), "a", offset);
5639 emitcode ("orl", "%s,a",
5640 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5648 // left & result in different registers
5649 if (AOP_TYPE (result) == AOP_CRY)
5652 // if(size), result in bit
5653 // if(!size && ifx), conditional oper: if(left | right)
5654 symbol *tlbl = newiTempLabel (NULL);
5655 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5657 emitcode ("setb", "c");
5660 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5661 emitcode ("orl", "a,%s",
5662 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5663 emitcode ("jnz", "%05d$", tlbl->key + 100);
5669 emitcode ("", "%05d$:", tlbl->key + 100);
5673 jmpTrueOrFalse (ifx, tlbl);
5677 for (; (size--); offset++)
5680 // result = left & right
5681 if (AOP_TYPE (right) == AOP_LIT)
5683 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5685 aopPut (AOP (result),
5686 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5690 D (emitcode (";", "better literal OR.");
5692 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5693 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5694 FALSE, FALSE, FALSE));
5699 // faster than result <- left, anl result,right
5700 // and better if result is SFR
5701 if (AOP_TYPE (left) == AOP_ACC)
5703 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5704 FALSE, FALSE, FALSE));
5708 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5709 emitcode ("orl", "a,%s",
5710 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5713 aopPut (AOP (result), "a", offset);
5719 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5720 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5721 freeAsmop (result, NULL, ic, TRUE);
5724 /*-----------------------------------------------------------------*/
5725 /* genXor - code for xclusive or */
5726 /*-----------------------------------------------------------------*/
5728 genXor (iCode * ic, iCode * ifx)
5730 operand *left, *right, *result;
5731 int size, offset = 0;
5732 unsigned long lit = 0L;
5735 D (emitcode (";", "genXor "););
5737 AOP_OP_3_NOFATAL (ic, pushResult);
5738 AOP_SET_LOCALS (ic);
5742 genFarFarLogicOp(ic, "xrl");
5747 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5749 AOP_TYPE (left), AOP_TYPE (right));
5750 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5752 AOP_SIZE (left), AOP_SIZE (right));
5755 /* if left is a literal & right is not ||
5756 if left needs acc & right does not */
5757 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5758 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5760 operand *tmp = right;
5765 /* if result = right then exchange them */
5766 if (sameRegs (AOP (result), AOP (right)))
5768 operand *tmp = right;
5773 /* if right is bit then exchange them */
5774 if (AOP_TYPE (right) == AOP_CRY &&
5775 AOP_TYPE (left) != AOP_CRY)
5777 operand *tmp = right;
5781 if (AOP_TYPE (right) == AOP_LIT)
5782 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5784 size = AOP_SIZE (result);
5788 if (AOP_TYPE (left) == AOP_CRY)
5790 if (AOP_TYPE (right) == AOP_LIT)
5792 // c = bit & literal;
5795 // lit>>1 != 0 => result = 1
5796 if (AOP_TYPE (result) == AOP_CRY)
5799 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5801 continueIfTrue (ifx);
5804 emitcode ("setb", "c");
5811 // lit == 0, result = left
5812 if (size && sameRegs (AOP (result), AOP (left)))
5814 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5818 // lit == 1, result = not(left)
5819 if (size && sameRegs (AOP (result), AOP (left)))
5821 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5826 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5827 emitcode ("cpl", "c");
5836 symbol *tlbl = newiTempLabel (NULL);
5837 if (AOP_TYPE (right) == AOP_CRY)
5840 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5844 int sizer = AOP_SIZE (right);
5846 // if val>>1 != 0, result = 1
5847 emitcode ("setb", "c");
5850 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5852 // test the msb of the lsb
5853 emitcode ("anl", "a,#0xfe");
5854 emitcode ("jnz", "%05d$", tlbl->key + 100);
5858 emitcode ("rrc", "a");
5860 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5861 emitcode ("cpl", "c");
5862 emitcode ("", "%05d$:", (tlbl->key + 100));
5869 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5870 genIfxJump (ifx, "c");
5874 if (sameRegs (AOP (result), AOP (left)))
5876 /* if left is same as result */
5877 for (; size--; offset++)
5879 if (AOP_TYPE (right) == AOP_LIT)
5881 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5883 else if (IS_AOP_PREG (left))
5885 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5886 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5887 aopPut (AOP (result), "a", offset);
5890 emitcode ("xrl", "%s,%s",
5891 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5892 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5896 if (AOP_TYPE (left) == AOP_ACC)
5897 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5900 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5901 if (IS_AOP_PREG (left))
5903 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5904 aopPut (AOP (result), "a", offset);
5907 emitcode ("xrl", "%s,a",
5908 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5915 // left & result in different registers
5916 if (AOP_TYPE (result) == AOP_CRY)
5919 // if(size), result in bit
5920 // if(!size && ifx), conditional oper: if(left ^ right)
5921 symbol *tlbl = newiTempLabel (NULL);
5922 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5924 emitcode ("setb", "c");
5927 if ((AOP_TYPE (right) == AOP_LIT) &&
5928 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5930 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5934 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5935 emitcode ("xrl", "a,%s",
5936 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5938 emitcode ("jnz", "%05d$", tlbl->key + 100);
5944 emitcode ("", "%05d$:", tlbl->key + 100);
5948 jmpTrueOrFalse (ifx, tlbl);
5951 for (; (size--); offset++)
5954 // result = left & right
5955 if (AOP_TYPE (right) == AOP_LIT)
5957 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5959 aopPut (AOP (result),
5960 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5964 D (emitcode (";", "better literal XOR.");
5966 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5967 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5968 FALSE, FALSE, FALSE));
5972 // faster than result <- left, anl result,right
5973 // and better if result is SFR
5974 if (AOP_TYPE (left) == AOP_ACC)
5976 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5977 FALSE, FALSE, FALSE));
5981 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5982 emitcode ("xrl", "a,%s",
5983 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5986 aopPut (AOP (result), "a", offset);
5991 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5992 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5993 freeAsmop (result, NULL, ic, TRUE);
5996 /*-----------------------------------------------------------------*/
5997 /* genInline - write the inline code out */
5998 /*-----------------------------------------------------------------*/
6000 genInline (iCode * ic)
6002 char *buffer, *bp, *bp1;
6004 D (emitcode (";", "genInline ");
6007 _G.inLine += (!options.asmpeep);
6009 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6010 strcpy (buffer, IC_INLINE (ic));
6012 /* emit each line as a code */
6037 /* emitcode("",buffer); */
6038 _G.inLine -= (!options.asmpeep);
6041 /*-----------------------------------------------------------------*/
6042 /* genRRC - rotate right with carry */
6043 /*-----------------------------------------------------------------*/
6047 operand *left, *result;
6048 int size, offset = 0;
6051 D (emitcode (";", "genRRC ");
6054 /* rotate right with carry */
6055 left = IC_LEFT (ic);
6056 result = IC_RESULT (ic);
6057 aopOp (left, ic, FALSE, FALSE);
6058 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6060 /* move it to the result */
6061 size = AOP_SIZE (result);
6065 _startLazyDPSEvaluation ();
6068 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6070 emitcode ("rrc", "a");
6071 if (AOP_SIZE (result) > 1)
6072 aopPut (AOP (result), "a", offset--);
6074 _endLazyDPSEvaluation ();
6076 /* now we need to put the carry into the
6077 highest order byte of the result */
6078 if (AOP_SIZE (result) > 1)
6080 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6083 emitcode ("mov", "acc.7,c");
6084 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6085 freeAsmop (left, NULL, ic, TRUE);
6086 freeAsmop (result, NULL, ic, TRUE);
6089 /*-----------------------------------------------------------------*/
6090 /* genRLC - generate code for rotate left with carry */
6091 /*-----------------------------------------------------------------*/
6095 operand *left, *result;
6096 int size, offset = 0;
6099 D (emitcode (";", "genRLC ");
6102 /* rotate right with carry */
6103 left = IC_LEFT (ic);
6104 result = IC_RESULT (ic);
6105 aopOp (left, ic, FALSE, FALSE);
6106 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6108 /* move it to the result */
6109 size = AOP_SIZE (result);
6113 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6115 emitcode ("add", "a,acc");
6116 if (AOP_SIZE (result) > 1)
6118 aopPut (AOP (result), "a", offset++);
6121 _startLazyDPSEvaluation ();
6124 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6126 emitcode ("rlc", "a");
6127 if (AOP_SIZE (result) > 1)
6128 aopPut (AOP (result), "a", offset++);
6130 _endLazyDPSEvaluation ();
6132 /* now we need to put the carry into the
6133 highest order byte of the result */
6134 if (AOP_SIZE (result) > 1)
6136 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6139 emitcode ("mov", "acc.0,c");
6140 aopPut (AOP (result), "a", 0);
6141 freeAsmop (left, NULL, ic, TRUE);
6142 freeAsmop (result, NULL, ic, TRUE);
6145 /*-----------------------------------------------------------------*/
6146 /* genGetHbit - generates code get highest order bit */
6147 /*-----------------------------------------------------------------*/
6149 genGetHbit (iCode * ic)
6151 operand *left, *result;
6152 left = IC_LEFT (ic);
6153 result = IC_RESULT (ic);
6154 aopOp (left, ic, FALSE, FALSE);
6155 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6157 D (emitcode (";", "genGetHbit ");
6160 /* get the highest order byte into a */
6161 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6162 if (AOP_TYPE (result) == AOP_CRY)
6164 emitcode ("rlc", "a");
6169 emitcode ("rl", "a");
6170 emitcode ("anl", "a,#0x01");
6175 freeAsmop (left, NULL, ic, TRUE);
6176 freeAsmop (result, NULL, ic, TRUE);
6179 /*-----------------------------------------------------------------*/
6180 /* AccRol - rotate left accumulator by known count */
6181 /*-----------------------------------------------------------------*/
6183 AccRol (int shCount)
6185 shCount &= 0x0007; // shCount : 0..7
6192 emitcode ("rl", "a");
6195 emitcode ("rl", "a");
6196 emitcode ("rl", "a");
6199 emitcode ("swap", "a");
6200 emitcode ("rr", "a");
6203 emitcode ("swap", "a");
6206 emitcode ("swap", "a");
6207 emitcode ("rl", "a");
6210 emitcode ("rr", "a");
6211 emitcode ("rr", "a");
6214 emitcode ("rr", "a");
6219 /*-----------------------------------------------------------------*/
6220 /* AccLsh - left shift accumulator by known count */
6221 /*-----------------------------------------------------------------*/
6223 AccLsh (int shCount)
6228 emitcode ("add", "a,acc");
6229 else if (shCount == 2)
6231 emitcode ("add", "a,acc");
6232 emitcode ("add", "a,acc");
6236 /* rotate left accumulator */
6238 /* and kill the lower order bits */
6239 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6244 /*-----------------------------------------------------------------*/
6245 /* AccRsh - right shift accumulator by known count */
6246 /*-----------------------------------------------------------------*/
6248 AccRsh (int shCount)
6255 emitcode ("rrc", "a");
6259 /* rotate right accumulator */
6260 AccRol (8 - shCount);
6261 /* and kill the higher order bits */
6262 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6267 #ifdef BETTER_LITERAL_SHIFT
6268 /*-----------------------------------------------------------------*/
6269 /* AccSRsh - signed right shift accumulator by known count */
6270 /*-----------------------------------------------------------------*/
6272 AccSRsh (int shCount)
6279 emitcode ("mov", "c,acc.7");
6280 emitcode ("rrc", "a");
6282 else if (shCount == 2)
6284 emitcode ("mov", "c,acc.7");
6285 emitcode ("rrc", "a");
6286 emitcode ("mov", "c,acc.7");
6287 emitcode ("rrc", "a");
6291 tlbl = newiTempLabel (NULL);
6292 /* rotate right accumulator */
6293 AccRol (8 - shCount);
6294 /* and kill the higher order bits */
6295 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6296 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6297 emitcode ("orl", "a,#0x%02x",
6298 (unsigned char) ~SRMask[shCount]);
6299 emitcode ("", "%05d$:", tlbl->key + 100);
6305 #ifdef BETTER_LITERAL_SHIFT
6306 /*-----------------------------------------------------------------*/
6307 /* shiftR1Left2Result - shift right one byte from left to result */
6308 /*-----------------------------------------------------------------*/
6310 shiftR1Left2Result (operand * left, int offl,
6311 operand * result, int offr,
6312 int shCount, int sign)
6314 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6315 /* shift right accumulator */
6320 aopPut (AOP (result), "a", offr);
6324 #ifdef BETTER_LITERAL_SHIFT
6325 /*-----------------------------------------------------------------*/
6326 /* shiftL1Left2Result - shift left one byte from left to result */
6327 /*-----------------------------------------------------------------*/
6329 shiftL1Left2Result (operand * left, int offl,
6330 operand * result, int offr, int shCount)
6332 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6333 /* shift left accumulator */
6335 aopPut (AOP (result), "a", offr);
6339 #ifdef BETTER_LITERAL_SHIFT
6340 /*-----------------------------------------------------------------*/
6341 /* movLeft2Result - move byte from left to result */
6342 /*-----------------------------------------------------------------*/
6344 movLeft2Result (operand * left, int offl,
6345 operand * result, int offr, int sign)
6348 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6350 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6352 if (*l == '@' && (IS_AOP_PREG (result)))
6354 emitcode ("mov", "a,%s", l);
6355 aopPut (AOP (result), "a", offr);
6361 aopPut (AOP (result), l, offr);
6365 /* MSB sign in acc.7 ! */
6366 if (getDataSize (left) == offl + 1)
6368 emitcode ("mov", "a,%s", l);
6369 aopPut (AOP (result), "a", offr);
6377 #ifdef BETTER_LITERAL_SHIFT
6378 /*-----------------------------------------------------------------*/
6379 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6380 /*-----------------------------------------------------------------*/
6384 emitcode ("rrc", "a");
6385 emitcode ("xch", "a,%s", x);
6386 emitcode ("rrc", "a");
6387 emitcode ("xch", "a,%s", x);
6391 #ifdef BETTER_LITERAL_SHIFT
6393 /*-----------------------------------------------------------------*/
6394 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6395 /*-----------------------------------------------------------------*/
6399 emitcode ("xch", "a,%s", x);
6400 emitcode ("rlc", "a");
6401 emitcode ("xch", "a,%s", x);
6402 emitcode ("rlc", "a");
6406 #ifdef BETTER_LITERAL_SHIFT
6407 /*-----------------------------------------------------------------*/
6408 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6409 /*-----------------------------------------------------------------*/
6413 emitcode ("xch", "a,%s", x);
6414 emitcode ("add", "a,acc");
6415 emitcode ("xch", "a,%s", x);
6416 emitcode ("rlc", "a");
6420 #ifdef BETTER_LITERAL_SHIFT
6421 /*-----------------------------------------------------------------*/
6422 /* AccAXLsh - left shift a:x by known count (0..7) */
6423 /*-----------------------------------------------------------------*/
6425 AccAXLsh (char *x, int shCount)
6440 case 5: // AAAAABBB:CCCCCDDD
6442 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6444 emitcode ("anl", "a,#0x%02x",
6445 SLMask[shCount]); // BBB00000:CCCCCDDD
6447 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6449 AccRol (shCount); // DDDCCCCC:BBB00000
6451 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6453 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6455 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6457 emitcode ("anl", "a,#0x%02x",
6458 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6460 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6462 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6465 case 6: // AAAAAABB:CCCCCCDD
6466 emitcode ("anl", "a,#0x%02x",
6467 SRMask[shCount]); // 000000BB:CCCCCCDD
6468 emitcode ("mov", "c,acc.0"); // c = B
6469 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6471 AccAXRrl1 (x); // BCCCCCCD:D000000B
6472 AccAXRrl1 (x); // BBCCCCCC:DD000000
6474 emitcode("rrc","a");
6475 emitcode("xch","a,%s", x);
6476 emitcode("rrc","a");
6477 emitcode("mov","c,acc.0"); //<< get correct bit
6478 emitcode("xch","a,%s", x);
6480 emitcode("rrc","a");
6481 emitcode("xch","a,%s", x);
6482 emitcode("rrc","a");
6483 emitcode("xch","a,%s", x);
6486 case 7: // a:x <<= 7
6488 emitcode ("anl", "a,#0x%02x",
6489 SRMask[shCount]); // 0000000B:CCCCCCCD
6491 emitcode ("mov", "c,acc.0"); // c = B
6493 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6495 AccAXRrl1 (x); // BCCCCCCC:D0000000
6504 #ifdef BETTER_LITERAL_SHIFT
6506 /*-----------------------------------------------------------------*/
6507 /* AccAXRsh - right shift a:x known count (0..7) */
6508 /*-----------------------------------------------------------------*/
6510 AccAXRsh (char *x, int shCount)
6518 AccAXRrl1 (x); // 0->a:x
6523 AccAXRrl1 (x); // 0->a:x
6526 AccAXRrl1 (x); // 0->a:x
6531 case 5: // AAAAABBB:CCCCCDDD = a:x
6533 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6535 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6537 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6539 emitcode ("anl", "a,#0x%02x",
6540 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6542 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6544 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6546 emitcode ("anl", "a,#0x%02x",
6547 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6549 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6551 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6553 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6556 case 6: // AABBBBBB:CCDDDDDD
6558 emitcode ("mov", "c,acc.7");
6559 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6561 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6563 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6565 emitcode ("anl", "a,#0x%02x",
6566 SRMask[shCount]); // 000000AA:BBBBBBCC
6569 case 7: // ABBBBBBB:CDDDDDDD
6571 emitcode ("mov", "c,acc.7"); // c = A
6573 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6575 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6577 emitcode ("anl", "a,#0x%02x",
6578 SRMask[shCount]); // 0000000A:BBBBBBBC
6587 #ifdef BETTER_LITERAL_SHIFT
6589 /*-----------------------------------------------------------------*/
6590 /* AccAXRshS - right shift signed a:x known count (0..7) */
6591 /*-----------------------------------------------------------------*/
6593 AccAXRshS (char *x, int shCount)
6601 emitcode ("mov", "c,acc.7");
6602 AccAXRrl1 (x); // s->a:x
6606 emitcode ("mov", "c,acc.7");
6607 AccAXRrl1 (x); // s->a:x
6609 emitcode ("mov", "c,acc.7");
6610 AccAXRrl1 (x); // s->a:x
6615 case 5: // AAAAABBB:CCCCCDDD = a:x
6617 tlbl = newiTempLabel (NULL);
6618 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6620 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6622 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6624 emitcode ("anl", "a,#0x%02x",
6625 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6627 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6629 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6631 emitcode ("anl", "a,#0x%02x",
6632 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6634 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6636 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6638 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6640 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6641 emitcode ("orl", "a,#0x%02x",
6642 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6644 emitcode ("", "%05d$:", tlbl->key + 100);
6645 break; // SSSSAAAA:BBBCCCCC
6647 case 6: // AABBBBBB:CCDDDDDD
6649 tlbl = newiTempLabel (NULL);
6650 emitcode ("mov", "c,acc.7");
6651 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6653 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6655 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6657 emitcode ("anl", "a,#0x%02x",
6658 SRMask[shCount]); // 000000AA:BBBBBBCC
6660 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6661 emitcode ("orl", "a,#0x%02x",
6662 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6664 emitcode ("", "%05d$:", tlbl->key + 100);
6666 case 7: // ABBBBBBB:CDDDDDDD
6668 tlbl = newiTempLabel (NULL);
6669 emitcode ("mov", "c,acc.7"); // c = A
6671 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6673 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6675 emitcode ("anl", "a,#0x%02x",
6676 SRMask[shCount]); // 0000000A:BBBBBBBC
6678 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6679 emitcode ("orl", "a,#0x%02x",
6680 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6682 emitcode ("", "%05d$:", tlbl->key + 100);
6690 #ifdef BETTER_LITERAL_SHIFT
6692 _loadLeftIntoAx(char **lsb,
6698 // Get the initial value from left into a pair of registers.
6699 // MSB must be in A, LSB can be any register.
6701 // If the result is held in registers, it is an optimization
6702 // if the LSB can be held in the register which will hold the,
6703 // result LSB since this saves us from having to copy it into
6704 // the result following AccAXLsh.
6706 // If the result is addressed indirectly, this is not a gain.
6707 if (AOP_NEEDSACC(result))
6711 _startLazyDPSEvaluation();
6712 if (AOP_TYPE(left) == AOP_DPTR2)
6715 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6716 // get LSB in DP2_RESULT_REG.
6717 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6718 assert(!strcmp(leftByte, DP2_RESULT_REG));
6722 // get LSB into DP2_RESULT_REG
6723 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6724 if (strcmp(leftByte, DP2_RESULT_REG))
6726 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6729 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6730 assert(strcmp(leftByte, DP2_RESULT_REG));
6733 _endLazyDPSEvaluation();
6734 *lsb = DP2_RESULT_REG;
6738 if (sameRegs (AOP (result), AOP (left)) &&
6739 ((offl + MSB16) == offr))
6741 /* don't crash result[offr] */
6742 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6743 emitcode ("xch", "a,%s",
6744 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6748 movLeft2Result (left, offl, result, offr, 0);
6749 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6751 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6752 assert(strcmp(*lsb,"a"));
6757 _storeAxResults(char *lsb,
6761 _startLazyDPSEvaluation();
6762 if (AOP_NEEDSACC(result))
6764 /* We have to explicitly update the result LSB.
6766 emitcode("xch","a,%s", lsb);
6767 aopPut(AOP(result), "a", offr);
6768 emitcode("mov","a,%s", lsb);
6770 if (getDataSize (result) > 1)
6772 aopPut (AOP (result), "a", offr + MSB16);
6774 _endLazyDPSEvaluation();
6777 /*-----------------------------------------------------------------*/
6778 /* shiftL2Left2Result - shift left two bytes from left to result */
6779 /*-----------------------------------------------------------------*/
6781 shiftL2Left2Result (operand * left, int offl,
6782 operand * result, int offr, int shCount)
6786 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6788 AccAXLsh (lsb, shCount);
6790 _storeAxResults(lsb, result, offr);
6794 #ifdef BETTER_LITERAL_SHIFT
6795 /*-----------------------------------------------------------------*/
6796 /* shiftR2Left2Result - shift right two bytes from left to result */
6797 /*-----------------------------------------------------------------*/
6799 shiftR2Left2Result (operand * left, int offl,
6800 operand * result, int offr,
6801 int shCount, int sign)
6805 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6807 /* a:x >> shCount (x = lsb(result)) */
6810 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6814 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6817 _storeAxResults(lsb, result, offr);
6823 /*-----------------------------------------------------------------*/
6824 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6825 /*-----------------------------------------------------------------*/
6827 shiftLLeftOrResult (operand * left, int offl,
6828 operand * result, int offr, int shCount)
6830 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6831 /* shift left accumulator */
6833 /* or with result */
6834 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6835 /* back to result */
6836 aopPut (AOP (result), "a", offr);
6842 /*-----------------------------------------------------------------*/
6843 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6844 /*-----------------------------------------------------------------*/
6846 shiftRLeftOrResult (operand * left, int offl,
6847 operand * result, int offr, int shCount)
6849 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6850 /* shift right accumulator */
6852 /* or with result */
6853 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6854 /* back to result */
6855 aopPut (AOP (result), "a", offr);
6859 #ifdef BETTER_LITERAL_SHIFT
6860 /*-----------------------------------------------------------------*/
6861 /* genlshOne - left shift a one byte quantity by known count */
6862 /*-----------------------------------------------------------------*/
6864 genlshOne (operand * result, operand * left, int shCount)
6866 D (emitcode (";", "genlshOne "););
6867 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6871 #ifdef BETTER_LITERAL_SHIFT
6872 /*-----------------------------------------------------------------*/
6873 /* genlshTwo - left shift two bytes by known amount != 0 */
6874 /*-----------------------------------------------------------------*/
6876 genlshTwo (operand * result, operand * left, int shCount)
6880 D (emitcode (";", "genlshTwo "););
6882 size = getDataSize (result);
6884 /* if shCount >= 8 */
6889 _startLazyDPSEvaluation();
6895 _endLazyDPSEvaluation();
6896 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6897 aopPut (AOP (result), zero, LSB);
6901 movLeft2Result (left, LSB, result, MSB16, 0);
6902 aopPut (AOP (result), zero, LSB);
6903 _endLazyDPSEvaluation();
6908 aopPut (AOP (result), zero, LSB);
6909 _endLazyDPSEvaluation();
6913 /* 1 <= shCount <= 7 */
6918 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6922 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6930 /*-----------------------------------------------------------------*/
6931 /* shiftLLong - shift left one long from left to result */
6932 /* offl = LSB or MSB16 */
6933 /*-----------------------------------------------------------------*/
6935 shiftLLong (operand * left, operand * result, int offr)
6938 int size = AOP_SIZE (result);
6940 if (size >= LSB + offr)
6942 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6944 emitcode ("add", "a,acc");
6945 if (sameRegs (AOP (left), AOP (result)) &&
6946 size >= MSB16 + offr && offr != LSB)
6947 emitcode ("xch", "a,%s",
6948 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6950 aopPut (AOP (result), "a", LSB + offr);
6953 if (size >= MSB16 + offr)
6955 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6957 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6960 emitcode ("rlc", "a");
6961 if (sameRegs (AOP (left), AOP (result)) &&
6962 size >= MSB24 + offr && offr != LSB)
6963 emitcode ("xch", "a,%s",
6964 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6966 aopPut (AOP (result), "a", MSB16 + offr);
6969 if (size >= MSB24 + offr)
6971 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6973 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6976 emitcode ("rlc", "a");
6977 if (sameRegs (AOP (left), AOP (result)) &&
6978 size >= MSB32 + offr && offr != LSB)
6979 emitcode ("xch", "a,%s",
6980 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6982 aopPut (AOP (result), "a", MSB24 + offr);
6985 if (size > MSB32 + offr)
6987 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6989 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6992 emitcode ("rlc", "a");
6993 aopPut (AOP (result), "a", MSB32 + offr);
6996 aopPut (AOP (result), zero, LSB);
7002 /*-----------------------------------------------------------------*/
7003 /* genlshFour - shift four byte by a known amount != 0 */
7004 /*-----------------------------------------------------------------*/
7006 genlshFour (operand * result, operand * left, int shCount)
7010 D (emitcode (";", "genlshFour ");
7013 size = AOP_SIZE (result);
7015 /* if shifting more that 3 bytes */
7020 /* lowest order of left goes to the highest
7021 order of the destination */
7022 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7024 movLeft2Result (left, LSB, result, MSB32, 0);
7025 aopPut (AOP (result), zero, LSB);
7026 aopPut (AOP (result), zero, MSB16);
7027 aopPut (AOP (result), zero, MSB24);
7031 /* more than two bytes */
7032 else if (shCount >= 16)
7034 /* lower order two bytes goes to higher order two bytes */
7036 /* if some more remaining */
7038 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7041 movLeft2Result (left, MSB16, result, MSB32, 0);
7042 movLeft2Result (left, LSB, result, MSB24, 0);
7044 aopPut (AOP (result), zero, MSB16);
7045 aopPut (AOP (result), zero, LSB);
7049 /* if more than 1 byte */
7050 else if (shCount >= 8)
7052 /* lower order three bytes goes to higher order three bytes */
7057 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7059 movLeft2Result (left, LSB, result, MSB16, 0);
7065 movLeft2Result (left, MSB24, result, MSB32, 0);
7066 movLeft2Result (left, MSB16, result, MSB24, 0);
7067 movLeft2Result (left, LSB, result, MSB16, 0);
7068 aopPut (AOP (result), zero, LSB);
7070 else if (shCount == 1)
7071 shiftLLong (left, result, MSB16);
7074 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7075 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7076 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7077 aopPut (AOP (result), zero, LSB);
7082 /* 1 <= shCount <= 7 */
7083 else if (shCount <= 2)
7085 shiftLLong (left, result, LSB);
7087 shiftLLong (result, result, LSB);
7089 /* 3 <= shCount <= 7, optimize */
7092 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7093 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7094 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7099 #ifdef BETTER_LITERAL_SHIFT
7100 /*-----------------------------------------------------------------*/
7101 /* genLeftShiftLiteral - left shifting by known count */
7102 /*-----------------------------------------------------------------*/
7104 genLeftShiftLiteral (operand * left,
7109 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7112 size = getSize (operandType (result));
7114 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7116 /* We only handle certain easy cases so far. */
7118 && (shCount < (size * 8))
7122 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7126 freeAsmop (right, NULL, ic, TRUE);
7128 aopOp(left, ic, FALSE, FALSE);
7129 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7132 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7134 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7135 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7137 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7140 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7142 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7143 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7145 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7151 emitcode ("; shift left ", "result %d, left %d", size,
7155 /* I suppose that the left size >= result size */
7158 _startLazyDPSEvaluation();
7161 movLeft2Result (left, size, result, size, 0);
7163 _endLazyDPSEvaluation();
7165 else if (shCount >= (size * 8))
7167 _startLazyDPSEvaluation();
7170 aopPut (AOP (result), zero, size);
7172 _endLazyDPSEvaluation();
7179 genlshOne (result, left, shCount);
7183 genlshTwo (result, left, shCount);
7187 genlshFour (result, left, shCount);
7191 fprintf(stderr, "*** ack! mystery literal shift!\n");
7195 freeAsmop (left, NULL, ic, TRUE);
7196 freeAsmop (result, NULL, ic, TRUE);
7201 /*-----------------------------------------------------------------*/
7202 /* genLeftShift - generates code for left shifting */
7203 /*-----------------------------------------------------------------*/
7205 genLeftShift (iCode * ic)
7207 operand *left, *right, *result;
7210 symbol *tlbl, *tlbl1;
7212 D (emitcode (";", "genLeftShift "););
7214 right = IC_RIGHT (ic);
7215 left = IC_LEFT (ic);
7216 result = IC_RESULT (ic);
7218 aopOp (right, ic, FALSE, FALSE);
7221 #ifdef BETTER_LITERAL_SHIFT
7222 /* if the shift count is known then do it
7223 as efficiently as possible */
7224 if (AOP_TYPE (right) == AOP_LIT)
7226 if (genLeftShiftLiteral (left, right, result, ic))
7233 /* shift count is unknown then we have to form
7234 a loop get the loop count in B : Note: we take
7235 only the lower order byte since shifting
7236 more that 32 bits make no sense anyway, ( the
7237 largest size of an object can be only 32 bits ) */
7239 if (AOP_TYPE (right) == AOP_LIT)
7241 /* Really should be handled by genLeftShiftLiteral,
7242 * but since I'm too lazy to fix that today, at least we can make
7243 * some small improvement.
7245 emitcode("mov", "b,#0x%02x",
7246 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7250 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7251 emitcode ("inc", "b");
7253 freeAsmop (right, NULL, ic, TRUE);
7254 aopOp (left, ic, FALSE, FALSE);
7255 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7257 /* now move the left to the result if they are not the
7259 if (!sameRegs (AOP (left), AOP (result)) &&
7260 AOP_SIZE (result) > 1)
7263 size = AOP_SIZE (result);
7265 _startLazyDPSEvaluation ();
7268 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7269 if (*l == '@' && (IS_AOP_PREG (result)))
7272 emitcode ("mov", "a,%s", l);
7273 aopPut (AOP (result), "a", offset);
7276 aopPut (AOP (result), l, offset);
7279 _endLazyDPSEvaluation ();
7282 tlbl = newiTempLabel (NULL);
7283 size = AOP_SIZE (result);
7285 tlbl1 = newiTempLabel (NULL);
7287 /* if it is only one byte then */
7290 symbol *tlbl1 = newiTempLabel (NULL);
7292 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7294 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7295 emitcode ("", "%05d$:", tlbl->key + 100);
7296 emitcode ("add", "a,acc");
7297 emitcode ("", "%05d$:", tlbl1->key + 100);
7298 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7299 aopPut (AOP (result), "a", 0);
7303 reAdjustPreg (AOP (result));
7305 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7306 emitcode ("", "%05d$:", tlbl->key + 100);
7307 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7309 emitcode ("add", "a,acc");
7310 aopPut (AOP (result), "a", offset++);
7311 _startLazyDPSEvaluation ();
7314 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7316 emitcode ("rlc", "a");
7317 aopPut (AOP (result), "a", offset++);
7319 _endLazyDPSEvaluation ();
7320 reAdjustPreg (AOP (result));
7322 emitcode ("", "%05d$:", tlbl1->key + 100);
7323 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7325 freeAsmop (left, NULL, ic, TRUE);
7326 freeAsmop (result, NULL, ic, TRUE);
7329 #ifdef BETTER_LITERAL_SHIFT
7330 /*-----------------------------------------------------------------*/
7331 /* genrshOne - right shift a one byte quantity by known count */
7332 /*-----------------------------------------------------------------*/
7334 genrshOne (operand * result, operand * left,
7335 int shCount, int sign)
7337 D (emitcode (";", "genrshOne"););
7338 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7342 #ifdef BETTER_LITERAL_SHIFT
7343 /*-----------------------------------------------------------------*/
7344 /* genrshTwo - right shift two bytes by known amount != 0 */
7345 /*-----------------------------------------------------------------*/
7347 genrshTwo (operand * result, operand * left,
7348 int shCount, int sign)
7350 D (emitcode (";", "genrshTwo"););
7352 /* if shCount >= 8 */
7356 _startLazyDPSEvaluation();
7359 shiftR1Left2Result (left, MSB16, result, LSB,
7364 movLeft2Result (left, MSB16, result, LSB, sign);
7366 addSign (result, MSB16, sign);
7367 _endLazyDPSEvaluation();
7370 /* 1 <= shCount <= 7 */
7373 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7380 /*-----------------------------------------------------------------*/
7381 /* shiftRLong - shift right one long from left to result */
7382 /* offl = LSB or MSB16 */
7383 /*-----------------------------------------------------------------*/
7385 shiftRLong (operand * left, int offl,
7386 operand * result, int sign)
7389 emitcode ("clr", "c");
7390 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7392 emitcode ("mov", "c,acc.7");
7393 emitcode ("rrc", "a");
7394 aopPut (AOP (result), "a", MSB32 - offl);
7396 /* add sign of "a" */
7397 addSign (result, MSB32, sign);
7399 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7400 emitcode ("rrc", "a");
7401 aopPut (AOP (result), "a", MSB24 - offl);
7403 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7404 emitcode ("rrc", "a");
7405 aopPut (AOP (result), "a", MSB16 - offl);
7409 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7410 emitcode ("rrc", "a");
7411 aopPut (AOP (result), "a", LSB);
7418 /*-----------------------------------------------------------------*/
7419 /* genrshFour - shift four byte by a known amount != 0 */
7420 /*-----------------------------------------------------------------*/
7422 genrshFour (operand * result, operand * left,
7423 int shCount, int sign)
7425 D (emitcode (";", "genrshFour");
7428 /* if shifting more that 3 bytes */
7433 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7435 movLeft2Result (left, MSB32, result, LSB, sign);
7436 addSign (result, MSB16, sign);
7438 else if (shCount >= 16)
7442 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7445 movLeft2Result (left, MSB24, result, LSB, 0);
7446 movLeft2Result (left, MSB32, result, MSB16, sign);
7448 addSign (result, MSB24, sign);
7450 else if (shCount >= 8)
7454 shiftRLong (left, MSB16, result, sign);
7455 else if (shCount == 0)
7457 movLeft2Result (left, MSB16, result, LSB, 0);
7458 movLeft2Result (left, MSB24, result, MSB16, 0);
7459 movLeft2Result (left, MSB32, result, MSB24, sign);
7460 addSign (result, MSB32, sign);
7464 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7465 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7466 /* the last shift is signed */
7467 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7468 addSign (result, MSB32, sign);
7472 { /* 1 <= shCount <= 7 */
7475 shiftRLong (left, LSB, result, sign);
7477 shiftRLong (result, LSB, result, sign);
7481 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7482 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7483 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7489 #ifdef BETTER_LITERAL_SHIFT
7490 /*-----------------------------------------------------------------*/
7491 /* genRightShiftLiteral - right shifting by known count */
7492 /*-----------------------------------------------------------------*/
7494 genRightShiftLiteral (operand * left,
7500 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7503 size = getSize (operandType (result));
7505 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7507 /* We only handle certain easy cases so far. */
7509 && (shCount < (size * 8))
7513 D(emitcode (";", "genRightShiftLiteral wimping out"););
7517 freeAsmop (right, NULL, ic, TRUE);
7519 aopOp (left, ic, FALSE, FALSE);
7520 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7523 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7527 /* test the LEFT size !!! */
7529 /* I suppose that the left size >= result size */
7532 size = getDataSize (result);
7533 _startLazyDPSEvaluation();
7536 movLeft2Result (left, size, result, size, 0);
7538 _endLazyDPSEvaluation();
7540 else if (shCount >= (size * 8))
7544 /* get sign in acc.7 */
7545 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7547 addSign (result, LSB, sign);
7554 genrshOne (result, left, shCount, sign);
7558 genrshTwo (result, left, shCount, sign);
7562 genrshFour (result, left, shCount, sign);
7569 freeAsmop (left, NULL, ic, TRUE);
7570 freeAsmop (result, NULL, ic, TRUE);
7576 /*-----------------------------------------------------------------*/
7577 /* genSignedRightShift - right shift of signed number */
7578 /*-----------------------------------------------------------------*/
7580 genSignedRightShift (iCode * ic)
7582 operand *right, *left, *result;
7585 symbol *tlbl, *tlbl1;
7587 D (emitcode (";", "genSignedRightShift "););
7589 /* we do it the hard way put the shift count in b
7590 and loop thru preserving the sign */
7592 right = IC_RIGHT (ic);
7593 left = IC_LEFT (ic);
7594 result = IC_RESULT (ic);
7596 aopOp (right, ic, FALSE, FALSE);
7598 #ifdef BETTER_LITERAL_SHIFT
7599 if (AOP_TYPE (right) == AOP_LIT)
7601 if (genRightShiftLiteral (left, right, result, ic, 1))
7607 /* shift count is unknown then we have to form
7608 a loop get the loop count in B : Note: we take
7609 only the lower order byte since shifting
7610 more that 32 bits make no sense anyway, ( the
7611 largest size of an object can be only 32 bits ) */
7613 if (AOP_TYPE (right) == AOP_LIT)
7615 /* Really should be handled by genRightShiftLiteral,
7616 * but since I'm too lazy to fix that today, at least we can make
7617 * some small improvement.
7619 emitcode("mov", "b,#0x%02x",
7620 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7624 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7625 emitcode ("inc", "b");
7627 freeAsmop (right, NULL, ic, TRUE);
7628 aopOp (left, ic, FALSE, FALSE);
7629 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7631 /* now move the left to the result if they are not the
7633 if (!sameRegs (AOP (left), AOP (result)) &&
7634 AOP_SIZE (result) > 1)
7637 size = AOP_SIZE (result);
7639 _startLazyDPSEvaluation ();
7642 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7643 if (*l == '@' && IS_AOP_PREG (result))
7646 emitcode ("mov", "a,%s", l);
7647 aopPut (AOP (result), "a", offset);
7650 aopPut (AOP (result), l, offset);
7653 _endLazyDPSEvaluation ();
7656 /* mov the highest order bit to OVR */
7657 tlbl = newiTempLabel (NULL);
7658 tlbl1 = newiTempLabel (NULL);
7660 size = AOP_SIZE (result);
7662 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7663 emitcode ("rlc", "a");
7664 emitcode ("mov", "ov,c");
7665 /* if it is only one byte then */
7668 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7670 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7671 emitcode ("", "%05d$:", tlbl->key + 100);
7672 emitcode ("mov", "c,ov");
7673 emitcode ("rrc", "a");
7674 emitcode ("", "%05d$:", tlbl1->key + 100);
7675 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7676 aopPut (AOP (result), "a", 0);
7680 reAdjustPreg (AOP (result));
7681 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7682 emitcode ("", "%05d$:", tlbl->key + 100);
7683 emitcode ("mov", "c,ov");
7684 _startLazyDPSEvaluation ();
7687 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7689 emitcode ("rrc", "a");
7690 aopPut (AOP (result), "a", offset--);
7692 _endLazyDPSEvaluation ();
7693 reAdjustPreg (AOP (result));
7694 emitcode ("", "%05d$:", tlbl1->key + 100);
7695 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7698 freeAsmop (left, NULL, ic, TRUE);
7699 freeAsmop (result, NULL, ic, TRUE);
7702 /*-----------------------------------------------------------------*/
7703 /* genRightShift - generate code for right shifting */
7704 /*-----------------------------------------------------------------*/
7706 genRightShift (iCode * ic)
7708 operand *right, *left, *result;
7712 symbol *tlbl, *tlbl1;
7714 D (emitcode (";", "genRightShift "););
7716 /* if signed then we do it the hard way preserve the
7717 sign bit moving it inwards */
7718 retype = getSpec (operandType (IC_RESULT (ic)));
7720 if (!SPEC_USIGN (retype))
7722 genSignedRightShift (ic);
7726 /* signed & unsigned types are treated the same : i.e. the
7727 signed is NOT propagated inwards : quoting from the
7728 ANSI - standard : "for E1 >> E2, is equivalent to division
7729 by 2**E2 if unsigned or if it has a non-negative value,
7730 otherwise the result is implementation defined ", MY definition
7731 is that the sign does not get propagated */
7733 right = IC_RIGHT (ic);
7734 left = IC_LEFT (ic);
7735 result = IC_RESULT (ic);
7737 aopOp (right, ic, FALSE, FALSE);
7739 #ifdef BETTER_LITERAL_SHIFT
7740 /* if the shift count is known then do it
7741 as efficiently as possible */
7742 if (AOP_TYPE (right) == AOP_LIT)
7744 if (genRightShiftLiteral (left, right, result, ic, 0))
7751 /* shift count is unknown then we have to form
7752 a loop get the loop count in B : Note: we take
7753 only the lower order byte since shifting
7754 more that 32 bits make no sense anyway, ( the
7755 largest size of an object can be only 32 bits ) */
7757 if (AOP_TYPE (right) == AOP_LIT)
7759 /* Really should be handled by genRightShiftLiteral,
7760 * but since I'm too lazy to fix that today, at least we can make
7761 * some small improvement.
7763 emitcode("mov", "b,#0x%02x",
7764 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7768 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7769 emitcode ("inc", "b");
7771 freeAsmop (right, NULL, ic, TRUE);
7772 aopOp (left, ic, FALSE, FALSE);
7773 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7775 /* now move the left to the result if they are not the
7777 if (!sameRegs (AOP (left), AOP (result)) &&
7778 AOP_SIZE (result) > 1)
7781 size = AOP_SIZE (result);
7783 _startLazyDPSEvaluation ();
7786 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7787 if (*l == '@' && IS_AOP_PREG (result))
7790 emitcode ("mov", "a,%s", l);
7791 aopPut (AOP (result), "a", offset);
7794 aopPut (AOP (result), l, offset);
7797 _endLazyDPSEvaluation ();
7800 tlbl = newiTempLabel (NULL);
7801 tlbl1 = newiTempLabel (NULL);
7802 size = AOP_SIZE (result);
7805 /* if it is only one byte then */
7808 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7810 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7811 emitcode ("", "%05d$:", tlbl->key + 100);
7813 emitcode ("rrc", "a");
7814 emitcode ("", "%05d$:", tlbl1->key + 100);
7815 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7816 aopPut (AOP (result), "a", 0);
7820 reAdjustPreg (AOP (result));
7821 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7822 emitcode ("", "%05d$:", tlbl->key + 100);
7824 _startLazyDPSEvaluation ();
7827 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7829 emitcode ("rrc", "a");
7830 aopPut (AOP (result), "a", offset--);
7832 _endLazyDPSEvaluation ();
7833 reAdjustPreg (AOP (result));
7835 emitcode ("", "%05d$:", tlbl1->key + 100);
7836 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7839 freeAsmop (left, NULL, ic, TRUE);
7840 freeAsmop (result, NULL, ic, TRUE);
7843 /*-----------------------------------------------------------------*/
7844 /* genUnpackBits - generates code for unpacking bits */
7845 /*-----------------------------------------------------------------*/
7847 genUnpackBits (operand * result, char *rname, int ptype)
7854 D (emitcode (";", "genUnpackBits ");
7857 etype = getSpec (operandType (result));
7859 /* read the first byte */
7865 emitcode ("mov", "a,@%s", rname);
7869 emitcode ("movx", "a,@%s", rname);
7873 emitcode ("movx", "a,@dptr");
7877 emitcode ("clr", "a");
7878 emitcode ("movc", "a", "@a+dptr");
7882 emitcode ("lcall", "__gptrget");
7886 /* if we have bitdisplacement then it fits */
7887 /* into this byte completely or if length is */
7888 /* less than a byte */
7889 if ((shCnt = SPEC_BSTR (etype)) ||
7890 (SPEC_BLEN (etype) <= 8))
7893 /* shift right acc */
7896 emitcode ("anl", "a,#0x%02x",
7897 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7898 aopPut (AOP (result), "a", offset);
7902 /* bit field did not fit in a byte */
7903 rlen = SPEC_BLEN (etype) - 8;
7904 aopPut (AOP (result), "a", offset++);
7913 emitcode ("inc", "%s", rname);
7914 emitcode ("mov", "a,@%s", rname);
7918 emitcode ("inc", "%s", rname);
7919 emitcode ("movx", "a,@%s", rname);
7923 emitcode ("inc", "dptr");
7924 emitcode ("movx", "a,@dptr");
7928 emitcode ("clr", "a");
7929 emitcode ("inc", "dptr");
7930 emitcode ("movc", "a", "@a+dptr");
7934 emitcode ("inc", "dptr");
7935 emitcode ("lcall", "__gptrget");
7940 /* if we are done */
7944 aopPut (AOP (result), "a", offset++);
7950 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7951 aopPut (AOP (result), "a", offset);
7958 /*-----------------------------------------------------------------*/
7959 /* genDataPointerGet - generates code when ptr offset is known */
7960 /*-----------------------------------------------------------------*/
7962 genDataPointerGet (operand * left,
7968 int size, offset = 0;
7969 aopOp (result, ic, TRUE, FALSE);
7971 /* get the string representation of the name */
7972 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7973 size = AOP_SIZE (result);
7974 _startLazyDPSEvaluation ();
7978 sprintf (buffer, "(%s + %d)", l + 1, offset);
7980 sprintf (buffer, "%s", l + 1);
7981 aopPut (AOP (result), buffer, offset++);
7983 _endLazyDPSEvaluation ();
7985 freeAsmop (left, NULL, ic, TRUE);
7986 freeAsmop (result, NULL, ic, TRUE);
7989 /*-----------------------------------------------------------------*/
7990 /* genNearPointerGet - emitcode for near pointer fetch */
7991 /*-----------------------------------------------------------------*/
7993 genNearPointerGet (operand * left,
8000 sym_link *rtype, *retype, *letype;
8001 sym_link *ltype = operandType (left);
8004 rtype = operandType (result);
8005 retype = getSpec (rtype);
8006 letype = getSpec (ltype);
8008 aopOp (left, ic, FALSE, FALSE);
8010 /* if left is rematerialisable and
8011 result is not bit variable type and
8012 the left is pointer to data space i.e
8013 lower 128 bytes of space */
8014 if (AOP_TYPE (left) == AOP_IMMD &&
8015 !IS_BITVAR (retype) &&
8016 !IS_BITVAR (letype) &&
8017 DCL_TYPE (ltype) == POINTER)
8019 genDataPointerGet (left, result, ic);
8023 /* if the value is already in a pointer register
8024 then don't need anything more */
8025 if (!AOP_INPREG (AOP (left)))
8027 /* otherwise get a free pointer register */
8029 preg = getFreePtr (ic, &aop, FALSE);
8030 emitcode ("mov", "%s,%s",
8032 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8036 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8038 freeAsmop (left, NULL, ic, TRUE);
8039 aopOp (result, ic, FALSE, FALSE);
8041 /* if bitfield then unpack the bits */
8042 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8043 genUnpackBits (result, rname, POINTER);
8046 /* we have can just get the values */
8047 int size = AOP_SIZE (result);
8052 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8055 emitcode ("mov", "a,@%s", rname);
8056 aopPut (AOP (result), "a", offset);
8060 sprintf (buffer, "@%s", rname);
8061 aopPut (AOP (result), buffer, offset);
8065 emitcode ("inc", "%s", rname);
8069 /* now some housekeeping stuff */
8072 /* we had to allocate for this iCode */
8073 freeAsmop (NULL, aop, ic, TRUE);
8077 /* we did not allocate which means left
8078 already in a pointer register, then
8079 if size > 0 && this could be used again
8080 we have to point it back to where it
8082 if (AOP_SIZE (result) > 1 &&
8083 !OP_SYMBOL (left)->remat &&
8084 (OP_SYMBOL (left)->liveTo > ic->seq ||
8087 int size = AOP_SIZE (result) - 1;
8089 emitcode ("dec", "%s", rname);
8094 freeAsmop (result, NULL, ic, TRUE);
8098 /*-----------------------------------------------------------------*/
8099 /* genPagedPointerGet - emitcode for paged pointer fetch */
8100 /*-----------------------------------------------------------------*/
8102 genPagedPointerGet (operand * left,
8109 sym_link *rtype, *retype, *letype;
8111 rtype = operandType (result);
8112 retype = getSpec (rtype);
8113 letype = getSpec (operandType (left));
8114 aopOp (left, ic, FALSE, FALSE);
8116 /* if the value is already in a pointer register
8117 then don't need anything more */
8118 if (!AOP_INPREG (AOP (left)))
8120 /* otherwise get a free pointer register */
8122 preg = getFreePtr (ic, &aop, FALSE);
8123 emitcode ("mov", "%s,%s",
8125 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8129 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8131 freeAsmop (left, NULL, ic, TRUE);
8132 aopOp (result, ic, FALSE, FALSE);
8134 /* if bitfield then unpack the bits */
8135 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8136 genUnpackBits (result, rname, PPOINTER);
8139 /* we have can just get the values */
8140 int size = AOP_SIZE (result);
8146 emitcode ("movx", "a,@%s", rname);
8147 aopPut (AOP (result), "a", offset);
8152 emitcode ("inc", "%s", rname);
8156 /* now some housekeeping stuff */
8159 /* we had to allocate for this iCode */
8160 freeAsmop (NULL, aop, ic, TRUE);
8164 /* we did not allocate which means left
8165 already in a pointer register, then
8166 if size > 0 && this could be used again
8167 we have to point it back to where it
8169 if (AOP_SIZE (result) > 1 &&
8170 !OP_SYMBOL (left)->remat &&
8171 (OP_SYMBOL (left)->liveTo > ic->seq ||
8174 int size = AOP_SIZE (result) - 1;
8176 emitcode ("dec", "%s", rname);
8181 freeAsmop (result, NULL, ic, TRUE);
8186 /*-----------------------------------------------------------------*/
8187 /* genFarPointerGet - gget value from far space */
8188 /*-----------------------------------------------------------------*/
8190 genFarPointerGet (operand * left,
8191 operand * result, iCode * ic)
8194 sym_link *retype = getSpec (operandType (result));
8195 sym_link *letype = getSpec (operandType (left));
8196 D (emitcode (";", "genFarPointerGet");
8199 aopOp (left, ic, FALSE, FALSE);
8201 /* if the operand is already in dptr
8202 then we do nothing else we move the value to dptr */
8203 if (AOP_TYPE (left) != AOP_STR)
8205 /* if this is remateriazable */
8206 if (AOP_TYPE (left) == AOP_IMMD)
8208 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8212 /* we need to get it byte by byte */
8213 _startLazyDPSEvaluation ();
8214 if (AOP_TYPE (left) != AOP_DPTR)
8216 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8217 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8218 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8222 /* We need to generate a load to DPTR indirect through DPTR. */
8223 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8225 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8226 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8227 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8228 emitcode ("pop", "dph");
8229 emitcode ("pop", "dpl");
8231 _endLazyDPSEvaluation ();
8234 /* so dptr know contains the address */
8235 freeAsmop (left, NULL, ic, TRUE);
8236 aopOp (result, ic, FALSE, TRUE);
8238 /* if bit then unpack */
8239 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8240 genUnpackBits (result, "dptr", FPOINTER);
8243 size = AOP_SIZE (result);
8246 _startLazyDPSEvaluation ();
8253 emitcode ("movx", "a,@dptr");
8255 emitcode ("inc", "dptr");
8257 aopPut (AOP (result), "a", offset++);
8259 _endLazyDPSEvaluation ();
8262 freeAsmop (result, NULL, ic, TRUE);
8265 /*-----------------------------------------------------------------*/
8266 /* emitcodePointerGet - gget value from code space */
8267 /*-----------------------------------------------------------------*/
8269 emitcodePointerGet (operand * left,
8270 operand * result, iCode * ic)
8273 sym_link *retype = getSpec (operandType (result));
8275 aopOp (left, ic, FALSE, FALSE);
8277 /* if the operand is already in dptr
8278 then we do nothing else we move the value to dptr */
8279 if (AOP_TYPE (left) != AOP_STR)
8281 /* if this is remateriazable */
8282 if (AOP_TYPE (left) == AOP_IMMD)
8284 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8287 { /* we need to get it byte by byte */
8288 _startLazyDPSEvaluation ();
8289 if (AOP_TYPE (left) != AOP_DPTR)
8291 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8292 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8293 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8297 /* We need to generate a load to DPTR indirect through DPTR. */
8298 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8300 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8301 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8302 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8303 emitcode ("pop", "dph");
8304 emitcode ("pop", "dpl");
8306 _endLazyDPSEvaluation ();
8309 /* so dptr know contains the address */
8310 freeAsmop (left, NULL, ic, TRUE);
8311 aopOp (result, ic, FALSE, TRUE);
8313 /* if bit then unpack */
8314 if (IS_BITVAR (retype))
8315 genUnpackBits (result, "dptr", CPOINTER);
8318 size = AOP_SIZE (result);
8321 _startLazyDPSEvaluation ();
8327 emitcode ("clr", "a");
8328 emitcode ("movc", "a,@a+dptr");
8330 emitcode ("inc", "dptr");
8331 aopPut (AOP (result), "a", offset++);
8333 _endLazyDPSEvaluation ();
8336 freeAsmop (result, NULL, ic, TRUE);
8339 /*-----------------------------------------------------------------*/
8340 /* genGenPointerGet - gget value from generic pointer space */
8341 /*-----------------------------------------------------------------*/
8343 genGenPointerGet (operand * left,
8344 operand * result, iCode * ic)
8347 sym_link *retype = getSpec (operandType (result));
8348 sym_link *letype = getSpec (operandType (left));
8350 D (emitcode (";", "genGenPointerGet "); );
8352 aopOp (left, ic, FALSE, TRUE);
8354 /* if the operand is already in dptr
8355 then we do nothing else we move the value to dptr */
8356 if (AOP_TYPE (left) != AOP_STR)
8358 /* if this is remateriazable */
8359 if (AOP_TYPE (left) == AOP_IMMD)
8361 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8362 emitcode ("mov", "b,#%d", pointerCode (retype));
8365 { /* we need to get it byte by byte */
8366 _startLazyDPSEvaluation ();
8367 if (AOP(left)->type==AOP_DPTR2) {
8369 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8372 emitcode ("mov", "dpl,%s", l);
8373 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8376 emitcode ("mov", "dph,%s", l);
8377 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8380 emitcode ("mov", "dpx,%s", l);
8381 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8383 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8384 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8385 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8386 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8388 _endLazyDPSEvaluation ();
8391 /* so dptr know contains the address */
8392 freeAsmop (left, NULL, ic, TRUE);
8393 aopOp (result, ic, FALSE, TRUE);
8395 /* if bit then unpack */
8396 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8397 genUnpackBits (result, "dptr", GPOINTER);
8400 size = AOP_SIZE (result);
8405 emitcode ("lcall", "__gptrget");
8406 aopPut (AOP (result), "a", offset++);
8408 emitcode ("inc", "dptr");
8412 freeAsmop (result, NULL, ic, TRUE);
8415 /*-----------------------------------------------------------------*/
8416 /* genPointerGet - generate code for pointer get */
8417 /*-----------------------------------------------------------------*/
8419 genPointerGet (iCode * ic)
8421 operand *left, *result;
8422 sym_link *type, *etype;
8425 D (emitcode (";", "genPointerGet ");
8428 left = IC_LEFT (ic);
8429 result = IC_RESULT (ic);
8431 /* depending on the type of pointer we need to
8432 move it to the correct pointer register */
8433 type = operandType (left);
8434 etype = getSpec (type);
8435 /* if left is of type of pointer then it is simple */
8436 if (IS_PTR (type) && !IS_FUNC (type->next))
8437 p_type = DCL_TYPE (type);
8440 /* we have to go by the storage class */
8441 p_type = PTR_TYPE (SPEC_OCLS (etype));
8444 /* now that we have the pointer type we assign
8445 the pointer values */
8451 genNearPointerGet (left, result, ic);
8455 genPagedPointerGet (left, result, ic);
8459 genFarPointerGet (left, result, ic);
8463 emitcodePointerGet (left, result, ic);
8467 genGenPointerGet (left, result, ic);
8473 /*-----------------------------------------------------------------*/
8474 /* genPackBits - generates code for packed bit storage */
8475 /*-----------------------------------------------------------------*/
8477 genPackBits (sym_link * etype,
8479 char *rname, int p_type)
8487 blen = SPEC_BLEN (etype);
8488 bstr = SPEC_BSTR (etype);
8490 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8493 /* if the bit lenth is less than or */
8494 /* it exactly fits a byte then */
8495 if (SPEC_BLEN (etype) <= 8)
8497 shCount = SPEC_BSTR (etype);
8499 /* shift left acc */
8502 if (SPEC_BLEN (etype) < 8)
8503 { /* if smaller than a byte */
8509 emitcode ("mov", "b,a");
8510 emitcode ("mov", "a,@%s", rname);
8514 emitcode ("mov", "b,a");
8515 emitcode ("movx", "a,@dptr");
8519 emitcode ("push", "b");
8520 emitcode ("push", "acc");
8521 emitcode ("lcall", "__gptrget");
8522 emitcode ("pop", "b");
8526 emitcode ("anl", "a,#0x%02x", (unsigned char)
8527 ((unsigned char) (0xFF << (blen + bstr)) |
8528 (unsigned char) (0xFF >> (8 - bstr))));
8529 emitcode ("orl", "a,b");
8530 if (p_type == GPOINTER)
8531 emitcode ("pop", "b");
8538 emitcode ("mov", "@%s,a", rname);
8542 emitcode ("movx", "@dptr,a");
8546 emitcode ("lcall", "__gptrput");
8551 if (SPEC_BLEN (etype) <= 8)
8554 emitcode ("inc", "%s", rname);
8555 rLen = SPEC_BLEN (etype);
8557 /* now generate for lengths greater than one byte */
8561 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8573 emitcode ("mov", "@%s,a", rname);
8576 emitcode ("mov", "@%s,%s", rname, l);
8581 emitcode ("movx", "@dptr,a");
8586 emitcode ("lcall", "__gptrput");
8589 emitcode ("inc", "%s", rname);
8594 /* last last was not complete */
8597 /* save the byte & read byte */
8601 emitcode ("mov", "b,a");
8602 emitcode ("mov", "a,@%s", rname);
8606 emitcode ("mov", "b,a");
8607 emitcode ("movx", "a,@dptr");
8611 emitcode ("push", "b");
8612 emitcode ("push", "acc");
8613 emitcode ("lcall", "__gptrget");
8614 emitcode ("pop", "b");
8618 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8619 emitcode ("orl", "a,b");
8622 if (p_type == GPOINTER)
8623 emitcode ("pop", "b");
8629 emitcode ("mov", "@%s,a", rname);
8633 emitcode ("movx", "@dptr,a");
8637 emitcode ("lcall", "__gptrput");
8641 /*-----------------------------------------------------------------*/
8642 /* genDataPointerSet - remat pointer to data space */
8643 /*-----------------------------------------------------------------*/
8645 genDataPointerSet (operand * right,
8649 int size, offset = 0;
8650 char *l, buffer[256];
8652 aopOp (right, ic, FALSE, FALSE);
8654 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8655 size = AOP_SIZE (right);
8659 sprintf (buffer, "(%s + %d)", l + 1, offset);
8661 sprintf (buffer, "%s", l + 1);
8662 emitcode ("mov", "%s,%s", buffer,
8663 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8666 freeAsmop (right, NULL, ic, TRUE);
8667 freeAsmop (result, NULL, ic, TRUE);
8670 /*-----------------------------------------------------------------*/
8671 /* genNearPointerSet - emitcode for near pointer put */
8672 /*-----------------------------------------------------------------*/
8674 genNearPointerSet (operand * right,
8681 sym_link *retype, *letype;
8682 sym_link *ptype = operandType (result);
8684 retype = getSpec (operandType (right));
8685 letype = getSpec (ptype);
8687 aopOp (result, ic, FALSE, FALSE);
8689 /* if the result is rematerializable &
8690 in data space & not a bit variable */
8691 if (AOP_TYPE (result) == AOP_IMMD &&
8692 DCL_TYPE (ptype) == POINTER &&
8693 !IS_BITVAR (retype) &&
8694 !IS_BITVAR (letype))
8696 genDataPointerSet (right, result, ic);
8700 /* if the value is already in a pointer register
8701 then don't need anything more */
8702 if (!AOP_INPREG (AOP (result)))
8704 /* otherwise get a free pointer register */
8706 preg = getFreePtr (ic, &aop, FALSE);
8707 emitcode ("mov", "%s,%s",
8709 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8713 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8715 freeAsmop (result, NULL, ic, TRUE);
8716 aopOp (right, ic, FALSE, FALSE);
8718 /* if bitfield then unpack the bits */
8719 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8720 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8723 /* we have can just get the values */
8724 int size = AOP_SIZE (right);
8729 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8733 emitcode ("mov", "@%s,a", rname);
8736 emitcode ("mov", "@%s,%s", rname, l);
8738 emitcode ("inc", "%s", rname);
8743 /* now some housekeeping stuff */
8746 /* we had to allocate for this iCode */
8747 freeAsmop (NULL, aop, ic, TRUE);
8751 /* we did not allocate which means left
8752 already in a pointer register, then
8753 if size > 0 && this could be used again
8754 we have to point it back to where it
8756 if (AOP_SIZE (right) > 1 &&
8757 !OP_SYMBOL (result)->remat &&
8758 (OP_SYMBOL (result)->liveTo > ic->seq ||
8761 int size = AOP_SIZE (right) - 1;
8763 emitcode ("dec", "%s", rname);
8768 freeAsmop (right, NULL, ic, TRUE);
8773 /*-----------------------------------------------------------------*/
8774 /* genPagedPointerSet - emitcode for Paged pointer put */
8775 /*-----------------------------------------------------------------*/
8777 genPagedPointerSet (operand * right,
8784 sym_link *retype, *letype;
8786 retype = getSpec (operandType (right));
8787 letype = getSpec (operandType (result));
8789 aopOp (result, ic, FALSE, FALSE);
8791 /* if the value is already in a pointer register
8792 then don't need anything more */
8793 if (!AOP_INPREG (AOP (result)))
8795 /* otherwise get a free pointer register */
8797 preg = getFreePtr (ic, &aop, FALSE);
8798 emitcode ("mov", "%s,%s",
8800 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8804 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8806 freeAsmop (result, NULL, ic, TRUE);
8807 aopOp (right, ic, FALSE, FALSE);
8809 /* if bitfield then unpack the bits */
8810 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8811 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8814 /* we have can just get the values */
8815 int size = AOP_SIZE (right);
8820 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8823 emitcode ("movx", "@%s,a", rname);
8826 emitcode ("inc", "%s", rname);
8832 /* now some housekeeping stuff */
8835 /* we had to allocate for this iCode */
8836 freeAsmop (NULL, aop, ic, TRUE);
8840 /* we did not allocate which means left
8841 already in a pointer register, then
8842 if size > 0 && this could be used again
8843 we have to point it back to where it
8845 if (AOP_SIZE (right) > 1 &&
8846 !OP_SYMBOL (result)->remat &&
8847 (OP_SYMBOL (result)->liveTo > ic->seq ||
8850 int size = AOP_SIZE (right) - 1;
8852 emitcode ("dec", "%s", rname);
8857 freeAsmop (right, NULL, ic, TRUE);
8862 /*-----------------------------------------------------------------*/
8863 /* genFarPointerSet - set value from far space */
8864 /*-----------------------------------------------------------------*/
8866 genFarPointerSet (operand * right,
8867 operand * result, iCode * ic)
8870 sym_link *retype = getSpec (operandType (right));
8871 sym_link *letype = getSpec (operandType (result));
8873 aopOp (result, ic, FALSE, FALSE);
8875 /* if the operand is already in dptr
8876 then we do nothing else we move the value to dptr */
8877 if (AOP_TYPE (result) != AOP_STR)
8879 /* if this is remateriazable */
8880 if (AOP_TYPE (result) == AOP_IMMD)
8881 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8884 /* we need to get it byte by byte */
8885 _startLazyDPSEvaluation ();
8886 if (AOP_TYPE (result) != AOP_DPTR)
8888 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8889 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8890 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8894 /* We need to generate a load to DPTR indirect through DPTR. */
8895 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8897 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8898 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8899 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8900 emitcode ("pop", "dph");
8901 emitcode ("pop", "dpl");
8903 _endLazyDPSEvaluation ();
8906 /* so dptr know contains the address */
8907 freeAsmop (result, NULL, ic, TRUE);
8908 aopOp (right, ic, FALSE, TRUE);
8910 /* if bit then unpack */
8911 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8912 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8915 size = AOP_SIZE (right);
8918 _startLazyDPSEvaluation ();
8921 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8927 emitcode ("movx", "@dptr,a");
8929 emitcode ("inc", "dptr");
8931 _endLazyDPSEvaluation ();
8934 freeAsmop (right, NULL, ic, TRUE);
8937 /*-----------------------------------------------------------------*/
8938 /* genGenPointerSet - set value from generic pointer space */
8939 /*-----------------------------------------------------------------*/
8941 genGenPointerSet (operand * right,
8942 operand * result, iCode * ic)
8945 sym_link *retype = getSpec (operandType (right));
8946 sym_link *letype = getSpec (operandType (result));
8948 aopOp (result, ic, FALSE, TRUE);
8950 /* if the operand is already in dptr
8951 then we do nothing else we move the value to dptr */
8952 if (AOP_TYPE (result) != AOP_STR)
8954 _startLazyDPSEvaluation ();
8955 /* if this is remateriazable */
8956 if (AOP_TYPE (result) == AOP_IMMD)
8958 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8959 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8962 { /* we need to get it byte by byte */
8963 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8964 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8965 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8966 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8968 _endLazyDPSEvaluation ();
8970 /* so dptr know contains the address */
8971 freeAsmop (result, NULL, ic, TRUE);
8972 aopOp (right, ic, FALSE, TRUE);
8974 /* if bit then unpack */
8975 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8976 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8979 size = AOP_SIZE (right);
8982 _startLazyDPSEvaluation ();
8985 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8991 emitcode ("lcall", "__gptrput");
8993 emitcode ("inc", "dptr");
8995 _endLazyDPSEvaluation ();
8998 freeAsmop (right, NULL, ic, TRUE);
9001 /*-----------------------------------------------------------------*/
9002 /* genPointerSet - stores the value into a pointer location */
9003 /*-----------------------------------------------------------------*/
9005 genPointerSet (iCode * ic)
9007 operand *right, *result;
9008 sym_link *type, *etype;
9011 D (emitcode (";", "genPointerSet ");
9014 right = IC_RIGHT (ic);
9015 result = IC_RESULT (ic);
9017 /* depending on the type of pointer we need to
9018 move it to the correct pointer register */
9019 type = operandType (result);
9020 etype = getSpec (type);
9021 /* if left is of type of pointer then it is simple */
9022 if (IS_PTR (type) && !IS_FUNC (type->next))
9024 p_type = DCL_TYPE (type);
9028 /* we have to go by the storage class */
9029 p_type = PTR_TYPE (SPEC_OCLS (etype));
9032 /* now that we have the pointer type we assign
9033 the pointer values */
9039 genNearPointerSet (right, result, ic);
9043 genPagedPointerSet (right, result, ic);
9047 genFarPointerSet (right, result, ic);
9051 genGenPointerSet (right, result, ic);
9057 /*-----------------------------------------------------------------*/
9058 /* genIfx - generate code for Ifx statement */
9059 /*-----------------------------------------------------------------*/
9061 genIfx (iCode * ic, iCode * popIc)
9063 operand *cond = IC_COND (ic);
9066 D (emitcode (";", "genIfx "););
9068 aopOp (cond, ic, FALSE, FALSE);
9070 /* get the value into acc */
9071 if (AOP_TYPE (cond) != AOP_CRY)
9075 /* the result is now in the accumulator */
9076 freeAsmop (cond, NULL, ic, TRUE);
9078 /* if there was something to be popped then do it */
9082 /* if the condition is a bit variable */
9083 if (isbit && IS_ITEMP (cond) &&
9085 genIfxJump (ic, SPIL_LOC (cond)->rname);
9086 else if (isbit && !IS_ITEMP (cond))
9087 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9089 genIfxJump (ic, "a");
9094 /*-----------------------------------------------------------------*/
9095 /* genAddrOf - generates code for address of */
9096 /*-----------------------------------------------------------------*/
9098 genAddrOf (iCode * ic)
9100 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9103 D (emitcode (";", "genAddrOf ");
9106 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9108 /* if the operand is on the stack then we
9109 need to get the stack offset of this
9113 /* if it has an offset then we need to compute
9117 emitcode ("mov", "a,_bp");
9118 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9119 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9123 /* we can just move _bp */
9124 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9126 /* fill the result with zero */
9127 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9130 if (options.stack10bit && size < (FPTRSIZE - 1))
9133 "*** warning: pointer to stack var truncated.\n");
9140 if (options.stack10bit && offset == 2)
9142 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9146 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9153 /* object not on stack then we need the name */
9154 size = AOP_SIZE (IC_RESULT (ic));
9159 char s[SDCC_NAME_MAX];
9161 sprintf (s, "#(%s >> %d)",
9165 sprintf (s, "#%s", sym->rname);
9166 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9170 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9174 /*-----------------------------------------------------------------*/
9175 /* genFarFarAssign - assignment when both are in far space */
9176 /*-----------------------------------------------------------------*/
9178 genFarFarAssign (operand * result, operand * right, iCode * ic)
9180 int size = AOP_SIZE (right);
9182 symbol *rSym = NULL;
9186 /* quick & easy case. */
9187 D(emitcode(";","genFarFarAssign (1 byte case)"););
9188 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9189 freeAsmop (right, NULL, ic, FALSE);
9190 /* now assign DPTR to result */
9192 aopOp(result, ic, FALSE, FALSE);
9194 aopPut(AOP(result), "a", 0);
9195 freeAsmop(result, NULL, ic, FALSE);
9199 /* See if we've got an underlying symbol to abuse. */
9200 if (IS_SYMOP(result) && OP_SYMBOL(result))
9202 if (IS_TRUE_SYMOP(result))
9204 rSym = OP_SYMBOL(result);
9206 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9208 rSym = OP_SYMBOL(result)->usl.spillLoc;
9212 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9214 /* We can use the '390 auto-toggle feature to good effect here. */
9216 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9217 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9218 emitcode ("mov", "dptr,#%s", rSym->rname);
9219 /* DP2 = result, DP1 = right, DP1 is current. */
9222 emitcode("movx", "a,@dptr");
9223 emitcode("movx", "@dptr,a");
9226 emitcode("inc", "dptr");
9227 emitcode("inc", "dptr");
9230 emitcode("mov", "dps, #0");
9231 freeAsmop (right, NULL, ic, FALSE);
9235 D (emitcode (";", "genFarFarAssign"););
9236 aopOp (result, ic, TRUE, TRUE);
9238 _startLazyDPSEvaluation ();
9242 aopPut (AOP (result),
9243 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9246 _endLazyDPSEvaluation ();
9247 freeAsmop (result, NULL, ic, FALSE);
9248 freeAsmop (right, NULL, ic, FALSE);
9252 /*-----------------------------------------------------------------*/
9253 /* genAssign - generate code for assignment */
9254 /*-----------------------------------------------------------------*/
9256 genAssign (iCode * ic)
9258 operand *result, *right;
9260 unsigned long lit = 0L;
9262 D (emitcode (";", "genAssign ");
9265 result = IC_RESULT (ic);
9266 right = IC_RIGHT (ic);
9268 /* if they are the same */
9269 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9272 aopOp (right, ic, FALSE, FALSE);
9274 emitcode (";", "genAssign: resultIsFar = %s",
9275 isOperandInFarSpace (result) ?
9278 /* special case both in far space */
9279 if ((AOP_TYPE (right) == AOP_DPTR ||
9280 AOP_TYPE (right) == AOP_DPTR2) &&
9281 /* IS_TRUE_SYMOP(result) && */
9282 isOperandInFarSpace (result))
9284 genFarFarAssign (result, right, ic);
9288 aopOp (result, ic, TRUE, FALSE);
9290 /* if they are the same registers */
9291 if (sameRegs (AOP (right), AOP (result)))
9294 /* if the result is a bit */
9295 if (AOP_TYPE (result) == AOP_CRY)
9298 /* if the right size is a literal then
9299 we know what the value is */
9300 if (AOP_TYPE (right) == AOP_LIT)
9302 if (((int) operandLitValue (right)))
9303 aopPut (AOP (result), one, 0);
9305 aopPut (AOP (result), zero, 0);
9309 /* the right is also a bit variable */
9310 if (AOP_TYPE (right) == AOP_CRY)
9312 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9313 aopPut (AOP (result), "c", 0);
9319 aopPut (AOP (result), "a", 0);
9323 /* bit variables done */
9325 size = AOP_SIZE (result);
9327 if (AOP_TYPE (right) == AOP_LIT)
9328 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9331 (AOP_TYPE (result) != AOP_REG) &&
9332 (AOP_TYPE (right) == AOP_LIT) &&
9333 !IS_FLOAT (operandType (right)))
9335 _startLazyDPSEvaluation ();
9336 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9338 aopPut (AOP (result),
9339 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9344 /* And now fill the rest with zeros. */
9347 emitcode ("clr", "a");
9351 aopPut (AOP (result), "a", offset++);
9353 _endLazyDPSEvaluation ();
9357 _startLazyDPSEvaluation ();
9360 aopPut (AOP (result),
9361 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9365 _endLazyDPSEvaluation ();
9369 freeAsmop (right, NULL, ic, FALSE);
9370 freeAsmop (result, NULL, ic, TRUE);
9373 /*-----------------------------------------------------------------*/
9374 /* genJumpTab - generates code for jump table */
9375 /*-----------------------------------------------------------------*/
9377 genJumpTab (iCode * ic)
9382 D (emitcode (";", "genJumpTab ");
9385 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9386 /* get the condition into accumulator */
9387 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9389 /* multiply by four! */
9390 emitcode ("add", "a,acc");
9391 emitcode ("add", "a,acc");
9392 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9394 jtab = newiTempLabel (NULL);
9395 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9396 emitcode ("jmp", "@a+dptr");
9397 emitcode ("", "%05d$:", jtab->key + 100);
9398 /* now generate the jump labels */
9399 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9400 jtab = setNextItem (IC_JTLABELS (ic)))
9401 emitcode ("ljmp", "%05d$", jtab->key + 100);
9405 /*-----------------------------------------------------------------*/
9406 /* genCast - gen code for casting */
9407 /*-----------------------------------------------------------------*/
9409 genCast (iCode * ic)
9411 operand *result = IC_RESULT (ic);
9412 sym_link *ctype = operandType (IC_LEFT (ic));
9413 sym_link *rtype = operandType (IC_RIGHT (ic));
9414 operand *right = IC_RIGHT (ic);
9417 D (emitcode (";", "genCast ");
9420 /* if they are equivalent then do nothing */
9421 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9424 aopOp (right, ic, FALSE, FALSE);
9425 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9427 /* if the result is a bit */
9428 if (AOP_TYPE (result) == AOP_CRY)
9430 /* if the right size is a literal then
9431 we know what the value is */
9432 if (AOP_TYPE (right) == AOP_LIT)
9434 if (((int) operandLitValue (right)))
9435 aopPut (AOP (result), one, 0);
9437 aopPut (AOP (result), zero, 0);
9442 /* the right is also a bit variable */
9443 if (AOP_TYPE (right) == AOP_CRY)
9445 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9446 aopPut (AOP (result), "c", 0);
9452 aopPut (AOP (result), "a", 0);
9456 /* if they are the same size : or less */
9457 if (AOP_SIZE (result) <= AOP_SIZE (right))
9460 /* if they are in the same place */
9461 if (sameRegs (AOP (right), AOP (result)))
9464 /* if they in different places then copy */
9465 size = AOP_SIZE (result);
9467 _startLazyDPSEvaluation ();
9470 aopPut (AOP (result),
9471 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9475 _endLazyDPSEvaluation ();
9480 /* if the result is of type pointer */
9485 sym_link *type = operandType (right);
9487 /* pointer to generic pointer */
9488 if (IS_GENPTR (ctype))
9494 p_type = DCL_TYPE (type);
9498 #if OLD_CAST_BEHAVIOR
9499 /* KV: we are converting a non-pointer type to
9500 * a generic pointer. This (ifdef'd out) code
9501 * says that the resulting generic pointer
9502 * should have the same class as the storage
9503 * location of the non-pointer variable.
9505 * For example, converting an int (which happens
9506 * to be stored in DATA space) to a pointer results
9507 * in a DATA generic pointer; if the original int
9508 * in XDATA space, so will be the resulting pointer.
9510 * I don't like that behavior, and thus this change:
9511 * all such conversions will be forced to XDATA and
9512 * throw a warning. If you want some non-XDATA
9513 * type, or you want to suppress the warning, you
9514 * must go through an intermediate cast, like so:
9516 * char _generic *gp = (char _xdata *)(intVar);
9518 sym_link *etype = getSpec (type);
9520 /* we have to go by the storage class */
9521 if (SPEC_OCLS (etype) != generic)
9523 p_type = PTR_TYPE (SPEC_OCLS (etype));
9528 /* Converting unknown class (i.e. register variable)
9529 * to generic pointer. This is not good, but
9530 * we'll make a guess (and throw a warning).
9533 werror (W_INT_TO_GEN_PTR_CAST);
9537 /* the first two bytes are known */
9538 size = GPTRSIZE - 1;
9540 _startLazyDPSEvaluation ();
9543 aopPut (AOP (result),
9544 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9548 _endLazyDPSEvaluation ();
9550 /* the last byte depending on type */
9568 /* this should never happen */
9569 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9570 "got unknown pointer type");
9573 aopPut (AOP (result), l, GPTRSIZE - 1);
9577 /* just copy the pointers */
9578 size = AOP_SIZE (result);
9580 _startLazyDPSEvaluation ();
9583 aopPut (AOP (result),
9584 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9588 _endLazyDPSEvaluation ();
9592 /* so we now know that the size of destination is greater
9593 than the size of the source */
9594 /* we move to result for the size of source */
9595 size = AOP_SIZE (right);
9597 _startLazyDPSEvaluation ();
9600 aopPut (AOP (result),
9601 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9605 _endLazyDPSEvaluation ();
9607 /* now depending on the sign of the source && destination */
9608 size = AOP_SIZE (result) - AOP_SIZE (right);
9609 /* if unsigned or not an integral type */
9610 /* also, if the source is a bit, we don't need to sign extend, because
9611 * it can't possibly have set the sign bit.
9613 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9617 aopPut (AOP (result), zero, offset++);
9622 /* we need to extend the sign :{ */
9623 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9624 FALSE, FALSE, TRUE);
9626 emitcode ("rlc", "a");
9627 emitcode ("subb", "a,acc");
9629 aopPut (AOP (result), "a", offset++);
9632 /* we are done hurray !!!! */
9635 freeAsmop (right, NULL, ic, TRUE);
9636 freeAsmop (result, NULL, ic, TRUE);
9640 /*-----------------------------------------------------------------*/
9641 /* genDjnz - generate decrement & jump if not zero instrucion */
9642 /*-----------------------------------------------------------------*/
9644 genDjnz (iCode * ic, iCode * ifx)
9650 /* if the if condition has a false label
9651 then we cannot save */
9655 /* if the minus is not of the form
9657 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9658 !IS_OP_LITERAL (IC_RIGHT (ic)))
9661 if (operandLitValue (IC_RIGHT (ic)) != 1)
9664 /* if the size of this greater than one then no
9666 if (getSize (operandType (IC_RESULT (ic))) > 1)
9669 /* otherwise we can save BIG */
9670 D(emitcode(";", "genDjnz"););
9672 lbl = newiTempLabel (NULL);
9673 lbl1 = newiTempLabel (NULL);
9675 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9677 if (AOP_NEEDSACC(IC_RESULT(ic)))
9679 /* If the result is accessed indirectly via
9680 * the accumulator, we must explicitly write
9681 * it back after the decrement.
9683 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9685 if (strcmp(rByte, "a"))
9687 /* Something is hopelessly wrong */
9688 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9689 __FILE__, __LINE__);
9690 /* We can just give up; the generated code will be inefficient,
9693 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9696 emitcode ("dec", "%s", rByte);
9697 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9698 emitcode ("jnz", "%05d$", lbl->key + 100);
9700 else if (IS_AOP_PREG (IC_RESULT (ic)))
9702 emitcode ("dec", "%s",
9703 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9704 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9705 emitcode ("jnz", "%05d$", lbl->key + 100);
9709 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9712 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9713 emitcode ("", "%05d$:", lbl->key + 100);
9714 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9715 emitcode ("", "%05d$:", lbl1->key + 100);
9717 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9722 /*-----------------------------------------------------------------*/
9723 /* genReceive - generate code for a receive iCode */
9724 /*-----------------------------------------------------------------*/
9726 genReceive (iCode * ic)
9729 D (emitcode (";", "genReceive ");
9732 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9733 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9734 IS_TRUE_SYMOP (IC_RESULT (ic))))
9736 int size = getSize (operandType (IC_RESULT (ic)));
9737 int offset = fReturnSizeDS390 - size;
9740 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9741 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9744 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9745 size = AOP_SIZE (IC_RESULT (ic));
9749 emitcode ("pop", "acc");
9750 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9757 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9759 assignResultValue (IC_RESULT (ic));
9762 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9765 /*-----------------------------------------------------------------*/
9766 /* gen390Code - generate code for Dallas 390 based controllers */
9767 /*-----------------------------------------------------------------*/
9769 gen390Code (iCode * lic)
9774 lineHead = lineCurr = NULL;
9778 /* print the allocation information */
9780 printAllocInfo (currFunc, codeOutFile);
9782 /* if debug information required */
9783 if (options.debug && currFunc)
9785 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9787 if (IS_STATIC (currFunc->etype))
9788 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9790 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9793 /* stack pointer name */
9794 if (options.useXstack)
9800 for (ic = lic; ic; ic = ic->next)
9803 if (cln != ic->lineno)
9808 emitcode ("", "C$%s$%d$%d$%d ==.",
9809 FileBaseName (ic->filename), ic->lineno,
9810 ic->level, ic->block);
9813 emitcode (";", "%s %d", ic->filename, ic->lineno);
9816 /* if the result is marked as
9817 spilt and rematerializable or code for
9818 this has already been generated then
9820 if (resultRemat (ic) || ic->generated)
9823 /* depending on the operation */
9843 /* IPOP happens only when trying to restore a
9844 spilt live range, if there is an ifx statement
9845 following this pop then the if statement might
9846 be using some of the registers being popped which
9847 would destory the contents of the register so
9848 we need to check for this condition and handle it */
9850 ic->next->op == IFX &&
9851 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9852 genIfx (ic->next, ic);
9870 genEndFunction (ic);
9890 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9907 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9911 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9918 /* note these two are xlated by algebraic equivalence
9919 during parsing SDCC.y */
9920 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9921 "got '>=' or '<=' shouldn't have come here");
9925 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9937 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9941 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9945 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9972 case GET_VALUE_AT_ADDRESS:
9977 if (POINTER_SET (ic))
10004 addSet (&_G.sendSet, ic);
10013 /* now we are ready to call the
10014 peep hole optimizer */
10015 if (!options.nopeep)
10016 peepHole (&lineHead);
10018 /* now do the actual printing */
10019 printLine (lineHead, codeOutFile);