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) */
2950 emitcode ("", "C$%s$%d$%d$%d ==.",
2951 FileBaseName (ic->filename), currFunc->lastLine,
2952 ic->level, ic->block);
2953 if (IS_STATIC (currFunc->etype))
2954 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2956 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2960 emitcode ("reti", "");
2964 if (SPEC_CRTCL (sym->etype))
2965 emitcode ("setb", "ea");
2967 if (sym->calleeSave)
2971 /* if any registers used */
2974 /* save the registers used */
2975 for (i = sym->regsUsed->size; i >= 0; i--)
2977 if (bitVectBitValue (sym->regsUsed, i) ||
2978 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2979 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2985 /* if debug then send end of function */
2989 emitcode ("", "C$%s$%d$%d$%d ==.",
2990 FileBaseName (ic->filename), currFunc->lastLine,
2991 ic->level, ic->block);
2992 if (IS_STATIC (currFunc->etype))
2993 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2995 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2999 emitcode ("ret", "");
3004 /*-----------------------------------------------------------------*/
3005 /* genRet - generate code for return statement */
3006 /*-----------------------------------------------------------------*/
3010 int size, offset = 0, pushed = 0;
3012 D (emitcode (";", "genRet ");
3015 /* if we have no return value then
3016 just generate the "ret" */
3020 /* we have something to return then
3021 move the return value into place */
3022 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3023 size = AOP_SIZE (IC_LEFT (ic));
3025 _startLazyDPSEvaluation ();
3029 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3031 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3032 FALSE, TRUE, FALSE);
3033 emitcode ("push", "%s", l);
3038 /* Since A is the last element of fReturn,
3039 * is is OK to clobber it in the aopGet.
3041 l = aopGet (AOP (IC_LEFT (ic)), offset,
3042 FALSE, FALSE, TRUE);
3043 if (strcmp (fReturn[offset], l))
3044 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3047 _endLazyDPSEvaluation ();
3054 if (strcmp (fReturn[pushed], "a"))
3055 emitcode ("pop", fReturn[pushed]);
3057 emitcode ("pop", "acc");
3060 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3063 /* generate a jump to the return label
3064 if the next is not the return statement */
3065 if (!(ic->next && ic->next->op == LABEL &&
3066 IC_LABEL (ic->next) == returnLabel))
3068 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3072 /*-----------------------------------------------------------------*/
3073 /* genLabel - generates a label */
3074 /*-----------------------------------------------------------------*/
3076 genLabel (iCode * ic)
3078 /* special case never generate */
3079 if (IC_LABEL (ic) == entryLabel)
3082 D (emitcode (";", "genLabel ");
3085 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3088 /*-----------------------------------------------------------------*/
3089 /* genGoto - generates a ljmp */
3090 /*-----------------------------------------------------------------*/
3092 genGoto (iCode * ic)
3094 D (emitcode (";", "genGoto ");
3096 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3099 /*-----------------------------------------------------------------*/
3100 /* findLabelBackwards: walks back through the iCode chain looking */
3101 /* for the given label. Returns number of iCode instructions */
3102 /* between that label and given ic. */
3103 /* Returns zero if label not found. */
3104 /*-----------------------------------------------------------------*/
3106 findLabelBackwards (iCode * ic, int key)
3115 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3117 /* printf("findLabelBackwards = %d\n", count); */
3125 /*-----------------------------------------------------------------*/
3126 /* genPlusIncr :- does addition with increment if possible */
3127 /*-----------------------------------------------------------------*/
3129 genPlusIncr (iCode * ic)
3131 unsigned int icount;
3132 unsigned int size = getDataSize (IC_RESULT (ic));
3134 /* will try to generate an increment */
3135 /* if the right side is not a literal
3137 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3140 /* if the literal value of the right hand side
3141 is greater than 4 then it is not worth it */
3142 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3145 /* if increment 16 bits in register */
3147 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3148 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3149 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3157 /* If the next instruction is a goto and the goto target
3158 * is <= 5 instructions previous to this, we can generate
3159 * jumps straight to that target.
3161 if (ic->next && ic->next->op == GOTO
3162 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3165 emitcode (";", "tail increment optimized (range %d)", labelRange);
3166 tlbl = IC_LABEL (ic->next);
3171 tlbl = newiTempLabel (NULL);
3174 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3175 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3176 IS_AOP_PREG (IC_RESULT (ic)))
3177 emitcode ("cjne", "%s,#0x00,%05d$"
3178 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3182 emitcode ("clr", "a");
3183 emitcode ("cjne", "a,%s,%05d$"
3184 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3188 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3191 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3192 IS_AOP_PREG (IC_RESULT (ic)))
3193 emitcode ("cjne", "%s,#0x00,%05d$"
3194 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3197 emitcode ("cjne", "a,%s,%05d$"
3198 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3201 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3205 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3206 IS_AOP_PREG (IC_RESULT (ic)))
3207 emitcode ("cjne", "%s,#0x00,%05d$"
3208 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3212 emitcode ("cjne", "a,%s,%05d$"
3213 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3216 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3221 emitcode ("", "%05d$:", tlbl->key + 100);
3226 /* if the sizes are greater than 1 then we cannot */
3227 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3228 AOP_SIZE (IC_LEFT (ic)) > 1)
3231 /* we can if the aops of the left & result match or
3232 if they are in registers and the registers are the
3235 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3236 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3237 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3242 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3243 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3244 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3249 _startLazyDPSEvaluation ();
3252 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3254 _endLazyDPSEvaluation ();
3263 /*-----------------------------------------------------------------*/
3264 /* outBitAcc - output a bit in acc */
3265 /*-----------------------------------------------------------------*/
3267 outBitAcc (operand * result)
3269 symbol *tlbl = newiTempLabel (NULL);
3270 /* if the result is a bit */
3271 if (AOP_TYPE (result) == AOP_CRY)
3273 aopPut (AOP (result), "a", 0);
3277 emitcode ("jz", "%05d$", tlbl->key + 100);
3278 emitcode ("mov", "a,%s", one);
3279 emitcode ("", "%05d$:", tlbl->key + 100);
3284 /*-----------------------------------------------------------------*/
3285 /* genPlusBits - generates code for addition of two bits */
3286 /*-----------------------------------------------------------------*/
3288 genPlusBits (iCode * ic)
3290 D (emitcode (";", "genPlusBits ");
3292 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3294 symbol *lbl = newiTempLabel (NULL);
3295 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3296 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3297 emitcode ("cpl", "c");
3298 emitcode ("", "%05d$:", (lbl->key + 100));
3299 outBitC (IC_RESULT (ic));
3303 emitcode ("clr", "a");
3304 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3305 emitcode ("rlc", "a");
3306 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3307 emitcode ("addc", "a,#0x00");
3308 outAcc (IC_RESULT (ic));
3313 adjustArithmeticResult (iCode * ic)
3315 if (opIsGptr (IC_RESULT (ic)) &&
3316 opIsGptr (IC_LEFT (ic)) &&
3317 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3319 aopPut (AOP (IC_RESULT (ic)),
3320 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3324 if (opIsGptr (IC_RESULT (ic)) &&
3325 opIsGptr (IC_RIGHT (ic)) &&
3326 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3328 aopPut (AOP (IC_RESULT (ic)),
3329 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3333 if (opIsGptr (IC_RESULT (ic)) &&
3334 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3335 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3336 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3337 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3340 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3341 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3345 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3346 // (because all three operands are in far space).
3347 #define AOP_OP_3(ic) \
3348 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3349 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3350 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3351 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3352 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3353 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3355 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3357 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3360 // Macro to aopOp all three operands of an ic. If this cannot be done,
3361 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3362 // will be set TRUE. The caller must then handle the case specially, noting
3363 // that the IC_RESULT operand is not aopOp'd.
3364 #define AOP_OP_3_NOFATAL(ic, rc) \
3365 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3366 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3367 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3368 isOperandInFarSpace(IC_RESULT(ic))) \
3370 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3375 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3376 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3378 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3379 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3381 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3383 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3387 // aopOp the left & right operands of an ic.
3388 #define AOP_OP_2(ic) \
3389 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3390 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3392 // convienience macro.
3393 #define AOP_SET_LOCALS(ic) \
3394 left = IC_LEFT(ic); \
3395 right = IC_RIGHT(ic); \
3396 result = IC_RESULT(ic);
3399 // Given an integer value of pushedSize bytes on the stack,
3400 // adjust it to be resultSize bytes, either by discarding
3401 // the most significant bytes or by zero-padding.
3403 // On exit from this macro, pushedSize will have been adjusted to
3404 // equal resultSize, and ACC may be trashed.
3405 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3406 /* If the pushed data is bigger than the result, \
3407 * simply discard unused bytes. Icky, but works. \
3409 while (pushedSize > resultSize) \
3411 D (emitcode (";", "discarding unused result byte."););\
3412 emitcode ("pop", "acc"); \
3415 if (pushedSize < resultSize) \
3417 emitcode ("clr", "a"); \
3418 /* Conversly, we haven't pushed enough here. \
3419 * just zero-pad, and all is well. \
3421 while (pushedSize < resultSize) \
3423 emitcode("push", "acc"); \
3427 assert(pushedSize == resultSize);
3429 /*-----------------------------------------------------------------*/
3430 /* genPlus - generates code for addition */
3431 /*-----------------------------------------------------------------*/
3433 genPlus (iCode * ic)
3435 int size, offset = 0;
3436 bool pushResult = FALSE;
3439 D (emitcode (";", "genPlus "););
3441 /* special cases :- */
3443 AOP_OP_3_NOFATAL (ic, pushResult);
3446 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3451 /* if literal, literal on the right or
3452 if left requires ACC or right is already
3454 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3455 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3456 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3458 operand *t = IC_RIGHT (ic);
3459 IC_RIGHT (ic) = IC_LEFT (ic);
3461 emitcode (";", "Swapped plus args.");
3464 /* if both left & right are in bit
3466 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3467 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3473 /* if left in bit space & right literal */
3474 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3475 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3477 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3478 /* if result in bit space */
3479 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3481 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3482 emitcode ("cpl", "c");
3483 outBitC (IC_RESULT (ic));
3487 size = getDataSize (IC_RESULT (ic));
3488 _startLazyDPSEvaluation ();
3491 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3492 emitcode ("addc", "a,#00");
3493 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3495 _endLazyDPSEvaluation ();
3500 /* if I can do an increment instead
3501 of add then GOOD for ME */
3502 if (genPlusIncr (ic) == TRUE)
3504 emitcode (";", "did genPlusIncr");
3509 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3511 _startLazyDPSEvaluation ();
3514 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3516 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3518 emitcode ("add", "a,%s",
3519 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3521 emitcode ("addc", "a,%s",
3522 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3526 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3528 /* right is going to use ACC or we would have taken the
3531 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3532 D(emitcode(";", "+ AOP_ACC special case."););
3533 emitcode("xch", "a, %s", DP2_RESULT_REG);
3535 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3538 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3540 emitcode("add", "a, %s", DP2_RESULT_REG);
3544 emitcode ("add", "a,%s",
3545 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3550 emitcode ("addc", "a,%s",
3551 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3556 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3560 emitcode ("push", "acc");
3564 _endLazyDPSEvaluation ();
3568 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3570 size = getDataSize (IC_LEFT (ic));
3571 rSize = getDataSize (IC_RESULT (ic));
3573 ADJUST_PUSHED_RESULT(size, rSize);
3575 _startLazyDPSEvaluation ();
3578 emitcode ("pop", "acc");
3579 aopPut (AOP (IC_RESULT (ic)), "a", size);
3581 _endLazyDPSEvaluation ();
3584 adjustArithmeticResult (ic);
3587 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3588 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3592 /*-----------------------------------------------------------------*/
3593 /* genMinusDec :- does subtraction with deccrement if possible */
3594 /*-----------------------------------------------------------------*/
3596 genMinusDec (iCode * ic)
3598 unsigned int icount;
3599 unsigned int size = getDataSize (IC_RESULT (ic));
3601 /* will try to generate an increment */
3602 /* if the right side is not a literal
3604 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3607 /* if the literal value of the right hand side
3608 is greater than 4 then it is not worth it */
3609 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3612 /* if decrement 16 bits in register */
3613 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3614 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3615 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3623 /* If the next instruction is a goto and the goto target
3624 * is <= 5 instructions previous to this, we can generate
3625 * jumps straight to that target.
3627 if (ic->next && ic->next->op == GOTO
3628 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3631 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3632 tlbl = IC_LABEL (ic->next);
3637 tlbl = newiTempLabel (NULL);
3641 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3642 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3643 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3644 IS_AOP_PREG (IC_RESULT (ic)))
3645 emitcode ("cjne", "%s,#0xff,%05d$"
3646 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3650 emitcode ("mov", "a,#0xff");
3651 emitcode ("cjne", "a,%s,%05d$"
3652 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3655 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3658 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3659 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3660 IS_AOP_PREG (IC_RESULT (ic)))
3661 emitcode ("cjne", "%s,#0xff,%05d$"
3662 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3666 emitcode ("cjne", "a,%s,%05d$"
3667 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3670 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3674 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3676 IS_AOP_PREG (IC_RESULT (ic)))
3677 emitcode ("cjne", "%s,#0xff,%05d$"
3678 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3682 emitcode ("cjne", "a,%s,%05d$"
3683 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3686 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3690 emitcode ("", "%05d$:", tlbl->key + 100);
3695 /* if the sizes are greater than 1 then we cannot */
3696 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3697 AOP_SIZE (IC_LEFT (ic)) > 1)
3700 /* we can if the aops of the left & result match or
3701 if they are in registers and the registers are the
3704 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3705 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3706 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3709 _startLazyDPSEvaluation ();
3712 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3714 _endLazyDPSEvaluation ();
3722 /*-----------------------------------------------------------------*/
3723 /* addSign - complete with sign */
3724 /*-----------------------------------------------------------------*/
3726 addSign (operand * result, int offset, int sign)
3728 int size = (getDataSize (result) - offset);
3731 _startLazyDPSEvaluation();
3734 emitcode ("rlc", "a");
3735 emitcode ("subb", "a,acc");
3738 aopPut (AOP (result), "a", offset++);
3745 aopPut (AOP (result), zero, offset++);
3748 _endLazyDPSEvaluation();
3752 /*-----------------------------------------------------------------*/
3753 /* genMinusBits - generates code for subtraction of two bits */
3754 /*-----------------------------------------------------------------*/
3756 genMinusBits (iCode * ic)
3758 symbol *lbl = newiTempLabel (NULL);
3760 D (emitcode (";", "genMinusBits "););
3762 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3764 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3765 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3766 emitcode ("cpl", "c");
3767 emitcode ("", "%05d$:", (lbl->key + 100));
3768 outBitC (IC_RESULT (ic));
3772 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3773 emitcode ("subb", "a,acc");
3774 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3775 emitcode ("inc", "a");
3776 emitcode ("", "%05d$:", (lbl->key + 100));
3777 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3778 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3782 /*-----------------------------------------------------------------*/
3783 /* genMinus - generates code for subtraction */
3784 /*-----------------------------------------------------------------*/
3786 genMinus (iCode * ic)
3788 int size, offset = 0;
3790 unsigned long lit = 0L;
3791 bool pushResult = FALSE;
3793 D (emitcode (";", "genMinus "););
3795 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3796 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3797 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3798 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3804 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3806 /* special cases :- */
3807 /* if both left & right are in bit space */
3808 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3809 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3815 /* if I can do an decrement instead
3816 of subtract then GOOD for ME */
3817 if (genMinusDec (ic) == TRUE)
3822 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3824 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3830 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3835 /* if literal, add a,#-lit, else normal subb */
3836 _startLazyDPSEvaluation ();
3839 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3840 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3841 emitcode ("subb", "a,%s",
3842 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3845 /* first add without previous c */
3847 emitcode ("add", "a,#0x%02x",
3848 (unsigned int) (lit & 0x0FFL));
3850 emitcode ("addc", "a,#0x%02x",
3851 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3856 emitcode ("push", "acc");
3860 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3864 _endLazyDPSEvaluation ();
3868 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3870 size = getDataSize (IC_LEFT (ic));
3871 rSize = getDataSize (IC_RESULT (ic));
3873 ADJUST_PUSHED_RESULT(size, rSize);
3875 _startLazyDPSEvaluation ();
3878 emitcode ("pop", "acc");
3879 aopPut (AOP (IC_RESULT (ic)), "a", size);
3881 _endLazyDPSEvaluation ();
3884 adjustArithmeticResult (ic);
3887 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3888 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3889 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3893 /*-----------------------------------------------------------------*/
3894 /* genMultbits :- multiplication of bits */
3895 /*-----------------------------------------------------------------*/
3897 genMultbits (operand * left,
3901 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3902 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3907 /*-----------------------------------------------------------------*/
3908 /* genMultOneByte : 8*8=8/16 bit multiplication */
3909 /*-----------------------------------------------------------------*/
3911 genMultOneByte (operand * left,
3915 sym_link *opetype = operandType (result);
3917 int size=AOP_SIZE(result);
3919 if (size<1 || size>2) {
3920 // this should never happen
3921 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3922 AOP_SIZE(result), __FILE__, lineno);
3926 /* (if two literals: the value is computed before) */
3927 /* if one literal, literal on the right */
3928 if (AOP_TYPE (left) == AOP_LIT)
3933 emitcode (";", "swapped left and right");
3936 if (SPEC_USIGN(opetype)
3937 // ignore the sign of left and right, what else can we do?
3938 || (SPEC_USIGN(operandType(left)) &&
3939 SPEC_USIGN(operandType(right)))) {
3940 // just an unsigned 8*8=8/16 multiply
3941 //emitcode (";","unsigned");
3942 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3943 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3944 emitcode ("mul", "ab");
3945 aopPut (AOP (result), "a", 0);
3947 aopPut (AOP (result), "b", 1);
3952 // we have to do a signed multiply
3954 emitcode (";", "signed");
3955 emitcode ("clr", "F0"); // reset sign flag
3956 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3958 lbl=newiTempLabel(NULL);
3959 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3960 // left side is negative, 8-bit two's complement, this fails for -128
3961 emitcode ("setb", "F0"); // set sign flag
3962 emitcode ("cpl", "a");
3963 emitcode ("inc", "a");
3965 emitcode ("", "%05d$:", lbl->key+100);
3968 if (AOP_TYPE(right)==AOP_LIT) {
3969 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3970 /* AND literal negative */
3971 if ((int) val < 0) {
3972 emitcode ("cpl", "F0"); // complement sign flag
3973 emitcode ("mov", "b,#0x%02x", -val);
3975 emitcode ("mov", "b,#0x%02x", val);
3978 lbl=newiTempLabel(NULL);
3979 emitcode ("mov", "b,a");
3980 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3981 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3982 // right side is negative, 8-bit two's complement
3983 emitcode ("cpl", "F0"); // complement sign flag
3984 emitcode ("cpl", "a");
3985 emitcode ("inc", "a");
3986 emitcode ("", "%05d$:", lbl->key+100);
3988 emitcode ("mul", "ab");
3990 lbl=newiTempLabel(NULL);
3991 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3992 // only ONE op was negative, we have to do a 8/16-bit two's complement
3993 emitcode ("cpl", "a"); // lsb
3995 emitcode ("inc", "a");
3997 emitcode ("add", "a,#1");
3998 emitcode ("xch", "a,b");
3999 emitcode ("cpl", "a"); // msb
4000 emitcode ("addc", "a,#0");
4001 emitcode ("xch", "a,b");
4004 emitcode ("", "%05d$:", lbl->key+100);
4005 aopPut (AOP (result), "a", 0);
4007 aopPut (AOP (result), "b", 1);
4011 /*-----------------------------------------------------------------*/
4012 /* genMult - generates code for multiplication */
4013 /*-----------------------------------------------------------------*/
4015 genMult (iCode * ic)
4017 operand *left = IC_LEFT (ic);
4018 operand *right = IC_RIGHT (ic);
4019 operand *result = IC_RESULT (ic);
4021 D (emitcode (";", "genMult "););
4023 /* assign the amsops */
4026 /* special cases first */
4028 if (AOP_TYPE (left) == AOP_CRY &&
4029 AOP_TYPE (right) == AOP_CRY)
4031 genMultbits (left, right, result);
4035 /* if both are of size == 1 */
4036 if (AOP_SIZE (left) == 1 &&
4037 AOP_SIZE (right) == 1)
4039 genMultOneByte (left, right, result);
4043 /* should have been converted to function call */
4047 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4048 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4049 freeAsmop (result, NULL, ic, TRUE);
4052 /*-----------------------------------------------------------------*/
4053 /* genDivbits :- division of bits */
4054 /*-----------------------------------------------------------------*/
4056 genDivbits (operand * left,
4063 /* the result must be bit */
4064 LOAD_AB_FOR_DIV (left, right, l);
4065 emitcode ("div", "ab");
4066 emitcode ("rrc", "a");
4067 aopPut (AOP (result), "c", 0);
4070 /*-----------------------------------------------------------------*/
4071 /* genDivOneByte : 8 bit division */
4072 /*-----------------------------------------------------------------*/
4074 genDivOneByte (operand * left,
4078 sym_link *opetype = operandType (result);
4083 size = AOP_SIZE (result) - 1;
4085 /* signed or unsigned */
4086 if (SPEC_USIGN (opetype))
4088 /* unsigned is easy */
4089 LOAD_AB_FOR_DIV (left, right, l);
4090 emitcode ("div", "ab");
4091 aopPut (AOP (result), "a", 0);
4093 aopPut (AOP (result), zero, offset++);
4097 /* signed is a little bit more difficult */
4099 /* save the signs of the operands */
4100 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4102 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4103 emitcode ("push", "acc"); /* save it on the stack */
4105 /* now sign adjust for both left & right */
4106 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4108 lbl = newiTempLabel (NULL);
4109 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4110 emitcode ("cpl", "a");
4111 emitcode ("inc", "a");
4112 emitcode ("", "%05d$:", (lbl->key + 100));
4113 emitcode ("mov", "b,a");
4115 /* sign adjust left side */
4116 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4119 lbl = newiTempLabel (NULL);
4120 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4121 emitcode ("cpl", "a");
4122 emitcode ("inc", "a");
4123 emitcode ("", "%05d$:", (lbl->key + 100));
4125 /* now the division */
4126 emitcode ("nop", "; workaround for DS80C390 div bug.");
4127 emitcode ("div", "ab");
4128 /* we are interested in the lower order
4130 emitcode ("mov", "b,a");
4131 lbl = newiTempLabel (NULL);
4132 emitcode ("pop", "acc");
4133 /* if there was an over flow we don't
4134 adjust the sign of the result */
4135 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4136 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4138 emitcode ("clr", "a");
4139 emitcode ("subb", "a,b");
4140 emitcode ("mov", "b,a");
4141 emitcode ("", "%05d$:", (lbl->key + 100));
4143 /* now we are done */
4144 aopPut (AOP (result), "b", 0);
4147 emitcode ("mov", "c,b.7");
4148 emitcode ("subb", "a,acc");
4151 aopPut (AOP (result), "a", offset++);
4155 /*-----------------------------------------------------------------*/
4156 /* genDiv - generates code for division */
4157 /*-----------------------------------------------------------------*/
4161 operand *left = IC_LEFT (ic);
4162 operand *right = IC_RIGHT (ic);
4163 operand *result = IC_RESULT (ic);
4165 D (emitcode (";", "genDiv ");
4168 /* assign the amsops */
4171 /* special cases first */
4173 if (AOP_TYPE (left) == AOP_CRY &&
4174 AOP_TYPE (right) == AOP_CRY)
4176 genDivbits (left, right, result);
4180 /* if both are of size == 1 */
4181 if (AOP_SIZE (left) == 1 &&
4182 AOP_SIZE (right) == 1)
4184 genDivOneByte (left, right, result);
4188 /* should have been converted to function call */
4191 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4192 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4193 freeAsmop (result, NULL, ic, TRUE);
4196 /*-----------------------------------------------------------------*/
4197 /* genModbits :- modulus of bits */
4198 /*-----------------------------------------------------------------*/
4200 genModbits (operand * left,
4207 /* the result must be bit */
4208 LOAD_AB_FOR_DIV (left, right, l);
4209 emitcode ("div", "ab");
4210 emitcode ("mov", "a,b");
4211 emitcode ("rrc", "a");
4212 aopPut (AOP (result), "c", 0);
4215 /*-----------------------------------------------------------------*/
4216 /* genModOneByte : 8 bit modulus */
4217 /*-----------------------------------------------------------------*/
4219 genModOneByte (operand * left,
4223 sym_link *opetype = operandType (result);
4227 /* signed or unsigned */
4228 if (SPEC_USIGN (opetype))
4230 /* unsigned is easy */
4231 LOAD_AB_FOR_DIV (left, right, l);
4232 emitcode ("div", "ab");
4233 aopPut (AOP (result), "b", 0);
4237 /* signed is a little bit more difficult */
4239 /* save the signs of the operands */
4240 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4243 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4244 emitcode ("push", "acc"); /* save it on the stack */
4246 /* now sign adjust for both left & right */
4247 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4250 lbl = newiTempLabel (NULL);
4251 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4252 emitcode ("cpl", "a");
4253 emitcode ("inc", "a");
4254 emitcode ("", "%05d$:", (lbl->key + 100));
4255 emitcode ("mov", "b,a");
4257 /* sign adjust left side */
4258 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4261 lbl = newiTempLabel (NULL);
4262 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4263 emitcode ("cpl", "a");
4264 emitcode ("inc", "a");
4265 emitcode ("", "%05d$:", (lbl->key + 100));
4267 /* now the multiplication */
4268 emitcode ("nop", "; workaround for DS80C390 div bug.");
4269 emitcode ("div", "ab");
4270 /* we are interested in the lower order
4272 lbl = newiTempLabel (NULL);
4273 emitcode ("pop", "acc");
4274 /* if there was an over flow we don't
4275 adjust the sign of the result */
4276 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4277 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4279 emitcode ("clr", "a");
4280 emitcode ("subb", "a,b");
4281 emitcode ("mov", "b,a");
4282 emitcode ("", "%05d$:", (lbl->key + 100));
4284 /* now we are done */
4285 aopPut (AOP (result), "b", 0);
4289 /*-----------------------------------------------------------------*/
4290 /* genMod - generates code for division */
4291 /*-----------------------------------------------------------------*/
4295 operand *left = IC_LEFT (ic);
4296 operand *right = IC_RIGHT (ic);
4297 operand *result = IC_RESULT (ic);
4299 D (emitcode (";", "genMod ");
4302 /* assign the amsops */
4305 /* special cases first */
4307 if (AOP_TYPE (left) == AOP_CRY &&
4308 AOP_TYPE (right) == AOP_CRY)
4310 genModbits (left, right, result);
4314 /* if both are of size == 1 */
4315 if (AOP_SIZE (left) == 1 &&
4316 AOP_SIZE (right) == 1)
4318 genModOneByte (left, right, result);
4322 /* should have been converted to function call */
4326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4327 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4328 freeAsmop (result, NULL, ic, TRUE);
4331 /*-----------------------------------------------------------------*/
4332 /* genIfxJump :- will create a jump depending on the ifx */
4333 /*-----------------------------------------------------------------*/
4335 genIfxJump (iCode * ic, char *jval)
4338 symbol *tlbl = newiTempLabel (NULL);
4341 D (emitcode (";", "genIfxJump ");
4344 /* if true label then we jump if condition
4348 jlbl = IC_TRUE (ic);
4349 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4350 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4354 /* false label is present */
4355 jlbl = IC_FALSE (ic);
4356 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4357 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4359 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4360 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4362 emitcode (inst, "%05d$", tlbl->key + 100);
4363 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4364 emitcode ("", "%05d$:", tlbl->key + 100);
4366 /* mark the icode as generated */
4370 /*-----------------------------------------------------------------*/
4371 /* genCmp :- greater or less than comparison */
4372 /*-----------------------------------------------------------------*/
4374 genCmp (operand * left, operand * right,
4375 iCode * ic, iCode * ifx, int sign)
4377 int size, offset = 0;
4378 unsigned long lit = 0L;
4381 D (emitcode (";", "genCmp");
4384 result = IC_RESULT (ic);
4386 /* if left & right are bit variables */
4387 if (AOP_TYPE (left) == AOP_CRY &&
4388 AOP_TYPE (right) == AOP_CRY)
4390 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4391 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4395 /* subtract right from left if at the
4396 end the carry flag is set then we know that
4397 left is greater than right */
4398 size = max (AOP_SIZE (left), AOP_SIZE (right));
4400 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4401 if ((size == 1) && !sign &&
4402 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4404 symbol *lbl = newiTempLabel (NULL);
4405 emitcode ("cjne", "%s,%s,%05d$",
4406 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4407 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4409 emitcode ("", "%05d$:", lbl->key + 100);
4413 if (AOP_TYPE (right) == AOP_LIT)
4415 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4416 /* optimize if(x < 0) or if(x >= 0) */
4425 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4427 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4430 aopOp (result, ic, FALSE, FALSE);
4432 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4434 freeAsmop (result, NULL, ic, TRUE);
4435 genIfxJump (ifx, "acc.7");
4440 emitcode ("rlc", "a");
4442 goto release_freedLR;
4450 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4451 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4452 emitcode (";", "genCmp #2");
4453 if (sign && (size == 0))
4455 emitcode (";", "genCmp #3");
4456 emitcode ("xrl", "a,#0x80");
4457 if (AOP_TYPE (right) == AOP_LIT)
4459 unsigned long lit = (unsigned long)
4460 floatFromVal (AOP (right)->aopu.aop_lit);
4461 emitcode (";", "genCmp #3.1");
4462 emitcode ("subb", "a,#0x%02x",
4463 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4467 emitcode (";", "genCmp #3.2");
4468 if (AOP_NEEDSACC (right))
4470 emitcode ("push", "acc");
4472 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4473 FALSE, FALSE, FALSE));
4474 emitcode ("xrl", "b,#0x80");
4475 if (AOP_NEEDSACC (right))
4477 emitcode ("pop", "acc");
4479 emitcode ("subb", "a,b");
4486 emitcode (";", "genCmp #4");
4487 if (AOP_NEEDSACC (right))
4490 emitcode (";", "genCmp #4.1");
4491 emitcode ("xch", "a, b");
4492 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4493 emitcode ("xch", "a, b");
4498 emitcode (";", "genCmp #4.2");
4499 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4502 emitcode ("subb", "a,%s", s);
4509 /* Don't need the left & right operands any more; do need the result. */
4510 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4511 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4513 aopOp (result, ic, FALSE, FALSE);
4517 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4523 /* if the result is used in the next
4524 ifx conditional branch then generate
4525 code a little differently */
4528 genIfxJump (ifx, "c");
4534 /* leave the result in acc */
4536 freeAsmop (result, NULL, ic, TRUE);
4539 /*-----------------------------------------------------------------*/
4540 /* genCmpGt :- greater than comparison */
4541 /*-----------------------------------------------------------------*/
4543 genCmpGt (iCode * ic, iCode * ifx)
4545 operand *left, *right;
4546 sym_link *letype, *retype;
4549 D (emitcode (";", "genCmpGt ");
4552 left = IC_LEFT (ic);
4553 right = IC_RIGHT (ic);
4555 letype = getSpec (operandType (left));
4556 retype = getSpec (operandType (right));
4557 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4559 /* assign the left & right amsops */
4562 genCmp (right, left, ic, ifx, sign);
4565 /*-----------------------------------------------------------------*/
4566 /* genCmpLt - less than comparisons */
4567 /*-----------------------------------------------------------------*/
4569 genCmpLt (iCode * ic, iCode * ifx)
4571 operand *left, *right;
4572 sym_link *letype, *retype;
4575 D (emitcode (";", "genCmpLt "););
4577 left = IC_LEFT (ic);
4578 right = IC_RIGHT (ic);
4580 letype = getSpec (operandType (left));
4581 retype = getSpec (operandType (right));
4582 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4584 /* assign the left & right amsops */
4587 genCmp (left, right, ic, ifx, sign);
4590 /*-----------------------------------------------------------------*/
4591 /* gencjneshort - compare and jump if not equal */
4592 /*-----------------------------------------------------------------*/
4594 gencjneshort (operand * left, operand * right, symbol * lbl)
4596 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4598 unsigned long lit = 0L;
4600 D (emitcode (";", "gencjneshort");
4603 /* if the left side is a literal or
4604 if the right is in a pointer register and left
4606 if ((AOP_TYPE (left) == AOP_LIT) ||
4607 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4614 if (AOP_TYPE (right) == AOP_LIT)
4615 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4617 if (opIsGptr (left) || opIsGptr (right))
4619 /* We are comparing a generic pointer to something.
4620 * Exclude the generic type byte from the comparison.
4623 D (emitcode (";", "cjneshort: generic ptr special case.");
4628 /* if the right side is a literal then anything goes */
4629 if (AOP_TYPE (right) == AOP_LIT &&
4630 AOP_TYPE (left) != AOP_DIR)
4634 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4636 emitcode ("cjne", "a,%s,%05d$",
4637 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4643 /* if the right side is in a register or in direct space or
4644 if the left is a pointer register & right is not */
4645 else if (AOP_TYPE (right) == AOP_REG ||
4646 AOP_TYPE (right) == AOP_DIR ||
4647 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4648 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4652 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4653 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4654 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4655 emitcode ("jnz", "%05d$", lbl->key + 100);
4657 emitcode ("cjne", "a,%s,%05d$",
4658 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4665 /* right is a pointer reg need both a & b */
4668 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4669 if (strcmp (l, "b"))
4670 emitcode ("mov", "b,%s", l);
4671 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4672 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4678 /*-----------------------------------------------------------------*/
4679 /* gencjne - compare and jump if not equal */
4680 /*-----------------------------------------------------------------*/
4682 gencjne (operand * left, operand * right, symbol * lbl)
4684 symbol *tlbl = newiTempLabel (NULL);
4686 D (emitcode (";", "gencjne");
4689 gencjneshort (left, right, lbl);
4691 emitcode ("mov", "a,%s", one);
4692 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4693 emitcode ("", "%05d$:", lbl->key + 100);
4694 emitcode ("clr", "a");
4695 emitcode ("", "%05d$:", tlbl->key + 100);
4698 /*-----------------------------------------------------------------*/
4699 /* genCmpEq - generates code for equal to */
4700 /*-----------------------------------------------------------------*/
4702 genCmpEq (iCode * ic, iCode * ifx)
4704 operand *left, *right, *result;
4706 D (emitcode (";", "genCmpEq ");
4710 AOP_SET_LOCALS (ic);
4712 /* if literal, literal on the right or
4713 if the right is in a pointer register and left
4715 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4716 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4718 operand *t = IC_RIGHT (ic);
4719 IC_RIGHT (ic) = IC_LEFT (ic);
4723 if (ifx && /* !AOP_SIZE(result) */
4724 OP_SYMBOL (result) &&
4725 OP_SYMBOL (result)->regType == REG_CND)
4728 /* if they are both bit variables */
4729 if (AOP_TYPE (left) == AOP_CRY &&
4730 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4732 if (AOP_TYPE (right) == AOP_LIT)
4734 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4737 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4738 emitcode ("cpl", "c");
4742 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4746 emitcode ("clr", "c");
4748 /* AOP_TYPE(right) == AOP_CRY */
4752 symbol *lbl = newiTempLabel (NULL);
4753 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4754 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4755 emitcode ("cpl", "c");
4756 emitcode ("", "%05d$:", (lbl->key + 100));
4758 /* if true label then we jump if condition
4760 tlbl = newiTempLabel (NULL);
4763 emitcode ("jnc", "%05d$", tlbl->key + 100);
4764 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4768 emitcode ("jc", "%05d$", tlbl->key + 100);
4769 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4771 emitcode ("", "%05d$:", tlbl->key + 100);
4775 tlbl = newiTempLabel (NULL);
4776 gencjneshort (left, right, tlbl);
4779 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4780 emitcode ("", "%05d$:", tlbl->key + 100);
4784 symbol *lbl = newiTempLabel (NULL);
4785 emitcode ("sjmp", "%05d$", lbl->key + 100);
4786 emitcode ("", "%05d$:", tlbl->key + 100);
4787 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4788 emitcode ("", "%05d$:", lbl->key + 100);
4791 /* mark the icode as generated */
4794 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4799 /* if they are both bit variables */
4800 if (AOP_TYPE (left) == AOP_CRY &&
4801 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4803 if (AOP_TYPE (right) == AOP_LIT)
4805 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4808 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4809 emitcode ("cpl", "c");
4813 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4817 emitcode ("clr", "c");
4819 /* AOP_TYPE(right) == AOP_CRY */
4823 symbol *lbl = newiTempLabel (NULL);
4824 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4825 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4826 emitcode ("cpl", "c");
4827 emitcode ("", "%05d$:", (lbl->key + 100));
4830 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4831 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4833 aopOp (result, ic, TRUE, FALSE);
4836 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4843 genIfxJump (ifx, "c");
4846 /* if the result is used in an arithmetic operation
4847 then put the result in place */
4852 gencjne (left, right, newiTempLabel (NULL));
4854 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4855 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4857 aopOp (result, ic, TRUE, FALSE);
4859 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4861 aopPut (AOP (result), "a", 0);
4866 genIfxJump (ifx, "a");
4869 /* if the result is used in an arithmetic operation
4870 then put the result in place */
4871 if (AOP_TYPE (result) != AOP_CRY)
4873 /* leave the result in acc */
4877 freeAsmop (result, NULL, ic, TRUE);
4880 /*-----------------------------------------------------------------*/
4881 /* ifxForOp - returns the icode containing the ifx for operand */
4882 /*-----------------------------------------------------------------*/
4884 ifxForOp (operand * op, iCode * ic)
4886 /* if true symbol then needs to be assigned */
4887 if (IS_TRUE_SYMOP (op))
4890 /* if this has register type condition and
4891 the next instruction is ifx with the same operand
4892 and live to of the operand is upto the ifx only then */
4894 ic->next->op == IFX &&
4895 IC_COND (ic->next)->key == op->key &&
4896 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4901 /*-----------------------------------------------------------------*/
4902 /* genAndOp - for && operation */
4903 /*-----------------------------------------------------------------*/
4905 genAndOp (iCode * ic)
4907 operand *left, *right, *result;
4910 D (emitcode (";", "genAndOp "););
4912 /* note here that && operations that are in an
4913 if statement are taken away by backPatchLabels
4914 only those used in arthmetic operations remain */
4916 AOP_SET_LOCALS (ic);
4918 /* if both are bit variables */
4919 if (AOP_TYPE (left) == AOP_CRY &&
4920 AOP_TYPE (right) == AOP_CRY)
4922 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4923 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4924 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4927 aopOp (result,ic,FALSE, FALSE);
4932 tlbl = newiTempLabel (NULL);
4934 emitcode ("jz", "%05d$", tlbl->key + 100);
4936 emitcode ("", "%05d$:", tlbl->key + 100);
4937 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4940 aopOp (result,ic,FALSE, FALSE);
4943 freeAsmop (result, NULL, ic, TRUE);
4947 /*-----------------------------------------------------------------*/
4948 /* genOrOp - for || operation */
4949 /*-----------------------------------------------------------------*/
4951 genOrOp (iCode * ic)
4953 operand *left, *right, *result;
4956 D (emitcode (";", "genOrOp "););
4958 /* note here that || operations that are in an
4959 if statement are taken away by backPatchLabels
4960 only those used in arthmetic operations remain */
4962 AOP_SET_LOCALS (ic);
4964 /* if both are bit variables */
4965 if (AOP_TYPE (left) == AOP_CRY &&
4966 AOP_TYPE (right) == AOP_CRY)
4968 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4969 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4970 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4971 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4973 aopOp (result,ic,FALSE, FALSE);
4979 tlbl = newiTempLabel (NULL);
4981 emitcode ("jnz", "%05d$", tlbl->key + 100);
4983 emitcode ("", "%05d$:", tlbl->key + 100);
4984 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4985 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4987 aopOp (result,ic,FALSE, FALSE);
4992 freeAsmop (result, NULL, ic, TRUE);
4995 /*-----------------------------------------------------------------*/
4996 /* isLiteralBit - test if lit == 2^n */
4997 /*-----------------------------------------------------------------*/
4999 isLiteralBit (unsigned long lit)
5001 unsigned long pw[32] =
5002 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5003 0x100L, 0x200L, 0x400L, 0x800L,
5004 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5005 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5006 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5007 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5008 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5011 for (idx = 0; idx < 32; idx++)
5017 /*-----------------------------------------------------------------*/
5018 /* continueIfTrue - */
5019 /*-----------------------------------------------------------------*/
5021 continueIfTrue (iCode * ic)
5024 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5028 /*-----------------------------------------------------------------*/
5030 /*-----------------------------------------------------------------*/
5032 jumpIfTrue (iCode * ic)
5035 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5039 /*-----------------------------------------------------------------*/
5040 /* jmpTrueOrFalse - */
5041 /*-----------------------------------------------------------------*/
5043 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5045 // ugly but optimized by peephole
5048 symbol *nlbl = newiTempLabel (NULL);
5049 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5050 emitcode ("", "%05d$:", tlbl->key + 100);
5051 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5052 emitcode ("", "%05d$:", nlbl->key + 100);
5056 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5057 emitcode ("", "%05d$:", tlbl->key + 100);
5062 // Generate code to perform a bit-wise logic operation
5063 // on two operands in far space (assumed to already have been
5064 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5065 // in far space. This requires pushing the result on the stack
5066 // then popping it into the result.
5068 genFarFarLogicOp(iCode *ic, char *logicOp)
5070 int size, resultSize, compSize;
5073 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5074 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5075 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5077 _startLazyDPSEvaluation();
5078 for (size = compSize; (size--); offset++)
5080 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5081 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5082 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5084 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5085 emitcode ("push", "acc");
5087 _endLazyDPSEvaluation();
5089 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5090 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5091 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5093 resultSize = AOP_SIZE(IC_RESULT(ic));
5095 ADJUST_PUSHED_RESULT(compSize, resultSize);
5097 _startLazyDPSEvaluation();
5100 emitcode ("pop", "acc");
5101 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5103 _endLazyDPSEvaluation();
5104 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5108 /*-----------------------------------------------------------------*/
5109 /* genAnd - code for and */
5110 /*-----------------------------------------------------------------*/
5112 genAnd (iCode * ic, iCode * ifx)
5114 operand *left, *right, *result;
5115 int size, offset = 0;
5116 unsigned long lit = 0L;
5121 D (emitcode (";", "genAnd "););
5123 AOP_OP_3_NOFATAL (ic, pushResult);
5124 AOP_SET_LOCALS (ic);
5128 genFarFarLogicOp(ic, "anl");
5133 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5135 AOP_TYPE (left), AOP_TYPE (right));
5136 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5138 AOP_SIZE (left), AOP_SIZE (right));
5141 /* if left is a literal & right is not then exchange them */
5142 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5143 AOP_NEEDSACC (left))
5145 operand *tmp = right;
5150 /* if result = right then exchange them */
5151 if (sameRegs (AOP (result), AOP (right)))
5153 operand *tmp = right;
5158 /* if right is bit then exchange them */
5159 if (AOP_TYPE (right) == AOP_CRY &&
5160 AOP_TYPE (left) != AOP_CRY)
5162 operand *tmp = right;
5166 if (AOP_TYPE (right) == AOP_LIT)
5167 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5169 size = AOP_SIZE (result);
5172 // result = bit & yy;
5173 if (AOP_TYPE (left) == AOP_CRY)
5175 // c = bit & literal;
5176 if (AOP_TYPE (right) == AOP_LIT)
5180 if (size && sameRegs (AOP (result), AOP (left)))
5183 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5188 if (size && (AOP_TYPE (result) == AOP_CRY))
5190 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5193 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5198 emitcode ("clr", "c");
5203 if (AOP_TYPE (right) == AOP_CRY)
5206 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5207 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5212 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5214 emitcode ("rrc", "a");
5215 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5223 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5224 genIfxJump (ifx, "c");
5228 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5229 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5230 if ((AOP_TYPE (right) == AOP_LIT) &&
5231 (AOP_TYPE (result) == AOP_CRY) &&
5232 (AOP_TYPE (left) != AOP_CRY))
5234 int posbit = isLiteralBit (lit);
5239 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5242 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5248 sprintf (buffer, "acc.%d", posbit & 0x07);
5249 genIfxJump (ifx, buffer);
5256 symbol *tlbl = newiTempLabel (NULL);
5257 int sizel = AOP_SIZE (left);
5259 emitcode ("setb", "c");
5262 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5264 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5266 if ((posbit = isLiteralBit (bytelit)) != 0)
5267 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5270 if (bytelit != 0x0FFL)
5271 emitcode ("anl", "a,%s",
5272 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5273 emitcode ("jnz", "%05d$", tlbl->key + 100);
5278 // bit = left & literal
5281 emitcode ("clr", "c");
5282 emitcode ("", "%05d$:", tlbl->key + 100);
5284 // if(left & literal)
5288 jmpTrueOrFalse (ifx, tlbl);
5296 /* if left is same as result */
5297 if (sameRegs (AOP (result), AOP (left)))
5299 for (; size--; offset++)
5301 if (AOP_TYPE (right) == AOP_LIT)
5303 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5305 else if (bytelit == 0)
5306 aopPut (AOP (result), zero, offset);
5307 else if (IS_AOP_PREG (result))
5309 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5310 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5311 aopPut (AOP (result), "a", offset);
5314 emitcode ("anl", "%s,%s",
5315 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5316 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5320 if (AOP_TYPE (left) == AOP_ACC)
5321 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5324 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5325 if (IS_AOP_PREG (result))
5327 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5328 aopPut (AOP (result), "a", offset);
5332 emitcode ("anl", "%s,a",
5333 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5340 // left & result in different registers
5341 if (AOP_TYPE (result) == AOP_CRY)
5344 // if(size), result in bit
5345 // if(!size && ifx), conditional oper: if(left & right)
5346 symbol *tlbl = newiTempLabel (NULL);
5347 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5349 emitcode ("setb", "c");
5352 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5353 emitcode ("anl", "a,%s",
5354 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5356 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5357 emitcode ("anl", "a,%s",
5358 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5360 emitcode ("jnz", "%05d$", tlbl->key + 100);
5366 emitcode ("", "%05d$:", tlbl->key + 100);
5370 jmpTrueOrFalse (ifx, tlbl);
5374 for (; (size--); offset++)
5377 // result = left & right
5378 if (AOP_TYPE (right) == AOP_LIT)
5380 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5382 aopPut (AOP (result),
5383 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5387 else if (bytelit == 0)
5389 aopPut (AOP (result), zero, offset);
5392 D (emitcode (";", "better literal AND.");
5394 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5395 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5396 FALSE, FALSE, FALSE));
5401 // faster than result <- left, anl result,right
5402 // and better if result is SFR
5403 if (AOP_TYPE (left) == AOP_ACC)
5405 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5406 FALSE, FALSE, FALSE));
5410 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5411 emitcode ("anl", "a,%s",
5412 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5415 aopPut (AOP (result), "a", offset);
5421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5423 freeAsmop (result, NULL, ic, TRUE);
5427 /*-----------------------------------------------------------------*/
5428 /* genOr - code for or */
5429 /*-----------------------------------------------------------------*/
5431 genOr (iCode * ic, iCode * ifx)
5433 operand *left, *right, *result;
5434 int size, offset = 0;
5435 unsigned long lit = 0L;
5438 D (emitcode (";", "genOr "););
5440 AOP_OP_3_NOFATAL (ic, pushResult);
5441 AOP_SET_LOCALS (ic);
5445 genFarFarLogicOp(ic, "orl");
5451 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5453 AOP_TYPE (left), AOP_TYPE (right));
5454 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5456 AOP_SIZE (left), AOP_SIZE (right));
5459 /* if left is a literal & right is not then exchange them */
5460 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5461 AOP_NEEDSACC (left))
5463 operand *tmp = right;
5468 /* if result = right then exchange them */
5469 if (sameRegs (AOP (result), AOP (right)))
5471 operand *tmp = right;
5476 /* if right is bit then exchange them */
5477 if (AOP_TYPE (right) == AOP_CRY &&
5478 AOP_TYPE (left) != AOP_CRY)
5480 operand *tmp = right;
5484 if (AOP_TYPE (right) == AOP_LIT)
5485 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5487 size = AOP_SIZE (result);
5491 if (AOP_TYPE (left) == AOP_CRY)
5493 if (AOP_TYPE (right) == AOP_LIT)
5495 // c = bit & literal;
5498 // lit != 0 => result = 1
5499 if (AOP_TYPE (result) == AOP_CRY)
5502 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5504 continueIfTrue (ifx);
5507 emitcode ("setb", "c");
5511 // lit == 0 => result = left
5512 if (size && sameRegs (AOP (result), AOP (left)))
5514 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5519 if (AOP_TYPE (right) == AOP_CRY)
5522 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5523 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5528 symbol *tlbl = newiTempLabel (NULL);
5529 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5530 emitcode ("setb", "c");
5531 emitcode ("jb", "%s,%05d$",
5532 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5534 emitcode ("jnz", "%05d$", tlbl->key + 100);
5535 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5537 jmpTrueOrFalse (ifx, tlbl);
5543 emitcode ("", "%05d$:", tlbl->key + 100);
5552 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5553 genIfxJump (ifx, "c");
5557 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5558 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5559 if ((AOP_TYPE (right) == AOP_LIT) &&
5560 (AOP_TYPE (result) == AOP_CRY) &&
5561 (AOP_TYPE (left) != AOP_CRY))
5567 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5569 continueIfTrue (ifx);
5574 // lit = 0, result = boolean(left)
5576 emitcode ("setb", "c");
5580 symbol *tlbl = newiTempLabel (NULL);
5581 emitcode ("jnz", "%05d$", tlbl->key + 100);
5583 emitcode ("", "%05d$:", tlbl->key + 100);
5587 genIfxJump (ifx, "a");
5595 /* if left is same as result */
5596 if (sameRegs (AOP (result), AOP (left)))
5598 for (; size--; offset++)
5600 if (AOP_TYPE (right) == AOP_LIT)
5602 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5608 if (IS_AOP_PREG (left))
5610 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5611 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5612 aopPut (AOP (result), "a", offset);
5616 emitcode ("orl", "%s,%s",
5617 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5618 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5624 if (AOP_TYPE (left) == AOP_ACC)
5626 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5630 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5631 if (IS_AOP_PREG (left))
5633 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5634 aopPut (AOP (result), "a", offset);
5638 emitcode ("orl", "%s,a",
5639 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5647 // left & result in different registers
5648 if (AOP_TYPE (result) == AOP_CRY)
5651 // if(size), result in bit
5652 // if(!size && ifx), conditional oper: if(left | right)
5653 symbol *tlbl = newiTempLabel (NULL);
5654 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5656 emitcode ("setb", "c");
5659 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5660 emitcode ("orl", "a,%s",
5661 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5663 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5664 emitcode ("orl", "a,%s",
5665 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5667 emitcode ("jnz", "%05d$", tlbl->key + 100);
5673 emitcode ("", "%05d$:", tlbl->key + 100);
5677 jmpTrueOrFalse (ifx, tlbl);
5681 for (; (size--); offset++)
5684 // result = left & right
5685 if (AOP_TYPE (right) == AOP_LIT)
5687 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5689 aopPut (AOP (result),
5690 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5694 D (emitcode (";", "better literal OR.");
5696 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5697 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5698 FALSE, FALSE, FALSE));
5703 // faster than result <- left, anl result,right
5704 // and better if result is SFR
5705 if (AOP_TYPE (left) == AOP_ACC)
5707 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5708 FALSE, FALSE, FALSE));
5712 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5713 emitcode ("orl", "a,%s",
5714 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5717 aopPut (AOP (result), "a", offset);
5723 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5724 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5725 freeAsmop (result, NULL, ic, TRUE);
5728 /*-----------------------------------------------------------------*/
5729 /* genXor - code for xclusive or */
5730 /*-----------------------------------------------------------------*/
5732 genXor (iCode * ic, iCode * ifx)
5734 operand *left, *right, *result;
5735 int size, offset = 0;
5736 unsigned long lit = 0L;
5739 D (emitcode (";", "genXor "););
5741 AOP_OP_3_NOFATAL (ic, pushResult);
5742 AOP_SET_LOCALS (ic);
5746 genFarFarLogicOp(ic, "xrl");
5751 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5753 AOP_TYPE (left), AOP_TYPE (right));
5754 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5756 AOP_SIZE (left), AOP_SIZE (right));
5759 /* if left is a literal & right is not ||
5760 if left needs acc & right does not */
5761 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5762 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5764 operand *tmp = right;
5769 /* if result = right then exchange them */
5770 if (sameRegs (AOP (result), AOP (right)))
5772 operand *tmp = right;
5777 /* if right is bit then exchange them */
5778 if (AOP_TYPE (right) == AOP_CRY &&
5779 AOP_TYPE (left) != AOP_CRY)
5781 operand *tmp = right;
5785 if (AOP_TYPE (right) == AOP_LIT)
5786 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5788 size = AOP_SIZE (result);
5792 if (AOP_TYPE (left) == AOP_CRY)
5794 if (AOP_TYPE (right) == AOP_LIT)
5796 // c = bit & literal;
5799 // lit>>1 != 0 => result = 1
5800 if (AOP_TYPE (result) == AOP_CRY)
5803 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5805 continueIfTrue (ifx);
5808 emitcode ("setb", "c");
5815 // lit == 0, result = left
5816 if (size && sameRegs (AOP (result), AOP (left)))
5818 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5822 // lit == 1, result = not(left)
5823 if (size && sameRegs (AOP (result), AOP (left)))
5825 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5830 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5831 emitcode ("cpl", "c");
5840 symbol *tlbl = newiTempLabel (NULL);
5841 if (AOP_TYPE (right) == AOP_CRY)
5844 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5848 int sizer = AOP_SIZE (right);
5850 // if val>>1 != 0, result = 1
5851 emitcode ("setb", "c");
5854 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5856 // test the msb of the lsb
5857 emitcode ("anl", "a,#0xfe");
5858 emitcode ("jnz", "%05d$", tlbl->key + 100);
5862 emitcode ("rrc", "a");
5864 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5865 emitcode ("cpl", "c");
5866 emitcode ("", "%05d$:", (tlbl->key + 100));
5873 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5874 genIfxJump (ifx, "c");
5878 if (sameRegs (AOP (result), AOP (left)))
5880 /* if left is same as result */
5881 for (; size--; offset++)
5883 if (AOP_TYPE (right) == AOP_LIT)
5885 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5887 else if (IS_AOP_PREG (left))
5889 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5890 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5891 aopPut (AOP (result), "a", offset);
5894 emitcode ("xrl", "%s,%s",
5895 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5896 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5900 if (AOP_TYPE (left) == AOP_ACC)
5901 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5904 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5905 if (IS_AOP_PREG (left))
5907 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5908 aopPut (AOP (result), "a", offset);
5911 emitcode ("xrl", "%s,a",
5912 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5919 // left & result in different registers
5920 if (AOP_TYPE (result) == AOP_CRY)
5923 // if(size), result in bit
5924 // if(!size && ifx), conditional oper: if(left ^ right)
5925 symbol *tlbl = newiTempLabel (NULL);
5926 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5928 emitcode ("setb", "c");
5931 if ((AOP_TYPE (right) == AOP_LIT) &&
5932 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5934 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5938 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5939 emitcode ("xrl", "a,%s",
5940 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5942 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5943 emitcode ("xrl", "a,%s",
5944 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5947 emitcode ("jnz", "%05d$", tlbl->key + 100);
5953 emitcode ("", "%05d$:", tlbl->key + 100);
5957 jmpTrueOrFalse (ifx, tlbl);
5960 for (; (size--); offset++)
5963 // result = left & right
5964 if (AOP_TYPE (right) == AOP_LIT)
5966 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5968 aopPut (AOP (result),
5969 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5973 D (emitcode (";", "better literal XOR.");
5975 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5976 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5977 FALSE, FALSE, FALSE));
5981 // faster than result <- left, anl result,right
5982 // and better if result is SFR
5983 if (AOP_TYPE (left) == AOP_ACC)
5985 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5986 FALSE, FALSE, FALSE));
5990 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5991 emitcode ("xrl", "a,%s",
5992 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5995 aopPut (AOP (result), "a", offset);
6000 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6002 freeAsmop (result, NULL, ic, TRUE);
6005 /*-----------------------------------------------------------------*/
6006 /* genInline - write the inline code out */
6007 /*-----------------------------------------------------------------*/
6009 genInline (iCode * ic)
6011 char *buffer, *bp, *bp1;
6013 D (emitcode (";", "genInline ");
6016 _G.inLine += (!options.asmpeep);
6018 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6019 strcpy (buffer, IC_INLINE (ic));
6021 /* emit each line as a code */
6046 /* emitcode("",buffer); */
6047 _G.inLine -= (!options.asmpeep);
6050 /*-----------------------------------------------------------------*/
6051 /* genRRC - rotate right with carry */
6052 /*-----------------------------------------------------------------*/
6056 operand *left, *result;
6057 int size, offset = 0;
6060 D (emitcode (";", "genRRC ");
6063 /* rotate right with carry */
6064 left = IC_LEFT (ic);
6065 result = IC_RESULT (ic);
6066 aopOp (left, ic, FALSE, FALSE);
6067 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6069 /* move it to the result */
6070 size = AOP_SIZE (result);
6074 _startLazyDPSEvaluation ();
6077 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6079 emitcode ("rrc", "a");
6080 if (AOP_SIZE (result) > 1)
6081 aopPut (AOP (result), "a", offset--);
6083 _endLazyDPSEvaluation ();
6085 /* now we need to put the carry into the
6086 highest order byte of the result */
6087 if (AOP_SIZE (result) > 1)
6089 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6092 emitcode ("mov", "acc.7,c");
6093 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6094 freeAsmop (left, NULL, ic, TRUE);
6095 freeAsmop (result, NULL, ic, TRUE);
6098 /*-----------------------------------------------------------------*/
6099 /* genRLC - generate code for rotate left with carry */
6100 /*-----------------------------------------------------------------*/
6104 operand *left, *result;
6105 int size, offset = 0;
6108 D (emitcode (";", "genRLC ");
6111 /* rotate right with carry */
6112 left = IC_LEFT (ic);
6113 result = IC_RESULT (ic);
6114 aopOp (left, ic, FALSE, FALSE);
6115 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6117 /* move it to the result */
6118 size = AOP_SIZE (result);
6122 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6124 emitcode ("add", "a,acc");
6125 if (AOP_SIZE (result) > 1)
6127 aopPut (AOP (result), "a", offset++);
6130 _startLazyDPSEvaluation ();
6133 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6135 emitcode ("rlc", "a");
6136 if (AOP_SIZE (result) > 1)
6137 aopPut (AOP (result), "a", offset++);
6139 _endLazyDPSEvaluation ();
6141 /* now we need to put the carry into the
6142 highest order byte of the result */
6143 if (AOP_SIZE (result) > 1)
6145 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6148 emitcode ("mov", "acc.0,c");
6149 aopPut (AOP (result), "a", 0);
6150 freeAsmop (left, NULL, ic, TRUE);
6151 freeAsmop (result, NULL, ic, TRUE);
6154 /*-----------------------------------------------------------------*/
6155 /* genGetHbit - generates code get highest order bit */
6156 /*-----------------------------------------------------------------*/
6158 genGetHbit (iCode * ic)
6160 operand *left, *result;
6161 left = IC_LEFT (ic);
6162 result = IC_RESULT (ic);
6163 aopOp (left, ic, FALSE, FALSE);
6164 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6166 D (emitcode (";", "genGetHbit ");
6169 /* get the highest order byte into a */
6170 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6171 if (AOP_TYPE (result) == AOP_CRY)
6173 emitcode ("rlc", "a");
6178 emitcode ("rl", "a");
6179 emitcode ("anl", "a,#0x01");
6184 freeAsmop (left, NULL, ic, TRUE);
6185 freeAsmop (result, NULL, ic, TRUE);
6188 /*-----------------------------------------------------------------*/
6189 /* AccRol - rotate left accumulator by known count */
6190 /*-----------------------------------------------------------------*/
6192 AccRol (int shCount)
6194 shCount &= 0x0007; // shCount : 0..7
6201 emitcode ("rl", "a");
6204 emitcode ("rl", "a");
6205 emitcode ("rl", "a");
6208 emitcode ("swap", "a");
6209 emitcode ("rr", "a");
6212 emitcode ("swap", "a");
6215 emitcode ("swap", "a");
6216 emitcode ("rl", "a");
6219 emitcode ("rr", "a");
6220 emitcode ("rr", "a");
6223 emitcode ("rr", "a");
6228 /*-----------------------------------------------------------------*/
6229 /* AccLsh - left shift accumulator by known count */
6230 /*-----------------------------------------------------------------*/
6232 AccLsh (int shCount)
6237 emitcode ("add", "a,acc");
6238 else if (shCount == 2)
6240 emitcode ("add", "a,acc");
6241 emitcode ("add", "a,acc");
6245 /* rotate left accumulator */
6247 /* and kill the lower order bits */
6248 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6253 /*-----------------------------------------------------------------*/
6254 /* AccRsh - right shift accumulator by known count */
6255 /*-----------------------------------------------------------------*/
6257 AccRsh (int shCount)
6264 emitcode ("rrc", "a");
6268 /* rotate right accumulator */
6269 AccRol (8 - shCount);
6270 /* and kill the higher order bits */
6271 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6276 #ifdef BETTER_LITERAL_SHIFT
6277 /*-----------------------------------------------------------------*/
6278 /* AccSRsh - signed right shift accumulator by known count */
6279 /*-----------------------------------------------------------------*/
6281 AccSRsh (int shCount)
6288 emitcode ("mov", "c,acc.7");
6289 emitcode ("rrc", "a");
6291 else if (shCount == 2)
6293 emitcode ("mov", "c,acc.7");
6294 emitcode ("rrc", "a");
6295 emitcode ("mov", "c,acc.7");
6296 emitcode ("rrc", "a");
6300 tlbl = newiTempLabel (NULL);
6301 /* rotate right accumulator */
6302 AccRol (8 - shCount);
6303 /* and kill the higher order bits */
6304 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6305 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6306 emitcode ("orl", "a,#0x%02x",
6307 (unsigned char) ~SRMask[shCount]);
6308 emitcode ("", "%05d$:", tlbl->key + 100);
6314 #ifdef BETTER_LITERAL_SHIFT
6315 /*-----------------------------------------------------------------*/
6316 /* shiftR1Left2Result - shift right one byte from left to result */
6317 /*-----------------------------------------------------------------*/
6319 shiftR1Left2Result (operand * left, int offl,
6320 operand * result, int offr,
6321 int shCount, int sign)
6323 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6324 /* shift right accumulator */
6329 aopPut (AOP (result), "a", offr);
6333 #ifdef BETTER_LITERAL_SHIFT
6334 /*-----------------------------------------------------------------*/
6335 /* shiftL1Left2Result - shift left one byte from left to result */
6336 /*-----------------------------------------------------------------*/
6338 shiftL1Left2Result (operand * left, int offl,
6339 operand * result, int offr, int shCount)
6341 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6342 /* shift left accumulator */
6344 aopPut (AOP (result), "a", offr);
6348 #ifdef BETTER_LITERAL_SHIFT
6349 /*-----------------------------------------------------------------*/
6350 /* movLeft2Result - move byte from left to result */
6351 /*-----------------------------------------------------------------*/
6353 movLeft2Result (operand * left, int offl,
6354 operand * result, int offr, int sign)
6357 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6359 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6361 if (*l == '@' && (IS_AOP_PREG (result)))
6363 emitcode ("mov", "a,%s", l);
6364 aopPut (AOP (result), "a", offr);
6370 aopPut (AOP (result), l, offr);
6374 /* MSB sign in acc.7 ! */
6375 if (getDataSize (left) == offl + 1)
6377 emitcode ("mov", "a,%s", l);
6378 aopPut (AOP (result), "a", offr);
6386 #ifdef BETTER_LITERAL_SHIFT
6387 /*-----------------------------------------------------------------*/
6388 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6389 /*-----------------------------------------------------------------*/
6393 emitcode ("rrc", "a");
6394 emitcode ("xch", "a,%s", x);
6395 emitcode ("rrc", "a");
6396 emitcode ("xch", "a,%s", x);
6400 #ifdef BETTER_LITERAL_SHIFT
6402 /*-----------------------------------------------------------------*/
6403 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6404 /*-----------------------------------------------------------------*/
6408 emitcode ("xch", "a,%s", x);
6409 emitcode ("rlc", "a");
6410 emitcode ("xch", "a,%s", x);
6411 emitcode ("rlc", "a");
6415 #ifdef BETTER_LITERAL_SHIFT
6416 /*-----------------------------------------------------------------*/
6417 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6418 /*-----------------------------------------------------------------*/
6422 emitcode ("xch", "a,%s", x);
6423 emitcode ("add", "a,acc");
6424 emitcode ("xch", "a,%s", x);
6425 emitcode ("rlc", "a");
6429 #ifdef BETTER_LITERAL_SHIFT
6430 /*-----------------------------------------------------------------*/
6431 /* AccAXLsh - left shift a:x by known count (0..7) */
6432 /*-----------------------------------------------------------------*/
6434 AccAXLsh (char *x, int shCount)
6449 case 5: // AAAAABBB:CCCCCDDD
6451 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6453 emitcode ("anl", "a,#0x%02x",
6454 SLMask[shCount]); // BBB00000:CCCCCDDD
6456 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6458 AccRol (shCount); // DDDCCCCC:BBB00000
6460 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6462 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6464 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6466 emitcode ("anl", "a,#0x%02x",
6467 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6469 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6471 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6474 case 6: // AAAAAABB:CCCCCCDD
6475 emitcode ("anl", "a,#0x%02x",
6476 SRMask[shCount]); // 000000BB:CCCCCCDD
6477 emitcode ("mov", "c,acc.0"); // c = B
6478 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6480 AccAXRrl1 (x); // BCCCCCCD:D000000B
6481 AccAXRrl1 (x); // BBCCCCCC:DD000000
6483 emitcode("rrc","a");
6484 emitcode("xch","a,%s", x);
6485 emitcode("rrc","a");
6486 emitcode("mov","c,acc.0"); //<< get correct bit
6487 emitcode("xch","a,%s", x);
6489 emitcode("rrc","a");
6490 emitcode("xch","a,%s", x);
6491 emitcode("rrc","a");
6492 emitcode("xch","a,%s", x);
6495 case 7: // a:x <<= 7
6497 emitcode ("anl", "a,#0x%02x",
6498 SRMask[shCount]); // 0000000B:CCCCCCCD
6500 emitcode ("mov", "c,acc.0"); // c = B
6502 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6504 AccAXRrl1 (x); // BCCCCCCC:D0000000
6513 #ifdef BETTER_LITERAL_SHIFT
6515 /*-----------------------------------------------------------------*/
6516 /* AccAXRsh - right shift a:x known count (0..7) */
6517 /*-----------------------------------------------------------------*/
6519 AccAXRsh (char *x, int shCount)
6527 AccAXRrl1 (x); // 0->a:x
6532 AccAXRrl1 (x); // 0->a:x
6535 AccAXRrl1 (x); // 0->a:x
6540 case 5: // AAAAABBB:CCCCCDDD = a:x
6542 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6544 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6546 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6548 emitcode ("anl", "a,#0x%02x",
6549 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6551 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6553 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6555 emitcode ("anl", "a,#0x%02x",
6556 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6558 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6560 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6562 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6565 case 6: // AABBBBBB:CCDDDDDD
6567 emitcode ("mov", "c,acc.7");
6568 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6570 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6572 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6574 emitcode ("anl", "a,#0x%02x",
6575 SRMask[shCount]); // 000000AA:BBBBBBCC
6578 case 7: // ABBBBBBB:CDDDDDDD
6580 emitcode ("mov", "c,acc.7"); // c = A
6582 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6584 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6586 emitcode ("anl", "a,#0x%02x",
6587 SRMask[shCount]); // 0000000A:BBBBBBBC
6596 #ifdef BETTER_LITERAL_SHIFT
6598 /*-----------------------------------------------------------------*/
6599 /* AccAXRshS - right shift signed a:x known count (0..7) */
6600 /*-----------------------------------------------------------------*/
6602 AccAXRshS (char *x, int shCount)
6610 emitcode ("mov", "c,acc.7");
6611 AccAXRrl1 (x); // s->a:x
6615 emitcode ("mov", "c,acc.7");
6616 AccAXRrl1 (x); // s->a:x
6618 emitcode ("mov", "c,acc.7");
6619 AccAXRrl1 (x); // s->a:x
6624 case 5: // AAAAABBB:CCCCCDDD = a:x
6626 tlbl = newiTempLabel (NULL);
6627 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6629 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6631 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6633 emitcode ("anl", "a,#0x%02x",
6634 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6636 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6638 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6640 emitcode ("anl", "a,#0x%02x",
6641 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6643 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6645 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6647 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6649 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6650 emitcode ("orl", "a,#0x%02x",
6651 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6653 emitcode ("", "%05d$:", tlbl->key + 100);
6654 break; // SSSSAAAA:BBBCCCCC
6656 case 6: // AABBBBBB:CCDDDDDD
6658 tlbl = newiTempLabel (NULL);
6659 emitcode ("mov", "c,acc.7");
6660 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6662 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6664 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6666 emitcode ("anl", "a,#0x%02x",
6667 SRMask[shCount]); // 000000AA:BBBBBBCC
6669 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6670 emitcode ("orl", "a,#0x%02x",
6671 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6673 emitcode ("", "%05d$:", tlbl->key + 100);
6675 case 7: // ABBBBBBB:CDDDDDDD
6677 tlbl = newiTempLabel (NULL);
6678 emitcode ("mov", "c,acc.7"); // c = A
6680 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6682 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6684 emitcode ("anl", "a,#0x%02x",
6685 SRMask[shCount]); // 0000000A:BBBBBBBC
6687 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6688 emitcode ("orl", "a,#0x%02x",
6689 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6691 emitcode ("", "%05d$:", tlbl->key + 100);
6699 #ifdef BETTER_LITERAL_SHIFT
6701 _loadLeftIntoAx(char **lsb,
6707 // Get the initial value from left into a pair of registers.
6708 // MSB must be in A, LSB can be any register.
6710 // If the result is held in registers, it is an optimization
6711 // if the LSB can be held in the register which will hold the,
6712 // result LSB since this saves us from having to copy it into
6713 // the result following AccAXLsh.
6715 // If the result is addressed indirectly, this is not a gain.
6716 if (AOP_NEEDSACC(result))
6720 _startLazyDPSEvaluation();
6721 if (AOP_TYPE(left) == AOP_DPTR2)
6724 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6725 // get LSB in DP2_RESULT_REG.
6726 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6727 assert(!strcmp(leftByte, DP2_RESULT_REG));
6731 // get LSB into DP2_RESULT_REG
6732 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6733 if (strcmp(leftByte, DP2_RESULT_REG))
6735 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6738 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6739 assert(strcmp(leftByte, DP2_RESULT_REG));
6742 _endLazyDPSEvaluation();
6743 *lsb = DP2_RESULT_REG;
6747 if (sameRegs (AOP (result), AOP (left)) &&
6748 ((offl + MSB16) == offr))
6750 /* don't crash result[offr] */
6751 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6752 emitcode ("xch", "a,%s",
6753 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6757 movLeft2Result (left, offl, result, offr, 0);
6758 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6760 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6761 assert(strcmp(*lsb,"a"));
6766 _storeAxResults(char *lsb,
6770 _startLazyDPSEvaluation();
6771 if (AOP_NEEDSACC(result))
6773 /* We have to explicitly update the result LSB.
6775 emitcode("xch","a,%s", lsb);
6776 aopPut(AOP(result), "a", offr);
6777 emitcode("mov","a,%s", lsb);
6779 if (getDataSize (result) > 1)
6781 aopPut (AOP (result), "a", offr + MSB16);
6783 _endLazyDPSEvaluation();
6786 /*-----------------------------------------------------------------*/
6787 /* shiftL2Left2Result - shift left two bytes from left to result */
6788 /*-----------------------------------------------------------------*/
6790 shiftL2Left2Result (operand * left, int offl,
6791 operand * result, int offr, int shCount)
6795 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6797 AccAXLsh (lsb, shCount);
6799 _storeAxResults(lsb, result, offr);
6803 #ifdef BETTER_LITERAL_SHIFT
6804 /*-----------------------------------------------------------------*/
6805 /* shiftR2Left2Result - shift right two bytes from left to result */
6806 /*-----------------------------------------------------------------*/
6808 shiftR2Left2Result (operand * left, int offl,
6809 operand * result, int offr,
6810 int shCount, int sign)
6814 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6816 /* a:x >> shCount (x = lsb(result)) */
6819 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6823 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6826 _storeAxResults(lsb, result, offr);
6832 /*-----------------------------------------------------------------*/
6833 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6834 /*-----------------------------------------------------------------*/
6836 shiftLLeftOrResult (operand * left, int offl,
6837 operand * result, int offr, int shCount)
6839 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6840 /* shift left accumulator */
6842 /* or with result */
6843 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6844 /* back to result */
6845 aopPut (AOP (result), "a", offr);
6851 /*-----------------------------------------------------------------*/
6852 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6853 /*-----------------------------------------------------------------*/
6855 shiftRLeftOrResult (operand * left, int offl,
6856 operand * result, int offr, int shCount)
6858 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6859 /* shift right accumulator */
6861 /* or with result */
6862 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6863 /* back to result */
6864 aopPut (AOP (result), "a", offr);
6868 #ifdef BETTER_LITERAL_SHIFT
6869 /*-----------------------------------------------------------------*/
6870 /* genlshOne - left shift a one byte quantity by known count */
6871 /*-----------------------------------------------------------------*/
6873 genlshOne (operand * result, operand * left, int shCount)
6875 D (emitcode (";", "genlshOne "););
6876 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6880 #ifdef BETTER_LITERAL_SHIFT
6881 /*-----------------------------------------------------------------*/
6882 /* genlshTwo - left shift two bytes by known amount != 0 */
6883 /*-----------------------------------------------------------------*/
6885 genlshTwo (operand * result, operand * left, int shCount)
6889 D (emitcode (";", "genlshTwo "););
6891 size = getDataSize (result);
6893 /* if shCount >= 8 */
6898 _startLazyDPSEvaluation();
6904 _endLazyDPSEvaluation();
6905 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6906 aopPut (AOP (result), zero, LSB);
6910 movLeft2Result (left, LSB, result, MSB16, 0);
6911 aopPut (AOP (result), zero, LSB);
6912 _endLazyDPSEvaluation();
6917 aopPut (AOP (result), zero, LSB);
6918 _endLazyDPSEvaluation();
6922 /* 1 <= shCount <= 7 */
6927 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6931 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6939 /*-----------------------------------------------------------------*/
6940 /* shiftLLong - shift left one long from left to result */
6941 /* offl = LSB or MSB16 */
6942 /*-----------------------------------------------------------------*/
6944 shiftLLong (operand * left, operand * result, int offr)
6947 int size = AOP_SIZE (result);
6949 if (size >= LSB + offr)
6951 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6953 emitcode ("add", "a,acc");
6954 if (sameRegs (AOP (left), AOP (result)) &&
6955 size >= MSB16 + offr && offr != LSB)
6956 emitcode ("xch", "a,%s",
6957 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6959 aopPut (AOP (result), "a", LSB + offr);
6962 if (size >= MSB16 + offr)
6964 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6966 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6969 emitcode ("rlc", "a");
6970 if (sameRegs (AOP (left), AOP (result)) &&
6971 size >= MSB24 + offr && offr != LSB)
6972 emitcode ("xch", "a,%s",
6973 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6975 aopPut (AOP (result), "a", MSB16 + offr);
6978 if (size >= MSB24 + offr)
6980 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6982 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6985 emitcode ("rlc", "a");
6986 if (sameRegs (AOP (left), AOP (result)) &&
6987 size >= MSB32 + offr && offr != LSB)
6988 emitcode ("xch", "a,%s",
6989 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6991 aopPut (AOP (result), "a", MSB24 + offr);
6994 if (size > MSB32 + offr)
6996 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6998 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7001 emitcode ("rlc", "a");
7002 aopPut (AOP (result), "a", MSB32 + offr);
7005 aopPut (AOP (result), zero, LSB);
7011 /*-----------------------------------------------------------------*/
7012 /* genlshFour - shift four byte by a known amount != 0 */
7013 /*-----------------------------------------------------------------*/
7015 genlshFour (operand * result, operand * left, int shCount)
7019 D (emitcode (";", "genlshFour ");
7022 size = AOP_SIZE (result);
7024 /* if shifting more that 3 bytes */
7029 /* lowest order of left goes to the highest
7030 order of the destination */
7031 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7033 movLeft2Result (left, LSB, result, MSB32, 0);
7034 aopPut (AOP (result), zero, LSB);
7035 aopPut (AOP (result), zero, MSB16);
7036 aopPut (AOP (result), zero, MSB24);
7040 /* more than two bytes */
7041 else if (shCount >= 16)
7043 /* lower order two bytes goes to higher order two bytes */
7045 /* if some more remaining */
7047 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7050 movLeft2Result (left, MSB16, result, MSB32, 0);
7051 movLeft2Result (left, LSB, result, MSB24, 0);
7053 aopPut (AOP (result), zero, MSB16);
7054 aopPut (AOP (result), zero, LSB);
7058 /* if more than 1 byte */
7059 else if (shCount >= 8)
7061 /* lower order three bytes goes to higher order three bytes */
7066 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7068 movLeft2Result (left, LSB, result, MSB16, 0);
7074 movLeft2Result (left, MSB24, result, MSB32, 0);
7075 movLeft2Result (left, MSB16, result, MSB24, 0);
7076 movLeft2Result (left, LSB, result, MSB16, 0);
7077 aopPut (AOP (result), zero, LSB);
7079 else if (shCount == 1)
7080 shiftLLong (left, result, MSB16);
7083 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7084 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7085 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7086 aopPut (AOP (result), zero, LSB);
7091 /* 1 <= shCount <= 7 */
7092 else if (shCount <= 2)
7094 shiftLLong (left, result, LSB);
7096 shiftLLong (result, result, LSB);
7098 /* 3 <= shCount <= 7, optimize */
7101 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7102 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7103 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7108 #ifdef BETTER_LITERAL_SHIFT
7109 /*-----------------------------------------------------------------*/
7110 /* genLeftShiftLiteral - left shifting by known count */
7111 /*-----------------------------------------------------------------*/
7113 genLeftShiftLiteral (operand * left,
7118 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7121 size = getSize (operandType (result));
7123 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7125 /* We only handle certain easy cases so far. */
7127 && (shCount < (size * 8))
7131 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7135 freeAsmop (right, NULL, ic, TRUE);
7137 aopOp(left, ic, FALSE, FALSE);
7138 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7141 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7143 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7144 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7146 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7149 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7151 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7152 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7154 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7160 emitcode ("; shift left ", "result %d, left %d", size,
7164 /* I suppose that the left size >= result size */
7167 _startLazyDPSEvaluation();
7170 movLeft2Result (left, size, result, size, 0);
7172 _endLazyDPSEvaluation();
7174 else if (shCount >= (size * 8))
7176 _startLazyDPSEvaluation();
7179 aopPut (AOP (result), zero, size);
7181 _endLazyDPSEvaluation();
7188 genlshOne (result, left, shCount);
7192 genlshTwo (result, left, shCount);
7196 genlshFour (result, left, shCount);
7200 fprintf(stderr, "*** ack! mystery literal shift!\n");
7204 freeAsmop (left, NULL, ic, TRUE);
7205 freeAsmop (result, NULL, ic, TRUE);
7210 /*-----------------------------------------------------------------*/
7211 /* genLeftShift - generates code for left shifting */
7212 /*-----------------------------------------------------------------*/
7214 genLeftShift (iCode * ic)
7216 operand *left, *right, *result;
7219 symbol *tlbl, *tlbl1;
7221 D (emitcode (";", "genLeftShift "););
7223 right = IC_RIGHT (ic);
7224 left = IC_LEFT (ic);
7225 result = IC_RESULT (ic);
7227 aopOp (right, ic, FALSE, FALSE);
7230 #ifdef BETTER_LITERAL_SHIFT
7231 /* if the shift count is known then do it
7232 as efficiently as possible */
7233 if (AOP_TYPE (right) == AOP_LIT)
7235 if (genLeftShiftLiteral (left, right, result, ic))
7242 /* shift count is unknown then we have to form
7243 a loop get the loop count in B : Note: we take
7244 only the lower order byte since shifting
7245 more that 32 bits make no sense anyway, ( the
7246 largest size of an object can be only 32 bits ) */
7248 if (AOP_TYPE (right) == AOP_LIT)
7250 /* Really should be handled by genLeftShiftLiteral,
7251 * but since I'm too lazy to fix that today, at least we can make
7252 * some small improvement.
7254 emitcode("mov", "b,#0x%02x",
7255 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7259 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7260 emitcode ("inc", "b");
7262 freeAsmop (right, NULL, ic, TRUE);
7263 aopOp (left, ic, FALSE, FALSE);
7264 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7266 /* now move the left to the result if they are not the
7268 if (!sameRegs (AOP (left), AOP (result)) &&
7269 AOP_SIZE (result) > 1)
7272 size = AOP_SIZE (result);
7274 _startLazyDPSEvaluation ();
7277 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7278 if (*l == '@' && (IS_AOP_PREG (result)))
7281 emitcode ("mov", "a,%s", l);
7282 aopPut (AOP (result), "a", offset);
7285 aopPut (AOP (result), l, offset);
7288 _endLazyDPSEvaluation ();
7291 tlbl = newiTempLabel (NULL);
7292 size = AOP_SIZE (result);
7294 tlbl1 = newiTempLabel (NULL);
7296 /* if it is only one byte then */
7299 symbol *tlbl1 = newiTempLabel (NULL);
7301 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7303 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7304 emitcode ("", "%05d$:", tlbl->key + 100);
7305 emitcode ("add", "a,acc");
7306 emitcode ("", "%05d$:", tlbl1->key + 100);
7307 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7308 aopPut (AOP (result), "a", 0);
7312 reAdjustPreg (AOP (result));
7314 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7315 emitcode ("", "%05d$:", tlbl->key + 100);
7316 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7318 emitcode ("add", "a,acc");
7319 aopPut (AOP (result), "a", offset++);
7320 _startLazyDPSEvaluation ();
7323 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7325 emitcode ("rlc", "a");
7326 aopPut (AOP (result), "a", offset++);
7328 _endLazyDPSEvaluation ();
7329 reAdjustPreg (AOP (result));
7331 emitcode ("", "%05d$:", tlbl1->key + 100);
7332 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7334 freeAsmop (left, NULL, ic, TRUE);
7335 freeAsmop (result, NULL, ic, TRUE);
7338 #ifdef BETTER_LITERAL_SHIFT
7339 /*-----------------------------------------------------------------*/
7340 /* genrshOne - right shift a one byte quantity by known count */
7341 /*-----------------------------------------------------------------*/
7343 genrshOne (operand * result, operand * left,
7344 int shCount, int sign)
7346 D (emitcode (";", "genrshOne"););
7347 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7351 #ifdef BETTER_LITERAL_SHIFT
7352 /*-----------------------------------------------------------------*/
7353 /* genrshTwo - right shift two bytes by known amount != 0 */
7354 /*-----------------------------------------------------------------*/
7356 genrshTwo (operand * result, operand * left,
7357 int shCount, int sign)
7359 D (emitcode (";", "genrshTwo"););
7361 /* if shCount >= 8 */
7365 _startLazyDPSEvaluation();
7368 shiftR1Left2Result (left, MSB16, result, LSB,
7373 movLeft2Result (left, MSB16, result, LSB, sign);
7375 addSign (result, MSB16, sign);
7376 _endLazyDPSEvaluation();
7379 /* 1 <= shCount <= 7 */
7382 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7389 /*-----------------------------------------------------------------*/
7390 /* shiftRLong - shift right one long from left to result */
7391 /* offl = LSB or MSB16 */
7392 /*-----------------------------------------------------------------*/
7394 shiftRLong (operand * left, int offl,
7395 operand * result, int sign)
7397 int isSameRegs=sameRegs(AOP(left),AOP(result));
7399 if (isSameRegs && offl>1) {
7400 // we are in big trouble, but this shouldn't happen
7401 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7404 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7409 emitcode ("rlc", "a");
7410 emitcode ("subb", "a,acc");
7411 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7413 aopPut (AOP(result), zero, MSB32);
7418 emitcode ("clr", "c");
7420 emitcode ("mov", "c,acc.7");
7423 emitcode ("rrc", "a");
7425 if (isSameRegs && offl==MSB16) {
7426 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7428 aopPut (AOP (result), "a", MSB32);
7429 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7432 emitcode ("rrc", "a");
7433 if (isSameRegs && offl==1) {
7434 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7436 aopPut (AOP (result), "a", MSB24);
7437 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7439 emitcode ("rrc", "a");
7440 aopPut (AOP (result), "a", MSB16 - offl);
7444 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7445 emitcode ("rrc", "a");
7446 aopPut (AOP (result), "a", LSB);
7453 /*-----------------------------------------------------------------*/
7454 /* genrshFour - shift four byte by a known amount != 0 */
7455 /*-----------------------------------------------------------------*/
7457 genrshFour (operand * result, operand * left,
7458 int shCount, int sign)
7460 D (emitcode (";", "genrshFour");
7463 /* if shifting more that 3 bytes */
7468 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7470 movLeft2Result (left, MSB32, result, LSB, sign);
7471 addSign (result, MSB16, sign);
7473 else if (shCount >= 16)
7477 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7480 movLeft2Result (left, MSB24, result, LSB, 0);
7481 movLeft2Result (left, MSB32, result, MSB16, sign);
7483 addSign (result, MSB24, sign);
7485 else if (shCount >= 8)
7489 shiftRLong (left, MSB16, result, sign);
7490 else if (shCount == 0)
7492 movLeft2Result (left, MSB16, result, LSB, 0);
7493 movLeft2Result (left, MSB24, result, MSB16, 0);
7494 movLeft2Result (left, MSB32, result, MSB24, sign);
7495 addSign (result, MSB32, sign);
7499 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7500 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7501 /* the last shift is signed */
7502 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7503 addSign (result, MSB32, sign);
7507 { /* 1 <= shCount <= 7 */
7510 shiftRLong (left, LSB, result, sign);
7512 shiftRLong (result, LSB, result, sign);
7516 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7517 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7518 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7524 #ifdef BETTER_LITERAL_SHIFT
7525 /*-----------------------------------------------------------------*/
7526 /* genRightShiftLiteral - right shifting by known count */
7527 /*-----------------------------------------------------------------*/
7529 genRightShiftLiteral (operand * left,
7535 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7538 size = getSize (operandType (result));
7540 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7542 /* We only handle certain easy cases so far. */
7544 && (shCount < (size * 8))
7548 D(emitcode (";", "genRightShiftLiteral wimping out"););
7552 freeAsmop (right, NULL, ic, TRUE);
7554 aopOp (left, ic, FALSE, FALSE);
7555 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7558 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7562 /* test the LEFT size !!! */
7564 /* I suppose that the left size >= result size */
7567 size = getDataSize (result);
7568 _startLazyDPSEvaluation();
7571 movLeft2Result (left, size, result, size, 0);
7573 _endLazyDPSEvaluation();
7575 else if (shCount >= (size * 8))
7579 /* get sign in acc.7 */
7580 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7582 addSign (result, LSB, sign);
7589 genrshOne (result, left, shCount, sign);
7593 genrshTwo (result, left, shCount, sign);
7597 genrshFour (result, left, shCount, sign);
7604 freeAsmop (left, NULL, ic, TRUE);
7605 freeAsmop (result, NULL, ic, TRUE);
7611 /*-----------------------------------------------------------------*/
7612 /* genSignedRightShift - right shift of signed number */
7613 /*-----------------------------------------------------------------*/
7615 genSignedRightShift (iCode * ic)
7617 operand *right, *left, *result;
7620 symbol *tlbl, *tlbl1;
7622 D (emitcode (";", "genSignedRightShift "););
7624 /* we do it the hard way put the shift count in b
7625 and loop thru preserving the sign */
7627 right = IC_RIGHT (ic);
7628 left = IC_LEFT (ic);
7629 result = IC_RESULT (ic);
7631 aopOp (right, ic, FALSE, FALSE);
7633 #ifdef BETTER_LITERAL_SHIFT
7634 if (AOP_TYPE (right) == AOP_LIT)
7636 if (genRightShiftLiteral (left, right, result, ic, 1))
7642 /* shift count is unknown then we have to form
7643 a loop get the loop count in B : Note: we take
7644 only the lower order byte since shifting
7645 more that 32 bits make no sense anyway, ( the
7646 largest size of an object can be only 32 bits ) */
7648 if (AOP_TYPE (right) == AOP_LIT)
7650 /* Really should be handled by genRightShiftLiteral,
7651 * but since I'm too lazy to fix that today, at least we can make
7652 * some small improvement.
7654 emitcode("mov", "b,#0x%02x",
7655 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7659 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7660 emitcode ("inc", "b");
7662 freeAsmop (right, NULL, ic, TRUE);
7663 aopOp (left, ic, FALSE, FALSE);
7664 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7666 /* now move the left to the result if they are not the
7668 if (!sameRegs (AOP (left), AOP (result)) &&
7669 AOP_SIZE (result) > 1)
7672 size = AOP_SIZE (result);
7674 _startLazyDPSEvaluation ();
7677 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7678 if (*l == '@' && IS_AOP_PREG (result))
7681 emitcode ("mov", "a,%s", l);
7682 aopPut (AOP (result), "a", offset);
7685 aopPut (AOP (result), l, offset);
7688 _endLazyDPSEvaluation ();
7691 /* mov the highest order bit to OVR */
7692 tlbl = newiTempLabel (NULL);
7693 tlbl1 = newiTempLabel (NULL);
7695 size = AOP_SIZE (result);
7697 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7698 emitcode ("rlc", "a");
7699 emitcode ("mov", "ov,c");
7700 /* if it is only one byte then */
7703 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7705 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7706 emitcode ("", "%05d$:", tlbl->key + 100);
7707 emitcode ("mov", "c,ov");
7708 emitcode ("rrc", "a");
7709 emitcode ("", "%05d$:", tlbl1->key + 100);
7710 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7711 aopPut (AOP (result), "a", 0);
7715 reAdjustPreg (AOP (result));
7716 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7717 emitcode ("", "%05d$:", tlbl->key + 100);
7718 emitcode ("mov", "c,ov");
7719 _startLazyDPSEvaluation ();
7722 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7724 emitcode ("rrc", "a");
7725 aopPut (AOP (result), "a", offset--);
7727 _endLazyDPSEvaluation ();
7728 reAdjustPreg (AOP (result));
7729 emitcode ("", "%05d$:", tlbl1->key + 100);
7730 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7733 freeAsmop (left, NULL, ic, TRUE);
7734 freeAsmop (result, NULL, ic, TRUE);
7737 /*-----------------------------------------------------------------*/
7738 /* genRightShift - generate code for right shifting */
7739 /*-----------------------------------------------------------------*/
7741 genRightShift (iCode * ic)
7743 operand *right, *left, *result;
7747 symbol *tlbl, *tlbl1;
7749 D (emitcode (";", "genRightShift "););
7751 /* if signed then we do it the hard way preserve the
7752 sign bit moving it inwards */
7753 retype = getSpec (operandType (IC_RESULT (ic)));
7755 if (!SPEC_USIGN (retype))
7757 genSignedRightShift (ic);
7761 /* signed & unsigned types are treated the same : i.e. the
7762 signed is NOT propagated inwards : quoting from the
7763 ANSI - standard : "for E1 >> E2, is equivalent to division
7764 by 2**E2 if unsigned or if it has a non-negative value,
7765 otherwise the result is implementation defined ", MY definition
7766 is that the sign does not get propagated */
7768 right = IC_RIGHT (ic);
7769 left = IC_LEFT (ic);
7770 result = IC_RESULT (ic);
7772 aopOp (right, ic, FALSE, FALSE);
7774 #ifdef BETTER_LITERAL_SHIFT
7775 /* if the shift count is known then do it
7776 as efficiently as possible */
7777 if (AOP_TYPE (right) == AOP_LIT)
7779 if (genRightShiftLiteral (left, right, result, ic, 0))
7786 /* shift count is unknown then we have to form
7787 a loop get the loop count in B : Note: we take
7788 only the lower order byte since shifting
7789 more that 32 bits make no sense anyway, ( the
7790 largest size of an object can be only 32 bits ) */
7792 if (AOP_TYPE (right) == AOP_LIT)
7794 /* Really should be handled by genRightShiftLiteral,
7795 * but since I'm too lazy to fix that today, at least we can make
7796 * some small improvement.
7798 emitcode("mov", "b,#0x%02x",
7799 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7803 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7804 emitcode ("inc", "b");
7806 freeAsmop (right, NULL, ic, TRUE);
7807 aopOp (left, ic, FALSE, FALSE);
7808 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7810 /* now move the left to the result if they are not the
7812 if (!sameRegs (AOP (left), AOP (result)) &&
7813 AOP_SIZE (result) > 1)
7816 size = AOP_SIZE (result);
7818 _startLazyDPSEvaluation ();
7821 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7822 if (*l == '@' && IS_AOP_PREG (result))
7825 emitcode ("mov", "a,%s", l);
7826 aopPut (AOP (result), "a", offset);
7829 aopPut (AOP (result), l, offset);
7832 _endLazyDPSEvaluation ();
7835 tlbl = newiTempLabel (NULL);
7836 tlbl1 = newiTempLabel (NULL);
7837 size = AOP_SIZE (result);
7840 /* if it is only one byte then */
7843 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7845 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7846 emitcode ("", "%05d$:", tlbl->key + 100);
7848 emitcode ("rrc", "a");
7849 emitcode ("", "%05d$:", tlbl1->key + 100);
7850 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7851 aopPut (AOP (result), "a", 0);
7855 reAdjustPreg (AOP (result));
7856 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7857 emitcode ("", "%05d$:", tlbl->key + 100);
7859 _startLazyDPSEvaluation ();
7862 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7864 emitcode ("rrc", "a");
7865 aopPut (AOP (result), "a", offset--);
7867 _endLazyDPSEvaluation ();
7868 reAdjustPreg (AOP (result));
7870 emitcode ("", "%05d$:", tlbl1->key + 100);
7871 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7874 freeAsmop (left, NULL, ic, TRUE);
7875 freeAsmop (result, NULL, ic, TRUE);
7878 /*-----------------------------------------------------------------*/
7879 /* genUnpackBits - generates code for unpacking bits */
7880 /*-----------------------------------------------------------------*/
7882 genUnpackBits (operand * result, char *rname, int ptype)
7889 D (emitcode (";", "genUnpackBits ");
7892 etype = getSpec (operandType (result));
7894 /* read the first byte */
7900 emitcode ("mov", "a,@%s", rname);
7904 emitcode ("movx", "a,@%s", rname);
7908 emitcode ("movx", "a,@dptr");
7912 emitcode ("clr", "a");
7913 emitcode ("movc", "a", "@a+dptr");
7917 emitcode ("lcall", "__gptrget");
7921 /* if we have bitdisplacement then it fits */
7922 /* into this byte completely or if length is */
7923 /* less than a byte */
7924 if ((shCnt = SPEC_BSTR (etype)) ||
7925 (SPEC_BLEN (etype) <= 8))
7928 /* shift right acc */
7931 emitcode ("anl", "a,#0x%02x",
7932 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7933 aopPut (AOP (result), "a", offset);
7937 /* bit field did not fit in a byte */
7938 rlen = SPEC_BLEN (etype) - 8;
7939 aopPut (AOP (result), "a", offset++);
7948 emitcode ("inc", "%s", rname);
7949 emitcode ("mov", "a,@%s", rname);
7953 emitcode ("inc", "%s", rname);
7954 emitcode ("movx", "a,@%s", rname);
7958 emitcode ("inc", "dptr");
7959 emitcode ("movx", "a,@dptr");
7963 emitcode ("clr", "a");
7964 emitcode ("inc", "dptr");
7965 emitcode ("movc", "a", "@a+dptr");
7969 emitcode ("inc", "dptr");
7970 emitcode ("lcall", "__gptrget");
7975 /* if we are done */
7979 aopPut (AOP (result), "a", offset++);
7985 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7986 aopPut (AOP (result), "a", offset);
7993 /*-----------------------------------------------------------------*/
7994 /* genDataPointerGet - generates code when ptr offset is known */
7995 /*-----------------------------------------------------------------*/
7997 genDataPointerGet (operand * left,
8003 int size, offset = 0;
8004 aopOp (result, ic, TRUE, FALSE);
8006 /* get the string representation of the name */
8007 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8008 size = AOP_SIZE (result);
8009 _startLazyDPSEvaluation ();
8013 sprintf (buffer, "(%s + %d)", l + 1, offset);
8015 sprintf (buffer, "%s", l + 1);
8016 aopPut (AOP (result), buffer, offset++);
8018 _endLazyDPSEvaluation ();
8020 freeAsmop (left, NULL, ic, TRUE);
8021 freeAsmop (result, NULL, ic, TRUE);
8024 /*-----------------------------------------------------------------*/
8025 /* genNearPointerGet - emitcode for near pointer fetch */
8026 /*-----------------------------------------------------------------*/
8028 genNearPointerGet (operand * left,
8035 sym_link *rtype, *retype, *letype;
8036 sym_link *ltype = operandType (left);
8039 rtype = operandType (result);
8040 retype = getSpec (rtype);
8041 letype = getSpec (ltype);
8043 aopOp (left, ic, FALSE, FALSE);
8045 /* if left is rematerialisable and
8046 result is not bit variable type and
8047 the left is pointer to data space i.e
8048 lower 128 bytes of space */
8049 if (AOP_TYPE (left) == AOP_IMMD &&
8050 !IS_BITVAR (retype) &&
8051 !IS_BITVAR (letype) &&
8052 DCL_TYPE (ltype) == POINTER)
8054 genDataPointerGet (left, result, ic);
8058 /* if the value is already in a pointer register
8059 then don't need anything more */
8060 if (!AOP_INPREG (AOP (left)))
8062 /* otherwise get a free pointer register */
8064 preg = getFreePtr (ic, &aop, FALSE);
8065 emitcode ("mov", "%s,%s",
8067 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8071 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8073 freeAsmop (left, NULL, ic, TRUE);
8074 aopOp (result, ic, FALSE, FALSE);
8076 /* if bitfield then unpack the bits */
8077 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8078 genUnpackBits (result, rname, POINTER);
8081 /* we have can just get the values */
8082 int size = AOP_SIZE (result);
8087 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8090 emitcode ("mov", "a,@%s", rname);
8091 aopPut (AOP (result), "a", offset);
8095 sprintf (buffer, "@%s", rname);
8096 aopPut (AOP (result), buffer, offset);
8100 emitcode ("inc", "%s", rname);
8104 /* now some housekeeping stuff */
8107 /* we had to allocate for this iCode */
8108 freeAsmop (NULL, aop, ic, TRUE);
8112 /* we did not allocate which means left
8113 already in a pointer register, then
8114 if size > 0 && this could be used again
8115 we have to point it back to where it
8117 if (AOP_SIZE (result) > 1 &&
8118 !OP_SYMBOL (left)->remat &&
8119 (OP_SYMBOL (left)->liveTo > ic->seq ||
8122 int size = AOP_SIZE (result) - 1;
8124 emitcode ("dec", "%s", rname);
8129 freeAsmop (result, NULL, ic, TRUE);
8133 /*-----------------------------------------------------------------*/
8134 /* genPagedPointerGet - emitcode for paged pointer fetch */
8135 /*-----------------------------------------------------------------*/
8137 genPagedPointerGet (operand * left,
8144 sym_link *rtype, *retype, *letype;
8146 rtype = operandType (result);
8147 retype = getSpec (rtype);
8148 letype = getSpec (operandType (left));
8149 aopOp (left, ic, FALSE, FALSE);
8151 /* if the value is already in a pointer register
8152 then don't need anything more */
8153 if (!AOP_INPREG (AOP (left)))
8155 /* otherwise get a free pointer register */
8157 preg = getFreePtr (ic, &aop, FALSE);
8158 emitcode ("mov", "%s,%s",
8160 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8164 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8166 freeAsmop (left, NULL, ic, TRUE);
8167 aopOp (result, ic, FALSE, FALSE);
8169 /* if bitfield then unpack the bits */
8170 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8171 genUnpackBits (result, rname, PPOINTER);
8174 /* we have can just get the values */
8175 int size = AOP_SIZE (result);
8181 emitcode ("movx", "a,@%s", rname);
8182 aopPut (AOP (result), "a", offset);
8187 emitcode ("inc", "%s", rname);
8191 /* now some housekeeping stuff */
8194 /* we had to allocate for this iCode */
8195 freeAsmop (NULL, aop, ic, TRUE);
8199 /* we did not allocate which means left
8200 already in a pointer register, then
8201 if size > 0 && this could be used again
8202 we have to point it back to where it
8204 if (AOP_SIZE (result) > 1 &&
8205 !OP_SYMBOL (left)->remat &&
8206 (OP_SYMBOL (left)->liveTo > ic->seq ||
8209 int size = AOP_SIZE (result) - 1;
8211 emitcode ("dec", "%s", rname);
8216 freeAsmop (result, NULL, ic, TRUE);
8221 /*-----------------------------------------------------------------*/
8222 /* genFarPointerGet - gget value from far space */
8223 /*-----------------------------------------------------------------*/
8225 genFarPointerGet (operand * left,
8226 operand * result, iCode * ic)
8229 sym_link *retype = getSpec (operandType (result));
8230 sym_link *letype = getSpec (operandType (left));
8231 D (emitcode (";", "genFarPointerGet");
8234 aopOp (left, ic, FALSE, FALSE);
8236 /* if the operand is already in dptr
8237 then we do nothing else we move the value to dptr */
8238 if (AOP_TYPE (left) != AOP_STR)
8240 /* if this is remateriazable */
8241 if (AOP_TYPE (left) == AOP_IMMD)
8243 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8247 /* we need to get it byte by byte */
8248 _startLazyDPSEvaluation ();
8249 if (AOP_TYPE (left) != AOP_DPTR)
8251 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8252 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8253 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8257 /* We need to generate a load to DPTR indirect through DPTR. */
8258 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8260 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8261 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8262 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8263 emitcode ("pop", "dph");
8264 emitcode ("pop", "dpl");
8266 _endLazyDPSEvaluation ();
8269 /* so dptr know contains the address */
8270 freeAsmop (left, NULL, ic, TRUE);
8271 aopOp (result, ic, FALSE, TRUE);
8273 /* if bit then unpack */
8274 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8275 genUnpackBits (result, "dptr", FPOINTER);
8278 size = AOP_SIZE (result);
8281 _startLazyDPSEvaluation ();
8288 emitcode ("movx", "a,@dptr");
8290 emitcode ("inc", "dptr");
8292 aopPut (AOP (result), "a", offset++);
8294 _endLazyDPSEvaluation ();
8297 freeAsmop (result, NULL, ic, TRUE);
8300 /*-----------------------------------------------------------------*/
8301 /* emitcodePointerGet - gget value from code space */
8302 /*-----------------------------------------------------------------*/
8304 emitcodePointerGet (operand * left,
8305 operand * result, iCode * ic)
8308 sym_link *retype = getSpec (operandType (result));
8310 aopOp (left, ic, FALSE, FALSE);
8312 /* if the operand is already in dptr
8313 then we do nothing else we move the value to dptr */
8314 if (AOP_TYPE (left) != AOP_STR)
8316 /* if this is remateriazable */
8317 if (AOP_TYPE (left) == AOP_IMMD)
8319 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8322 { /* we need to get it byte by byte */
8323 _startLazyDPSEvaluation ();
8324 if (AOP_TYPE (left) != AOP_DPTR)
8326 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8327 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8328 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8332 /* We need to generate a load to DPTR indirect through DPTR. */
8333 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8335 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8336 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8337 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8338 emitcode ("pop", "dph");
8339 emitcode ("pop", "dpl");
8341 _endLazyDPSEvaluation ();
8344 /* so dptr know contains the address */
8345 freeAsmop (left, NULL, ic, TRUE);
8346 aopOp (result, ic, FALSE, TRUE);
8348 /* if bit then unpack */
8349 if (IS_BITVAR (retype))
8350 genUnpackBits (result, "dptr", CPOINTER);
8353 size = AOP_SIZE (result);
8356 _startLazyDPSEvaluation ();
8362 emitcode ("clr", "a");
8363 emitcode ("movc", "a,@a+dptr");
8365 emitcode ("inc", "dptr");
8366 aopPut (AOP (result), "a", offset++);
8368 _endLazyDPSEvaluation ();
8371 freeAsmop (result, NULL, ic, TRUE);
8374 /*-----------------------------------------------------------------*/
8375 /* genGenPointerGet - gget value from generic pointer space */
8376 /*-----------------------------------------------------------------*/
8378 genGenPointerGet (operand * left,
8379 operand * result, iCode * ic)
8382 sym_link *retype = getSpec (operandType (result));
8383 sym_link *letype = getSpec (operandType (left));
8385 D (emitcode (";", "genGenPointerGet "); );
8387 aopOp (left, ic, FALSE, TRUE);
8389 /* if the operand is already in dptr
8390 then we do nothing else we move the value to dptr */
8391 if (AOP_TYPE (left) != AOP_STR)
8393 /* if this is remateriazable */
8394 if (AOP_TYPE (left) == AOP_IMMD)
8396 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8397 emitcode ("mov", "b,#%d", pointerCode (retype));
8400 { /* we need to get it byte by byte */
8401 _startLazyDPSEvaluation ();
8402 if (AOP(left)->type==AOP_DPTR2) {
8404 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8407 emitcode ("mov", "dpl,%s", l);
8408 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8411 emitcode ("mov", "dph,%s", l);
8412 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8415 emitcode ("mov", "dpx,%s", l);
8416 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8418 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8419 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8420 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8421 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8423 _endLazyDPSEvaluation ();
8426 /* so dptr know contains the address */
8427 freeAsmop (left, NULL, ic, TRUE);
8428 aopOp (result, ic, FALSE, TRUE);
8430 /* if bit then unpack */
8431 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8432 genUnpackBits (result, "dptr", GPOINTER);
8435 size = AOP_SIZE (result);
8440 emitcode ("lcall", "__gptrget");
8441 aopPut (AOP (result), "a", offset++);
8443 emitcode ("inc", "dptr");
8447 freeAsmop (result, NULL, ic, TRUE);
8450 /*-----------------------------------------------------------------*/
8451 /* genPointerGet - generate code for pointer get */
8452 /*-----------------------------------------------------------------*/
8454 genPointerGet (iCode * ic)
8456 operand *left, *result;
8457 sym_link *type, *etype;
8460 D (emitcode (";", "genPointerGet ");
8463 left = IC_LEFT (ic);
8464 result = IC_RESULT (ic);
8466 /* depending on the type of pointer we need to
8467 move it to the correct pointer register */
8468 type = operandType (left);
8469 etype = getSpec (type);
8470 /* if left is of type of pointer then it is simple */
8471 if (IS_PTR (type) && !IS_FUNC (type->next))
8472 p_type = DCL_TYPE (type);
8475 /* we have to go by the storage class */
8476 p_type = PTR_TYPE (SPEC_OCLS (etype));
8479 /* now that we have the pointer type we assign
8480 the pointer values */
8486 genNearPointerGet (left, result, ic);
8490 genPagedPointerGet (left, result, ic);
8494 genFarPointerGet (left, result, ic);
8498 emitcodePointerGet (left, result, ic);
8502 genGenPointerGet (left, result, ic);
8508 /*-----------------------------------------------------------------*/
8509 /* genPackBits - generates code for packed bit storage */
8510 /*-----------------------------------------------------------------*/
8512 genPackBits (sym_link * etype,
8514 char *rname, int p_type)
8522 blen = SPEC_BLEN (etype);
8523 bstr = SPEC_BSTR (etype);
8525 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8528 /* if the bit lenth is less than or */
8529 /* it exactly fits a byte then */
8530 if (SPEC_BLEN (etype) <= 8)
8532 shCount = SPEC_BSTR (etype);
8534 /* shift left acc */
8537 if (SPEC_BLEN (etype) < 8)
8538 { /* if smaller than a byte */
8544 emitcode ("mov", "b,a");
8545 emitcode ("mov", "a,@%s", rname);
8549 emitcode ("mov", "b,a");
8550 emitcode ("movx", "a,@dptr");
8554 emitcode ("push", "b");
8555 emitcode ("push", "acc");
8556 emitcode ("lcall", "__gptrget");
8557 emitcode ("pop", "b");
8561 emitcode ("anl", "a,#0x%02x", (unsigned char)
8562 ((unsigned char) (0xFF << (blen + bstr)) |
8563 (unsigned char) (0xFF >> (8 - bstr))));
8564 emitcode ("orl", "a,b");
8565 if (p_type == GPOINTER)
8566 emitcode ("pop", "b");
8573 emitcode ("mov", "@%s,a", rname);
8577 emitcode ("movx", "@dptr,a");
8581 emitcode ("lcall", "__gptrput");
8586 if (SPEC_BLEN (etype) <= 8)
8589 emitcode ("inc", "%s", rname);
8590 rLen = SPEC_BLEN (etype);
8592 /* now generate for lengths greater than one byte */
8596 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8608 emitcode ("mov", "@%s,a", rname);
8611 emitcode ("mov", "@%s,%s", rname, l);
8616 emitcode ("movx", "@dptr,a");
8621 emitcode ("lcall", "__gptrput");
8624 emitcode ("inc", "%s", rname);
8629 /* last last was not complete */
8632 /* save the byte & read byte */
8636 emitcode ("mov", "b,a");
8637 emitcode ("mov", "a,@%s", rname);
8641 emitcode ("mov", "b,a");
8642 emitcode ("movx", "a,@dptr");
8646 emitcode ("push", "b");
8647 emitcode ("push", "acc");
8648 emitcode ("lcall", "__gptrget");
8649 emitcode ("pop", "b");
8653 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8654 emitcode ("orl", "a,b");
8657 if (p_type == GPOINTER)
8658 emitcode ("pop", "b");
8664 emitcode ("mov", "@%s,a", rname);
8668 emitcode ("movx", "@dptr,a");
8672 emitcode ("lcall", "__gptrput");
8676 /*-----------------------------------------------------------------*/
8677 /* genDataPointerSet - remat pointer to data space */
8678 /*-----------------------------------------------------------------*/
8680 genDataPointerSet (operand * right,
8684 int size, offset = 0;
8685 char *l, buffer[256];
8687 aopOp (right, ic, FALSE, FALSE);
8689 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8690 size = AOP_SIZE (right);
8694 sprintf (buffer, "(%s + %d)", l + 1, offset);
8696 sprintf (buffer, "%s", l + 1);
8697 emitcode ("mov", "%s,%s", buffer,
8698 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8701 freeAsmop (right, NULL, ic, TRUE);
8702 freeAsmop (result, NULL, ic, TRUE);
8705 /*-----------------------------------------------------------------*/
8706 /* genNearPointerSet - emitcode for near pointer put */
8707 /*-----------------------------------------------------------------*/
8709 genNearPointerSet (operand * right,
8716 sym_link *retype, *letype;
8717 sym_link *ptype = operandType (result);
8719 retype = getSpec (operandType (right));
8720 letype = getSpec (ptype);
8722 aopOp (result, ic, FALSE, FALSE);
8724 /* if the result is rematerializable &
8725 in data space & not a bit variable */
8726 if (AOP_TYPE (result) == AOP_IMMD &&
8727 DCL_TYPE (ptype) == POINTER &&
8728 !IS_BITVAR (retype) &&
8729 !IS_BITVAR (letype))
8731 genDataPointerSet (right, result, ic);
8735 /* if the value is already in a pointer register
8736 then don't need anything more */
8737 if (!AOP_INPREG (AOP (result)))
8739 /* otherwise get a free pointer register */
8741 preg = getFreePtr (ic, &aop, FALSE);
8742 emitcode ("mov", "%s,%s",
8744 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8748 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8750 freeAsmop (result, NULL, ic, TRUE);
8751 aopOp (right, ic, FALSE, FALSE);
8753 /* if bitfield then unpack the bits */
8754 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8755 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8758 /* we have can just get the values */
8759 int size = AOP_SIZE (right);
8764 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8768 emitcode ("mov", "@%s,a", rname);
8771 emitcode ("mov", "@%s,%s", rname, l);
8773 emitcode ("inc", "%s", rname);
8778 /* now some housekeeping stuff */
8781 /* we had to allocate for this iCode */
8782 freeAsmop (NULL, aop, ic, TRUE);
8786 /* we did not allocate which means left
8787 already in a pointer register, then
8788 if size > 0 && this could be used again
8789 we have to point it back to where it
8791 if (AOP_SIZE (right) > 1 &&
8792 !OP_SYMBOL (result)->remat &&
8793 (OP_SYMBOL (result)->liveTo > ic->seq ||
8796 int size = AOP_SIZE (right) - 1;
8798 emitcode ("dec", "%s", rname);
8803 freeAsmop (right, NULL, ic, TRUE);
8808 /*-----------------------------------------------------------------*/
8809 /* genPagedPointerSet - emitcode for Paged pointer put */
8810 /*-----------------------------------------------------------------*/
8812 genPagedPointerSet (operand * right,
8819 sym_link *retype, *letype;
8821 retype = getSpec (operandType (right));
8822 letype = getSpec (operandType (result));
8824 aopOp (result, ic, FALSE, FALSE);
8826 /* if the value is already in a pointer register
8827 then don't need anything more */
8828 if (!AOP_INPREG (AOP (result)))
8830 /* otherwise get a free pointer register */
8832 preg = getFreePtr (ic, &aop, FALSE);
8833 emitcode ("mov", "%s,%s",
8835 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8839 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8841 freeAsmop (result, NULL, ic, TRUE);
8842 aopOp (right, ic, FALSE, FALSE);
8844 /* if bitfield then unpack the bits */
8845 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8846 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8849 /* we have can just get the values */
8850 int size = AOP_SIZE (right);
8855 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8858 emitcode ("movx", "@%s,a", rname);
8861 emitcode ("inc", "%s", rname);
8867 /* now some housekeeping stuff */
8870 /* we had to allocate for this iCode */
8871 freeAsmop (NULL, aop, ic, TRUE);
8875 /* we did not allocate which means left
8876 already in a pointer register, then
8877 if size > 0 && this could be used again
8878 we have to point it back to where it
8880 if (AOP_SIZE (right) > 1 &&
8881 !OP_SYMBOL (result)->remat &&
8882 (OP_SYMBOL (result)->liveTo > ic->seq ||
8885 int size = AOP_SIZE (right) - 1;
8887 emitcode ("dec", "%s", rname);
8892 freeAsmop (right, NULL, ic, TRUE);
8897 /*-----------------------------------------------------------------*/
8898 /* genFarPointerSet - set value from far space */
8899 /*-----------------------------------------------------------------*/
8901 genFarPointerSet (operand * right,
8902 operand * result, iCode * ic)
8905 sym_link *retype = getSpec (operandType (right));
8906 sym_link *letype = getSpec (operandType (result));
8908 aopOp (result, ic, FALSE, FALSE);
8910 /* if the operand is already in dptr
8911 then we do nothing else we move the value to dptr */
8912 if (AOP_TYPE (result) != AOP_STR)
8914 /* if this is remateriazable */
8915 if (AOP_TYPE (result) == AOP_IMMD)
8916 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8919 /* we need to get it byte by byte */
8920 _startLazyDPSEvaluation ();
8921 if (AOP_TYPE (result) != AOP_DPTR)
8923 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8924 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8925 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8929 /* We need to generate a load to DPTR indirect through DPTR. */
8930 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8932 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8933 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8934 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8935 emitcode ("pop", "dph");
8936 emitcode ("pop", "dpl");
8938 _endLazyDPSEvaluation ();
8941 /* so dptr know contains the address */
8942 freeAsmop (result, NULL, ic, TRUE);
8943 aopOp (right, ic, FALSE, TRUE);
8945 /* if bit then unpack */
8946 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8947 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8950 size = AOP_SIZE (right);
8953 _startLazyDPSEvaluation ();
8956 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8962 emitcode ("movx", "@dptr,a");
8964 emitcode ("inc", "dptr");
8966 _endLazyDPSEvaluation ();
8969 freeAsmop (right, NULL, ic, TRUE);
8972 /*-----------------------------------------------------------------*/
8973 /* genGenPointerSet - set value from generic pointer space */
8974 /*-----------------------------------------------------------------*/
8976 genGenPointerSet (operand * right,
8977 operand * result, iCode * ic)
8980 sym_link *retype = getSpec (operandType (right));
8981 sym_link *letype = getSpec (operandType (result));
8983 aopOp (result, ic, FALSE, TRUE);
8985 /* if the operand is already in dptr
8986 then we do nothing else we move the value to dptr */
8987 if (AOP_TYPE (result) != AOP_STR)
8989 _startLazyDPSEvaluation ();
8990 /* if this is remateriazable */
8991 if (AOP_TYPE (result) == AOP_IMMD)
8993 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8994 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8997 { /* we need to get it byte by byte */
8998 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8999 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9000 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9001 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9003 _endLazyDPSEvaluation ();
9005 /* so dptr know contains the address */
9006 freeAsmop (result, NULL, ic, TRUE);
9007 aopOp (right, ic, FALSE, TRUE);
9009 /* if bit then unpack */
9010 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9011 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9014 size = AOP_SIZE (right);
9017 _startLazyDPSEvaluation ();
9020 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9026 emitcode ("lcall", "__gptrput");
9028 emitcode ("inc", "dptr");
9030 _endLazyDPSEvaluation ();
9033 freeAsmop (right, NULL, ic, TRUE);
9036 /*-----------------------------------------------------------------*/
9037 /* genPointerSet - stores the value into a pointer location */
9038 /*-----------------------------------------------------------------*/
9040 genPointerSet (iCode * ic)
9042 operand *right, *result;
9043 sym_link *type, *etype;
9046 D (emitcode (";", "genPointerSet ");
9049 right = IC_RIGHT (ic);
9050 result = IC_RESULT (ic);
9052 /* depending on the type of pointer we need to
9053 move it to the correct pointer register */
9054 type = operandType (result);
9055 etype = getSpec (type);
9056 /* if left is of type of pointer then it is simple */
9057 if (IS_PTR (type) && !IS_FUNC (type->next))
9059 p_type = DCL_TYPE (type);
9063 /* we have to go by the storage class */
9064 p_type = PTR_TYPE (SPEC_OCLS (etype));
9067 /* now that we have the pointer type we assign
9068 the pointer values */
9074 genNearPointerSet (right, result, ic);
9078 genPagedPointerSet (right, result, ic);
9082 genFarPointerSet (right, result, ic);
9086 genGenPointerSet (right, result, ic);
9092 /*-----------------------------------------------------------------*/
9093 /* genIfx - generate code for Ifx statement */
9094 /*-----------------------------------------------------------------*/
9096 genIfx (iCode * ic, iCode * popIc)
9098 operand *cond = IC_COND (ic);
9101 D (emitcode (";", "genIfx "););
9103 aopOp (cond, ic, FALSE, FALSE);
9105 /* get the value into acc */
9106 if (AOP_TYPE (cond) != AOP_CRY)
9110 /* the result is now in the accumulator */
9111 freeAsmop (cond, NULL, ic, TRUE);
9113 /* if there was something to be popped then do it */
9117 /* if the condition is a bit variable */
9118 if (isbit && IS_ITEMP (cond) &&
9120 genIfxJump (ic, SPIL_LOC (cond)->rname);
9121 else if (isbit && !IS_ITEMP (cond))
9122 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9124 genIfxJump (ic, "a");
9129 /*-----------------------------------------------------------------*/
9130 /* genAddrOf - generates code for address of */
9131 /*-----------------------------------------------------------------*/
9133 genAddrOf (iCode * ic)
9135 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9138 D (emitcode (";", "genAddrOf ");
9141 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9143 /* if the operand is on the stack then we
9144 need to get the stack offset of this
9148 /* if it has an offset then we need to compute
9152 emitcode ("mov", "a,_bp");
9153 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9154 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9158 /* we can just move _bp */
9159 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9161 /* fill the result with zero */
9162 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9165 if (options.stack10bit && size < (FPTRSIZE - 1))
9168 "*** warning: pointer to stack var truncated.\n");
9175 if (options.stack10bit && offset == 2)
9177 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9181 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9188 /* object not on stack then we need the name */
9189 size = AOP_SIZE (IC_RESULT (ic));
9194 char s[SDCC_NAME_MAX];
9196 sprintf (s, "#(%s >> %d)",
9200 sprintf (s, "#%s", sym->rname);
9201 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9205 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9209 /*-----------------------------------------------------------------*/
9210 /* genFarFarAssign - assignment when both are in far space */
9211 /*-----------------------------------------------------------------*/
9213 genFarFarAssign (operand * result, operand * right, iCode * ic)
9215 int size = AOP_SIZE (right);
9217 symbol *rSym = NULL;
9221 /* quick & easy case. */
9222 D(emitcode(";","genFarFarAssign (1 byte case)"););
9223 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9224 freeAsmop (right, NULL, ic, FALSE);
9225 /* now assign DPTR to result */
9227 aopOp(result, ic, FALSE, FALSE);
9229 aopPut(AOP(result), "a", 0);
9230 freeAsmop(result, NULL, ic, FALSE);
9234 /* See if we've got an underlying symbol to abuse. */
9235 if (IS_SYMOP(result) && OP_SYMBOL(result))
9237 if (IS_TRUE_SYMOP(result))
9239 rSym = OP_SYMBOL(result);
9241 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9243 rSym = OP_SYMBOL(result)->usl.spillLoc;
9247 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9249 /* We can use the '390 auto-toggle feature to good effect here. */
9251 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9252 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9253 emitcode ("mov", "dptr,#%s", rSym->rname);
9254 /* DP2 = result, DP1 = right, DP1 is current. */
9257 emitcode("movx", "a,@dptr");
9258 emitcode("movx", "@dptr,a");
9261 emitcode("inc", "dptr");
9262 emitcode("inc", "dptr");
9265 emitcode("mov", "dps, #0");
9266 freeAsmop (right, NULL, ic, FALSE);
9270 D (emitcode (";", "genFarFarAssign"););
9271 aopOp (result, ic, TRUE, TRUE);
9273 _startLazyDPSEvaluation ();
9277 aopPut (AOP (result),
9278 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9281 _endLazyDPSEvaluation ();
9282 freeAsmop (result, NULL, ic, FALSE);
9283 freeAsmop (right, NULL, ic, FALSE);
9287 /*-----------------------------------------------------------------*/
9288 /* genAssign - generate code for assignment */
9289 /*-----------------------------------------------------------------*/
9291 genAssign (iCode * ic)
9293 operand *result, *right;
9295 unsigned long lit = 0L;
9297 D (emitcode (";", "genAssign ");
9300 result = IC_RESULT (ic);
9301 right = IC_RIGHT (ic);
9303 /* if they are the same */
9304 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9307 aopOp (right, ic, FALSE, FALSE);
9309 emitcode (";", "genAssign: resultIsFar = %s",
9310 isOperandInFarSpace (result) ?
9313 /* special case both in far space */
9314 if ((AOP_TYPE (right) == AOP_DPTR ||
9315 AOP_TYPE (right) == AOP_DPTR2) &&
9316 /* IS_TRUE_SYMOP(result) && */
9317 isOperandInFarSpace (result))
9319 genFarFarAssign (result, right, ic);
9323 aopOp (result, ic, TRUE, FALSE);
9325 /* if they are the same registers */
9326 if (sameRegs (AOP (right), AOP (result)))
9329 /* if the result is a bit */
9330 if (AOP_TYPE (result) == AOP_CRY)
9333 /* if the right size is a literal then
9334 we know what the value is */
9335 if (AOP_TYPE (right) == AOP_LIT)
9337 if (((int) operandLitValue (right)))
9338 aopPut (AOP (result), one, 0);
9340 aopPut (AOP (result), zero, 0);
9344 /* the right is also a bit variable */
9345 if (AOP_TYPE (right) == AOP_CRY)
9347 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9348 aopPut (AOP (result), "c", 0);
9354 aopPut (AOP (result), "a", 0);
9358 /* bit variables done */
9360 size = AOP_SIZE (result);
9362 if (AOP_TYPE (right) == AOP_LIT)
9363 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9366 (AOP_TYPE (result) != AOP_REG) &&
9367 (AOP_TYPE (right) == AOP_LIT) &&
9368 !IS_FLOAT (operandType (right)))
9370 _startLazyDPSEvaluation ();
9371 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9373 aopPut (AOP (result),
9374 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9379 /* And now fill the rest with zeros. */
9382 emitcode ("clr", "a");
9386 aopPut (AOP (result), "a", offset++);
9388 _endLazyDPSEvaluation ();
9392 _startLazyDPSEvaluation ();
9395 aopPut (AOP (result),
9396 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9400 _endLazyDPSEvaluation ();
9404 freeAsmop (right, NULL, ic, FALSE);
9405 freeAsmop (result, NULL, ic, TRUE);
9408 /*-----------------------------------------------------------------*/
9409 /* genJumpTab - generates code for jump table */
9410 /*-----------------------------------------------------------------*/
9412 genJumpTab (iCode * ic)
9417 D (emitcode (";", "genJumpTab ");
9420 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9421 /* get the condition into accumulator */
9422 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9424 /* multiply by four! */
9425 emitcode ("add", "a,acc");
9426 emitcode ("add", "a,acc");
9427 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9429 jtab = newiTempLabel (NULL);
9430 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9431 emitcode ("jmp", "@a+dptr");
9432 emitcode ("", "%05d$:", jtab->key + 100);
9433 /* now generate the jump labels */
9434 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9435 jtab = setNextItem (IC_JTLABELS (ic)))
9436 emitcode ("ljmp", "%05d$", jtab->key + 100);
9440 /*-----------------------------------------------------------------*/
9441 /* genCast - gen code for casting */
9442 /*-----------------------------------------------------------------*/
9444 genCast (iCode * ic)
9446 operand *result = IC_RESULT (ic);
9447 sym_link *ctype = operandType (IC_LEFT (ic));
9448 sym_link *rtype = operandType (IC_RIGHT (ic));
9449 operand *right = IC_RIGHT (ic);
9452 D (emitcode (";", "genCast ");
9455 /* if they are equivalent then do nothing */
9456 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9459 aopOp (right, ic, FALSE, FALSE);
9460 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9462 /* if the result is a bit */
9463 if (AOP_TYPE (result) == AOP_CRY)
9465 /* if the right size is a literal then
9466 we know what the value is */
9467 if (AOP_TYPE (right) == AOP_LIT)
9469 if (((int) operandLitValue (right)))
9470 aopPut (AOP (result), one, 0);
9472 aopPut (AOP (result), zero, 0);
9477 /* the right is also a bit variable */
9478 if (AOP_TYPE (right) == AOP_CRY)
9480 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9481 aopPut (AOP (result), "c", 0);
9487 aopPut (AOP (result), "a", 0);
9491 /* if they are the same size : or less */
9492 if (AOP_SIZE (result) <= AOP_SIZE (right))
9495 /* if they are in the same place */
9496 if (sameRegs (AOP (right), AOP (result)))
9499 /* if they in different places then copy */
9500 size = AOP_SIZE (result);
9502 _startLazyDPSEvaluation ();
9505 aopPut (AOP (result),
9506 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9510 _endLazyDPSEvaluation ();
9515 /* if the result is of type pointer */
9520 sym_link *type = operandType (right);
9522 /* pointer to generic pointer */
9523 if (IS_GENPTR (ctype))
9529 p_type = DCL_TYPE (type);
9533 #if OLD_CAST_BEHAVIOR
9534 /* KV: we are converting a non-pointer type to
9535 * a generic pointer. This (ifdef'd out) code
9536 * says that the resulting generic pointer
9537 * should have the same class as the storage
9538 * location of the non-pointer variable.
9540 * For example, converting an int (which happens
9541 * to be stored in DATA space) to a pointer results
9542 * in a DATA generic pointer; if the original int
9543 * in XDATA space, so will be the resulting pointer.
9545 * I don't like that behavior, and thus this change:
9546 * all such conversions will be forced to XDATA and
9547 * throw a warning. If you want some non-XDATA
9548 * type, or you want to suppress the warning, you
9549 * must go through an intermediate cast, like so:
9551 * char _generic *gp = (char _xdata *)(intVar);
9553 sym_link *etype = getSpec (type);
9555 /* we have to go by the storage class */
9556 if (SPEC_OCLS (etype) != generic)
9558 p_type = PTR_TYPE (SPEC_OCLS (etype));
9563 /* Converting unknown class (i.e. register variable)
9564 * to generic pointer. This is not good, but
9565 * we'll make a guess (and throw a warning).
9568 werror (W_INT_TO_GEN_PTR_CAST);
9572 /* the first two bytes are known */
9573 size = GPTRSIZE - 1;
9575 _startLazyDPSEvaluation ();
9578 aopPut (AOP (result),
9579 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9583 _endLazyDPSEvaluation ();
9585 /* the last byte depending on type */
9603 /* this should never happen */
9604 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9605 "got unknown pointer type");
9608 aopPut (AOP (result), l, GPTRSIZE - 1);
9612 /* just copy the pointers */
9613 size = AOP_SIZE (result);
9615 _startLazyDPSEvaluation ();
9618 aopPut (AOP (result),
9619 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9623 _endLazyDPSEvaluation ();
9627 /* so we now know that the size of destination is greater
9628 than the size of the source */
9629 /* we move to result for the size of source */
9630 size = AOP_SIZE (right);
9632 _startLazyDPSEvaluation ();
9635 aopPut (AOP (result),
9636 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9640 _endLazyDPSEvaluation ();
9642 /* now depending on the sign of the source && destination */
9643 size = AOP_SIZE (result) - AOP_SIZE (right);
9644 /* if unsigned or not an integral type */
9645 /* also, if the source is a bit, we don't need to sign extend, because
9646 * it can't possibly have set the sign bit.
9648 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9652 aopPut (AOP (result), zero, offset++);
9657 /* we need to extend the sign :{ */
9658 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9659 FALSE, FALSE, TRUE);
9661 emitcode ("rlc", "a");
9662 emitcode ("subb", "a,acc");
9664 aopPut (AOP (result), "a", offset++);
9667 /* we are done hurray !!!! */
9670 freeAsmop (right, NULL, ic, TRUE);
9671 freeAsmop (result, NULL, ic, TRUE);
9675 /*-----------------------------------------------------------------*/
9676 /* genDjnz - generate decrement & jump if not zero instrucion */
9677 /*-----------------------------------------------------------------*/
9679 genDjnz (iCode * ic, iCode * ifx)
9685 /* if the if condition has a false label
9686 then we cannot save */
9690 /* if the minus is not of the form
9692 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9693 !IS_OP_LITERAL (IC_RIGHT (ic)))
9696 if (operandLitValue (IC_RIGHT (ic)) != 1)
9699 /* if the size of this greater than one then no
9701 if (getSize (operandType (IC_RESULT (ic))) > 1)
9704 /* otherwise we can save BIG */
9705 D(emitcode(";", "genDjnz"););
9707 lbl = newiTempLabel (NULL);
9708 lbl1 = newiTempLabel (NULL);
9710 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9712 if (AOP_NEEDSACC(IC_RESULT(ic)))
9714 /* If the result is accessed indirectly via
9715 * the accumulator, we must explicitly write
9716 * it back after the decrement.
9718 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9720 if (strcmp(rByte, "a"))
9722 /* Something is hopelessly wrong */
9723 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9724 __FILE__, __LINE__);
9725 /* We can just give up; the generated code will be inefficient,
9728 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9731 emitcode ("dec", "%s", rByte);
9732 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9733 emitcode ("jnz", "%05d$", lbl->key + 100);
9735 else if (IS_AOP_PREG (IC_RESULT (ic)))
9737 emitcode ("dec", "%s",
9738 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9739 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9740 emitcode ("jnz", "%05d$", lbl->key + 100);
9744 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9747 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9748 emitcode ("", "%05d$:", lbl->key + 100);
9749 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9750 emitcode ("", "%05d$:", lbl1->key + 100);
9752 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9757 /*-----------------------------------------------------------------*/
9758 /* genReceive - generate code for a receive iCode */
9759 /*-----------------------------------------------------------------*/
9761 genReceive (iCode * ic)
9764 D (emitcode (";", "genReceive ");
9767 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9768 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9769 IS_TRUE_SYMOP (IC_RESULT (ic))))
9771 int size = getSize (operandType (IC_RESULT (ic)));
9772 int offset = fReturnSizeDS390 - size;
9775 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9776 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9779 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9780 size = AOP_SIZE (IC_RESULT (ic));
9784 emitcode ("pop", "acc");
9785 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9792 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9794 assignResultValue (IC_RESULT (ic));
9797 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9800 /*-----------------------------------------------------------------*/
9801 /* gen390Code - generate code for Dallas 390 based controllers */
9802 /*-----------------------------------------------------------------*/
9804 gen390Code (iCode * lic)
9809 lineHead = lineCurr = NULL;
9813 /* print the allocation information */
9815 printAllocInfo (currFunc, codeOutFile);
9817 /* if debug information required */
9818 if (options.debug && currFunc)
9820 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9822 if (IS_STATIC (currFunc->etype))
9823 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9825 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9828 /* stack pointer name */
9829 if (options.useXstack)
9835 for (ic = lic; ic; ic = ic->next)
9838 if (cln != ic->lineno)
9843 emitcode ("", "C$%s$%d$%d$%d ==.",
9844 FileBaseName (ic->filename), ic->lineno,
9845 ic->level, ic->block);
9848 emitcode (";", "%s %d", ic->filename, ic->lineno);
9851 /* if the result is marked as
9852 spilt and rematerializable or code for
9853 this has already been generated then
9855 if (resultRemat (ic) || ic->generated)
9858 /* depending on the operation */
9878 /* IPOP happens only when trying to restore a
9879 spilt live range, if there is an ifx statement
9880 following this pop then the if statement might
9881 be using some of the registers being popped which
9882 would destory the contents of the register so
9883 we need to check for this condition and handle it */
9885 ic->next->op == IFX &&
9886 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9887 genIfx (ic->next, ic);
9905 genEndFunction (ic);
9925 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9942 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9946 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9953 /* note these two are xlated by algebraic equivalence
9954 during parsing SDCC.y */
9955 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9956 "got '>=' or '<=' shouldn't have come here");
9960 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9972 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9976 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9980 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10004 genRightShift (ic);
10007 case GET_VALUE_AT_ADDRESS:
10008 genPointerGet (ic);
10012 if (POINTER_SET (ic))
10013 genPointerSet (ic);
10039 addSet (&_G.sendSet, ic);
10048 /* now we are ready to call the
10049 peep hole optimizer */
10050 if (!options.nopeep)
10051 peepHole (&lineHead);
10053 /* now do the actual printing */
10054 printLine (lineHead, codeOutFile);