1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #define BETTER_LITERAL_SHIFT
53 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
66 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
67 static char *fReturn[] =
68 {"dpl", "dph", "dpx", "b", "a"};
69 static char *accUse[] =
72 static short rbank = -1;
86 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
93 #define MOVA(x) { char *_mova_tmp = strdup(x); \
94 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96 emitcode("mov","a,%s",_mova_tmp); \
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
122 /*-----------------------------------------------------------------*/
123 /* emitcode - writes the code into a file : for now it is simple */
124 /*-----------------------------------------------------------------*/
126 emitcode (char *inst, char *fmt,...)
129 char lb[INITIAL_INLINEASM];
137 sprintf (lb, "%s\t", inst);
139 sprintf (lb, "%s", inst);
140 vsprintf (lb + (strlen (lb)), fmt, ap);
143 vsprintf (lb, fmt, ap);
145 while (isspace (*lbp))
149 lineCurr = (lineCurr ?
150 connectLine (lineCurr, newLineNode (lb)) :
151 (lineHead = newLineNode (lb)));
152 lineCurr->isInline = _G.inLine;
153 lineCurr->isDebug = _G.debugLine;
157 /*-----------------------------------------------------------------*/
158 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
159 /*-----------------------------------------------------------------*/
161 getFreePtr (iCode * ic, asmop ** aopp, bool result)
163 bool r0iu = FALSE, r1iu = FALSE;
164 bool r0ou = FALSE, r1ou = FALSE;
166 /* the logic: if r0 & r1 used in the instruction
167 then we are in trouble otherwise */
169 /* first check if r0 & r1 are used by this
170 instruction, in which case we are in trouble */
171 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
172 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
177 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
178 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
180 /* if no usage of r0 then return it */
183 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
184 (*aopp)->type = AOP_R0;
186 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
189 /* if no usage of r1 then return it */
192 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
193 (*aopp)->type = AOP_R1;
195 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
198 /* now we know they both have usage */
199 /* if r0 not used in this instruction */
202 /* push it if not already pushed */
205 emitcode ("push", "%s",
206 ds390_regWithIdx (R0_IDX)->dname);
210 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
211 (*aopp)->type = AOP_R0;
213 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
216 /* if r1 not used then */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 ds390_regWithIdx (R1_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
229 (*aopp)->type = AOP_R1;
230 return ds390_regWithIdx (R1_IDX);
234 /* I said end of world but not quite end of world yet */
235 /* if this is a result then we can push it on the stack */
238 (*aopp)->type = AOP_STK;
242 /* other wise this is true end of the world */
243 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
244 "getFreePtr should never reach here");
248 /*-----------------------------------------------------------------*/
249 /* newAsmop - creates a new asmOp */
250 /*-----------------------------------------------------------------*/
252 newAsmop (short type)
256 aop = Safe_calloc (1, sizeof (asmop));
261 static int _currentDPS; /* Current processor DPS. */
262 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
263 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
265 /*-----------------------------------------------------------------*/
266 /* genSetDPTR: generate code to select which DPTR is in use (zero */
267 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
268 /* alternate DPTR (DPL1/DPH1/DPX1). */
269 /*-----------------------------------------------------------------*/
274 /* If we are doing lazy evaluation, simply note the desired
275 * change, but don't emit any code yet.
285 emitcode ("mov", "dps, #0x00");
289 emitcode ("mov", "dps, #0x01");
293 /*-----------------------------------------------------------------*/
294 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
296 /* Any code that operates on DPTR (NB: not on the individual */
297 /* components, like DPH) *must* call _flushLazyDPS() before using */
298 /* DPTR within a lazy DPS evaluation block. */
300 /* Note that aopPut and aopGet already contain the proper calls to */
301 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
302 /* DPS evaluation block. */
304 /* Also, _flushLazyDPS must be called before any flow control */
305 /* operations that could potentially branch out of the block. */
307 /* Lazy DPS evaluation is simply an optimization (though an */
308 /* important one), so if in doubt, leave it out. */
309 /*-----------------------------------------------------------------*/
311 _startLazyDPSEvaluation (void)
315 #ifdef BETTER_LITERAL_SHIFT
322 /*-----------------------------------------------------------------*/
323 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
324 /* desired one. Call before using DPTR within a lazy DPS evaluation */
326 /*-----------------------------------------------------------------*/
336 if (_desiredDPS != _currentDPS)
340 emitcode ("inc", "dps");
344 emitcode ("dec", "dps");
346 _currentDPS = _desiredDPS;
350 /*-----------------------------------------------------------------*/
351 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
353 /* Forces us back to the safe state (standard DPTR selected). */
354 /*-----------------------------------------------------------------*/
356 _endLazyDPSEvaluation (void)
358 #ifdef BETTER_LITERAL_SHIFT
377 /*-----------------------------------------------------------------*/
378 /* pointerCode - returns the code for a pointer type */
379 /*-----------------------------------------------------------------*/
381 pointerCode (sym_link * etype)
384 return PTR_TYPE (SPEC_OCLS (etype));
388 /*-----------------------------------------------------------------*/
389 /* aopForSym - for a true symbol */
390 /*-----------------------------------------------------------------*/
392 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
395 memmap *space = SPEC_OCLS (sym->etype);
397 /* if already has one */
401 /* assign depending on the storage class */
402 /* if it is on the stack or indirectly addressable */
403 /* space we need to assign either r0 or r1 to it */
404 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
406 sym->aop = aop = newAsmop (0);
407 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
408 aop->size = getSize (sym->type);
410 /* now assign the address of the variable to
411 the pointer register */
412 if (aop->type != AOP_STK)
418 emitcode ("push", "acc");
420 emitcode ("mov", "a,_bp");
421 emitcode ("add", "a,#0x%02x",
423 ((char) (sym->stack - _G.nRegsSaved)) :
424 ((char) sym->stack)) & 0xff);
425 emitcode ("mov", "%s,a",
426 aop->aopu.aop_ptr->name);
429 emitcode ("pop", "acc");
432 emitcode ("mov", "%s,#%s",
433 aop->aopu.aop_ptr->name,
435 aop->paged = space->paged;
438 aop->aopu.aop_stk = sym->stack;
442 if (sym->onStack && options.stack10bit)
444 /* It's on the 10 bit stack, which is located in
449 emitcode ("push", "acc");
451 emitcode ("mov", "a,_bp");
452 emitcode ("add", "a,#0x%02x",
454 ((char) (sym->stack - _G.nRegsSaved)) :
455 ((char) sym->stack)) & 0xff);
459 emitcode ("mov", "dpx1,#0x40");
460 emitcode ("mov", "dph1,#0x00");
461 emitcode ("mov", "dpl1, a");
465 emitcode ("mov", "dpx,#0x40");
466 emitcode ("mov", "dph,#0x00");
467 emitcode ("mov", "dpl, a");
471 emitcode ("pop", "acc");
473 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
474 aop->size = getSize (sym->type);
478 /* if in bit space */
479 if (IN_BITSPACE (space))
481 sym->aop = aop = newAsmop (AOP_CRY);
482 aop->aopu.aop_dir = sym->rname;
483 aop->size = getSize (sym->type);
486 /* if it is in direct space */
487 if (IN_DIRSPACE (space))
489 sym->aop = aop = newAsmop (AOP_DIR);
490 aop->aopu.aop_dir = sym->rname;
491 aop->size = getSize (sym->type);
495 /* special case for a function */
496 if (IS_FUNC (sym->type))
498 sym->aop = aop = newAsmop (AOP_IMMD);
499 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
500 strcpy (aop->aopu.aop_immd, sym->rname);
501 aop->size = FPTRSIZE;
505 /* only remaining is far space */
506 /* in which case DPTR gets the address */
507 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
512 emitcode ("mov", "dptr,#%s", sym->rname);
517 emitcode ("mov", "dptr,#%s", sym->rname);
519 aop->size = getSize (sym->type);
521 /* if it is in code space */
522 if (IN_CODESPACE (space))
528 /*-----------------------------------------------------------------*/
529 /* aopForRemat - rematerialzes an object */
530 /*-----------------------------------------------------------------*/
532 aopForRemat (symbol * sym)
534 iCode *ic = sym->rematiCode;
535 asmop *aop = newAsmop (AOP_IMMD);
542 val += (int) operandLitValue (IC_RIGHT (ic));
543 else if (ic->op == '-')
544 val -= (int) operandLitValue (IC_RIGHT (ic));
548 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
552 sprintf (buffer, "(%s %c 0x%04x)",
553 OP_SYMBOL (IC_LEFT (ic))->rname,
554 val >= 0 ? '+' : '-',
557 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
559 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
560 strcpy (aop->aopu.aop_immd, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
658 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
665 if (aop1->type != AOP_REG ||
666 aop2->type != AOP_REG)
669 if (aop1->size != aop2->size)
672 for (i = 0; i < aop1->size; i++)
673 if (aop1->aopu.aop_reg[i] !=
674 aop2->aopu.aop_reg[i])
680 /*-----------------------------------------------------------------*/
681 /* aopOp - allocates an asmop for an operand : */
682 /*-----------------------------------------------------------------*/
684 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
693 /* if this a literal */
694 if (IS_OP_LITERAL (op))
696 op->aop = aop = newAsmop (AOP_LIT);
697 aop->aopu.aop_lit = op->operand.valOperand;
698 aop->size = getSize (operandType (op));
702 /* if already has a asmop then continue */
706 /* if the underlying symbol has a aop */
707 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
709 op->aop = OP_SYMBOL (op)->aop;
713 /* if this is a true symbol */
714 if (IS_TRUE_SYMOP (op))
716 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
720 /* this is a temporary : this has
726 e) can be a return use only */
728 sym = OP_SYMBOL (op);
731 /* if the type is a conditional */
732 if (sym->regType == REG_CND)
734 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
739 /* if it is spilt then two situations
741 b) has a spill location */
742 if (sym->isspilt || sym->nRegs == 0)
745 /* rematerialize it NOW */
748 sym->aop = op->aop = aop =
750 aop->size = getSize (sym->type);
757 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
758 aop->size = getSize (sym->type);
759 for (i = 0; i < 2; i++)
760 aop->aopu.aop_str[i] = accUse[i];
770 /* a AOP_STR uses DPTR, but DPTR is already in use;
773 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
776 aop = op->aop = sym->aop = newAsmop (AOP_STR);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < (int) fReturnSizeDS390; i++)
779 aop->aopu.aop_str[i] = fReturn[i];
783 /* else spill location */
784 sym->aop = op->aop = aop =
785 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
786 aop->size = getSize (sym->type);
790 /* must be in a register */
791 sym->aop = op->aop = aop = newAsmop (AOP_REG);
792 aop->size = sym->nRegs;
793 for (i = 0; i < sym->nRegs; i++)
794 aop->aopu.aop_reg[i] = sym->regs[i];
797 /*-----------------------------------------------------------------*/
798 /* freeAsmop - free up the asmop given to an operand */
799 /*----------------------------------------------------------------*/
801 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
818 /* depending on the asmop type only three cases need work AOP_RO
819 , AOP_R1 && AOP_STK */
827 emitcode ("pop", "ar0");
831 bitVectUnSetBit (ic->rUsed, R0_IDX);
839 emitcode ("pop", "ar1");
843 bitVectUnSetBit (ic->rUsed, R1_IDX);
849 int stk = aop->aopu.aop_stk + aop->size;
850 bitVectUnSetBit (ic->rUsed, R0_IDX);
851 bitVectUnSetBit (ic->rUsed, R1_IDX);
853 getFreePtr (ic, &aop, FALSE);
855 if (options.stack10bit)
857 /* I'm not sure what to do here yet... */
860 "*** Warning: probably generating bad code for "
861 "10 bit stack mode.\n");
866 emitcode ("mov", "a,_bp");
867 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
868 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
872 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
877 emitcode ("pop", "acc");
878 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
881 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
884 freeAsmop (op, NULL, ic, TRUE);
887 emitcode ("pop", "ar0");
893 emitcode ("pop", "ar1");
900 /* all other cases just dealloc */
906 OP_SYMBOL (op)->aop = NULL;
907 /* if the symbol has a spill */
909 SPIL_LOC (op)->aop = NULL;
914 /*------------------------------------------------------------------*/
915 /* aopGet - for fetching value of the aop */
917 /* Set canClobberACC if you are sure it is OK to clobber the value */
918 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
919 /* just less efficient. */
920 /*------------------------------------------------------------------*/
932 /* offset is greater than
934 if (offset > (aop->size - 1) &&
935 aop->type != AOP_LIT)
938 /* depending on type */
944 /* if we need to increment it */
945 while (offset > aop->coff)
947 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
951 while (offset < aop->coff)
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
960 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
961 return (dname ? "acc" : "a");
963 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
964 rs = Safe_calloc (1, strlen (s) + 1);
971 if (aop->type == AOP_DPTR2)
976 emitcode ("xch", "a, %s", DP2_RESULT_REG);
982 while (offset > aop->coff)
984 emitcode ("inc", "dptr");
988 while (offset < aop->coff)
990 emitcode ("lcall", "__decdptr");
997 emitcode ("clr", "a");
998 emitcode ("movc", "a,@a+dptr");
1002 emitcode ("movx", "a,@dptr");
1005 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011 return DP2_RESULT_REG;
1014 return (dname ? "acc" : "a");
1018 sprintf (s, "#%s", aop->aopu.aop_immd);
1020 sprintf (s, "#(%s >> %d)",
1025 aop->aopu.aop_immd);
1026 rs = Safe_calloc (1, strlen (s) + 1);
1032 sprintf (s, "(%s + %d)",
1036 sprintf (s, "%s", aop->aopu.aop_dir);
1037 rs = Safe_calloc (1, strlen (s) + 1);
1043 return aop->aopu.aop_reg[offset]->dname;
1045 return aop->aopu.aop_reg[offset]->name;
1048 emitcode ("clr", "a");
1049 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1050 emitcode ("rlc", "a");
1051 return (dname ? "acc" : "a");
1054 if (!offset && dname)
1056 return aop->aopu.aop_str[offset];
1059 return aopLiteral (aop->aopu.aop_lit, offset);
1063 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1067 return aop->aopu.aop_str[offset];
1071 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1072 "aopget got unsupported aop->type");
1075 /*-----------------------------------------------------------------*/
1076 /* aopPut - puts a string for a aop */
1077 /*-----------------------------------------------------------------*/
1079 aopPut (asmop * aop, char *s, int offset)
1083 if (aop->size && offset > (aop->size - 1))
1085 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1086 "aopPut got offset > aop->size");
1090 /* will assign value to value */
1091 /* depending on where it is ofcourse */
1096 sprintf (d, "(%s + %d)",
1097 aop->aopu.aop_dir, offset);
1099 sprintf (d, "%s", aop->aopu.aop_dir);
1102 emitcode ("mov", "%s,%s", d, s);
1107 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1108 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1111 strcmp (s, "r0") == 0 ||
1112 strcmp (s, "r1") == 0 ||
1113 strcmp (s, "r2") == 0 ||
1114 strcmp (s, "r3") == 0 ||
1115 strcmp (s, "r4") == 0 ||
1116 strcmp (s, "r5") == 0 ||
1117 strcmp (s, "r6") == 0 ||
1118 strcmp (s, "r7") == 0)
1119 emitcode ("mov", "%s,%s",
1120 aop->aopu.aop_reg[offset]->dname, s);
1122 emitcode ("mov", "%s,%s",
1123 aop->aopu.aop_reg[offset]->name, s);
1130 if (aop->type == AOP_DPTR2)
1138 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139 "aopPut writting to code space");
1143 while (offset > aop->coff)
1146 emitcode ("inc", "dptr");
1149 while (offset < aop->coff)
1152 emitcode ("lcall", "__decdptr");
1157 /* if not in accumulater */
1160 emitcode ("movx", "@dptr,a");
1162 if (aop->type == AOP_DPTR2)
1170 while (offset > aop->coff)
1173 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1175 while (offset < aop->coff)
1178 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1185 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1191 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1193 else if (strcmp (s, "r0") == 0 ||
1194 strcmp (s, "r1") == 0 ||
1195 strcmp (s, "r2") == 0 ||
1196 strcmp (s, "r3") == 0 ||
1197 strcmp (s, "r4") == 0 ||
1198 strcmp (s, "r5") == 0 ||
1199 strcmp (s, "r6") == 0 ||
1200 strcmp (s, "r7") == 0)
1203 sprintf (buffer, "a%s", s);
1204 emitcode ("mov", "@%s,%s",
1205 aop->aopu.aop_ptr->name, buffer);
1208 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1213 if (strcmp (s, "a") == 0)
1214 emitcode ("push", "acc");
1216 emitcode ("push", "%s", s);
1221 /* if bit variable */
1222 if (!aop->aopu.aop_dir)
1224 emitcode ("clr", "a");
1225 emitcode ("rlc", "a");
1230 emitcode ("clr", "%s", aop->aopu.aop_dir);
1232 emitcode ("setb", "%s", aop->aopu.aop_dir);
1233 else if (!strcmp (s, "c"))
1234 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237 if (strcmp (s, "a"))
1242 symbol *lbl = newiTempLabel (NULL);
1243 emitcode ("clr", "c");
1244 emitcode ("jz", "%05d$", lbl->key + 100);
1245 emitcode ("cpl", "c");
1246 emitcode ("", "%05d$:", lbl->key + 100);
1247 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1255 if (strcmp (aop->aopu.aop_str[offset], s))
1256 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1261 if (!offset && (strcmp (s, "acc") == 0))
1264 if (strcmp (aop->aopu.aop_str[offset], s))
1265 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1270 "aopPut got unsupported aop->type");
1277 /*--------------------------------------------------------------------*/
1278 /* reAdjustPreg - points a register back to where it should (coff==0) */
1279 /*--------------------------------------------------------------------*/
1281 reAdjustPreg (asmop * aop)
1283 if ((aop->coff==0) || (aop->size <= 1)) {
1292 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1296 if (aop->type == AOP_DPTR2)
1303 emitcode ("lcall", "__decdptr");
1306 if (aop->type == AOP_DPTR2)
1316 #define AOP(op) op->aop
1317 #define AOP_TYPE(op) AOP(op)->type
1318 #define AOP_SIZE(op) AOP(op)->size
1319 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1320 AOP_TYPE(x) == AOP_R0))
1322 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1323 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1326 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1327 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1328 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1330 /* Workaround for DS80C390 bug: div ab may return bogus results
1331 * if A is accessed in instruction immediately before the div.
1333 * Will be fixed in B4 rev of processor, Dallas claims.
1336 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1337 if (!AOP_NEEDSACC(RIGHT)) \
1339 /* We can load A first, then B, since \
1340 * B (the RIGHT operand) won't clobber A, \
1341 * thus avoiding touching A right before the div. \
1343 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1344 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1346 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1350 /* Just stuff in a nop after loading A. */ \
1351 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1352 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1354 emitcode("nop", "; workaround for DS80C390 div bug."); \
1357 /*-----------------------------------------------------------------*/
1358 /* genNotFloat - generates not for float operations */
1359 /*-----------------------------------------------------------------*/
1361 genNotFloat (operand * op, operand * res)
1367 D (emitcode (";", "genNotFloat ");
1370 /* we will put 127 in the first byte of
1372 aopPut (AOP (res), "#127", 0);
1373 size = AOP_SIZE (op) - 1;
1376 _startLazyDPSEvaluation ();
1377 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1382 emitcode ("orl", "a,%s",
1384 offset++, FALSE, FALSE, FALSE));
1386 _endLazyDPSEvaluation ();
1388 tlbl = newiTempLabel (NULL);
1389 aopPut (res->aop, one, 1);
1390 emitcode ("jz", "%05d$", (tlbl->key + 100));
1391 aopPut (res->aop, zero, 1);
1392 emitcode ("", "%05d$:", (tlbl->key + 100));
1394 size = res->aop->size - 2;
1396 /* put zeros in the rest */
1398 aopPut (res->aop, zero, offset++);
1401 /*-----------------------------------------------------------------*/
1402 /* opIsGptr: returns non-zero if the passed operand is */
1403 /* a generic pointer type. */
1404 /*-----------------------------------------------------------------*/
1406 opIsGptr (operand * op)
1408 sym_link *type = operandType (op);
1410 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1417 /*-----------------------------------------------------------------*/
1418 /* getDataSize - get the operand data size */
1419 /*-----------------------------------------------------------------*/
1421 getDataSize (operand * op)
1424 size = AOP_SIZE (op);
1425 if (size == GPTRSIZE)
1427 sym_link *type = operandType (op);
1428 if (IS_GENPTR (type))
1430 /* generic pointer; arithmetic operations
1431 * should ignore the high byte (pointer type).
1439 /*-----------------------------------------------------------------*/
1440 /* outAcc - output Acc */
1441 /*-----------------------------------------------------------------*/
1443 outAcc (operand * result)
1446 size = getDataSize (result);
1449 aopPut (AOP (result), "a", 0);
1452 /* unsigned or positive */
1455 aopPut (AOP (result), zero, offset++);
1460 /*-----------------------------------------------------------------*/
1461 /* outBitC - output a bit C */
1462 /*-----------------------------------------------------------------*/
1464 outBitC (operand * result)
1466 /* if the result is bit */
1467 if (AOP_TYPE (result) == AOP_CRY)
1469 aopPut (AOP (result), "c", 0);
1473 emitcode ("clr", "a");
1474 emitcode ("rlc", "a");
1479 /*-----------------------------------------------------------------*/
1480 /* toBoolean - emit code for orl a,operator(sizeop) */
1481 /*-----------------------------------------------------------------*/
1483 toBoolean (operand * oper)
1485 int size = AOP_SIZE (oper) - 1;
1489 /* The generic part of a generic pointer should
1490 * not participate in it's truth value.
1492 * i.e. 0x10000000 is zero.
1494 if (opIsGptr (oper))
1496 D (emitcode (";", "toBoolean: generic ptr special case.");
1501 _startLazyDPSEvaluation ();
1502 if (AOP_NEEDSACC (oper) && size)
1505 emitcode ("push", "b");
1506 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1510 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1516 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1520 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1523 _endLazyDPSEvaluation ();
1527 emitcode ("mov", "a,b");
1528 emitcode ("pop", "b");
1533 /*-----------------------------------------------------------------*/
1534 /* genNot - generate code for ! operation */
1535 /*-----------------------------------------------------------------*/
1540 sym_link *optype = operandType (IC_LEFT (ic));
1542 D (emitcode (";", "genNot ");
1545 /* assign asmOps to operand & result */
1546 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1547 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1549 /* if in bit space then a special case */
1550 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1552 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1553 emitcode ("cpl", "c");
1554 outBitC (IC_RESULT (ic));
1558 /* if type float then do float */
1559 if (IS_FLOAT (optype))
1561 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1565 toBoolean (IC_LEFT (ic));
1567 tlbl = newiTempLabel (NULL);
1568 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1569 emitcode ("", "%05d$:", tlbl->key + 100);
1570 outBitC (IC_RESULT (ic));
1573 /* release the aops */
1574 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1575 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1579 /*-----------------------------------------------------------------*/
1580 /* genCpl - generate code for complement */
1581 /*-----------------------------------------------------------------*/
1588 D (emitcode (";", "genCpl ");
1592 /* assign asmOps to operand & result */
1593 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1594 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1596 /* if both are in bit space then
1598 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1599 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1602 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1603 emitcode ("cpl", "c");
1604 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1608 size = AOP_SIZE (IC_RESULT (ic));
1609 _startLazyDPSEvaluation ();
1612 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1614 emitcode ("cpl", "a");
1615 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1617 _endLazyDPSEvaluation ();
1621 /* release the aops */
1622 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1623 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* genUminusFloat - unary minus for floating points */
1628 /*-----------------------------------------------------------------*/
1630 genUminusFloat (operand * op, operand * result)
1632 int size, offset = 0;
1634 /* for this we just need to flip the
1635 first it then copy the rest in place */
1636 D (emitcode (";", "genUminusFloat");
1639 _startLazyDPSEvaluation ();
1640 size = AOP_SIZE (op) - 1;
1641 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1644 emitcode ("cpl", "acc.7");
1645 aopPut (AOP (result), "a", 3);
1649 aopPut (AOP (result),
1650 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1654 _endLazyDPSEvaluation ();
1657 /*-----------------------------------------------------------------*/
1658 /* genUminus - unary minus code generation */
1659 /*-----------------------------------------------------------------*/
1661 genUminus (iCode * ic)
1664 sym_link *optype, *rtype;
1666 D (emitcode (";", "genUminus ");
1671 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1672 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1674 /* if both in bit space then special
1676 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1677 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1680 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1681 emitcode ("cpl", "c");
1682 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1686 optype = operandType (IC_LEFT (ic));
1687 rtype = operandType (IC_RESULT (ic));
1689 /* if float then do float stuff */
1690 if (IS_FLOAT (optype))
1692 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1696 /* otherwise subtract from zero */
1697 size = AOP_SIZE (IC_LEFT (ic));
1699 _startLazyDPSEvaluation ();
1702 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1703 if (!strcmp (l, "a"))
1707 emitcode ("cpl", "a");
1708 emitcode ("addc", "a,#0");
1714 emitcode ("clr", "a");
1715 emitcode ("subb", "a,%s", l);
1717 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1719 _endLazyDPSEvaluation ();
1721 /* if any remaining bytes in the result */
1722 /* we just need to propagate the sign */
1723 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1725 emitcode ("rlc", "a");
1726 emitcode ("subb", "a,acc");
1728 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1732 /* release the aops */
1733 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1734 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1737 /*-----------------------------------------------------------------*/
1738 /* saveRegisters - will look for a call and save the registers */
1739 /*-----------------------------------------------------------------*/
1741 saveRegisters (iCode * lic)
1749 for (ic = lic; ic; ic = ic->next)
1750 if (ic->op == CALL || ic->op == PCALL)
1755 fprintf (stderr, "found parameter push with no function call\n");
1759 /* if the registers have been saved already then
1761 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1762 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
1765 /* find the registers in use at this time
1766 and push them away to safety */
1767 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1771 if (options.useXstack)
1773 if (bitVectBitValue (rsave, R0_IDX))
1774 emitcode ("mov", "b,r0");
1775 emitcode ("mov", "r0,%s", spname);
1776 for (i = 0; i < ds390_nRegs; i++)
1778 if (bitVectBitValue (rsave, i))
1781 emitcode ("mov", "a,b");
1783 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1784 emitcode ("movx", "@r0,a");
1785 emitcode ("inc", "r0");
1788 emitcode ("mov", "%s,r0", spname);
1789 if (bitVectBitValue (rsave, R0_IDX))
1790 emitcode ("mov", "r0,b");
1793 for (i = 0; i < ds390_nRegs; i++)
1795 if (bitVectBitValue (rsave, i))
1796 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1799 detype = getSpec (operandType (IC_LEFT (ic)));
1802 /*-----------------------------------------------------------------*/
1803 /* unsaveRegisters - pop the pushed registers */
1804 /*-----------------------------------------------------------------*/
1806 unsaveRegisters (iCode * ic)
1810 /* find the registers in use at this time
1811 and push them away to safety */
1812 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1815 if (options.useXstack)
1817 emitcode ("mov", "r0,%s", spname);
1818 for (i = ds390_nRegs; i >= 0; i--)
1820 if (bitVectBitValue (rsave, i))
1822 emitcode ("dec", "r0");
1823 emitcode ("movx", "a,@r0");
1825 emitcode ("mov", "b,a");
1827 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1831 emitcode ("mov", "%s,r0", spname);
1832 if (bitVectBitValue (rsave, R0_IDX))
1833 emitcode ("mov", "r0,b");
1836 for (i = ds390_nRegs; i >= 0; i--)
1838 if (bitVectBitValue (rsave, i))
1839 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1845 /*-----------------------------------------------------------------*/
1847 /*-----------------------------------------------------------------*/
1849 pushSide (operand * oper, int size)
1852 _startLazyDPSEvaluation ();
1855 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1856 if (AOP_TYPE (oper) != AOP_REG &&
1857 AOP_TYPE (oper) != AOP_DIR &&
1860 emitcode ("mov", "a,%s", l);
1861 emitcode ("push", "acc");
1864 emitcode ("push", "%s", l);
1866 _endLazyDPSEvaluation ();
1869 /*-----------------------------------------------------------------*/
1870 /* assignResultValue - */
1871 /*-----------------------------------------------------------------*/
1873 assignResultValue (operand * oper)
1876 int size = AOP_SIZE (oper);
1878 _startLazyDPSEvaluation ();
1881 aopPut (AOP (oper), fReturn[offset], offset);
1884 _endLazyDPSEvaluation ();
1888 /*-----------------------------------------------------------------*/
1889 /* genXpush - pushes onto the external stack */
1890 /*-----------------------------------------------------------------*/
1892 genXpush (iCode * ic)
1894 asmop *aop = newAsmop (0);
1896 int size, offset = 0;
1898 D (emitcode (";", "genXpush ");
1901 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1902 r = getFreePtr (ic, &aop, FALSE);
1905 emitcode ("mov", "%s,_spx", r->name);
1907 size = AOP_SIZE (IC_LEFT (ic));
1908 _startLazyDPSEvaluation ();
1912 char *l = aopGet (AOP (IC_LEFT (ic)),
1913 offset++, FALSE, FALSE, TRUE);
1915 emitcode ("movx", "@%s,a", r->name);
1916 emitcode ("inc", "%s", r->name);
1919 _endLazyDPSEvaluation ();
1922 emitcode ("mov", "_spx,%s", r->name);
1924 freeAsmop (NULL, aop, ic, TRUE);
1925 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1928 /*-----------------------------------------------------------------*/
1929 /* genIpush - genrate code for pushing this gets a little complex */
1930 /*-----------------------------------------------------------------*/
1932 genIpush (iCode * ic)
1934 int size, offset = 0;
1937 D (emitcode (";", "genIpush ");
1940 /* if this is not a parm push : ie. it is spill push
1941 and spill push is always done on the local stack */
1945 /* and the item is spilt then do nothing */
1946 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1949 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1950 size = AOP_SIZE (IC_LEFT (ic));
1951 /* push it on the stack */
1952 _startLazyDPSEvaluation ();
1955 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1961 emitcode ("push", "%s", l);
1963 _endLazyDPSEvaluation ();
1967 /* this is a paramter push: in this case we call
1968 the routine to find the call and save those
1969 registers that need to be saved */
1972 /* if use external stack then call the external
1973 stack pushing routine */
1974 if (options.useXstack)
1980 /* then do the push */
1981 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1983 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1984 size = AOP_SIZE (IC_LEFT (ic));
1986 _startLazyDPSEvaluation ();
1989 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1990 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1991 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1994 emitcode ("mov", "a,%s", l);
1995 emitcode ("push", "acc");
1998 emitcode ("push", "%s", l);
2000 _endLazyDPSEvaluation ();
2002 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2005 /*-----------------------------------------------------------------*/
2006 /* genIpop - recover the registers: can happen only for spilling */
2007 /*-----------------------------------------------------------------*/
2009 genIpop (iCode * ic)
2013 D (emitcode (";", "genIpop ");
2017 /* if the temp was not pushed then */
2018 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2021 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2022 size = AOP_SIZE (IC_LEFT (ic));
2023 offset = (size - 1);
2024 _startLazyDPSEvaluation ();
2027 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2028 FALSE, TRUE, TRUE));
2030 _endLazyDPSEvaluation ();
2032 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2035 /*-----------------------------------------------------------------*/
2036 /* unsaveRBank - restores the resgister bank from stack */
2037 /*-----------------------------------------------------------------*/
2039 unsaveRBank (int bank, iCode * ic, bool popPsw)
2045 if (options.useXstack)
2049 /* Assume r0 is available for use. */
2050 r = ds390_regWithIdx (R0_IDX);;
2055 r = getFreePtr (ic, &aop, FALSE);
2057 emitcode ("mov", "%s,_spx", r->name);
2062 if (options.useXstack)
2064 emitcode ("movx", "a,@%s", r->name);
2065 emitcode ("mov", "psw,a");
2066 emitcode ("dec", "%s", r->name);
2070 emitcode ("pop", "psw");
2074 for (i = (ds390_nRegs - 1); i >= 0; i--)
2076 if (options.useXstack)
2078 emitcode ("movx", "a,@%s", r->name);
2079 emitcode ("mov", "(%s+%d),a",
2080 regs390[i].base, 8 * bank + regs390[i].offset);
2081 emitcode ("dec", "%s", r->name);
2085 emitcode ("pop", "(%s+%d)",
2086 regs390[i].base, 8 * bank + regs390[i].offset);
2089 if (options.useXstack)
2091 emitcode ("mov", "_spx,%s", r->name);
2096 freeAsmop (NULL, aop, ic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* saveRBank - saves an entire register bank on the stack */
2102 /*-----------------------------------------------------------------*/
2104 saveRBank (int bank, iCode * ic, bool pushPsw)
2110 if (options.useXstack)
2114 /* Assume r0 is available for use. */
2115 r = ds390_regWithIdx (R0_IDX);;
2120 r = getFreePtr (ic, &aop, FALSE);
2122 emitcode ("mov", "%s,_spx", r->name);
2125 for (i = 0; i < ds390_nRegs; i++)
2127 if (options.useXstack)
2129 emitcode ("inc", "%s", r->name);
2130 emitcode ("mov", "a,(%s+%d)",
2131 regs390[i].base, 8 * bank + regs390[i].offset);
2132 emitcode ("movx", "@%s,a", r->name);
2135 emitcode ("push", "(%s+%d)",
2136 regs390[i].base, 8 * bank + regs390[i].offset);
2141 if (options.useXstack)
2143 emitcode ("mov", "a,psw");
2144 emitcode ("movx", "@%s,a", r->name);
2145 emitcode ("inc", "%s", r->name);
2146 emitcode ("mov", "_spx,%s", r->name);
2150 emitcode ("push", "psw");
2153 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2158 freeAsmop (NULL, aop, ic, TRUE);
2167 /*-----------------------------------------------------------------*/
2168 /* genCall - generates a call statement */
2169 /*-----------------------------------------------------------------*/
2171 genCall (iCode * ic)
2174 bool restoreBank = FALSE;
2175 bool swapBanks = FALSE;
2177 D (emitcode (";", "genCall "););
2179 /* if we are calling a not _naked function that is not using
2180 the same register bank then we need to save the
2181 destination registers on the stack */
2182 detype = getSpec (operandType (IC_LEFT (ic)));
2183 if (detype && !SPEC_NAKED(detype) &&
2184 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2185 IS_ISR (currFunc->etype))
2189 /* This is unexpected; the bank should have been saved in
2192 saveRBank (SPEC_BANK (detype), ic, FALSE);
2198 /* if caller saves & we have not saved then */
2202 /* if send set is not empty the assign */
2203 /* We've saved all the registers we care about;
2204 * therefore, we may clobber any register not used
2205 * in the calling convention (i.e. anything not in
2212 for (sic = setFirstItem (_G.sendSet); sic;
2213 sic = setNextItem (_G.sendSet))
2215 int size, offset = 0;
2217 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2218 size = AOP_SIZE (IC_LEFT (sic));
2220 _startLazyDPSEvaluation ();
2223 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2224 FALSE, FALSE, TRUE);
2225 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2227 emitcode("mov", "%s,%s", regs390[offset].name, l);
2229 else if (strcmp (l, fReturn[offset]))
2231 emitcode ("mov", "%s,%s",
2237 _endLazyDPSEvaluation ();
2238 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2240 size = AOP_SIZE (IC_LEFT (sic));
2248 emitcode("mov", "%s,%s",
2249 fReturn[size], regs390[size].name);
2252 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2259 emitcode ("mov", "psw,#0x%02x",
2260 ((SPEC_BANK(detype)) << 3) & 0xff);
2264 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2265 OP_SYMBOL (IC_LEFT (ic))->rname :
2266 OP_SYMBOL (IC_LEFT (ic))->name));
2270 emitcode ("mov", "psw,#0x%02x",
2271 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
2274 /* if we need assign a result value */
2275 if ((IS_ITEMP (IC_RESULT (ic)) &&
2276 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2277 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2278 IS_TRUE_SYMOP (IC_RESULT (ic)))
2280 if (isOperandInFarSpace (IC_RESULT (ic))
2281 && getSize (operandType (IC_RESULT (ic))) <= 2)
2283 int size = getSize (operandType (IC_RESULT (ic)));
2285 /* Special case for 1 or 2 byte return in far space. */
2289 emitcode ("mov", "b,%s", fReturn[1]);
2292 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2293 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2297 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2304 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2307 assignResultValue (IC_RESULT (ic));
2309 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2313 /* adjust the stack for parameters if
2318 if (ic->parmBytes > 3)
2320 emitcode ("mov", "a,%s", spname);
2321 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2322 emitcode ("mov", "%s,a", spname);
2325 for (i = 0; i < ic->parmBytes; i++)
2326 emitcode ("dec", "%s", spname);
2329 /* if we hade saved some registers then unsave them */
2330 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2331 unsaveRegisters (ic);
2333 /* if register bank was saved then pop them */
2335 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
2338 /*-----------------------------------------------------------------*/
2339 /* genPcall - generates a call by pointer statement */
2340 /*-----------------------------------------------------------------*/
2342 genPcall (iCode * ic)
2345 symbol *rlbl = newiTempLabel (NULL);
2347 D (emitcode (";", "genPcall ");
2351 /* if caller saves & we have not saved then */
2355 /* if we are calling a function that is not using
2356 the same register bank then we need to save the
2357 destination registers on the stack */
2358 detype = getSpec (operandType (IC_LEFT (ic)));
2360 IS_ISR (currFunc->etype) &&
2361 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2362 saveRBank (SPEC_BANK (detype), ic, TRUE);
2365 /* push the return address on to the stack */
2366 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2367 emitcode ("push", "acc");
2368 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2369 emitcode ("push", "acc");
2371 if (options.model == MODEL_FLAT24)
2373 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2374 emitcode ("push", "acc");
2377 /* now push the calling address */
2378 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2380 pushSide (IC_LEFT (ic), FPTRSIZE);
2382 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2384 /* if send set is not empty the assign */
2389 for (sic = setFirstItem (_G.sendSet); sic;
2390 sic = setNextItem (_G.sendSet))
2392 int size, offset = 0;
2394 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2395 size = AOP_SIZE (IC_LEFT (sic));
2396 _startLazyDPSEvaluation ();
2399 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2400 FALSE, FALSE, TRUE);
2401 if (strcmp (l, fReturn[offset]))
2403 emitcode ("mov", "%s,%s",
2409 _endLazyDPSEvaluation ();
2410 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2415 emitcode ("ret", "");
2416 emitcode ("", "%05d$:", (rlbl->key + 100));
2419 /* if we need assign a result value */
2420 if ((IS_ITEMP (IC_RESULT (ic)) &&
2421 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2422 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2423 IS_TRUE_SYMOP (IC_RESULT (ic)))
2427 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2430 assignResultValue (IC_RESULT (ic));
2432 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2435 /* adjust the stack for parameters if
2440 if (ic->parmBytes > 3)
2442 emitcode ("mov", "a,%s", spname);
2443 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2444 emitcode ("mov", "%s,a", spname);
2447 for (i = 0; i < ic->parmBytes; i++)
2448 emitcode ("dec", "%s", spname);
2452 /* if register bank was saved then unsave them */
2454 (SPEC_BANK (currFunc->etype) !=
2455 SPEC_BANK (detype)))
2456 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2458 /* if we hade saved some registers then
2461 unsaveRegisters (ic);
2465 /*-----------------------------------------------------------------*/
2466 /* resultRemat - result is rematerializable */
2467 /*-----------------------------------------------------------------*/
2469 resultRemat (iCode * ic)
2471 if (SKIP_IC (ic) || ic->op == IFX)
2474 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2476 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2477 if (sym->remat && !POINTER_SET (ic))
2484 #if defined(__BORLANDC__) || defined(_MSC_VER)
2485 #define STRCASECMP stricmp
2487 #define STRCASECMP strcasecmp
2490 /*-----------------------------------------------------------------*/
2491 /* inExcludeList - return 1 if the string is in exclude Reg list */
2492 /*-----------------------------------------------------------------*/
2494 inExcludeList (char *s)
2498 if (options.excludeRegs[i] &&
2499 STRCASECMP (options.excludeRegs[i], "none") == 0)
2502 for (i = 0; options.excludeRegs[i]; i++)
2504 if (options.excludeRegs[i] &&
2505 STRCASECMP (s, options.excludeRegs[i]) == 0)
2511 /*-----------------------------------------------------------------*/
2512 /* genFunction - generated code for function entry */
2513 /*-----------------------------------------------------------------*/
2515 genFunction (iCode * ic)
2519 bool switchedPSW = FALSE;
2521 D (emitcode (";", "genFunction "););
2524 /* create the function header */
2525 emitcode (";", "-----------------------------------------");
2526 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2527 emitcode (";", "-----------------------------------------");
2529 emitcode ("", "%s:", sym->rname);
2530 fetype = getSpec (operandType (IC_LEFT (ic)));
2532 if (SPEC_NAKED(fetype))
2534 emitcode(";", "naked function: no prologue.");
2538 /* if critical function then turn interrupts off */
2539 if (SPEC_CRTCL (fetype))
2540 emitcode ("clr", "ea");
2542 /* here we need to generate the equates for the
2543 register bank if required */
2544 if (SPEC_BANK (fetype) != rbank)
2548 rbank = SPEC_BANK (fetype);
2549 for (i = 0; i < ds390_nRegs; i++)
2551 if (strcmp (regs390[i].base, "0") == 0)
2552 emitcode ("", "%s = 0x%02x",
2554 8 * rbank + regs390[i].offset);
2556 emitcode ("", "%s = %s + 0x%02x",
2559 8 * rbank + regs390[i].offset);
2563 /* if this is an interrupt service routine then
2564 save acc, b, dpl, dph */
2565 if (IS_ISR (sym->etype))
2568 if (!inExcludeList ("acc"))
2569 emitcode ("push", "acc");
2570 if (!inExcludeList ("b"))
2571 emitcode ("push", "b");
2572 if (!inExcludeList ("dpl"))
2573 emitcode ("push", "dpl");
2574 if (!inExcludeList ("dph"))
2575 emitcode ("push", "dph");
2576 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2578 emitcode ("push", "dpx");
2579 /* Make sure we're using standard DPTR */
2580 emitcode ("push", "dps");
2581 emitcode ("mov", "dps, #0x00");
2582 if (options.stack10bit)
2584 /* This ISR could conceivably use DPTR2. Better save it. */
2585 emitcode ("push", "dpl1");
2586 emitcode ("push", "dph1");
2587 emitcode ("push", "dpx1");
2588 emitcode ("push", DP2_RESULT_REG);
2591 /* if this isr has no bank i.e. is going to
2592 run with bank 0 , then we need to save more
2594 if (!SPEC_BANK (sym->etype))
2597 /* if this function does not call any other
2598 function then we can be economical and
2599 save only those registers that are used */
2604 /* if any registers used */
2607 /* save the registers used */
2608 for (i = 0; i < sym->regsUsed->size; i++)
2610 if (bitVectBitValue (sym->regsUsed, i) ||
2611 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2612 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2619 /* this function has a function call cannot
2620 determines register usage so we will have to push the
2622 saveRBank (0, ic, FALSE);
2627 /* This ISR uses a non-zero bank.
2629 * We assume that the bank is available for our
2632 * However, if this ISR calls a function which uses some
2633 * other bank, we must save that bank entirely.
2635 unsigned long banksToSave = 0;
2640 #define MAX_REGISTER_BANKS 4
2645 for (i = ic; i; i = i->next)
2647 if (i->op == ENDFUNCTION)
2649 /* we got to the end OK. */
2657 detype = getSpec(operandType (IC_LEFT(i)));
2659 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2661 /* Mark this bank for saving. */
2662 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2664 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2668 banksToSave |= (1 << SPEC_BANK(detype));
2671 /* And note that we don't need to do it in
2679 /* This is a mess; we have no idea what
2680 * register bank the called function might
2683 * The only thing I can think of to do is
2684 * throw a warning and hope.
2686 werror(W_FUNCPTR_IN_USING_ISR);
2690 if (banksToSave && options.useXstack)
2692 /* Since we aren't passing it an ic,
2693 * saveRBank will assume r0 is available to abuse.
2695 * So switch to our (trashable) bank now, so
2696 * the caller's R0 isn't trashed.
2698 emitcode ("push", "psw");
2699 emitcode ("mov", "psw,#0x%02x",
2700 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2704 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2706 if (banksToSave & (1 << ix))
2708 saveRBank(ix, NULL, FALSE);
2712 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2717 /* if callee-save to be used for this function
2718 then save the registers being used in this function */
2719 if (sym->calleeSave)
2723 /* if any registers used */
2726 /* save the registers used */
2727 for (i = 0; i < sym->regsUsed->size; i++)
2729 if (bitVectBitValue (sym->regsUsed, i) ||
2730 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2732 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2740 /* set the register bank to the desired value */
2741 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2744 emitcode ("push", "psw");
2745 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2748 if (IS_RENT (sym->etype) || options.stackAuto)
2751 if (options.useXstack)
2753 emitcode ("mov", "r0,%s", spname);
2754 emitcode ("mov", "a,_bp");
2755 emitcode ("movx", "@r0,a");
2756 emitcode ("inc", "%s", spname);
2760 /* set up the stack */
2761 emitcode ("push", "_bp"); /* save the callers stack */
2763 emitcode ("mov", "_bp,%s", spname);
2766 /* adjust the stack for the function */
2772 werror (W_STACK_OVERFLOW, sym->name);
2774 if (i > 3 && sym->recvSize < 4)
2777 emitcode ("mov", "a,sp");
2778 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2779 emitcode ("mov", "sp,a");
2784 emitcode ("inc", "sp");
2790 emitcode ("mov", "a,_spx");
2791 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2792 emitcode ("mov", "_spx,a");
2797 /*-----------------------------------------------------------------*/
2798 /* genEndFunction - generates epilogue for functions */
2799 /*-----------------------------------------------------------------*/
2801 genEndFunction (iCode * ic)
2803 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2805 D (emitcode (";", "genEndFunction "););
2807 if (SPEC_NAKED(sym->etype))
2809 emitcode(";", "naked function: no epilogue.");
2813 if (IS_RENT (sym->etype) || options.stackAuto)
2815 emitcode ("mov", "%s,_bp", spname);
2818 /* if use external stack but some variables were
2819 added to the local stack then decrement the
2821 if (options.useXstack && sym->stack)
2823 emitcode ("mov", "a,sp");
2824 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2825 emitcode ("mov", "sp,a");
2829 if ((IS_RENT (sym->etype) || options.stackAuto))
2831 if (options.useXstack)
2833 emitcode ("mov", "r0,%s", spname);
2834 emitcode ("movx", "a,@r0");
2835 emitcode ("mov", "_bp,a");
2836 emitcode ("dec", "%s", spname);
2840 emitcode ("pop", "_bp");
2844 /* restore the register bank */
2845 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2847 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2848 || !options.useXstack)
2850 /* Special case of ISR using non-zero bank with useXstack
2853 emitcode ("pop", "psw");
2857 if (IS_ISR (sym->etype))
2860 /* now we need to restore the registers */
2861 /* if this isr has no bank i.e. is going to
2862 run with bank 0 , then we need to save more
2864 if (!SPEC_BANK (sym->etype))
2866 /* if this function does not call any other
2867 function then we can be economical and
2868 save only those registers that are used */
2873 /* if any registers used */
2876 /* save the registers used */
2877 for (i = sym->regsUsed->size; i >= 0; i--)
2879 if (bitVectBitValue (sym->regsUsed, i) ||
2880 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2881 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2888 /* this function has a function call cannot
2889 determines register usage so we will have to pop the
2891 unsaveRBank (0, ic, FALSE);
2896 /* This ISR uses a non-zero bank.
2898 * Restore any register banks saved by genFunction
2901 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2904 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2906 if (savedBanks & (1 << ix))
2908 unsaveRBank(ix, NULL, FALSE);
2912 if (options.useXstack)
2914 /* Restore bank AFTER calling unsaveRBank,
2915 * since it can trash r0.
2917 emitcode ("pop", "psw");
2921 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2923 if (options.stack10bit)
2925 emitcode ("pop", DP2_RESULT_REG);
2926 emitcode ("pop", "dpx1");
2927 emitcode ("pop", "dph1");
2928 emitcode ("pop", "dpl1");
2930 emitcode ("pop", "dps");
2931 emitcode ("pop", "dpx");
2933 if (!inExcludeList ("dph"))
2934 emitcode ("pop", "dph");
2935 if (!inExcludeList ("dpl"))
2936 emitcode ("pop", "dpl");
2937 if (!inExcludeList ("b"))
2938 emitcode ("pop", "b");
2939 if (!inExcludeList ("acc"))
2940 emitcode ("pop", "acc");
2942 if (SPEC_CRTCL (sym->etype))
2943 emitcode ("setb", "ea");
2945 /* if debug then send end of function */
2946 if (options.debug && currFunc) {
2948 emitcode ("", "C$%s$%d$%d$%d ==.",
2949 FileBaseName (ic->filename), currFunc->lastLine,
2950 ic->level, ic->block);
2951 if (IS_STATIC (currFunc->etype))
2952 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2954 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2958 emitcode ("reti", "");
2962 if (SPEC_CRTCL (sym->etype))
2963 emitcode ("setb", "ea");
2965 if (sym->calleeSave)
2969 /* if any registers used */
2972 /* save the registers used */
2973 for (i = sym->regsUsed->size; i >= 0; i--)
2975 if (bitVectBitValue (sym->regsUsed, i) ||
2976 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2977 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2983 /* if debug then send end of function */
2984 if (options.debug && currFunc)
2987 emitcode ("", "C$%s$%d$%d$%d ==.",
2988 FileBaseName (ic->filename), currFunc->lastLine,
2989 ic->level, ic->block);
2990 if (IS_STATIC (currFunc->etype))
2991 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2993 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2997 emitcode ("ret", "");
3002 /*-----------------------------------------------------------------*/
3003 /* genRet - generate code for return statement */
3004 /*-----------------------------------------------------------------*/
3008 int size, offset = 0, pushed = 0;
3010 D (emitcode (";", "genRet ");
3013 /* if we have no return value then
3014 just generate the "ret" */
3018 /* we have something to return then
3019 move the return value into place */
3020 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3021 size = AOP_SIZE (IC_LEFT (ic));
3023 _startLazyDPSEvaluation ();
3027 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3029 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3030 FALSE, TRUE, FALSE);
3031 emitcode ("push", "%s", l);
3036 /* Since A is the last element of fReturn,
3037 * is is OK to clobber it in the aopGet.
3039 l = aopGet (AOP (IC_LEFT (ic)), offset,
3040 FALSE, FALSE, TRUE);
3041 if (strcmp (fReturn[offset], l))
3042 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3045 _endLazyDPSEvaluation ();
3052 if (strcmp (fReturn[pushed], "a"))
3053 emitcode ("pop", fReturn[pushed]);
3055 emitcode ("pop", "acc");
3058 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3061 /* generate a jump to the return label
3062 if the next is not the return statement */
3063 if (!(ic->next && ic->next->op == LABEL &&
3064 IC_LABEL (ic->next) == returnLabel))
3066 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3070 /*-----------------------------------------------------------------*/
3071 /* genLabel - generates a label */
3072 /*-----------------------------------------------------------------*/
3074 genLabel (iCode * ic)
3076 /* special case never generate */
3077 if (IC_LABEL (ic) == entryLabel)
3080 D (emitcode (";", "genLabel ");
3083 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3086 /*-----------------------------------------------------------------*/
3087 /* genGoto - generates a ljmp */
3088 /*-----------------------------------------------------------------*/
3090 genGoto (iCode * ic)
3092 D (emitcode (";", "genGoto ");
3094 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3097 /*-----------------------------------------------------------------*/
3098 /* findLabelBackwards: walks back through the iCode chain looking */
3099 /* for the given label. Returns number of iCode instructions */
3100 /* between that label and given ic. */
3101 /* Returns zero if label not found. */
3102 /*-----------------------------------------------------------------*/
3104 findLabelBackwards (iCode * ic, int key)
3113 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3115 /* printf("findLabelBackwards = %d\n", count); */
3123 /*-----------------------------------------------------------------*/
3124 /* genPlusIncr :- does addition with increment if possible */
3125 /*-----------------------------------------------------------------*/
3127 genPlusIncr (iCode * ic)
3129 unsigned int icount;
3130 unsigned int size = getDataSize (IC_RESULT (ic));
3132 /* will try to generate an increment */
3133 /* if the right side is not a literal
3135 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3138 /* if the literal value of the right hand side
3139 is greater than 4 then it is not worth it */
3140 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3143 /* if increment 16 bits in register */
3145 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3146 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3147 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3155 /* If the next instruction is a goto and the goto target
3156 * is <= 5 instructions previous to this, we can generate
3157 * jumps straight to that target.
3159 if (ic->next && ic->next->op == GOTO
3160 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3163 emitcode (";", "tail increment optimized (range %d)", labelRange);
3164 tlbl = IC_LABEL (ic->next);
3169 tlbl = newiTempLabel (NULL);
3172 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3173 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3174 IS_AOP_PREG (IC_RESULT (ic)))
3175 emitcode ("cjne", "%s,#0x00,%05d$"
3176 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3180 emitcode ("clr", "a");
3181 emitcode ("cjne", "a,%s,%05d$"
3182 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3186 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3189 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3190 IS_AOP_PREG (IC_RESULT (ic)))
3191 emitcode ("cjne", "%s,#0x00,%05d$"
3192 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3195 emitcode ("cjne", "a,%s,%05d$"
3196 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3199 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3203 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3204 IS_AOP_PREG (IC_RESULT (ic)))
3205 emitcode ("cjne", "%s,#0x00,%05d$"
3206 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3210 emitcode ("cjne", "a,%s,%05d$"
3211 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3214 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3219 emitcode ("", "%05d$:", tlbl->key + 100);
3224 /* if the sizes are greater than 1 then we cannot */
3225 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3226 AOP_SIZE (IC_LEFT (ic)) > 1)
3229 /* we can if the aops of the left & result match or
3230 if they are in registers and the registers are the
3233 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3234 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3235 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3240 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3241 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3242 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3247 _startLazyDPSEvaluation ();
3250 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3252 _endLazyDPSEvaluation ();
3261 /*-----------------------------------------------------------------*/
3262 /* outBitAcc - output a bit in acc */
3263 /*-----------------------------------------------------------------*/
3265 outBitAcc (operand * result)
3267 symbol *tlbl = newiTempLabel (NULL);
3268 /* if the result is a bit */
3269 if (AOP_TYPE (result) == AOP_CRY)
3271 aopPut (AOP (result), "a", 0);
3275 emitcode ("jz", "%05d$", tlbl->key + 100);
3276 emitcode ("mov", "a,%s", one);
3277 emitcode ("", "%05d$:", tlbl->key + 100);
3282 /*-----------------------------------------------------------------*/
3283 /* genPlusBits - generates code for addition of two bits */
3284 /*-----------------------------------------------------------------*/
3286 genPlusBits (iCode * ic)
3288 D (emitcode (";", "genPlusBits ");
3290 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3292 symbol *lbl = newiTempLabel (NULL);
3293 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3294 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3295 emitcode ("cpl", "c");
3296 emitcode ("", "%05d$:", (lbl->key + 100));
3297 outBitC (IC_RESULT (ic));
3301 emitcode ("clr", "a");
3302 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3303 emitcode ("rlc", "a");
3304 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3305 emitcode ("addc", "a,#0x00");
3306 outAcc (IC_RESULT (ic));
3311 adjustArithmeticResult (iCode * ic)
3313 if (opIsGptr (IC_RESULT (ic)) &&
3314 opIsGptr (IC_LEFT (ic)) &&
3315 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3317 aopPut (AOP (IC_RESULT (ic)),
3318 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3322 if (opIsGptr (IC_RESULT (ic)) &&
3323 opIsGptr (IC_RIGHT (ic)) &&
3324 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3326 aopPut (AOP (IC_RESULT (ic)),
3327 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3331 if (opIsGptr (IC_RESULT (ic)) &&
3332 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3333 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3334 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3335 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3338 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3339 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3343 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3344 // (because all three operands are in far space).
3345 #define AOP_OP_3(ic) \
3346 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3347 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3348 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3349 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3350 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3351 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3353 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3355 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3358 // Macro to aopOp all three operands of an ic. If this cannot be done,
3359 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3360 // will be set TRUE. The caller must then handle the case specially, noting
3361 // that the IC_RESULT operand is not aopOp'd.
3362 #define AOP_OP_3_NOFATAL(ic, rc) \
3363 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3364 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3365 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3366 isOperandInFarSpace(IC_RESULT(ic))) \
3368 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3373 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3374 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3376 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3377 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3379 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3381 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3385 // aopOp the left & right operands of an ic.
3386 #define AOP_OP_2(ic) \
3387 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3388 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3390 // convienience macro.
3391 #define AOP_SET_LOCALS(ic) \
3392 left = IC_LEFT(ic); \
3393 right = IC_RIGHT(ic); \
3394 result = IC_RESULT(ic);
3397 // Given an integer value of pushedSize bytes on the stack,
3398 // adjust it to be resultSize bytes, either by discarding
3399 // the most significant bytes or by zero-padding.
3401 // On exit from this macro, pushedSize will have been adjusted to
3402 // equal resultSize, and ACC may be trashed.
3403 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3404 /* If the pushed data is bigger than the result, \
3405 * simply discard unused bytes. Icky, but works. \
3407 while (pushedSize > resultSize) \
3409 D (emitcode (";", "discarding unused result byte."););\
3410 emitcode ("pop", "acc"); \
3413 if (pushedSize < resultSize) \
3415 emitcode ("clr", "a"); \
3416 /* Conversly, we haven't pushed enough here. \
3417 * just zero-pad, and all is well. \
3419 while (pushedSize < resultSize) \
3421 emitcode("push", "acc"); \
3425 assert(pushedSize == resultSize);
3427 /*-----------------------------------------------------------------*/
3428 /* genPlus - generates code for addition */
3429 /*-----------------------------------------------------------------*/
3431 genPlus (iCode * ic)
3433 int size, offset = 0;
3434 bool pushResult = FALSE;
3437 D (emitcode (";", "genPlus "););
3439 /* special cases :- */
3441 AOP_OP_3_NOFATAL (ic, pushResult);
3444 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3449 /* if literal, literal on the right or
3450 if left requires ACC or right is already
3452 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3453 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3454 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3456 operand *t = IC_RIGHT (ic);
3457 IC_RIGHT (ic) = IC_LEFT (ic);
3459 emitcode (";", "Swapped plus args.");
3462 /* if both left & right are in bit
3464 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3465 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3471 /* if left in bit space & right literal */
3472 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3473 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3475 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3476 /* if result in bit space */
3477 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3479 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3480 emitcode ("cpl", "c");
3481 outBitC (IC_RESULT (ic));
3485 size = getDataSize (IC_RESULT (ic));
3486 _startLazyDPSEvaluation ();
3489 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3490 emitcode ("addc", "a,#00");
3491 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3493 _endLazyDPSEvaluation ();
3498 /* if I can do an increment instead
3499 of add then GOOD for ME */
3500 if (genPlusIncr (ic) == TRUE)
3502 emitcode (";", "did genPlusIncr");
3507 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3509 _startLazyDPSEvaluation ();
3512 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3514 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3516 emitcode ("add", "a,%s",
3517 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3519 emitcode ("addc", "a,%s",
3520 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3524 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3526 /* right is going to use ACC or we would have taken the
3529 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3530 D(emitcode(";", "+ AOP_ACC special case."););
3531 emitcode("xch", "a, %s", DP2_RESULT_REG);
3533 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3536 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3538 emitcode("add", "a, %s", DP2_RESULT_REG);
3542 emitcode ("add", "a,%s",
3543 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3548 emitcode ("addc", "a,%s",
3549 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3554 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3558 emitcode ("push", "acc");
3562 _endLazyDPSEvaluation ();
3566 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3568 size = getDataSize (IC_LEFT (ic));
3569 rSize = getDataSize (IC_RESULT (ic));
3571 ADJUST_PUSHED_RESULT(size, rSize);
3573 _startLazyDPSEvaluation ();
3576 emitcode ("pop", "acc");
3577 aopPut (AOP (IC_RESULT (ic)), "a", size);
3579 _endLazyDPSEvaluation ();
3582 adjustArithmeticResult (ic);
3585 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3586 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3587 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3590 /*-----------------------------------------------------------------*/
3591 /* genMinusDec :- does subtraction with deccrement if possible */
3592 /*-----------------------------------------------------------------*/
3594 genMinusDec (iCode * ic)
3596 unsigned int icount;
3597 unsigned int size = getDataSize (IC_RESULT (ic));
3599 /* will try to generate an increment */
3600 /* if the right side is not a literal
3602 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3605 /* if the literal value of the right hand side
3606 is greater than 4 then it is not worth it */
3607 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3610 /* if decrement 16 bits in register */
3611 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3612 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3613 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3621 /* If the next instruction is a goto and the goto target
3622 * is <= 5 instructions previous to this, we can generate
3623 * jumps straight to that target.
3625 if (ic->next && ic->next->op == GOTO
3626 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3629 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3630 tlbl = IC_LABEL (ic->next);
3635 tlbl = newiTempLabel (NULL);
3639 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3640 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3641 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3642 IS_AOP_PREG (IC_RESULT (ic)))
3643 emitcode ("cjne", "%s,#0xff,%05d$"
3644 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3648 emitcode ("mov", "a,#0xff");
3649 emitcode ("cjne", "a,%s,%05d$"
3650 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3653 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3656 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3657 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3658 IS_AOP_PREG (IC_RESULT (ic)))
3659 emitcode ("cjne", "%s,#0xff,%05d$"
3660 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3664 emitcode ("cjne", "a,%s,%05d$"
3665 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3668 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3672 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3673 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3674 IS_AOP_PREG (IC_RESULT (ic)))
3675 emitcode ("cjne", "%s,#0xff,%05d$"
3676 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3680 emitcode ("cjne", "a,%s,%05d$"
3681 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3684 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3688 emitcode ("", "%05d$:", tlbl->key + 100);
3693 /* if the sizes are greater than 1 then we cannot */
3694 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3695 AOP_SIZE (IC_LEFT (ic)) > 1)
3698 /* we can if the aops of the left & result match or
3699 if they are in registers and the registers are the
3702 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3703 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3704 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3707 _startLazyDPSEvaluation ();
3710 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3712 _endLazyDPSEvaluation ();
3720 /*-----------------------------------------------------------------*/
3721 /* addSign - complete with sign */
3722 /*-----------------------------------------------------------------*/
3724 addSign (operand * result, int offset, int sign)
3726 int size = (getDataSize (result) - offset);
3729 _startLazyDPSEvaluation();
3732 emitcode ("rlc", "a");
3733 emitcode ("subb", "a,acc");
3736 aopPut (AOP (result), "a", offset++);
3743 aopPut (AOP (result), zero, offset++);
3746 _endLazyDPSEvaluation();
3750 /*-----------------------------------------------------------------*/
3751 /* genMinusBits - generates code for subtraction of two bits */
3752 /*-----------------------------------------------------------------*/
3754 genMinusBits (iCode * ic)
3756 symbol *lbl = newiTempLabel (NULL);
3758 D (emitcode (";", "genMinusBits "););
3760 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3762 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3763 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3764 emitcode ("cpl", "c");
3765 emitcode ("", "%05d$:", (lbl->key + 100));
3766 outBitC (IC_RESULT (ic));
3770 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3771 emitcode ("subb", "a,acc");
3772 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3773 emitcode ("inc", "a");
3774 emitcode ("", "%05d$:", (lbl->key + 100));
3775 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3776 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3780 /*-----------------------------------------------------------------*/
3781 /* genMinus - generates code for subtraction */
3782 /*-----------------------------------------------------------------*/
3784 genMinus (iCode * ic)
3786 int size, offset = 0;
3788 unsigned long lit = 0L;
3789 bool pushResult = FALSE;
3791 D (emitcode (";", "genMinus "););
3793 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3794 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3795 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3796 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3802 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3804 /* special cases :- */
3805 /* if both left & right are in bit space */
3806 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3807 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3813 /* if I can do an decrement instead
3814 of subtract then GOOD for ME */
3815 if (genMinusDec (ic) == TRUE)
3820 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3822 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3828 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3833 /* if literal, add a,#-lit, else normal subb */
3834 _startLazyDPSEvaluation ();
3837 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3838 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3839 emitcode ("subb", "a,%s",
3840 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3843 /* first add without previous c */
3845 emitcode ("add", "a,#0x%02x",
3846 (unsigned int) (lit & 0x0FFL));
3848 emitcode ("addc", "a,#0x%02x",
3849 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3854 emitcode ("push", "acc");
3858 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3862 _endLazyDPSEvaluation ();
3866 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3868 size = getDataSize (IC_LEFT (ic));
3869 rSize = getDataSize (IC_RESULT (ic));
3871 ADJUST_PUSHED_RESULT(size, rSize);
3873 _startLazyDPSEvaluation ();
3876 emitcode ("pop", "acc");
3877 aopPut (AOP (IC_RESULT (ic)), "a", size);
3879 _endLazyDPSEvaluation ();
3882 adjustArithmeticResult (ic);
3885 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3886 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3887 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3891 /*-----------------------------------------------------------------*/
3892 /* genMultbits :- multiplication of bits */
3893 /*-----------------------------------------------------------------*/
3895 genMultbits (operand * left,
3899 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3900 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3905 /*-----------------------------------------------------------------*/
3906 /* genMultOneByte : 8*8=8/16 bit multiplication */
3907 /*-----------------------------------------------------------------*/
3909 genMultOneByte (operand * left,
3913 sym_link *opetype = operandType (result);
3915 int size=AOP_SIZE(result);
3917 if (size<1 || size>2) {
3918 // this should never happen
3919 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3920 AOP_SIZE(result), __FILE__, lineno);
3924 /* (if two literals: the value is computed before) */
3925 /* if one literal, literal on the right */
3926 if (AOP_TYPE (left) == AOP_LIT)
3931 emitcode (";", "swapped left and right");
3934 if (SPEC_USIGN(opetype)
3935 // ignore the sign of left and right, what else can we do?
3936 || (SPEC_USIGN(operandType(left)) &&
3937 SPEC_USIGN(operandType(right)))) {
3938 // just an unsigned 8*8=8/16 multiply
3939 //emitcode (";","unsigned");
3940 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3941 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3942 emitcode ("mul", "ab");
3943 aopPut (AOP (result), "a", 0);
3945 aopPut (AOP (result), "b", 1);
3950 // we have to do a signed multiply
3952 emitcode (";", "signed");
3953 emitcode ("clr", "F0"); // reset sign flag
3954 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3956 lbl=newiTempLabel(NULL);
3957 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3958 // left side is negative, 8-bit two's complement, this fails for -128
3959 emitcode ("setb", "F0"); // set sign flag
3960 emitcode ("cpl", "a");
3961 emitcode ("inc", "a");
3963 emitcode ("", "%05d$:", lbl->key+100);
3966 if (AOP_TYPE(right)==AOP_LIT) {
3967 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3968 /* AND literal negative */
3969 if ((int) val < 0) {
3970 emitcode ("cpl", "F0"); // complement sign flag
3971 emitcode ("mov", "b,#0x%02x", -val);
3973 emitcode ("mov", "b,#0x%02x", val);
3976 lbl=newiTempLabel(NULL);
3977 emitcode ("mov", "b,a");
3978 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3979 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3980 // right side is negative, 8-bit two's complement
3981 emitcode ("cpl", "F0"); // complement sign flag
3982 emitcode ("cpl", "a");
3983 emitcode ("inc", "a");
3984 emitcode ("", "%05d$:", lbl->key+100);
3986 emitcode ("mul", "ab");
3988 lbl=newiTempLabel(NULL);
3989 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3990 // only ONE op was negative, we have to do a 8/16-bit two's complement
3991 emitcode ("cpl", "a"); // lsb
3993 emitcode ("inc", "a");
3995 emitcode ("add", "a,#1");
3996 emitcode ("xch", "a,b");
3997 emitcode ("cpl", "a"); // msb
3998 emitcode ("addc", "a,#0");
3999 emitcode ("xch", "a,b");
4002 emitcode ("", "%05d$:", lbl->key+100);
4003 aopPut (AOP (result), "a", 0);
4005 aopPut (AOP (result), "b", 1);
4009 /*-----------------------------------------------------------------*/
4010 /* genMult - generates code for multiplication */
4011 /*-----------------------------------------------------------------*/
4013 genMult (iCode * ic)
4015 operand *left = IC_LEFT (ic);
4016 operand *right = IC_RIGHT (ic);
4017 operand *result = IC_RESULT (ic);
4019 D (emitcode (";", "genMult "););
4021 /* assign the amsops */
4024 /* special cases first */
4026 if (AOP_TYPE (left) == AOP_CRY &&
4027 AOP_TYPE (right) == AOP_CRY)
4029 genMultbits (left, right, result);
4033 /* if both are of size == 1 */
4034 if (AOP_SIZE (left) == 1 &&
4035 AOP_SIZE (right) == 1)
4037 genMultOneByte (left, right, result);
4041 /* should have been converted to function call */
4045 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4046 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4047 freeAsmop (result, NULL, ic, TRUE);
4050 /*-----------------------------------------------------------------*/
4051 /* genDivbits :- division of bits */
4052 /*-----------------------------------------------------------------*/
4054 genDivbits (operand * left,
4061 /* the result must be bit */
4062 LOAD_AB_FOR_DIV (left, right, l);
4063 emitcode ("div", "ab");
4064 emitcode ("rrc", "a");
4065 aopPut (AOP (result), "c", 0);
4068 /*-----------------------------------------------------------------*/
4069 /* genDivOneByte : 8 bit division */
4070 /*-----------------------------------------------------------------*/
4072 genDivOneByte (operand * left,
4076 sym_link *opetype = operandType (result);
4081 size = AOP_SIZE (result) - 1;
4083 /* signed or unsigned */
4084 if (SPEC_USIGN (opetype))
4086 /* unsigned is easy */
4087 LOAD_AB_FOR_DIV (left, right, l);
4088 emitcode ("div", "ab");
4089 aopPut (AOP (result), "a", 0);
4091 aopPut (AOP (result), zero, offset++);
4095 /* signed is a little bit more difficult */
4097 /* save the signs of the operands */
4098 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4100 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4101 emitcode ("push", "acc"); /* save it on the stack */
4103 /* now sign adjust for both left & right */
4104 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4106 lbl = newiTempLabel (NULL);
4107 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4108 emitcode ("cpl", "a");
4109 emitcode ("inc", "a");
4110 emitcode ("", "%05d$:", (lbl->key + 100));
4111 emitcode ("mov", "b,a");
4113 /* sign adjust left side */
4114 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4117 lbl = newiTempLabel (NULL);
4118 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4119 emitcode ("cpl", "a");
4120 emitcode ("inc", "a");
4121 emitcode ("", "%05d$:", (lbl->key + 100));
4123 /* now the division */
4124 emitcode ("nop", "; workaround for DS80C390 div bug.");
4125 emitcode ("div", "ab");
4126 /* we are interested in the lower order
4128 emitcode ("mov", "b,a");
4129 lbl = newiTempLabel (NULL);
4130 emitcode ("pop", "acc");
4131 /* if there was an over flow we don't
4132 adjust the sign of the result */
4133 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4134 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4136 emitcode ("clr", "a");
4137 emitcode ("subb", "a,b");
4138 emitcode ("mov", "b,a");
4139 emitcode ("", "%05d$:", (lbl->key + 100));
4141 /* now we are done */
4142 aopPut (AOP (result), "b", 0);
4145 emitcode ("mov", "c,b.7");
4146 emitcode ("subb", "a,acc");
4149 aopPut (AOP (result), "a", offset++);
4153 /*-----------------------------------------------------------------*/
4154 /* genDiv - generates code for division */
4155 /*-----------------------------------------------------------------*/
4159 operand *left = IC_LEFT (ic);
4160 operand *right = IC_RIGHT (ic);
4161 operand *result = IC_RESULT (ic);
4163 D (emitcode (";", "genDiv ");
4166 /* assign the amsops */
4169 /* special cases first */
4171 if (AOP_TYPE (left) == AOP_CRY &&
4172 AOP_TYPE (right) == AOP_CRY)
4174 genDivbits (left, right, result);
4178 /* if both are of size == 1 */
4179 if (AOP_SIZE (left) == 1 &&
4180 AOP_SIZE (right) == 1)
4182 genDivOneByte (left, right, result);
4186 /* should have been converted to function call */
4189 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4190 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191 freeAsmop (result, NULL, ic, TRUE);
4194 /*-----------------------------------------------------------------*/
4195 /* genModbits :- modulus of bits */
4196 /*-----------------------------------------------------------------*/
4198 genModbits (operand * left,
4205 /* the result must be bit */
4206 LOAD_AB_FOR_DIV (left, right, l);
4207 emitcode ("div", "ab");
4208 emitcode ("mov", "a,b");
4209 emitcode ("rrc", "a");
4210 aopPut (AOP (result), "c", 0);
4213 /*-----------------------------------------------------------------*/
4214 /* genModOneByte : 8 bit modulus */
4215 /*-----------------------------------------------------------------*/
4217 genModOneByte (operand * left,
4221 sym_link *opetype = operandType (result);
4225 /* signed or unsigned */
4226 if (SPEC_USIGN (opetype))
4228 /* unsigned is easy */
4229 LOAD_AB_FOR_DIV (left, right, l);
4230 emitcode ("div", "ab");
4231 aopPut (AOP (result), "b", 0);
4235 /* signed is a little bit more difficult */
4237 /* save the signs of the operands */
4238 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4241 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4242 emitcode ("push", "acc"); /* save it on the stack */
4244 /* now sign adjust for both left & right */
4245 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4248 lbl = newiTempLabel (NULL);
4249 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4250 emitcode ("cpl", "a");
4251 emitcode ("inc", "a");
4252 emitcode ("", "%05d$:", (lbl->key + 100));
4253 emitcode ("mov", "b,a");
4255 /* sign adjust left side */
4256 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4259 lbl = newiTempLabel (NULL);
4260 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4261 emitcode ("cpl", "a");
4262 emitcode ("inc", "a");
4263 emitcode ("", "%05d$:", (lbl->key + 100));
4265 /* now the multiplication */
4266 emitcode ("nop", "; workaround for DS80C390 div bug.");
4267 emitcode ("div", "ab");
4268 /* we are interested in the lower order
4270 lbl = newiTempLabel (NULL);
4271 emitcode ("pop", "acc");
4272 /* if there was an over flow we don't
4273 adjust the sign of the result */
4274 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4275 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4277 emitcode ("clr", "a");
4278 emitcode ("subb", "a,b");
4279 emitcode ("mov", "b,a");
4280 emitcode ("", "%05d$:", (lbl->key + 100));
4282 /* now we are done */
4283 aopPut (AOP (result), "b", 0);
4287 /*-----------------------------------------------------------------*/
4288 /* genMod - generates code for division */
4289 /*-----------------------------------------------------------------*/
4293 operand *left = IC_LEFT (ic);
4294 operand *right = IC_RIGHT (ic);
4295 operand *result = IC_RESULT (ic);
4297 D (emitcode (";", "genMod ");
4300 /* assign the amsops */
4303 /* special cases first */
4305 if (AOP_TYPE (left) == AOP_CRY &&
4306 AOP_TYPE (right) == AOP_CRY)
4308 genModbits (left, right, result);
4312 /* if both are of size == 1 */
4313 if (AOP_SIZE (left) == 1 &&
4314 AOP_SIZE (right) == 1)
4316 genModOneByte (left, right, result);
4320 /* should have been converted to function call */
4324 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4325 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4326 freeAsmop (result, NULL, ic, TRUE);
4329 /*-----------------------------------------------------------------*/
4330 /* genIfxJump :- will create a jump depending on the ifx */
4331 /*-----------------------------------------------------------------*/
4333 genIfxJump (iCode * ic, char *jval)
4336 symbol *tlbl = newiTempLabel (NULL);
4339 D (emitcode (";", "genIfxJump ");
4342 /* if true label then we jump if condition
4346 jlbl = IC_TRUE (ic);
4347 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4348 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4352 /* false label is present */
4353 jlbl = IC_FALSE (ic);
4354 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4355 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4357 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4358 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4360 emitcode (inst, "%05d$", tlbl->key + 100);
4361 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4362 emitcode ("", "%05d$:", tlbl->key + 100);
4364 /* mark the icode as generated */
4368 /*-----------------------------------------------------------------*/
4369 /* genCmp :- greater or less than comparison */
4370 /*-----------------------------------------------------------------*/
4372 genCmp (operand * left, operand * right,
4373 iCode * ic, iCode * ifx, int sign)
4375 int size, offset = 0;
4376 unsigned long lit = 0L;
4379 D (emitcode (";", "genCmp");
4382 result = IC_RESULT (ic);
4384 /* if left & right are bit variables */
4385 if (AOP_TYPE (left) == AOP_CRY &&
4386 AOP_TYPE (right) == AOP_CRY)
4388 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4389 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4393 /* subtract right from left if at the
4394 end the carry flag is set then we know that
4395 left is greater than right */
4396 size = max (AOP_SIZE (left), AOP_SIZE (right));
4398 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4399 if ((size == 1) && !sign &&
4400 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4402 symbol *lbl = newiTempLabel (NULL);
4403 emitcode ("cjne", "%s,%s,%05d$",
4404 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4405 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4407 emitcode ("", "%05d$:", lbl->key + 100);
4411 if (AOP_TYPE (right) == AOP_LIT)
4413 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4414 /* optimize if(x < 0) or if(x >= 0) */
4423 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4425 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4426 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428 aopOp (result, ic, FALSE, FALSE);
4430 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4432 freeAsmop (result, NULL, ic, TRUE);
4433 genIfxJump (ifx, "acc.7");
4438 emitcode ("rlc", "a");
4440 goto release_freedLR;
4448 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4449 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4450 emitcode (";", "genCmp #2");
4451 if (sign && (size == 0))
4453 emitcode (";", "genCmp #3");
4454 emitcode ("xrl", "a,#0x80");
4455 if (AOP_TYPE (right) == AOP_LIT)
4457 unsigned long lit = (unsigned long)
4458 floatFromVal (AOP (right)->aopu.aop_lit);
4459 emitcode (";", "genCmp #3.1");
4460 emitcode ("subb", "a,#0x%02x",
4461 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4465 emitcode (";", "genCmp #3.2");
4466 if (AOP_NEEDSACC (right))
4468 emitcode ("push", "acc");
4470 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4471 FALSE, FALSE, FALSE));
4472 emitcode ("xrl", "b,#0x80");
4473 if (AOP_NEEDSACC (right))
4475 emitcode ("pop", "acc");
4477 emitcode ("subb", "a,b");
4484 emitcode (";", "genCmp #4");
4485 if (AOP_NEEDSACC (right))
4488 emitcode (";", "genCmp #4.1");
4489 emitcode ("xch", "a, b");
4490 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4491 emitcode ("xch", "a, b");
4496 emitcode (";", "genCmp #4.2");
4497 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4500 emitcode ("subb", "a,%s", s);
4507 /* Don't need the left & right operands any more; do need the result. */
4508 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4509 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4511 aopOp (result, ic, FALSE, FALSE);
4515 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4521 /* if the result is used in the next
4522 ifx conditional branch then generate
4523 code a little differently */
4526 genIfxJump (ifx, "c");
4532 /* leave the result in acc */
4534 freeAsmop (result, NULL, ic, TRUE);
4537 /*-----------------------------------------------------------------*/
4538 /* genCmpGt :- greater than comparison */
4539 /*-----------------------------------------------------------------*/
4541 genCmpGt (iCode * ic, iCode * ifx)
4543 operand *left, *right;
4544 sym_link *letype, *retype;
4547 D (emitcode (";", "genCmpGt ");
4550 left = IC_LEFT (ic);
4551 right = IC_RIGHT (ic);
4553 letype = getSpec (operandType (left));
4554 retype = getSpec (operandType (right));
4555 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4557 /* assign the left & right amsops */
4560 genCmp (right, left, ic, ifx, sign);
4563 /*-----------------------------------------------------------------*/
4564 /* genCmpLt - less than comparisons */
4565 /*-----------------------------------------------------------------*/
4567 genCmpLt (iCode * ic, iCode * ifx)
4569 operand *left, *right;
4570 sym_link *letype, *retype;
4573 D (emitcode (";", "genCmpLt "););
4575 left = IC_LEFT (ic);
4576 right = IC_RIGHT (ic);
4578 letype = getSpec (operandType (left));
4579 retype = getSpec (operandType (right));
4580 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4582 /* assign the left & right amsops */
4585 genCmp (left, right, ic, ifx, sign);
4588 /*-----------------------------------------------------------------*/
4589 /* gencjneshort - compare and jump if not equal */
4590 /*-----------------------------------------------------------------*/
4592 gencjneshort (operand * left, operand * right, symbol * lbl)
4594 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4596 unsigned long lit = 0L;
4598 D (emitcode (";", "gencjneshort");
4601 /* if the left side is a literal or
4602 if the right is in a pointer register and left
4604 if ((AOP_TYPE (left) == AOP_LIT) ||
4605 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4612 if (AOP_TYPE (right) == AOP_LIT)
4613 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4615 if (opIsGptr (left) || opIsGptr (right))
4617 /* We are comparing a generic pointer to something.
4618 * Exclude the generic type byte from the comparison.
4621 D (emitcode (";", "cjneshort: generic ptr special case.");
4626 /* if the right side is a literal then anything goes */
4627 if (AOP_TYPE (right) == AOP_LIT &&
4628 AOP_TYPE (left) != AOP_DIR)
4632 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4634 emitcode ("cjne", "a,%s,%05d$",
4635 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4641 /* if the right side is in a register or in direct space or
4642 if the left is a pointer register & right is not */
4643 else if (AOP_TYPE (right) == AOP_REG ||
4644 AOP_TYPE (right) == AOP_DIR ||
4645 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4646 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4650 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4651 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4652 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4653 emitcode ("jnz", "%05d$", lbl->key + 100);
4655 emitcode ("cjne", "a,%s,%05d$",
4656 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4663 /* right is a pointer reg need both a & b */
4666 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4667 if (strcmp (l, "b"))
4668 emitcode ("mov", "b,%s", l);
4669 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4670 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4676 /*-----------------------------------------------------------------*/
4677 /* gencjne - compare and jump if not equal */
4678 /*-----------------------------------------------------------------*/
4680 gencjne (operand * left, operand * right, symbol * lbl)
4682 symbol *tlbl = newiTempLabel (NULL);
4684 D (emitcode (";", "gencjne");
4687 gencjneshort (left, right, lbl);
4689 emitcode ("mov", "a,%s", one);
4690 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4691 emitcode ("", "%05d$:", lbl->key + 100);
4692 emitcode ("clr", "a");
4693 emitcode ("", "%05d$:", tlbl->key + 100);
4696 /*-----------------------------------------------------------------*/
4697 /* genCmpEq - generates code for equal to */
4698 /*-----------------------------------------------------------------*/
4700 genCmpEq (iCode * ic, iCode * ifx)
4702 operand *left, *right, *result;
4704 D (emitcode (";", "genCmpEq ");
4708 AOP_SET_LOCALS (ic);
4710 /* if literal, literal on the right or
4711 if the right is in a pointer register and left
4713 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4714 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4716 operand *t = IC_RIGHT (ic);
4717 IC_RIGHT (ic) = IC_LEFT (ic);
4721 if (ifx && /* !AOP_SIZE(result) */
4722 OP_SYMBOL (result) &&
4723 OP_SYMBOL (result)->regType == REG_CND)
4726 /* if they are both bit variables */
4727 if (AOP_TYPE (left) == AOP_CRY &&
4728 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4730 if (AOP_TYPE (right) == AOP_LIT)
4732 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4735 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4736 emitcode ("cpl", "c");
4740 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4744 emitcode ("clr", "c");
4746 /* AOP_TYPE(right) == AOP_CRY */
4750 symbol *lbl = newiTempLabel (NULL);
4751 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4752 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4753 emitcode ("cpl", "c");
4754 emitcode ("", "%05d$:", (lbl->key + 100));
4756 /* if true label then we jump if condition
4758 tlbl = newiTempLabel (NULL);
4761 emitcode ("jnc", "%05d$", tlbl->key + 100);
4762 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4766 emitcode ("jc", "%05d$", tlbl->key + 100);
4767 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4769 emitcode ("", "%05d$:", tlbl->key + 100);
4773 tlbl = newiTempLabel (NULL);
4774 gencjneshort (left, right, tlbl);
4777 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4778 emitcode ("", "%05d$:", tlbl->key + 100);
4782 symbol *lbl = newiTempLabel (NULL);
4783 emitcode ("sjmp", "%05d$", lbl->key + 100);
4784 emitcode ("", "%05d$:", tlbl->key + 100);
4785 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4786 emitcode ("", "%05d$:", lbl->key + 100);
4789 /* mark the icode as generated */
4792 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4793 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4797 /* if they are both bit variables */
4798 if (AOP_TYPE (left) == AOP_CRY &&
4799 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4801 if (AOP_TYPE (right) == AOP_LIT)
4803 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4806 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4807 emitcode ("cpl", "c");
4811 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4815 emitcode ("clr", "c");
4817 /* AOP_TYPE(right) == AOP_CRY */
4821 symbol *lbl = newiTempLabel (NULL);
4822 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4823 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4824 emitcode ("cpl", "c");
4825 emitcode ("", "%05d$:", (lbl->key + 100));
4828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4831 aopOp (result, ic, TRUE, FALSE);
4834 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4841 genIfxJump (ifx, "c");
4844 /* if the result is used in an arithmetic operation
4845 then put the result in place */
4850 gencjne (left, right, newiTempLabel (NULL));
4852 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4855 aopOp (result, ic, TRUE, FALSE);
4857 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4859 aopPut (AOP (result), "a", 0);
4864 genIfxJump (ifx, "a");
4867 /* if the result is used in an arithmetic operation
4868 then put the result in place */
4869 if (AOP_TYPE (result) != AOP_CRY)
4871 /* leave the result in acc */
4875 freeAsmop (result, NULL, ic, TRUE);
4878 /*-----------------------------------------------------------------*/
4879 /* ifxForOp - returns the icode containing the ifx for operand */
4880 /*-----------------------------------------------------------------*/
4882 ifxForOp (operand * op, iCode * ic)
4884 /* if true symbol then needs to be assigned */
4885 if (IS_TRUE_SYMOP (op))
4888 /* if this has register type condition and
4889 the next instruction is ifx with the same operand
4890 and live to of the operand is upto the ifx only then */
4892 ic->next->op == IFX &&
4893 IC_COND (ic->next)->key == op->key &&
4894 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4899 /*-----------------------------------------------------------------*/
4900 /* genAndOp - for && operation */
4901 /*-----------------------------------------------------------------*/
4903 genAndOp (iCode * ic)
4905 operand *left, *right, *result;
4908 D (emitcode (";", "genAndOp "););
4910 /* note here that && operations that are in an
4911 if statement are taken away by backPatchLabels
4912 only those used in arthmetic operations remain */
4914 AOP_SET_LOCALS (ic);
4916 /* if both are bit variables */
4917 if (AOP_TYPE (left) == AOP_CRY &&
4918 AOP_TYPE (right) == AOP_CRY)
4920 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4921 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4922 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4923 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 aopOp (result,ic,FALSE, FALSE);
4930 tlbl = newiTempLabel (NULL);
4932 emitcode ("jz", "%05d$", tlbl->key + 100);
4934 emitcode ("", "%05d$:", tlbl->key + 100);
4935 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 aopOp (result,ic,FALSE, FALSE);
4941 freeAsmop (result, NULL, ic, TRUE);
4945 /*-----------------------------------------------------------------*/
4946 /* genOrOp - for || operation */
4947 /*-----------------------------------------------------------------*/
4949 genOrOp (iCode * ic)
4951 operand *left, *right, *result;
4954 D (emitcode (";", "genOrOp "););
4956 /* note here that || operations that are in an
4957 if statement are taken away by backPatchLabels
4958 only those used in arthmetic operations remain */
4960 AOP_SET_LOCALS (ic);
4962 /* if both are bit variables */
4963 if (AOP_TYPE (left) == AOP_CRY &&
4964 AOP_TYPE (right) == AOP_CRY)
4966 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4967 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4968 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4969 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4971 aopOp (result,ic,FALSE, FALSE);
4977 tlbl = newiTempLabel (NULL);
4979 emitcode ("jnz", "%05d$", tlbl->key + 100);
4981 emitcode ("", "%05d$:", tlbl->key + 100);
4982 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4983 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4985 aopOp (result,ic,FALSE, FALSE);
4990 freeAsmop (result, NULL, ic, TRUE);
4993 /*-----------------------------------------------------------------*/
4994 /* isLiteralBit - test if lit == 2^n */
4995 /*-----------------------------------------------------------------*/
4997 isLiteralBit (unsigned long lit)
4999 unsigned long pw[32] =
5000 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5001 0x100L, 0x200L, 0x400L, 0x800L,
5002 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5003 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5004 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5005 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5006 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5009 for (idx = 0; idx < 32; idx++)
5015 /*-----------------------------------------------------------------*/
5016 /* continueIfTrue - */
5017 /*-----------------------------------------------------------------*/
5019 continueIfTrue (iCode * ic)
5022 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5026 /*-----------------------------------------------------------------*/
5028 /*-----------------------------------------------------------------*/
5030 jumpIfTrue (iCode * ic)
5033 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5037 /*-----------------------------------------------------------------*/
5038 /* jmpTrueOrFalse - */
5039 /*-----------------------------------------------------------------*/
5041 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5043 // ugly but optimized by peephole
5046 symbol *nlbl = newiTempLabel (NULL);
5047 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5048 emitcode ("", "%05d$:", tlbl->key + 100);
5049 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5050 emitcode ("", "%05d$:", nlbl->key + 100);
5054 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5055 emitcode ("", "%05d$:", tlbl->key + 100);
5060 // Generate code to perform a bit-wise logic operation
5061 // on two operands in far space (assumed to already have been
5062 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5063 // in far space. This requires pushing the result on the stack
5064 // then popping it into the result.
5066 genFarFarLogicOp(iCode *ic, char *logicOp)
5068 int size, resultSize, compSize;
5071 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5072 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5073 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5075 _startLazyDPSEvaluation();
5076 for (size = compSize; (size--); offset++)
5078 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5079 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5080 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5082 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5083 emitcode ("push", "acc");
5085 _endLazyDPSEvaluation();
5087 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5088 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5089 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5091 resultSize = AOP_SIZE(IC_RESULT(ic));
5093 ADJUST_PUSHED_RESULT(compSize, resultSize);
5095 _startLazyDPSEvaluation();
5098 emitcode ("pop", "acc");
5099 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5101 _endLazyDPSEvaluation();
5102 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5106 /*-----------------------------------------------------------------*/
5107 /* genAnd - code for and */
5108 /*-----------------------------------------------------------------*/
5110 genAnd (iCode * ic, iCode * ifx)
5112 operand *left, *right, *result;
5113 int size, offset = 0;
5114 unsigned long lit = 0L;
5119 D (emitcode (";", "genAnd "););
5121 AOP_OP_3_NOFATAL (ic, pushResult);
5122 AOP_SET_LOCALS (ic);
5126 genFarFarLogicOp(ic, "anl");
5131 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5133 AOP_TYPE (left), AOP_TYPE (right));
5134 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5136 AOP_SIZE (left), AOP_SIZE (right));
5139 /* if left is a literal & right is not then exchange them */
5140 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5141 AOP_NEEDSACC (left))
5143 operand *tmp = right;
5148 /* if result = right then exchange them */
5149 if (sameRegs (AOP (result), AOP (right)))
5151 operand *tmp = right;
5156 /* if right is bit then exchange them */
5157 if (AOP_TYPE (right) == AOP_CRY &&
5158 AOP_TYPE (left) != AOP_CRY)
5160 operand *tmp = right;
5164 if (AOP_TYPE (right) == AOP_LIT)
5165 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5167 size = AOP_SIZE (result);
5170 // result = bit & yy;
5171 if (AOP_TYPE (left) == AOP_CRY)
5173 // c = bit & literal;
5174 if (AOP_TYPE (right) == AOP_LIT)
5178 if (size && sameRegs (AOP (result), AOP (left)))
5181 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5186 if (size && (AOP_TYPE (result) == AOP_CRY))
5188 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5191 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5196 emitcode ("clr", "c");
5201 if (AOP_TYPE (right) == AOP_CRY)
5204 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5205 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5210 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5212 emitcode ("rrc", "a");
5213 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5221 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5222 genIfxJump (ifx, "c");
5226 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5227 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5228 if ((AOP_TYPE (right) == AOP_LIT) &&
5229 (AOP_TYPE (result) == AOP_CRY) &&
5230 (AOP_TYPE (left) != AOP_CRY))
5232 int posbit = isLiteralBit (lit);
5237 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5240 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5246 sprintf (buffer, "acc.%d", posbit & 0x07);
5247 genIfxJump (ifx, buffer);
5254 symbol *tlbl = newiTempLabel (NULL);
5255 int sizel = AOP_SIZE (left);
5257 emitcode ("setb", "c");
5260 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5262 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5264 if ((posbit = isLiteralBit (bytelit)) != 0)
5265 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5268 if (bytelit != 0x0FFL)
5269 emitcode ("anl", "a,%s",
5270 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5271 emitcode ("jnz", "%05d$", tlbl->key + 100);
5276 // bit = left & literal
5279 emitcode ("clr", "c");
5280 emitcode ("", "%05d$:", tlbl->key + 100);
5282 // if(left & literal)
5286 jmpTrueOrFalse (ifx, tlbl);
5294 /* if left is same as result */
5295 if (sameRegs (AOP (result), AOP (left)))
5297 for (; size--; offset++)
5299 if (AOP_TYPE (right) == AOP_LIT)
5301 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5303 else if (bytelit == 0)
5304 aopPut (AOP (result), zero, offset);
5305 else if (IS_AOP_PREG (result))
5307 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5308 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5309 aopPut (AOP (result), "a", offset);
5312 emitcode ("anl", "%s,%s",
5313 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5314 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5318 if (AOP_TYPE (left) == AOP_ACC)
5319 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5322 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5323 if (IS_AOP_PREG (result))
5325 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5326 aopPut (AOP (result), "a", offset);
5330 emitcode ("anl", "%s,a",
5331 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5338 // left & result in different registers
5339 if (AOP_TYPE (result) == AOP_CRY)
5342 // if(size), result in bit
5343 // if(!size && ifx), conditional oper: if(left & right)
5344 symbol *tlbl = newiTempLabel (NULL);
5345 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5347 emitcode ("setb", "c");
5350 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5351 emitcode ("anl", "a,%s",
5352 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5354 if (AOP_TYPE(left)==AOP_ACC) {
5355 emitcode("mov", "b,a");
5356 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5357 emitcode("anl", "a,b");
5359 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5360 emitcode ("anl", "a,%s",
5361 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5364 emitcode ("jnz", "%05d$", tlbl->key + 100);
5370 emitcode ("", "%05d$:", tlbl->key + 100);
5374 jmpTrueOrFalse (ifx, tlbl);
5378 for (; (size--); offset++)
5381 // result = left & right
5382 if (AOP_TYPE (right) == AOP_LIT)
5384 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5386 aopPut (AOP (result),
5387 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5391 else if (bytelit == 0)
5393 aopPut (AOP (result), zero, offset);
5396 D (emitcode (";", "better literal AND.");
5398 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5399 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5400 FALSE, FALSE, FALSE));
5405 // faster than result <- left, anl result,right
5406 // and better if result is SFR
5407 if (AOP_TYPE (left) == AOP_ACC)
5409 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5410 FALSE, FALSE, FALSE));
5414 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5415 emitcode ("anl", "a,%s",
5416 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5419 aopPut (AOP (result), "a", offset);
5425 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5426 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5427 freeAsmop (result, NULL, ic, TRUE);
5431 /*-----------------------------------------------------------------*/
5432 /* genOr - code for or */
5433 /*-----------------------------------------------------------------*/
5435 genOr (iCode * ic, iCode * ifx)
5437 operand *left, *right, *result;
5438 int size, offset = 0;
5439 unsigned long lit = 0L;
5442 D (emitcode (";", "genOr "););
5444 AOP_OP_3_NOFATAL (ic, pushResult);
5445 AOP_SET_LOCALS (ic);
5449 genFarFarLogicOp(ic, "orl");
5455 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5457 AOP_TYPE (left), AOP_TYPE (right));
5458 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5460 AOP_SIZE (left), AOP_SIZE (right));
5463 /* if left is a literal & right is not then exchange them */
5464 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5465 AOP_NEEDSACC (left))
5467 operand *tmp = right;
5472 /* if result = right then exchange them */
5473 if (sameRegs (AOP (result), AOP (right)))
5475 operand *tmp = right;
5480 /* if right is bit then exchange them */
5481 if (AOP_TYPE (right) == AOP_CRY &&
5482 AOP_TYPE (left) != AOP_CRY)
5484 operand *tmp = right;
5488 if (AOP_TYPE (right) == AOP_LIT)
5489 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5491 size = AOP_SIZE (result);
5495 if (AOP_TYPE (left) == AOP_CRY)
5497 if (AOP_TYPE (right) == AOP_LIT)
5499 // c = bit & literal;
5502 // lit != 0 => result = 1
5503 if (AOP_TYPE (result) == AOP_CRY)
5506 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5508 continueIfTrue (ifx);
5511 emitcode ("setb", "c");
5515 // lit == 0 => result = left
5516 if (size && sameRegs (AOP (result), AOP (left)))
5518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5523 if (AOP_TYPE (right) == AOP_CRY)
5526 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5527 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5532 symbol *tlbl = newiTempLabel (NULL);
5533 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5534 emitcode ("setb", "c");
5535 emitcode ("jb", "%s,%05d$",
5536 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5538 emitcode ("jnz", "%05d$", tlbl->key + 100);
5539 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5541 jmpTrueOrFalse (ifx, tlbl);
5547 emitcode ("", "%05d$:", tlbl->key + 100);
5556 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5557 genIfxJump (ifx, "c");
5561 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5562 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5563 if ((AOP_TYPE (right) == AOP_LIT) &&
5564 (AOP_TYPE (result) == AOP_CRY) &&
5565 (AOP_TYPE (left) != AOP_CRY))
5571 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5573 continueIfTrue (ifx);
5578 // lit = 0, result = boolean(left)
5580 emitcode ("setb", "c");
5584 symbol *tlbl = newiTempLabel (NULL);
5585 emitcode ("jnz", "%05d$", tlbl->key + 100);
5587 emitcode ("", "%05d$:", tlbl->key + 100);
5591 genIfxJump (ifx, "a");
5599 /* if left is same as result */
5600 if (sameRegs (AOP (result), AOP (left)))
5602 for (; size--; offset++)
5604 if (AOP_TYPE (right) == AOP_LIT)
5606 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5612 if (IS_AOP_PREG (left))
5614 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5615 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5616 aopPut (AOP (result), "a", offset);
5620 emitcode ("orl", "%s,%s",
5621 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5622 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5628 if (AOP_TYPE (left) == AOP_ACC)
5630 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5634 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5635 if (IS_AOP_PREG (left))
5637 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5638 aopPut (AOP (result), "a", offset);
5642 emitcode ("orl", "%s,a",
5643 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5651 // left & result in different registers
5652 if (AOP_TYPE (result) == AOP_CRY)
5655 // if(size), result in bit
5656 // if(!size && ifx), conditional oper: if(left | right)
5657 symbol *tlbl = newiTempLabel (NULL);
5658 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5660 emitcode ("setb", "c");
5663 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5664 emitcode ("orl", "a,%s",
5665 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5667 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5668 emitcode ("orl", "a,%s",
5669 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5671 emitcode ("jnz", "%05d$", tlbl->key + 100);
5677 emitcode ("", "%05d$:", tlbl->key + 100);
5681 jmpTrueOrFalse (ifx, tlbl);
5685 for (; (size--); offset++)
5688 // result = left & right
5689 if (AOP_TYPE (right) == AOP_LIT)
5691 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5693 aopPut (AOP (result),
5694 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5698 D (emitcode (";", "better literal OR.");
5700 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5701 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5702 FALSE, FALSE, FALSE));
5707 // faster than result <- left, anl result,right
5708 // and better if result is SFR
5709 if (AOP_TYPE (left) == AOP_ACC)
5711 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5712 FALSE, FALSE, FALSE));
5716 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5717 emitcode ("orl", "a,%s",
5718 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5721 aopPut (AOP (result), "a", offset);
5727 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5728 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5729 freeAsmop (result, NULL, ic, TRUE);
5732 /*-----------------------------------------------------------------*/
5733 /* genXor - code for xclusive or */
5734 /*-----------------------------------------------------------------*/
5736 genXor (iCode * ic, iCode * ifx)
5738 operand *left, *right, *result;
5739 int size, offset = 0;
5740 unsigned long lit = 0L;
5743 D (emitcode (";", "genXor "););
5745 AOP_OP_3_NOFATAL (ic, pushResult);
5746 AOP_SET_LOCALS (ic);
5750 genFarFarLogicOp(ic, "xrl");
5755 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5757 AOP_TYPE (left), AOP_TYPE (right));
5758 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5760 AOP_SIZE (left), AOP_SIZE (right));
5763 /* if left is a literal & right is not ||
5764 if left needs acc & right does not */
5765 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5766 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5768 operand *tmp = right;
5773 /* if result = right then exchange them */
5774 if (sameRegs (AOP (result), AOP (right)))
5776 operand *tmp = right;
5781 /* if right is bit then exchange them */
5782 if (AOP_TYPE (right) == AOP_CRY &&
5783 AOP_TYPE (left) != AOP_CRY)
5785 operand *tmp = right;
5789 if (AOP_TYPE (right) == AOP_LIT)
5790 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5792 size = AOP_SIZE (result);
5796 if (AOP_TYPE (left) == AOP_CRY)
5798 if (AOP_TYPE (right) == AOP_LIT)
5800 // c = bit & literal;
5803 // lit>>1 != 0 => result = 1
5804 if (AOP_TYPE (result) == AOP_CRY)
5807 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5809 continueIfTrue (ifx);
5812 emitcode ("setb", "c");
5819 // lit == 0, result = left
5820 if (size && sameRegs (AOP (result), AOP (left)))
5822 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5826 // lit == 1, result = not(left)
5827 if (size && sameRegs (AOP (result), AOP (left)))
5829 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5834 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5835 emitcode ("cpl", "c");
5844 symbol *tlbl = newiTempLabel (NULL);
5845 if (AOP_TYPE (right) == AOP_CRY)
5848 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5852 int sizer = AOP_SIZE (right);
5854 // if val>>1 != 0, result = 1
5855 emitcode ("setb", "c");
5858 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5860 // test the msb of the lsb
5861 emitcode ("anl", "a,#0xfe");
5862 emitcode ("jnz", "%05d$", tlbl->key + 100);
5866 emitcode ("rrc", "a");
5868 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5869 emitcode ("cpl", "c");
5870 emitcode ("", "%05d$:", (tlbl->key + 100));
5877 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5878 genIfxJump (ifx, "c");
5882 if (sameRegs (AOP (result), AOP (left)))
5884 /* if left is same as result */
5885 for (; size--; offset++)
5887 if (AOP_TYPE (right) == AOP_LIT)
5889 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5891 else if (IS_AOP_PREG (left))
5893 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5894 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5895 aopPut (AOP (result), "a", offset);
5898 emitcode ("xrl", "%s,%s",
5899 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5900 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5904 if (AOP_TYPE (left) == AOP_ACC)
5905 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5908 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5909 if (IS_AOP_PREG (left))
5911 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5912 aopPut (AOP (result), "a", offset);
5915 emitcode ("xrl", "%s,a",
5916 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5923 // left & result in different registers
5924 if (AOP_TYPE (result) == AOP_CRY)
5927 // if(size), result in bit
5928 // if(!size && ifx), conditional oper: if(left ^ right)
5929 symbol *tlbl = newiTempLabel (NULL);
5930 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5932 emitcode ("setb", "c");
5935 if ((AOP_TYPE (right) == AOP_LIT) &&
5936 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5938 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5942 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5943 emitcode ("xrl", "a,%s",
5944 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5946 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5947 emitcode ("xrl", "a,%s",
5948 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5951 emitcode ("jnz", "%05d$", tlbl->key + 100);
5957 emitcode ("", "%05d$:", tlbl->key + 100);
5961 jmpTrueOrFalse (ifx, tlbl);
5964 for (; (size--); offset++)
5967 // result = left & right
5968 if (AOP_TYPE (right) == AOP_LIT)
5970 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5972 aopPut (AOP (result),
5973 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5977 D (emitcode (";", "better literal XOR.");
5979 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5980 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5981 FALSE, FALSE, FALSE));
5985 // faster than result <- left, anl result,right
5986 // and better if result is SFR
5987 if (AOP_TYPE (left) == AOP_ACC)
5989 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5990 FALSE, FALSE, FALSE));
5994 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5995 emitcode ("xrl", "a,%s",
5996 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5999 aopPut (AOP (result), "a", offset);
6004 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6005 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6006 freeAsmop (result, NULL, ic, TRUE);
6009 /*-----------------------------------------------------------------*/
6010 /* genInline - write the inline code out */
6011 /*-----------------------------------------------------------------*/
6013 genInline (iCode * ic)
6015 char *buffer, *bp, *bp1;
6017 D (emitcode (";", "genInline ");
6020 _G.inLine += (!options.asmpeep);
6022 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6023 strcpy (buffer, IC_INLINE (ic));
6025 /* emit each line as a code */
6050 /* emitcode("",buffer); */
6051 _G.inLine -= (!options.asmpeep);
6054 /*-----------------------------------------------------------------*/
6055 /* genRRC - rotate right with carry */
6056 /*-----------------------------------------------------------------*/
6060 operand *left, *result;
6061 int size, offset = 0;
6064 D (emitcode (";", "genRRC ");
6067 /* rotate right with carry */
6068 left = IC_LEFT (ic);
6069 result = IC_RESULT (ic);
6070 aopOp (left, ic, FALSE, FALSE);
6071 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6073 /* move it to the result */
6074 size = AOP_SIZE (result);
6078 _startLazyDPSEvaluation ();
6081 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6083 emitcode ("rrc", "a");
6084 if (AOP_SIZE (result) > 1)
6085 aopPut (AOP (result), "a", offset--);
6087 _endLazyDPSEvaluation ();
6089 /* now we need to put the carry into the
6090 highest order byte of the result */
6091 if (AOP_SIZE (result) > 1)
6093 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6096 emitcode ("mov", "acc.7,c");
6097 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6098 freeAsmop (left, NULL, ic, TRUE);
6099 freeAsmop (result, NULL, ic, TRUE);
6102 /*-----------------------------------------------------------------*/
6103 /* genRLC - generate code for rotate left with carry */
6104 /*-----------------------------------------------------------------*/
6108 operand *left, *result;
6109 int size, offset = 0;
6112 D (emitcode (";", "genRLC ");
6115 /* rotate right with carry */
6116 left = IC_LEFT (ic);
6117 result = IC_RESULT (ic);
6118 aopOp (left, ic, FALSE, FALSE);
6119 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6121 /* move it to the result */
6122 size = AOP_SIZE (result);
6126 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6128 emitcode ("add", "a,acc");
6129 if (AOP_SIZE (result) > 1)
6131 aopPut (AOP (result), "a", offset++);
6134 _startLazyDPSEvaluation ();
6137 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6139 emitcode ("rlc", "a");
6140 if (AOP_SIZE (result) > 1)
6141 aopPut (AOP (result), "a", offset++);
6143 _endLazyDPSEvaluation ();
6145 /* now we need to put the carry into the
6146 highest order byte of the result */
6147 if (AOP_SIZE (result) > 1)
6149 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6152 emitcode ("mov", "acc.0,c");
6153 aopPut (AOP (result), "a", 0);
6154 freeAsmop (left, NULL, ic, TRUE);
6155 freeAsmop (result, NULL, ic, TRUE);
6158 /*-----------------------------------------------------------------*/
6159 /* genGetHbit - generates code get highest order bit */
6160 /*-----------------------------------------------------------------*/
6162 genGetHbit (iCode * ic)
6164 operand *left, *result;
6165 left = IC_LEFT (ic);
6166 result = IC_RESULT (ic);
6167 aopOp (left, ic, FALSE, FALSE);
6168 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6170 D (emitcode (";", "genGetHbit ");
6173 /* get the highest order byte into a */
6174 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6175 if (AOP_TYPE (result) == AOP_CRY)
6177 emitcode ("rlc", "a");
6182 emitcode ("rl", "a");
6183 emitcode ("anl", "a,#0x01");
6188 freeAsmop (left, NULL, ic, TRUE);
6189 freeAsmop (result, NULL, ic, TRUE);
6192 /*-----------------------------------------------------------------*/
6193 /* AccRol - rotate left accumulator by known count */
6194 /*-----------------------------------------------------------------*/
6196 AccRol (int shCount)
6198 shCount &= 0x0007; // shCount : 0..7
6205 emitcode ("rl", "a");
6208 emitcode ("rl", "a");
6209 emitcode ("rl", "a");
6212 emitcode ("swap", "a");
6213 emitcode ("rr", "a");
6216 emitcode ("swap", "a");
6219 emitcode ("swap", "a");
6220 emitcode ("rl", "a");
6223 emitcode ("rr", "a");
6224 emitcode ("rr", "a");
6227 emitcode ("rr", "a");
6232 /*-----------------------------------------------------------------*/
6233 /* AccLsh - left shift accumulator by known count */
6234 /*-----------------------------------------------------------------*/
6236 AccLsh (int shCount)
6241 emitcode ("add", "a,acc");
6242 else if (shCount == 2)
6244 emitcode ("add", "a,acc");
6245 emitcode ("add", "a,acc");
6249 /* rotate left accumulator */
6251 /* and kill the lower order bits */
6252 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6257 /*-----------------------------------------------------------------*/
6258 /* AccRsh - right shift accumulator by known count */
6259 /*-----------------------------------------------------------------*/
6261 AccRsh (int shCount)
6268 emitcode ("rrc", "a");
6272 /* rotate right accumulator */
6273 AccRol (8 - shCount);
6274 /* and kill the higher order bits */
6275 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6280 #ifdef BETTER_LITERAL_SHIFT
6281 /*-----------------------------------------------------------------*/
6282 /* AccSRsh - signed right shift accumulator by known count */
6283 /*-----------------------------------------------------------------*/
6285 AccSRsh (int shCount)
6292 emitcode ("mov", "c,acc.7");
6293 emitcode ("rrc", "a");
6295 else if (shCount == 2)
6297 emitcode ("mov", "c,acc.7");
6298 emitcode ("rrc", "a");
6299 emitcode ("mov", "c,acc.7");
6300 emitcode ("rrc", "a");
6304 tlbl = newiTempLabel (NULL);
6305 /* rotate right accumulator */
6306 AccRol (8 - shCount);
6307 /* and kill the higher order bits */
6308 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6309 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6310 emitcode ("orl", "a,#0x%02x",
6311 (unsigned char) ~SRMask[shCount]);
6312 emitcode ("", "%05d$:", tlbl->key + 100);
6318 #ifdef BETTER_LITERAL_SHIFT
6319 /*-----------------------------------------------------------------*/
6320 /* shiftR1Left2Result - shift right one byte from left to result */
6321 /*-----------------------------------------------------------------*/
6323 shiftR1Left2Result (operand * left, int offl,
6324 operand * result, int offr,
6325 int shCount, int sign)
6327 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6328 /* shift right accumulator */
6333 aopPut (AOP (result), "a", offr);
6337 #ifdef BETTER_LITERAL_SHIFT
6338 /*-----------------------------------------------------------------*/
6339 /* shiftL1Left2Result - shift left one byte from left to result */
6340 /*-----------------------------------------------------------------*/
6342 shiftL1Left2Result (operand * left, int offl,
6343 operand * result, int offr, int shCount)
6345 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6346 /* shift left accumulator */
6348 aopPut (AOP (result), "a", offr);
6352 #ifdef BETTER_LITERAL_SHIFT
6353 /*-----------------------------------------------------------------*/
6354 /* movLeft2Result - move byte from left to result */
6355 /*-----------------------------------------------------------------*/
6357 movLeft2Result (operand * left, int offl,
6358 operand * result, int offr, int sign)
6361 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6363 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6365 if (*l == '@' && (IS_AOP_PREG (result)))
6367 emitcode ("mov", "a,%s", l);
6368 aopPut (AOP (result), "a", offr);
6374 aopPut (AOP (result), l, offr);
6378 /* MSB sign in acc.7 ! */
6379 if (getDataSize (left) == offl + 1)
6381 emitcode ("mov", "a,%s", l);
6382 aopPut (AOP (result), "a", offr);
6390 #ifdef BETTER_LITERAL_SHIFT
6391 /*-----------------------------------------------------------------*/
6392 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6393 /*-----------------------------------------------------------------*/
6397 emitcode ("rrc", "a");
6398 emitcode ("xch", "a,%s", x);
6399 emitcode ("rrc", "a");
6400 emitcode ("xch", "a,%s", x);
6404 #ifdef BETTER_LITERAL_SHIFT
6406 /*-----------------------------------------------------------------*/
6407 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6408 /*-----------------------------------------------------------------*/
6412 emitcode ("xch", "a,%s", x);
6413 emitcode ("rlc", "a");
6414 emitcode ("xch", "a,%s", x);
6415 emitcode ("rlc", "a");
6419 #ifdef BETTER_LITERAL_SHIFT
6420 /*-----------------------------------------------------------------*/
6421 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6422 /*-----------------------------------------------------------------*/
6426 emitcode ("xch", "a,%s", x);
6427 emitcode ("add", "a,acc");
6428 emitcode ("xch", "a,%s", x);
6429 emitcode ("rlc", "a");
6433 #ifdef BETTER_LITERAL_SHIFT
6434 /*-----------------------------------------------------------------*/
6435 /* AccAXLsh - left shift a:x by known count (0..7) */
6436 /*-----------------------------------------------------------------*/
6438 AccAXLsh (char *x, int shCount)
6453 case 5: // AAAAABBB:CCCCCDDD
6455 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6457 emitcode ("anl", "a,#0x%02x",
6458 SLMask[shCount]); // BBB00000:CCCCCDDD
6460 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6462 AccRol (shCount); // DDDCCCCC:BBB00000
6464 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6466 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6468 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6470 emitcode ("anl", "a,#0x%02x",
6471 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6473 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6475 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6478 case 6: // AAAAAABB:CCCCCCDD
6479 emitcode ("anl", "a,#0x%02x",
6480 SRMask[shCount]); // 000000BB:CCCCCCDD
6481 emitcode ("mov", "c,acc.0"); // c = B
6482 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6484 AccAXRrl1 (x); // BCCCCCCD:D000000B
6485 AccAXRrl1 (x); // BBCCCCCC:DD000000
6487 emitcode("rrc","a");
6488 emitcode("xch","a,%s", x);
6489 emitcode("rrc","a");
6490 emitcode("mov","c,acc.0"); //<< get correct bit
6491 emitcode("xch","a,%s", x);
6493 emitcode("rrc","a");
6494 emitcode("xch","a,%s", x);
6495 emitcode("rrc","a");
6496 emitcode("xch","a,%s", x);
6499 case 7: // a:x <<= 7
6501 emitcode ("anl", "a,#0x%02x",
6502 SRMask[shCount]); // 0000000B:CCCCCCCD
6504 emitcode ("mov", "c,acc.0"); // c = B
6506 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6508 AccAXRrl1 (x); // BCCCCCCC:D0000000
6517 #ifdef BETTER_LITERAL_SHIFT
6519 /*-----------------------------------------------------------------*/
6520 /* AccAXRsh - right shift a:x known count (0..7) */
6521 /*-----------------------------------------------------------------*/
6523 AccAXRsh (char *x, int shCount)
6531 AccAXRrl1 (x); // 0->a:x
6536 AccAXRrl1 (x); // 0->a:x
6539 AccAXRrl1 (x); // 0->a:x
6544 case 5: // AAAAABBB:CCCCCDDD = a:x
6546 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6548 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6550 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6552 emitcode ("anl", "a,#0x%02x",
6553 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6555 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6557 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6559 emitcode ("anl", "a,#0x%02x",
6560 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6562 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6564 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6566 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6569 case 6: // AABBBBBB:CCDDDDDD
6571 emitcode ("mov", "c,acc.7");
6572 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6574 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6576 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6578 emitcode ("anl", "a,#0x%02x",
6579 SRMask[shCount]); // 000000AA:BBBBBBCC
6582 case 7: // ABBBBBBB:CDDDDDDD
6584 emitcode ("mov", "c,acc.7"); // c = A
6586 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6588 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6590 emitcode ("anl", "a,#0x%02x",
6591 SRMask[shCount]); // 0000000A:BBBBBBBC
6600 #ifdef BETTER_LITERAL_SHIFT
6602 /*-----------------------------------------------------------------*/
6603 /* AccAXRshS - right shift signed a:x known count (0..7) */
6604 /*-----------------------------------------------------------------*/
6606 AccAXRshS (char *x, int shCount)
6614 emitcode ("mov", "c,acc.7");
6615 AccAXRrl1 (x); // s->a:x
6619 emitcode ("mov", "c,acc.7");
6620 AccAXRrl1 (x); // s->a:x
6622 emitcode ("mov", "c,acc.7");
6623 AccAXRrl1 (x); // s->a:x
6628 case 5: // AAAAABBB:CCCCCDDD = a:x
6630 tlbl = newiTempLabel (NULL);
6631 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6633 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6635 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6637 emitcode ("anl", "a,#0x%02x",
6638 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6640 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6642 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6644 emitcode ("anl", "a,#0x%02x",
6645 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6647 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6649 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6651 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6653 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6654 emitcode ("orl", "a,#0x%02x",
6655 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6657 emitcode ("", "%05d$:", tlbl->key + 100);
6658 break; // SSSSAAAA:BBBCCCCC
6660 case 6: // AABBBBBB:CCDDDDDD
6662 tlbl = newiTempLabel (NULL);
6663 emitcode ("mov", "c,acc.7");
6664 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6666 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6668 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6670 emitcode ("anl", "a,#0x%02x",
6671 SRMask[shCount]); // 000000AA:BBBBBBCC
6673 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6674 emitcode ("orl", "a,#0x%02x",
6675 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6677 emitcode ("", "%05d$:", tlbl->key + 100);
6679 case 7: // ABBBBBBB:CDDDDDDD
6681 tlbl = newiTempLabel (NULL);
6682 emitcode ("mov", "c,acc.7"); // c = A
6684 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6686 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6688 emitcode ("anl", "a,#0x%02x",
6689 SRMask[shCount]); // 0000000A:BBBBBBBC
6691 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6692 emitcode ("orl", "a,#0x%02x",
6693 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6695 emitcode ("", "%05d$:", tlbl->key + 100);
6703 #ifdef BETTER_LITERAL_SHIFT
6705 _loadLeftIntoAx(char **lsb,
6711 // Get the initial value from left into a pair of registers.
6712 // MSB must be in A, LSB can be any register.
6714 // If the result is held in registers, it is an optimization
6715 // if the LSB can be held in the register which will hold the,
6716 // result LSB since this saves us from having to copy it into
6717 // the result following AccAXLsh.
6719 // If the result is addressed indirectly, this is not a gain.
6720 if (AOP_NEEDSACC(result))
6724 _startLazyDPSEvaluation();
6725 if (AOP_TYPE(left) == AOP_DPTR2)
6728 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6729 // get LSB in DP2_RESULT_REG.
6730 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6731 assert(!strcmp(leftByte, DP2_RESULT_REG));
6735 // get LSB into DP2_RESULT_REG
6736 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6737 if (strcmp(leftByte, DP2_RESULT_REG))
6739 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6742 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6743 assert(strcmp(leftByte, DP2_RESULT_REG));
6746 _endLazyDPSEvaluation();
6747 *lsb = DP2_RESULT_REG;
6751 if (sameRegs (AOP (result), AOP (left)) &&
6752 ((offl + MSB16) == offr))
6754 /* don't crash result[offr] */
6755 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6756 emitcode ("xch", "a,%s",
6757 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6761 movLeft2Result (left, offl, result, offr, 0);
6762 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6764 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6765 assert(strcmp(*lsb,"a"));
6770 _storeAxResults(char *lsb,
6774 _startLazyDPSEvaluation();
6775 if (AOP_NEEDSACC(result))
6777 /* We have to explicitly update the result LSB.
6779 emitcode("xch","a,%s", lsb);
6780 aopPut(AOP(result), "a", offr);
6781 emitcode("mov","a,%s", lsb);
6783 if (getDataSize (result) > 1)
6785 aopPut (AOP (result), "a", offr + MSB16);
6787 _endLazyDPSEvaluation();
6790 /*-----------------------------------------------------------------*/
6791 /* shiftL2Left2Result - shift left two bytes from left to result */
6792 /*-----------------------------------------------------------------*/
6794 shiftL2Left2Result (operand * left, int offl,
6795 operand * result, int offr, int shCount)
6799 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6801 AccAXLsh (lsb, shCount);
6803 _storeAxResults(lsb, result, offr);
6807 #ifdef BETTER_LITERAL_SHIFT
6808 /*-----------------------------------------------------------------*/
6809 /* shiftR2Left2Result - shift right two bytes from left to result */
6810 /*-----------------------------------------------------------------*/
6812 shiftR2Left2Result (operand * left, int offl,
6813 operand * result, int offr,
6814 int shCount, int sign)
6818 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6820 /* a:x >> shCount (x = lsb(result)) */
6823 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6827 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6830 _storeAxResults(lsb, result, offr);
6836 /*-----------------------------------------------------------------*/
6837 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6838 /*-----------------------------------------------------------------*/
6840 shiftLLeftOrResult (operand * left, int offl,
6841 operand * result, int offr, int shCount)
6843 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6844 /* shift left accumulator */
6846 /* or with result */
6847 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6848 /* back to result */
6849 aopPut (AOP (result), "a", offr);
6855 /*-----------------------------------------------------------------*/
6856 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6857 /*-----------------------------------------------------------------*/
6859 shiftRLeftOrResult (operand * left, int offl,
6860 operand * result, int offr, int shCount)
6862 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6863 /* shift right accumulator */
6865 /* or with result */
6866 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6867 /* back to result */
6868 aopPut (AOP (result), "a", offr);
6872 #ifdef BETTER_LITERAL_SHIFT
6873 /*-----------------------------------------------------------------*/
6874 /* genlshOne - left shift a one byte quantity by known count */
6875 /*-----------------------------------------------------------------*/
6877 genlshOne (operand * result, operand * left, int shCount)
6879 D (emitcode (";", "genlshOne "););
6880 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6884 #ifdef BETTER_LITERAL_SHIFT
6885 /*-----------------------------------------------------------------*/
6886 /* genlshTwo - left shift two bytes by known amount != 0 */
6887 /*-----------------------------------------------------------------*/
6889 genlshTwo (operand * result, operand * left, int shCount)
6893 D (emitcode (";", "genlshTwo "););
6895 size = getDataSize (result);
6897 /* if shCount >= 8 */
6902 _startLazyDPSEvaluation();
6908 _endLazyDPSEvaluation();
6909 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6910 aopPut (AOP (result), zero, LSB);
6914 movLeft2Result (left, LSB, result, MSB16, 0);
6915 aopPut (AOP (result), zero, LSB);
6916 _endLazyDPSEvaluation();
6921 aopPut (AOP (result), zero, LSB);
6922 _endLazyDPSEvaluation();
6926 /* 1 <= shCount <= 7 */
6931 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6935 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6943 /*-----------------------------------------------------------------*/
6944 /* shiftLLong - shift left one long from left to result */
6945 /* offl = LSB or MSB16 */
6946 /*-----------------------------------------------------------------*/
6948 shiftLLong (operand * left, operand * result, int offr)
6951 int size = AOP_SIZE (result);
6953 if (size >= LSB + offr)
6955 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6957 emitcode ("add", "a,acc");
6958 if (sameRegs (AOP (left), AOP (result)) &&
6959 size >= MSB16 + offr && offr != LSB)
6960 emitcode ("xch", "a,%s",
6961 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6963 aopPut (AOP (result), "a", LSB + offr);
6966 if (size >= MSB16 + offr)
6968 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6970 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6973 emitcode ("rlc", "a");
6974 if (sameRegs (AOP (left), AOP (result)) &&
6975 size >= MSB24 + offr && offr != LSB)
6976 emitcode ("xch", "a,%s",
6977 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6979 aopPut (AOP (result), "a", MSB16 + offr);
6982 if (size >= MSB24 + offr)
6984 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6986 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6989 emitcode ("rlc", "a");
6990 if (sameRegs (AOP (left), AOP (result)) &&
6991 size >= MSB32 + offr && offr != LSB)
6992 emitcode ("xch", "a,%s",
6993 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6995 aopPut (AOP (result), "a", MSB24 + offr);
6998 if (size > MSB32 + offr)
7000 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7002 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7005 emitcode ("rlc", "a");
7006 aopPut (AOP (result), "a", MSB32 + offr);
7009 aopPut (AOP (result), zero, LSB);
7015 /*-----------------------------------------------------------------*/
7016 /* genlshFour - shift four byte by a known amount != 0 */
7017 /*-----------------------------------------------------------------*/
7019 genlshFour (operand * result, operand * left, int shCount)
7023 D (emitcode (";", "genlshFour ");
7026 size = AOP_SIZE (result);
7028 /* if shifting more that 3 bytes */
7033 /* lowest order of left goes to the highest
7034 order of the destination */
7035 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7037 movLeft2Result (left, LSB, result, MSB32, 0);
7038 aopPut (AOP (result), zero, LSB);
7039 aopPut (AOP (result), zero, MSB16);
7040 aopPut (AOP (result), zero, MSB24);
7044 /* more than two bytes */
7045 else if (shCount >= 16)
7047 /* lower order two bytes goes to higher order two bytes */
7049 /* if some more remaining */
7051 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7054 movLeft2Result (left, MSB16, result, MSB32, 0);
7055 movLeft2Result (left, LSB, result, MSB24, 0);
7057 aopPut (AOP (result), zero, MSB16);
7058 aopPut (AOP (result), zero, LSB);
7062 /* if more than 1 byte */
7063 else if (shCount >= 8)
7065 /* lower order three bytes goes to higher order three bytes */
7070 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7072 movLeft2Result (left, LSB, result, MSB16, 0);
7078 movLeft2Result (left, MSB24, result, MSB32, 0);
7079 movLeft2Result (left, MSB16, result, MSB24, 0);
7080 movLeft2Result (left, LSB, result, MSB16, 0);
7081 aopPut (AOP (result), zero, LSB);
7083 else if (shCount == 1)
7084 shiftLLong (left, result, MSB16);
7087 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7088 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7089 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7090 aopPut (AOP (result), zero, LSB);
7095 /* 1 <= shCount <= 7 */
7096 else if (shCount <= 2)
7098 shiftLLong (left, result, LSB);
7100 shiftLLong (result, result, LSB);
7102 /* 3 <= shCount <= 7, optimize */
7105 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7106 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7107 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7112 #ifdef BETTER_LITERAL_SHIFT
7113 /*-----------------------------------------------------------------*/
7114 /* genLeftShiftLiteral - left shifting by known count */
7115 /*-----------------------------------------------------------------*/
7117 genLeftShiftLiteral (operand * left,
7122 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7125 size = getSize (operandType (result));
7127 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7129 /* We only handle certain easy cases so far. */
7131 && (shCount < (size * 8))
7135 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7139 freeAsmop (right, NULL, ic, TRUE);
7141 aopOp(left, ic, FALSE, FALSE);
7142 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7145 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7147 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7148 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7150 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7153 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7155 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7156 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7158 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7164 emitcode ("; shift left ", "result %d, left %d", size,
7168 /* I suppose that the left size >= result size */
7171 _startLazyDPSEvaluation();
7174 movLeft2Result (left, size, result, size, 0);
7176 _endLazyDPSEvaluation();
7178 else if (shCount >= (size * 8))
7180 _startLazyDPSEvaluation();
7183 aopPut (AOP (result), zero, size);
7185 _endLazyDPSEvaluation();
7192 genlshOne (result, left, shCount);
7196 genlshTwo (result, left, shCount);
7200 genlshFour (result, left, shCount);
7204 fprintf(stderr, "*** ack! mystery literal shift!\n");
7208 freeAsmop (left, NULL, ic, TRUE);
7209 freeAsmop (result, NULL, ic, TRUE);
7214 /*-----------------------------------------------------------------*/
7215 /* genLeftShift - generates code for left shifting */
7216 /*-----------------------------------------------------------------*/
7218 genLeftShift (iCode * ic)
7220 operand *left, *right, *result;
7223 symbol *tlbl, *tlbl1;
7225 D (emitcode (";", "genLeftShift "););
7227 right = IC_RIGHT (ic);
7228 left = IC_LEFT (ic);
7229 result = IC_RESULT (ic);
7231 aopOp (right, ic, FALSE, FALSE);
7234 #ifdef BETTER_LITERAL_SHIFT
7235 /* if the shift count is known then do it
7236 as efficiently as possible */
7237 if (AOP_TYPE (right) == AOP_LIT)
7239 if (genLeftShiftLiteral (left, right, result, ic))
7246 /* shift count is unknown then we have to form
7247 a loop get the loop count in B : Note: we take
7248 only the lower order byte since shifting
7249 more that 32 bits make no sense anyway, ( the
7250 largest size of an object can be only 32 bits ) */
7252 if (AOP_TYPE (right) == AOP_LIT)
7254 /* Really should be handled by genLeftShiftLiteral,
7255 * but since I'm too lazy to fix that today, at least we can make
7256 * some small improvement.
7258 emitcode("mov", "b,#0x%02x",
7259 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7263 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7264 emitcode ("inc", "b");
7266 freeAsmop (right, NULL, ic, TRUE);
7267 aopOp (left, ic, FALSE, FALSE);
7268 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7270 /* now move the left to the result if they are not the
7272 if (!sameRegs (AOP (left), AOP (result)) &&
7273 AOP_SIZE (result) > 1)
7276 size = AOP_SIZE (result);
7278 _startLazyDPSEvaluation ();
7281 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7282 if (*l == '@' && (IS_AOP_PREG (result)))
7285 emitcode ("mov", "a,%s", l);
7286 aopPut (AOP (result), "a", offset);
7289 aopPut (AOP (result), l, offset);
7292 _endLazyDPSEvaluation ();
7295 tlbl = newiTempLabel (NULL);
7296 size = AOP_SIZE (result);
7298 tlbl1 = newiTempLabel (NULL);
7300 /* if it is only one byte then */
7303 symbol *tlbl1 = newiTempLabel (NULL);
7305 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7307 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7308 emitcode ("", "%05d$:", tlbl->key + 100);
7309 emitcode ("add", "a,acc");
7310 emitcode ("", "%05d$:", tlbl1->key + 100);
7311 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7312 aopPut (AOP (result), "a", 0);
7316 reAdjustPreg (AOP (result));
7318 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7319 emitcode ("", "%05d$:", tlbl->key + 100);
7320 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7322 emitcode ("add", "a,acc");
7323 aopPut (AOP (result), "a", offset++);
7324 _startLazyDPSEvaluation ();
7327 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7329 emitcode ("rlc", "a");
7330 aopPut (AOP (result), "a", offset++);
7332 _endLazyDPSEvaluation ();
7333 reAdjustPreg (AOP (result));
7335 emitcode ("", "%05d$:", tlbl1->key + 100);
7336 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7338 freeAsmop (left, NULL, ic, TRUE);
7339 freeAsmop (result, NULL, ic, TRUE);
7342 #ifdef BETTER_LITERAL_SHIFT
7343 /*-----------------------------------------------------------------*/
7344 /* genrshOne - right shift a one byte quantity by known count */
7345 /*-----------------------------------------------------------------*/
7347 genrshOne (operand * result, operand * left,
7348 int shCount, int sign)
7350 D (emitcode (";", "genrshOne"););
7351 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7355 #ifdef BETTER_LITERAL_SHIFT
7356 /*-----------------------------------------------------------------*/
7357 /* genrshTwo - right shift two bytes by known amount != 0 */
7358 /*-----------------------------------------------------------------*/
7360 genrshTwo (operand * result, operand * left,
7361 int shCount, int sign)
7363 D (emitcode (";", "genrshTwo"););
7365 /* if shCount >= 8 */
7369 _startLazyDPSEvaluation();
7372 shiftR1Left2Result (left, MSB16, result, LSB,
7377 movLeft2Result (left, MSB16, result, LSB, sign);
7379 addSign (result, MSB16, sign);
7380 _endLazyDPSEvaluation();
7383 /* 1 <= shCount <= 7 */
7386 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7393 /*-----------------------------------------------------------------*/
7394 /* shiftRLong - shift right one long from left to result */
7395 /* offl = LSB or MSB16 */
7396 /*-----------------------------------------------------------------*/
7398 shiftRLong (operand * left, int offl,
7399 operand * result, int sign)
7401 int isSameRegs=sameRegs(AOP(left),AOP(result));
7403 if (isSameRegs && offl>1) {
7404 // we are in big trouble, but this shouldn't happen
7405 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7408 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7413 emitcode ("rlc", "a");
7414 emitcode ("subb", "a,acc");
7415 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7417 aopPut (AOP(result), zero, MSB32);
7422 emitcode ("clr", "c");
7424 emitcode ("mov", "c,acc.7");
7427 emitcode ("rrc", "a");
7429 if (isSameRegs && offl==MSB16) {
7430 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7432 aopPut (AOP (result), "a", MSB32);
7433 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7436 emitcode ("rrc", "a");
7437 if (isSameRegs && offl==1) {
7438 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7440 aopPut (AOP (result), "a", MSB24);
7441 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7443 emitcode ("rrc", "a");
7444 aopPut (AOP (result), "a", MSB16 - offl);
7448 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7449 emitcode ("rrc", "a");
7450 aopPut (AOP (result), "a", LSB);
7457 /*-----------------------------------------------------------------*/
7458 /* genrshFour - shift four byte by a known amount != 0 */
7459 /*-----------------------------------------------------------------*/
7461 genrshFour (operand * result, operand * left,
7462 int shCount, int sign)
7464 D (emitcode (";", "genrshFour");
7467 /* if shifting more that 3 bytes */
7472 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7474 movLeft2Result (left, MSB32, result, LSB, sign);
7475 addSign (result, MSB16, sign);
7477 else if (shCount >= 16)
7481 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7484 movLeft2Result (left, MSB24, result, LSB, 0);
7485 movLeft2Result (left, MSB32, result, MSB16, sign);
7487 addSign (result, MSB24, sign);
7489 else if (shCount >= 8)
7493 shiftRLong (left, MSB16, result, sign);
7494 else if (shCount == 0)
7496 movLeft2Result (left, MSB16, result, LSB, 0);
7497 movLeft2Result (left, MSB24, result, MSB16, 0);
7498 movLeft2Result (left, MSB32, result, MSB24, sign);
7499 addSign (result, MSB32, sign);
7503 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7504 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7505 /* the last shift is signed */
7506 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7507 addSign (result, MSB32, sign);
7511 { /* 1 <= shCount <= 7 */
7514 shiftRLong (left, LSB, result, sign);
7516 shiftRLong (result, LSB, result, sign);
7520 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7521 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7522 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7528 #ifdef BETTER_LITERAL_SHIFT
7529 /*-----------------------------------------------------------------*/
7530 /* genRightShiftLiteral - right shifting by known count */
7531 /*-----------------------------------------------------------------*/
7533 genRightShiftLiteral (operand * left,
7539 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7542 size = getSize (operandType (result));
7544 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7546 /* We only handle certain easy cases so far. */
7548 && (shCount < (size * 8))
7552 D(emitcode (";", "genRightShiftLiteral wimping out"););
7556 freeAsmop (right, NULL, ic, TRUE);
7558 aopOp (left, ic, FALSE, FALSE);
7559 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7562 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7566 /* test the LEFT size !!! */
7568 /* I suppose that the left size >= result size */
7571 size = getDataSize (result);
7572 _startLazyDPSEvaluation();
7575 movLeft2Result (left, size, result, size, 0);
7577 _endLazyDPSEvaluation();
7579 else if (shCount >= (size * 8))
7583 /* get sign in acc.7 */
7584 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7586 addSign (result, LSB, sign);
7593 genrshOne (result, left, shCount, sign);
7597 genrshTwo (result, left, shCount, sign);
7601 genrshFour (result, left, shCount, sign);
7608 freeAsmop (left, NULL, ic, TRUE);
7609 freeAsmop (result, NULL, ic, TRUE);
7615 /*-----------------------------------------------------------------*/
7616 /* genSignedRightShift - right shift of signed number */
7617 /*-----------------------------------------------------------------*/
7619 genSignedRightShift (iCode * ic)
7621 operand *right, *left, *result;
7624 symbol *tlbl, *tlbl1;
7626 D (emitcode (";", "genSignedRightShift "););
7628 /* we do it the hard way put the shift count in b
7629 and loop thru preserving the sign */
7631 right = IC_RIGHT (ic);
7632 left = IC_LEFT (ic);
7633 result = IC_RESULT (ic);
7635 aopOp (right, ic, FALSE, FALSE);
7637 #ifdef BETTER_LITERAL_SHIFT
7638 if (AOP_TYPE (right) == AOP_LIT)
7640 if (genRightShiftLiteral (left, right, result, ic, 1))
7646 /* shift count is unknown then we have to form
7647 a loop get the loop count in B : Note: we take
7648 only the lower order byte since shifting
7649 more that 32 bits make no sense anyway, ( the
7650 largest size of an object can be only 32 bits ) */
7652 if (AOP_TYPE (right) == AOP_LIT)
7654 /* Really should be handled by genRightShiftLiteral,
7655 * but since I'm too lazy to fix that today, at least we can make
7656 * some small improvement.
7658 emitcode("mov", "b,#0x%02x",
7659 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7663 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7664 emitcode ("inc", "b");
7666 freeAsmop (right, NULL, ic, TRUE);
7667 aopOp (left, ic, FALSE, FALSE);
7668 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7670 /* now move the left to the result if they are not the
7672 if (!sameRegs (AOP (left), AOP (result)) &&
7673 AOP_SIZE (result) > 1)
7676 size = AOP_SIZE (result);
7678 _startLazyDPSEvaluation ();
7681 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7682 if (*l == '@' && IS_AOP_PREG (result))
7685 emitcode ("mov", "a,%s", l);
7686 aopPut (AOP (result), "a", offset);
7689 aopPut (AOP (result), l, offset);
7692 _endLazyDPSEvaluation ();
7695 /* mov the highest order bit to OVR */
7696 tlbl = newiTempLabel (NULL);
7697 tlbl1 = newiTempLabel (NULL);
7699 size = AOP_SIZE (result);
7701 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7702 emitcode ("rlc", "a");
7703 emitcode ("mov", "ov,c");
7704 /* if it is only one byte then */
7707 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7709 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7710 emitcode ("", "%05d$:", tlbl->key + 100);
7711 emitcode ("mov", "c,ov");
7712 emitcode ("rrc", "a");
7713 emitcode ("", "%05d$:", tlbl1->key + 100);
7714 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7715 aopPut (AOP (result), "a", 0);
7719 reAdjustPreg (AOP (result));
7720 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7721 emitcode ("", "%05d$:", tlbl->key + 100);
7722 emitcode ("mov", "c,ov");
7723 _startLazyDPSEvaluation ();
7726 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7728 emitcode ("rrc", "a");
7729 aopPut (AOP (result), "a", offset--);
7731 _endLazyDPSEvaluation ();
7732 reAdjustPreg (AOP (result));
7733 emitcode ("", "%05d$:", tlbl1->key + 100);
7734 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7737 freeAsmop (left, NULL, ic, TRUE);
7738 freeAsmop (result, NULL, ic, TRUE);
7741 /*-----------------------------------------------------------------*/
7742 /* genRightShift - generate code for right shifting */
7743 /*-----------------------------------------------------------------*/
7745 genRightShift (iCode * ic)
7747 operand *right, *left, *result;
7751 symbol *tlbl, *tlbl1;
7753 D (emitcode (";", "genRightShift "););
7755 /* if signed then we do it the hard way preserve the
7756 sign bit moving it inwards */
7757 retype = getSpec (operandType (IC_RESULT (ic)));
7759 if (!SPEC_USIGN (retype))
7761 genSignedRightShift (ic);
7765 /* signed & unsigned types are treated the same : i.e. the
7766 signed is NOT propagated inwards : quoting from the
7767 ANSI - standard : "for E1 >> E2, is equivalent to division
7768 by 2**E2 if unsigned or if it has a non-negative value,
7769 otherwise the result is implementation defined ", MY definition
7770 is that the sign does not get propagated */
7772 right = IC_RIGHT (ic);
7773 left = IC_LEFT (ic);
7774 result = IC_RESULT (ic);
7776 aopOp (right, ic, FALSE, FALSE);
7778 #ifdef BETTER_LITERAL_SHIFT
7779 /* if the shift count is known then do it
7780 as efficiently as possible */
7781 if (AOP_TYPE (right) == AOP_LIT)
7783 if (genRightShiftLiteral (left, right, result, ic, 0))
7790 /* shift count is unknown then we have to form
7791 a loop get the loop count in B : Note: we take
7792 only the lower order byte since shifting
7793 more that 32 bits make no sense anyway, ( the
7794 largest size of an object can be only 32 bits ) */
7796 if (AOP_TYPE (right) == AOP_LIT)
7798 /* Really should be handled by genRightShiftLiteral,
7799 * but since I'm too lazy to fix that today, at least we can make
7800 * some small improvement.
7802 emitcode("mov", "b,#0x%02x",
7803 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7807 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7808 emitcode ("inc", "b");
7810 freeAsmop (right, NULL, ic, TRUE);
7811 aopOp (left, ic, FALSE, FALSE);
7812 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7814 /* now move the left to the result if they are not the
7816 if (!sameRegs (AOP (left), AOP (result)) &&
7817 AOP_SIZE (result) > 1)
7820 size = AOP_SIZE (result);
7822 _startLazyDPSEvaluation ();
7825 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7826 if (*l == '@' && IS_AOP_PREG (result))
7829 emitcode ("mov", "a,%s", l);
7830 aopPut (AOP (result), "a", offset);
7833 aopPut (AOP (result), l, offset);
7836 _endLazyDPSEvaluation ();
7839 tlbl = newiTempLabel (NULL);
7840 tlbl1 = newiTempLabel (NULL);
7841 size = AOP_SIZE (result);
7844 /* if it is only one byte then */
7847 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7849 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7850 emitcode ("", "%05d$:", tlbl->key + 100);
7852 emitcode ("rrc", "a");
7853 emitcode ("", "%05d$:", tlbl1->key + 100);
7854 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7855 aopPut (AOP (result), "a", 0);
7859 reAdjustPreg (AOP (result));
7860 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7861 emitcode ("", "%05d$:", tlbl->key + 100);
7863 _startLazyDPSEvaluation ();
7866 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7868 emitcode ("rrc", "a");
7869 aopPut (AOP (result), "a", offset--);
7871 _endLazyDPSEvaluation ();
7872 reAdjustPreg (AOP (result));
7874 emitcode ("", "%05d$:", tlbl1->key + 100);
7875 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7878 freeAsmop (left, NULL, ic, TRUE);
7879 freeAsmop (result, NULL, ic, TRUE);
7882 /*-----------------------------------------------------------------*/
7883 /* genUnpackBits - generates code for unpacking bits */
7884 /*-----------------------------------------------------------------*/
7886 genUnpackBits (operand * result, char *rname, int ptype)
7893 D (emitcode (";", "genUnpackBits ");
7896 etype = getSpec (operandType (result));
7898 /* read the first byte */
7904 emitcode ("mov", "a,@%s", rname);
7908 emitcode ("movx", "a,@%s", rname);
7912 emitcode ("movx", "a,@dptr");
7916 emitcode ("clr", "a");
7917 emitcode ("movc", "a", "@a+dptr");
7921 emitcode ("lcall", "__gptrget");
7925 /* if we have bitdisplacement then it fits */
7926 /* into this byte completely or if length is */
7927 /* less than a byte */
7928 if ((shCnt = SPEC_BSTR (etype)) ||
7929 (SPEC_BLEN (etype) <= 8))
7932 /* shift right acc */
7935 emitcode ("anl", "a,#0x%02x",
7936 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7937 aopPut (AOP (result), "a", offset);
7941 /* bit field did not fit in a byte */
7942 rlen = SPEC_BLEN (etype) - 8;
7943 aopPut (AOP (result), "a", offset++);
7952 emitcode ("inc", "%s", rname);
7953 emitcode ("mov", "a,@%s", rname);
7957 emitcode ("inc", "%s", rname);
7958 emitcode ("movx", "a,@%s", rname);
7962 emitcode ("inc", "dptr");
7963 emitcode ("movx", "a,@dptr");
7967 emitcode ("clr", "a");
7968 emitcode ("inc", "dptr");
7969 emitcode ("movc", "a", "@a+dptr");
7973 emitcode ("inc", "dptr");
7974 emitcode ("lcall", "__gptrget");
7979 /* if we are done */
7983 aopPut (AOP (result), "a", offset++);
7989 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7990 aopPut (AOP (result), "a", offset);
7997 /*-----------------------------------------------------------------*/
7998 /* genDataPointerGet - generates code when ptr offset is known */
7999 /*-----------------------------------------------------------------*/
8001 genDataPointerGet (operand * left,
8007 int size, offset = 0;
8008 aopOp (result, ic, TRUE, FALSE);
8010 /* get the string representation of the name */
8011 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8012 size = AOP_SIZE (result);
8013 _startLazyDPSEvaluation ();
8017 sprintf (buffer, "(%s + %d)", l + 1, offset);
8019 sprintf (buffer, "%s", l + 1);
8020 aopPut (AOP (result), buffer, offset++);
8022 _endLazyDPSEvaluation ();
8024 freeAsmop (left, NULL, ic, TRUE);
8025 freeAsmop (result, NULL, ic, TRUE);
8028 /*-----------------------------------------------------------------*/
8029 /* genNearPointerGet - emitcode for near pointer fetch */
8030 /*-----------------------------------------------------------------*/
8032 genNearPointerGet (operand * left,
8039 sym_link *rtype, *retype, *letype;
8040 sym_link *ltype = operandType (left);
8043 rtype = operandType (result);
8044 retype = getSpec (rtype);
8045 letype = getSpec (ltype);
8047 aopOp (left, ic, FALSE, FALSE);
8049 /* if left is rematerialisable and
8050 result is not bit variable type and
8051 the left is pointer to data space i.e
8052 lower 128 bytes of space */
8053 if (AOP_TYPE (left) == AOP_IMMD &&
8054 !IS_BITVAR (retype) &&
8055 !IS_BITVAR (letype) &&
8056 DCL_TYPE (ltype) == POINTER)
8058 genDataPointerGet (left, result, ic);
8062 /* if the value is already in a pointer register
8063 then don't need anything more */
8064 if (!AOP_INPREG (AOP (left)))
8066 /* otherwise get a free pointer register */
8068 preg = getFreePtr (ic, &aop, FALSE);
8069 emitcode ("mov", "%s,%s",
8071 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8075 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8077 freeAsmop (left, NULL, ic, TRUE);
8078 aopOp (result, ic, FALSE, FALSE);
8080 /* if bitfield then unpack the bits */
8081 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8082 genUnpackBits (result, rname, POINTER);
8085 /* we have can just get the values */
8086 int size = AOP_SIZE (result);
8091 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8094 emitcode ("mov", "a,@%s", rname);
8095 aopPut (AOP (result), "a", offset);
8099 sprintf (buffer, "@%s", rname);
8100 aopPut (AOP (result), buffer, offset);
8104 emitcode ("inc", "%s", rname);
8108 /* now some housekeeping stuff */
8111 /* we had to allocate for this iCode */
8112 freeAsmop (NULL, aop, ic, TRUE);
8116 /* we did not allocate which means left
8117 already in a pointer register, then
8118 if size > 0 && this could be used again
8119 we have to point it back to where it
8121 if (AOP_SIZE (result) > 1 &&
8122 !OP_SYMBOL (left)->remat &&
8123 (OP_SYMBOL (left)->liveTo > ic->seq ||
8126 int size = AOP_SIZE (result) - 1;
8128 emitcode ("dec", "%s", rname);
8133 freeAsmop (result, NULL, ic, TRUE);
8137 /*-----------------------------------------------------------------*/
8138 /* genPagedPointerGet - emitcode for paged pointer fetch */
8139 /*-----------------------------------------------------------------*/
8141 genPagedPointerGet (operand * left,
8148 sym_link *rtype, *retype, *letype;
8150 rtype = operandType (result);
8151 retype = getSpec (rtype);
8152 letype = getSpec (operandType (left));
8153 aopOp (left, ic, FALSE, FALSE);
8155 /* if the value is already in a pointer register
8156 then don't need anything more */
8157 if (!AOP_INPREG (AOP (left)))
8159 /* otherwise get a free pointer register */
8161 preg = getFreePtr (ic, &aop, FALSE);
8162 emitcode ("mov", "%s,%s",
8164 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8168 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8170 freeAsmop (left, NULL, ic, TRUE);
8171 aopOp (result, ic, FALSE, FALSE);
8173 /* if bitfield then unpack the bits */
8174 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8175 genUnpackBits (result, rname, PPOINTER);
8178 /* we have can just get the values */
8179 int size = AOP_SIZE (result);
8185 emitcode ("movx", "a,@%s", rname);
8186 aopPut (AOP (result), "a", offset);
8191 emitcode ("inc", "%s", rname);
8195 /* now some housekeeping stuff */
8198 /* we had to allocate for this iCode */
8199 freeAsmop (NULL, aop, ic, TRUE);
8203 /* we did not allocate which means left
8204 already in a pointer register, then
8205 if size > 0 && this could be used again
8206 we have to point it back to where it
8208 if (AOP_SIZE (result) > 1 &&
8209 !OP_SYMBOL (left)->remat &&
8210 (OP_SYMBOL (left)->liveTo > ic->seq ||
8213 int size = AOP_SIZE (result) - 1;
8215 emitcode ("dec", "%s", rname);
8220 freeAsmop (result, NULL, ic, TRUE);
8225 /*-----------------------------------------------------------------*/
8226 /* genFarPointerGet - gget value from far space */
8227 /*-----------------------------------------------------------------*/
8229 genFarPointerGet (operand * left,
8230 operand * result, iCode * ic)
8233 sym_link *retype = getSpec (operandType (result));
8234 sym_link *letype = getSpec (operandType (left));
8235 D (emitcode (";", "genFarPointerGet");
8238 aopOp (left, ic, FALSE, FALSE);
8240 /* if the operand is already in dptr
8241 then we do nothing else we move the value to dptr */
8242 if (AOP_TYPE (left) != AOP_STR)
8244 /* if this is remateriazable */
8245 if (AOP_TYPE (left) == AOP_IMMD)
8247 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8251 /* we need to get it byte by byte */
8252 _startLazyDPSEvaluation ();
8253 if (AOP_TYPE (left) != AOP_DPTR)
8255 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8256 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8257 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8261 /* We need to generate a load to DPTR indirect through DPTR. */
8262 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8264 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8265 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8266 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8267 emitcode ("pop", "dph");
8268 emitcode ("pop", "dpl");
8270 _endLazyDPSEvaluation ();
8273 /* so dptr know contains the address */
8274 freeAsmop (left, NULL, ic, TRUE);
8275 aopOp (result, ic, FALSE, TRUE);
8277 /* if bit then unpack */
8278 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8279 genUnpackBits (result, "dptr", FPOINTER);
8282 size = AOP_SIZE (result);
8285 _startLazyDPSEvaluation ();
8292 emitcode ("movx", "a,@dptr");
8294 emitcode ("inc", "dptr");
8296 aopPut (AOP (result), "a", offset++);
8298 _endLazyDPSEvaluation ();
8301 freeAsmop (result, NULL, ic, TRUE);
8304 /*-----------------------------------------------------------------*/
8305 /* emitcodePointerGet - gget value from code space */
8306 /*-----------------------------------------------------------------*/
8308 emitcodePointerGet (operand * left,
8309 operand * result, iCode * ic)
8312 sym_link *retype = getSpec (operandType (result));
8314 aopOp (left, ic, FALSE, FALSE);
8316 /* if the operand is already in dptr
8317 then we do nothing else we move the value to dptr */
8318 if (AOP_TYPE (left) != AOP_STR)
8320 /* if this is remateriazable */
8321 if (AOP_TYPE (left) == AOP_IMMD)
8323 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8326 { /* we need to get it byte by byte */
8327 _startLazyDPSEvaluation ();
8328 if (AOP_TYPE (left) != AOP_DPTR)
8330 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8331 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8332 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8336 /* We need to generate a load to DPTR indirect through DPTR. */
8337 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8339 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8340 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8341 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8342 emitcode ("pop", "dph");
8343 emitcode ("pop", "dpl");
8345 _endLazyDPSEvaluation ();
8348 /* so dptr know contains the address */
8349 freeAsmop (left, NULL, ic, TRUE);
8350 aopOp (result, ic, FALSE, TRUE);
8352 /* if bit then unpack */
8353 if (IS_BITVAR (retype))
8354 genUnpackBits (result, "dptr", CPOINTER);
8357 size = AOP_SIZE (result);
8360 _startLazyDPSEvaluation ();
8366 emitcode ("clr", "a");
8367 emitcode ("movc", "a,@a+dptr");
8369 emitcode ("inc", "dptr");
8370 aopPut (AOP (result), "a", offset++);
8372 _endLazyDPSEvaluation ();
8375 freeAsmop (result, NULL, ic, TRUE);
8378 /*-----------------------------------------------------------------*/
8379 /* genGenPointerGet - gget value from generic pointer space */
8380 /*-----------------------------------------------------------------*/
8382 genGenPointerGet (operand * left,
8383 operand * result, iCode * ic)
8386 sym_link *retype = getSpec (operandType (result));
8387 sym_link *letype = getSpec (operandType (left));
8389 D (emitcode (";", "genGenPointerGet "); );
8391 aopOp (left, ic, FALSE, TRUE);
8393 /* if the operand is already in dptr
8394 then we do nothing else we move the value to dptr */
8395 if (AOP_TYPE (left) != AOP_STR)
8397 /* if this is remateriazable */
8398 if (AOP_TYPE (left) == AOP_IMMD)
8400 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8401 emitcode ("mov", "b,#%d", pointerCode (retype));
8404 { /* we need to get it byte by byte */
8405 _startLazyDPSEvaluation ();
8406 if (AOP(left)->type==AOP_DPTR2) {
8408 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8411 emitcode ("mov", "dpl,%s", l);
8412 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8415 emitcode ("mov", "dph,%s", l);
8416 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8419 emitcode ("mov", "dpx,%s", l);
8420 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8422 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8423 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8424 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8425 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8427 _endLazyDPSEvaluation ();
8430 /* so dptr know contains the address */
8431 freeAsmop (left, NULL, ic, TRUE);
8432 aopOp (result, ic, FALSE, TRUE);
8434 /* if bit then unpack */
8435 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8436 genUnpackBits (result, "dptr", GPOINTER);
8439 size = AOP_SIZE (result);
8444 emitcode ("lcall", "__gptrget");
8445 aopPut (AOP (result), "a", offset++);
8447 emitcode ("inc", "dptr");
8451 freeAsmop (result, NULL, ic, TRUE);
8454 /*-----------------------------------------------------------------*/
8455 /* genPointerGet - generate code for pointer get */
8456 /*-----------------------------------------------------------------*/
8458 genPointerGet (iCode * ic)
8460 operand *left, *result;
8461 sym_link *type, *etype;
8464 D (emitcode (";", "genPointerGet ");
8467 left = IC_LEFT (ic);
8468 result = IC_RESULT (ic);
8470 /* depending on the type of pointer we need to
8471 move it to the correct pointer register */
8472 type = operandType (left);
8473 etype = getSpec (type);
8474 /* if left is of type of pointer then it is simple */
8475 if (IS_PTR (type) && !IS_FUNC (type->next))
8476 p_type = DCL_TYPE (type);
8479 /* we have to go by the storage class */
8480 p_type = PTR_TYPE (SPEC_OCLS (etype));
8483 /* now that we have the pointer type we assign
8484 the pointer values */
8490 genNearPointerGet (left, result, ic);
8494 genPagedPointerGet (left, result, ic);
8498 genFarPointerGet (left, result, ic);
8502 emitcodePointerGet (left, result, ic);
8506 genGenPointerGet (left, result, ic);
8512 /*-----------------------------------------------------------------*/
8513 /* genPackBits - generates code for packed bit storage */
8514 /*-----------------------------------------------------------------*/
8516 genPackBits (sym_link * etype,
8518 char *rname, int p_type)
8526 blen = SPEC_BLEN (etype);
8527 bstr = SPEC_BSTR (etype);
8529 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8532 /* if the bit lenth is less than or */
8533 /* it exactly fits a byte then */
8534 if (SPEC_BLEN (etype) <= 8)
8536 shCount = SPEC_BSTR (etype);
8538 /* shift left acc */
8541 if (SPEC_BLEN (etype) < 8)
8542 { /* if smaller than a byte */
8548 emitcode ("mov", "b,a");
8549 emitcode ("mov", "a,@%s", rname);
8553 emitcode ("mov", "b,a");
8554 emitcode ("movx", "a,@dptr");
8558 emitcode ("push", "b");
8559 emitcode ("push", "acc");
8560 emitcode ("lcall", "__gptrget");
8561 emitcode ("pop", "b");
8565 emitcode ("anl", "a,#0x%02x", (unsigned char)
8566 ((unsigned char) (0xFF << (blen + bstr)) |
8567 (unsigned char) (0xFF >> (8 - bstr))));
8568 emitcode ("orl", "a,b");
8569 if (p_type == GPOINTER)
8570 emitcode ("pop", "b");
8577 emitcode ("mov", "@%s,a", rname);
8581 emitcode ("movx", "@dptr,a");
8585 emitcode ("lcall", "__gptrput");
8590 if (SPEC_BLEN (etype) <= 8)
8593 emitcode ("inc", "%s", rname);
8594 rLen = SPEC_BLEN (etype);
8596 /* now generate for lengths greater than one byte */
8600 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8612 emitcode ("mov", "@%s,a", rname);
8615 emitcode ("mov", "@%s,%s", rname, l);
8620 emitcode ("movx", "@dptr,a");
8625 emitcode ("lcall", "__gptrput");
8628 emitcode ("inc", "%s", rname);
8633 /* last last was not complete */
8636 /* save the byte & read byte */
8640 emitcode ("mov", "b,a");
8641 emitcode ("mov", "a,@%s", rname);
8645 emitcode ("mov", "b,a");
8646 emitcode ("movx", "a,@dptr");
8650 emitcode ("push", "b");
8651 emitcode ("push", "acc");
8652 emitcode ("lcall", "__gptrget");
8653 emitcode ("pop", "b");
8657 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8658 emitcode ("orl", "a,b");
8661 if (p_type == GPOINTER)
8662 emitcode ("pop", "b");
8668 emitcode ("mov", "@%s,a", rname);
8672 emitcode ("movx", "@dptr,a");
8676 emitcode ("lcall", "__gptrput");
8680 /*-----------------------------------------------------------------*/
8681 /* genDataPointerSet - remat pointer to data space */
8682 /*-----------------------------------------------------------------*/
8684 genDataPointerSet (operand * right,
8688 int size, offset = 0;
8689 char *l, buffer[256];
8691 aopOp (right, ic, FALSE, FALSE);
8693 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8694 size = AOP_SIZE (right);
8698 sprintf (buffer, "(%s + %d)", l + 1, offset);
8700 sprintf (buffer, "%s", l + 1);
8701 emitcode ("mov", "%s,%s", buffer,
8702 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8705 freeAsmop (right, NULL, ic, TRUE);
8706 freeAsmop (result, NULL, ic, TRUE);
8709 /*-----------------------------------------------------------------*/
8710 /* genNearPointerSet - emitcode for near pointer put */
8711 /*-----------------------------------------------------------------*/
8713 genNearPointerSet (operand * right,
8720 sym_link *retype, *letype;
8721 sym_link *ptype = operandType (result);
8723 retype = getSpec (operandType (right));
8724 letype = getSpec (ptype);
8726 aopOp (result, ic, FALSE, FALSE);
8728 /* if the result is rematerializable &
8729 in data space & not a bit variable */
8730 if (AOP_TYPE (result) == AOP_IMMD &&
8731 DCL_TYPE (ptype) == POINTER &&
8732 !IS_BITVAR (retype) &&
8733 !IS_BITVAR (letype))
8735 genDataPointerSet (right, result, ic);
8739 /* if the value is already in a pointer register
8740 then don't need anything more */
8741 if (!AOP_INPREG (AOP (result)))
8743 /* otherwise get a free pointer register */
8745 preg = getFreePtr (ic, &aop, FALSE);
8746 emitcode ("mov", "%s,%s",
8748 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8752 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8754 freeAsmop (result, NULL, ic, TRUE);
8755 aopOp (right, ic, FALSE, FALSE);
8757 /* if bitfield then unpack the bits */
8758 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8759 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8762 /* we have can just get the values */
8763 int size = AOP_SIZE (right);
8768 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8772 emitcode ("mov", "@%s,a", rname);
8775 emitcode ("mov", "@%s,%s", rname, l);
8777 emitcode ("inc", "%s", rname);
8782 /* now some housekeeping stuff */
8785 /* we had to allocate for this iCode */
8786 freeAsmop (NULL, aop, ic, TRUE);
8790 /* we did not allocate which means left
8791 already in a pointer register, then
8792 if size > 0 && this could be used again
8793 we have to point it back to where it
8795 if (AOP_SIZE (right) > 1 &&
8796 !OP_SYMBOL (result)->remat &&
8797 (OP_SYMBOL (result)->liveTo > ic->seq ||
8800 int size = AOP_SIZE (right) - 1;
8802 emitcode ("dec", "%s", rname);
8807 freeAsmop (right, NULL, ic, TRUE);
8812 /*-----------------------------------------------------------------*/
8813 /* genPagedPointerSet - emitcode for Paged pointer put */
8814 /*-----------------------------------------------------------------*/
8816 genPagedPointerSet (operand * right,
8823 sym_link *retype, *letype;
8825 retype = getSpec (operandType (right));
8826 letype = getSpec (operandType (result));
8828 aopOp (result, ic, FALSE, FALSE);
8830 /* if the value is already in a pointer register
8831 then don't need anything more */
8832 if (!AOP_INPREG (AOP (result)))
8834 /* otherwise get a free pointer register */
8836 preg = getFreePtr (ic, &aop, FALSE);
8837 emitcode ("mov", "%s,%s",
8839 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8843 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8845 freeAsmop (result, NULL, ic, TRUE);
8846 aopOp (right, ic, FALSE, FALSE);
8848 /* if bitfield then unpack the bits */
8849 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8850 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8853 /* we have can just get the values */
8854 int size = AOP_SIZE (right);
8859 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8862 emitcode ("movx", "@%s,a", rname);
8865 emitcode ("inc", "%s", rname);
8871 /* now some housekeeping stuff */
8874 /* we had to allocate for this iCode */
8875 freeAsmop (NULL, aop, ic, TRUE);
8879 /* we did not allocate which means left
8880 already in a pointer register, then
8881 if size > 0 && this could be used again
8882 we have to point it back to where it
8884 if (AOP_SIZE (right) > 1 &&
8885 !OP_SYMBOL (result)->remat &&
8886 (OP_SYMBOL (result)->liveTo > ic->seq ||
8889 int size = AOP_SIZE (right) - 1;
8891 emitcode ("dec", "%s", rname);
8896 freeAsmop (right, NULL, ic, TRUE);
8901 /*-----------------------------------------------------------------*/
8902 /* genFarPointerSet - set value from far space */
8903 /*-----------------------------------------------------------------*/
8905 genFarPointerSet (operand * right,
8906 operand * result, iCode * ic)
8909 sym_link *retype = getSpec (operandType (right));
8910 sym_link *letype = getSpec (operandType (result));
8912 aopOp (result, ic, FALSE, FALSE);
8914 /* if the operand is already in dptr
8915 then we do nothing else we move the value to dptr */
8916 if (AOP_TYPE (result) != AOP_STR)
8918 /* if this is remateriazable */
8919 if (AOP_TYPE (result) == AOP_IMMD)
8920 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8923 /* we need to get it byte by byte */
8924 _startLazyDPSEvaluation ();
8925 if (AOP_TYPE (result) != AOP_DPTR)
8927 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8928 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8929 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8933 /* We need to generate a load to DPTR indirect through DPTR. */
8934 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8936 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8937 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8938 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8939 emitcode ("pop", "dph");
8940 emitcode ("pop", "dpl");
8942 _endLazyDPSEvaluation ();
8945 /* so dptr know contains the address */
8946 freeAsmop (result, NULL, ic, TRUE);
8947 aopOp (right, ic, FALSE, TRUE);
8949 /* if bit then unpack */
8950 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8951 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8954 size = AOP_SIZE (right);
8957 _startLazyDPSEvaluation ();
8960 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8966 emitcode ("movx", "@dptr,a");
8968 emitcode ("inc", "dptr");
8970 _endLazyDPSEvaluation ();
8973 freeAsmop (right, NULL, ic, TRUE);
8976 /*-----------------------------------------------------------------*/
8977 /* genGenPointerSet - set value from generic pointer space */
8978 /*-----------------------------------------------------------------*/
8980 genGenPointerSet (operand * right,
8981 operand * result, iCode * ic)
8984 sym_link *retype = getSpec (operandType (right));
8985 sym_link *letype = getSpec (operandType (result));
8987 aopOp (result, ic, FALSE, TRUE);
8989 /* if the operand is already in dptr
8990 then we do nothing else we move the value to dptr */
8991 if (AOP_TYPE (result) != AOP_STR)
8993 _startLazyDPSEvaluation ();
8994 /* if this is remateriazable */
8995 if (AOP_TYPE (result) == AOP_IMMD)
8997 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8998 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9001 { /* we need to get it byte by byte */
9002 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9003 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9004 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9005 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9007 _endLazyDPSEvaluation ();
9009 /* so dptr know contains the address */
9010 freeAsmop (result, NULL, ic, TRUE);
9011 aopOp (right, ic, FALSE, TRUE);
9013 /* if bit then unpack */
9014 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9015 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9018 size = AOP_SIZE (right);
9021 _startLazyDPSEvaluation ();
9024 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9030 emitcode ("lcall", "__gptrput");
9032 emitcode ("inc", "dptr");
9034 _endLazyDPSEvaluation ();
9037 freeAsmop (right, NULL, ic, TRUE);
9040 /*-----------------------------------------------------------------*/
9041 /* genPointerSet - stores the value into a pointer location */
9042 /*-----------------------------------------------------------------*/
9044 genPointerSet (iCode * ic)
9046 operand *right, *result;
9047 sym_link *type, *etype;
9050 D (emitcode (";", "genPointerSet ");
9053 right = IC_RIGHT (ic);
9054 result = IC_RESULT (ic);
9056 /* depending on the type of pointer we need to
9057 move it to the correct pointer register */
9058 type = operandType (result);
9059 etype = getSpec (type);
9060 /* if left is of type of pointer then it is simple */
9061 if (IS_PTR (type) && !IS_FUNC (type->next))
9063 p_type = DCL_TYPE (type);
9067 /* we have to go by the storage class */
9068 p_type = PTR_TYPE (SPEC_OCLS (etype));
9071 /* now that we have the pointer type we assign
9072 the pointer values */
9078 genNearPointerSet (right, result, ic);
9082 genPagedPointerSet (right, result, ic);
9086 genFarPointerSet (right, result, ic);
9090 genGenPointerSet (right, result, ic);
9096 /*-----------------------------------------------------------------*/
9097 /* genIfx - generate code for Ifx statement */
9098 /*-----------------------------------------------------------------*/
9100 genIfx (iCode * ic, iCode * popIc)
9102 operand *cond = IC_COND (ic);
9105 D (emitcode (";", "genIfx "););
9107 aopOp (cond, ic, FALSE, FALSE);
9109 /* get the value into acc */
9110 if (AOP_TYPE (cond) != AOP_CRY)
9114 /* the result is now in the accumulator */
9115 freeAsmop (cond, NULL, ic, TRUE);
9117 /* if there was something to be popped then do it */
9121 /* if the condition is a bit variable */
9122 if (isbit && IS_ITEMP (cond) &&
9124 genIfxJump (ic, SPIL_LOC (cond)->rname);
9125 else if (isbit && !IS_ITEMP (cond))
9126 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9128 genIfxJump (ic, "a");
9133 /*-----------------------------------------------------------------*/
9134 /* genAddrOf - generates code for address of */
9135 /*-----------------------------------------------------------------*/
9137 genAddrOf (iCode * ic)
9139 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9142 D (emitcode (";", "genAddrOf ");
9145 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9147 /* if the operand is on the stack then we
9148 need to get the stack offset of this
9152 /* if it has an offset then we need to compute
9156 emitcode ("mov", "a,_bp");
9157 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9158 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9162 /* we can just move _bp */
9163 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9165 /* fill the result with zero */
9166 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9169 if (options.stack10bit && size < (FPTRSIZE - 1))
9172 "*** warning: pointer to stack var truncated.\n");
9179 if (options.stack10bit && offset == 2)
9181 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9185 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9192 /* object not on stack then we need the name */
9193 size = AOP_SIZE (IC_RESULT (ic));
9198 char s[SDCC_NAME_MAX];
9200 sprintf (s, "#(%s >> %d)",
9204 sprintf (s, "#%s", sym->rname);
9205 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9209 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9213 /*-----------------------------------------------------------------*/
9214 /* genFarFarAssign - assignment when both are in far space */
9215 /*-----------------------------------------------------------------*/
9217 genFarFarAssign (operand * result, operand * right, iCode * ic)
9219 int size = AOP_SIZE (right);
9221 symbol *rSym = NULL;
9225 /* quick & easy case. */
9226 D(emitcode(";","genFarFarAssign (1 byte case)"););
9227 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9228 freeAsmop (right, NULL, ic, FALSE);
9229 /* now assign DPTR to result */
9231 aopOp(result, ic, FALSE, FALSE);
9233 aopPut(AOP(result), "a", 0);
9234 freeAsmop(result, NULL, ic, FALSE);
9238 /* See if we've got an underlying symbol to abuse. */
9239 if (IS_SYMOP(result) && OP_SYMBOL(result))
9241 if (IS_TRUE_SYMOP(result))
9243 rSym = OP_SYMBOL(result);
9245 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9247 rSym = OP_SYMBOL(result)->usl.spillLoc;
9251 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9253 /* We can use the '390 auto-toggle feature to good effect here. */
9255 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9256 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9257 emitcode ("mov", "dptr,#%s", rSym->rname);
9258 /* DP2 = result, DP1 = right, DP1 is current. */
9261 emitcode("movx", "a,@dptr");
9262 emitcode("movx", "@dptr,a");
9265 emitcode("inc", "dptr");
9266 emitcode("inc", "dptr");
9269 emitcode("mov", "dps, #0");
9270 freeAsmop (right, NULL, ic, FALSE);
9274 D (emitcode (";", "genFarFarAssign"););
9275 aopOp (result, ic, TRUE, TRUE);
9277 _startLazyDPSEvaluation ();
9281 aopPut (AOP (result),
9282 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9285 _endLazyDPSEvaluation ();
9286 freeAsmop (result, NULL, ic, FALSE);
9287 freeAsmop (right, NULL, ic, FALSE);
9291 /*-----------------------------------------------------------------*/
9292 /* genAssign - generate code for assignment */
9293 /*-----------------------------------------------------------------*/
9295 genAssign (iCode * ic)
9297 operand *result, *right;
9299 unsigned long lit = 0L;
9301 D (emitcode (";", "genAssign ");
9304 result = IC_RESULT (ic);
9305 right = IC_RIGHT (ic);
9307 /* if they are the same */
9308 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9311 aopOp (right, ic, FALSE, FALSE);
9313 emitcode (";", "genAssign: resultIsFar = %s",
9314 isOperandInFarSpace (result) ?
9317 /* special case both in far space */
9318 if ((AOP_TYPE (right) == AOP_DPTR ||
9319 AOP_TYPE (right) == AOP_DPTR2) &&
9320 /* IS_TRUE_SYMOP(result) && */
9321 isOperandInFarSpace (result))
9323 genFarFarAssign (result, right, ic);
9327 aopOp (result, ic, TRUE, FALSE);
9329 /* if they are the same registers */
9330 if (sameRegs (AOP (right), AOP (result)))
9333 /* if the result is a bit */
9334 if (AOP_TYPE (result) == AOP_CRY)
9337 /* if the right size is a literal then
9338 we know what the value is */
9339 if (AOP_TYPE (right) == AOP_LIT)
9341 if (((int) operandLitValue (right)))
9342 aopPut (AOP (result), one, 0);
9344 aopPut (AOP (result), zero, 0);
9348 /* the right is also a bit variable */
9349 if (AOP_TYPE (right) == AOP_CRY)
9351 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9352 aopPut (AOP (result), "c", 0);
9358 aopPut (AOP (result), "a", 0);
9362 /* bit variables done */
9364 size = AOP_SIZE (result);
9366 if (AOP_TYPE (right) == AOP_LIT)
9367 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9370 (AOP_TYPE (result) != AOP_REG) &&
9371 (AOP_TYPE (right) == AOP_LIT) &&
9372 !IS_FLOAT (operandType (right)))
9374 _startLazyDPSEvaluation ();
9375 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9377 aopPut (AOP (result),
9378 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9383 /* And now fill the rest with zeros. */
9386 emitcode ("clr", "a");
9390 aopPut (AOP (result), "a", offset++);
9392 _endLazyDPSEvaluation ();
9396 _startLazyDPSEvaluation ();
9399 aopPut (AOP (result),
9400 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9404 _endLazyDPSEvaluation ();
9408 freeAsmop (right, NULL, ic, FALSE);
9409 freeAsmop (result, NULL, ic, TRUE);
9412 /*-----------------------------------------------------------------*/
9413 /* genJumpTab - generates code for jump table */
9414 /*-----------------------------------------------------------------*/
9416 genJumpTab (iCode * ic)
9421 D (emitcode (";", "genJumpTab ");
9424 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9425 /* get the condition into accumulator */
9426 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9428 /* multiply by four! */
9429 emitcode ("add", "a,acc");
9430 emitcode ("add", "a,acc");
9431 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9433 jtab = newiTempLabel (NULL);
9434 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9435 emitcode ("jmp", "@a+dptr");
9436 emitcode ("", "%05d$:", jtab->key + 100);
9437 /* now generate the jump labels */
9438 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9439 jtab = setNextItem (IC_JTLABELS (ic)))
9440 emitcode ("ljmp", "%05d$", jtab->key + 100);
9444 /*-----------------------------------------------------------------*/
9445 /* genCast - gen code for casting */
9446 /*-----------------------------------------------------------------*/
9448 genCast (iCode * ic)
9450 operand *result = IC_RESULT (ic);
9451 sym_link *ctype = operandType (IC_LEFT (ic));
9452 sym_link *rtype = operandType (IC_RIGHT (ic));
9453 operand *right = IC_RIGHT (ic);
9456 D (emitcode (";", "genCast ");
9459 /* if they are equivalent then do nothing */
9460 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9463 aopOp (right, ic, FALSE, FALSE);
9464 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9466 /* if the result is a bit */
9467 if (AOP_TYPE (result) == AOP_CRY)
9469 /* if the right size is a literal then
9470 we know what the value is */
9471 if (AOP_TYPE (right) == AOP_LIT)
9473 if (((int) operandLitValue (right)))
9474 aopPut (AOP (result), one, 0);
9476 aopPut (AOP (result), zero, 0);
9481 /* the right is also a bit variable */
9482 if (AOP_TYPE (right) == AOP_CRY)
9484 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9485 aopPut (AOP (result), "c", 0);
9491 aopPut (AOP (result), "a", 0);
9495 /* if they are the same size : or less */
9496 if (AOP_SIZE (result) <= AOP_SIZE (right))
9499 /* if they are in the same place */
9500 if (sameRegs (AOP (right), AOP (result)))
9503 /* if they in different places then copy */
9504 size = AOP_SIZE (result);
9506 _startLazyDPSEvaluation ();
9509 aopPut (AOP (result),
9510 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9514 _endLazyDPSEvaluation ();
9519 /* if the result is of type pointer */
9524 sym_link *type = operandType (right);
9526 /* pointer to generic pointer */
9527 if (IS_GENPTR (ctype))
9533 p_type = DCL_TYPE (type);
9537 #if OLD_CAST_BEHAVIOR
9538 /* KV: we are converting a non-pointer type to
9539 * a generic pointer. This (ifdef'd out) code
9540 * says that the resulting generic pointer
9541 * should have the same class as the storage
9542 * location of the non-pointer variable.
9544 * For example, converting an int (which happens
9545 * to be stored in DATA space) to a pointer results
9546 * in a DATA generic pointer; if the original int
9547 * in XDATA space, so will be the resulting pointer.
9549 * I don't like that behavior, and thus this change:
9550 * all such conversions will be forced to XDATA and
9551 * throw a warning. If you want some non-XDATA
9552 * type, or you want to suppress the warning, you
9553 * must go through an intermediate cast, like so:
9555 * char _generic *gp = (char _xdata *)(intVar);
9557 sym_link *etype = getSpec (type);
9559 /* we have to go by the storage class */
9560 if (SPEC_OCLS (etype) != generic)
9562 p_type = PTR_TYPE (SPEC_OCLS (etype));
9567 /* Converting unknown class (i.e. register variable)
9568 * to generic pointer. This is not good, but
9569 * we'll make a guess (and throw a warning).
9572 werror (W_INT_TO_GEN_PTR_CAST);
9576 /* the first two bytes are known */
9577 size = GPTRSIZE - 1;
9579 _startLazyDPSEvaluation ();
9582 aopPut (AOP (result),
9583 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9587 _endLazyDPSEvaluation ();
9589 /* the last byte depending on type */
9607 /* this should never happen */
9608 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9609 "got unknown pointer type");
9612 aopPut (AOP (result), l, GPTRSIZE - 1);
9616 /* just copy the pointers */
9617 size = AOP_SIZE (result);
9619 _startLazyDPSEvaluation ();
9622 aopPut (AOP (result),
9623 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9627 _endLazyDPSEvaluation ();
9631 /* so we now know that the size of destination is greater
9632 than the size of the source */
9633 /* we move to result for the size of source */
9634 size = AOP_SIZE (right);
9636 _startLazyDPSEvaluation ();
9639 aopPut (AOP (result),
9640 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9644 _endLazyDPSEvaluation ();
9646 /* now depending on the sign of the source && destination */
9647 size = AOP_SIZE (result) - AOP_SIZE (right);
9648 /* if unsigned or not an integral type */
9649 /* also, if the source is a bit, we don't need to sign extend, because
9650 * it can't possibly have set the sign bit.
9652 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9656 aopPut (AOP (result), zero, offset++);
9661 /* we need to extend the sign :{ */
9662 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9663 FALSE, FALSE, TRUE);
9665 emitcode ("rlc", "a");
9666 emitcode ("subb", "a,acc");
9668 aopPut (AOP (result), "a", offset++);
9671 /* we are done hurray !!!! */
9674 freeAsmop (right, NULL, ic, TRUE);
9675 freeAsmop (result, NULL, ic, TRUE);
9679 /*-----------------------------------------------------------------*/
9680 /* genDjnz - generate decrement & jump if not zero instrucion */
9681 /*-----------------------------------------------------------------*/
9683 genDjnz (iCode * ic, iCode * ifx)
9689 /* if the if condition has a false label
9690 then we cannot save */
9694 /* if the minus is not of the form
9696 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9697 !IS_OP_LITERAL (IC_RIGHT (ic)))
9700 if (operandLitValue (IC_RIGHT (ic)) != 1)
9703 /* if the size of this greater than one then no
9705 if (getSize (operandType (IC_RESULT (ic))) > 1)
9708 /* otherwise we can save BIG */
9709 D(emitcode(";", "genDjnz"););
9711 lbl = newiTempLabel (NULL);
9712 lbl1 = newiTempLabel (NULL);
9714 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9716 if (AOP_NEEDSACC(IC_RESULT(ic)))
9718 /* If the result is accessed indirectly via
9719 * the accumulator, we must explicitly write
9720 * it back after the decrement.
9722 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9724 if (strcmp(rByte, "a"))
9726 /* Something is hopelessly wrong */
9727 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9728 __FILE__, __LINE__);
9729 /* We can just give up; the generated code will be inefficient,
9732 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9735 emitcode ("dec", "%s", rByte);
9736 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9737 emitcode ("jnz", "%05d$", lbl->key + 100);
9739 else if (IS_AOP_PREG (IC_RESULT (ic)))
9741 emitcode ("dec", "%s",
9742 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9743 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9744 emitcode ("jnz", "%05d$", lbl->key + 100);
9748 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9751 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9752 emitcode ("", "%05d$:", lbl->key + 100);
9753 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9754 emitcode ("", "%05d$:", lbl1->key + 100);
9756 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9761 /*-----------------------------------------------------------------*/
9762 /* genReceive - generate code for a receive iCode */
9763 /*-----------------------------------------------------------------*/
9765 genReceive (iCode * ic)
9768 D (emitcode (";", "genReceive ");
9771 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9772 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9773 IS_TRUE_SYMOP (IC_RESULT (ic))))
9775 int size = getSize (operandType (IC_RESULT (ic)));
9776 int offset = fReturnSizeDS390 - size;
9779 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9780 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9783 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9784 size = AOP_SIZE (IC_RESULT (ic));
9788 emitcode ("pop", "acc");
9789 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9796 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9798 assignResultValue (IC_RESULT (ic));
9801 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9804 /*-----------------------------------------------------------------*/
9805 /* gen390Code - generate code for Dallas 390 based controllers */
9806 /*-----------------------------------------------------------------*/
9808 gen390Code (iCode * lic)
9813 lineHead = lineCurr = NULL;
9817 /* print the allocation information */
9819 printAllocInfo (currFunc, codeOutFile);
9821 /* if debug information required */
9822 if (options.debug && currFunc)
9824 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9826 if (IS_STATIC (currFunc->etype))
9827 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9829 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9832 /* stack pointer name */
9833 if (options.useXstack)
9839 for (ic = lic; ic; ic = ic->next)
9842 if (cln != ic->lineno)
9847 emitcode ("", "C$%s$%d$%d$%d ==.",
9848 FileBaseName (ic->filename), ic->lineno,
9849 ic->level, ic->block);
9852 emitcode (";", "%s %d", ic->filename, ic->lineno);
9855 /* if the result is marked as
9856 spilt and rematerializable or code for
9857 this has already been generated then
9859 if (resultRemat (ic) || ic->generated)
9862 /* depending on the operation */
9882 /* IPOP happens only when trying to restore a
9883 spilt live range, if there is an ifx statement
9884 following this pop then the if statement might
9885 be using some of the registers being popped which
9886 would destory the contents of the register so
9887 we need to check for this condition and handle it */
9889 ic->next->op == IFX &&
9890 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9891 genIfx (ic->next, ic);
9909 genEndFunction (ic);
9929 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9946 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9950 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9957 /* note these two are xlated by algebraic equivalence
9958 during parsing SDCC.y */
9959 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9960 "got '>=' or '<=' shouldn't have come here");
9964 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9976 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9980 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9984 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10008 genRightShift (ic);
10011 case GET_VALUE_AT_ADDRESS:
10012 genPointerGet (ic);
10016 if (POINTER_SET (ic))
10017 genPointerSet (ic);
10043 addSet (&_G.sendSet, ic);
10052 /* now we are ready to call the
10053 peep hole optimizer */
10054 if (!options.nopeep)
10055 peepHole (&lineHead);
10057 /* now do the actual printing */
10058 printLine (lineHead, codeOutFile);