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 if (AOP_TYPE(left)==AOP_ACC) {
5357 emitcode("mov", "b,a");
5358 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5359 emitcode("anl", "a,b");
5361 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5362 emitcode ("anl", "a,%s",
5363 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5366 emitcode ("jnz", "%05d$", tlbl->key + 100);
5372 emitcode ("", "%05d$:", tlbl->key + 100);
5376 jmpTrueOrFalse (ifx, tlbl);
5380 for (; (size--); offset++)
5383 // result = left & right
5384 if (AOP_TYPE (right) == AOP_LIT)
5386 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5388 aopPut (AOP (result),
5389 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5393 else if (bytelit == 0)
5395 aopPut (AOP (result), zero, offset);
5398 D (emitcode (";", "better literal AND.");
5400 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5401 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5402 FALSE, FALSE, FALSE));
5407 // faster than result <- left, anl result,right
5408 // and better if result is SFR
5409 if (AOP_TYPE (left) == AOP_ACC)
5411 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5412 FALSE, FALSE, FALSE));
5416 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5417 emitcode ("anl", "a,%s",
5418 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5421 aopPut (AOP (result), "a", offset);
5427 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5428 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5429 freeAsmop (result, NULL, ic, TRUE);
5433 /*-----------------------------------------------------------------*/
5434 /* genOr - code for or */
5435 /*-----------------------------------------------------------------*/
5437 genOr (iCode * ic, iCode * ifx)
5439 operand *left, *right, *result;
5440 int size, offset = 0;
5441 unsigned long lit = 0L;
5444 D (emitcode (";", "genOr "););
5446 AOP_OP_3_NOFATAL (ic, pushResult);
5447 AOP_SET_LOCALS (ic);
5451 genFarFarLogicOp(ic, "orl");
5457 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5459 AOP_TYPE (left), AOP_TYPE (right));
5460 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5462 AOP_SIZE (left), AOP_SIZE (right));
5465 /* if left is a literal & right is not then exchange them */
5466 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5467 AOP_NEEDSACC (left))
5469 operand *tmp = right;
5474 /* if result = right then exchange them */
5475 if (sameRegs (AOP (result), AOP (right)))
5477 operand *tmp = right;
5482 /* if right is bit then exchange them */
5483 if (AOP_TYPE (right) == AOP_CRY &&
5484 AOP_TYPE (left) != AOP_CRY)
5486 operand *tmp = right;
5490 if (AOP_TYPE (right) == AOP_LIT)
5491 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5493 size = AOP_SIZE (result);
5497 if (AOP_TYPE (left) == AOP_CRY)
5499 if (AOP_TYPE (right) == AOP_LIT)
5501 // c = bit & literal;
5504 // lit != 0 => result = 1
5505 if (AOP_TYPE (result) == AOP_CRY)
5508 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5510 continueIfTrue (ifx);
5513 emitcode ("setb", "c");
5517 // lit == 0 => result = left
5518 if (size && sameRegs (AOP (result), AOP (left)))
5520 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5525 if (AOP_TYPE (right) == AOP_CRY)
5528 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5529 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5534 symbol *tlbl = newiTempLabel (NULL);
5535 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5536 emitcode ("setb", "c");
5537 emitcode ("jb", "%s,%05d$",
5538 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5540 emitcode ("jnz", "%05d$", tlbl->key + 100);
5541 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5543 jmpTrueOrFalse (ifx, tlbl);
5549 emitcode ("", "%05d$:", tlbl->key + 100);
5558 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5559 genIfxJump (ifx, "c");
5563 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5564 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5565 if ((AOP_TYPE (right) == AOP_LIT) &&
5566 (AOP_TYPE (result) == AOP_CRY) &&
5567 (AOP_TYPE (left) != AOP_CRY))
5573 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5575 continueIfTrue (ifx);
5580 // lit = 0, result = boolean(left)
5582 emitcode ("setb", "c");
5586 symbol *tlbl = newiTempLabel (NULL);
5587 emitcode ("jnz", "%05d$", tlbl->key + 100);
5589 emitcode ("", "%05d$:", tlbl->key + 100);
5593 genIfxJump (ifx, "a");
5601 /* if left is same as result */
5602 if (sameRegs (AOP (result), AOP (left)))
5604 for (; size--; offset++)
5606 if (AOP_TYPE (right) == AOP_LIT)
5608 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5614 if (IS_AOP_PREG (left))
5616 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5617 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5618 aopPut (AOP (result), "a", offset);
5622 emitcode ("orl", "%s,%s",
5623 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5624 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5630 if (AOP_TYPE (left) == AOP_ACC)
5632 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5636 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5637 if (IS_AOP_PREG (left))
5639 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5640 aopPut (AOP (result), "a", offset);
5644 emitcode ("orl", "%s,a",
5645 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5653 // left & result in different registers
5654 if (AOP_TYPE (result) == AOP_CRY)
5657 // if(size), result in bit
5658 // if(!size && ifx), conditional oper: if(left | right)
5659 symbol *tlbl = newiTempLabel (NULL);
5660 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5662 emitcode ("setb", "c");
5665 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5666 emitcode ("orl", "a,%s",
5667 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5669 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5670 emitcode ("orl", "a,%s",
5671 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5673 emitcode ("jnz", "%05d$", tlbl->key + 100);
5679 emitcode ("", "%05d$:", tlbl->key + 100);
5683 jmpTrueOrFalse (ifx, tlbl);
5687 for (; (size--); offset++)
5690 // result = left & right
5691 if (AOP_TYPE (right) == AOP_LIT)
5693 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5695 aopPut (AOP (result),
5696 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5700 D (emitcode (";", "better literal OR.");
5702 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5703 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5704 FALSE, FALSE, FALSE));
5709 // faster than result <- left, anl result,right
5710 // and better if result is SFR
5711 if (AOP_TYPE (left) == AOP_ACC)
5713 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5714 FALSE, FALSE, FALSE));
5718 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5719 emitcode ("orl", "a,%s",
5720 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5723 aopPut (AOP (result), "a", offset);
5729 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5730 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5731 freeAsmop (result, NULL, ic, TRUE);
5734 /*-----------------------------------------------------------------*/
5735 /* genXor - code for xclusive or */
5736 /*-----------------------------------------------------------------*/
5738 genXor (iCode * ic, iCode * ifx)
5740 operand *left, *right, *result;
5741 int size, offset = 0;
5742 unsigned long lit = 0L;
5745 D (emitcode (";", "genXor "););
5747 AOP_OP_3_NOFATAL (ic, pushResult);
5748 AOP_SET_LOCALS (ic);
5752 genFarFarLogicOp(ic, "xrl");
5757 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5759 AOP_TYPE (left), AOP_TYPE (right));
5760 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5762 AOP_SIZE (left), AOP_SIZE (right));
5765 /* if left is a literal & right is not ||
5766 if left needs acc & right does not */
5767 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5768 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5770 operand *tmp = right;
5775 /* if result = right then exchange them */
5776 if (sameRegs (AOP (result), AOP (right)))
5778 operand *tmp = right;
5783 /* if right is bit then exchange them */
5784 if (AOP_TYPE (right) == AOP_CRY &&
5785 AOP_TYPE (left) != AOP_CRY)
5787 operand *tmp = right;
5791 if (AOP_TYPE (right) == AOP_LIT)
5792 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5794 size = AOP_SIZE (result);
5798 if (AOP_TYPE (left) == AOP_CRY)
5800 if (AOP_TYPE (right) == AOP_LIT)
5802 // c = bit & literal;
5805 // lit>>1 != 0 => result = 1
5806 if (AOP_TYPE (result) == AOP_CRY)
5809 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5811 continueIfTrue (ifx);
5814 emitcode ("setb", "c");
5821 // lit == 0, result = left
5822 if (size && sameRegs (AOP (result), AOP (left)))
5824 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5828 // lit == 1, result = not(left)
5829 if (size && sameRegs (AOP (result), AOP (left)))
5831 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5836 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5837 emitcode ("cpl", "c");
5846 symbol *tlbl = newiTempLabel (NULL);
5847 if (AOP_TYPE (right) == AOP_CRY)
5850 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5854 int sizer = AOP_SIZE (right);
5856 // if val>>1 != 0, result = 1
5857 emitcode ("setb", "c");
5860 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5862 // test the msb of the lsb
5863 emitcode ("anl", "a,#0xfe");
5864 emitcode ("jnz", "%05d$", tlbl->key + 100);
5868 emitcode ("rrc", "a");
5870 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5871 emitcode ("cpl", "c");
5872 emitcode ("", "%05d$:", (tlbl->key + 100));
5879 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5880 genIfxJump (ifx, "c");
5884 if (sameRegs (AOP (result), AOP (left)))
5886 /* if left is same as result */
5887 for (; size--; offset++)
5889 if (AOP_TYPE (right) == AOP_LIT)
5891 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5893 else if (IS_AOP_PREG (left))
5895 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5896 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5897 aopPut (AOP (result), "a", offset);
5900 emitcode ("xrl", "%s,%s",
5901 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5902 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5906 if (AOP_TYPE (left) == AOP_ACC)
5907 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5910 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5911 if (IS_AOP_PREG (left))
5913 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5914 aopPut (AOP (result), "a", offset);
5917 emitcode ("xrl", "%s,a",
5918 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5925 // left & result in different registers
5926 if (AOP_TYPE (result) == AOP_CRY)
5929 // if(size), result in bit
5930 // if(!size && ifx), conditional oper: if(left ^ right)
5931 symbol *tlbl = newiTempLabel (NULL);
5932 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5934 emitcode ("setb", "c");
5937 if ((AOP_TYPE (right) == AOP_LIT) &&
5938 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5940 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5944 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5945 emitcode ("xrl", "a,%s",
5946 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5948 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5949 emitcode ("xrl", "a,%s",
5950 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5953 emitcode ("jnz", "%05d$", tlbl->key + 100);
5959 emitcode ("", "%05d$:", tlbl->key + 100);
5963 jmpTrueOrFalse (ifx, tlbl);
5966 for (; (size--); offset++)
5969 // result = left & right
5970 if (AOP_TYPE (right) == AOP_LIT)
5972 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5974 aopPut (AOP (result),
5975 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5979 D (emitcode (";", "better literal XOR.");
5981 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5982 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5983 FALSE, FALSE, FALSE));
5987 // faster than result <- left, anl result,right
5988 // and better if result is SFR
5989 if (AOP_TYPE (left) == AOP_ACC)
5991 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5992 FALSE, FALSE, FALSE));
5996 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5997 emitcode ("xrl", "a,%s",
5998 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6001 aopPut (AOP (result), "a", offset);
6006 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6007 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6008 freeAsmop (result, NULL, ic, TRUE);
6011 /*-----------------------------------------------------------------*/
6012 /* genInline - write the inline code out */
6013 /*-----------------------------------------------------------------*/
6015 genInline (iCode * ic)
6017 char *buffer, *bp, *bp1;
6019 D (emitcode (";", "genInline ");
6022 _G.inLine += (!options.asmpeep);
6024 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6025 strcpy (buffer, IC_INLINE (ic));
6027 /* emit each line as a code */
6052 /* emitcode("",buffer); */
6053 _G.inLine -= (!options.asmpeep);
6056 /*-----------------------------------------------------------------*/
6057 /* genRRC - rotate right with carry */
6058 /*-----------------------------------------------------------------*/
6062 operand *left, *result;
6063 int size, offset = 0;
6066 D (emitcode (";", "genRRC ");
6069 /* rotate right with carry */
6070 left = IC_LEFT (ic);
6071 result = IC_RESULT (ic);
6072 aopOp (left, ic, FALSE, FALSE);
6073 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6075 /* move it to the result */
6076 size = AOP_SIZE (result);
6080 _startLazyDPSEvaluation ();
6083 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6085 emitcode ("rrc", "a");
6086 if (AOP_SIZE (result) > 1)
6087 aopPut (AOP (result), "a", offset--);
6089 _endLazyDPSEvaluation ();
6091 /* now we need to put the carry into the
6092 highest order byte of the result */
6093 if (AOP_SIZE (result) > 1)
6095 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6098 emitcode ("mov", "acc.7,c");
6099 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6100 freeAsmop (left, NULL, ic, TRUE);
6101 freeAsmop (result, NULL, ic, TRUE);
6104 /*-----------------------------------------------------------------*/
6105 /* genRLC - generate code for rotate left with carry */
6106 /*-----------------------------------------------------------------*/
6110 operand *left, *result;
6111 int size, offset = 0;
6114 D (emitcode (";", "genRLC ");
6117 /* rotate right with carry */
6118 left = IC_LEFT (ic);
6119 result = IC_RESULT (ic);
6120 aopOp (left, ic, FALSE, FALSE);
6121 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6123 /* move it to the result */
6124 size = AOP_SIZE (result);
6128 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6130 emitcode ("add", "a,acc");
6131 if (AOP_SIZE (result) > 1)
6133 aopPut (AOP (result), "a", offset++);
6136 _startLazyDPSEvaluation ();
6139 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6141 emitcode ("rlc", "a");
6142 if (AOP_SIZE (result) > 1)
6143 aopPut (AOP (result), "a", offset++);
6145 _endLazyDPSEvaluation ();
6147 /* now we need to put the carry into the
6148 highest order byte of the result */
6149 if (AOP_SIZE (result) > 1)
6151 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6154 emitcode ("mov", "acc.0,c");
6155 aopPut (AOP (result), "a", 0);
6156 freeAsmop (left, NULL, ic, TRUE);
6157 freeAsmop (result, NULL, ic, TRUE);
6160 /*-----------------------------------------------------------------*/
6161 /* genGetHbit - generates code get highest order bit */
6162 /*-----------------------------------------------------------------*/
6164 genGetHbit (iCode * ic)
6166 operand *left, *result;
6167 left = IC_LEFT (ic);
6168 result = IC_RESULT (ic);
6169 aopOp (left, ic, FALSE, FALSE);
6170 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6172 D (emitcode (";", "genGetHbit ");
6175 /* get the highest order byte into a */
6176 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6177 if (AOP_TYPE (result) == AOP_CRY)
6179 emitcode ("rlc", "a");
6184 emitcode ("rl", "a");
6185 emitcode ("anl", "a,#0x01");
6190 freeAsmop (left, NULL, ic, TRUE);
6191 freeAsmop (result, NULL, ic, TRUE);
6194 /*-----------------------------------------------------------------*/
6195 /* AccRol - rotate left accumulator by known count */
6196 /*-----------------------------------------------------------------*/
6198 AccRol (int shCount)
6200 shCount &= 0x0007; // shCount : 0..7
6207 emitcode ("rl", "a");
6210 emitcode ("rl", "a");
6211 emitcode ("rl", "a");
6214 emitcode ("swap", "a");
6215 emitcode ("rr", "a");
6218 emitcode ("swap", "a");
6221 emitcode ("swap", "a");
6222 emitcode ("rl", "a");
6225 emitcode ("rr", "a");
6226 emitcode ("rr", "a");
6229 emitcode ("rr", "a");
6234 /*-----------------------------------------------------------------*/
6235 /* AccLsh - left shift accumulator by known count */
6236 /*-----------------------------------------------------------------*/
6238 AccLsh (int shCount)
6243 emitcode ("add", "a,acc");
6244 else if (shCount == 2)
6246 emitcode ("add", "a,acc");
6247 emitcode ("add", "a,acc");
6251 /* rotate left accumulator */
6253 /* and kill the lower order bits */
6254 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6259 /*-----------------------------------------------------------------*/
6260 /* AccRsh - right shift accumulator by known count */
6261 /*-----------------------------------------------------------------*/
6263 AccRsh (int shCount)
6270 emitcode ("rrc", "a");
6274 /* rotate right accumulator */
6275 AccRol (8 - shCount);
6276 /* and kill the higher order bits */
6277 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6282 #ifdef BETTER_LITERAL_SHIFT
6283 /*-----------------------------------------------------------------*/
6284 /* AccSRsh - signed right shift accumulator by known count */
6285 /*-----------------------------------------------------------------*/
6287 AccSRsh (int shCount)
6294 emitcode ("mov", "c,acc.7");
6295 emitcode ("rrc", "a");
6297 else if (shCount == 2)
6299 emitcode ("mov", "c,acc.7");
6300 emitcode ("rrc", "a");
6301 emitcode ("mov", "c,acc.7");
6302 emitcode ("rrc", "a");
6306 tlbl = newiTempLabel (NULL);
6307 /* rotate right accumulator */
6308 AccRol (8 - shCount);
6309 /* and kill the higher order bits */
6310 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6311 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6312 emitcode ("orl", "a,#0x%02x",
6313 (unsigned char) ~SRMask[shCount]);
6314 emitcode ("", "%05d$:", tlbl->key + 100);
6320 #ifdef BETTER_LITERAL_SHIFT
6321 /*-----------------------------------------------------------------*/
6322 /* shiftR1Left2Result - shift right one byte from left to result */
6323 /*-----------------------------------------------------------------*/
6325 shiftR1Left2Result (operand * left, int offl,
6326 operand * result, int offr,
6327 int shCount, int sign)
6329 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6330 /* shift right accumulator */
6335 aopPut (AOP (result), "a", offr);
6339 #ifdef BETTER_LITERAL_SHIFT
6340 /*-----------------------------------------------------------------*/
6341 /* shiftL1Left2Result - shift left one byte from left to result */
6342 /*-----------------------------------------------------------------*/
6344 shiftL1Left2Result (operand * left, int offl,
6345 operand * result, int offr, int shCount)
6347 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6348 /* shift left accumulator */
6350 aopPut (AOP (result), "a", offr);
6354 #ifdef BETTER_LITERAL_SHIFT
6355 /*-----------------------------------------------------------------*/
6356 /* movLeft2Result - move byte from left to result */
6357 /*-----------------------------------------------------------------*/
6359 movLeft2Result (operand * left, int offl,
6360 operand * result, int offr, int sign)
6363 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6365 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6367 if (*l == '@' && (IS_AOP_PREG (result)))
6369 emitcode ("mov", "a,%s", l);
6370 aopPut (AOP (result), "a", offr);
6376 aopPut (AOP (result), l, offr);
6380 /* MSB sign in acc.7 ! */
6381 if (getDataSize (left) == offl + 1)
6383 emitcode ("mov", "a,%s", l);
6384 aopPut (AOP (result), "a", offr);
6392 #ifdef BETTER_LITERAL_SHIFT
6393 /*-----------------------------------------------------------------*/
6394 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6395 /*-----------------------------------------------------------------*/
6399 emitcode ("rrc", "a");
6400 emitcode ("xch", "a,%s", x);
6401 emitcode ("rrc", "a");
6402 emitcode ("xch", "a,%s", x);
6406 #ifdef BETTER_LITERAL_SHIFT
6408 /*-----------------------------------------------------------------*/
6409 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6410 /*-----------------------------------------------------------------*/
6414 emitcode ("xch", "a,%s", x);
6415 emitcode ("rlc", "a");
6416 emitcode ("xch", "a,%s", x);
6417 emitcode ("rlc", "a");
6421 #ifdef BETTER_LITERAL_SHIFT
6422 /*-----------------------------------------------------------------*/
6423 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6424 /*-----------------------------------------------------------------*/
6428 emitcode ("xch", "a,%s", x);
6429 emitcode ("add", "a,acc");
6430 emitcode ("xch", "a,%s", x);
6431 emitcode ("rlc", "a");
6435 #ifdef BETTER_LITERAL_SHIFT
6436 /*-----------------------------------------------------------------*/
6437 /* AccAXLsh - left shift a:x by known count (0..7) */
6438 /*-----------------------------------------------------------------*/
6440 AccAXLsh (char *x, int shCount)
6455 case 5: // AAAAABBB:CCCCCDDD
6457 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6459 emitcode ("anl", "a,#0x%02x",
6460 SLMask[shCount]); // BBB00000:CCCCCDDD
6462 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6464 AccRol (shCount); // DDDCCCCC:BBB00000
6466 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6468 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6470 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6472 emitcode ("anl", "a,#0x%02x",
6473 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6475 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6477 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6480 case 6: // AAAAAABB:CCCCCCDD
6481 emitcode ("anl", "a,#0x%02x",
6482 SRMask[shCount]); // 000000BB:CCCCCCDD
6483 emitcode ("mov", "c,acc.0"); // c = B
6484 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6486 AccAXRrl1 (x); // BCCCCCCD:D000000B
6487 AccAXRrl1 (x); // BBCCCCCC:DD000000
6489 emitcode("rrc","a");
6490 emitcode("xch","a,%s", x);
6491 emitcode("rrc","a");
6492 emitcode("mov","c,acc.0"); //<< get correct bit
6493 emitcode("xch","a,%s", x);
6495 emitcode("rrc","a");
6496 emitcode("xch","a,%s", x);
6497 emitcode("rrc","a");
6498 emitcode("xch","a,%s", x);
6501 case 7: // a:x <<= 7
6503 emitcode ("anl", "a,#0x%02x",
6504 SRMask[shCount]); // 0000000B:CCCCCCCD
6506 emitcode ("mov", "c,acc.0"); // c = B
6508 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6510 AccAXRrl1 (x); // BCCCCCCC:D0000000
6519 #ifdef BETTER_LITERAL_SHIFT
6521 /*-----------------------------------------------------------------*/
6522 /* AccAXRsh - right shift a:x known count (0..7) */
6523 /*-----------------------------------------------------------------*/
6525 AccAXRsh (char *x, int shCount)
6533 AccAXRrl1 (x); // 0->a:x
6538 AccAXRrl1 (x); // 0->a:x
6541 AccAXRrl1 (x); // 0->a:x
6546 case 5: // AAAAABBB:CCCCCDDD = a:x
6548 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6550 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6552 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6554 emitcode ("anl", "a,#0x%02x",
6555 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6557 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6559 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6561 emitcode ("anl", "a,#0x%02x",
6562 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6564 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6566 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6568 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6571 case 6: // AABBBBBB:CCDDDDDD
6573 emitcode ("mov", "c,acc.7");
6574 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6576 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6578 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6580 emitcode ("anl", "a,#0x%02x",
6581 SRMask[shCount]); // 000000AA:BBBBBBCC
6584 case 7: // ABBBBBBB:CDDDDDDD
6586 emitcode ("mov", "c,acc.7"); // c = A
6588 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6590 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6592 emitcode ("anl", "a,#0x%02x",
6593 SRMask[shCount]); // 0000000A:BBBBBBBC
6602 #ifdef BETTER_LITERAL_SHIFT
6604 /*-----------------------------------------------------------------*/
6605 /* AccAXRshS - right shift signed a:x known count (0..7) */
6606 /*-----------------------------------------------------------------*/
6608 AccAXRshS (char *x, int shCount)
6616 emitcode ("mov", "c,acc.7");
6617 AccAXRrl1 (x); // s->a:x
6621 emitcode ("mov", "c,acc.7");
6622 AccAXRrl1 (x); // s->a:x
6624 emitcode ("mov", "c,acc.7");
6625 AccAXRrl1 (x); // s->a:x
6630 case 5: // AAAAABBB:CCCCCDDD = a:x
6632 tlbl = newiTempLabel (NULL);
6633 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6635 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6637 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6639 emitcode ("anl", "a,#0x%02x",
6640 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6642 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6644 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6646 emitcode ("anl", "a,#0x%02x",
6647 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6649 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6651 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6653 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6655 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6656 emitcode ("orl", "a,#0x%02x",
6657 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6659 emitcode ("", "%05d$:", tlbl->key + 100);
6660 break; // SSSSAAAA:BBBCCCCC
6662 case 6: // AABBBBBB:CCDDDDDD
6664 tlbl = newiTempLabel (NULL);
6665 emitcode ("mov", "c,acc.7");
6666 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6668 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6670 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6672 emitcode ("anl", "a,#0x%02x",
6673 SRMask[shCount]); // 000000AA:BBBBBBCC
6675 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6676 emitcode ("orl", "a,#0x%02x",
6677 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6679 emitcode ("", "%05d$:", tlbl->key + 100);
6681 case 7: // ABBBBBBB:CDDDDDDD
6683 tlbl = newiTempLabel (NULL);
6684 emitcode ("mov", "c,acc.7"); // c = A
6686 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6688 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6690 emitcode ("anl", "a,#0x%02x",
6691 SRMask[shCount]); // 0000000A:BBBBBBBC
6693 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6694 emitcode ("orl", "a,#0x%02x",
6695 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6697 emitcode ("", "%05d$:", tlbl->key + 100);
6705 #ifdef BETTER_LITERAL_SHIFT
6707 _loadLeftIntoAx(char **lsb,
6713 // Get the initial value from left into a pair of registers.
6714 // MSB must be in A, LSB can be any register.
6716 // If the result is held in registers, it is an optimization
6717 // if the LSB can be held in the register which will hold the,
6718 // result LSB since this saves us from having to copy it into
6719 // the result following AccAXLsh.
6721 // If the result is addressed indirectly, this is not a gain.
6722 if (AOP_NEEDSACC(result))
6726 _startLazyDPSEvaluation();
6727 if (AOP_TYPE(left) == AOP_DPTR2)
6730 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6731 // get LSB in DP2_RESULT_REG.
6732 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6733 assert(!strcmp(leftByte, DP2_RESULT_REG));
6737 // get LSB into DP2_RESULT_REG
6738 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6739 if (strcmp(leftByte, DP2_RESULT_REG))
6741 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6744 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6745 assert(strcmp(leftByte, DP2_RESULT_REG));
6748 _endLazyDPSEvaluation();
6749 *lsb = DP2_RESULT_REG;
6753 if (sameRegs (AOP (result), AOP (left)) &&
6754 ((offl + MSB16) == offr))
6756 /* don't crash result[offr] */
6757 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6758 emitcode ("xch", "a,%s",
6759 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6763 movLeft2Result (left, offl, result, offr, 0);
6764 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6766 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6767 assert(strcmp(*lsb,"a"));
6772 _storeAxResults(char *lsb,
6776 _startLazyDPSEvaluation();
6777 if (AOP_NEEDSACC(result))
6779 /* We have to explicitly update the result LSB.
6781 emitcode("xch","a,%s", lsb);
6782 aopPut(AOP(result), "a", offr);
6783 emitcode("mov","a,%s", lsb);
6785 if (getDataSize (result) > 1)
6787 aopPut (AOP (result), "a", offr + MSB16);
6789 _endLazyDPSEvaluation();
6792 /*-----------------------------------------------------------------*/
6793 /* shiftL2Left2Result - shift left two bytes from left to result */
6794 /*-----------------------------------------------------------------*/
6796 shiftL2Left2Result (operand * left, int offl,
6797 operand * result, int offr, int shCount)
6801 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6803 AccAXLsh (lsb, shCount);
6805 _storeAxResults(lsb, result, offr);
6809 #ifdef BETTER_LITERAL_SHIFT
6810 /*-----------------------------------------------------------------*/
6811 /* shiftR2Left2Result - shift right two bytes from left to result */
6812 /*-----------------------------------------------------------------*/
6814 shiftR2Left2Result (operand * left, int offl,
6815 operand * result, int offr,
6816 int shCount, int sign)
6820 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6822 /* a:x >> shCount (x = lsb(result)) */
6825 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6829 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6832 _storeAxResults(lsb, result, offr);
6838 /*-----------------------------------------------------------------*/
6839 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6840 /*-----------------------------------------------------------------*/
6842 shiftLLeftOrResult (operand * left, int offl,
6843 operand * result, int offr, int shCount)
6845 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6846 /* shift left accumulator */
6848 /* or with result */
6849 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6850 /* back to result */
6851 aopPut (AOP (result), "a", offr);
6857 /*-----------------------------------------------------------------*/
6858 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6859 /*-----------------------------------------------------------------*/
6861 shiftRLeftOrResult (operand * left, int offl,
6862 operand * result, int offr, int shCount)
6864 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6865 /* shift right accumulator */
6867 /* or with result */
6868 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6869 /* back to result */
6870 aopPut (AOP (result), "a", offr);
6874 #ifdef BETTER_LITERAL_SHIFT
6875 /*-----------------------------------------------------------------*/
6876 /* genlshOne - left shift a one byte quantity by known count */
6877 /*-----------------------------------------------------------------*/
6879 genlshOne (operand * result, operand * left, int shCount)
6881 D (emitcode (";", "genlshOne "););
6882 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6886 #ifdef BETTER_LITERAL_SHIFT
6887 /*-----------------------------------------------------------------*/
6888 /* genlshTwo - left shift two bytes by known amount != 0 */
6889 /*-----------------------------------------------------------------*/
6891 genlshTwo (operand * result, operand * left, int shCount)
6895 D (emitcode (";", "genlshTwo "););
6897 size = getDataSize (result);
6899 /* if shCount >= 8 */
6904 _startLazyDPSEvaluation();
6910 _endLazyDPSEvaluation();
6911 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6912 aopPut (AOP (result), zero, LSB);
6916 movLeft2Result (left, LSB, result, MSB16, 0);
6917 aopPut (AOP (result), zero, LSB);
6918 _endLazyDPSEvaluation();
6923 aopPut (AOP (result), zero, LSB);
6924 _endLazyDPSEvaluation();
6928 /* 1 <= shCount <= 7 */
6933 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6937 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6945 /*-----------------------------------------------------------------*/
6946 /* shiftLLong - shift left one long from left to result */
6947 /* offl = LSB or MSB16 */
6948 /*-----------------------------------------------------------------*/
6950 shiftLLong (operand * left, operand * result, int offr)
6953 int size = AOP_SIZE (result);
6955 if (size >= LSB + offr)
6957 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6959 emitcode ("add", "a,acc");
6960 if (sameRegs (AOP (left), AOP (result)) &&
6961 size >= MSB16 + offr && offr != LSB)
6962 emitcode ("xch", "a,%s",
6963 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6965 aopPut (AOP (result), "a", LSB + offr);
6968 if (size >= MSB16 + offr)
6970 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6972 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6975 emitcode ("rlc", "a");
6976 if (sameRegs (AOP (left), AOP (result)) &&
6977 size >= MSB24 + offr && offr != LSB)
6978 emitcode ("xch", "a,%s",
6979 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6981 aopPut (AOP (result), "a", MSB16 + offr);
6984 if (size >= MSB24 + offr)
6986 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6988 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6991 emitcode ("rlc", "a");
6992 if (sameRegs (AOP (left), AOP (result)) &&
6993 size >= MSB32 + offr && offr != LSB)
6994 emitcode ("xch", "a,%s",
6995 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6997 aopPut (AOP (result), "a", MSB24 + offr);
7000 if (size > MSB32 + offr)
7002 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7004 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7007 emitcode ("rlc", "a");
7008 aopPut (AOP (result), "a", MSB32 + offr);
7011 aopPut (AOP (result), zero, LSB);
7017 /*-----------------------------------------------------------------*/
7018 /* genlshFour - shift four byte by a known amount != 0 */
7019 /*-----------------------------------------------------------------*/
7021 genlshFour (operand * result, operand * left, int shCount)
7025 D (emitcode (";", "genlshFour ");
7028 size = AOP_SIZE (result);
7030 /* if shifting more that 3 bytes */
7035 /* lowest order of left goes to the highest
7036 order of the destination */
7037 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7039 movLeft2Result (left, LSB, result, MSB32, 0);
7040 aopPut (AOP (result), zero, LSB);
7041 aopPut (AOP (result), zero, MSB16);
7042 aopPut (AOP (result), zero, MSB24);
7046 /* more than two bytes */
7047 else if (shCount >= 16)
7049 /* lower order two bytes goes to higher order two bytes */
7051 /* if some more remaining */
7053 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7056 movLeft2Result (left, MSB16, result, MSB32, 0);
7057 movLeft2Result (left, LSB, result, MSB24, 0);
7059 aopPut (AOP (result), zero, MSB16);
7060 aopPut (AOP (result), zero, LSB);
7064 /* if more than 1 byte */
7065 else if (shCount >= 8)
7067 /* lower order three bytes goes to higher order three bytes */
7072 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7074 movLeft2Result (left, LSB, result, MSB16, 0);
7080 movLeft2Result (left, MSB24, result, MSB32, 0);
7081 movLeft2Result (left, MSB16, result, MSB24, 0);
7082 movLeft2Result (left, LSB, result, MSB16, 0);
7083 aopPut (AOP (result), zero, LSB);
7085 else if (shCount == 1)
7086 shiftLLong (left, result, MSB16);
7089 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7090 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7091 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7092 aopPut (AOP (result), zero, LSB);
7097 /* 1 <= shCount <= 7 */
7098 else if (shCount <= 2)
7100 shiftLLong (left, result, LSB);
7102 shiftLLong (result, result, LSB);
7104 /* 3 <= shCount <= 7, optimize */
7107 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7108 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7109 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7114 #ifdef BETTER_LITERAL_SHIFT
7115 /*-----------------------------------------------------------------*/
7116 /* genLeftShiftLiteral - left shifting by known count */
7117 /*-----------------------------------------------------------------*/
7119 genLeftShiftLiteral (operand * left,
7124 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7127 size = getSize (operandType (result));
7129 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7131 /* We only handle certain easy cases so far. */
7133 && (shCount < (size * 8))
7137 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7141 freeAsmop (right, NULL, ic, TRUE);
7143 aopOp(left, ic, FALSE, FALSE);
7144 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7147 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7149 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7150 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7152 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7155 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7157 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7158 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7160 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7166 emitcode ("; shift left ", "result %d, left %d", size,
7170 /* I suppose that the left size >= result size */
7173 _startLazyDPSEvaluation();
7176 movLeft2Result (left, size, result, size, 0);
7178 _endLazyDPSEvaluation();
7180 else if (shCount >= (size * 8))
7182 _startLazyDPSEvaluation();
7185 aopPut (AOP (result), zero, size);
7187 _endLazyDPSEvaluation();
7194 genlshOne (result, left, shCount);
7198 genlshTwo (result, left, shCount);
7202 genlshFour (result, left, shCount);
7206 fprintf(stderr, "*** ack! mystery literal shift!\n");
7210 freeAsmop (left, NULL, ic, TRUE);
7211 freeAsmop (result, NULL, ic, TRUE);
7216 /*-----------------------------------------------------------------*/
7217 /* genLeftShift - generates code for left shifting */
7218 /*-----------------------------------------------------------------*/
7220 genLeftShift (iCode * ic)
7222 operand *left, *right, *result;
7225 symbol *tlbl, *tlbl1;
7227 D (emitcode (";", "genLeftShift "););
7229 right = IC_RIGHT (ic);
7230 left = IC_LEFT (ic);
7231 result = IC_RESULT (ic);
7233 aopOp (right, ic, FALSE, FALSE);
7236 #ifdef BETTER_LITERAL_SHIFT
7237 /* if the shift count is known then do it
7238 as efficiently as possible */
7239 if (AOP_TYPE (right) == AOP_LIT)
7241 if (genLeftShiftLiteral (left, right, result, ic))
7248 /* shift count is unknown then we have to form
7249 a loop get the loop count in B : Note: we take
7250 only the lower order byte since shifting
7251 more that 32 bits make no sense anyway, ( the
7252 largest size of an object can be only 32 bits ) */
7254 if (AOP_TYPE (right) == AOP_LIT)
7256 /* Really should be handled by genLeftShiftLiteral,
7257 * but since I'm too lazy to fix that today, at least we can make
7258 * some small improvement.
7260 emitcode("mov", "b,#0x%02x",
7261 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7265 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7266 emitcode ("inc", "b");
7268 freeAsmop (right, NULL, ic, TRUE);
7269 aopOp (left, ic, FALSE, FALSE);
7270 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7272 /* now move the left to the result if they are not the
7274 if (!sameRegs (AOP (left), AOP (result)) &&
7275 AOP_SIZE (result) > 1)
7278 size = AOP_SIZE (result);
7280 _startLazyDPSEvaluation ();
7283 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7284 if (*l == '@' && (IS_AOP_PREG (result)))
7287 emitcode ("mov", "a,%s", l);
7288 aopPut (AOP (result), "a", offset);
7291 aopPut (AOP (result), l, offset);
7294 _endLazyDPSEvaluation ();
7297 tlbl = newiTempLabel (NULL);
7298 size = AOP_SIZE (result);
7300 tlbl1 = newiTempLabel (NULL);
7302 /* if it is only one byte then */
7305 symbol *tlbl1 = newiTempLabel (NULL);
7307 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7309 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7310 emitcode ("", "%05d$:", tlbl->key + 100);
7311 emitcode ("add", "a,acc");
7312 emitcode ("", "%05d$:", tlbl1->key + 100);
7313 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7314 aopPut (AOP (result), "a", 0);
7318 reAdjustPreg (AOP (result));
7320 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7321 emitcode ("", "%05d$:", tlbl->key + 100);
7322 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7324 emitcode ("add", "a,acc");
7325 aopPut (AOP (result), "a", offset++);
7326 _startLazyDPSEvaluation ();
7329 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7331 emitcode ("rlc", "a");
7332 aopPut (AOP (result), "a", offset++);
7334 _endLazyDPSEvaluation ();
7335 reAdjustPreg (AOP (result));
7337 emitcode ("", "%05d$:", tlbl1->key + 100);
7338 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7340 freeAsmop (left, NULL, ic, TRUE);
7341 freeAsmop (result, NULL, ic, TRUE);
7344 #ifdef BETTER_LITERAL_SHIFT
7345 /*-----------------------------------------------------------------*/
7346 /* genrshOne - right shift a one byte quantity by known count */
7347 /*-----------------------------------------------------------------*/
7349 genrshOne (operand * result, operand * left,
7350 int shCount, int sign)
7352 D (emitcode (";", "genrshOne"););
7353 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7357 #ifdef BETTER_LITERAL_SHIFT
7358 /*-----------------------------------------------------------------*/
7359 /* genrshTwo - right shift two bytes by known amount != 0 */
7360 /*-----------------------------------------------------------------*/
7362 genrshTwo (operand * result, operand * left,
7363 int shCount, int sign)
7365 D (emitcode (";", "genrshTwo"););
7367 /* if shCount >= 8 */
7371 _startLazyDPSEvaluation();
7374 shiftR1Left2Result (left, MSB16, result, LSB,
7379 movLeft2Result (left, MSB16, result, LSB, sign);
7381 addSign (result, MSB16, sign);
7382 _endLazyDPSEvaluation();
7385 /* 1 <= shCount <= 7 */
7388 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7395 /*-----------------------------------------------------------------*/
7396 /* shiftRLong - shift right one long from left to result */
7397 /* offl = LSB or MSB16 */
7398 /*-----------------------------------------------------------------*/
7400 shiftRLong (operand * left, int offl,
7401 operand * result, int sign)
7403 int isSameRegs=sameRegs(AOP(left),AOP(result));
7405 if (isSameRegs && offl>1) {
7406 // we are in big trouble, but this shouldn't happen
7407 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7410 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7415 emitcode ("rlc", "a");
7416 emitcode ("subb", "a,acc");
7417 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7419 aopPut (AOP(result), zero, MSB32);
7424 emitcode ("clr", "c");
7426 emitcode ("mov", "c,acc.7");
7429 emitcode ("rrc", "a");
7431 if (isSameRegs && offl==MSB16) {
7432 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7434 aopPut (AOP (result), "a", MSB32);
7435 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7438 emitcode ("rrc", "a");
7439 if (isSameRegs && offl==1) {
7440 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7442 aopPut (AOP (result), "a", MSB24);
7443 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7445 emitcode ("rrc", "a");
7446 aopPut (AOP (result), "a", MSB16 - offl);
7450 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7451 emitcode ("rrc", "a");
7452 aopPut (AOP (result), "a", LSB);
7459 /*-----------------------------------------------------------------*/
7460 /* genrshFour - shift four byte by a known amount != 0 */
7461 /*-----------------------------------------------------------------*/
7463 genrshFour (operand * result, operand * left,
7464 int shCount, int sign)
7466 D (emitcode (";", "genrshFour");
7469 /* if shifting more that 3 bytes */
7474 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7476 movLeft2Result (left, MSB32, result, LSB, sign);
7477 addSign (result, MSB16, sign);
7479 else if (shCount >= 16)
7483 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7486 movLeft2Result (left, MSB24, result, LSB, 0);
7487 movLeft2Result (left, MSB32, result, MSB16, sign);
7489 addSign (result, MSB24, sign);
7491 else if (shCount >= 8)
7495 shiftRLong (left, MSB16, result, sign);
7496 else if (shCount == 0)
7498 movLeft2Result (left, MSB16, result, LSB, 0);
7499 movLeft2Result (left, MSB24, result, MSB16, 0);
7500 movLeft2Result (left, MSB32, result, MSB24, sign);
7501 addSign (result, MSB32, sign);
7505 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7506 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7507 /* the last shift is signed */
7508 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7509 addSign (result, MSB32, sign);
7513 { /* 1 <= shCount <= 7 */
7516 shiftRLong (left, LSB, result, sign);
7518 shiftRLong (result, LSB, result, sign);
7522 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7523 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7524 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7530 #ifdef BETTER_LITERAL_SHIFT
7531 /*-----------------------------------------------------------------*/
7532 /* genRightShiftLiteral - right shifting by known count */
7533 /*-----------------------------------------------------------------*/
7535 genRightShiftLiteral (operand * left,
7541 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7544 size = getSize (operandType (result));
7546 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7548 /* We only handle certain easy cases so far. */
7550 && (shCount < (size * 8))
7554 D(emitcode (";", "genRightShiftLiteral wimping out"););
7558 freeAsmop (right, NULL, ic, TRUE);
7560 aopOp (left, ic, FALSE, FALSE);
7561 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7564 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7568 /* test the LEFT size !!! */
7570 /* I suppose that the left size >= result size */
7573 size = getDataSize (result);
7574 _startLazyDPSEvaluation();
7577 movLeft2Result (left, size, result, size, 0);
7579 _endLazyDPSEvaluation();
7581 else if (shCount >= (size * 8))
7585 /* get sign in acc.7 */
7586 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7588 addSign (result, LSB, sign);
7595 genrshOne (result, left, shCount, sign);
7599 genrshTwo (result, left, shCount, sign);
7603 genrshFour (result, left, shCount, sign);
7610 freeAsmop (left, NULL, ic, TRUE);
7611 freeAsmop (result, NULL, ic, TRUE);
7617 /*-----------------------------------------------------------------*/
7618 /* genSignedRightShift - right shift of signed number */
7619 /*-----------------------------------------------------------------*/
7621 genSignedRightShift (iCode * ic)
7623 operand *right, *left, *result;
7626 symbol *tlbl, *tlbl1;
7628 D (emitcode (";", "genSignedRightShift "););
7630 /* we do it the hard way put the shift count in b
7631 and loop thru preserving the sign */
7633 right = IC_RIGHT (ic);
7634 left = IC_LEFT (ic);
7635 result = IC_RESULT (ic);
7637 aopOp (right, ic, FALSE, FALSE);
7639 #ifdef BETTER_LITERAL_SHIFT
7640 if (AOP_TYPE (right) == AOP_LIT)
7642 if (genRightShiftLiteral (left, right, result, ic, 1))
7648 /* shift count is unknown then we have to form
7649 a loop get the loop count in B : Note: we take
7650 only the lower order byte since shifting
7651 more that 32 bits make no sense anyway, ( the
7652 largest size of an object can be only 32 bits ) */
7654 if (AOP_TYPE (right) == AOP_LIT)
7656 /* Really should be handled by genRightShiftLiteral,
7657 * but since I'm too lazy to fix that today, at least we can make
7658 * some small improvement.
7660 emitcode("mov", "b,#0x%02x",
7661 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7665 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7666 emitcode ("inc", "b");
7668 freeAsmop (right, NULL, ic, TRUE);
7669 aopOp (left, ic, FALSE, FALSE);
7670 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7672 /* now move the left to the result if they are not the
7674 if (!sameRegs (AOP (left), AOP (result)) &&
7675 AOP_SIZE (result) > 1)
7678 size = AOP_SIZE (result);
7680 _startLazyDPSEvaluation ();
7683 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7684 if (*l == '@' && IS_AOP_PREG (result))
7687 emitcode ("mov", "a,%s", l);
7688 aopPut (AOP (result), "a", offset);
7691 aopPut (AOP (result), l, offset);
7694 _endLazyDPSEvaluation ();
7697 /* mov the highest order bit to OVR */
7698 tlbl = newiTempLabel (NULL);
7699 tlbl1 = newiTempLabel (NULL);
7701 size = AOP_SIZE (result);
7703 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7704 emitcode ("rlc", "a");
7705 emitcode ("mov", "ov,c");
7706 /* if it is only one byte then */
7709 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7711 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7712 emitcode ("", "%05d$:", tlbl->key + 100);
7713 emitcode ("mov", "c,ov");
7714 emitcode ("rrc", "a");
7715 emitcode ("", "%05d$:", tlbl1->key + 100);
7716 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7717 aopPut (AOP (result), "a", 0);
7721 reAdjustPreg (AOP (result));
7722 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7723 emitcode ("", "%05d$:", tlbl->key + 100);
7724 emitcode ("mov", "c,ov");
7725 _startLazyDPSEvaluation ();
7728 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7730 emitcode ("rrc", "a");
7731 aopPut (AOP (result), "a", offset--);
7733 _endLazyDPSEvaluation ();
7734 reAdjustPreg (AOP (result));
7735 emitcode ("", "%05d$:", tlbl1->key + 100);
7736 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7739 freeAsmop (left, NULL, ic, TRUE);
7740 freeAsmop (result, NULL, ic, TRUE);
7743 /*-----------------------------------------------------------------*/
7744 /* genRightShift - generate code for right shifting */
7745 /*-----------------------------------------------------------------*/
7747 genRightShift (iCode * ic)
7749 operand *right, *left, *result;
7753 symbol *tlbl, *tlbl1;
7755 D (emitcode (";", "genRightShift "););
7757 /* if signed then we do it the hard way preserve the
7758 sign bit moving it inwards */
7759 retype = getSpec (operandType (IC_RESULT (ic)));
7761 if (!SPEC_USIGN (retype))
7763 genSignedRightShift (ic);
7767 /* signed & unsigned types are treated the same : i.e. the
7768 signed is NOT propagated inwards : quoting from the
7769 ANSI - standard : "for E1 >> E2, is equivalent to division
7770 by 2**E2 if unsigned or if it has a non-negative value,
7771 otherwise the result is implementation defined ", MY definition
7772 is that the sign does not get propagated */
7774 right = IC_RIGHT (ic);
7775 left = IC_LEFT (ic);
7776 result = IC_RESULT (ic);
7778 aopOp (right, ic, FALSE, FALSE);
7780 #ifdef BETTER_LITERAL_SHIFT
7781 /* if the shift count is known then do it
7782 as efficiently as possible */
7783 if (AOP_TYPE (right) == AOP_LIT)
7785 if (genRightShiftLiteral (left, right, result, ic, 0))
7792 /* shift count is unknown then we have to form
7793 a loop get the loop count in B : Note: we take
7794 only the lower order byte since shifting
7795 more that 32 bits make no sense anyway, ( the
7796 largest size of an object can be only 32 bits ) */
7798 if (AOP_TYPE (right) == AOP_LIT)
7800 /* Really should be handled by genRightShiftLiteral,
7801 * but since I'm too lazy to fix that today, at least we can make
7802 * some small improvement.
7804 emitcode("mov", "b,#0x%02x",
7805 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7809 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7810 emitcode ("inc", "b");
7812 freeAsmop (right, NULL, ic, TRUE);
7813 aopOp (left, ic, FALSE, FALSE);
7814 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7816 /* now move the left to the result if they are not the
7818 if (!sameRegs (AOP (left), AOP (result)) &&
7819 AOP_SIZE (result) > 1)
7822 size = AOP_SIZE (result);
7824 _startLazyDPSEvaluation ();
7827 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7828 if (*l == '@' && IS_AOP_PREG (result))
7831 emitcode ("mov", "a,%s", l);
7832 aopPut (AOP (result), "a", offset);
7835 aopPut (AOP (result), l, offset);
7838 _endLazyDPSEvaluation ();
7841 tlbl = newiTempLabel (NULL);
7842 tlbl1 = newiTempLabel (NULL);
7843 size = AOP_SIZE (result);
7846 /* if it is only one byte then */
7849 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7851 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7852 emitcode ("", "%05d$:", tlbl->key + 100);
7854 emitcode ("rrc", "a");
7855 emitcode ("", "%05d$:", tlbl1->key + 100);
7856 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7857 aopPut (AOP (result), "a", 0);
7861 reAdjustPreg (AOP (result));
7862 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7863 emitcode ("", "%05d$:", tlbl->key + 100);
7865 _startLazyDPSEvaluation ();
7868 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7870 emitcode ("rrc", "a");
7871 aopPut (AOP (result), "a", offset--);
7873 _endLazyDPSEvaluation ();
7874 reAdjustPreg (AOP (result));
7876 emitcode ("", "%05d$:", tlbl1->key + 100);
7877 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7880 freeAsmop (left, NULL, ic, TRUE);
7881 freeAsmop (result, NULL, ic, TRUE);
7884 /*-----------------------------------------------------------------*/
7885 /* genUnpackBits - generates code for unpacking bits */
7886 /*-----------------------------------------------------------------*/
7888 genUnpackBits (operand * result, char *rname, int ptype)
7895 D (emitcode (";", "genUnpackBits ");
7898 etype = getSpec (operandType (result));
7900 /* read the first byte */
7906 emitcode ("mov", "a,@%s", rname);
7910 emitcode ("movx", "a,@%s", rname);
7914 emitcode ("movx", "a,@dptr");
7918 emitcode ("clr", "a");
7919 emitcode ("movc", "a", "@a+dptr");
7923 emitcode ("lcall", "__gptrget");
7927 /* if we have bitdisplacement then it fits */
7928 /* into this byte completely or if length is */
7929 /* less than a byte */
7930 if ((shCnt = SPEC_BSTR (etype)) ||
7931 (SPEC_BLEN (etype) <= 8))
7934 /* shift right acc */
7937 emitcode ("anl", "a,#0x%02x",
7938 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7939 aopPut (AOP (result), "a", offset);
7943 /* bit field did not fit in a byte */
7944 rlen = SPEC_BLEN (etype) - 8;
7945 aopPut (AOP (result), "a", offset++);
7954 emitcode ("inc", "%s", rname);
7955 emitcode ("mov", "a,@%s", rname);
7959 emitcode ("inc", "%s", rname);
7960 emitcode ("movx", "a,@%s", rname);
7964 emitcode ("inc", "dptr");
7965 emitcode ("movx", "a,@dptr");
7969 emitcode ("clr", "a");
7970 emitcode ("inc", "dptr");
7971 emitcode ("movc", "a", "@a+dptr");
7975 emitcode ("inc", "dptr");
7976 emitcode ("lcall", "__gptrget");
7981 /* if we are done */
7985 aopPut (AOP (result), "a", offset++);
7991 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7992 aopPut (AOP (result), "a", offset);
7999 /*-----------------------------------------------------------------*/
8000 /* genDataPointerGet - generates code when ptr offset is known */
8001 /*-----------------------------------------------------------------*/
8003 genDataPointerGet (operand * left,
8009 int size, offset = 0;
8010 aopOp (result, ic, TRUE, FALSE);
8012 /* get the string representation of the name */
8013 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8014 size = AOP_SIZE (result);
8015 _startLazyDPSEvaluation ();
8019 sprintf (buffer, "(%s + %d)", l + 1, offset);
8021 sprintf (buffer, "%s", l + 1);
8022 aopPut (AOP (result), buffer, offset++);
8024 _endLazyDPSEvaluation ();
8026 freeAsmop (left, NULL, ic, TRUE);
8027 freeAsmop (result, NULL, ic, TRUE);
8030 /*-----------------------------------------------------------------*/
8031 /* genNearPointerGet - emitcode for near pointer fetch */
8032 /*-----------------------------------------------------------------*/
8034 genNearPointerGet (operand * left,
8041 sym_link *rtype, *retype, *letype;
8042 sym_link *ltype = operandType (left);
8045 rtype = operandType (result);
8046 retype = getSpec (rtype);
8047 letype = getSpec (ltype);
8049 aopOp (left, ic, FALSE, FALSE);
8051 /* if left is rematerialisable and
8052 result is not bit variable type and
8053 the left is pointer to data space i.e
8054 lower 128 bytes of space */
8055 if (AOP_TYPE (left) == AOP_IMMD &&
8056 !IS_BITVAR (retype) &&
8057 !IS_BITVAR (letype) &&
8058 DCL_TYPE (ltype) == POINTER)
8060 genDataPointerGet (left, result, ic);
8064 /* if the value is already in a pointer register
8065 then don't need anything more */
8066 if (!AOP_INPREG (AOP (left)))
8068 /* otherwise get a free pointer register */
8070 preg = getFreePtr (ic, &aop, FALSE);
8071 emitcode ("mov", "%s,%s",
8073 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8077 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8079 freeAsmop (left, NULL, ic, TRUE);
8080 aopOp (result, ic, FALSE, FALSE);
8082 /* if bitfield then unpack the bits */
8083 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8084 genUnpackBits (result, rname, POINTER);
8087 /* we have can just get the values */
8088 int size = AOP_SIZE (result);
8093 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8096 emitcode ("mov", "a,@%s", rname);
8097 aopPut (AOP (result), "a", offset);
8101 sprintf (buffer, "@%s", rname);
8102 aopPut (AOP (result), buffer, offset);
8106 emitcode ("inc", "%s", rname);
8110 /* now some housekeeping stuff */
8113 /* we had to allocate for this iCode */
8114 freeAsmop (NULL, aop, ic, TRUE);
8118 /* we did not allocate which means left
8119 already in a pointer register, then
8120 if size > 0 && this could be used again
8121 we have to point it back to where it
8123 if (AOP_SIZE (result) > 1 &&
8124 !OP_SYMBOL (left)->remat &&
8125 (OP_SYMBOL (left)->liveTo > ic->seq ||
8128 int size = AOP_SIZE (result) - 1;
8130 emitcode ("dec", "%s", rname);
8135 freeAsmop (result, NULL, ic, TRUE);
8139 /*-----------------------------------------------------------------*/
8140 /* genPagedPointerGet - emitcode for paged pointer fetch */
8141 /*-----------------------------------------------------------------*/
8143 genPagedPointerGet (operand * left,
8150 sym_link *rtype, *retype, *letype;
8152 rtype = operandType (result);
8153 retype = getSpec (rtype);
8154 letype = getSpec (operandType (left));
8155 aopOp (left, ic, FALSE, FALSE);
8157 /* if the value is already in a pointer register
8158 then don't need anything more */
8159 if (!AOP_INPREG (AOP (left)))
8161 /* otherwise get a free pointer register */
8163 preg = getFreePtr (ic, &aop, FALSE);
8164 emitcode ("mov", "%s,%s",
8166 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8170 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8172 freeAsmop (left, NULL, ic, TRUE);
8173 aopOp (result, ic, FALSE, FALSE);
8175 /* if bitfield then unpack the bits */
8176 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8177 genUnpackBits (result, rname, PPOINTER);
8180 /* we have can just get the values */
8181 int size = AOP_SIZE (result);
8187 emitcode ("movx", "a,@%s", rname);
8188 aopPut (AOP (result), "a", offset);
8193 emitcode ("inc", "%s", rname);
8197 /* now some housekeeping stuff */
8200 /* we had to allocate for this iCode */
8201 freeAsmop (NULL, aop, ic, TRUE);
8205 /* we did not allocate which means left
8206 already in a pointer register, then
8207 if size > 0 && this could be used again
8208 we have to point it back to where it
8210 if (AOP_SIZE (result) > 1 &&
8211 !OP_SYMBOL (left)->remat &&
8212 (OP_SYMBOL (left)->liveTo > ic->seq ||
8215 int size = AOP_SIZE (result) - 1;
8217 emitcode ("dec", "%s", rname);
8222 freeAsmop (result, NULL, ic, TRUE);
8227 /*-----------------------------------------------------------------*/
8228 /* genFarPointerGet - gget value from far space */
8229 /*-----------------------------------------------------------------*/
8231 genFarPointerGet (operand * left,
8232 operand * result, iCode * ic)
8235 sym_link *retype = getSpec (operandType (result));
8236 sym_link *letype = getSpec (operandType (left));
8237 D (emitcode (";", "genFarPointerGet");
8240 aopOp (left, ic, FALSE, FALSE);
8242 /* if the operand is already in dptr
8243 then we do nothing else we move the value to dptr */
8244 if (AOP_TYPE (left) != AOP_STR)
8246 /* if this is remateriazable */
8247 if (AOP_TYPE (left) == AOP_IMMD)
8249 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8253 /* we need to get it byte by byte */
8254 _startLazyDPSEvaluation ();
8255 if (AOP_TYPE (left) != AOP_DPTR)
8257 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8258 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8259 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8263 /* We need to generate a load to DPTR indirect through DPTR. */
8264 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8266 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8267 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8268 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8269 emitcode ("pop", "dph");
8270 emitcode ("pop", "dpl");
8272 _endLazyDPSEvaluation ();
8275 /* so dptr know contains the address */
8276 freeAsmop (left, NULL, ic, TRUE);
8277 aopOp (result, ic, FALSE, TRUE);
8279 /* if bit then unpack */
8280 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8281 genUnpackBits (result, "dptr", FPOINTER);
8284 size = AOP_SIZE (result);
8287 _startLazyDPSEvaluation ();
8294 emitcode ("movx", "a,@dptr");
8296 emitcode ("inc", "dptr");
8298 aopPut (AOP (result), "a", offset++);
8300 _endLazyDPSEvaluation ();
8303 freeAsmop (result, NULL, ic, TRUE);
8306 /*-----------------------------------------------------------------*/
8307 /* emitcodePointerGet - gget value from code space */
8308 /*-----------------------------------------------------------------*/
8310 emitcodePointerGet (operand * left,
8311 operand * result, iCode * ic)
8314 sym_link *retype = getSpec (operandType (result));
8316 aopOp (left, ic, FALSE, FALSE);
8318 /* if the operand is already in dptr
8319 then we do nothing else we move the value to dptr */
8320 if (AOP_TYPE (left) != AOP_STR)
8322 /* if this is remateriazable */
8323 if (AOP_TYPE (left) == AOP_IMMD)
8325 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8328 { /* we need to get it byte by byte */
8329 _startLazyDPSEvaluation ();
8330 if (AOP_TYPE (left) != AOP_DPTR)
8332 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8333 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8334 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8338 /* We need to generate a load to DPTR indirect through DPTR. */
8339 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8341 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8342 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8343 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8344 emitcode ("pop", "dph");
8345 emitcode ("pop", "dpl");
8347 _endLazyDPSEvaluation ();
8350 /* so dptr know contains the address */
8351 freeAsmop (left, NULL, ic, TRUE);
8352 aopOp (result, ic, FALSE, TRUE);
8354 /* if bit then unpack */
8355 if (IS_BITVAR (retype))
8356 genUnpackBits (result, "dptr", CPOINTER);
8359 size = AOP_SIZE (result);
8362 _startLazyDPSEvaluation ();
8368 emitcode ("clr", "a");
8369 emitcode ("movc", "a,@a+dptr");
8371 emitcode ("inc", "dptr");
8372 aopPut (AOP (result), "a", offset++);
8374 _endLazyDPSEvaluation ();
8377 freeAsmop (result, NULL, ic, TRUE);
8380 /*-----------------------------------------------------------------*/
8381 /* genGenPointerGet - gget value from generic pointer space */
8382 /*-----------------------------------------------------------------*/
8384 genGenPointerGet (operand * left,
8385 operand * result, iCode * ic)
8388 sym_link *retype = getSpec (operandType (result));
8389 sym_link *letype = getSpec (operandType (left));
8391 D (emitcode (";", "genGenPointerGet "); );
8393 aopOp (left, ic, FALSE, TRUE);
8395 /* if the operand is already in dptr
8396 then we do nothing else we move the value to dptr */
8397 if (AOP_TYPE (left) != AOP_STR)
8399 /* if this is remateriazable */
8400 if (AOP_TYPE (left) == AOP_IMMD)
8402 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8403 emitcode ("mov", "b,#%d", pointerCode (retype));
8406 { /* we need to get it byte by byte */
8407 _startLazyDPSEvaluation ();
8408 if (AOP(left)->type==AOP_DPTR2) {
8410 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8413 emitcode ("mov", "dpl,%s", l);
8414 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8417 emitcode ("mov", "dph,%s", l);
8418 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8421 emitcode ("mov", "dpx,%s", l);
8422 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8424 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8425 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8426 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8427 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8429 _endLazyDPSEvaluation ();
8432 /* so dptr know contains the address */
8433 freeAsmop (left, NULL, ic, TRUE);
8434 aopOp (result, ic, FALSE, TRUE);
8436 /* if bit then unpack */
8437 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8438 genUnpackBits (result, "dptr", GPOINTER);
8441 size = AOP_SIZE (result);
8446 emitcode ("lcall", "__gptrget");
8447 aopPut (AOP (result), "a", offset++);
8449 emitcode ("inc", "dptr");
8453 freeAsmop (result, NULL, ic, TRUE);
8456 /*-----------------------------------------------------------------*/
8457 /* genPointerGet - generate code for pointer get */
8458 /*-----------------------------------------------------------------*/
8460 genPointerGet (iCode * ic)
8462 operand *left, *result;
8463 sym_link *type, *etype;
8466 D (emitcode (";", "genPointerGet ");
8469 left = IC_LEFT (ic);
8470 result = IC_RESULT (ic);
8472 /* depending on the type of pointer we need to
8473 move it to the correct pointer register */
8474 type = operandType (left);
8475 etype = getSpec (type);
8476 /* if left is of type of pointer then it is simple */
8477 if (IS_PTR (type) && !IS_FUNC (type->next))
8478 p_type = DCL_TYPE (type);
8481 /* we have to go by the storage class */
8482 p_type = PTR_TYPE (SPEC_OCLS (etype));
8485 /* now that we have the pointer type we assign
8486 the pointer values */
8492 genNearPointerGet (left, result, ic);
8496 genPagedPointerGet (left, result, ic);
8500 genFarPointerGet (left, result, ic);
8504 emitcodePointerGet (left, result, ic);
8508 genGenPointerGet (left, result, ic);
8514 /*-----------------------------------------------------------------*/
8515 /* genPackBits - generates code for packed bit storage */
8516 /*-----------------------------------------------------------------*/
8518 genPackBits (sym_link * etype,
8520 char *rname, int p_type)
8528 blen = SPEC_BLEN (etype);
8529 bstr = SPEC_BSTR (etype);
8531 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8534 /* if the bit lenth is less than or */
8535 /* it exactly fits a byte then */
8536 if (SPEC_BLEN (etype) <= 8)
8538 shCount = SPEC_BSTR (etype);
8540 /* shift left acc */
8543 if (SPEC_BLEN (etype) < 8)
8544 { /* if smaller than a byte */
8550 emitcode ("mov", "b,a");
8551 emitcode ("mov", "a,@%s", rname);
8555 emitcode ("mov", "b,a");
8556 emitcode ("movx", "a,@dptr");
8560 emitcode ("push", "b");
8561 emitcode ("push", "acc");
8562 emitcode ("lcall", "__gptrget");
8563 emitcode ("pop", "b");
8567 emitcode ("anl", "a,#0x%02x", (unsigned char)
8568 ((unsigned char) (0xFF << (blen + bstr)) |
8569 (unsigned char) (0xFF >> (8 - bstr))));
8570 emitcode ("orl", "a,b");
8571 if (p_type == GPOINTER)
8572 emitcode ("pop", "b");
8579 emitcode ("mov", "@%s,a", rname);
8583 emitcode ("movx", "@dptr,a");
8587 emitcode ("lcall", "__gptrput");
8592 if (SPEC_BLEN (etype) <= 8)
8595 emitcode ("inc", "%s", rname);
8596 rLen = SPEC_BLEN (etype);
8598 /* now generate for lengths greater than one byte */
8602 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8614 emitcode ("mov", "@%s,a", rname);
8617 emitcode ("mov", "@%s,%s", rname, l);
8622 emitcode ("movx", "@dptr,a");
8627 emitcode ("lcall", "__gptrput");
8630 emitcode ("inc", "%s", rname);
8635 /* last last was not complete */
8638 /* save the byte & read byte */
8642 emitcode ("mov", "b,a");
8643 emitcode ("mov", "a,@%s", rname);
8647 emitcode ("mov", "b,a");
8648 emitcode ("movx", "a,@dptr");
8652 emitcode ("push", "b");
8653 emitcode ("push", "acc");
8654 emitcode ("lcall", "__gptrget");
8655 emitcode ("pop", "b");
8659 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8660 emitcode ("orl", "a,b");
8663 if (p_type == GPOINTER)
8664 emitcode ("pop", "b");
8670 emitcode ("mov", "@%s,a", rname);
8674 emitcode ("movx", "@dptr,a");
8678 emitcode ("lcall", "__gptrput");
8682 /*-----------------------------------------------------------------*/
8683 /* genDataPointerSet - remat pointer to data space */
8684 /*-----------------------------------------------------------------*/
8686 genDataPointerSet (operand * right,
8690 int size, offset = 0;
8691 char *l, buffer[256];
8693 aopOp (right, ic, FALSE, FALSE);
8695 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8696 size = AOP_SIZE (right);
8700 sprintf (buffer, "(%s + %d)", l + 1, offset);
8702 sprintf (buffer, "%s", l + 1);
8703 emitcode ("mov", "%s,%s", buffer,
8704 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8707 freeAsmop (right, NULL, ic, TRUE);
8708 freeAsmop (result, NULL, ic, TRUE);
8711 /*-----------------------------------------------------------------*/
8712 /* genNearPointerSet - emitcode for near pointer put */
8713 /*-----------------------------------------------------------------*/
8715 genNearPointerSet (operand * right,
8722 sym_link *retype, *letype;
8723 sym_link *ptype = operandType (result);
8725 retype = getSpec (operandType (right));
8726 letype = getSpec (ptype);
8728 aopOp (result, ic, FALSE, FALSE);
8730 /* if the result is rematerializable &
8731 in data space & not a bit variable */
8732 if (AOP_TYPE (result) == AOP_IMMD &&
8733 DCL_TYPE (ptype) == POINTER &&
8734 !IS_BITVAR (retype) &&
8735 !IS_BITVAR (letype))
8737 genDataPointerSet (right, result, ic);
8741 /* if the value is already in a pointer register
8742 then don't need anything more */
8743 if (!AOP_INPREG (AOP (result)))
8745 /* otherwise get a free pointer register */
8747 preg = getFreePtr (ic, &aop, FALSE);
8748 emitcode ("mov", "%s,%s",
8750 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8754 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8756 freeAsmop (result, NULL, ic, TRUE);
8757 aopOp (right, ic, FALSE, FALSE);
8759 /* if bitfield then unpack the bits */
8760 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8761 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8764 /* we have can just get the values */
8765 int size = AOP_SIZE (right);
8770 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8774 emitcode ("mov", "@%s,a", rname);
8777 emitcode ("mov", "@%s,%s", rname, l);
8779 emitcode ("inc", "%s", rname);
8784 /* now some housekeeping stuff */
8787 /* we had to allocate for this iCode */
8788 freeAsmop (NULL, aop, ic, TRUE);
8792 /* we did not allocate which means left
8793 already in a pointer register, then
8794 if size > 0 && this could be used again
8795 we have to point it back to where it
8797 if (AOP_SIZE (right) > 1 &&
8798 !OP_SYMBOL (result)->remat &&
8799 (OP_SYMBOL (result)->liveTo > ic->seq ||
8802 int size = AOP_SIZE (right) - 1;
8804 emitcode ("dec", "%s", rname);
8809 freeAsmop (right, NULL, ic, TRUE);
8814 /*-----------------------------------------------------------------*/
8815 /* genPagedPointerSet - emitcode for Paged pointer put */
8816 /*-----------------------------------------------------------------*/
8818 genPagedPointerSet (operand * right,
8825 sym_link *retype, *letype;
8827 retype = getSpec (operandType (right));
8828 letype = getSpec (operandType (result));
8830 aopOp (result, ic, FALSE, FALSE);
8832 /* if the value is already in a pointer register
8833 then don't need anything more */
8834 if (!AOP_INPREG (AOP (result)))
8836 /* otherwise get a free pointer register */
8838 preg = getFreePtr (ic, &aop, FALSE);
8839 emitcode ("mov", "%s,%s",
8841 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8845 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8847 freeAsmop (result, NULL, ic, TRUE);
8848 aopOp (right, ic, FALSE, FALSE);
8850 /* if bitfield then unpack the bits */
8851 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8852 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8855 /* we have can just get the values */
8856 int size = AOP_SIZE (right);
8861 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8864 emitcode ("movx", "@%s,a", rname);
8867 emitcode ("inc", "%s", rname);
8873 /* now some housekeeping stuff */
8876 /* we had to allocate for this iCode */
8877 freeAsmop (NULL, aop, ic, TRUE);
8881 /* we did not allocate which means left
8882 already in a pointer register, then
8883 if size > 0 && this could be used again
8884 we have to point it back to where it
8886 if (AOP_SIZE (right) > 1 &&
8887 !OP_SYMBOL (result)->remat &&
8888 (OP_SYMBOL (result)->liveTo > ic->seq ||
8891 int size = AOP_SIZE (right) - 1;
8893 emitcode ("dec", "%s", rname);
8898 freeAsmop (right, NULL, ic, TRUE);
8903 /*-----------------------------------------------------------------*/
8904 /* genFarPointerSet - set value from far space */
8905 /*-----------------------------------------------------------------*/
8907 genFarPointerSet (operand * right,
8908 operand * result, iCode * ic)
8911 sym_link *retype = getSpec (operandType (right));
8912 sym_link *letype = getSpec (operandType (result));
8914 aopOp (result, ic, FALSE, FALSE);
8916 /* if the operand is already in dptr
8917 then we do nothing else we move the value to dptr */
8918 if (AOP_TYPE (result) != AOP_STR)
8920 /* if this is remateriazable */
8921 if (AOP_TYPE (result) == AOP_IMMD)
8922 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8925 /* we need to get it byte by byte */
8926 _startLazyDPSEvaluation ();
8927 if (AOP_TYPE (result) != AOP_DPTR)
8929 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8930 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8931 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8935 /* We need to generate a load to DPTR indirect through DPTR. */
8936 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8938 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8939 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8940 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8941 emitcode ("pop", "dph");
8942 emitcode ("pop", "dpl");
8944 _endLazyDPSEvaluation ();
8947 /* so dptr know contains the address */
8948 freeAsmop (result, NULL, ic, TRUE);
8949 aopOp (right, ic, FALSE, TRUE);
8951 /* if bit then unpack */
8952 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8953 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8956 size = AOP_SIZE (right);
8959 _startLazyDPSEvaluation ();
8962 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8968 emitcode ("movx", "@dptr,a");
8970 emitcode ("inc", "dptr");
8972 _endLazyDPSEvaluation ();
8975 freeAsmop (right, NULL, ic, TRUE);
8978 /*-----------------------------------------------------------------*/
8979 /* genGenPointerSet - set value from generic pointer space */
8980 /*-----------------------------------------------------------------*/
8982 genGenPointerSet (operand * right,
8983 operand * result, iCode * ic)
8986 sym_link *retype = getSpec (operandType (right));
8987 sym_link *letype = getSpec (operandType (result));
8989 aopOp (result, ic, FALSE, TRUE);
8991 /* if the operand is already in dptr
8992 then we do nothing else we move the value to dptr */
8993 if (AOP_TYPE (result) != AOP_STR)
8995 _startLazyDPSEvaluation ();
8996 /* if this is remateriazable */
8997 if (AOP_TYPE (result) == AOP_IMMD)
8999 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9000 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9003 { /* we need to get it byte by byte */
9004 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9005 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9006 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9007 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9009 _endLazyDPSEvaluation ();
9011 /* so dptr know contains the address */
9012 freeAsmop (result, NULL, ic, TRUE);
9013 aopOp (right, ic, FALSE, TRUE);
9015 /* if bit then unpack */
9016 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9017 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9020 size = AOP_SIZE (right);
9023 _startLazyDPSEvaluation ();
9026 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9032 emitcode ("lcall", "__gptrput");
9034 emitcode ("inc", "dptr");
9036 _endLazyDPSEvaluation ();
9039 freeAsmop (right, NULL, ic, TRUE);
9042 /*-----------------------------------------------------------------*/
9043 /* genPointerSet - stores the value into a pointer location */
9044 /*-----------------------------------------------------------------*/
9046 genPointerSet (iCode * ic)
9048 operand *right, *result;
9049 sym_link *type, *etype;
9052 D (emitcode (";", "genPointerSet ");
9055 right = IC_RIGHT (ic);
9056 result = IC_RESULT (ic);
9058 /* depending on the type of pointer we need to
9059 move it to the correct pointer register */
9060 type = operandType (result);
9061 etype = getSpec (type);
9062 /* if left is of type of pointer then it is simple */
9063 if (IS_PTR (type) && !IS_FUNC (type->next))
9065 p_type = DCL_TYPE (type);
9069 /* we have to go by the storage class */
9070 p_type = PTR_TYPE (SPEC_OCLS (etype));
9073 /* now that we have the pointer type we assign
9074 the pointer values */
9080 genNearPointerSet (right, result, ic);
9084 genPagedPointerSet (right, result, ic);
9088 genFarPointerSet (right, result, ic);
9092 genGenPointerSet (right, result, ic);
9098 /*-----------------------------------------------------------------*/
9099 /* genIfx - generate code for Ifx statement */
9100 /*-----------------------------------------------------------------*/
9102 genIfx (iCode * ic, iCode * popIc)
9104 operand *cond = IC_COND (ic);
9107 D (emitcode (";", "genIfx "););
9109 aopOp (cond, ic, FALSE, FALSE);
9111 /* get the value into acc */
9112 if (AOP_TYPE (cond) != AOP_CRY)
9116 /* the result is now in the accumulator */
9117 freeAsmop (cond, NULL, ic, TRUE);
9119 /* if there was something to be popped then do it */
9123 /* if the condition is a bit variable */
9124 if (isbit && IS_ITEMP (cond) &&
9126 genIfxJump (ic, SPIL_LOC (cond)->rname);
9127 else if (isbit && !IS_ITEMP (cond))
9128 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9130 genIfxJump (ic, "a");
9135 /*-----------------------------------------------------------------*/
9136 /* genAddrOf - generates code for address of */
9137 /*-----------------------------------------------------------------*/
9139 genAddrOf (iCode * ic)
9141 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9144 D (emitcode (";", "genAddrOf ");
9147 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9149 /* if the operand is on the stack then we
9150 need to get the stack offset of this
9154 /* if it has an offset then we need to compute
9158 emitcode ("mov", "a,_bp");
9159 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9160 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9164 /* we can just move _bp */
9165 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9167 /* fill the result with zero */
9168 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9171 if (options.stack10bit && size < (FPTRSIZE - 1))
9174 "*** warning: pointer to stack var truncated.\n");
9181 if (options.stack10bit && offset == 2)
9183 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9187 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9194 /* object not on stack then we need the name */
9195 size = AOP_SIZE (IC_RESULT (ic));
9200 char s[SDCC_NAME_MAX];
9202 sprintf (s, "#(%s >> %d)",
9206 sprintf (s, "#%s", sym->rname);
9207 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9211 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9215 /*-----------------------------------------------------------------*/
9216 /* genFarFarAssign - assignment when both are in far space */
9217 /*-----------------------------------------------------------------*/
9219 genFarFarAssign (operand * result, operand * right, iCode * ic)
9221 int size = AOP_SIZE (right);
9223 symbol *rSym = NULL;
9227 /* quick & easy case. */
9228 D(emitcode(";","genFarFarAssign (1 byte case)"););
9229 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9230 freeAsmop (right, NULL, ic, FALSE);
9231 /* now assign DPTR to result */
9233 aopOp(result, ic, FALSE, FALSE);
9235 aopPut(AOP(result), "a", 0);
9236 freeAsmop(result, NULL, ic, FALSE);
9240 /* See if we've got an underlying symbol to abuse. */
9241 if (IS_SYMOP(result) && OP_SYMBOL(result))
9243 if (IS_TRUE_SYMOP(result))
9245 rSym = OP_SYMBOL(result);
9247 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9249 rSym = OP_SYMBOL(result)->usl.spillLoc;
9253 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9255 /* We can use the '390 auto-toggle feature to good effect here. */
9257 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9258 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9259 emitcode ("mov", "dptr,#%s", rSym->rname);
9260 /* DP2 = result, DP1 = right, DP1 is current. */
9263 emitcode("movx", "a,@dptr");
9264 emitcode("movx", "@dptr,a");
9267 emitcode("inc", "dptr");
9268 emitcode("inc", "dptr");
9271 emitcode("mov", "dps, #0");
9272 freeAsmop (right, NULL, ic, FALSE);
9276 D (emitcode (";", "genFarFarAssign"););
9277 aopOp (result, ic, TRUE, TRUE);
9279 _startLazyDPSEvaluation ();
9283 aopPut (AOP (result),
9284 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9287 _endLazyDPSEvaluation ();
9288 freeAsmop (result, NULL, ic, FALSE);
9289 freeAsmop (right, NULL, ic, FALSE);
9293 /*-----------------------------------------------------------------*/
9294 /* genAssign - generate code for assignment */
9295 /*-----------------------------------------------------------------*/
9297 genAssign (iCode * ic)
9299 operand *result, *right;
9301 unsigned long lit = 0L;
9303 D (emitcode (";", "genAssign ");
9306 result = IC_RESULT (ic);
9307 right = IC_RIGHT (ic);
9309 /* if they are the same */
9310 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9313 aopOp (right, ic, FALSE, FALSE);
9315 emitcode (";", "genAssign: resultIsFar = %s",
9316 isOperandInFarSpace (result) ?
9319 /* special case both in far space */
9320 if ((AOP_TYPE (right) == AOP_DPTR ||
9321 AOP_TYPE (right) == AOP_DPTR2) &&
9322 /* IS_TRUE_SYMOP(result) && */
9323 isOperandInFarSpace (result))
9325 genFarFarAssign (result, right, ic);
9329 aopOp (result, ic, TRUE, FALSE);
9331 /* if they are the same registers */
9332 if (sameRegs (AOP (right), AOP (result)))
9335 /* if the result is a bit */
9336 if (AOP_TYPE (result) == AOP_CRY)
9339 /* if the right size is a literal then
9340 we know what the value is */
9341 if (AOP_TYPE (right) == AOP_LIT)
9343 if (((int) operandLitValue (right)))
9344 aopPut (AOP (result), one, 0);
9346 aopPut (AOP (result), zero, 0);
9350 /* the right is also a bit variable */
9351 if (AOP_TYPE (right) == AOP_CRY)
9353 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9354 aopPut (AOP (result), "c", 0);
9360 aopPut (AOP (result), "a", 0);
9364 /* bit variables done */
9366 size = AOP_SIZE (result);
9368 if (AOP_TYPE (right) == AOP_LIT)
9369 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9372 (AOP_TYPE (result) != AOP_REG) &&
9373 (AOP_TYPE (right) == AOP_LIT) &&
9374 !IS_FLOAT (operandType (right)))
9376 _startLazyDPSEvaluation ();
9377 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9379 aopPut (AOP (result),
9380 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9385 /* And now fill the rest with zeros. */
9388 emitcode ("clr", "a");
9392 aopPut (AOP (result), "a", offset++);
9394 _endLazyDPSEvaluation ();
9398 _startLazyDPSEvaluation ();
9401 aopPut (AOP (result),
9402 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9406 _endLazyDPSEvaluation ();
9410 freeAsmop (right, NULL, ic, FALSE);
9411 freeAsmop (result, NULL, ic, TRUE);
9414 /*-----------------------------------------------------------------*/
9415 /* genJumpTab - generates code for jump table */
9416 /*-----------------------------------------------------------------*/
9418 genJumpTab (iCode * ic)
9423 D (emitcode (";", "genJumpTab ");
9426 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9427 /* get the condition into accumulator */
9428 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9430 /* multiply by four! */
9431 emitcode ("add", "a,acc");
9432 emitcode ("add", "a,acc");
9433 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9435 jtab = newiTempLabel (NULL);
9436 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9437 emitcode ("jmp", "@a+dptr");
9438 emitcode ("", "%05d$:", jtab->key + 100);
9439 /* now generate the jump labels */
9440 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9441 jtab = setNextItem (IC_JTLABELS (ic)))
9442 emitcode ("ljmp", "%05d$", jtab->key + 100);
9446 /*-----------------------------------------------------------------*/
9447 /* genCast - gen code for casting */
9448 /*-----------------------------------------------------------------*/
9450 genCast (iCode * ic)
9452 operand *result = IC_RESULT (ic);
9453 sym_link *ctype = operandType (IC_LEFT (ic));
9454 sym_link *rtype = operandType (IC_RIGHT (ic));
9455 operand *right = IC_RIGHT (ic);
9458 D (emitcode (";", "genCast ");
9461 /* if they are equivalent then do nothing */
9462 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9465 aopOp (right, ic, FALSE, FALSE);
9466 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9468 /* if the result is a bit */
9469 if (AOP_TYPE (result) == AOP_CRY)
9471 /* if the right size is a literal then
9472 we know what the value is */
9473 if (AOP_TYPE (right) == AOP_LIT)
9475 if (((int) operandLitValue (right)))
9476 aopPut (AOP (result), one, 0);
9478 aopPut (AOP (result), zero, 0);
9483 /* the right is also a bit variable */
9484 if (AOP_TYPE (right) == AOP_CRY)
9486 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9487 aopPut (AOP (result), "c", 0);
9493 aopPut (AOP (result), "a", 0);
9497 /* if they are the same size : or less */
9498 if (AOP_SIZE (result) <= AOP_SIZE (right))
9501 /* if they are in the same place */
9502 if (sameRegs (AOP (right), AOP (result)))
9505 /* if they in different places then copy */
9506 size = AOP_SIZE (result);
9508 _startLazyDPSEvaluation ();
9511 aopPut (AOP (result),
9512 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9516 _endLazyDPSEvaluation ();
9521 /* if the result is of type pointer */
9526 sym_link *type = operandType (right);
9528 /* pointer to generic pointer */
9529 if (IS_GENPTR (ctype))
9535 p_type = DCL_TYPE (type);
9539 #if OLD_CAST_BEHAVIOR
9540 /* KV: we are converting a non-pointer type to
9541 * a generic pointer. This (ifdef'd out) code
9542 * says that the resulting generic pointer
9543 * should have the same class as the storage
9544 * location of the non-pointer variable.
9546 * For example, converting an int (which happens
9547 * to be stored in DATA space) to a pointer results
9548 * in a DATA generic pointer; if the original int
9549 * in XDATA space, so will be the resulting pointer.
9551 * I don't like that behavior, and thus this change:
9552 * all such conversions will be forced to XDATA and
9553 * throw a warning. If you want some non-XDATA
9554 * type, or you want to suppress the warning, you
9555 * must go through an intermediate cast, like so:
9557 * char _generic *gp = (char _xdata *)(intVar);
9559 sym_link *etype = getSpec (type);
9561 /* we have to go by the storage class */
9562 if (SPEC_OCLS (etype) != generic)
9564 p_type = PTR_TYPE (SPEC_OCLS (etype));
9569 /* Converting unknown class (i.e. register variable)
9570 * to generic pointer. This is not good, but
9571 * we'll make a guess (and throw a warning).
9574 werror (W_INT_TO_GEN_PTR_CAST);
9578 /* the first two bytes are known */
9579 size = GPTRSIZE - 1;
9581 _startLazyDPSEvaluation ();
9584 aopPut (AOP (result),
9585 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9589 _endLazyDPSEvaluation ();
9591 /* the last byte depending on type */
9609 /* this should never happen */
9610 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9611 "got unknown pointer type");
9614 aopPut (AOP (result), l, GPTRSIZE - 1);
9618 /* just copy the pointers */
9619 size = AOP_SIZE (result);
9621 _startLazyDPSEvaluation ();
9624 aopPut (AOP (result),
9625 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9629 _endLazyDPSEvaluation ();
9633 /* so we now know that the size of destination is greater
9634 than the size of the source */
9635 /* we move to result for the size of source */
9636 size = AOP_SIZE (right);
9638 _startLazyDPSEvaluation ();
9641 aopPut (AOP (result),
9642 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9646 _endLazyDPSEvaluation ();
9648 /* now depending on the sign of the source && destination */
9649 size = AOP_SIZE (result) - AOP_SIZE (right);
9650 /* if unsigned or not an integral type */
9651 /* also, if the source is a bit, we don't need to sign extend, because
9652 * it can't possibly have set the sign bit.
9654 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9658 aopPut (AOP (result), zero, offset++);
9663 /* we need to extend the sign :{ */
9664 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9665 FALSE, FALSE, TRUE);
9667 emitcode ("rlc", "a");
9668 emitcode ("subb", "a,acc");
9670 aopPut (AOP (result), "a", offset++);
9673 /* we are done hurray !!!! */
9676 freeAsmop (right, NULL, ic, TRUE);
9677 freeAsmop (result, NULL, ic, TRUE);
9681 /*-----------------------------------------------------------------*/
9682 /* genDjnz - generate decrement & jump if not zero instrucion */
9683 /*-----------------------------------------------------------------*/
9685 genDjnz (iCode * ic, iCode * ifx)
9691 /* if the if condition has a false label
9692 then we cannot save */
9696 /* if the minus is not of the form
9698 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9699 !IS_OP_LITERAL (IC_RIGHT (ic)))
9702 if (operandLitValue (IC_RIGHT (ic)) != 1)
9705 /* if the size of this greater than one then no
9707 if (getSize (operandType (IC_RESULT (ic))) > 1)
9710 /* otherwise we can save BIG */
9711 D(emitcode(";", "genDjnz"););
9713 lbl = newiTempLabel (NULL);
9714 lbl1 = newiTempLabel (NULL);
9716 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9718 if (AOP_NEEDSACC(IC_RESULT(ic)))
9720 /* If the result is accessed indirectly via
9721 * the accumulator, we must explicitly write
9722 * it back after the decrement.
9724 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9726 if (strcmp(rByte, "a"))
9728 /* Something is hopelessly wrong */
9729 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9730 __FILE__, __LINE__);
9731 /* We can just give up; the generated code will be inefficient,
9734 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9737 emitcode ("dec", "%s", rByte);
9738 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9739 emitcode ("jnz", "%05d$", lbl->key + 100);
9741 else if (IS_AOP_PREG (IC_RESULT (ic)))
9743 emitcode ("dec", "%s",
9744 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9745 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9746 emitcode ("jnz", "%05d$", lbl->key + 100);
9750 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9753 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9754 emitcode ("", "%05d$:", lbl->key + 100);
9755 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9756 emitcode ("", "%05d$:", lbl1->key + 100);
9758 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9763 /*-----------------------------------------------------------------*/
9764 /* genReceive - generate code for a receive iCode */
9765 /*-----------------------------------------------------------------*/
9767 genReceive (iCode * ic)
9770 D (emitcode (";", "genReceive ");
9773 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9774 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9775 IS_TRUE_SYMOP (IC_RESULT (ic))))
9777 int size = getSize (operandType (IC_RESULT (ic)));
9778 int offset = fReturnSizeDS390 - size;
9781 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9782 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9785 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9786 size = AOP_SIZE (IC_RESULT (ic));
9790 emitcode ("pop", "acc");
9791 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9798 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9800 assignResultValue (IC_RESULT (ic));
9803 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9806 /*-----------------------------------------------------------------*/
9807 /* gen390Code - generate code for Dallas 390 based controllers */
9808 /*-----------------------------------------------------------------*/
9810 gen390Code (iCode * lic)
9815 lineHead = lineCurr = NULL;
9819 /* print the allocation information */
9821 printAllocInfo (currFunc, codeOutFile);
9823 /* if debug information required */
9824 if (options.debug && currFunc)
9826 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9828 if (IS_STATIC (currFunc->etype))
9829 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9831 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9834 /* stack pointer name */
9835 if (options.useXstack)
9841 for (ic = lic; ic; ic = ic->next)
9844 if (cln != ic->lineno)
9849 emitcode ("", "C$%s$%d$%d$%d ==.",
9850 FileBaseName (ic->filename), ic->lineno,
9851 ic->level, ic->block);
9854 emitcode (";", "%s %d", ic->filename, ic->lineno);
9857 /* if the result is marked as
9858 spilt and rematerializable or code for
9859 this has already been generated then
9861 if (resultRemat (ic) || ic->generated)
9864 /* depending on the operation */
9884 /* IPOP happens only when trying to restore a
9885 spilt live range, if there is an ifx statement
9886 following this pop then the if statement might
9887 be using some of the registers being popped which
9888 would destory the contents of the register so
9889 we need to check for this condition and handle it */
9891 ic->next->op == IFX &&
9892 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9893 genIfx (ic->next, ic);
9911 genEndFunction (ic);
9931 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9948 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9952 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9959 /* note these two are xlated by algebraic equivalence
9960 during parsing SDCC.y */
9961 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9962 "got '>=' or '<=' shouldn't have come here");
9966 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9978 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9982 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9986 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10010 genRightShift (ic);
10013 case GET_VALUE_AT_ADDRESS:
10014 genPointerGet (ic);
10018 if (POINTER_SET (ic))
10019 genPointerSet (ic);
10045 addSet (&_G.sendSet, ic);
10054 /* now we are ready to call the
10055 peep hole optimizer */
10056 if (!options.nopeep)
10057 peepHole (&lineHead);
10059 /* now do the actual printing */
10060 printLine (lineHead, codeOutFile);