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 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5660 emitcode ("orl", "a,%s",
5661 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5662 emitcode ("jnz", "%05d$", tlbl->key + 100);
5668 emitcode ("", "%05d$:", tlbl->key + 100);
5672 jmpTrueOrFalse (ifx, tlbl);
5676 for (; (size--); offset++)
5679 // result = left & right
5680 if (AOP_TYPE (right) == AOP_LIT)
5682 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5684 aopPut (AOP (result),
5685 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5689 D (emitcode (";", "better literal OR.");
5691 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5692 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5693 FALSE, FALSE, FALSE));
5698 // faster than result <- left, anl result,right
5699 // and better if result is SFR
5700 if (AOP_TYPE (left) == AOP_ACC)
5702 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5703 FALSE, FALSE, FALSE));
5707 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5708 emitcode ("orl", "a,%s",
5709 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5712 aopPut (AOP (result), "a", offset);
5718 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5719 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5720 freeAsmop (result, NULL, ic, TRUE);
5723 /*-----------------------------------------------------------------*/
5724 /* genXor - code for xclusive or */
5725 /*-----------------------------------------------------------------*/
5727 genXor (iCode * ic, iCode * ifx)
5729 operand *left, *right, *result;
5730 int size, offset = 0;
5731 unsigned long lit = 0L;
5734 D (emitcode (";", "genXor "););
5736 AOP_OP_3_NOFATAL (ic, pushResult);
5737 AOP_SET_LOCALS (ic);
5741 genFarFarLogicOp(ic, "xrl");
5746 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5748 AOP_TYPE (left), AOP_TYPE (right));
5749 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5751 AOP_SIZE (left), AOP_SIZE (right));
5754 /* if left is a literal & right is not ||
5755 if left needs acc & right does not */
5756 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5757 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5759 operand *tmp = right;
5764 /* if result = right then exchange them */
5765 if (sameRegs (AOP (result), AOP (right)))
5767 operand *tmp = right;
5772 /* if right is bit then exchange them */
5773 if (AOP_TYPE (right) == AOP_CRY &&
5774 AOP_TYPE (left) != AOP_CRY)
5776 operand *tmp = right;
5780 if (AOP_TYPE (right) == AOP_LIT)
5781 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5783 size = AOP_SIZE (result);
5787 if (AOP_TYPE (left) == AOP_CRY)
5789 if (AOP_TYPE (right) == AOP_LIT)
5791 // c = bit & literal;
5794 // lit>>1 != 0 => result = 1
5795 if (AOP_TYPE (result) == AOP_CRY)
5798 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5800 continueIfTrue (ifx);
5803 emitcode ("setb", "c");
5810 // lit == 0, result = left
5811 if (size && sameRegs (AOP (result), AOP (left)))
5813 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5817 // lit == 1, result = not(left)
5818 if (size && sameRegs (AOP (result), AOP (left)))
5820 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5825 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5826 emitcode ("cpl", "c");
5835 symbol *tlbl = newiTempLabel (NULL);
5836 if (AOP_TYPE (right) == AOP_CRY)
5839 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5843 int sizer = AOP_SIZE (right);
5845 // if val>>1 != 0, result = 1
5846 emitcode ("setb", "c");
5849 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5851 // test the msb of the lsb
5852 emitcode ("anl", "a,#0xfe");
5853 emitcode ("jnz", "%05d$", tlbl->key + 100);
5857 emitcode ("rrc", "a");
5859 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5860 emitcode ("cpl", "c");
5861 emitcode ("", "%05d$:", (tlbl->key + 100));
5868 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5869 genIfxJump (ifx, "c");
5873 if (sameRegs (AOP (result), AOP (left)))
5875 /* if left is same as result */
5876 for (; size--; offset++)
5878 if (AOP_TYPE (right) == AOP_LIT)
5880 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5882 else if (IS_AOP_PREG (left))
5884 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5885 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5886 aopPut (AOP (result), "a", offset);
5889 emitcode ("xrl", "%s,%s",
5890 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5891 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5895 if (AOP_TYPE (left) == AOP_ACC)
5896 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5899 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5900 if (IS_AOP_PREG (left))
5902 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5903 aopPut (AOP (result), "a", offset);
5906 emitcode ("xrl", "%s,a",
5907 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5914 // left & result in different registers
5915 if (AOP_TYPE (result) == AOP_CRY)
5918 // if(size), result in bit
5919 // if(!size && ifx), conditional oper: if(left ^ right)
5920 symbol *tlbl = newiTempLabel (NULL);
5921 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5923 emitcode ("setb", "c");
5926 if ((AOP_TYPE (right) == AOP_LIT) &&
5927 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5929 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5933 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5934 emitcode ("xrl", "a,%s",
5935 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5937 emitcode ("jnz", "%05d$", tlbl->key + 100);
5943 emitcode ("", "%05d$:", tlbl->key + 100);
5947 jmpTrueOrFalse (ifx, tlbl);
5950 for (; (size--); offset++)
5953 // result = left & right
5954 if (AOP_TYPE (right) == AOP_LIT)
5956 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5958 aopPut (AOP (result),
5959 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5963 D (emitcode (";", "better literal XOR.");
5965 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5966 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5967 FALSE, FALSE, FALSE));
5971 // faster than result <- left, anl result,right
5972 // and better if result is SFR
5973 if (AOP_TYPE (left) == AOP_ACC)
5975 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5976 FALSE, FALSE, FALSE));
5980 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5981 emitcode ("xrl", "a,%s",
5982 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5985 aopPut (AOP (result), "a", offset);
5990 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5991 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5992 freeAsmop (result, NULL, ic, TRUE);
5995 /*-----------------------------------------------------------------*/
5996 /* genInline - write the inline code out */
5997 /*-----------------------------------------------------------------*/
5999 genInline (iCode * ic)
6001 char *buffer, *bp, *bp1;
6003 D (emitcode (";", "genInline ");
6006 _G.inLine += (!options.asmpeep);
6008 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6009 strcpy (buffer, IC_INLINE (ic));
6011 /* emit each line as a code */
6036 /* emitcode("",buffer); */
6037 _G.inLine -= (!options.asmpeep);
6040 /*-----------------------------------------------------------------*/
6041 /* genRRC - rotate right with carry */
6042 /*-----------------------------------------------------------------*/
6046 operand *left, *result;
6047 int size, offset = 0;
6050 D (emitcode (";", "genRRC ");
6053 /* rotate right with carry */
6054 left = IC_LEFT (ic);
6055 result = IC_RESULT (ic);
6056 aopOp (left, ic, FALSE, FALSE);
6057 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6059 /* move it to the result */
6060 size = AOP_SIZE (result);
6064 _startLazyDPSEvaluation ();
6067 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6069 emitcode ("rrc", "a");
6070 if (AOP_SIZE (result) > 1)
6071 aopPut (AOP (result), "a", offset--);
6073 _endLazyDPSEvaluation ();
6075 /* now we need to put the carry into the
6076 highest order byte of the result */
6077 if (AOP_SIZE (result) > 1)
6079 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6082 emitcode ("mov", "acc.7,c");
6083 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6084 freeAsmop (left, NULL, ic, TRUE);
6085 freeAsmop (result, NULL, ic, TRUE);
6088 /*-----------------------------------------------------------------*/
6089 /* genRLC - generate code for rotate left with carry */
6090 /*-----------------------------------------------------------------*/
6094 operand *left, *result;
6095 int size, offset = 0;
6098 D (emitcode (";", "genRLC ");
6101 /* rotate right with carry */
6102 left = IC_LEFT (ic);
6103 result = IC_RESULT (ic);
6104 aopOp (left, ic, FALSE, FALSE);
6105 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6107 /* move it to the result */
6108 size = AOP_SIZE (result);
6112 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6114 emitcode ("add", "a,acc");
6115 if (AOP_SIZE (result) > 1)
6117 aopPut (AOP (result), "a", offset++);
6120 _startLazyDPSEvaluation ();
6123 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6125 emitcode ("rlc", "a");
6126 if (AOP_SIZE (result) > 1)
6127 aopPut (AOP (result), "a", offset++);
6129 _endLazyDPSEvaluation ();
6131 /* now we need to put the carry into the
6132 highest order byte of the result */
6133 if (AOP_SIZE (result) > 1)
6135 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6138 emitcode ("mov", "acc.0,c");
6139 aopPut (AOP (result), "a", 0);
6140 freeAsmop (left, NULL, ic, TRUE);
6141 freeAsmop (result, NULL, ic, TRUE);
6144 /*-----------------------------------------------------------------*/
6145 /* genGetHbit - generates code get highest order bit */
6146 /*-----------------------------------------------------------------*/
6148 genGetHbit (iCode * ic)
6150 operand *left, *result;
6151 left = IC_LEFT (ic);
6152 result = IC_RESULT (ic);
6153 aopOp (left, ic, FALSE, FALSE);
6154 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6156 D (emitcode (";", "genGetHbit ");
6159 /* get the highest order byte into a */
6160 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6161 if (AOP_TYPE (result) == AOP_CRY)
6163 emitcode ("rlc", "a");
6168 emitcode ("rl", "a");
6169 emitcode ("anl", "a,#0x01");
6174 freeAsmop (left, NULL, ic, TRUE);
6175 freeAsmop (result, NULL, ic, TRUE);
6178 /*-----------------------------------------------------------------*/
6179 /* AccRol - rotate left accumulator by known count */
6180 /*-----------------------------------------------------------------*/
6182 AccRol (int shCount)
6184 shCount &= 0x0007; // shCount : 0..7
6191 emitcode ("rl", "a");
6194 emitcode ("rl", "a");
6195 emitcode ("rl", "a");
6198 emitcode ("swap", "a");
6199 emitcode ("rr", "a");
6202 emitcode ("swap", "a");
6205 emitcode ("swap", "a");
6206 emitcode ("rl", "a");
6209 emitcode ("rr", "a");
6210 emitcode ("rr", "a");
6213 emitcode ("rr", "a");
6218 /*-----------------------------------------------------------------*/
6219 /* AccLsh - left shift accumulator by known count */
6220 /*-----------------------------------------------------------------*/
6222 AccLsh (int shCount)
6227 emitcode ("add", "a,acc");
6228 else if (shCount == 2)
6230 emitcode ("add", "a,acc");
6231 emitcode ("add", "a,acc");
6235 /* rotate left accumulator */
6237 /* and kill the lower order bits */
6238 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6243 /*-----------------------------------------------------------------*/
6244 /* AccRsh - right shift accumulator by known count */
6245 /*-----------------------------------------------------------------*/
6247 AccRsh (int shCount)
6254 emitcode ("rrc", "a");
6258 /* rotate right accumulator */
6259 AccRol (8 - shCount);
6260 /* and kill the higher order bits */
6261 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6266 #ifdef BETTER_LITERAL_SHIFT
6267 /*-----------------------------------------------------------------*/
6268 /* AccSRsh - signed right shift accumulator by known count */
6269 /*-----------------------------------------------------------------*/
6271 AccSRsh (int shCount)
6278 emitcode ("mov", "c,acc.7");
6279 emitcode ("rrc", "a");
6281 else if (shCount == 2)
6283 emitcode ("mov", "c,acc.7");
6284 emitcode ("rrc", "a");
6285 emitcode ("mov", "c,acc.7");
6286 emitcode ("rrc", "a");
6290 tlbl = newiTempLabel (NULL);
6291 /* rotate right accumulator */
6292 AccRol (8 - shCount);
6293 /* and kill the higher order bits */
6294 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6295 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6296 emitcode ("orl", "a,#0x%02x",
6297 (unsigned char) ~SRMask[shCount]);
6298 emitcode ("", "%05d$:", tlbl->key + 100);
6304 #ifdef BETTER_LITERAL_SHIFT
6305 /*-----------------------------------------------------------------*/
6306 /* shiftR1Left2Result - shift right one byte from left to result */
6307 /*-----------------------------------------------------------------*/
6309 shiftR1Left2Result (operand * left, int offl,
6310 operand * result, int offr,
6311 int shCount, int sign)
6313 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6314 /* shift right accumulator */
6319 aopPut (AOP (result), "a", offr);
6323 #ifdef BETTER_LITERAL_SHIFT
6324 /*-----------------------------------------------------------------*/
6325 /* shiftL1Left2Result - shift left one byte from left to result */
6326 /*-----------------------------------------------------------------*/
6328 shiftL1Left2Result (operand * left, int offl,
6329 operand * result, int offr, int shCount)
6331 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6332 /* shift left accumulator */
6334 aopPut (AOP (result), "a", offr);
6338 #ifdef BETTER_LITERAL_SHIFT
6339 /*-----------------------------------------------------------------*/
6340 /* movLeft2Result - move byte from left to result */
6341 /*-----------------------------------------------------------------*/
6343 movLeft2Result (operand * left, int offl,
6344 operand * result, int offr, int sign)
6347 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6349 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6351 if (*l == '@' && (IS_AOP_PREG (result)))
6353 emitcode ("mov", "a,%s", l);
6354 aopPut (AOP (result), "a", offr);
6360 aopPut (AOP (result), l, offr);
6364 /* MSB sign in acc.7 ! */
6365 if (getDataSize (left) == offl + 1)
6367 emitcode ("mov", "a,%s", l);
6368 aopPut (AOP (result), "a", offr);
6376 #ifdef BETTER_LITERAL_SHIFT
6377 /*-----------------------------------------------------------------*/
6378 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6379 /*-----------------------------------------------------------------*/
6383 emitcode ("rrc", "a");
6384 emitcode ("xch", "a,%s", x);
6385 emitcode ("rrc", "a");
6386 emitcode ("xch", "a,%s", x);
6390 #ifdef BETTER_LITERAL_SHIFT
6392 /*-----------------------------------------------------------------*/
6393 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6394 /*-----------------------------------------------------------------*/
6398 emitcode ("xch", "a,%s", x);
6399 emitcode ("rlc", "a");
6400 emitcode ("xch", "a,%s", x);
6401 emitcode ("rlc", "a");
6405 #ifdef BETTER_LITERAL_SHIFT
6406 /*-----------------------------------------------------------------*/
6407 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6408 /*-----------------------------------------------------------------*/
6412 emitcode ("xch", "a,%s", x);
6413 emitcode ("add", "a,acc");
6414 emitcode ("xch", "a,%s", x);
6415 emitcode ("rlc", "a");
6419 #ifdef BETTER_LITERAL_SHIFT
6420 /*-----------------------------------------------------------------*/
6421 /* AccAXLsh - left shift a:x by known count (0..7) */
6422 /*-----------------------------------------------------------------*/
6424 AccAXLsh (char *x, int shCount)
6439 case 5: // AAAAABBB:CCCCCDDD
6441 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6443 emitcode ("anl", "a,#0x%02x",
6444 SLMask[shCount]); // BBB00000:CCCCCDDD
6446 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6448 AccRol (shCount); // DDDCCCCC:BBB00000
6450 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6452 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6454 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6456 emitcode ("anl", "a,#0x%02x",
6457 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6459 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6461 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6464 case 6: // AAAAAABB:CCCCCCDD
6465 emitcode ("anl", "a,#0x%02x",
6466 SRMask[shCount]); // 000000BB:CCCCCCDD
6467 emitcode ("mov", "c,acc.0"); // c = B
6468 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6470 AccAXRrl1 (x); // BCCCCCCD:D000000B
6471 AccAXRrl1 (x); // BBCCCCCC:DD000000
6473 emitcode("rrc","a");
6474 emitcode("xch","a,%s", x);
6475 emitcode("rrc","a");
6476 emitcode("mov","c,acc.0"); //<< get correct bit
6477 emitcode("xch","a,%s", x);
6479 emitcode("rrc","a");
6480 emitcode("xch","a,%s", x);
6481 emitcode("rrc","a");
6482 emitcode("xch","a,%s", x);
6485 case 7: // a:x <<= 7
6487 emitcode ("anl", "a,#0x%02x",
6488 SRMask[shCount]); // 0000000B:CCCCCCCD
6490 emitcode ("mov", "c,acc.0"); // c = B
6492 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6494 AccAXRrl1 (x); // BCCCCCCC:D0000000
6503 #ifdef BETTER_LITERAL_SHIFT
6505 /*-----------------------------------------------------------------*/
6506 /* AccAXRsh - right shift a:x known count (0..7) */
6507 /*-----------------------------------------------------------------*/
6509 AccAXRsh (char *x, int shCount)
6517 AccAXRrl1 (x); // 0->a:x
6522 AccAXRrl1 (x); // 0->a:x
6525 AccAXRrl1 (x); // 0->a:x
6530 case 5: // AAAAABBB:CCCCCDDD = a:x
6532 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6534 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6536 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6538 emitcode ("anl", "a,#0x%02x",
6539 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6541 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6543 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6545 emitcode ("anl", "a,#0x%02x",
6546 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6548 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6550 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6552 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6555 case 6: // AABBBBBB:CCDDDDDD
6557 emitcode ("mov", "c,acc.7");
6558 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6560 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6562 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6564 emitcode ("anl", "a,#0x%02x",
6565 SRMask[shCount]); // 000000AA:BBBBBBCC
6568 case 7: // ABBBBBBB:CDDDDDDD
6570 emitcode ("mov", "c,acc.7"); // c = A
6572 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6574 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6576 emitcode ("anl", "a,#0x%02x",
6577 SRMask[shCount]); // 0000000A:BBBBBBBC
6586 #ifdef BETTER_LITERAL_SHIFT
6588 /*-----------------------------------------------------------------*/
6589 /* AccAXRshS - right shift signed a:x known count (0..7) */
6590 /*-----------------------------------------------------------------*/
6592 AccAXRshS (char *x, int shCount)
6600 emitcode ("mov", "c,acc.7");
6601 AccAXRrl1 (x); // s->a:x
6605 emitcode ("mov", "c,acc.7");
6606 AccAXRrl1 (x); // s->a:x
6608 emitcode ("mov", "c,acc.7");
6609 AccAXRrl1 (x); // s->a:x
6614 case 5: // AAAAABBB:CCCCCDDD = a:x
6616 tlbl = newiTempLabel (NULL);
6617 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6619 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6621 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6623 emitcode ("anl", "a,#0x%02x",
6624 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6626 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6628 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6630 emitcode ("anl", "a,#0x%02x",
6631 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6633 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6635 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6637 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6639 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6640 emitcode ("orl", "a,#0x%02x",
6641 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6643 emitcode ("", "%05d$:", tlbl->key + 100);
6644 break; // SSSSAAAA:BBBCCCCC
6646 case 6: // AABBBBBB:CCDDDDDD
6648 tlbl = newiTempLabel (NULL);
6649 emitcode ("mov", "c,acc.7");
6650 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6652 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6654 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6656 emitcode ("anl", "a,#0x%02x",
6657 SRMask[shCount]); // 000000AA:BBBBBBCC
6659 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6660 emitcode ("orl", "a,#0x%02x",
6661 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6663 emitcode ("", "%05d$:", tlbl->key + 100);
6665 case 7: // ABBBBBBB:CDDDDDDD
6667 tlbl = newiTempLabel (NULL);
6668 emitcode ("mov", "c,acc.7"); // c = A
6670 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6672 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6674 emitcode ("anl", "a,#0x%02x",
6675 SRMask[shCount]); // 0000000A:BBBBBBBC
6677 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6678 emitcode ("orl", "a,#0x%02x",
6679 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6681 emitcode ("", "%05d$:", tlbl->key + 100);
6689 #ifdef BETTER_LITERAL_SHIFT
6691 _loadLeftIntoAx(char **lsb,
6697 // Get the initial value from left into a pair of registers.
6698 // MSB must be in A, LSB can be any register.
6700 // If the result is held in registers, it is an optimization
6701 // if the LSB can be held in the register which will hold the,
6702 // result LSB since this saves us from having to copy it into
6703 // the result following AccAXLsh.
6705 // If the result is addressed indirectly, this is not a gain.
6706 if (AOP_NEEDSACC(result))
6710 _startLazyDPSEvaluation();
6711 if (AOP_TYPE(left) == AOP_DPTR2)
6714 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6715 // get LSB in DP2_RESULT_REG.
6716 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6717 assert(!strcmp(leftByte, DP2_RESULT_REG));
6721 // get LSB into DP2_RESULT_REG
6722 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6723 if (strcmp(leftByte, DP2_RESULT_REG))
6725 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6728 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6729 assert(strcmp(leftByte, DP2_RESULT_REG));
6732 _endLazyDPSEvaluation();
6733 *lsb = DP2_RESULT_REG;
6737 if (sameRegs (AOP (result), AOP (left)) &&
6738 ((offl + MSB16) == offr))
6740 /* don't crash result[offr] */
6741 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6742 emitcode ("xch", "a,%s",
6743 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6747 movLeft2Result (left, offl, result, offr, 0);
6748 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6750 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6751 assert(strcmp(*lsb,"a"));
6756 _storeAxResults(char *lsb,
6760 _startLazyDPSEvaluation();
6761 if (AOP_NEEDSACC(result))
6763 /* We have to explicitly update the result LSB.
6765 emitcode("xch","a,%s", lsb);
6766 aopPut(AOP(result), "a", offr);
6767 emitcode("mov","a,%s", lsb);
6769 if (getDataSize (result) > 1)
6771 aopPut (AOP (result), "a", offr + MSB16);
6773 _endLazyDPSEvaluation();
6776 /*-----------------------------------------------------------------*/
6777 /* shiftL2Left2Result - shift left two bytes from left to result */
6778 /*-----------------------------------------------------------------*/
6780 shiftL2Left2Result (operand * left, int offl,
6781 operand * result, int offr, int shCount)
6785 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6787 AccAXLsh (lsb, shCount);
6789 _storeAxResults(lsb, result, offr);
6793 #ifdef BETTER_LITERAL_SHIFT
6794 /*-----------------------------------------------------------------*/
6795 /* shiftR2Left2Result - shift right two bytes from left to result */
6796 /*-----------------------------------------------------------------*/
6798 shiftR2Left2Result (operand * left, int offl,
6799 operand * result, int offr,
6800 int shCount, int sign)
6804 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6806 /* a:x >> shCount (x = lsb(result)) */
6809 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6813 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6816 _storeAxResults(lsb, result, offr);
6822 /*-----------------------------------------------------------------*/
6823 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6824 /*-----------------------------------------------------------------*/
6826 shiftLLeftOrResult (operand * left, int offl,
6827 operand * result, int offr, int shCount)
6829 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6830 /* shift left accumulator */
6832 /* or with result */
6833 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6834 /* back to result */
6835 aopPut (AOP (result), "a", offr);
6841 /*-----------------------------------------------------------------*/
6842 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6843 /*-----------------------------------------------------------------*/
6845 shiftRLeftOrResult (operand * left, int offl,
6846 operand * result, int offr, int shCount)
6848 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6849 /* shift right accumulator */
6851 /* or with result */
6852 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6853 /* back to result */
6854 aopPut (AOP (result), "a", offr);
6858 #ifdef BETTER_LITERAL_SHIFT
6859 /*-----------------------------------------------------------------*/
6860 /* genlshOne - left shift a one byte quantity by known count */
6861 /*-----------------------------------------------------------------*/
6863 genlshOne (operand * result, operand * left, int shCount)
6865 D (emitcode (";", "genlshOne "););
6866 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6870 #ifdef BETTER_LITERAL_SHIFT
6871 /*-----------------------------------------------------------------*/
6872 /* genlshTwo - left shift two bytes by known amount != 0 */
6873 /*-----------------------------------------------------------------*/
6875 genlshTwo (operand * result, operand * left, int shCount)
6879 D (emitcode (";", "genlshTwo "););
6881 size = getDataSize (result);
6883 /* if shCount >= 8 */
6888 _startLazyDPSEvaluation();
6894 _endLazyDPSEvaluation();
6895 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6896 aopPut (AOP (result), zero, LSB);
6900 movLeft2Result (left, LSB, result, MSB16, 0);
6901 aopPut (AOP (result), zero, LSB);
6902 _endLazyDPSEvaluation();
6907 aopPut (AOP (result), zero, LSB);
6908 _endLazyDPSEvaluation();
6912 /* 1 <= shCount <= 7 */
6917 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6921 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6929 /*-----------------------------------------------------------------*/
6930 /* shiftLLong - shift left one long from left to result */
6931 /* offl = LSB or MSB16 */
6932 /*-----------------------------------------------------------------*/
6934 shiftLLong (operand * left, operand * result, int offr)
6937 int size = AOP_SIZE (result);
6939 if (size >= LSB + offr)
6941 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6943 emitcode ("add", "a,acc");
6944 if (sameRegs (AOP (left), AOP (result)) &&
6945 size >= MSB16 + offr && offr != LSB)
6946 emitcode ("xch", "a,%s",
6947 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6949 aopPut (AOP (result), "a", LSB + offr);
6952 if (size >= MSB16 + offr)
6954 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6956 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6959 emitcode ("rlc", "a");
6960 if (sameRegs (AOP (left), AOP (result)) &&
6961 size >= MSB24 + offr && offr != LSB)
6962 emitcode ("xch", "a,%s",
6963 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6965 aopPut (AOP (result), "a", MSB16 + offr);
6968 if (size >= MSB24 + offr)
6970 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6972 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6975 emitcode ("rlc", "a");
6976 if (sameRegs (AOP (left), AOP (result)) &&
6977 size >= MSB32 + offr && offr != LSB)
6978 emitcode ("xch", "a,%s",
6979 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6981 aopPut (AOP (result), "a", MSB24 + offr);
6984 if (size > MSB32 + offr)
6986 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6988 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6991 emitcode ("rlc", "a");
6992 aopPut (AOP (result), "a", MSB32 + offr);
6995 aopPut (AOP (result), zero, LSB);
7001 /*-----------------------------------------------------------------*/
7002 /* genlshFour - shift four byte by a known amount != 0 */
7003 /*-----------------------------------------------------------------*/
7005 genlshFour (operand * result, operand * left, int shCount)
7009 D (emitcode (";", "genlshFour ");
7012 size = AOP_SIZE (result);
7014 /* if shifting more that 3 bytes */
7019 /* lowest order of left goes to the highest
7020 order of the destination */
7021 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7023 movLeft2Result (left, LSB, result, MSB32, 0);
7024 aopPut (AOP (result), zero, LSB);
7025 aopPut (AOP (result), zero, MSB16);
7026 aopPut (AOP (result), zero, MSB24);
7030 /* more than two bytes */
7031 else if (shCount >= 16)
7033 /* lower order two bytes goes to higher order two bytes */
7035 /* if some more remaining */
7037 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7040 movLeft2Result (left, MSB16, result, MSB32, 0);
7041 movLeft2Result (left, LSB, result, MSB24, 0);
7043 aopPut (AOP (result), zero, MSB16);
7044 aopPut (AOP (result), zero, LSB);
7048 /* if more than 1 byte */
7049 else if (shCount >= 8)
7051 /* lower order three bytes goes to higher order three bytes */
7056 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7058 movLeft2Result (left, LSB, result, MSB16, 0);
7064 movLeft2Result (left, MSB24, result, MSB32, 0);
7065 movLeft2Result (left, MSB16, result, MSB24, 0);
7066 movLeft2Result (left, LSB, result, MSB16, 0);
7067 aopPut (AOP (result), zero, LSB);
7069 else if (shCount == 1)
7070 shiftLLong (left, result, MSB16);
7073 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7074 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7075 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7076 aopPut (AOP (result), zero, LSB);
7081 /* 1 <= shCount <= 7 */
7082 else if (shCount <= 2)
7084 shiftLLong (left, result, LSB);
7086 shiftLLong (result, result, LSB);
7088 /* 3 <= shCount <= 7, optimize */
7091 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7092 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7093 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7098 #ifdef BETTER_LITERAL_SHIFT
7099 /*-----------------------------------------------------------------*/
7100 /* genLeftShiftLiteral - left shifting by known count */
7101 /*-----------------------------------------------------------------*/
7103 genLeftShiftLiteral (operand * left,
7108 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7111 size = getSize (operandType (result));
7113 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7115 /* We only handle certain easy cases so far. */
7117 && (shCount < (size * 8))
7121 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7125 freeAsmop (right, NULL, ic, TRUE);
7127 aopOp(left, ic, FALSE, FALSE);
7128 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7131 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7133 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7134 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7136 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7139 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7141 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7142 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7144 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7150 emitcode ("; shift left ", "result %d, left %d", size,
7154 /* I suppose that the left size >= result size */
7157 _startLazyDPSEvaluation();
7160 movLeft2Result (left, size, result, size, 0);
7162 _endLazyDPSEvaluation();
7164 else if (shCount >= (size * 8))
7166 _startLazyDPSEvaluation();
7169 aopPut (AOP (result), zero, size);
7171 _endLazyDPSEvaluation();
7178 genlshOne (result, left, shCount);
7182 genlshTwo (result, left, shCount);
7186 genlshFour (result, left, shCount);
7190 fprintf(stderr, "*** ack! mystery literal shift!\n");
7194 freeAsmop (left, NULL, ic, TRUE);
7195 freeAsmop (result, NULL, ic, TRUE);
7200 /*-----------------------------------------------------------------*/
7201 /* genLeftShift - generates code for left shifting */
7202 /*-----------------------------------------------------------------*/
7204 genLeftShift (iCode * ic)
7206 operand *left, *right, *result;
7209 symbol *tlbl, *tlbl1;
7211 D (emitcode (";", "genLeftShift "););
7213 right = IC_RIGHT (ic);
7214 left = IC_LEFT (ic);
7215 result = IC_RESULT (ic);
7217 aopOp (right, ic, FALSE, FALSE);
7220 #ifdef BETTER_LITERAL_SHIFT
7221 /* if the shift count is known then do it
7222 as efficiently as possible */
7223 if (AOP_TYPE (right) == AOP_LIT)
7225 if (genLeftShiftLiteral (left, right, result, ic))
7232 /* shift count is unknown then we have to form
7233 a loop get the loop count in B : Note: we take
7234 only the lower order byte since shifting
7235 more that 32 bits make no sense anyway, ( the
7236 largest size of an object can be only 32 bits ) */
7238 if (AOP_TYPE (right) == AOP_LIT)
7240 /* Really should be handled by genLeftShiftLiteral,
7241 * but since I'm too lazy to fix that today, at least we can make
7242 * some small improvement.
7244 emitcode("mov", "b,#0x%02x",
7245 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7249 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7250 emitcode ("inc", "b");
7252 freeAsmop (right, NULL, ic, TRUE);
7253 aopOp (left, ic, FALSE, FALSE);
7254 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7256 /* now move the left to the result if they are not the
7258 if (!sameRegs (AOP (left), AOP (result)) &&
7259 AOP_SIZE (result) > 1)
7262 size = AOP_SIZE (result);
7264 _startLazyDPSEvaluation ();
7267 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7268 if (*l == '@' && (IS_AOP_PREG (result)))
7271 emitcode ("mov", "a,%s", l);
7272 aopPut (AOP (result), "a", offset);
7275 aopPut (AOP (result), l, offset);
7278 _endLazyDPSEvaluation ();
7281 tlbl = newiTempLabel (NULL);
7282 size = AOP_SIZE (result);
7284 tlbl1 = newiTempLabel (NULL);
7286 /* if it is only one byte then */
7289 symbol *tlbl1 = newiTempLabel (NULL);
7291 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7293 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7294 emitcode ("", "%05d$:", tlbl->key + 100);
7295 emitcode ("add", "a,acc");
7296 emitcode ("", "%05d$:", tlbl1->key + 100);
7297 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7298 aopPut (AOP (result), "a", 0);
7302 reAdjustPreg (AOP (result));
7304 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7305 emitcode ("", "%05d$:", tlbl->key + 100);
7306 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7308 emitcode ("add", "a,acc");
7309 aopPut (AOP (result), "a", offset++);
7310 _startLazyDPSEvaluation ();
7313 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7315 emitcode ("rlc", "a");
7316 aopPut (AOP (result), "a", offset++);
7318 _endLazyDPSEvaluation ();
7319 reAdjustPreg (AOP (result));
7321 emitcode ("", "%05d$:", tlbl1->key + 100);
7322 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7324 freeAsmop (left, NULL, ic, TRUE);
7325 freeAsmop (result, NULL, ic, TRUE);
7328 #ifdef BETTER_LITERAL_SHIFT
7329 /*-----------------------------------------------------------------*/
7330 /* genrshOne - right shift a one byte quantity by known count */
7331 /*-----------------------------------------------------------------*/
7333 genrshOne (operand * result, operand * left,
7334 int shCount, int sign)
7336 D (emitcode (";", "genrshOne"););
7337 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7341 #ifdef BETTER_LITERAL_SHIFT
7342 /*-----------------------------------------------------------------*/
7343 /* genrshTwo - right shift two bytes by known amount != 0 */
7344 /*-----------------------------------------------------------------*/
7346 genrshTwo (operand * result, operand * left,
7347 int shCount, int sign)
7349 D (emitcode (";", "genrshTwo"););
7351 /* if shCount >= 8 */
7355 _startLazyDPSEvaluation();
7358 shiftR1Left2Result (left, MSB16, result, LSB,
7363 movLeft2Result (left, MSB16, result, LSB, sign);
7365 addSign (result, MSB16, sign);
7366 _endLazyDPSEvaluation();
7369 /* 1 <= shCount <= 7 */
7372 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7379 /*-----------------------------------------------------------------*/
7380 /* shiftRLong - shift right one long from left to result */
7381 /* offl = LSB or MSB16 */
7382 /*-----------------------------------------------------------------*/
7384 shiftRLong (operand * left, int offl,
7385 operand * result, int sign)
7387 int isSameRegs=sameRegs(AOP(left),AOP(result));
7389 if (isSameRegs && offl>1) {
7390 // we are in big trouble, but this shouldn't happen
7391 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7394 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7399 emitcode ("rlc", "a");
7400 emitcode ("subb", "a,acc");
7401 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7403 aopPut (AOP(result), zero, MSB32);
7408 emitcode ("clr", "c");
7410 emitcode ("mov", "c,acc.7");
7413 emitcode ("rrc", "a");
7415 if (isSameRegs && offl==MSB16) {
7416 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7418 aopPut (AOP (result), "a", MSB32);
7419 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7422 emitcode ("rrc", "a");
7423 if (isSameRegs && offl==1) {
7424 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7426 aopPut (AOP (result), "a", MSB24);
7427 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7429 emitcode ("rrc", "a");
7430 aopPut (AOP (result), "a", MSB16 - offl);
7434 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7435 emitcode ("rrc", "a");
7436 aopPut (AOP (result), "a", LSB);
7443 /*-----------------------------------------------------------------*/
7444 /* genrshFour - shift four byte by a known amount != 0 */
7445 /*-----------------------------------------------------------------*/
7447 genrshFour (operand * result, operand * left,
7448 int shCount, int sign)
7450 D (emitcode (";", "genrshFour");
7453 /* if shifting more that 3 bytes */
7458 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7460 movLeft2Result (left, MSB32, result, LSB, sign);
7461 addSign (result, MSB16, sign);
7463 else if (shCount >= 16)
7467 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7470 movLeft2Result (left, MSB24, result, LSB, 0);
7471 movLeft2Result (left, MSB32, result, MSB16, sign);
7473 addSign (result, MSB24, sign);
7475 else if (shCount >= 8)
7479 shiftRLong (left, MSB16, result, sign);
7480 else if (shCount == 0)
7482 movLeft2Result (left, MSB16, result, LSB, 0);
7483 movLeft2Result (left, MSB24, result, MSB16, 0);
7484 movLeft2Result (left, MSB32, result, MSB24, sign);
7485 addSign (result, MSB32, sign);
7489 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7490 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7491 /* the last shift is signed */
7492 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7493 addSign (result, MSB32, sign);
7497 { /* 1 <= shCount <= 7 */
7500 shiftRLong (left, LSB, result, sign);
7502 shiftRLong (result, LSB, result, sign);
7506 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7507 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7508 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7514 #ifdef BETTER_LITERAL_SHIFT
7515 /*-----------------------------------------------------------------*/
7516 /* genRightShiftLiteral - right shifting by known count */
7517 /*-----------------------------------------------------------------*/
7519 genRightShiftLiteral (operand * left,
7525 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7528 size = getSize (operandType (result));
7530 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7532 /* We only handle certain easy cases so far. */
7534 && (shCount < (size * 8))
7538 D(emitcode (";", "genRightShiftLiteral wimping out"););
7542 freeAsmop (right, NULL, ic, TRUE);
7544 aopOp (left, ic, FALSE, FALSE);
7545 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7548 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7552 /* test the LEFT size !!! */
7554 /* I suppose that the left size >= result size */
7557 size = getDataSize (result);
7558 _startLazyDPSEvaluation();
7561 movLeft2Result (left, size, result, size, 0);
7563 _endLazyDPSEvaluation();
7565 else if (shCount >= (size * 8))
7569 /* get sign in acc.7 */
7570 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7572 addSign (result, LSB, sign);
7579 genrshOne (result, left, shCount, sign);
7583 genrshTwo (result, left, shCount, sign);
7587 genrshFour (result, left, shCount, sign);
7594 freeAsmop (left, NULL, ic, TRUE);
7595 freeAsmop (result, NULL, ic, TRUE);
7601 /*-----------------------------------------------------------------*/
7602 /* genSignedRightShift - right shift of signed number */
7603 /*-----------------------------------------------------------------*/
7605 genSignedRightShift (iCode * ic)
7607 operand *right, *left, *result;
7610 symbol *tlbl, *tlbl1;
7612 D (emitcode (";", "genSignedRightShift "););
7614 /* we do it the hard way put the shift count in b
7615 and loop thru preserving the sign */
7617 right = IC_RIGHT (ic);
7618 left = IC_LEFT (ic);
7619 result = IC_RESULT (ic);
7621 aopOp (right, ic, FALSE, FALSE);
7623 #ifdef BETTER_LITERAL_SHIFT
7624 if (AOP_TYPE (right) == AOP_LIT)
7626 if (genRightShiftLiteral (left, right, result, ic, 1))
7632 /* shift count is unknown then we have to form
7633 a loop get the loop count in B : Note: we take
7634 only the lower order byte since shifting
7635 more that 32 bits make no sense anyway, ( the
7636 largest size of an object can be only 32 bits ) */
7638 if (AOP_TYPE (right) == AOP_LIT)
7640 /* Really should be handled by genRightShiftLiteral,
7641 * but since I'm too lazy to fix that today, at least we can make
7642 * some small improvement.
7644 emitcode("mov", "b,#0x%02x",
7645 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7649 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7650 emitcode ("inc", "b");
7652 freeAsmop (right, NULL, ic, TRUE);
7653 aopOp (left, ic, FALSE, FALSE);
7654 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7656 /* now move the left to the result if they are not the
7658 if (!sameRegs (AOP (left), AOP (result)) &&
7659 AOP_SIZE (result) > 1)
7662 size = AOP_SIZE (result);
7664 _startLazyDPSEvaluation ();
7667 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7668 if (*l == '@' && IS_AOP_PREG (result))
7671 emitcode ("mov", "a,%s", l);
7672 aopPut (AOP (result), "a", offset);
7675 aopPut (AOP (result), l, offset);
7678 _endLazyDPSEvaluation ();
7681 /* mov the highest order bit to OVR */
7682 tlbl = newiTempLabel (NULL);
7683 tlbl1 = newiTempLabel (NULL);
7685 size = AOP_SIZE (result);
7687 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7688 emitcode ("rlc", "a");
7689 emitcode ("mov", "ov,c");
7690 /* if it is only one byte then */
7693 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7695 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7696 emitcode ("", "%05d$:", tlbl->key + 100);
7697 emitcode ("mov", "c,ov");
7698 emitcode ("rrc", "a");
7699 emitcode ("", "%05d$:", tlbl1->key + 100);
7700 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7701 aopPut (AOP (result), "a", 0);
7705 reAdjustPreg (AOP (result));
7706 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7707 emitcode ("", "%05d$:", tlbl->key + 100);
7708 emitcode ("mov", "c,ov");
7709 _startLazyDPSEvaluation ();
7712 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7714 emitcode ("rrc", "a");
7715 aopPut (AOP (result), "a", offset--);
7717 _endLazyDPSEvaluation ();
7718 reAdjustPreg (AOP (result));
7719 emitcode ("", "%05d$:", tlbl1->key + 100);
7720 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7723 freeAsmop (left, NULL, ic, TRUE);
7724 freeAsmop (result, NULL, ic, TRUE);
7727 /*-----------------------------------------------------------------*/
7728 /* genRightShift - generate code for right shifting */
7729 /*-----------------------------------------------------------------*/
7731 genRightShift (iCode * ic)
7733 operand *right, *left, *result;
7737 symbol *tlbl, *tlbl1;
7739 D (emitcode (";", "genRightShift "););
7741 /* if signed then we do it the hard way preserve the
7742 sign bit moving it inwards */
7743 retype = getSpec (operandType (IC_RESULT (ic)));
7745 if (!SPEC_USIGN (retype))
7747 genSignedRightShift (ic);
7751 /* signed & unsigned types are treated the same : i.e. the
7752 signed is NOT propagated inwards : quoting from the
7753 ANSI - standard : "for E1 >> E2, is equivalent to division
7754 by 2**E2 if unsigned or if it has a non-negative value,
7755 otherwise the result is implementation defined ", MY definition
7756 is that the sign does not get propagated */
7758 right = IC_RIGHT (ic);
7759 left = IC_LEFT (ic);
7760 result = IC_RESULT (ic);
7762 aopOp (right, ic, FALSE, FALSE);
7764 #ifdef BETTER_LITERAL_SHIFT
7765 /* if the shift count is known then do it
7766 as efficiently as possible */
7767 if (AOP_TYPE (right) == AOP_LIT)
7769 if (genRightShiftLiteral (left, right, result, ic, 0))
7776 /* shift count is unknown then we have to form
7777 a loop get the loop count in B : Note: we take
7778 only the lower order byte since shifting
7779 more that 32 bits make no sense anyway, ( the
7780 largest size of an object can be only 32 bits ) */
7782 if (AOP_TYPE (right) == AOP_LIT)
7784 /* Really should be handled by genRightShiftLiteral,
7785 * but since I'm too lazy to fix that today, at least we can make
7786 * some small improvement.
7788 emitcode("mov", "b,#0x%02x",
7789 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7793 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7794 emitcode ("inc", "b");
7796 freeAsmop (right, NULL, ic, TRUE);
7797 aopOp (left, ic, FALSE, FALSE);
7798 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7800 /* now move the left to the result if they are not the
7802 if (!sameRegs (AOP (left), AOP (result)) &&
7803 AOP_SIZE (result) > 1)
7806 size = AOP_SIZE (result);
7808 _startLazyDPSEvaluation ();
7811 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7812 if (*l == '@' && IS_AOP_PREG (result))
7815 emitcode ("mov", "a,%s", l);
7816 aopPut (AOP (result), "a", offset);
7819 aopPut (AOP (result), l, offset);
7822 _endLazyDPSEvaluation ();
7825 tlbl = newiTempLabel (NULL);
7826 tlbl1 = newiTempLabel (NULL);
7827 size = AOP_SIZE (result);
7830 /* if it is only one byte then */
7833 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7835 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7836 emitcode ("", "%05d$:", tlbl->key + 100);
7838 emitcode ("rrc", "a");
7839 emitcode ("", "%05d$:", tlbl1->key + 100);
7840 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7841 aopPut (AOP (result), "a", 0);
7845 reAdjustPreg (AOP (result));
7846 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7847 emitcode ("", "%05d$:", tlbl->key + 100);
7849 _startLazyDPSEvaluation ();
7852 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7854 emitcode ("rrc", "a");
7855 aopPut (AOP (result), "a", offset--);
7857 _endLazyDPSEvaluation ();
7858 reAdjustPreg (AOP (result));
7860 emitcode ("", "%05d$:", tlbl1->key + 100);
7861 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7864 freeAsmop (left, NULL, ic, TRUE);
7865 freeAsmop (result, NULL, ic, TRUE);
7868 /*-----------------------------------------------------------------*/
7869 /* genUnpackBits - generates code for unpacking bits */
7870 /*-----------------------------------------------------------------*/
7872 genUnpackBits (operand * result, char *rname, int ptype)
7879 D (emitcode (";", "genUnpackBits ");
7882 etype = getSpec (operandType (result));
7884 /* read the first byte */
7890 emitcode ("mov", "a,@%s", rname);
7894 emitcode ("movx", "a,@%s", rname);
7898 emitcode ("movx", "a,@dptr");
7902 emitcode ("clr", "a");
7903 emitcode ("movc", "a", "@a+dptr");
7907 emitcode ("lcall", "__gptrget");
7911 /* if we have bitdisplacement then it fits */
7912 /* into this byte completely or if length is */
7913 /* less than a byte */
7914 if ((shCnt = SPEC_BSTR (etype)) ||
7915 (SPEC_BLEN (etype) <= 8))
7918 /* shift right acc */
7921 emitcode ("anl", "a,#0x%02x",
7922 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7923 aopPut (AOP (result), "a", offset);
7927 /* bit field did not fit in a byte */
7928 rlen = SPEC_BLEN (etype) - 8;
7929 aopPut (AOP (result), "a", offset++);
7938 emitcode ("inc", "%s", rname);
7939 emitcode ("mov", "a,@%s", rname);
7943 emitcode ("inc", "%s", rname);
7944 emitcode ("movx", "a,@%s", rname);
7948 emitcode ("inc", "dptr");
7949 emitcode ("movx", "a,@dptr");
7953 emitcode ("clr", "a");
7954 emitcode ("inc", "dptr");
7955 emitcode ("movc", "a", "@a+dptr");
7959 emitcode ("inc", "dptr");
7960 emitcode ("lcall", "__gptrget");
7965 /* if we are done */
7969 aopPut (AOP (result), "a", offset++);
7975 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7976 aopPut (AOP (result), "a", offset);
7983 /*-----------------------------------------------------------------*/
7984 /* genDataPointerGet - generates code when ptr offset is known */
7985 /*-----------------------------------------------------------------*/
7987 genDataPointerGet (operand * left,
7993 int size, offset = 0;
7994 aopOp (result, ic, TRUE, FALSE);
7996 /* get the string representation of the name */
7997 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7998 size = AOP_SIZE (result);
7999 _startLazyDPSEvaluation ();
8003 sprintf (buffer, "(%s + %d)", l + 1, offset);
8005 sprintf (buffer, "%s", l + 1);
8006 aopPut (AOP (result), buffer, offset++);
8008 _endLazyDPSEvaluation ();
8010 freeAsmop (left, NULL, ic, TRUE);
8011 freeAsmop (result, NULL, ic, TRUE);
8014 /*-----------------------------------------------------------------*/
8015 /* genNearPointerGet - emitcode for near pointer fetch */
8016 /*-----------------------------------------------------------------*/
8018 genNearPointerGet (operand * left,
8025 sym_link *rtype, *retype, *letype;
8026 sym_link *ltype = operandType (left);
8029 rtype = operandType (result);
8030 retype = getSpec (rtype);
8031 letype = getSpec (ltype);
8033 aopOp (left, ic, FALSE, FALSE);
8035 /* if left is rematerialisable and
8036 result is not bit variable type and
8037 the left is pointer to data space i.e
8038 lower 128 bytes of space */
8039 if (AOP_TYPE (left) == AOP_IMMD &&
8040 !IS_BITVAR (retype) &&
8041 !IS_BITVAR (letype) &&
8042 DCL_TYPE (ltype) == POINTER)
8044 genDataPointerGet (left, result, ic);
8048 /* if the value is already in a pointer register
8049 then don't need anything more */
8050 if (!AOP_INPREG (AOP (left)))
8052 /* otherwise get a free pointer register */
8054 preg = getFreePtr (ic, &aop, FALSE);
8055 emitcode ("mov", "%s,%s",
8057 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8061 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8063 freeAsmop (left, NULL, ic, TRUE);
8064 aopOp (result, ic, FALSE, FALSE);
8066 /* if bitfield then unpack the bits */
8067 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8068 genUnpackBits (result, rname, POINTER);
8071 /* we have can just get the values */
8072 int size = AOP_SIZE (result);
8077 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8080 emitcode ("mov", "a,@%s", rname);
8081 aopPut (AOP (result), "a", offset);
8085 sprintf (buffer, "@%s", rname);
8086 aopPut (AOP (result), buffer, offset);
8090 emitcode ("inc", "%s", rname);
8094 /* now some housekeeping stuff */
8097 /* we had to allocate for this iCode */
8098 freeAsmop (NULL, aop, ic, TRUE);
8102 /* we did not allocate which means left
8103 already in a pointer register, then
8104 if size > 0 && this could be used again
8105 we have to point it back to where it
8107 if (AOP_SIZE (result) > 1 &&
8108 !OP_SYMBOL (left)->remat &&
8109 (OP_SYMBOL (left)->liveTo > ic->seq ||
8112 int size = AOP_SIZE (result) - 1;
8114 emitcode ("dec", "%s", rname);
8119 freeAsmop (result, NULL, ic, TRUE);
8123 /*-----------------------------------------------------------------*/
8124 /* genPagedPointerGet - emitcode for paged pointer fetch */
8125 /*-----------------------------------------------------------------*/
8127 genPagedPointerGet (operand * left,
8134 sym_link *rtype, *retype, *letype;
8136 rtype = operandType (result);
8137 retype = getSpec (rtype);
8138 letype = getSpec (operandType (left));
8139 aopOp (left, ic, FALSE, FALSE);
8141 /* if the value is already in a pointer register
8142 then don't need anything more */
8143 if (!AOP_INPREG (AOP (left)))
8145 /* otherwise get a free pointer register */
8147 preg = getFreePtr (ic, &aop, FALSE);
8148 emitcode ("mov", "%s,%s",
8150 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8154 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8156 freeAsmop (left, NULL, ic, TRUE);
8157 aopOp (result, ic, FALSE, FALSE);
8159 /* if bitfield then unpack the bits */
8160 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8161 genUnpackBits (result, rname, PPOINTER);
8164 /* we have can just get the values */
8165 int size = AOP_SIZE (result);
8171 emitcode ("movx", "a,@%s", rname);
8172 aopPut (AOP (result), "a", offset);
8177 emitcode ("inc", "%s", rname);
8181 /* now some housekeeping stuff */
8184 /* we had to allocate for this iCode */
8185 freeAsmop (NULL, aop, ic, TRUE);
8189 /* we did not allocate which means left
8190 already in a pointer register, then
8191 if size > 0 && this could be used again
8192 we have to point it back to where it
8194 if (AOP_SIZE (result) > 1 &&
8195 !OP_SYMBOL (left)->remat &&
8196 (OP_SYMBOL (left)->liveTo > ic->seq ||
8199 int size = AOP_SIZE (result) - 1;
8201 emitcode ("dec", "%s", rname);
8206 freeAsmop (result, NULL, ic, TRUE);
8211 /*-----------------------------------------------------------------*/
8212 /* genFarPointerGet - gget value from far space */
8213 /*-----------------------------------------------------------------*/
8215 genFarPointerGet (operand * left,
8216 operand * result, iCode * ic)
8219 sym_link *retype = getSpec (operandType (result));
8220 sym_link *letype = getSpec (operandType (left));
8221 D (emitcode (";", "genFarPointerGet");
8224 aopOp (left, ic, FALSE, FALSE);
8226 /* if the operand is already in dptr
8227 then we do nothing else we move the value to dptr */
8228 if (AOP_TYPE (left) != AOP_STR)
8230 /* if this is remateriazable */
8231 if (AOP_TYPE (left) == AOP_IMMD)
8233 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8237 /* we need to get it byte by byte */
8238 _startLazyDPSEvaluation ();
8239 if (AOP_TYPE (left) != AOP_DPTR)
8241 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8242 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8243 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8247 /* We need to generate a load to DPTR indirect through DPTR. */
8248 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8250 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8251 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8252 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8253 emitcode ("pop", "dph");
8254 emitcode ("pop", "dpl");
8256 _endLazyDPSEvaluation ();
8259 /* so dptr know contains the address */
8260 freeAsmop (left, NULL, ic, TRUE);
8261 aopOp (result, ic, FALSE, TRUE);
8263 /* if bit then unpack */
8264 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8265 genUnpackBits (result, "dptr", FPOINTER);
8268 size = AOP_SIZE (result);
8271 _startLazyDPSEvaluation ();
8278 emitcode ("movx", "a,@dptr");
8280 emitcode ("inc", "dptr");
8282 aopPut (AOP (result), "a", offset++);
8284 _endLazyDPSEvaluation ();
8287 freeAsmop (result, NULL, ic, TRUE);
8290 /*-----------------------------------------------------------------*/
8291 /* emitcodePointerGet - gget value from code space */
8292 /*-----------------------------------------------------------------*/
8294 emitcodePointerGet (operand * left,
8295 operand * result, iCode * ic)
8298 sym_link *retype = getSpec (operandType (result));
8300 aopOp (left, ic, FALSE, FALSE);
8302 /* if the operand is already in dptr
8303 then we do nothing else we move the value to dptr */
8304 if (AOP_TYPE (left) != AOP_STR)
8306 /* if this is remateriazable */
8307 if (AOP_TYPE (left) == AOP_IMMD)
8309 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8312 { /* we need to get it byte by byte */
8313 _startLazyDPSEvaluation ();
8314 if (AOP_TYPE (left) != AOP_DPTR)
8316 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8317 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8318 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8322 /* We need to generate a load to DPTR indirect through DPTR. */
8323 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8325 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8326 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8327 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8328 emitcode ("pop", "dph");
8329 emitcode ("pop", "dpl");
8331 _endLazyDPSEvaluation ();
8334 /* so dptr know contains the address */
8335 freeAsmop (left, NULL, ic, TRUE);
8336 aopOp (result, ic, FALSE, TRUE);
8338 /* if bit then unpack */
8339 if (IS_BITVAR (retype))
8340 genUnpackBits (result, "dptr", CPOINTER);
8343 size = AOP_SIZE (result);
8346 _startLazyDPSEvaluation ();
8352 emitcode ("clr", "a");
8353 emitcode ("movc", "a,@a+dptr");
8355 emitcode ("inc", "dptr");
8356 aopPut (AOP (result), "a", offset++);
8358 _endLazyDPSEvaluation ();
8361 freeAsmop (result, NULL, ic, TRUE);
8364 /*-----------------------------------------------------------------*/
8365 /* genGenPointerGet - gget value from generic pointer space */
8366 /*-----------------------------------------------------------------*/
8368 genGenPointerGet (operand * left,
8369 operand * result, iCode * ic)
8372 sym_link *retype = getSpec (operandType (result));
8373 sym_link *letype = getSpec (operandType (left));
8375 D (emitcode (";", "genGenPointerGet "); );
8377 aopOp (left, ic, FALSE, TRUE);
8379 /* if the operand is already in dptr
8380 then we do nothing else we move the value to dptr */
8381 if (AOP_TYPE (left) != AOP_STR)
8383 /* if this is remateriazable */
8384 if (AOP_TYPE (left) == AOP_IMMD)
8386 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8387 emitcode ("mov", "b,#%d", pointerCode (retype));
8390 { /* we need to get it byte by byte */
8391 _startLazyDPSEvaluation ();
8392 if (AOP(left)->type==AOP_DPTR2) {
8394 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8397 emitcode ("mov", "dpl,%s", l);
8398 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8401 emitcode ("mov", "dph,%s", l);
8402 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8405 emitcode ("mov", "dpx,%s", l);
8406 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8408 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8409 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8410 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8411 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8413 _endLazyDPSEvaluation ();
8416 /* so dptr know contains the address */
8417 freeAsmop (left, NULL, ic, TRUE);
8418 aopOp (result, ic, FALSE, TRUE);
8420 /* if bit then unpack */
8421 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8422 genUnpackBits (result, "dptr", GPOINTER);
8425 size = AOP_SIZE (result);
8430 emitcode ("lcall", "__gptrget");
8431 aopPut (AOP (result), "a", offset++);
8433 emitcode ("inc", "dptr");
8437 freeAsmop (result, NULL, ic, TRUE);
8440 /*-----------------------------------------------------------------*/
8441 /* genPointerGet - generate code for pointer get */
8442 /*-----------------------------------------------------------------*/
8444 genPointerGet (iCode * ic)
8446 operand *left, *result;
8447 sym_link *type, *etype;
8450 D (emitcode (";", "genPointerGet ");
8453 left = IC_LEFT (ic);
8454 result = IC_RESULT (ic);
8456 /* depending on the type of pointer we need to
8457 move it to the correct pointer register */
8458 type = operandType (left);
8459 etype = getSpec (type);
8460 /* if left is of type of pointer then it is simple */
8461 if (IS_PTR (type) && !IS_FUNC (type->next))
8462 p_type = DCL_TYPE (type);
8465 /* we have to go by the storage class */
8466 p_type = PTR_TYPE (SPEC_OCLS (etype));
8469 /* now that we have the pointer type we assign
8470 the pointer values */
8476 genNearPointerGet (left, result, ic);
8480 genPagedPointerGet (left, result, ic);
8484 genFarPointerGet (left, result, ic);
8488 emitcodePointerGet (left, result, ic);
8492 genGenPointerGet (left, result, ic);
8498 /*-----------------------------------------------------------------*/
8499 /* genPackBits - generates code for packed bit storage */
8500 /*-----------------------------------------------------------------*/
8502 genPackBits (sym_link * etype,
8504 char *rname, int p_type)
8512 blen = SPEC_BLEN (etype);
8513 bstr = SPEC_BSTR (etype);
8515 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8518 /* if the bit lenth is less than or */
8519 /* it exactly fits a byte then */
8520 if (SPEC_BLEN (etype) <= 8)
8522 shCount = SPEC_BSTR (etype);
8524 /* shift left acc */
8527 if (SPEC_BLEN (etype) < 8)
8528 { /* if smaller than a byte */
8534 emitcode ("mov", "b,a");
8535 emitcode ("mov", "a,@%s", rname);
8539 emitcode ("mov", "b,a");
8540 emitcode ("movx", "a,@dptr");
8544 emitcode ("push", "b");
8545 emitcode ("push", "acc");
8546 emitcode ("lcall", "__gptrget");
8547 emitcode ("pop", "b");
8551 emitcode ("anl", "a,#0x%02x", (unsigned char)
8552 ((unsigned char) (0xFF << (blen + bstr)) |
8553 (unsigned char) (0xFF >> (8 - bstr))));
8554 emitcode ("orl", "a,b");
8555 if (p_type == GPOINTER)
8556 emitcode ("pop", "b");
8563 emitcode ("mov", "@%s,a", rname);
8567 emitcode ("movx", "@dptr,a");
8571 emitcode ("lcall", "__gptrput");
8576 if (SPEC_BLEN (etype) <= 8)
8579 emitcode ("inc", "%s", rname);
8580 rLen = SPEC_BLEN (etype);
8582 /* now generate for lengths greater than one byte */
8586 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8598 emitcode ("mov", "@%s,a", rname);
8601 emitcode ("mov", "@%s,%s", rname, l);
8606 emitcode ("movx", "@dptr,a");
8611 emitcode ("lcall", "__gptrput");
8614 emitcode ("inc", "%s", rname);
8619 /* last last was not complete */
8622 /* save the byte & read byte */
8626 emitcode ("mov", "b,a");
8627 emitcode ("mov", "a,@%s", rname);
8631 emitcode ("mov", "b,a");
8632 emitcode ("movx", "a,@dptr");
8636 emitcode ("push", "b");
8637 emitcode ("push", "acc");
8638 emitcode ("lcall", "__gptrget");
8639 emitcode ("pop", "b");
8643 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8644 emitcode ("orl", "a,b");
8647 if (p_type == GPOINTER)
8648 emitcode ("pop", "b");
8654 emitcode ("mov", "@%s,a", rname);
8658 emitcode ("movx", "@dptr,a");
8662 emitcode ("lcall", "__gptrput");
8666 /*-----------------------------------------------------------------*/
8667 /* genDataPointerSet - remat pointer to data space */
8668 /*-----------------------------------------------------------------*/
8670 genDataPointerSet (operand * right,
8674 int size, offset = 0;
8675 char *l, buffer[256];
8677 aopOp (right, ic, FALSE, FALSE);
8679 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8680 size = AOP_SIZE (right);
8684 sprintf (buffer, "(%s + %d)", l + 1, offset);
8686 sprintf (buffer, "%s", l + 1);
8687 emitcode ("mov", "%s,%s", buffer,
8688 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8691 freeAsmop (right, NULL, ic, TRUE);
8692 freeAsmop (result, NULL, ic, TRUE);
8695 /*-----------------------------------------------------------------*/
8696 /* genNearPointerSet - emitcode for near pointer put */
8697 /*-----------------------------------------------------------------*/
8699 genNearPointerSet (operand * right,
8706 sym_link *retype, *letype;
8707 sym_link *ptype = operandType (result);
8709 retype = getSpec (operandType (right));
8710 letype = getSpec (ptype);
8712 aopOp (result, ic, FALSE, FALSE);
8714 /* if the result is rematerializable &
8715 in data space & not a bit variable */
8716 if (AOP_TYPE (result) == AOP_IMMD &&
8717 DCL_TYPE (ptype) == POINTER &&
8718 !IS_BITVAR (retype) &&
8719 !IS_BITVAR (letype))
8721 genDataPointerSet (right, result, ic);
8725 /* if the value is already in a pointer register
8726 then don't need anything more */
8727 if (!AOP_INPREG (AOP (result)))
8729 /* otherwise get a free pointer register */
8731 preg = getFreePtr (ic, &aop, FALSE);
8732 emitcode ("mov", "%s,%s",
8734 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8738 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8740 freeAsmop (result, NULL, ic, TRUE);
8741 aopOp (right, ic, FALSE, FALSE);
8743 /* if bitfield then unpack the bits */
8744 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8745 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8748 /* we have can just get the values */
8749 int size = AOP_SIZE (right);
8754 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8758 emitcode ("mov", "@%s,a", rname);
8761 emitcode ("mov", "@%s,%s", rname, l);
8763 emitcode ("inc", "%s", rname);
8768 /* now some housekeeping stuff */
8771 /* we had to allocate for this iCode */
8772 freeAsmop (NULL, aop, ic, TRUE);
8776 /* we did not allocate which means left
8777 already in a pointer register, then
8778 if size > 0 && this could be used again
8779 we have to point it back to where it
8781 if (AOP_SIZE (right) > 1 &&
8782 !OP_SYMBOL (result)->remat &&
8783 (OP_SYMBOL (result)->liveTo > ic->seq ||
8786 int size = AOP_SIZE (right) - 1;
8788 emitcode ("dec", "%s", rname);
8793 freeAsmop (right, NULL, ic, TRUE);
8798 /*-----------------------------------------------------------------*/
8799 /* genPagedPointerSet - emitcode for Paged pointer put */
8800 /*-----------------------------------------------------------------*/
8802 genPagedPointerSet (operand * right,
8809 sym_link *retype, *letype;
8811 retype = getSpec (operandType (right));
8812 letype = getSpec (operandType (result));
8814 aopOp (result, ic, FALSE, FALSE);
8816 /* if the value is already in a pointer register
8817 then don't need anything more */
8818 if (!AOP_INPREG (AOP (result)))
8820 /* otherwise get a free pointer register */
8822 preg = getFreePtr (ic, &aop, FALSE);
8823 emitcode ("mov", "%s,%s",
8825 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8829 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8831 freeAsmop (result, NULL, ic, TRUE);
8832 aopOp (right, ic, FALSE, FALSE);
8834 /* if bitfield then unpack the bits */
8835 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8836 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8839 /* we have can just get the values */
8840 int size = AOP_SIZE (right);
8845 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8848 emitcode ("movx", "@%s,a", rname);
8851 emitcode ("inc", "%s", rname);
8857 /* now some housekeeping stuff */
8860 /* we had to allocate for this iCode */
8861 freeAsmop (NULL, aop, ic, TRUE);
8865 /* we did not allocate which means left
8866 already in a pointer register, then
8867 if size > 0 && this could be used again
8868 we have to point it back to where it
8870 if (AOP_SIZE (right) > 1 &&
8871 !OP_SYMBOL (result)->remat &&
8872 (OP_SYMBOL (result)->liveTo > ic->seq ||
8875 int size = AOP_SIZE (right) - 1;
8877 emitcode ("dec", "%s", rname);
8882 freeAsmop (right, NULL, ic, TRUE);
8887 /*-----------------------------------------------------------------*/
8888 /* genFarPointerSet - set value from far space */
8889 /*-----------------------------------------------------------------*/
8891 genFarPointerSet (operand * right,
8892 operand * result, iCode * ic)
8895 sym_link *retype = getSpec (operandType (right));
8896 sym_link *letype = getSpec (operandType (result));
8898 aopOp (result, ic, FALSE, FALSE);
8900 /* if the operand is already in dptr
8901 then we do nothing else we move the value to dptr */
8902 if (AOP_TYPE (result) != AOP_STR)
8904 /* if this is remateriazable */
8905 if (AOP_TYPE (result) == AOP_IMMD)
8906 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8909 /* we need to get it byte by byte */
8910 _startLazyDPSEvaluation ();
8911 if (AOP_TYPE (result) != AOP_DPTR)
8913 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8914 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8915 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8919 /* We need to generate a load to DPTR indirect through DPTR. */
8920 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8922 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8923 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8924 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8925 emitcode ("pop", "dph");
8926 emitcode ("pop", "dpl");
8928 _endLazyDPSEvaluation ();
8931 /* so dptr know contains the address */
8932 freeAsmop (result, NULL, ic, TRUE);
8933 aopOp (right, ic, FALSE, TRUE);
8935 /* if bit then unpack */
8936 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8937 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8940 size = AOP_SIZE (right);
8943 _startLazyDPSEvaluation ();
8946 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8952 emitcode ("movx", "@dptr,a");
8954 emitcode ("inc", "dptr");
8956 _endLazyDPSEvaluation ();
8959 freeAsmop (right, NULL, ic, TRUE);
8962 /*-----------------------------------------------------------------*/
8963 /* genGenPointerSet - set value from generic pointer space */
8964 /*-----------------------------------------------------------------*/
8966 genGenPointerSet (operand * right,
8967 operand * result, iCode * ic)
8970 sym_link *retype = getSpec (operandType (right));
8971 sym_link *letype = getSpec (operandType (result));
8973 aopOp (result, ic, FALSE, TRUE);
8975 /* if the operand is already in dptr
8976 then we do nothing else we move the value to dptr */
8977 if (AOP_TYPE (result) != AOP_STR)
8979 _startLazyDPSEvaluation ();
8980 /* if this is remateriazable */
8981 if (AOP_TYPE (result) == AOP_IMMD)
8983 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8984 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8987 { /* we need to get it byte by byte */
8988 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8989 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8990 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8991 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8993 _endLazyDPSEvaluation ();
8995 /* so dptr know contains the address */
8996 freeAsmop (result, NULL, ic, TRUE);
8997 aopOp (right, ic, FALSE, TRUE);
8999 /* if bit then unpack */
9000 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9001 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9004 size = AOP_SIZE (right);
9007 _startLazyDPSEvaluation ();
9010 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9016 emitcode ("lcall", "__gptrput");
9018 emitcode ("inc", "dptr");
9020 _endLazyDPSEvaluation ();
9023 freeAsmop (right, NULL, ic, TRUE);
9026 /*-----------------------------------------------------------------*/
9027 /* genPointerSet - stores the value into a pointer location */
9028 /*-----------------------------------------------------------------*/
9030 genPointerSet (iCode * ic)
9032 operand *right, *result;
9033 sym_link *type, *etype;
9036 D (emitcode (";", "genPointerSet ");
9039 right = IC_RIGHT (ic);
9040 result = IC_RESULT (ic);
9042 /* depending on the type of pointer we need to
9043 move it to the correct pointer register */
9044 type = operandType (result);
9045 etype = getSpec (type);
9046 /* if left is of type of pointer then it is simple */
9047 if (IS_PTR (type) && !IS_FUNC (type->next))
9049 p_type = DCL_TYPE (type);
9053 /* we have to go by the storage class */
9054 p_type = PTR_TYPE (SPEC_OCLS (etype));
9057 /* now that we have the pointer type we assign
9058 the pointer values */
9064 genNearPointerSet (right, result, ic);
9068 genPagedPointerSet (right, result, ic);
9072 genFarPointerSet (right, result, ic);
9076 genGenPointerSet (right, result, ic);
9082 /*-----------------------------------------------------------------*/
9083 /* genIfx - generate code for Ifx statement */
9084 /*-----------------------------------------------------------------*/
9086 genIfx (iCode * ic, iCode * popIc)
9088 operand *cond = IC_COND (ic);
9091 D (emitcode (";", "genIfx "););
9093 aopOp (cond, ic, FALSE, FALSE);
9095 /* get the value into acc */
9096 if (AOP_TYPE (cond) != AOP_CRY)
9100 /* the result is now in the accumulator */
9101 freeAsmop (cond, NULL, ic, TRUE);
9103 /* if there was something to be popped then do it */
9107 /* if the condition is a bit variable */
9108 if (isbit && IS_ITEMP (cond) &&
9110 genIfxJump (ic, SPIL_LOC (cond)->rname);
9111 else if (isbit && !IS_ITEMP (cond))
9112 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9114 genIfxJump (ic, "a");
9119 /*-----------------------------------------------------------------*/
9120 /* genAddrOf - generates code for address of */
9121 /*-----------------------------------------------------------------*/
9123 genAddrOf (iCode * ic)
9125 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9128 D (emitcode (";", "genAddrOf ");
9131 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9133 /* if the operand is on the stack then we
9134 need to get the stack offset of this
9138 /* if it has an offset then we need to compute
9142 emitcode ("mov", "a,_bp");
9143 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9144 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9148 /* we can just move _bp */
9149 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9151 /* fill the result with zero */
9152 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9155 if (options.stack10bit && size < (FPTRSIZE - 1))
9158 "*** warning: pointer to stack var truncated.\n");
9165 if (options.stack10bit && offset == 2)
9167 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9171 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9178 /* object not on stack then we need the name */
9179 size = AOP_SIZE (IC_RESULT (ic));
9184 char s[SDCC_NAME_MAX];
9186 sprintf (s, "#(%s >> %d)",
9190 sprintf (s, "#%s", sym->rname);
9191 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9195 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9199 /*-----------------------------------------------------------------*/
9200 /* genFarFarAssign - assignment when both are in far space */
9201 /*-----------------------------------------------------------------*/
9203 genFarFarAssign (operand * result, operand * right, iCode * ic)
9205 int size = AOP_SIZE (right);
9207 symbol *rSym = NULL;
9211 /* quick & easy case. */
9212 D(emitcode(";","genFarFarAssign (1 byte case)"););
9213 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9214 freeAsmop (right, NULL, ic, FALSE);
9215 /* now assign DPTR to result */
9217 aopOp(result, ic, FALSE, FALSE);
9219 aopPut(AOP(result), "a", 0);
9220 freeAsmop(result, NULL, ic, FALSE);
9224 /* See if we've got an underlying symbol to abuse. */
9225 if (IS_SYMOP(result) && OP_SYMBOL(result))
9227 if (IS_TRUE_SYMOP(result))
9229 rSym = OP_SYMBOL(result);
9231 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9233 rSym = OP_SYMBOL(result)->usl.spillLoc;
9237 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9239 /* We can use the '390 auto-toggle feature to good effect here. */
9241 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9242 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9243 emitcode ("mov", "dptr,#%s", rSym->rname);
9244 /* DP2 = result, DP1 = right, DP1 is current. */
9247 emitcode("movx", "a,@dptr");
9248 emitcode("movx", "@dptr,a");
9251 emitcode("inc", "dptr");
9252 emitcode("inc", "dptr");
9255 emitcode("mov", "dps, #0");
9256 freeAsmop (right, NULL, ic, FALSE);
9260 D (emitcode (";", "genFarFarAssign"););
9261 aopOp (result, ic, TRUE, TRUE);
9263 _startLazyDPSEvaluation ();
9267 aopPut (AOP (result),
9268 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9271 _endLazyDPSEvaluation ();
9272 freeAsmop (result, NULL, ic, FALSE);
9273 freeAsmop (right, NULL, ic, FALSE);
9277 /*-----------------------------------------------------------------*/
9278 /* genAssign - generate code for assignment */
9279 /*-----------------------------------------------------------------*/
9281 genAssign (iCode * ic)
9283 operand *result, *right;
9285 unsigned long lit = 0L;
9287 D (emitcode (";", "genAssign ");
9290 result = IC_RESULT (ic);
9291 right = IC_RIGHT (ic);
9293 /* if they are the same */
9294 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9297 aopOp (right, ic, FALSE, FALSE);
9299 emitcode (";", "genAssign: resultIsFar = %s",
9300 isOperandInFarSpace (result) ?
9303 /* special case both in far space */
9304 if ((AOP_TYPE (right) == AOP_DPTR ||
9305 AOP_TYPE (right) == AOP_DPTR2) &&
9306 /* IS_TRUE_SYMOP(result) && */
9307 isOperandInFarSpace (result))
9309 genFarFarAssign (result, right, ic);
9313 aopOp (result, ic, TRUE, FALSE);
9315 /* if they are the same registers */
9316 if (sameRegs (AOP (right), AOP (result)))
9319 /* if the result is a bit */
9320 if (AOP_TYPE (result) == AOP_CRY)
9323 /* if the right size is a literal then
9324 we know what the value is */
9325 if (AOP_TYPE (right) == AOP_LIT)
9327 if (((int) operandLitValue (right)))
9328 aopPut (AOP (result), one, 0);
9330 aopPut (AOP (result), zero, 0);
9334 /* the right is also a bit variable */
9335 if (AOP_TYPE (right) == AOP_CRY)
9337 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9338 aopPut (AOP (result), "c", 0);
9344 aopPut (AOP (result), "a", 0);
9348 /* bit variables done */
9350 size = AOP_SIZE (result);
9352 if (AOP_TYPE (right) == AOP_LIT)
9353 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9356 (AOP_TYPE (result) != AOP_REG) &&
9357 (AOP_TYPE (right) == AOP_LIT) &&
9358 !IS_FLOAT (operandType (right)))
9360 _startLazyDPSEvaluation ();
9361 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9363 aopPut (AOP (result),
9364 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9369 /* And now fill the rest with zeros. */
9372 emitcode ("clr", "a");
9376 aopPut (AOP (result), "a", offset++);
9378 _endLazyDPSEvaluation ();
9382 _startLazyDPSEvaluation ();
9385 aopPut (AOP (result),
9386 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9390 _endLazyDPSEvaluation ();
9394 freeAsmop (right, NULL, ic, FALSE);
9395 freeAsmop (result, NULL, ic, TRUE);
9398 /*-----------------------------------------------------------------*/
9399 /* genJumpTab - generates code for jump table */
9400 /*-----------------------------------------------------------------*/
9402 genJumpTab (iCode * ic)
9407 D (emitcode (";", "genJumpTab ");
9410 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9411 /* get the condition into accumulator */
9412 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9414 /* multiply by four! */
9415 emitcode ("add", "a,acc");
9416 emitcode ("add", "a,acc");
9417 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9419 jtab = newiTempLabel (NULL);
9420 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9421 emitcode ("jmp", "@a+dptr");
9422 emitcode ("", "%05d$:", jtab->key + 100);
9423 /* now generate the jump labels */
9424 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9425 jtab = setNextItem (IC_JTLABELS (ic)))
9426 emitcode ("ljmp", "%05d$", jtab->key + 100);
9430 /*-----------------------------------------------------------------*/
9431 /* genCast - gen code for casting */
9432 /*-----------------------------------------------------------------*/
9434 genCast (iCode * ic)
9436 operand *result = IC_RESULT (ic);
9437 sym_link *ctype = operandType (IC_LEFT (ic));
9438 sym_link *rtype = operandType (IC_RIGHT (ic));
9439 operand *right = IC_RIGHT (ic);
9442 D (emitcode (";", "genCast ");
9445 /* if they are equivalent then do nothing */
9446 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9449 aopOp (right, ic, FALSE, FALSE);
9450 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9452 /* if the result is a bit */
9453 if (AOP_TYPE (result) == AOP_CRY)
9455 /* if the right size is a literal then
9456 we know what the value is */
9457 if (AOP_TYPE (right) == AOP_LIT)
9459 if (((int) operandLitValue (right)))
9460 aopPut (AOP (result), one, 0);
9462 aopPut (AOP (result), zero, 0);
9467 /* the right is also a bit variable */
9468 if (AOP_TYPE (right) == AOP_CRY)
9470 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9471 aopPut (AOP (result), "c", 0);
9477 aopPut (AOP (result), "a", 0);
9481 /* if they are the same size : or less */
9482 if (AOP_SIZE (result) <= AOP_SIZE (right))
9485 /* if they are in the same place */
9486 if (sameRegs (AOP (right), AOP (result)))
9489 /* if they in different places then copy */
9490 size = AOP_SIZE (result);
9492 _startLazyDPSEvaluation ();
9495 aopPut (AOP (result),
9496 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9500 _endLazyDPSEvaluation ();
9505 /* if the result is of type pointer */
9510 sym_link *type = operandType (right);
9512 /* pointer to generic pointer */
9513 if (IS_GENPTR (ctype))
9519 p_type = DCL_TYPE (type);
9523 #if OLD_CAST_BEHAVIOR
9524 /* KV: we are converting a non-pointer type to
9525 * a generic pointer. This (ifdef'd out) code
9526 * says that the resulting generic pointer
9527 * should have the same class as the storage
9528 * location of the non-pointer variable.
9530 * For example, converting an int (which happens
9531 * to be stored in DATA space) to a pointer results
9532 * in a DATA generic pointer; if the original int
9533 * in XDATA space, so will be the resulting pointer.
9535 * I don't like that behavior, and thus this change:
9536 * all such conversions will be forced to XDATA and
9537 * throw a warning. If you want some non-XDATA
9538 * type, or you want to suppress the warning, you
9539 * must go through an intermediate cast, like so:
9541 * char _generic *gp = (char _xdata *)(intVar);
9543 sym_link *etype = getSpec (type);
9545 /* we have to go by the storage class */
9546 if (SPEC_OCLS (etype) != generic)
9548 p_type = PTR_TYPE (SPEC_OCLS (etype));
9553 /* Converting unknown class (i.e. register variable)
9554 * to generic pointer. This is not good, but
9555 * we'll make a guess (and throw a warning).
9558 werror (W_INT_TO_GEN_PTR_CAST);
9562 /* the first two bytes are known */
9563 size = GPTRSIZE - 1;
9565 _startLazyDPSEvaluation ();
9568 aopPut (AOP (result),
9569 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9573 _endLazyDPSEvaluation ();
9575 /* the last byte depending on type */
9593 /* this should never happen */
9594 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9595 "got unknown pointer type");
9598 aopPut (AOP (result), l, GPTRSIZE - 1);
9602 /* just copy the pointers */
9603 size = AOP_SIZE (result);
9605 _startLazyDPSEvaluation ();
9608 aopPut (AOP (result),
9609 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9613 _endLazyDPSEvaluation ();
9617 /* so we now know that the size of destination is greater
9618 than the size of the source */
9619 /* we move to result for the size of source */
9620 size = AOP_SIZE (right);
9622 _startLazyDPSEvaluation ();
9625 aopPut (AOP (result),
9626 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9630 _endLazyDPSEvaluation ();
9632 /* now depending on the sign of the source && destination */
9633 size = AOP_SIZE (result) - AOP_SIZE (right);
9634 /* if unsigned or not an integral type */
9635 /* also, if the source is a bit, we don't need to sign extend, because
9636 * it can't possibly have set the sign bit.
9638 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9642 aopPut (AOP (result), zero, offset++);
9647 /* we need to extend the sign :{ */
9648 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9649 FALSE, FALSE, TRUE);
9651 emitcode ("rlc", "a");
9652 emitcode ("subb", "a,acc");
9654 aopPut (AOP (result), "a", offset++);
9657 /* we are done hurray !!!! */
9660 freeAsmop (right, NULL, ic, TRUE);
9661 freeAsmop (result, NULL, ic, TRUE);
9665 /*-----------------------------------------------------------------*/
9666 /* genDjnz - generate decrement & jump if not zero instrucion */
9667 /*-----------------------------------------------------------------*/
9669 genDjnz (iCode * ic, iCode * ifx)
9675 /* if the if condition has a false label
9676 then we cannot save */
9680 /* if the minus is not of the form
9682 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9683 !IS_OP_LITERAL (IC_RIGHT (ic)))
9686 if (operandLitValue (IC_RIGHT (ic)) != 1)
9689 /* if the size of this greater than one then no
9691 if (getSize (operandType (IC_RESULT (ic))) > 1)
9694 /* otherwise we can save BIG */
9695 D(emitcode(";", "genDjnz"););
9697 lbl = newiTempLabel (NULL);
9698 lbl1 = newiTempLabel (NULL);
9700 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9702 if (AOP_NEEDSACC(IC_RESULT(ic)))
9704 /* If the result is accessed indirectly via
9705 * the accumulator, we must explicitly write
9706 * it back after the decrement.
9708 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9710 if (strcmp(rByte, "a"))
9712 /* Something is hopelessly wrong */
9713 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9714 __FILE__, __LINE__);
9715 /* We can just give up; the generated code will be inefficient,
9718 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9721 emitcode ("dec", "%s", rByte);
9722 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9723 emitcode ("jnz", "%05d$", lbl->key + 100);
9725 else if (IS_AOP_PREG (IC_RESULT (ic)))
9727 emitcode ("dec", "%s",
9728 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9729 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9730 emitcode ("jnz", "%05d$", lbl->key + 100);
9734 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9737 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9738 emitcode ("", "%05d$:", lbl->key + 100);
9739 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9740 emitcode ("", "%05d$:", lbl1->key + 100);
9742 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9747 /*-----------------------------------------------------------------*/
9748 /* genReceive - generate code for a receive iCode */
9749 /*-----------------------------------------------------------------*/
9751 genReceive (iCode * ic)
9754 D (emitcode (";", "genReceive ");
9757 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9758 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9759 IS_TRUE_SYMOP (IC_RESULT (ic))))
9761 int size = getSize (operandType (IC_RESULT (ic)));
9762 int offset = fReturnSizeDS390 - size;
9765 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9766 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9769 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9770 size = AOP_SIZE (IC_RESULT (ic));
9774 emitcode ("pop", "acc");
9775 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9782 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9784 assignResultValue (IC_RESULT (ic));
9787 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9790 /*-----------------------------------------------------------------*/
9791 /* gen390Code - generate code for Dallas 390 based controllers */
9792 /*-----------------------------------------------------------------*/
9794 gen390Code (iCode * lic)
9799 lineHead = lineCurr = NULL;
9803 /* print the allocation information */
9805 printAllocInfo (currFunc, codeOutFile);
9807 /* if debug information required */
9808 if (options.debug && currFunc)
9810 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9812 if (IS_STATIC (currFunc->etype))
9813 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9815 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9818 /* stack pointer name */
9819 if (options.useXstack)
9825 for (ic = lic; ic; ic = ic->next)
9828 if (cln != ic->lineno)
9833 emitcode ("", "C$%s$%d$%d$%d ==.",
9834 FileBaseName (ic->filename), ic->lineno,
9835 ic->level, ic->block);
9838 emitcode (";", "%s %d", ic->filename, ic->lineno);
9841 /* if the result is marked as
9842 spilt and rematerializable or code for
9843 this has already been generated then
9845 if (resultRemat (ic) || ic->generated)
9848 /* depending on the operation */
9868 /* IPOP happens only when trying to restore a
9869 spilt live range, if there is an ifx statement
9870 following this pop then the if statement might
9871 be using some of the registers being popped which
9872 would destory the contents of the register so
9873 we need to check for this condition and handle it */
9875 ic->next->op == IFX &&
9876 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9877 genIfx (ic->next, ic);
9895 genEndFunction (ic);
9915 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9932 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9936 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9943 /* note these two are xlated by algebraic equivalence
9944 during parsing SDCC.y */
9945 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9946 "got '>=' or '<=' shouldn't have come here");
9950 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9962 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9966 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9970 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9997 case GET_VALUE_AT_ADDRESS:
10002 if (POINTER_SET (ic))
10003 genPointerSet (ic);
10029 addSet (&_G.sendSet, ic);
10038 /* now we are ready to call the
10039 peep hole optimizer */
10040 if (!options.nopeep)
10041 peepHole (&lineHead);
10043 /* now do the actual printing */
10044 printLine (lineHead, codeOutFile);