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__) && !defined(__CYGWIN__)
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 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
172 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
177 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
178 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
180 /* if no usage of r0 then return it */
183 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
184 (*aopp)->type = AOP_R0;
186 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
189 /* if no usage of r1 then return it */
192 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
193 (*aopp)->type = AOP_R1;
195 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
198 /* now we know they both have usage */
199 /* if r0 not used in this instruction */
202 /* push it if not already pushed */
205 emitcode ("push", "%s",
206 ds390_regWithIdx (R0_IDX)->dname);
210 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
211 (*aopp)->type = AOP_R0;
213 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
216 /* if r1 not used then */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 ds390_regWithIdx (R1_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
229 (*aopp)->type = AOP_R1;
230 return ds390_regWithIdx (R1_IDX);
234 /* I said end of world but not quite end of world yet */
235 /* if this is a result then we can push it on the stack */
238 (*aopp)->type = AOP_STK;
242 /* other wise this is true end of the world */
243 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
244 "getFreePtr should never reach here");
248 /*-----------------------------------------------------------------*/
249 /* newAsmop - creates a new asmOp */
250 /*-----------------------------------------------------------------*/
252 newAsmop (short type)
256 aop = Safe_calloc (1, sizeof (asmop));
261 static int _currentDPS; /* Current processor DPS. */
262 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
263 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
265 /*-----------------------------------------------------------------*/
266 /* genSetDPTR: generate code to select which DPTR is in use (zero */
267 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
268 /* alternate DPTR (DPL1/DPH1/DPX1). */
269 /*-----------------------------------------------------------------*/
274 /* If we are doing lazy evaluation, simply note the desired
275 * change, but don't emit any code yet.
285 emitcode ("mov", "dps, #0x00");
289 emitcode ("mov", "dps, #0x01");
293 /*-----------------------------------------------------------------*/
294 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
296 /* Any code that operates on DPTR (NB: not on the individual */
297 /* components, like DPH) *must* call _flushLazyDPS() before using */
298 /* DPTR within a lazy DPS evaluation block. */
300 /* Note that aopPut and aopGet already contain the proper calls to */
301 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
302 /* DPS evaluation block. */
304 /* Also, _flushLazyDPS must be called before any flow control */
305 /* operations that could potentially branch out of the block. */
307 /* Lazy DPS evaluation is simply an optimization (though an */
308 /* important one), so if in doubt, leave it out. */
309 /*-----------------------------------------------------------------*/
311 _startLazyDPSEvaluation (void)
315 #ifdef BETTER_LITERAL_SHIFT
322 /*-----------------------------------------------------------------*/
323 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
324 /* desired one. Call before using DPTR within a lazy DPS evaluation */
326 /*-----------------------------------------------------------------*/
336 if (_desiredDPS != _currentDPS)
340 emitcode ("inc", "dps");
344 emitcode ("dec", "dps");
346 _currentDPS = _desiredDPS;
350 /*-----------------------------------------------------------------*/
351 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
353 /* Forces us back to the safe state (standard DPTR selected). */
354 /*-----------------------------------------------------------------*/
356 _endLazyDPSEvaluation (void)
358 #ifdef BETTER_LITERAL_SHIFT
377 /*-----------------------------------------------------------------*/
378 /* pointerCode - returns the code for a pointer type */
379 /*-----------------------------------------------------------------*/
381 pointerCode (sym_link * etype)
384 return PTR_TYPE (SPEC_OCLS (etype));
388 /*-----------------------------------------------------------------*/
389 /* aopForSym - for a true symbol */
390 /*-----------------------------------------------------------------*/
392 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
395 memmap *space = SPEC_OCLS (sym->etype);
397 /* if already has one */
401 /* assign depending on the storage class */
402 /* if it is on the stack or indirectly addressable */
403 /* space we need to assign either r0 or r1 to it */
404 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
406 sym->aop = aop = newAsmop (0);
407 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
408 aop->size = getSize (sym->type);
410 /* now assign the address of the variable to
411 the pointer register */
412 if (aop->type != AOP_STK)
418 emitcode ("push", "acc");
420 emitcode ("mov", "a,_bp");
421 emitcode ("add", "a,#0x%02x",
423 ((char) (sym->stack - _G.nRegsSaved)) :
424 ((char) sym->stack)) & 0xff);
425 emitcode ("mov", "%s,a",
426 aop->aopu.aop_ptr->name);
429 emitcode ("pop", "acc");
432 emitcode ("mov", "%s,#%s",
433 aop->aopu.aop_ptr->name,
435 aop->paged = space->paged;
438 aop->aopu.aop_stk = sym->stack;
442 if (sym->onStack && options.stack10bit)
444 /* It's on the 10 bit stack, which is located in
449 emitcode ("push", "acc");
451 emitcode ("mov", "a,_bp");
452 emitcode ("add", "a,#0x%02x",
454 ((char) (sym->stack - _G.nRegsSaved)) :
455 ((char) sym->stack)) & 0xff);
459 emitcode ("mov", "dpx1,#0x40");
460 emitcode ("mov", "dph1,#0x00");
461 emitcode ("mov", "dpl1, a");
465 emitcode ("mov", "dpx,#0x40");
466 emitcode ("mov", "dph,#0x00");
467 emitcode ("mov", "dpl, a");
471 emitcode ("pop", "acc");
473 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
474 aop->size = getSize (sym->type);
478 /* if in bit space */
479 if (IN_BITSPACE (space))
481 sym->aop = aop = newAsmop (AOP_CRY);
482 aop->aopu.aop_dir = sym->rname;
483 aop->size = getSize (sym->type);
486 /* if it is in direct space */
487 if (IN_DIRSPACE (space))
489 sym->aop = aop = newAsmop (AOP_DIR);
490 aop->aopu.aop_dir = sym->rname;
491 aop->size = getSize (sym->type);
495 /* special case for a function */
496 if (IS_FUNC (sym->type))
498 sym->aop = aop = newAsmop (AOP_IMMD);
499 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
500 strcpy (aop->aopu.aop_immd, sym->rname);
501 aop->size = FPTRSIZE;
505 /* only remaining is far space */
506 /* in which case DPTR gets the address */
507 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
512 emitcode ("mov", "dptr,#%s", sym->rname);
517 emitcode ("mov", "dptr,#%s", sym->rname);
519 aop->size = getSize (sym->type);
521 /* if it is in code space */
522 if (IN_CODESPACE (space))
528 /*-----------------------------------------------------------------*/
529 /* aopForRemat - rematerialzes an object */
530 /*-----------------------------------------------------------------*/
532 aopForRemat (symbol * sym)
534 iCode *ic = sym->rematiCode;
535 asmop *aop = newAsmop (AOP_IMMD);
542 val += (int) operandLitValue (IC_RIGHT (ic));
543 else if (ic->op == '-')
544 val -= (int) operandLitValue (IC_RIGHT (ic));
548 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
552 sprintf (buffer, "(%s %c 0x%04x)",
553 OP_SYMBOL (IC_LEFT (ic))->rname,
554 val >= 0 ? '+' : '-',
557 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
559 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
560 strcpy (aop->aopu.aop_immd, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
658 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
665 if (aop1->type != AOP_REG ||
666 aop2->type != AOP_REG)
669 if (aop1->size != aop2->size)
672 for (i = 0; i < aop1->size; i++)
673 if (aop1->aopu.aop_reg[i] !=
674 aop2->aopu.aop_reg[i])
680 /*-----------------------------------------------------------------*/
681 /* aopOp - allocates an asmop for an operand : */
682 /*-----------------------------------------------------------------*/
684 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
693 /* if this a literal */
694 if (IS_OP_LITERAL (op))
696 op->aop = aop = newAsmop (AOP_LIT);
697 aop->aopu.aop_lit = op->operand.valOperand;
698 aop->size = getSize (operandType (op));
702 /* if already has a asmop then continue */
706 /* if the underlying symbol has a aop */
707 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
709 op->aop = OP_SYMBOL (op)->aop;
713 /* if this is a true symbol */
714 if (IS_TRUE_SYMOP (op))
716 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
720 /* this is a temporary : this has
726 e) can be a return use only */
728 sym = OP_SYMBOL (op);
731 /* if the type is a conditional */
732 if (sym->regType == REG_CND)
734 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
739 /* if it is spilt then two situations
741 b) has a spill location */
742 if (sym->isspilt || sym->nRegs == 0)
745 /* rematerialize it NOW */
748 sym->aop = op->aop = aop =
750 aop->size = getSize (sym->type);
757 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
758 aop->size = getSize (sym->type);
759 for (i = 0; i < 2; i++)
760 aop->aopu.aop_str[i] = accUse[i];
770 /* a AOP_STR uses DPTR, but DPTR is already in use;
773 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
776 aop = op->aop = sym->aop = newAsmop (AOP_STR);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < (int) fReturnSizeDS390; i++)
779 aop->aopu.aop_str[i] = fReturn[i];
783 /* else spill location */
784 sym->aop = op->aop = aop =
785 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
786 aop->size = getSize (sym->type);
790 /* must be in a register */
791 sym->aop = op->aop = aop = newAsmop (AOP_REG);
792 aop->size = sym->nRegs;
793 for (i = 0; i < sym->nRegs; i++)
794 aop->aopu.aop_reg[i] = sym->regs[i];
797 /*-----------------------------------------------------------------*/
798 /* freeAsmop - free up the asmop given to an operand */
799 /*----------------------------------------------------------------*/
801 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
818 /* depending on the asmop type only three cases need work AOP_RO
819 , AOP_R1 && AOP_STK */
827 emitcode ("pop", "ar0");
831 bitVectUnSetBit (ic->rUsed, R0_IDX);
839 emitcode ("pop", "ar1");
843 bitVectUnSetBit (ic->rUsed, R1_IDX);
849 int stk = aop->aopu.aop_stk + aop->size;
850 bitVectUnSetBit (ic->rUsed, R0_IDX);
851 bitVectUnSetBit (ic->rUsed, R1_IDX);
853 getFreePtr (ic, &aop, FALSE);
855 if (options.stack10bit)
857 /* I'm not sure what to do here yet... */
860 "*** Warning: probably generating bad code for "
861 "10 bit stack mode.\n");
866 emitcode ("mov", "a,_bp");
867 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
868 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
872 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
877 emitcode ("pop", "acc");
878 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
881 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
884 freeAsmop (op, NULL, ic, TRUE);
887 emitcode ("pop", "ar0");
893 emitcode ("pop", "ar1");
900 /* all other cases just dealloc */
906 OP_SYMBOL (op)->aop = NULL;
907 /* if the symbol has a spill */
909 SPIL_LOC (op)->aop = NULL;
914 /*------------------------------------------------------------------*/
915 /* aopGet - for fetching value of the aop */
917 /* Set canClobberACC if you are sure it is OK to clobber the value */
918 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
919 /* just less efficient. */
920 /*------------------------------------------------------------------*/
932 /* offset is greater than
934 if (offset > (aop->size - 1) &&
935 aop->type != AOP_LIT)
938 /* depending on type */
944 /* if we need to increment it */
945 while (offset > aop->coff)
947 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
951 while (offset < aop->coff)
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
960 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
961 return (dname ? "acc" : "a");
963 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
964 rs = Safe_calloc (1, strlen (s) + 1);
971 if (aop->type == AOP_DPTR2)
976 emitcode ("xch", "a, %s", DP2_RESULT_REG);
982 while (offset > aop->coff)
984 emitcode ("inc", "dptr");
988 while (offset < aop->coff)
990 emitcode ("lcall", "__decdptr");
997 emitcode ("clr", "a");
998 emitcode ("movc", "a,@a+dptr");
1002 emitcode ("movx", "a,@dptr");
1005 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011 return DP2_RESULT_REG;
1014 return (dname ? "acc" : "a");
1018 sprintf (s, "#%s", aop->aopu.aop_immd);
1020 sprintf (s, "#(%s >> %d)",
1025 aop->aopu.aop_immd);
1026 rs = Safe_calloc (1, strlen (s) + 1);
1032 sprintf (s, "(%s + %d)",
1036 sprintf (s, "%s", aop->aopu.aop_dir);
1037 rs = Safe_calloc (1, strlen (s) + 1);
1043 return aop->aopu.aop_reg[offset]->dname;
1045 return aop->aopu.aop_reg[offset]->name;
1048 emitcode ("clr", "a");
1049 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1050 emitcode ("rlc", "a");
1051 return (dname ? "acc" : "a");
1054 if (!offset && dname)
1056 return aop->aopu.aop_str[offset];
1059 return aopLiteral (aop->aopu.aop_lit, offset);
1063 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1067 return aop->aopu.aop_str[offset];
1071 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1072 "aopget got unsupported aop->type");
1075 /*-----------------------------------------------------------------*/
1076 /* aopPut - puts a string for a aop */
1077 /*-----------------------------------------------------------------*/
1079 aopPut (asmop * aop, char *s, int offset)
1083 if (aop->size && offset > (aop->size - 1))
1085 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1086 "aopPut got offset > aop->size");
1090 /* will assign value to value */
1091 /* depending on where it is ofcourse */
1096 sprintf (d, "(%s + %d)",
1097 aop->aopu.aop_dir, offset);
1099 sprintf (d, "%s", aop->aopu.aop_dir);
1102 emitcode ("mov", "%s,%s", d, s);
1107 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1108 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1111 strcmp (s, "r0") == 0 ||
1112 strcmp (s, "r1") == 0 ||
1113 strcmp (s, "r2") == 0 ||
1114 strcmp (s, "r3") == 0 ||
1115 strcmp (s, "r4") == 0 ||
1116 strcmp (s, "r5") == 0 ||
1117 strcmp (s, "r6") == 0 ||
1118 strcmp (s, "r7") == 0)
1119 emitcode ("mov", "%s,%s",
1120 aop->aopu.aop_reg[offset]->dname, s);
1122 emitcode ("mov", "%s,%s",
1123 aop->aopu.aop_reg[offset]->name, s);
1130 if (aop->type == AOP_DPTR2)
1138 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139 "aopPut writting to code space");
1143 while (offset > aop->coff)
1146 emitcode ("inc", "dptr");
1149 while (offset < aop->coff)
1152 emitcode ("lcall", "__decdptr");
1157 /* if not in accumulater */
1160 emitcode ("movx", "@dptr,a");
1162 if (aop->type == AOP_DPTR2)
1170 while (offset > aop->coff)
1173 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1175 while (offset < aop->coff)
1178 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1185 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1191 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1193 else if (strcmp (s, "r0") == 0 ||
1194 strcmp (s, "r1") == 0 ||
1195 strcmp (s, "r2") == 0 ||
1196 strcmp (s, "r3") == 0 ||
1197 strcmp (s, "r4") == 0 ||
1198 strcmp (s, "r5") == 0 ||
1199 strcmp (s, "r6") == 0 ||
1200 strcmp (s, "r7") == 0)
1203 sprintf (buffer, "a%s", s);
1204 emitcode ("mov", "@%s,%s",
1205 aop->aopu.aop_ptr->name, buffer);
1208 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1213 if (strcmp (s, "a") == 0)
1214 emitcode ("push", "acc");
1216 emitcode ("push", "%s", s);
1221 /* if bit variable */
1222 if (!aop->aopu.aop_dir)
1224 emitcode ("clr", "a");
1225 emitcode ("rlc", "a");
1230 emitcode ("clr", "%s", aop->aopu.aop_dir);
1232 emitcode ("setb", "%s", aop->aopu.aop_dir);
1233 else if (!strcmp (s, "c"))
1234 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237 if (strcmp (s, "a"))
1242 symbol *lbl = newiTempLabel (NULL);
1243 emitcode ("clr", "c");
1244 emitcode ("jz", "%05d$", lbl->key + 100);
1245 emitcode ("cpl", "c");
1246 emitcode ("", "%05d$:", lbl->key + 100);
1247 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1255 if (strcmp (aop->aopu.aop_str[offset], s))
1256 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1261 if (!offset && (strcmp (s, "acc") == 0))
1264 if (strcmp (aop->aopu.aop_str[offset], s))
1265 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1270 "aopPut got unsupported aop->type");
1277 /*--------------------------------------------------------------------*/
1278 /* reAdjustPreg - points a register back to where it should (coff==0) */
1279 /*--------------------------------------------------------------------*/
1281 reAdjustPreg (asmop * aop)
1283 if ((aop->coff==0) || (aop->size <= 1)) {
1292 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1296 if (aop->type == AOP_DPTR2)
1303 emitcode ("lcall", "__decdptr");
1306 if (aop->type == AOP_DPTR2)
1316 #define AOP(op) op->aop
1317 #define AOP_TYPE(op) AOP(op)->type
1318 #define AOP_SIZE(op) AOP(op)->size
1319 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1320 AOP_TYPE(x) == AOP_R0))
1322 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1323 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1326 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1327 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1328 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1330 /* Workaround for DS80C390 bug: div ab may return bogus results
1331 * if A is accessed in instruction immediately before the div.
1333 * Will be fixed in B4 rev of processor, Dallas claims.
1336 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1337 if (!AOP_NEEDSACC(RIGHT)) \
1339 /* We can load A first, then B, since \
1340 * B (the RIGHT operand) won't clobber A, \
1341 * thus avoiding touching A right before the div. \
1343 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1344 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1346 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1350 /* Just stuff in a nop after loading A. */ \
1351 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1352 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1354 emitcode("nop", "; workaround for DS80C390 div bug."); \
1357 /*-----------------------------------------------------------------*/
1358 /* genNotFloat - generates not for float operations */
1359 /*-----------------------------------------------------------------*/
1361 genNotFloat (operand * op, operand * res)
1367 D (emitcode (";", "genNotFloat ");
1370 /* we will put 127 in the first byte of
1372 aopPut (AOP (res), "#127", 0);
1373 size = AOP_SIZE (op) - 1;
1376 _startLazyDPSEvaluation ();
1377 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1382 emitcode ("orl", "a,%s",
1384 offset++, FALSE, FALSE, FALSE));
1386 _endLazyDPSEvaluation ();
1388 tlbl = newiTempLabel (NULL);
1389 aopPut (res->aop, one, 1);
1390 emitcode ("jz", "%05d$", (tlbl->key + 100));
1391 aopPut (res->aop, zero, 1);
1392 emitcode ("", "%05d$:", (tlbl->key + 100));
1394 size = res->aop->size - 2;
1396 /* put zeros in the rest */
1398 aopPut (res->aop, zero, offset++);
1401 /*-----------------------------------------------------------------*/
1402 /* opIsGptr: returns non-zero if the passed operand is */
1403 /* a generic pointer type. */
1404 /*-----------------------------------------------------------------*/
1406 opIsGptr (operand * op)
1408 sym_link *type = operandType (op);
1410 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1417 /*-----------------------------------------------------------------*/
1418 /* getDataSize - get the operand data size */
1419 /*-----------------------------------------------------------------*/
1421 getDataSize (operand * op)
1424 size = AOP_SIZE (op);
1425 if (size == GPTRSIZE)
1427 sym_link *type = operandType (op);
1428 if (IS_GENPTR (type))
1430 /* generic pointer; arithmetic operations
1431 * should ignore the high byte (pointer type).
1439 /*-----------------------------------------------------------------*/
1440 /* outAcc - output Acc */
1441 /*-----------------------------------------------------------------*/
1443 outAcc (operand * result)
1446 size = getDataSize (result);
1449 aopPut (AOP (result), "a", 0);
1452 /* unsigned or positive */
1455 aopPut (AOP (result), zero, offset++);
1460 /*-----------------------------------------------------------------*/
1461 /* outBitC - output a bit C */
1462 /*-----------------------------------------------------------------*/
1464 outBitC (operand * result)
1466 /* if the result is bit */
1467 if (AOP_TYPE (result) == AOP_CRY)
1469 aopPut (AOP (result), "c", 0);
1473 emitcode ("clr", "a");
1474 emitcode ("rlc", "a");
1479 /*-----------------------------------------------------------------*/
1480 /* toBoolean - emit code for orl a,operator(sizeop) */
1481 /*-----------------------------------------------------------------*/
1483 toBoolean (operand * oper)
1485 int size = AOP_SIZE (oper) - 1;
1489 /* The generic part of a generic pointer should
1490 * not participate in it's truth value.
1492 * i.e. 0x10000000 is zero.
1494 if (opIsGptr (oper))
1496 D (emitcode (";", "toBoolean: generic ptr special case.");
1501 _startLazyDPSEvaluation ();
1502 if (AOP_NEEDSACC (oper) && size)
1505 emitcode ("push", "b");
1506 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1510 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1516 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1520 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1523 _endLazyDPSEvaluation ();
1527 emitcode ("mov", "a,b");
1528 emitcode ("pop", "b");
1533 /*-----------------------------------------------------------------*/
1534 /* genNot - generate code for ! operation */
1535 /*-----------------------------------------------------------------*/
1540 sym_link *optype = operandType (IC_LEFT (ic));
1542 D (emitcode (";", "genNot ");
1545 /* assign asmOps to operand & result */
1546 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1547 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1549 /* if in bit space then a special case */
1550 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1552 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1553 emitcode ("cpl", "c");
1554 outBitC (IC_RESULT (ic));
1558 /* if type float then do float */
1559 if (IS_FLOAT (optype))
1561 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1565 toBoolean (IC_LEFT (ic));
1567 tlbl = newiTempLabel (NULL);
1568 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1569 emitcode ("", "%05d$:", tlbl->key + 100);
1570 outBitC (IC_RESULT (ic));
1573 /* release the aops */
1574 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1575 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1579 /*-----------------------------------------------------------------*/
1580 /* genCpl - generate code for complement */
1581 /*-----------------------------------------------------------------*/
1588 D (emitcode (";", "genCpl ");
1592 /* assign asmOps to operand & result */
1593 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1594 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1596 /* if both are in bit space then
1598 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1599 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1602 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1603 emitcode ("cpl", "c");
1604 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1608 size = AOP_SIZE (IC_RESULT (ic));
1609 _startLazyDPSEvaluation ();
1612 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1614 emitcode ("cpl", "a");
1615 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1617 _endLazyDPSEvaluation ();
1621 /* release the aops */
1622 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1623 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* genUminusFloat - unary minus for floating points */
1628 /*-----------------------------------------------------------------*/
1630 genUminusFloat (operand * op, operand * result)
1632 int size, offset = 0;
1634 /* for this we just need to flip the
1635 first it then copy the rest in place */
1636 D (emitcode (";", "genUminusFloat");
1639 _startLazyDPSEvaluation ();
1640 size = AOP_SIZE (op) - 1;
1641 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1644 emitcode ("cpl", "acc.7");
1645 aopPut (AOP (result), "a", 3);
1649 aopPut (AOP (result),
1650 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1654 _endLazyDPSEvaluation ();
1657 /*-----------------------------------------------------------------*/
1658 /* genUminus - unary minus code generation */
1659 /*-----------------------------------------------------------------*/
1661 genUminus (iCode * ic)
1664 sym_link *optype, *rtype;
1666 D (emitcode (";", "genUminus ");
1671 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1672 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1674 /* if both in bit space then special
1676 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1677 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1680 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1681 emitcode ("cpl", "c");
1682 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1686 optype = operandType (IC_LEFT (ic));
1687 rtype = operandType (IC_RESULT (ic));
1689 /* if float then do float stuff */
1690 if (IS_FLOAT (optype))
1692 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1696 /* otherwise subtract from zero */
1697 size = AOP_SIZE (IC_LEFT (ic));
1699 _startLazyDPSEvaluation ();
1702 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1703 if (!strcmp (l, "a"))
1707 emitcode ("cpl", "a");
1708 emitcode ("addc", "a,#0");
1714 emitcode ("clr", "a");
1715 emitcode ("subb", "a,%s", l);
1717 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1719 _endLazyDPSEvaluation ();
1721 /* if any remaining bytes in the result */
1722 /* we just need to propagate the sign */
1723 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1725 emitcode ("rlc", "a");
1726 emitcode ("subb", "a,acc");
1728 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1732 /* release the aops */
1733 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1734 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1737 /*-----------------------------------------------------------------*/
1738 /* saveRegisters - will look for a call and save the registers */
1739 /*-----------------------------------------------------------------*/
1741 saveRegisters (iCode * lic)
1749 for (ic = lic; ic; ic = ic->next)
1750 if (ic->op == CALL || ic->op == PCALL)
1755 fprintf (stderr, "found parameter push with no function call\n");
1759 /* if the registers have been saved already then
1761 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1762 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
1765 /* find the registers in use at this time
1766 and push them away to safety */
1767 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1771 if (options.useXstack)
1773 if (bitVectBitValue (rsave, R0_IDX))
1774 emitcode ("mov", "b,r0");
1775 emitcode ("mov", "r0,%s", spname);
1776 for (i = 0; i < ds390_nRegs; i++)
1778 if (bitVectBitValue (rsave, i))
1781 emitcode ("mov", "a,b");
1783 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1784 emitcode ("movx", "@r0,a");
1785 emitcode ("inc", "r0");
1788 emitcode ("mov", "%s,r0", spname);
1789 if (bitVectBitValue (rsave, R0_IDX))
1790 emitcode ("mov", "r0,b");
1793 for (i = 0; i < ds390_nRegs; i++)
1795 if (bitVectBitValue (rsave, i))
1796 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1799 detype = getSpec (operandType (IC_LEFT (ic)));
1802 /*-----------------------------------------------------------------*/
1803 /* unsaveRegisters - pop the pushed registers */
1804 /*-----------------------------------------------------------------*/
1806 unsaveRegisters (iCode * ic)
1810 /* find the registers in use at this time
1811 and push them away to safety */
1812 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1815 if (options.useXstack)
1817 emitcode ("mov", "r0,%s", spname);
1818 for (i = ds390_nRegs; i >= 0; i--)
1820 if (bitVectBitValue (rsave, i))
1822 emitcode ("dec", "r0");
1823 emitcode ("movx", "a,@r0");
1825 emitcode ("mov", "b,a");
1827 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1831 emitcode ("mov", "%s,r0", spname);
1832 if (bitVectBitValue (rsave, R0_IDX))
1833 emitcode ("mov", "r0,b");
1836 for (i = ds390_nRegs; i >= 0; i--)
1838 if (bitVectBitValue (rsave, i))
1839 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1845 /*-----------------------------------------------------------------*/
1847 /*-----------------------------------------------------------------*/
1849 pushSide (operand * oper, int size)
1852 _startLazyDPSEvaluation ();
1855 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1856 if (AOP_TYPE (oper) != AOP_REG &&
1857 AOP_TYPE (oper) != AOP_DIR &&
1860 emitcode ("mov", "a,%s", l);
1861 emitcode ("push", "acc");
1864 emitcode ("push", "%s", l);
1866 _endLazyDPSEvaluation ();
1869 /*-----------------------------------------------------------------*/
1870 /* assignResultValue - */
1871 /*-----------------------------------------------------------------*/
1873 assignResultValue (operand * oper)
1876 int size = AOP_SIZE (oper);
1878 _startLazyDPSEvaluation ();
1881 aopPut (AOP (oper), fReturn[offset], offset);
1884 _endLazyDPSEvaluation ();
1888 /*-----------------------------------------------------------------*/
1889 /* genXpush - pushes onto the external stack */
1890 /*-----------------------------------------------------------------*/
1892 genXpush (iCode * ic)
1894 asmop *aop = newAsmop (0);
1896 int size, offset = 0;
1898 D (emitcode (";", "genXpush ");
1901 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1902 r = getFreePtr (ic, &aop, FALSE);
1905 emitcode ("mov", "%s,_spx", r->name);
1907 size = AOP_SIZE (IC_LEFT (ic));
1908 _startLazyDPSEvaluation ();
1912 char *l = aopGet (AOP (IC_LEFT (ic)),
1913 offset++, FALSE, FALSE, TRUE);
1915 emitcode ("movx", "@%s,a", r->name);
1916 emitcode ("inc", "%s", r->name);
1919 _endLazyDPSEvaluation ();
1922 emitcode ("mov", "_spx,%s", r->name);
1924 freeAsmop (NULL, aop, ic, TRUE);
1925 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1928 /*-----------------------------------------------------------------*/
1929 /* genIpush - genrate code for pushing this gets a little complex */
1930 /*-----------------------------------------------------------------*/
1932 genIpush (iCode * ic)
1934 int size, offset = 0;
1937 D (emitcode (";", "genIpush ");
1940 /* if this is not a parm push : ie. it is spill push
1941 and spill push is always done on the local stack */
1945 /* and the item is spilt then do nothing */
1946 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1949 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1950 size = AOP_SIZE (IC_LEFT (ic));
1951 /* push it on the stack */
1952 _startLazyDPSEvaluation ();
1955 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1961 emitcode ("push", "%s", l);
1963 _endLazyDPSEvaluation ();
1967 /* this is a paramter push: in this case we call
1968 the routine to find the call and save those
1969 registers that need to be saved */
1972 /* if use external stack then call the external
1973 stack pushing routine */
1974 if (options.useXstack)
1980 /* then do the push */
1981 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1983 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1984 size = AOP_SIZE (IC_LEFT (ic));
1986 _startLazyDPSEvaluation ();
1989 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1990 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1991 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1994 emitcode ("mov", "a,%s", l);
1995 emitcode ("push", "acc");
1998 emitcode ("push", "%s", l);
2000 _endLazyDPSEvaluation ();
2002 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2005 /*-----------------------------------------------------------------*/
2006 /* genIpop - recover the registers: can happen only for spilling */
2007 /*-----------------------------------------------------------------*/
2009 genIpop (iCode * ic)
2013 D (emitcode (";", "genIpop ");
2017 /* if the temp was not pushed then */
2018 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2021 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2022 size = AOP_SIZE (IC_LEFT (ic));
2023 offset = (size - 1);
2024 _startLazyDPSEvaluation ();
2027 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2028 FALSE, TRUE, TRUE));
2030 _endLazyDPSEvaluation ();
2032 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2035 /*-----------------------------------------------------------------*/
2036 /* unsaveRBank - restores the resgister bank from stack */
2037 /*-----------------------------------------------------------------*/
2039 unsaveRBank (int bank, iCode * ic, bool popPsw)
2045 if (options.useXstack)
2049 /* Assume r0 is available for use. */
2050 r = ds390_regWithIdx (R0_IDX);;
2055 r = getFreePtr (ic, &aop, FALSE);
2057 emitcode ("mov", "%s,_spx", r->name);
2062 if (options.useXstack)
2064 emitcode ("movx", "a,@%s", r->name);
2065 emitcode ("mov", "psw,a");
2066 emitcode ("dec", "%s", r->name);
2070 emitcode ("pop", "psw");
2074 for (i = (ds390_nRegs - 1); i >= 0; i--)
2076 if (options.useXstack)
2078 emitcode ("movx", "a,@%s", r->name);
2079 emitcode ("mov", "(%s+%d),a",
2080 regs390[i].base, 8 * bank + regs390[i].offset);
2081 emitcode ("dec", "%s", r->name);
2085 emitcode ("pop", "(%s+%d)",
2086 regs390[i].base, 8 * bank + regs390[i].offset);
2089 if (options.useXstack)
2091 emitcode ("mov", "_spx,%s", r->name);
2096 freeAsmop (NULL, aop, ic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* saveRBank - saves an entire register bank on the stack */
2102 /*-----------------------------------------------------------------*/
2104 saveRBank (int bank, iCode * ic, bool pushPsw)
2110 if (options.useXstack)
2114 /* Assume r0 is available for use. */
2115 r = ds390_regWithIdx (R0_IDX);;
2120 r = getFreePtr (ic, &aop, FALSE);
2122 emitcode ("mov", "%s,_spx", r->name);
2125 for (i = 0; i < ds390_nRegs; i++)
2127 if (options.useXstack)
2129 emitcode ("inc", "%s", r->name);
2130 emitcode ("mov", "a,(%s+%d)",
2131 regs390[i].base, 8 * bank + regs390[i].offset);
2132 emitcode ("movx", "@%s,a", r->name);
2135 emitcode ("push", "(%s+%d)",
2136 regs390[i].base, 8 * bank + regs390[i].offset);
2141 if (options.useXstack)
2143 emitcode ("mov", "a,psw");
2144 emitcode ("movx", "@%s,a", r->name);
2145 emitcode ("inc", "%s", r->name);
2146 emitcode ("mov", "_spx,%s", r->name);
2150 emitcode ("push", "psw");
2153 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2158 freeAsmop (NULL, aop, ic, TRUE);
2167 /*-----------------------------------------------------------------*/
2168 /* genCall - generates a call statement */
2169 /*-----------------------------------------------------------------*/
2171 genCall (iCode * ic)
2174 bool restoreBank = FALSE;
2175 bool swapBanks = FALSE;
2177 D (emitcode (";", "genCall "););
2179 /* if we are calling a not _naked function that is not using
2180 the same register bank then we need to save the
2181 destination registers on the stack */
2182 detype = getSpec (operandType (IC_LEFT (ic)));
2183 if (detype && !SPEC_NAKED(detype) &&
2184 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2185 IS_ISR (currFunc->etype))
2189 /* This is unexpected; the bank should have been saved in
2192 saveRBank (SPEC_BANK (detype), ic, FALSE);
2198 /* if caller saves & we have not saved then */
2202 /* if send set is not empty the assign */
2203 /* We've saved all the registers we care about;
2204 * therefore, we may clobber any register not used
2205 * in the calling convention (i.e. anything not in
2212 for (sic = setFirstItem (_G.sendSet); sic;
2213 sic = setNextItem (_G.sendSet))
2215 int size, offset = 0;
2217 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2218 size = AOP_SIZE (IC_LEFT (sic));
2220 _startLazyDPSEvaluation ();
2223 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2224 FALSE, FALSE, TRUE);
2225 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2227 emitcode("mov", "%s,%s", regs390[offset].name, l);
2229 else if (strcmp (l, fReturn[offset]))
2231 emitcode ("mov", "%s,%s",
2237 _endLazyDPSEvaluation ();
2238 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2240 size = AOP_SIZE (IC_LEFT (sic));
2248 emitcode("mov", "%s,%s",
2249 fReturn[size], regs390[size].name);
2252 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2259 emitcode ("mov", "psw,#0x%02x",
2260 ((SPEC_BANK(detype)) << 3) & 0xff);
2264 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2265 OP_SYMBOL (IC_LEFT (ic))->rname :
2266 OP_SYMBOL (IC_LEFT (ic))->name));
2270 emitcode ("mov", "psw,#0x%02x",
2271 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
2274 /* if we need assign a result value */
2275 if ((IS_ITEMP (IC_RESULT (ic)) &&
2276 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2277 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2278 IS_TRUE_SYMOP (IC_RESULT (ic)))
2280 if (isOperandInFarSpace (IC_RESULT (ic))
2281 && getSize (operandType (IC_RESULT (ic))) <= 2)
2283 int size = getSize (operandType (IC_RESULT (ic)));
2285 /* Special case for 1 or 2 byte return in far space. */
2289 emitcode ("mov", "b,%s", fReturn[1]);
2292 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2293 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2297 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2304 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2307 assignResultValue (IC_RESULT (ic));
2309 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2313 /* adjust the stack for parameters if
2318 if (ic->parmBytes > 3)
2320 emitcode ("mov", "a,%s", spname);
2321 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2322 emitcode ("mov", "%s,a", spname);
2325 for (i = 0; i < ic->parmBytes; i++)
2326 emitcode ("dec", "%s", spname);
2329 /* if we hade saved some registers then unsave them */
2330 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2331 unsaveRegisters (ic);
2333 /* if register bank was saved then pop them */
2335 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
2338 /*-----------------------------------------------------------------*/
2339 /* genPcall - generates a call by pointer statement */
2340 /*-----------------------------------------------------------------*/
2342 genPcall (iCode * ic)
2345 symbol *rlbl = newiTempLabel (NULL);
2347 D (emitcode (";", "genPcall ");
2351 /* if caller saves & we have not saved then */
2355 /* if we are calling a function that is not using
2356 the same register bank then we need to save the
2357 destination registers on the stack */
2358 detype = getSpec (operandType (IC_LEFT (ic)));
2360 IS_ISR (currFunc->etype) &&
2361 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2362 saveRBank (SPEC_BANK (detype), ic, TRUE);
2365 /* push the return address on to the stack */
2366 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2367 emitcode ("push", "acc");
2368 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2369 emitcode ("push", "acc");
2371 if (options.model == MODEL_FLAT24)
2373 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2374 emitcode ("push", "acc");
2377 /* now push the calling address */
2378 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2380 pushSide (IC_LEFT (ic), FPTRSIZE);
2382 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2384 /* if send set is not empty the assign */
2389 for (sic = setFirstItem (_G.sendSet); sic;
2390 sic = setNextItem (_G.sendSet))
2392 int size, offset = 0;
2394 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2395 size = AOP_SIZE (IC_LEFT (sic));
2396 _startLazyDPSEvaluation ();
2399 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2400 FALSE, FALSE, TRUE);
2401 if (strcmp (l, fReturn[offset]))
2403 emitcode ("mov", "%s,%s",
2409 _endLazyDPSEvaluation ();
2410 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2415 emitcode ("ret", "");
2416 emitcode ("", "%05d$:", (rlbl->key + 100));
2419 /* if we need assign a result value */
2420 if ((IS_ITEMP (IC_RESULT (ic)) &&
2421 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2422 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2423 IS_TRUE_SYMOP (IC_RESULT (ic)))
2427 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2430 assignResultValue (IC_RESULT (ic));
2432 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2435 /* adjust the stack for parameters if
2440 if (ic->parmBytes > 3)
2442 emitcode ("mov", "a,%s", spname);
2443 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2444 emitcode ("mov", "%s,a", spname);
2447 for (i = 0; i < ic->parmBytes; i++)
2448 emitcode ("dec", "%s", spname);
2452 /* if register bank was saved then unsave them */
2454 (SPEC_BANK (currFunc->etype) !=
2455 SPEC_BANK (detype)))
2456 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2458 /* if we hade saved some registers then
2461 unsaveRegisters (ic);
2465 /*-----------------------------------------------------------------*/
2466 /* resultRemat - result is rematerializable */
2467 /*-----------------------------------------------------------------*/
2469 resultRemat (iCode * ic)
2471 if (SKIP_IC (ic) || ic->op == IFX)
2474 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2476 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2477 if (sym->remat && !POINTER_SET (ic))
2484 #if defined(__BORLANDC__) || defined(_MSC_VER)
2485 #define STRCASECMP stricmp
2487 #define STRCASECMP strcasecmp
2490 /*-----------------------------------------------------------------*/
2491 /* inExcludeList - return 1 if the string is in exclude Reg list */
2492 /*-----------------------------------------------------------------*/
2494 inExcludeList (char *s)
2498 if (options.excludeRegs[i] &&
2499 STRCASECMP (options.excludeRegs[i], "none") == 0)
2502 for (i = 0; options.excludeRegs[i]; i++)
2504 if (options.excludeRegs[i] &&
2505 STRCASECMP (s, options.excludeRegs[i]) == 0)
2511 /*-----------------------------------------------------------------*/
2512 /* genFunction - generated code for function entry */
2513 /*-----------------------------------------------------------------*/
2515 genFunction (iCode * ic)
2519 bool switchedPSW = FALSE;
2521 D (emitcode (";", "genFunction "););
2524 /* create the function header */
2525 emitcode (";", "-----------------------------------------");
2526 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2527 emitcode (";", "-----------------------------------------");
2529 emitcode ("", "%s:", sym->rname);
2530 fetype = getSpec (operandType (IC_LEFT (ic)));
2532 if (SPEC_NAKED(fetype))
2534 emitcode(";", "naked function: no prologue.");
2538 /* if critical function then turn interrupts off */
2539 if (SPEC_CRTCL (fetype))
2540 emitcode ("clr", "ea");
2542 /* here we need to generate the equates for the
2543 register bank if required */
2544 if (SPEC_BANK (fetype) != rbank)
2548 rbank = SPEC_BANK (fetype);
2549 for (i = 0; i < ds390_nRegs; i++)
2551 if (strcmp (regs390[i].base, "0") == 0)
2552 emitcode ("", "%s = 0x%02x",
2554 8 * rbank + regs390[i].offset);
2556 emitcode ("", "%s = %s + 0x%02x",
2559 8 * rbank + regs390[i].offset);
2563 /* if this is an interrupt service routine then
2564 save acc, b, dpl, dph */
2565 if (IS_ISR (sym->etype))
2568 if (!inExcludeList ("acc"))
2569 emitcode ("push", "acc");
2570 if (!inExcludeList ("b"))
2571 emitcode ("push", "b");
2572 if (!inExcludeList ("dpl"))
2573 emitcode ("push", "dpl");
2574 if (!inExcludeList ("dph"))
2575 emitcode ("push", "dph");
2576 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2578 emitcode ("push", "dpx");
2579 /* Make sure we're using standard DPTR */
2580 emitcode ("push", "dps");
2581 emitcode ("mov", "dps, #0x00");
2582 if (options.stack10bit)
2584 /* This ISR could conceivably use DPTR2. Better save it. */
2585 emitcode ("push", "dpl1");
2586 emitcode ("push", "dph1");
2587 emitcode ("push", "dpx1");
2588 emitcode ("push", DP2_RESULT_REG);
2591 /* if this isr has no bank i.e. is going to
2592 run with bank 0 , then we need to save more
2594 if (!SPEC_BANK (sym->etype))
2597 /* if this function does not call any other
2598 function then we can be economical and
2599 save only those registers that are used */
2604 /* if any registers used */
2607 /* save the registers used */
2608 for (i = 0; i < sym->regsUsed->size; i++)
2610 if (bitVectBitValue (sym->regsUsed, i) ||
2611 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2612 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2619 /* this function has a function call cannot
2620 determines register usage so we will have to push the
2622 saveRBank (0, ic, FALSE);
2627 /* This ISR uses a non-zero bank.
2629 * We assume that the bank is available for our
2632 * However, if this ISR calls a function which uses some
2633 * other bank, we must save that bank entirely.
2635 unsigned long banksToSave = 0;
2640 #define MAX_REGISTER_BANKS 4
2645 for (i = ic; i; i = i->next)
2647 if (i->op == ENDFUNCTION)
2649 /* we got to the end OK. */
2657 detype = getSpec(operandType (IC_LEFT(i)));
2659 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2661 /* Mark this bank for saving. */
2662 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2664 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2668 banksToSave |= (1 << SPEC_BANK(detype));
2671 /* And note that we don't need to do it in
2679 /* This is a mess; we have no idea what
2680 * register bank the called function might
2683 * The only thing I can think of to do is
2684 * throw a warning and hope.
2686 werror(W_FUNCPTR_IN_USING_ISR);
2690 if (banksToSave && options.useXstack)
2692 /* Since we aren't passing it an ic,
2693 * saveRBank will assume r0 is available to abuse.
2695 * So switch to our (trashable) bank now, so
2696 * the caller's R0 isn't trashed.
2698 emitcode ("push", "psw");
2699 emitcode ("mov", "psw,#0x%02x",
2700 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2704 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2706 if (banksToSave & (1 << ix))
2708 saveRBank(ix, NULL, FALSE);
2712 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2717 /* if callee-save to be used for this function
2718 then save the registers being used in this function */
2719 if (sym->calleeSave)
2723 /* if any registers used */
2726 /* save the registers used */
2727 for (i = 0; i < sym->regsUsed->size; i++)
2729 if (bitVectBitValue (sym->regsUsed, i) ||
2730 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2732 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2740 /* set the register bank to the desired value */
2741 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2744 emitcode ("push", "psw");
2745 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2748 if (IS_RENT (sym->etype) || options.stackAuto)
2751 if (options.useXstack)
2753 emitcode ("mov", "r0,%s", spname);
2754 emitcode ("mov", "a,_bp");
2755 emitcode ("movx", "@r0,a");
2756 emitcode ("inc", "%s", spname);
2760 /* set up the stack */
2761 emitcode ("push", "_bp"); /* save the callers stack */
2763 emitcode ("mov", "_bp,%s", spname);
2766 /* adjust the stack for the function */
2772 werror (W_STACK_OVERFLOW, sym->name);
2774 if (i > 3 && sym->recvSize < 4)
2777 emitcode ("mov", "a,sp");
2778 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2779 emitcode ("mov", "sp,a");
2784 emitcode ("inc", "sp");
2790 emitcode ("mov", "a,_spx");
2791 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2792 emitcode ("mov", "_spx,a");
2797 /*-----------------------------------------------------------------*/
2798 /* genEndFunction - generates epilogue for functions */
2799 /*-----------------------------------------------------------------*/
2801 genEndFunction (iCode * ic)
2803 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2805 D (emitcode (";", "genEndFunction "););
2807 if (SPEC_NAKED(sym->etype))
2809 emitcode(";", "naked function: no epilogue.");
2813 if (IS_RENT (sym->etype) || options.stackAuto)
2815 emitcode ("mov", "%s,_bp", spname);
2818 /* if use external stack but some variables were
2819 added to the local stack then decrement the
2821 if (options.useXstack && sym->stack)
2823 emitcode ("mov", "a,sp");
2824 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2825 emitcode ("mov", "sp,a");
2829 if ((IS_RENT (sym->etype) || options.stackAuto))
2831 if (options.useXstack)
2833 emitcode ("mov", "r0,%s", spname);
2834 emitcode ("movx", "a,@r0");
2835 emitcode ("mov", "_bp,a");
2836 emitcode ("dec", "%s", spname);
2840 emitcode ("pop", "_bp");
2844 /* restore the register bank */
2845 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2847 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2848 || !options.useXstack)
2850 /* Special case of ISR using non-zero bank with useXstack
2853 emitcode ("pop", "psw");
2857 if (IS_ISR (sym->etype))
2860 /* now we need to restore the registers */
2861 /* if this isr has no bank i.e. is going to
2862 run with bank 0 , then we need to save more
2864 if (!SPEC_BANK (sym->etype))
2866 /* if this function does not call any other
2867 function then we can be economical and
2868 save only those registers that are used */
2873 /* if any registers used */
2876 /* save the registers used */
2877 for (i = sym->regsUsed->size; i >= 0; i--)
2879 if (bitVectBitValue (sym->regsUsed, i) ||
2880 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2881 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2888 /* this function has a function call cannot
2889 determines register usage so we will have to pop the
2891 unsaveRBank (0, ic, FALSE);
2896 /* This ISR uses a non-zero bank.
2898 * Restore any register banks saved by genFunction
2901 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2904 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2906 if (savedBanks & (1 << ix))
2908 unsaveRBank(ix, NULL, FALSE);
2912 if (options.useXstack)
2914 /* Restore bank AFTER calling unsaveRBank,
2915 * since it can trash r0.
2917 emitcode ("pop", "psw");
2921 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2923 if (options.stack10bit)
2925 emitcode ("pop", DP2_RESULT_REG);
2926 emitcode ("pop", "dpx1");
2927 emitcode ("pop", "dph1");
2928 emitcode ("pop", "dpl1");
2930 emitcode ("pop", "dps");
2931 emitcode ("pop", "dpx");
2933 if (!inExcludeList ("dph"))
2934 emitcode ("pop", "dph");
2935 if (!inExcludeList ("dpl"))
2936 emitcode ("pop", "dpl");
2937 if (!inExcludeList ("b"))
2938 emitcode ("pop", "b");
2939 if (!inExcludeList ("acc"))
2940 emitcode ("pop", "acc");
2942 if (SPEC_CRTCL (sym->etype))
2943 emitcode ("setb", "ea");
2945 /* if debug then send end of function */
2946 if (options.debug && currFunc) {
2948 emitcode ("", "C$%s$%d$%d$%d ==.",
2949 FileBaseName (ic->filename), currFunc->lastLine,
2950 ic->level, ic->block);
2951 if (IS_STATIC (currFunc->etype))
2952 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2954 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2958 emitcode ("reti", "");
2962 if (SPEC_CRTCL (sym->etype))
2963 emitcode ("setb", "ea");
2965 if (sym->calleeSave)
2969 /* if any registers used */
2972 /* save the registers used */
2973 for (i = sym->regsUsed->size; i >= 0; i--)
2975 if (bitVectBitValue (sym->regsUsed, i) ||
2976 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2977 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2983 /* if debug then send end of function */
2984 if (options.debug && currFunc)
2987 emitcode ("", "C$%s$%d$%d$%d ==.",
2988 FileBaseName (ic->filename), currFunc->lastLine,
2989 ic->level, ic->block);
2990 if (IS_STATIC (currFunc->etype))
2991 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2993 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2997 emitcode ("ret", "");
3002 /*-----------------------------------------------------------------*/
3003 /* genRet - generate code for return statement */
3004 /*-----------------------------------------------------------------*/
3008 int size, offset = 0, pushed = 0;
3010 D (emitcode (";", "genRet ");
3013 /* if we have no return value then
3014 just generate the "ret" */
3018 /* we have something to return then
3019 move the return value into place */
3020 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3021 size = AOP_SIZE (IC_LEFT (ic));
3023 _startLazyDPSEvaluation ();
3027 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3029 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3030 FALSE, TRUE, FALSE);
3031 emitcode ("push", "%s", l);
3036 /* Since A is the last element of fReturn,
3037 * is is OK to clobber it in the aopGet.
3039 l = aopGet (AOP (IC_LEFT (ic)), offset,
3040 FALSE, FALSE, TRUE);
3041 if (strcmp (fReturn[offset], l))
3042 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3045 _endLazyDPSEvaluation ();
3052 if (strcmp (fReturn[pushed], "a"))
3053 emitcode ("pop", fReturn[pushed]);
3055 emitcode ("pop", "acc");
3058 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3061 /* generate a jump to the return label
3062 if the next is not the return statement */
3063 if (!(ic->next && ic->next->op == LABEL &&
3064 IC_LABEL (ic->next) == returnLabel))
3066 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3070 /*-----------------------------------------------------------------*/
3071 /* genLabel - generates a label */
3072 /*-----------------------------------------------------------------*/
3074 genLabel (iCode * ic)
3076 /* special case never generate */
3077 if (IC_LABEL (ic) == entryLabel)
3080 D (emitcode (";", "genLabel ");
3083 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3086 /*-----------------------------------------------------------------*/
3087 /* genGoto - generates a ljmp */
3088 /*-----------------------------------------------------------------*/
3090 genGoto (iCode * ic)
3092 D (emitcode (";", "genGoto ");
3094 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3097 /*-----------------------------------------------------------------*/
3098 /* findLabelBackwards: walks back through the iCode chain looking */
3099 /* for the given label. Returns number of iCode instructions */
3100 /* between that label and given ic. */
3101 /* Returns zero if label not found. */
3102 /*-----------------------------------------------------------------*/
3104 findLabelBackwards (iCode * ic, int key)
3113 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3115 /* printf("findLabelBackwards = %d\n", count); */
3123 /*-----------------------------------------------------------------*/
3124 /* genPlusIncr :- does addition with increment if possible */
3125 /*-----------------------------------------------------------------*/
3127 genPlusIncr (iCode * ic)
3129 unsigned int icount;
3130 unsigned int size = getDataSize (IC_RESULT (ic));
3132 /* will try to generate an increment */
3133 /* if the right side is not a literal
3135 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3138 /* if the literal value of the right hand side
3139 is greater than 4 then it is not worth it */
3140 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3143 /* if increment 16 bits in register */
3145 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3146 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3147 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3155 /* If the next instruction is a goto and the goto target
3156 * is <= 5 instructions previous to this, we can generate
3157 * jumps straight to that target.
3159 if (ic->next && ic->next->op == GOTO
3160 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3163 emitcode (";", "tail increment optimized (range %d)", labelRange);
3164 tlbl = IC_LABEL (ic->next);
3169 tlbl = newiTempLabel (NULL);
3172 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3173 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3174 IS_AOP_PREG (IC_RESULT (ic)))
3175 emitcode ("cjne", "%s,#0x00,%05d$"
3176 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3180 emitcode ("clr", "a");
3181 emitcode ("cjne", "a,%s,%05d$"
3182 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3186 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3189 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3190 IS_AOP_PREG (IC_RESULT (ic)))
3191 emitcode ("cjne", "%s,#0x00,%05d$"
3192 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3195 emitcode ("cjne", "a,%s,%05d$"
3196 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3199 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3203 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3204 IS_AOP_PREG (IC_RESULT (ic)))
3205 emitcode ("cjne", "%s,#0x00,%05d$"
3206 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3210 emitcode ("cjne", "a,%s,%05d$"
3211 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3214 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3219 emitcode ("", "%05d$:", tlbl->key + 100);
3224 /* if the sizes are greater than 1 then we cannot */
3225 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3226 AOP_SIZE (IC_LEFT (ic)) > 1)
3229 /* we can if the aops of the left & result match or
3230 if they are in registers and the registers are the
3233 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3234 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3235 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3240 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3241 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3242 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3247 _startLazyDPSEvaluation ();
3250 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3252 _endLazyDPSEvaluation ();
3261 /*-----------------------------------------------------------------*/
3262 /* outBitAcc - output a bit in acc */
3263 /*-----------------------------------------------------------------*/
3265 outBitAcc (operand * result)
3267 symbol *tlbl = newiTempLabel (NULL);
3268 /* if the result is a bit */
3269 if (AOP_TYPE (result) == AOP_CRY)
3271 aopPut (AOP (result), "a", 0);
3275 emitcode ("jz", "%05d$", tlbl->key + 100);
3276 emitcode ("mov", "a,%s", one);
3277 emitcode ("", "%05d$:", tlbl->key + 100);
3282 /*-----------------------------------------------------------------*/
3283 /* genPlusBits - generates code for addition of two bits */
3284 /*-----------------------------------------------------------------*/
3286 genPlusBits (iCode * ic)
3288 D (emitcode (";", "genPlusBits ");
3290 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3292 symbol *lbl = newiTempLabel (NULL);
3293 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3294 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3295 emitcode ("cpl", "c");
3296 emitcode ("", "%05d$:", (lbl->key + 100));
3297 outBitC (IC_RESULT (ic));
3301 emitcode ("clr", "a");
3302 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3303 emitcode ("rlc", "a");
3304 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3305 emitcode ("addc", "a,#0x00");
3306 outAcc (IC_RESULT (ic));
3311 adjustArithmeticResult (iCode * ic)
3313 if (opIsGptr (IC_RESULT (ic)) &&
3314 opIsGptr (IC_LEFT (ic)) &&
3315 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3317 aopPut (AOP (IC_RESULT (ic)),
3318 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3322 if (opIsGptr (IC_RESULT (ic)) &&
3323 opIsGptr (IC_RIGHT (ic)) &&
3324 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3326 aopPut (AOP (IC_RESULT (ic)),
3327 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3331 if (opIsGptr (IC_RESULT (ic)) &&
3332 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3333 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3334 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3335 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3338 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3339 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3343 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3344 // (because all three operands are in far space).
3345 #define AOP_OP_3(ic) \
3346 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3347 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3348 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3349 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3350 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3351 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3353 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3355 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3358 // Macro to aopOp all three operands of an ic. If this cannot be done,
3359 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3360 // will be set TRUE. The caller must then handle the case specially, noting
3361 // that the IC_RESULT operand is not aopOp'd.
3362 #define AOP_OP_3_NOFATAL(ic, rc) \
3363 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3364 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3365 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3366 isOperandInFarSpace(IC_RESULT(ic))) \
3368 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3373 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3374 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3376 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3377 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3379 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3381 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3385 // aopOp the left & right operands of an ic.
3386 #define AOP_OP_2(ic) \
3387 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3388 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3390 // convienience macro.
3391 #define AOP_SET_LOCALS(ic) \
3392 left = IC_LEFT(ic); \
3393 right = IC_RIGHT(ic); \
3394 result = IC_RESULT(ic);
3397 // Given an integer value of pushedSize bytes on the stack,
3398 // adjust it to be resultSize bytes, either by discarding
3399 // the most significant bytes or by zero-padding.
3401 // On exit from this macro, pushedSize will have been adjusted to
3402 // equal resultSize, and ACC may be trashed.
3403 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3404 /* If the pushed data is bigger than the result, \
3405 * simply discard unused bytes. Icky, but works. \
3407 while (pushedSize > resultSize) \
3409 D (emitcode (";", "discarding unused result byte."););\
3410 emitcode ("pop", "acc"); \
3413 if (pushedSize < resultSize) \
3415 emitcode ("clr", "a"); \
3416 /* Conversly, we haven't pushed enough here. \
3417 * just zero-pad, and all is well. \
3419 while (pushedSize < resultSize) \
3421 emitcode("push", "acc"); \
3425 assert(pushedSize == resultSize);
3427 /*-----------------------------------------------------------------*/
3428 /* genPlus - generates code for addition */
3429 /*-----------------------------------------------------------------*/
3431 genPlus (iCode * ic)
3433 int size, offset = 0;
3434 bool pushResult = FALSE;
3437 D (emitcode (";", "genPlus "););
3439 /* special cases :- */
3441 AOP_OP_3_NOFATAL (ic, pushResult);
3444 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3449 /* if literal, literal on the right or
3450 if left requires ACC or right is already
3452 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3453 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3454 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3456 operand *t = IC_RIGHT (ic);
3457 IC_RIGHT (ic) = IC_LEFT (ic);
3459 emitcode (";", "Swapped plus args.");
3462 /* if both left & right are in bit
3464 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3465 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3471 /* if left in bit space & right literal */
3472 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3473 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3475 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3476 /* if result in bit space */
3477 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3479 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3480 emitcode ("cpl", "c");
3481 outBitC (IC_RESULT (ic));
3485 size = getDataSize (IC_RESULT (ic));
3486 _startLazyDPSEvaluation ();
3489 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3490 emitcode ("addc", "a,#00");
3491 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3493 _endLazyDPSEvaluation ();
3498 /* if I can do an increment instead
3499 of add then GOOD for ME */
3500 if (genPlusIncr (ic) == TRUE)
3502 emitcode (";", "did genPlusIncr");
3507 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3509 _startLazyDPSEvaluation ();
3512 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3514 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3516 emitcode ("add", "a,%s",
3517 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3519 emitcode ("addc", "a,%s",
3520 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3524 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3526 /* right is going to use ACC or we would have taken the
3529 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3530 D(emitcode(";", "+ AOP_ACC special case."););
3531 emitcode("xch", "a, %s", DP2_RESULT_REG);
3533 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3536 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3538 emitcode("add", "a, %s", DP2_RESULT_REG);
3542 emitcode ("add", "a,%s",
3543 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3548 emitcode ("addc", "a,%s",
3549 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3554 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3558 emitcode ("push", "acc");
3562 _endLazyDPSEvaluation ();
3566 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3568 size = getDataSize (IC_LEFT (ic));
3569 rSize = getDataSize (IC_RESULT (ic));
3571 ADJUST_PUSHED_RESULT(size, rSize);
3573 _startLazyDPSEvaluation ();
3576 emitcode ("pop", "acc");
3577 aopPut (AOP (IC_RESULT (ic)), "a", size);
3579 _endLazyDPSEvaluation ();
3582 adjustArithmeticResult (ic);
3585 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3586 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3587 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3590 /*-----------------------------------------------------------------*/
3591 /* genMinusDec :- does subtraction with deccrement if possible */
3592 /*-----------------------------------------------------------------*/
3594 genMinusDec (iCode * ic)
3596 unsigned int icount;
3597 unsigned int size = getDataSize (IC_RESULT (ic));
3599 /* will try to generate an increment */
3600 /* if the right side is not a literal
3602 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3605 /* if the literal value of the right hand side
3606 is greater than 4 then it is not worth it */
3607 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3610 /* if decrement 16 bits in register */
3611 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3612 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3613 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3621 /* If the next instruction is a goto and the goto target
3622 * is <= 5 instructions previous to this, we can generate
3623 * jumps straight to that target.
3625 if (ic->next && ic->next->op == GOTO
3626 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3629 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3630 tlbl = IC_LABEL (ic->next);
3635 tlbl = newiTempLabel (NULL);
3639 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3640 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3641 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3642 IS_AOP_PREG (IC_RESULT (ic)))
3643 emitcode ("cjne", "%s,#0xff,%05d$"
3644 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3648 emitcode ("mov", "a,#0xff");
3649 emitcode ("cjne", "a,%s,%05d$"
3650 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3653 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3656 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3657 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3658 IS_AOP_PREG (IC_RESULT (ic)))
3659 emitcode ("cjne", "%s,#0xff,%05d$"
3660 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3664 emitcode ("cjne", "a,%s,%05d$"
3665 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3668 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3672 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3673 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3674 IS_AOP_PREG (IC_RESULT (ic)))
3675 emitcode ("cjne", "%s,#0xff,%05d$"
3676 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3680 emitcode ("cjne", "a,%s,%05d$"
3681 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3684 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3688 emitcode ("", "%05d$:", tlbl->key + 100);
3693 /* if the sizes are greater than 1 then we cannot */
3694 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3695 AOP_SIZE (IC_LEFT (ic)) > 1)
3698 /* we can if the aops of the left & result match or
3699 if they are in registers and the registers are the
3702 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3703 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3704 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3707 _startLazyDPSEvaluation ();
3710 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3712 _endLazyDPSEvaluation ();
3720 /*-----------------------------------------------------------------*/
3721 /* addSign - complete with sign */
3722 /*-----------------------------------------------------------------*/
3724 addSign (operand * result, int offset, int sign)
3726 int size = (getDataSize (result) - offset);
3729 _startLazyDPSEvaluation();
3732 emitcode ("rlc", "a");
3733 emitcode ("subb", "a,acc");
3736 aopPut (AOP (result), "a", offset++);
3743 aopPut (AOP (result), zero, offset++);
3746 _endLazyDPSEvaluation();
3750 /*-----------------------------------------------------------------*/
3751 /* genMinusBits - generates code for subtraction of two bits */
3752 /*-----------------------------------------------------------------*/
3754 genMinusBits (iCode * ic)
3756 symbol *lbl = newiTempLabel (NULL);
3758 D (emitcode (";", "genMinusBits "););
3760 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3762 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3763 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3764 emitcode ("cpl", "c");
3765 emitcode ("", "%05d$:", (lbl->key + 100));
3766 outBitC (IC_RESULT (ic));
3770 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3771 emitcode ("subb", "a,acc");
3772 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3773 emitcode ("inc", "a");
3774 emitcode ("", "%05d$:", (lbl->key + 100));
3775 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3776 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3780 /*-----------------------------------------------------------------*/
3781 /* genMinus - generates code for subtraction */
3782 /*-----------------------------------------------------------------*/
3784 genMinus (iCode * ic)
3786 int size, offset = 0;
3788 unsigned long lit = 0L;
3789 bool pushResult = FALSE;
3791 D (emitcode (";", "genMinus "););
3793 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3794 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3795 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3796 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3802 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3804 /* special cases :- */
3805 /* if both left & right are in bit space */
3806 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3807 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3813 /* if I can do an decrement instead
3814 of subtract then GOOD for ME */
3815 if (genMinusDec (ic) == TRUE)
3820 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3822 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3828 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3833 /* if literal, add a,#-lit, else normal subb */
3834 _startLazyDPSEvaluation ();
3837 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3838 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3839 emitcode ("subb", "a,%s",
3840 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3843 /* first add without previous c */
3845 emitcode ("add", "a,#0x%02x",
3846 (unsigned int) (lit & 0x0FFL));
3848 emitcode ("addc", "a,#0x%02x",
3849 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3854 emitcode ("push", "acc");
3858 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3862 _endLazyDPSEvaluation ();
3866 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3868 size = getDataSize (IC_LEFT (ic));
3869 rSize = getDataSize (IC_RESULT (ic));
3871 ADJUST_PUSHED_RESULT(size, rSize);
3873 _startLazyDPSEvaluation ();
3876 emitcode ("pop", "acc");
3877 aopPut (AOP (IC_RESULT (ic)), "a", size);
3879 _endLazyDPSEvaluation ();
3882 adjustArithmeticResult (ic);
3885 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3886 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3887 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3891 /*-----------------------------------------------------------------*/
3892 /* genMultbits :- multiplication of bits */
3893 /*-----------------------------------------------------------------*/
3895 genMultbits (operand * left,
3899 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3900 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3905 /*-----------------------------------------------------------------*/
3906 /* genMultOneByte : 8*8=8/16 bit multiplication */
3907 /*-----------------------------------------------------------------*/
3909 genMultOneByte (operand * left,
3913 sym_link *opetype = operandType (result);
3915 int size=AOP_SIZE(result);
3917 if (size<1 || size>2) {
3918 // this should never happen
3919 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3920 AOP_SIZE(result), __FILE__, lineno);
3924 /* (if two literals: the value is computed before) */
3925 /* if one literal, literal on the right */
3926 if (AOP_TYPE (left) == AOP_LIT)
3931 emitcode (";", "swapped left and right");
3934 if (SPEC_USIGN(opetype)
3935 // ignore the sign of left and right, what else can we do?
3936 || (SPEC_USIGN(operandType(left)) &&
3937 SPEC_USIGN(operandType(right)))) {
3938 // just an unsigned 8*8=8/16 multiply
3939 //emitcode (";","unsigned");
3940 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3941 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3942 emitcode ("mul", "ab");
3943 aopPut (AOP (result), "a", 0);
3945 aopPut (AOP (result), "b", 1);
3950 // we have to do a signed multiply
3952 emitcode (";", "signed");
3953 emitcode ("clr", "F0"); // reset sign flag
3954 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3956 lbl=newiTempLabel(NULL);
3957 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3958 // left side is negative, 8-bit two's complement, this fails for -128
3959 emitcode ("setb", "F0"); // set sign flag
3960 emitcode ("cpl", "a");
3961 emitcode ("inc", "a");
3963 emitcode ("", "%05d$:", lbl->key+100);
3966 if (AOP_TYPE(right)==AOP_LIT) {
3967 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3968 /* AND literal negative */
3969 if ((int) val < 0) {
3970 emitcode ("cpl", "F0"); // complement sign flag
3971 emitcode ("mov", "b,#0x%02x", -val);
3973 emitcode ("mov", "b,#0x%02x", val);
3976 lbl=newiTempLabel(NULL);
3977 emitcode ("mov", "b,a");
3978 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3979 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3980 // right side is negative, 8-bit two's complement
3981 emitcode ("cpl", "F0"); // complement sign flag
3982 emitcode ("cpl", "a");
3983 emitcode ("inc", "a");
3984 emitcode ("", "%05d$:", lbl->key+100);
3986 emitcode ("mul", "ab");
3988 lbl=newiTempLabel(NULL);
3989 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3990 // only ONE op was negative, we have to do a 8/16-bit two's complement
3991 emitcode ("cpl", "a"); // lsb
3993 emitcode ("inc", "a");
3995 emitcode ("add", "a,#1");
3996 emitcode ("xch", "a,b");
3997 emitcode ("cpl", "a"); // msb
3998 emitcode ("addc", "a,#0");
3999 emitcode ("xch", "a,b");
4002 emitcode ("", "%05d$:", lbl->key+100);
4003 aopPut (AOP (result), "a", 0);
4005 aopPut (AOP (result), "b", 1);
4009 /*-----------------------------------------------------------------*/
4010 /* genMult - generates code for multiplication */
4011 /*-----------------------------------------------------------------*/
4013 genMult (iCode * ic)
4015 operand *left = IC_LEFT (ic);
4016 operand *right = IC_RIGHT (ic);
4017 operand *result = IC_RESULT (ic);
4019 D (emitcode (";", "genMult "););
4021 /* assign the amsops */
4024 /* special cases first */
4026 if (AOP_TYPE (left) == AOP_CRY &&
4027 AOP_TYPE (right) == AOP_CRY)
4029 genMultbits (left, right, result);
4033 /* if both are of size == 1 */
4034 if (AOP_SIZE (left) == 1 &&
4035 AOP_SIZE (right) == 1)
4037 genMultOneByte (left, right, result);
4041 /* should have been converted to function call */
4045 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4046 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4047 freeAsmop (result, NULL, ic, TRUE);
4050 /*-----------------------------------------------------------------*/
4051 /* genDivbits :- division of bits */
4052 /*-----------------------------------------------------------------*/
4054 genDivbits (operand * left,
4061 /* the result must be bit */
4062 LOAD_AB_FOR_DIV (left, right, l);
4063 emitcode ("div", "ab");
4064 emitcode ("rrc", "a");
4065 aopPut (AOP (result), "c", 0);
4068 /*-----------------------------------------------------------------*/
4069 /* genDivOneByte : 8 bit division */
4070 /*-----------------------------------------------------------------*/
4072 genDivOneByte (operand * left,
4076 sym_link *opetype = operandType (result);
4081 size = AOP_SIZE (result) - 1;
4083 /* signed or unsigned */
4084 if (SPEC_USIGN (opetype))
4086 /* unsigned is easy */
4087 LOAD_AB_FOR_DIV (left, right, l);
4088 emitcode ("div", "ab");
4089 aopPut (AOP (result), "a", 0);
4091 aopPut (AOP (result), zero, offset++);
4095 /* signed is a little bit more difficult */
4097 /* save the signs of the operands */
4098 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4100 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4101 emitcode ("push", "acc"); /* save it on the stack */
4103 /* now sign adjust for both left & right */
4104 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4106 lbl = newiTempLabel (NULL);
4107 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4108 emitcode ("cpl", "a");
4109 emitcode ("inc", "a");
4110 emitcode ("", "%05d$:", (lbl->key + 100));
4111 emitcode ("mov", "b,a");
4113 /* sign adjust left side */
4114 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4117 lbl = newiTempLabel (NULL);
4118 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4119 emitcode ("cpl", "a");
4120 emitcode ("inc", "a");
4121 emitcode ("", "%05d$:", (lbl->key + 100));
4123 /* now the division */
4124 emitcode ("nop", "; workaround for DS80C390 div bug.");
4125 emitcode ("div", "ab");
4126 /* we are interested in the lower order
4128 emitcode ("mov", "b,a");
4129 lbl = newiTempLabel (NULL);
4130 emitcode ("pop", "acc");
4131 /* if there was an over flow we don't
4132 adjust the sign of the result */
4133 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4134 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4136 emitcode ("clr", "a");
4137 emitcode ("subb", "a,b");
4138 emitcode ("mov", "b,a");
4139 emitcode ("", "%05d$:", (lbl->key + 100));
4141 /* now we are done */
4142 aopPut (AOP (result), "b", 0);
4145 emitcode ("mov", "c,b.7");
4146 emitcode ("subb", "a,acc");
4149 aopPut (AOP (result), "a", offset++);
4153 /*-----------------------------------------------------------------*/
4154 /* genDiv - generates code for division */
4155 /*-----------------------------------------------------------------*/
4159 operand *left = IC_LEFT (ic);
4160 operand *right = IC_RIGHT (ic);
4161 operand *result = IC_RESULT (ic);
4163 D (emitcode (";", "genDiv ");
4166 /* assign the amsops */
4169 /* special cases first */
4171 if (AOP_TYPE (left) == AOP_CRY &&
4172 AOP_TYPE (right) == AOP_CRY)
4174 genDivbits (left, right, result);
4178 /* if both are of size == 1 */
4179 if (AOP_SIZE (left) == 1 &&
4180 AOP_SIZE (right) == 1)
4182 genDivOneByte (left, right, result);
4186 /* should have been converted to function call */
4189 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4190 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191 freeAsmop (result, NULL, ic, TRUE);
4194 /*-----------------------------------------------------------------*/
4195 /* genModbits :- modulus of bits */
4196 /*-----------------------------------------------------------------*/
4198 genModbits (operand * left,
4205 /* the result must be bit */
4206 LOAD_AB_FOR_DIV (left, right, l);
4207 emitcode ("div", "ab");
4208 emitcode ("mov", "a,b");
4209 emitcode ("rrc", "a");
4210 aopPut (AOP (result), "c", 0);
4213 /*-----------------------------------------------------------------*/
4214 /* genModOneByte : 8 bit modulus */
4215 /*-----------------------------------------------------------------*/
4217 genModOneByte (operand * left,
4221 sym_link *opetype = operandType (result);
4225 /* signed or unsigned */
4226 if (SPEC_USIGN (opetype))
4228 /* unsigned is easy */
4229 LOAD_AB_FOR_DIV (left, right, l);
4230 emitcode ("div", "ab");
4231 aopPut (AOP (result), "b", 0);
4235 /* signed is a little bit more difficult */
4237 /* save the signs of the operands */
4238 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4241 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4242 emitcode ("push", "acc"); /* save it on the stack */
4244 /* now sign adjust for both left & right */
4245 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4248 lbl = newiTempLabel (NULL);
4249 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4250 emitcode ("cpl", "a");
4251 emitcode ("inc", "a");
4252 emitcode ("", "%05d$:", (lbl->key + 100));
4253 emitcode ("mov", "b,a");
4255 /* sign adjust left side */
4256 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4259 lbl = newiTempLabel (NULL);
4260 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4261 emitcode ("cpl", "a");
4262 emitcode ("inc", "a");
4263 emitcode ("", "%05d$:", (lbl->key + 100));
4265 /* now the multiplication */
4266 emitcode ("nop", "; workaround for DS80C390 div bug.");
4267 emitcode ("div", "ab");
4268 /* we are interested in the lower order
4270 lbl = newiTempLabel (NULL);
4271 emitcode ("pop", "acc");
4272 /* if there was an over flow we don't
4273 adjust the sign of the result */
4274 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4275 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4277 emitcode ("clr", "a");
4278 emitcode ("subb", "a,b");
4279 emitcode ("mov", "b,a");
4280 emitcode ("", "%05d$:", (lbl->key + 100));
4282 /* now we are done */
4283 aopPut (AOP (result), "b", 0);
4287 /*-----------------------------------------------------------------*/
4288 /* genMod - generates code for division */
4289 /*-----------------------------------------------------------------*/
4293 operand *left = IC_LEFT (ic);
4294 operand *right = IC_RIGHT (ic);
4295 operand *result = IC_RESULT (ic);
4297 D (emitcode (";", "genMod ");
4300 /* assign the amsops */
4303 /* special cases first */
4305 if (AOP_TYPE (left) == AOP_CRY &&
4306 AOP_TYPE (right) == AOP_CRY)
4308 genModbits (left, right, result);
4312 /* if both are of size == 1 */
4313 if (AOP_SIZE (left) == 1 &&
4314 AOP_SIZE (right) == 1)
4316 genModOneByte (left, right, result);
4320 /* should have been converted to function call */
4324 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4325 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4326 freeAsmop (result, NULL, ic, TRUE);
4329 /*-----------------------------------------------------------------*/
4330 /* genIfxJump :- will create a jump depending on the ifx */
4331 /*-----------------------------------------------------------------*/
4333 genIfxJump (iCode * ic, char *jval)
4336 symbol *tlbl = newiTempLabel (NULL);
4339 D (emitcode (";", "genIfxJump ");
4342 /* if true label then we jump if condition
4346 jlbl = IC_TRUE (ic);
4347 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4348 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4352 /* false label is present */
4353 jlbl = IC_FALSE (ic);
4354 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4355 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4357 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4358 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4360 emitcode (inst, "%05d$", tlbl->key + 100);
4361 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4362 emitcode ("", "%05d$:", tlbl->key + 100);
4364 /* mark the icode as generated */
4368 /*-----------------------------------------------------------------*/
4369 /* genCmp :- greater or less than comparison */
4370 /*-----------------------------------------------------------------*/
4372 genCmp (operand * left, operand * right,
4373 iCode * ic, iCode * ifx, int sign)
4375 int size, offset = 0;
4376 unsigned long lit = 0L;
4379 D (emitcode (";", "genCmp");
4382 result = IC_RESULT (ic);
4384 /* if left & right are bit variables */
4385 if (AOP_TYPE (left) == AOP_CRY &&
4386 AOP_TYPE (right) == AOP_CRY)
4388 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4389 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4393 /* subtract right from left if at the
4394 end the carry flag is set then we know that
4395 left is greater than right */
4396 size = max (AOP_SIZE (left), AOP_SIZE (right));
4398 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4399 if ((size == 1) && !sign &&
4400 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4402 symbol *lbl = newiTempLabel (NULL);
4403 emitcode ("cjne", "%s,%s,%05d$",
4404 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4405 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4407 emitcode ("", "%05d$:", lbl->key + 100);
4411 if (AOP_TYPE (right) == AOP_LIT)
4413 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4414 /* optimize if(x < 0) or if(x >= 0) */
4423 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4425 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4426 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428 aopOp (result, ic, FALSE, FALSE);
4430 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4432 freeAsmop (result, NULL, ic, TRUE);
4433 genIfxJump (ifx, "acc.7");
4438 emitcode ("rlc", "a");
4440 goto release_freedLR;
4448 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4449 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4450 emitcode (";", "genCmp #2");
4451 if (sign && (size == 0))
4453 emitcode (";", "genCmp #3");
4454 emitcode ("xrl", "a,#0x80");
4455 if (AOP_TYPE (right) == AOP_LIT)
4457 unsigned long lit = (unsigned long)
4458 floatFromVal (AOP (right)->aopu.aop_lit);
4459 emitcode (";", "genCmp #3.1");
4460 emitcode ("subb", "a,#0x%02x",
4461 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4465 emitcode (";", "genCmp #3.2");
4466 if (AOP_NEEDSACC (right))
4468 emitcode ("push", "acc");
4470 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4471 FALSE, FALSE, FALSE));
4472 emitcode ("xrl", "b,#0x80");
4473 if (AOP_NEEDSACC (right))
4475 emitcode ("pop", "acc");
4477 emitcode ("subb", "a,b");
4484 emitcode (";", "genCmp #4");
4485 if (AOP_NEEDSACC (right))
4488 emitcode (";", "genCmp #4.1");
4489 emitcode ("xch", "a, b");
4490 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4491 emitcode ("xch", "a, b");
4496 emitcode (";", "genCmp #4.2");
4497 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4500 emitcode ("subb", "a,%s", s);
4507 /* Don't need the left & right operands any more; do need the result. */
4508 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4509 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4511 aopOp (result, ic, FALSE, FALSE);
4515 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4521 /* if the result is used in the next
4522 ifx conditional branch then generate
4523 code a little differently */
4526 genIfxJump (ifx, "c");
4532 /* leave the result in acc */
4534 freeAsmop (result, NULL, ic, TRUE);
4537 /*-----------------------------------------------------------------*/
4538 /* genCmpGt :- greater than comparison */
4539 /*-----------------------------------------------------------------*/
4541 genCmpGt (iCode * ic, iCode * ifx)
4543 operand *left, *right;
4544 sym_link *letype, *retype;
4547 D (emitcode (";", "genCmpGt ");
4550 left = IC_LEFT (ic);
4551 right = IC_RIGHT (ic);
4553 letype = getSpec (operandType (left));
4554 retype = getSpec (operandType (right));
4555 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4557 /* assign the left & right amsops */
4560 genCmp (right, left, ic, ifx, sign);
4563 /*-----------------------------------------------------------------*/
4564 /* genCmpLt - less than comparisons */
4565 /*-----------------------------------------------------------------*/
4567 genCmpLt (iCode * ic, iCode * ifx)
4569 operand *left, *right;
4570 sym_link *letype, *retype;
4573 D (emitcode (";", "genCmpLt "););
4575 left = IC_LEFT (ic);
4576 right = IC_RIGHT (ic);
4578 letype = getSpec (operandType (left));
4579 retype = getSpec (operandType (right));
4580 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4582 /* assign the left & right amsops */
4585 genCmp (left, right, ic, ifx, sign);
4588 /*-----------------------------------------------------------------*/
4589 /* gencjneshort - compare and jump if not equal */
4590 /*-----------------------------------------------------------------*/
4592 gencjneshort (operand * left, operand * right, symbol * lbl)
4594 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4596 unsigned long lit = 0L;
4598 D (emitcode (";", "gencjneshort");
4601 /* if the left side is a literal or
4602 if the right is in a pointer register and left
4604 if ((AOP_TYPE (left) == AOP_LIT) ||
4605 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4612 if (AOP_TYPE (right) == AOP_LIT)
4613 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4615 if (opIsGptr (left) || opIsGptr (right))
4617 /* We are comparing a generic pointer to something.
4618 * Exclude the generic type byte from the comparison.
4621 D (emitcode (";", "cjneshort: generic ptr special case.");
4626 /* if the right side is a literal then anything goes */
4627 if (AOP_TYPE (right) == AOP_LIT &&
4628 AOP_TYPE (left) != AOP_DIR)
4632 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4634 emitcode ("cjne", "a,%s,%05d$",
4635 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4641 /* if the right side is in a register or in direct space or
4642 if the left is a pointer register & right is not */
4643 else if (AOP_TYPE (right) == AOP_REG ||
4644 AOP_TYPE (right) == AOP_DIR ||
4645 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4646 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4650 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4651 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4652 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4653 emitcode ("jnz", "%05d$", lbl->key + 100);
4655 emitcode ("cjne", "a,%s,%05d$",
4656 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4663 /* right is a pointer reg need both a & b */
4666 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4667 if (strcmp (l, "b"))
4668 emitcode ("mov", "b,%s", l);
4669 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4670 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4676 /*-----------------------------------------------------------------*/
4677 /* gencjne - compare and jump if not equal */
4678 /*-----------------------------------------------------------------*/
4680 gencjne (operand * left, operand * right, symbol * lbl)
4682 symbol *tlbl = newiTempLabel (NULL);
4684 D (emitcode (";", "gencjne");
4687 gencjneshort (left, right, lbl);
4689 emitcode ("mov", "a,%s", one);
4690 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4691 emitcode ("", "%05d$:", lbl->key + 100);
4692 emitcode ("clr", "a");
4693 emitcode ("", "%05d$:", tlbl->key + 100);
4696 /*-----------------------------------------------------------------*/
4697 /* genCmpEq - generates code for equal to */
4698 /*-----------------------------------------------------------------*/
4700 genCmpEq (iCode * ic, iCode * ifx)
4702 operand *left, *right, *result;
4704 D (emitcode (";", "genCmpEq ");
4708 AOP_SET_LOCALS (ic);
4710 /* if literal, literal on the right or
4711 if the right is in a pointer register and left
4713 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4714 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4716 operand *t = IC_RIGHT (ic);
4717 IC_RIGHT (ic) = IC_LEFT (ic);
4721 if (ifx && /* !AOP_SIZE(result) */
4722 OP_SYMBOL (result) &&
4723 OP_SYMBOL (result)->regType == REG_CND)
4726 /* if they are both bit variables */
4727 if (AOP_TYPE (left) == AOP_CRY &&
4728 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4730 if (AOP_TYPE (right) == AOP_LIT)
4732 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4735 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4736 emitcode ("cpl", "c");
4740 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4744 emitcode ("clr", "c");
4746 /* AOP_TYPE(right) == AOP_CRY */
4750 symbol *lbl = newiTempLabel (NULL);
4751 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4752 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4753 emitcode ("cpl", "c");
4754 emitcode ("", "%05d$:", (lbl->key + 100));
4756 /* if true label then we jump if condition
4758 tlbl = newiTempLabel (NULL);
4761 emitcode ("jnc", "%05d$", tlbl->key + 100);
4762 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4766 emitcode ("jc", "%05d$", tlbl->key + 100);
4767 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4769 emitcode ("", "%05d$:", tlbl->key + 100);
4773 tlbl = newiTempLabel (NULL);
4774 gencjneshort (left, right, tlbl);
4777 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4778 emitcode ("", "%05d$:", tlbl->key + 100);
4782 symbol *lbl = newiTempLabel (NULL);
4783 emitcode ("sjmp", "%05d$", lbl->key + 100);
4784 emitcode ("", "%05d$:", tlbl->key + 100);
4785 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4786 emitcode ("", "%05d$:", lbl->key + 100);
4789 /* mark the icode as generated */
4792 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4793 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4797 /* if they are both bit variables */
4798 if (AOP_TYPE (left) == AOP_CRY &&
4799 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4801 if (AOP_TYPE (right) == AOP_LIT)
4803 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4806 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4807 emitcode ("cpl", "c");
4811 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4815 emitcode ("clr", "c");
4817 /* AOP_TYPE(right) == AOP_CRY */
4821 symbol *lbl = newiTempLabel (NULL);
4822 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4823 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4824 emitcode ("cpl", "c");
4825 emitcode ("", "%05d$:", (lbl->key + 100));
4828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4831 aopOp (result, ic, TRUE, FALSE);
4834 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4841 genIfxJump (ifx, "c");
4844 /* if the result is used in an arithmetic operation
4845 then put the result in place */
4850 gencjne (left, right, newiTempLabel (NULL));
4852 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4855 aopOp (result, ic, TRUE, FALSE);
4857 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4859 aopPut (AOP (result), "a", 0);
4864 genIfxJump (ifx, "a");
4867 /* if the result is used in an arithmetic operation
4868 then put the result in place */
4869 if (AOP_TYPE (result) != AOP_CRY)
4871 /* leave the result in acc */
4875 freeAsmop (result, NULL, ic, TRUE);
4878 /*-----------------------------------------------------------------*/
4879 /* ifxForOp - returns the icode containing the ifx for operand */
4880 /*-----------------------------------------------------------------*/
4882 ifxForOp (operand * op, iCode * ic)
4884 /* if true symbol then needs to be assigned */
4885 if (IS_TRUE_SYMOP (op))
4888 /* if this has register type condition and
4889 the next instruction is ifx with the same operand
4890 and live to of the operand is upto the ifx only then */
4892 ic->next->op == IFX &&
4893 IC_COND (ic->next)->key == op->key &&
4894 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4899 /*-----------------------------------------------------------------*/
4900 /* genAndOp - for && operation */
4901 /*-----------------------------------------------------------------*/
4903 genAndOp (iCode * ic)
4905 operand *left, *right, *result;
4908 D (emitcode (";", "genAndOp "););
4910 /* note here that && operations that are in an
4911 if statement are taken away by backPatchLabels
4912 only those used in arthmetic operations remain */
4914 AOP_SET_LOCALS (ic);
4916 /* if both are bit variables */
4917 if (AOP_TYPE (left) == AOP_CRY &&
4918 AOP_TYPE (right) == AOP_CRY)
4920 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4921 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4922 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4923 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 aopOp (result,ic,FALSE, FALSE);
4930 tlbl = newiTempLabel (NULL);
4932 emitcode ("jz", "%05d$", tlbl->key + 100);
4934 emitcode ("", "%05d$:", tlbl->key + 100);
4935 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 aopOp (result,ic,FALSE, FALSE);
4941 freeAsmop (result, NULL, ic, TRUE);
4945 /*-----------------------------------------------------------------*/
4946 /* genOrOp - for || operation */
4947 /*-----------------------------------------------------------------*/
4949 genOrOp (iCode * ic)
4951 operand *left, *right, *result;
4954 D (emitcode (";", "genOrOp "););
4956 /* note here that || operations that are in an
4957 if statement are taken away by backPatchLabels
4958 only those used in arthmetic operations remain */
4960 AOP_SET_LOCALS (ic);
4962 /* if both are bit variables */
4963 if (AOP_TYPE (left) == AOP_CRY &&
4964 AOP_TYPE (right) == AOP_CRY)
4966 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4967 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4968 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4969 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4971 aopOp (result,ic,FALSE, FALSE);
4977 tlbl = newiTempLabel (NULL);
4979 emitcode ("jnz", "%05d$", tlbl->key + 100);
4981 emitcode ("", "%05d$:", tlbl->key + 100);
4982 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4983 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4985 aopOp (result,ic,FALSE, FALSE);
4990 freeAsmop (result, NULL, ic, TRUE);
4993 /*-----------------------------------------------------------------*/
4994 /* isLiteralBit - test if lit == 2^n */
4995 /*-----------------------------------------------------------------*/
4997 isLiteralBit (unsigned long lit)
4999 unsigned long pw[32] =
5000 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5001 0x100L, 0x200L, 0x400L, 0x800L,
5002 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5003 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5004 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5005 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5006 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5009 for (idx = 0; idx < 32; idx++)
5015 /*-----------------------------------------------------------------*/
5016 /* continueIfTrue - */
5017 /*-----------------------------------------------------------------*/
5019 continueIfTrue (iCode * ic)
5022 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5026 /*-----------------------------------------------------------------*/
5028 /*-----------------------------------------------------------------*/
5030 jumpIfTrue (iCode * ic)
5033 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5037 /*-----------------------------------------------------------------*/
5038 /* jmpTrueOrFalse - */
5039 /*-----------------------------------------------------------------*/
5041 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5043 // ugly but optimized by peephole
5046 symbol *nlbl = newiTempLabel (NULL);
5047 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5048 emitcode ("", "%05d$:", tlbl->key + 100);
5049 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5050 emitcode ("", "%05d$:", nlbl->key + 100);
5054 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5055 emitcode ("", "%05d$:", tlbl->key + 100);
5060 // Generate code to perform a bit-wise logic operation
5061 // on two operands in far space (assumed to already have been
5062 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5063 // in far space. This requires pushing the result on the stack
5064 // then popping it into the result.
5066 genFarFarLogicOp(iCode *ic, char *logicOp)
5068 int size, resultSize, compSize;
5071 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5072 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5073 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5075 _startLazyDPSEvaluation();
5076 for (size = compSize; (size--); offset++)
5078 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5079 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5080 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5082 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5083 emitcode ("push", "acc");
5085 _endLazyDPSEvaluation();
5087 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5088 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5089 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5091 resultSize = AOP_SIZE(IC_RESULT(ic));
5093 ADJUST_PUSHED_RESULT(compSize, resultSize);
5095 _startLazyDPSEvaluation();
5098 emitcode ("pop", "acc");
5099 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5101 _endLazyDPSEvaluation();
5102 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5106 /*-----------------------------------------------------------------*/
5107 /* genAnd - code for and */
5108 /*-----------------------------------------------------------------*/
5110 genAnd (iCode * ic, iCode * ifx)
5112 operand *left, *right, *result;
5113 int size, offset = 0;
5114 unsigned long lit = 0L;
5119 D (emitcode (";", "genAnd "););
5121 AOP_OP_3_NOFATAL (ic, pushResult);
5122 AOP_SET_LOCALS (ic);
5126 genFarFarLogicOp(ic, "anl");
5131 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5133 AOP_TYPE (left), AOP_TYPE (right));
5134 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5136 AOP_SIZE (left), AOP_SIZE (right));
5139 /* if left is a literal & right is not then exchange them */
5140 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5141 AOP_NEEDSACC (left))
5143 operand *tmp = right;
5148 /* if result = right then exchange them */
5149 if (sameRegs (AOP (result), AOP (right)))
5151 operand *tmp = right;
5156 /* if right is bit then exchange them */
5157 if (AOP_TYPE (right) == AOP_CRY &&
5158 AOP_TYPE (left) != AOP_CRY)
5160 operand *tmp = right;
5164 if (AOP_TYPE (right) == AOP_LIT)
5165 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5167 size = AOP_SIZE (result);
5170 // result = bit & yy;
5171 if (AOP_TYPE (left) == AOP_CRY)
5173 // c = bit & literal;
5174 if (AOP_TYPE (right) == AOP_LIT)
5178 if (size && sameRegs (AOP (result), AOP (left)))
5181 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5186 if (size && (AOP_TYPE (result) == AOP_CRY))
5188 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5191 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5196 emitcode ("clr", "c");
5201 if (AOP_TYPE (right) == AOP_CRY)
5204 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5205 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5210 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5212 emitcode ("rrc", "a");
5213 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5221 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5222 genIfxJump (ifx, "c");
5226 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5227 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5228 if ((AOP_TYPE (right) == AOP_LIT) &&
5229 (AOP_TYPE (result) == AOP_CRY) &&
5230 (AOP_TYPE (left) != AOP_CRY))
5232 int posbit = isLiteralBit (lit);
5237 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5240 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5246 sprintf (buffer, "acc.%d", posbit & 0x07);
5247 genIfxJump (ifx, buffer);
5254 symbol *tlbl = newiTempLabel (NULL);
5255 int sizel = AOP_SIZE (left);
5257 emitcode ("setb", "c");
5260 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5262 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5264 if ((posbit = isLiteralBit (bytelit)) != 0)
5265 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5268 if (bytelit != 0x0FFL)
5269 emitcode ("anl", "a,%s",
5270 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5271 emitcode ("jnz", "%05d$", tlbl->key + 100);
5276 // bit = left & literal
5279 emitcode ("clr", "c");
5280 emitcode ("", "%05d$:", tlbl->key + 100);
5282 // if(left & literal)
5286 jmpTrueOrFalse (ifx, tlbl);
5294 /* if left is same as result */
5295 if (sameRegs (AOP (result), AOP (left)))
5297 for (; size--; offset++)
5299 if (AOP_TYPE (right) == AOP_LIT)
5301 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5303 else if (bytelit == 0)
5304 aopPut (AOP (result), zero, offset);
5305 else if (IS_AOP_PREG (result))
5307 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5308 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5309 aopPut (AOP (result), "a", offset);
5312 emitcode ("anl", "%s,%s",
5313 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5314 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5318 if (AOP_TYPE (left) == AOP_ACC)
5319 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5322 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5323 if (IS_AOP_PREG (result))
5325 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5326 aopPut (AOP (result), "a", offset);
5330 emitcode ("anl", "%s,a",
5331 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5338 // left & result in different registers
5339 if (AOP_TYPE (result) == AOP_CRY)
5342 // if(size), result in bit
5343 // if(!size && ifx), conditional oper: if(left & right)
5344 symbol *tlbl = newiTempLabel (NULL);
5345 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5347 emitcode ("setb", "c");
5350 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5351 emitcode ("anl", "a,%s",
5352 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5354 if (AOP_TYPE(left)==AOP_ACC) {
5355 emitcode("mov", "b,a");
5356 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5357 emitcode("anl", "a,b");
5359 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5360 emitcode ("anl", "a,%s",
5361 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5364 emitcode ("jnz", "%05d$", tlbl->key + 100);
5370 emitcode ("", "%05d$:", tlbl->key + 100);
5374 jmpTrueOrFalse (ifx, tlbl);
5378 for (; (size--); offset++)
5381 // result = left & right
5382 if (AOP_TYPE (right) == AOP_LIT)
5384 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5386 aopPut (AOP (result),
5387 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5391 else if (bytelit == 0)
5393 aopPut (AOP (result), zero, offset);
5396 D (emitcode (";", "better literal AND.");
5398 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5399 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5400 FALSE, FALSE, FALSE));
5405 // faster than result <- left, anl result,right
5406 // and better if result is SFR
5407 if (AOP_TYPE (left) == AOP_ACC)
5409 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5410 FALSE, FALSE, FALSE));
5414 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5415 emitcode ("anl", "a,%s",
5416 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5419 aopPut (AOP (result), "a", offset);
5425 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5426 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5427 freeAsmop (result, NULL, ic, TRUE);
5431 /*-----------------------------------------------------------------*/
5432 /* genOr - code for or */
5433 /*-----------------------------------------------------------------*/
5435 genOr (iCode * ic, iCode * ifx)
5437 operand *left, *right, *result;
5438 int size, offset = 0;
5439 unsigned long lit = 0L;
5442 D (emitcode (";", "genOr "););
5444 AOP_OP_3_NOFATAL (ic, pushResult);
5445 AOP_SET_LOCALS (ic);
5449 genFarFarLogicOp(ic, "orl");
5455 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5457 AOP_TYPE (left), AOP_TYPE (right));
5458 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5460 AOP_SIZE (left), AOP_SIZE (right));
5463 /* if left is a literal & right is not then exchange them */
5464 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5465 AOP_NEEDSACC (left))
5467 operand *tmp = right;
5472 /* if result = right then exchange them */
5473 if (sameRegs (AOP (result), AOP (right)))
5475 operand *tmp = right;
5480 /* if right is bit then exchange them */
5481 if (AOP_TYPE (right) == AOP_CRY &&
5482 AOP_TYPE (left) != AOP_CRY)
5484 operand *tmp = right;
5488 if (AOP_TYPE (right) == AOP_LIT)
5489 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5491 size = AOP_SIZE (result);
5495 if (AOP_TYPE (left) == AOP_CRY)
5497 if (AOP_TYPE (right) == AOP_LIT)
5499 // c = bit & literal;
5502 // lit != 0 => result = 1
5503 if (AOP_TYPE (result) == AOP_CRY)
5506 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5508 continueIfTrue (ifx);
5511 emitcode ("setb", "c");
5515 // lit == 0 => result = left
5516 if (size && sameRegs (AOP (result), AOP (left)))
5518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5523 if (AOP_TYPE (right) == AOP_CRY)
5526 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5527 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5532 symbol *tlbl = newiTempLabel (NULL);
5533 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5534 emitcode ("setb", "c");
5535 emitcode ("jb", "%s,%05d$",
5536 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5538 emitcode ("jnz", "%05d$", tlbl->key + 100);
5539 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5541 jmpTrueOrFalse (ifx, tlbl);
5547 emitcode ("", "%05d$:", tlbl->key + 100);
5556 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5557 genIfxJump (ifx, "c");
5561 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5562 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5563 if ((AOP_TYPE (right) == AOP_LIT) &&
5564 (AOP_TYPE (result) == AOP_CRY) &&
5565 (AOP_TYPE (left) != AOP_CRY))
5571 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5573 continueIfTrue (ifx);
5578 // lit = 0, result = boolean(left)
5580 emitcode ("setb", "c");
5584 symbol *tlbl = newiTempLabel (NULL);
5585 emitcode ("jnz", "%05d$", tlbl->key + 100);
5587 emitcode ("", "%05d$:", tlbl->key + 100);
5591 genIfxJump (ifx, "a");
5599 /* if left is same as result */
5600 if (sameRegs (AOP (result), AOP (left)))
5602 for (; size--; offset++)
5604 if (AOP_TYPE (right) == AOP_LIT)
5606 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5612 if (IS_AOP_PREG (left))
5614 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5615 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5616 aopPut (AOP (result), "a", offset);
5620 emitcode ("orl", "%s,%s",
5621 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5622 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5628 if (AOP_TYPE (left) == AOP_ACC)
5630 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5634 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5635 if (IS_AOP_PREG (left))
5637 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5638 aopPut (AOP (result), "a", offset);
5642 emitcode ("orl", "%s,a",
5643 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5651 // left & result in different registers
5652 if (AOP_TYPE (result) == AOP_CRY)
5655 // if(size), result in bit
5656 // if(!size && ifx), conditional oper: if(left | right)
5657 symbol *tlbl = newiTempLabel (NULL);
5658 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5660 emitcode ("setb", "c");
5663 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5664 emitcode ("orl", "a,%s",
5665 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5667 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5668 emitcode ("orl", "a,%s",
5669 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5671 emitcode ("jnz", "%05d$", tlbl->key + 100);
5677 emitcode ("", "%05d$:", tlbl->key + 100);
5681 jmpTrueOrFalse (ifx, tlbl);
5685 for (; (size--); offset++)
5688 // result = left & right
5689 if (AOP_TYPE (right) == AOP_LIT)
5691 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5693 aopPut (AOP (result),
5694 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5698 D (emitcode (";", "better literal OR.");
5700 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5701 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5702 FALSE, FALSE, FALSE));
5707 // faster than result <- left, anl result,right
5708 // and better if result is SFR
5709 if (AOP_TYPE (left) == AOP_ACC)
5711 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5712 FALSE, FALSE, FALSE));
5716 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5717 emitcode ("orl", "a,%s",
5718 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5721 aopPut (AOP (result), "a", offset);
5727 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5728 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5729 freeAsmop (result, NULL, ic, TRUE);
5732 /*-----------------------------------------------------------------*/
5733 /* genXor - code for xclusive or */
5734 /*-----------------------------------------------------------------*/
5736 genXor (iCode * ic, iCode * ifx)
5738 operand *left, *right, *result;
5739 int size, offset = 0;
5740 unsigned long lit = 0L;
5743 D (emitcode (";", "genXor "););
5745 AOP_OP_3_NOFATAL (ic, pushResult);
5746 AOP_SET_LOCALS (ic);
5750 genFarFarLogicOp(ic, "xrl");
5755 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5757 AOP_TYPE (left), AOP_TYPE (right));
5758 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5760 AOP_SIZE (left), AOP_SIZE (right));
5763 /* if left is a literal & right is not ||
5764 if left needs acc & right does not */
5765 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5766 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5768 operand *tmp = right;
5773 /* if result = right then exchange them */
5774 if (sameRegs (AOP (result), AOP (right)))
5776 operand *tmp = right;
5781 /* if right is bit then exchange them */
5782 if (AOP_TYPE (right) == AOP_CRY &&
5783 AOP_TYPE (left) != AOP_CRY)
5785 operand *tmp = right;
5789 if (AOP_TYPE (right) == AOP_LIT)
5790 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5792 size = AOP_SIZE (result);
5796 if (AOP_TYPE (left) == AOP_CRY)
5798 if (AOP_TYPE (right) == AOP_LIT)
5800 // c = bit & literal;
5803 // lit>>1 != 0 => result = 1
5804 if (AOP_TYPE (result) == AOP_CRY)
5807 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5809 continueIfTrue (ifx);
5812 emitcode ("setb", "c");
5819 // lit == 0, result = left
5820 if (size && sameRegs (AOP (result), AOP (left)))
5822 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5826 // lit == 1, result = not(left)
5827 if (size && sameRegs (AOP (result), AOP (left)))
5829 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5834 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5835 emitcode ("cpl", "c");
5844 symbol *tlbl = newiTempLabel (NULL);
5845 if (AOP_TYPE (right) == AOP_CRY)
5848 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5852 int sizer = AOP_SIZE (right);
5854 // if val>>1 != 0, result = 1
5855 emitcode ("setb", "c");
5858 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5860 // test the msb of the lsb
5861 emitcode ("anl", "a,#0xfe");
5862 emitcode ("jnz", "%05d$", tlbl->key + 100);
5866 emitcode ("rrc", "a");
5868 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5869 emitcode ("cpl", "c");
5870 emitcode ("", "%05d$:", (tlbl->key + 100));
5877 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5878 genIfxJump (ifx, "c");
5882 if (sameRegs (AOP (result), AOP (left)))
5884 /* if left is same as result */
5885 for (; size--; offset++)
5887 if (AOP_TYPE (right) == AOP_LIT)
5889 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5891 else if (IS_AOP_PREG (left))
5893 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5894 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5895 aopPut (AOP (result), "a", offset);
5898 emitcode ("xrl", "%s,%s",
5899 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5900 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5904 if (AOP_TYPE (left) == AOP_ACC)
5905 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5908 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5909 if (IS_AOP_PREG (left))
5911 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5912 aopPut (AOP (result), "a", offset);
5915 emitcode ("xrl", "%s,a",
5916 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5923 // left & result in different registers
5924 if (AOP_TYPE (result) == AOP_CRY)
5927 // if(size), result in bit
5928 // if(!size && ifx), conditional oper: if(left ^ right)
5929 symbol *tlbl = newiTempLabel (NULL);
5930 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5932 emitcode ("setb", "c");
5935 if ((AOP_TYPE (right) == AOP_LIT) &&
5936 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5938 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5942 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5943 emitcode ("xrl", "a,%s",
5944 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5946 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5947 emitcode ("xrl", "a,%s",
5948 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5951 emitcode ("jnz", "%05d$", tlbl->key + 100);
5957 emitcode ("", "%05d$:", tlbl->key + 100);
5961 jmpTrueOrFalse (ifx, tlbl);
5964 for (; (size--); offset++)
5967 // result = left & right
5968 if (AOP_TYPE (right) == AOP_LIT)
5970 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5972 aopPut (AOP (result),
5973 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5977 D (emitcode (";", "better literal XOR.");
5979 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5980 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5981 FALSE, FALSE, FALSE));
5985 // faster than result <- left, anl result,right
5986 // and better if result is SFR
5987 if (AOP_TYPE (left) == AOP_ACC)
5989 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5990 FALSE, FALSE, FALSE));
5994 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5995 emitcode ("xrl", "a,%s",
5996 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5999 aopPut (AOP (result), "a", offset);
6004 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6005 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6006 freeAsmop (result, NULL, ic, TRUE);
6009 /*-----------------------------------------------------------------*/
6010 /* genInline - write the inline code out */
6011 /*-----------------------------------------------------------------*/
6013 genInline (iCode * ic)
6015 char *buffer, *bp, *bp1;
6017 D (emitcode (";", "genInline ");
6020 _G.inLine += (!options.asmpeep);
6022 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6023 strcpy (buffer, IC_INLINE (ic));
6025 /* emit each line as a code */
6050 /* emitcode("",buffer); */
6051 _G.inLine -= (!options.asmpeep);
6054 /*-----------------------------------------------------------------*/
6055 /* genRRC - rotate right with carry */
6056 /*-----------------------------------------------------------------*/
6060 operand *left, *result;
6061 int size, offset = 0;
6064 D (emitcode (";", "genRRC ");
6067 /* rotate right with carry */
6068 left = IC_LEFT (ic);
6069 result = IC_RESULT (ic);
6070 aopOp (left, ic, FALSE, FALSE);
6071 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6073 /* move it to the result */
6074 size = AOP_SIZE (result);
6078 _startLazyDPSEvaluation ();
6081 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6083 emitcode ("rrc", "a");
6084 if (AOP_SIZE (result) > 1)
6085 aopPut (AOP (result), "a", offset--);
6087 _endLazyDPSEvaluation ();
6089 /* now we need to put the carry into the
6090 highest order byte of the result */
6091 if (AOP_SIZE (result) > 1)
6093 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6096 emitcode ("mov", "acc.7,c");
6097 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6098 freeAsmop (left, NULL, ic, TRUE);
6099 freeAsmop (result, NULL, ic, TRUE);
6102 /*-----------------------------------------------------------------*/
6103 /* genRLC - generate code for rotate left with carry */
6104 /*-----------------------------------------------------------------*/
6108 operand *left, *result;
6109 int size, offset = 0;
6112 D (emitcode (";", "genRLC ");
6115 /* rotate right with carry */
6116 left = IC_LEFT (ic);
6117 result = IC_RESULT (ic);
6118 aopOp (left, ic, FALSE, FALSE);
6119 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6121 /* move it to the result */
6122 size = AOP_SIZE (result);
6126 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6128 emitcode ("add", "a,acc");
6129 if (AOP_SIZE (result) > 1)
6131 aopPut (AOP (result), "a", offset++);
6134 _startLazyDPSEvaluation ();
6137 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6139 emitcode ("rlc", "a");
6140 if (AOP_SIZE (result) > 1)
6141 aopPut (AOP (result), "a", offset++);
6143 _endLazyDPSEvaluation ();
6145 /* now we need to put the carry into the
6146 highest order byte of the result */
6147 if (AOP_SIZE (result) > 1)
6149 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6152 emitcode ("mov", "acc.0,c");
6153 aopPut (AOP (result), "a", 0);
6154 freeAsmop (left, NULL, ic, TRUE);
6155 freeAsmop (result, NULL, ic, TRUE);
6158 /*-----------------------------------------------------------------*/
6159 /* genGetHbit - generates code get highest order bit */
6160 /*-----------------------------------------------------------------*/
6162 genGetHbit (iCode * ic)
6164 operand *left, *result;
6165 left = IC_LEFT (ic);
6166 result = IC_RESULT (ic);
6167 aopOp (left, ic, FALSE, FALSE);
6168 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6170 D (emitcode (";", "genGetHbit ");
6173 /* get the highest order byte into a */
6174 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6175 if (AOP_TYPE (result) == AOP_CRY)
6177 emitcode ("rlc", "a");
6182 emitcode ("rl", "a");
6183 emitcode ("anl", "a,#0x01");
6188 freeAsmop (left, NULL, ic, TRUE);
6189 freeAsmop (result, NULL, ic, TRUE);
6192 /*-----------------------------------------------------------------*/
6193 /* AccRol - rotate left accumulator by known count */
6194 /*-----------------------------------------------------------------*/
6196 AccRol (int shCount)
6198 shCount &= 0x0007; // shCount : 0..7
6205 emitcode ("rl", "a");
6208 emitcode ("rl", "a");
6209 emitcode ("rl", "a");
6212 emitcode ("swap", "a");
6213 emitcode ("rr", "a");
6216 emitcode ("swap", "a");
6219 emitcode ("swap", "a");
6220 emitcode ("rl", "a");
6223 emitcode ("rr", "a");
6224 emitcode ("rr", "a");
6227 emitcode ("rr", "a");
6232 /*-----------------------------------------------------------------*/
6233 /* AccLsh - left shift accumulator by known count */
6234 /*-----------------------------------------------------------------*/
6236 AccLsh (int shCount)
6241 emitcode ("add", "a,acc");
6242 else if (shCount == 2)
6244 emitcode ("add", "a,acc");
6245 emitcode ("add", "a,acc");
6249 /* rotate left accumulator */
6251 /* and kill the lower order bits */
6252 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6257 /*-----------------------------------------------------------------*/
6258 /* AccRsh - right shift accumulator by known count */
6259 /*-----------------------------------------------------------------*/
6261 AccRsh (int shCount)
6268 emitcode ("rrc", "a");
6272 /* rotate right accumulator */
6273 AccRol (8 - shCount);
6274 /* and kill the higher order bits */
6275 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6280 #ifdef BETTER_LITERAL_SHIFT
6281 /*-----------------------------------------------------------------*/
6282 /* AccSRsh - signed right shift accumulator by known count */
6283 /*-----------------------------------------------------------------*/
6285 AccSRsh (int shCount)
6292 emitcode ("mov", "c,acc.7");
6293 emitcode ("rrc", "a");
6295 else if (shCount == 2)
6297 emitcode ("mov", "c,acc.7");
6298 emitcode ("rrc", "a");
6299 emitcode ("mov", "c,acc.7");
6300 emitcode ("rrc", "a");
6304 tlbl = newiTempLabel (NULL);
6305 /* rotate right accumulator */
6306 AccRol (8 - shCount);
6307 /* and kill the higher order bits */
6308 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6309 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6310 emitcode ("orl", "a,#0x%02x",
6311 (unsigned char) ~SRMask[shCount]);
6312 emitcode ("", "%05d$:", tlbl->key + 100);
6318 #ifdef BETTER_LITERAL_SHIFT
6319 /*-----------------------------------------------------------------*/
6320 /* shiftR1Left2Result - shift right one byte from left to result */
6321 /*-----------------------------------------------------------------*/
6323 shiftR1Left2Result (operand * left, int offl,
6324 operand * result, int offr,
6325 int shCount, int sign)
6327 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6328 /* shift right accumulator */
6333 aopPut (AOP (result), "a", offr);
6337 #ifdef BETTER_LITERAL_SHIFT
6338 /*-----------------------------------------------------------------*/
6339 /* shiftL1Left2Result - shift left one byte from left to result */
6340 /*-----------------------------------------------------------------*/
6342 shiftL1Left2Result (operand * left, int offl,
6343 operand * result, int offr, int shCount)
6345 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6346 /* shift left accumulator */
6348 aopPut (AOP (result), "a", offr);
6352 #ifdef BETTER_LITERAL_SHIFT
6353 /*-----------------------------------------------------------------*/
6354 /* movLeft2Result - move byte from left to result */
6355 /*-----------------------------------------------------------------*/
6357 movLeft2Result (operand * left, int offl,
6358 operand * result, int offr, int sign)
6361 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6363 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6365 if (*l == '@' && (IS_AOP_PREG (result)))
6367 emitcode ("mov", "a,%s", l);
6368 aopPut (AOP (result), "a", offr);
6374 aopPut (AOP (result), l, offr);
6378 /* MSB sign in acc.7 ! */
6379 if (getDataSize (left) == offl + 1)
6381 emitcode ("mov", "a,%s", l);
6382 aopPut (AOP (result), "a", offr);
6390 #ifdef BETTER_LITERAL_SHIFT
6391 /*-----------------------------------------------------------------*/
6392 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6393 /*-----------------------------------------------------------------*/
6397 emitcode ("rrc", "a");
6398 emitcode ("xch", "a,%s", x);
6399 emitcode ("rrc", "a");
6400 emitcode ("xch", "a,%s", x);
6404 #ifdef BETTER_LITERAL_SHIFT
6406 /*-----------------------------------------------------------------*/
6407 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6408 /*-----------------------------------------------------------------*/
6412 emitcode ("xch", "a,%s", x);
6413 emitcode ("rlc", "a");
6414 emitcode ("xch", "a,%s", x);
6415 emitcode ("rlc", "a");
6419 #ifdef BETTER_LITERAL_SHIFT
6420 /*-----------------------------------------------------------------*/
6421 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6422 /*-----------------------------------------------------------------*/
6426 emitcode ("xch", "a,%s", x);
6427 emitcode ("add", "a,acc");
6428 emitcode ("xch", "a,%s", x);
6429 emitcode ("rlc", "a");
6433 #ifdef BETTER_LITERAL_SHIFT
6434 /*-----------------------------------------------------------------*/
6435 /* AccAXLsh - left shift a:x by known count (0..7) */
6436 /*-----------------------------------------------------------------*/
6438 AccAXLsh (char *x, int shCount)
6453 case 5: // AAAAABBB:CCCCCDDD
6455 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6457 emitcode ("anl", "a,#0x%02x",
6458 SLMask[shCount]); // BBB00000:CCCCCDDD
6460 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6462 AccRol (shCount); // DDDCCCCC:BBB00000
6464 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6466 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6468 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6470 emitcode ("anl", "a,#0x%02x",
6471 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6473 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6475 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6478 case 6: // AAAAAABB:CCCCCCDD
6479 emitcode ("anl", "a,#0x%02x",
6480 SRMask[shCount]); // 000000BB:CCCCCCDD
6481 emitcode ("mov", "c,acc.0"); // c = B
6482 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6484 AccAXRrl1 (x); // BCCCCCCD:D000000B
6485 AccAXRrl1 (x); // BBCCCCCC:DD000000
6487 emitcode("rrc","a");
6488 emitcode("xch","a,%s", x);
6489 emitcode("rrc","a");
6490 emitcode("mov","c,acc.0"); //<< get correct bit
6491 emitcode("xch","a,%s", x);
6493 emitcode("rrc","a");
6494 emitcode("xch","a,%s", x);
6495 emitcode("rrc","a");
6496 emitcode("xch","a,%s", x);
6499 case 7: // a:x <<= 7
6501 emitcode ("anl", "a,#0x%02x",
6502 SRMask[shCount]); // 0000000B:CCCCCCCD
6504 emitcode ("mov", "c,acc.0"); // c = B
6506 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6508 AccAXRrl1 (x); // BCCCCCCC:D0000000
6517 #ifdef BETTER_LITERAL_SHIFT
6519 /*-----------------------------------------------------------------*/
6520 /* AccAXRsh - right shift a:x known count (0..7) */
6521 /*-----------------------------------------------------------------*/
6523 AccAXRsh (char *x, int shCount)
6531 AccAXRrl1 (x); // 0->a:x
6536 AccAXRrl1 (x); // 0->a:x
6539 AccAXRrl1 (x); // 0->a:x
6544 case 5: // AAAAABBB:CCCCCDDD = a:x
6546 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6548 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6550 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6552 emitcode ("anl", "a,#0x%02x",
6553 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6555 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6557 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6559 emitcode ("anl", "a,#0x%02x",
6560 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6562 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6564 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6566 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6569 case 6: // AABBBBBB:CCDDDDDD
6571 emitcode ("mov", "c,acc.7");
6572 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6574 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6576 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6578 emitcode ("anl", "a,#0x%02x",
6579 SRMask[shCount]); // 000000AA:BBBBBBCC
6582 case 7: // ABBBBBBB:CDDDDDDD
6584 emitcode ("mov", "c,acc.7"); // c = A
6586 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6588 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6590 emitcode ("anl", "a,#0x%02x",
6591 SRMask[shCount]); // 0000000A:BBBBBBBC
6600 #ifdef BETTER_LITERAL_SHIFT
6601 /*-----------------------------------------------------------------*/
6602 /* AccAXRshS - right shift signed a:x known count (0..7) */
6603 /*-----------------------------------------------------------------*/
6605 AccAXRshS (char *x, int shCount)
6613 emitcode ("mov", "c,acc.7");
6614 AccAXRrl1 (x); // s->a:x
6618 emitcode ("mov", "c,acc.7");
6619 AccAXRrl1 (x); // s->a:x
6621 emitcode ("mov", "c,acc.7");
6622 AccAXRrl1 (x); // s->a:x
6627 case 5: // AAAAABBB:CCCCCDDD = a:x
6629 tlbl = newiTempLabel (NULL);
6630 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6632 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6634 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6636 emitcode ("anl", "a,#0x%02x",
6637 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6639 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6641 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6643 emitcode ("anl", "a,#0x%02x",
6644 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6646 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6648 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6650 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6652 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6653 emitcode ("orl", "a,#0x%02x",
6654 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6656 emitcode ("", "%05d$:", tlbl->key + 100);
6657 break; // SSSSAAAA:BBBCCCCC
6659 case 6: // AABBBBBB:CCDDDDDD
6661 tlbl = newiTempLabel (NULL);
6662 emitcode ("mov", "c,acc.7");
6663 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6665 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6667 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6669 emitcode ("anl", "a,#0x%02x",
6670 SRMask[shCount]); // 000000AA:BBBBBBCC
6672 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6673 emitcode ("orl", "a,#0x%02x",
6674 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6676 emitcode ("", "%05d$:", tlbl->key + 100);
6678 case 7: // ABBBBBBB:CDDDDDDD
6680 tlbl = newiTempLabel (NULL);
6681 emitcode ("mov", "c,acc.7"); // c = A
6683 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6685 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6687 emitcode ("anl", "a,#0x%02x",
6688 SRMask[shCount]); // 0000000A:BBBBBBBC
6690 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6691 emitcode ("orl", "a,#0x%02x",
6692 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6694 emitcode ("", "%05d$:", tlbl->key + 100);
6702 #ifdef BETTER_LITERAL_SHIFT
6704 _loadLeftIntoAx(char **lsb,
6710 // Get the initial value from left into a pair of registers.
6711 // MSB must be in A, LSB can be any register.
6713 // If the result is held in registers, it is an optimization
6714 // if the LSB can be held in the register which will hold the,
6715 // result LSB since this saves us from having to copy it into
6716 // the result following AccAXLsh.
6718 // If the result is addressed indirectly, this is not a gain.
6719 if (AOP_NEEDSACC(result))
6723 _startLazyDPSEvaluation();
6724 if (AOP_TYPE(left) == AOP_DPTR2)
6727 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6728 // get LSB in DP2_RESULT_REG.
6729 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6730 assert(!strcmp(leftByte, DP2_RESULT_REG));
6734 // get LSB into DP2_RESULT_REG
6735 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6736 if (strcmp(leftByte, DP2_RESULT_REG))
6738 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6741 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6742 assert(strcmp(leftByte, DP2_RESULT_REG));
6745 _endLazyDPSEvaluation();
6746 *lsb = DP2_RESULT_REG;
6750 if (sameRegs (AOP (result), AOP (left)) &&
6751 ((offl + MSB16) == offr))
6753 /* don't crash result[offr] */
6754 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6755 emitcode ("xch", "a,%s",
6756 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6760 movLeft2Result (left, offl, result, offr, 0);
6761 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6763 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6764 assert(strcmp(*lsb,"a"));
6769 _storeAxResults(char *lsb,
6773 _startLazyDPSEvaluation();
6774 if (AOP_NEEDSACC(result))
6776 /* We have to explicitly update the result LSB.
6778 emitcode("xch","a,%s", lsb);
6779 aopPut(AOP(result), "a", offr);
6780 emitcode("mov","a,%s", lsb);
6782 if (getDataSize (result) > 1)
6784 aopPut (AOP (result), "a", offr + MSB16);
6786 _endLazyDPSEvaluation();
6789 /*-----------------------------------------------------------------*/
6790 /* shiftL2Left2Result - shift left two bytes from left to result */
6791 /*-----------------------------------------------------------------*/
6793 shiftL2Left2Result (operand * left, int offl,
6794 operand * result, int offr, int shCount)
6798 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6800 AccAXLsh (lsb, shCount);
6802 _storeAxResults(lsb, result, offr);
6806 #ifdef BETTER_LITERAL_SHIFT
6807 /*-----------------------------------------------------------------*/
6808 /* shiftR2Left2Result - shift right two bytes from left to result */
6809 /*-----------------------------------------------------------------*/
6811 shiftR2Left2Result (operand * left, int offl,
6812 operand * result, int offr,
6813 int shCount, int sign)
6817 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6819 /* a:x >> shCount (x = lsb(result)) */
6822 AccAXRshS(lsb, shCount);
6826 AccAXRsh(lsb, shCount);
6829 _storeAxResults(lsb, result, offr);
6835 /*-----------------------------------------------------------------*/
6836 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6837 /*-----------------------------------------------------------------*/
6839 shiftLLeftOrResult (operand * left, int offl,
6840 operand * result, int offr, int shCount)
6842 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6843 /* shift left accumulator */
6845 /* or with result */
6846 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6847 /* back to result */
6848 aopPut (AOP (result), "a", offr);
6854 /*-----------------------------------------------------------------*/
6855 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6856 /*-----------------------------------------------------------------*/
6858 shiftRLeftOrResult (operand * left, int offl,
6859 operand * result, int offr, int shCount)
6861 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6862 /* shift right accumulator */
6864 /* or with result */
6865 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6866 /* back to result */
6867 aopPut (AOP (result), "a", offr);
6871 #ifdef BETTER_LITERAL_SHIFT
6872 /*-----------------------------------------------------------------*/
6873 /* genlshOne - left shift a one byte quantity by known count */
6874 /*-----------------------------------------------------------------*/
6876 genlshOne (operand * result, operand * left, int shCount)
6878 D (emitcode (";", "genlshOne "););
6879 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6883 #ifdef BETTER_LITERAL_SHIFT
6884 /*-----------------------------------------------------------------*/
6885 /* genlshTwo - left shift two bytes by known amount != 0 */
6886 /*-----------------------------------------------------------------*/
6888 genlshTwo (operand * result, operand * left, int shCount)
6892 D (emitcode (";", "genlshTwo "););
6894 size = getDataSize (result);
6896 /* if shCount >= 8 */
6901 _startLazyDPSEvaluation();
6907 _endLazyDPSEvaluation();
6908 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6909 aopPut (AOP (result), zero, LSB);
6913 movLeft2Result (left, LSB, result, MSB16, 0);
6914 aopPut (AOP (result), zero, LSB);
6915 _endLazyDPSEvaluation();
6920 aopPut (AOP (result), zero, LSB);
6921 _endLazyDPSEvaluation();
6925 /* 1 <= shCount <= 7 */
6930 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6934 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6942 /*-----------------------------------------------------------------*/
6943 /* shiftLLong - shift left one long from left to result */
6944 /* offl = LSB or MSB16 */
6945 /*-----------------------------------------------------------------*/
6947 shiftLLong (operand * left, operand * result, int offr)
6950 int size = AOP_SIZE (result);
6952 if (size >= LSB + offr)
6954 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6956 emitcode ("add", "a,acc");
6957 if (sameRegs (AOP (left), AOP (result)) &&
6958 size >= MSB16 + offr && offr != LSB)
6959 emitcode ("xch", "a,%s",
6960 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6962 aopPut (AOP (result), "a", LSB + offr);
6965 if (size >= MSB16 + offr)
6967 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6969 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6972 emitcode ("rlc", "a");
6973 if (sameRegs (AOP (left), AOP (result)) &&
6974 size >= MSB24 + offr && offr != LSB)
6975 emitcode ("xch", "a,%s",
6976 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6978 aopPut (AOP (result), "a", MSB16 + offr);
6981 if (size >= MSB24 + offr)
6983 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6985 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6988 emitcode ("rlc", "a");
6989 if (sameRegs (AOP (left), AOP (result)) &&
6990 size >= MSB32 + offr && offr != LSB)
6991 emitcode ("xch", "a,%s",
6992 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6994 aopPut (AOP (result), "a", MSB24 + offr);
6997 if (size > MSB32 + offr)
6999 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7001 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7004 emitcode ("rlc", "a");
7005 aopPut (AOP (result), "a", MSB32 + offr);
7008 aopPut (AOP (result), zero, LSB);
7014 /*-----------------------------------------------------------------*/
7015 /* genlshFour - shift four byte by a known amount != 0 */
7016 /*-----------------------------------------------------------------*/
7018 genlshFour (operand * result, operand * left, int shCount)
7022 D (emitcode (";", "genlshFour ");
7025 size = AOP_SIZE (result);
7027 /* if shifting more that 3 bytes */
7032 /* lowest order of left goes to the highest
7033 order of the destination */
7034 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7036 movLeft2Result (left, LSB, result, MSB32, 0);
7037 aopPut (AOP (result), zero, LSB);
7038 aopPut (AOP (result), zero, MSB16);
7039 aopPut (AOP (result), zero, MSB24);
7043 /* more than two bytes */
7044 else if (shCount >= 16)
7046 /* lower order two bytes goes to higher order two bytes */
7048 /* if some more remaining */
7050 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7053 movLeft2Result (left, MSB16, result, MSB32, 0);
7054 movLeft2Result (left, LSB, result, MSB24, 0);
7056 aopPut (AOP (result), zero, MSB16);
7057 aopPut (AOP (result), zero, LSB);
7061 /* if more than 1 byte */
7062 else if (shCount >= 8)
7064 /* lower order three bytes goes to higher order three bytes */
7069 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7071 movLeft2Result (left, LSB, result, MSB16, 0);
7077 movLeft2Result (left, MSB24, result, MSB32, 0);
7078 movLeft2Result (left, MSB16, result, MSB24, 0);
7079 movLeft2Result (left, LSB, result, MSB16, 0);
7080 aopPut (AOP (result), zero, LSB);
7082 else if (shCount == 1)
7083 shiftLLong (left, result, MSB16);
7086 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7087 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7088 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7089 aopPut (AOP (result), zero, LSB);
7094 /* 1 <= shCount <= 7 */
7095 else if (shCount <= 2)
7097 shiftLLong (left, result, LSB);
7099 shiftLLong (result, result, LSB);
7101 /* 3 <= shCount <= 7, optimize */
7104 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7105 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7106 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7111 #ifdef BETTER_LITERAL_SHIFT
7112 /*-----------------------------------------------------------------*/
7113 /* genLeftShiftLiteral - left shifting by known count */
7114 /*-----------------------------------------------------------------*/
7116 genLeftShiftLiteral (operand * left,
7121 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7124 size = getSize (operandType (result));
7126 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7128 /* We only handle certain easy cases so far. */
7130 && (shCount < (size * 8))
7134 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7138 freeAsmop (right, NULL, ic, TRUE);
7140 aopOp(left, ic, FALSE, FALSE);
7141 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7144 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7146 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7147 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7149 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7152 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7154 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7155 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7157 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7163 emitcode ("; shift left ", "result %d, left %d", size,
7167 /* I suppose that the left size >= result size */
7170 _startLazyDPSEvaluation();
7173 movLeft2Result (left, size, result, size, 0);
7175 _endLazyDPSEvaluation();
7177 else if (shCount >= (size * 8))
7179 _startLazyDPSEvaluation();
7182 aopPut (AOP (result), zero, size);
7184 _endLazyDPSEvaluation();
7191 genlshOne (result, left, shCount);
7195 genlshTwo (result, left, shCount);
7199 genlshFour (result, left, shCount);
7203 fprintf(stderr, "*** ack! mystery literal shift!\n");
7207 freeAsmop (left, NULL, ic, TRUE);
7208 freeAsmop (result, NULL, ic, TRUE);
7213 /*-----------------------------------------------------------------*/
7214 /* genLeftShift - generates code for left shifting */
7215 /*-----------------------------------------------------------------*/
7217 genLeftShift (iCode * ic)
7219 operand *left, *right, *result;
7222 symbol *tlbl, *tlbl1;
7224 D (emitcode (";", "genLeftShift "););
7226 right = IC_RIGHT (ic);
7227 left = IC_LEFT (ic);
7228 result = IC_RESULT (ic);
7230 aopOp (right, ic, FALSE, FALSE);
7233 #ifdef BETTER_LITERAL_SHIFT
7234 /* if the shift count is known then do it
7235 as efficiently as possible */
7236 if (AOP_TYPE (right) == AOP_LIT)
7238 if (genLeftShiftLiteral (left, right, result, ic))
7245 /* shift count is unknown then we have to form
7246 a loop get the loop count in B : Note: we take
7247 only the lower order byte since shifting
7248 more that 32 bits make no sense anyway, ( the
7249 largest size of an object can be only 32 bits ) */
7251 if (AOP_TYPE (right) == AOP_LIT)
7253 /* Really should be handled by genLeftShiftLiteral,
7254 * but since I'm too lazy to fix that today, at least we can make
7255 * some small improvement.
7257 emitcode("mov", "b,#0x%02x",
7258 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7262 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7263 emitcode ("inc", "b");
7265 freeAsmop (right, NULL, ic, TRUE);
7266 aopOp (left, ic, FALSE, FALSE);
7267 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7269 /* now move the left to the result if they are not the
7271 if (!sameRegs (AOP (left), AOP (result)) &&
7272 AOP_SIZE (result) > 1)
7275 size = AOP_SIZE (result);
7277 _startLazyDPSEvaluation ();
7280 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7281 if (*l == '@' && (IS_AOP_PREG (result)))
7284 emitcode ("mov", "a,%s", l);
7285 aopPut (AOP (result), "a", offset);
7288 aopPut (AOP (result), l, offset);
7291 _endLazyDPSEvaluation ();
7294 tlbl = newiTempLabel (NULL);
7295 size = AOP_SIZE (result);
7297 tlbl1 = newiTempLabel (NULL);
7299 /* if it is only one byte then */
7302 symbol *tlbl1 = newiTempLabel (NULL);
7304 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7306 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7307 emitcode ("", "%05d$:", tlbl->key + 100);
7308 emitcode ("add", "a,acc");
7309 emitcode ("", "%05d$:", tlbl1->key + 100);
7310 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7311 aopPut (AOP (result), "a", 0);
7315 reAdjustPreg (AOP (result));
7317 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7318 emitcode ("", "%05d$:", tlbl->key + 100);
7319 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7321 emitcode ("add", "a,acc");
7322 aopPut (AOP (result), "a", offset++);
7323 _startLazyDPSEvaluation ();
7326 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7328 emitcode ("rlc", "a");
7329 aopPut (AOP (result), "a", offset++);
7331 _endLazyDPSEvaluation ();
7332 reAdjustPreg (AOP (result));
7334 emitcode ("", "%05d$:", tlbl1->key + 100);
7335 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7337 freeAsmop (left, NULL, ic, TRUE);
7338 freeAsmop (result, NULL, ic, TRUE);
7341 #ifdef BETTER_LITERAL_SHIFT
7342 /*-----------------------------------------------------------------*/
7343 /* genrshOne - right shift a one byte quantity by known count */
7344 /*-----------------------------------------------------------------*/
7346 genrshOne (operand * result, operand * left,
7347 int shCount, int sign)
7349 D (emitcode (";", "genrshOne"););
7350 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7354 #ifdef BETTER_LITERAL_SHIFT
7355 /*-----------------------------------------------------------------*/
7356 /* genrshTwo - right shift two bytes by known amount != 0 */
7357 /*-----------------------------------------------------------------*/
7359 genrshTwo (operand * result, operand * left,
7360 int shCount, int sign)
7362 D (emitcode (";", "genrshTwo"););
7364 /* if shCount >= 8 */
7368 _startLazyDPSEvaluation();
7371 shiftR1Left2Result (left, MSB16, result, LSB,
7376 movLeft2Result (left, MSB16, result, LSB, sign);
7378 addSign (result, MSB16, sign);
7379 _endLazyDPSEvaluation();
7382 /* 1 <= shCount <= 7 */
7385 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7392 /*-----------------------------------------------------------------*/
7393 /* shiftRLong - shift right one long from left to result */
7394 /* offl = LSB or MSB16 */
7395 /*-----------------------------------------------------------------*/
7397 shiftRLong (operand * left, int offl,
7398 operand * result, int sign)
7400 int isSameRegs=sameRegs(AOP(left),AOP(result));
7402 if (isSameRegs && offl>1) {
7403 // we are in big trouble, but this shouldn't happen
7404 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7407 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7412 emitcode ("rlc", "a");
7413 emitcode ("subb", "a,acc");
7414 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7416 aopPut (AOP(result), zero, MSB32);
7421 emitcode ("clr", "c");
7423 emitcode ("mov", "c,acc.7");
7426 emitcode ("rrc", "a");
7428 if (isSameRegs && offl==MSB16) {
7429 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7431 aopPut (AOP (result), "a", MSB32);
7432 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7435 emitcode ("rrc", "a");
7436 if (isSameRegs && offl==1) {
7437 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7439 aopPut (AOP (result), "a", MSB24);
7440 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7442 emitcode ("rrc", "a");
7443 aopPut (AOP (result), "a", MSB16 - offl);
7447 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7448 emitcode ("rrc", "a");
7449 aopPut (AOP (result), "a", LSB);
7456 /*-----------------------------------------------------------------*/
7457 /* genrshFour - shift four byte by a known amount != 0 */
7458 /*-----------------------------------------------------------------*/
7460 genrshFour (operand * result, operand * left,
7461 int shCount, int sign)
7463 D (emitcode (";", "genrshFour");
7466 /* if shifting more that 3 bytes */
7471 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7473 movLeft2Result (left, MSB32, result, LSB, sign);
7474 addSign (result, MSB16, sign);
7476 else if (shCount >= 16)
7480 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7483 movLeft2Result (left, MSB24, result, LSB, 0);
7484 movLeft2Result (left, MSB32, result, MSB16, sign);
7486 addSign (result, MSB24, sign);
7488 else if (shCount >= 8)
7492 shiftRLong (left, MSB16, result, sign);
7493 else if (shCount == 0)
7495 movLeft2Result (left, MSB16, result, LSB, 0);
7496 movLeft2Result (left, MSB24, result, MSB16, 0);
7497 movLeft2Result (left, MSB32, result, MSB24, sign);
7498 addSign (result, MSB32, sign);
7502 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7503 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7504 /* the last shift is signed */
7505 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7506 addSign (result, MSB32, sign);
7510 { /* 1 <= shCount <= 7 */
7513 shiftRLong (left, LSB, result, sign);
7515 shiftRLong (result, LSB, result, sign);
7519 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7520 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7521 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7527 #ifdef BETTER_LITERAL_SHIFT
7528 /*-----------------------------------------------------------------*/
7529 /* genRightShiftLiteral - right shifting by known count */
7530 /*-----------------------------------------------------------------*/
7532 genRightShiftLiteral (operand * left,
7538 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7541 size = getSize (operandType (result));
7543 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7545 /* We only handle certain easy cases so far. */
7547 && (shCount < (size * 8))
7551 D(emitcode (";", "genRightShiftLiteral wimping out"););
7555 freeAsmop (right, NULL, ic, TRUE);
7557 aopOp (left, ic, FALSE, FALSE);
7558 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7561 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7565 /* test the LEFT size !!! */
7567 /* I suppose that the left size >= result size */
7570 size = getDataSize (result);
7571 _startLazyDPSEvaluation();
7574 movLeft2Result (left, size, result, size, 0);
7576 _endLazyDPSEvaluation();
7578 else if (shCount >= (size * 8))
7582 /* get sign in acc.7 */
7583 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7585 addSign (result, LSB, sign);
7592 genrshOne (result, left, shCount, sign);
7596 genrshTwo (result, left, shCount, sign);
7600 genrshFour (result, left, shCount, sign);
7607 freeAsmop (left, NULL, ic, TRUE);
7608 freeAsmop (result, NULL, ic, TRUE);
7614 /*-----------------------------------------------------------------*/
7615 /* genSignedRightShift - right shift of signed number */
7616 /*-----------------------------------------------------------------*/
7618 genSignedRightShift (iCode * ic)
7620 operand *right, *left, *result;
7623 symbol *tlbl, *tlbl1;
7625 D (emitcode (";", "genSignedRightShift "););
7627 /* we do it the hard way put the shift count in b
7628 and loop thru preserving the sign */
7630 right = IC_RIGHT (ic);
7631 left = IC_LEFT (ic);
7632 result = IC_RESULT (ic);
7634 aopOp (right, ic, FALSE, FALSE);
7636 #ifdef BETTER_LITERAL_SHIFT
7637 if (AOP_TYPE (right) == AOP_LIT)
7639 if (genRightShiftLiteral (left, right, result, ic, 1))
7645 /* shift count is unknown then we have to form
7646 a loop get the loop count in B : Note: we take
7647 only the lower order byte since shifting
7648 more that 32 bits make no sense anyway, ( the
7649 largest size of an object can be only 32 bits ) */
7651 if (AOP_TYPE (right) == AOP_LIT)
7653 /* Really should be handled by genRightShiftLiteral,
7654 * but since I'm too lazy to fix that today, at least we can make
7655 * some small improvement.
7657 emitcode("mov", "b,#0x%02x",
7658 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7662 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7663 emitcode ("inc", "b");
7665 freeAsmop (right, NULL, ic, TRUE);
7666 aopOp (left, ic, FALSE, FALSE);
7667 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7669 /* now move the left to the result if they are not the
7671 if (!sameRegs (AOP (left), AOP (result)) &&
7672 AOP_SIZE (result) > 1)
7675 size = AOP_SIZE (result);
7677 _startLazyDPSEvaluation ();
7680 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7681 if (*l == '@' && IS_AOP_PREG (result))
7684 emitcode ("mov", "a,%s", l);
7685 aopPut (AOP (result), "a", offset);
7688 aopPut (AOP (result), l, offset);
7691 _endLazyDPSEvaluation ();
7694 /* mov the highest order bit to OVR */
7695 tlbl = newiTempLabel (NULL);
7696 tlbl1 = newiTempLabel (NULL);
7698 size = AOP_SIZE (result);
7700 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7701 emitcode ("rlc", "a");
7702 emitcode ("mov", "ov,c");
7703 /* if it is only one byte then */
7706 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7708 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7709 emitcode ("", "%05d$:", tlbl->key + 100);
7710 emitcode ("mov", "c,ov");
7711 emitcode ("rrc", "a");
7712 emitcode ("", "%05d$:", tlbl1->key + 100);
7713 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7714 aopPut (AOP (result), "a", 0);
7718 reAdjustPreg (AOP (result));
7719 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7720 emitcode ("", "%05d$:", tlbl->key + 100);
7721 emitcode ("mov", "c,ov");
7722 _startLazyDPSEvaluation ();
7725 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7727 emitcode ("rrc", "a");
7728 aopPut (AOP (result), "a", offset--);
7730 _endLazyDPSEvaluation ();
7731 reAdjustPreg (AOP (result));
7732 emitcode ("", "%05d$:", tlbl1->key + 100);
7733 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7736 freeAsmop (left, NULL, ic, TRUE);
7737 freeAsmop (result, NULL, ic, TRUE);
7740 /*-----------------------------------------------------------------*/
7741 /* genRightShift - generate code for right shifting */
7742 /*-----------------------------------------------------------------*/
7744 genRightShift (iCode * ic)
7746 operand *right, *left, *result;
7750 symbol *tlbl, *tlbl1;
7752 D (emitcode (";", "genRightShift "););
7754 /* if signed then we do it the hard way preserve the
7755 sign bit moving it inwards */
7756 retype = getSpec (operandType (IC_RESULT (ic)));
7758 if (!SPEC_USIGN (retype))
7760 genSignedRightShift (ic);
7764 /* signed & unsigned types are treated the same : i.e. the
7765 signed is NOT propagated inwards : quoting from the
7766 ANSI - standard : "for E1 >> E2, is equivalent to division
7767 by 2**E2 if unsigned or if it has a non-negative value,
7768 otherwise the result is implementation defined ", MY definition
7769 is that the sign does not get propagated */
7771 right = IC_RIGHT (ic);
7772 left = IC_LEFT (ic);
7773 result = IC_RESULT (ic);
7775 aopOp (right, ic, FALSE, FALSE);
7777 #ifdef BETTER_LITERAL_SHIFT
7778 /* if the shift count is known then do it
7779 as efficiently as possible */
7780 if (AOP_TYPE (right) == AOP_LIT)
7782 if (genRightShiftLiteral (left, right, result, ic, 0))
7789 /* shift count is unknown then we have to form
7790 a loop get the loop count in B : Note: we take
7791 only the lower order byte since shifting
7792 more that 32 bits make no sense anyway, ( the
7793 largest size of an object can be only 32 bits ) */
7795 if (AOP_TYPE (right) == AOP_LIT)
7797 /* Really should be handled by genRightShiftLiteral,
7798 * but since I'm too lazy to fix that today, at least we can make
7799 * some small improvement.
7801 emitcode("mov", "b,#0x%02x",
7802 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7806 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7807 emitcode ("inc", "b");
7809 freeAsmop (right, NULL, ic, TRUE);
7810 aopOp (left, ic, FALSE, FALSE);
7811 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7813 /* now move the left to the result if they are not the
7815 if (!sameRegs (AOP (left), AOP (result)) &&
7816 AOP_SIZE (result) > 1)
7819 size = AOP_SIZE (result);
7821 _startLazyDPSEvaluation ();
7824 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7825 if (*l == '@' && IS_AOP_PREG (result))
7828 emitcode ("mov", "a,%s", l);
7829 aopPut (AOP (result), "a", offset);
7832 aopPut (AOP (result), l, offset);
7835 _endLazyDPSEvaluation ();
7838 tlbl = newiTempLabel (NULL);
7839 tlbl1 = newiTempLabel (NULL);
7840 size = AOP_SIZE (result);
7843 /* if it is only one byte then */
7846 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7848 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7849 emitcode ("", "%05d$:", tlbl->key + 100);
7851 emitcode ("rrc", "a");
7852 emitcode ("", "%05d$:", tlbl1->key + 100);
7853 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7854 aopPut (AOP (result), "a", 0);
7858 reAdjustPreg (AOP (result));
7859 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7860 emitcode ("", "%05d$:", tlbl->key + 100);
7862 _startLazyDPSEvaluation ();
7865 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7867 emitcode ("rrc", "a");
7868 aopPut (AOP (result), "a", offset--);
7870 _endLazyDPSEvaluation ();
7871 reAdjustPreg (AOP (result));
7873 emitcode ("", "%05d$:", tlbl1->key + 100);
7874 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7877 freeAsmop (left, NULL, ic, TRUE);
7878 freeAsmop (result, NULL, ic, TRUE);
7881 /*-----------------------------------------------------------------*/
7882 /* genUnpackBits - generates code for unpacking bits */
7883 /*-----------------------------------------------------------------*/
7885 genUnpackBits (operand * result, char *rname, int ptype)
7892 D (emitcode (";", "genUnpackBits ");
7895 etype = getSpec (operandType (result));
7897 /* read the first byte */
7903 emitcode ("mov", "a,@%s", rname);
7907 emitcode ("movx", "a,@%s", rname);
7911 emitcode ("movx", "a,@dptr");
7915 emitcode ("clr", "a");
7916 emitcode ("movc", "a", "@a+dptr");
7920 emitcode ("lcall", "__gptrget");
7924 /* if we have bitdisplacement then it fits */
7925 /* into this byte completely or if length is */
7926 /* less than a byte */
7927 if ((shCnt = SPEC_BSTR (etype)) ||
7928 (SPEC_BLEN (etype) <= 8))
7931 /* shift right acc */
7934 emitcode ("anl", "a,#0x%02x",
7935 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7936 aopPut (AOP (result), "a", offset);
7940 /* bit field did not fit in a byte */
7941 rlen = SPEC_BLEN (etype) - 8;
7942 aopPut (AOP (result), "a", offset++);
7951 emitcode ("inc", "%s", rname);
7952 emitcode ("mov", "a,@%s", rname);
7956 emitcode ("inc", "%s", rname);
7957 emitcode ("movx", "a,@%s", rname);
7961 emitcode ("inc", "dptr");
7962 emitcode ("movx", "a,@dptr");
7966 emitcode ("clr", "a");
7967 emitcode ("inc", "dptr");
7968 emitcode ("movc", "a", "@a+dptr");
7972 emitcode ("inc", "dptr");
7973 emitcode ("lcall", "__gptrget");
7978 /* if we are done */
7982 aopPut (AOP (result), "a", offset++);
7988 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7989 aopPut (AOP (result), "a", offset);
7996 /*-----------------------------------------------------------------*/
7997 /* genDataPointerGet - generates code when ptr offset is known */
7998 /*-----------------------------------------------------------------*/
8000 genDataPointerGet (operand * left,
8006 int size, offset = 0;
8007 aopOp (result, ic, TRUE, FALSE);
8009 /* get the string representation of the name */
8010 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8011 size = AOP_SIZE (result);
8012 _startLazyDPSEvaluation ();
8016 sprintf (buffer, "(%s + %d)", l + 1, offset);
8018 sprintf (buffer, "%s", l + 1);
8019 aopPut (AOP (result), buffer, offset++);
8021 _endLazyDPSEvaluation ();
8023 freeAsmop (left, NULL, ic, TRUE);
8024 freeAsmop (result, NULL, ic, TRUE);
8027 /*-----------------------------------------------------------------*/
8028 /* genNearPointerGet - emitcode for near pointer fetch */
8029 /*-----------------------------------------------------------------*/
8031 genNearPointerGet (operand * left,
8038 sym_link *rtype, *retype, *letype;
8039 sym_link *ltype = operandType (left);
8042 rtype = operandType (result);
8043 retype = getSpec (rtype);
8044 letype = getSpec (ltype);
8046 aopOp (left, ic, FALSE, FALSE);
8048 /* if left is rematerialisable and
8049 result is not bit variable type and
8050 the left is pointer to data space i.e
8051 lower 128 bytes of space */
8052 if (AOP_TYPE (left) == AOP_IMMD &&
8053 !IS_BITVAR (retype) &&
8054 !IS_BITVAR (letype) &&
8055 DCL_TYPE (ltype) == POINTER)
8057 genDataPointerGet (left, result, ic);
8061 /* if the value is already in a pointer register
8062 then don't need anything more */
8063 if (!AOP_INPREG (AOP (left)))
8065 /* otherwise get a free pointer register */
8067 preg = getFreePtr (ic, &aop, FALSE);
8068 emitcode ("mov", "%s,%s",
8070 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8074 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8076 freeAsmop (left, NULL, ic, TRUE);
8077 aopOp (result, ic, FALSE, FALSE);
8079 /* if bitfield then unpack the bits */
8080 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8081 genUnpackBits (result, rname, POINTER);
8084 /* we have can just get the values */
8085 int size = AOP_SIZE (result);
8090 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8093 emitcode ("mov", "a,@%s", rname);
8094 aopPut (AOP (result), "a", offset);
8098 sprintf (buffer, "@%s", rname);
8099 aopPut (AOP (result), buffer, offset);
8103 emitcode ("inc", "%s", rname);
8107 /* now some housekeeping stuff */
8110 /* we had to allocate for this iCode */
8111 freeAsmop (NULL, aop, ic, TRUE);
8115 /* we did not allocate which means left
8116 already in a pointer register, then
8117 if size > 0 && this could be used again
8118 we have to point it back to where it
8120 if (AOP_SIZE (result) > 1 &&
8121 !OP_SYMBOL (left)->remat &&
8122 (OP_SYMBOL (left)->liveTo > ic->seq ||
8125 int size = AOP_SIZE (result) - 1;
8127 emitcode ("dec", "%s", rname);
8132 freeAsmop (result, NULL, ic, TRUE);
8136 /*-----------------------------------------------------------------*/
8137 /* genPagedPointerGet - emitcode for paged pointer fetch */
8138 /*-----------------------------------------------------------------*/
8140 genPagedPointerGet (operand * left,
8147 sym_link *rtype, *retype, *letype;
8149 rtype = operandType (result);
8150 retype = getSpec (rtype);
8151 letype = getSpec (operandType (left));
8152 aopOp (left, ic, FALSE, FALSE);
8154 /* if the value is already in a pointer register
8155 then don't need anything more */
8156 if (!AOP_INPREG (AOP (left)))
8158 /* otherwise get a free pointer register */
8160 preg = getFreePtr (ic, &aop, FALSE);
8161 emitcode ("mov", "%s,%s",
8163 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8167 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8169 freeAsmop (left, NULL, ic, TRUE);
8170 aopOp (result, ic, FALSE, FALSE);
8172 /* if bitfield then unpack the bits */
8173 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8174 genUnpackBits (result, rname, PPOINTER);
8177 /* we have can just get the values */
8178 int size = AOP_SIZE (result);
8184 emitcode ("movx", "a,@%s", rname);
8185 aopPut (AOP (result), "a", offset);
8190 emitcode ("inc", "%s", rname);
8194 /* now some housekeeping stuff */
8197 /* we had to allocate for this iCode */
8198 freeAsmop (NULL, aop, ic, TRUE);
8202 /* we did not allocate which means left
8203 already in a pointer register, then
8204 if size > 0 && this could be used again
8205 we have to point it back to where it
8207 if (AOP_SIZE (result) > 1 &&
8208 !OP_SYMBOL (left)->remat &&
8209 (OP_SYMBOL (left)->liveTo > ic->seq ||
8212 int size = AOP_SIZE (result) - 1;
8214 emitcode ("dec", "%s", rname);
8219 freeAsmop (result, NULL, ic, TRUE);
8224 /*-----------------------------------------------------------------*/
8225 /* genFarPointerGet - gget value from far space */
8226 /*-----------------------------------------------------------------*/
8228 genFarPointerGet (operand * left,
8229 operand * result, iCode * ic)
8232 sym_link *retype = getSpec (operandType (result));
8233 sym_link *letype = getSpec (operandType (left));
8234 D (emitcode (";", "genFarPointerGet");
8237 aopOp (left, ic, FALSE, FALSE);
8239 /* if the operand is already in dptr
8240 then we do nothing else we move the value to dptr */
8241 if (AOP_TYPE (left) != AOP_STR)
8243 /* if this is remateriazable */
8244 if (AOP_TYPE (left) == AOP_IMMD)
8246 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8250 /* we need to get it byte by byte */
8251 _startLazyDPSEvaluation ();
8252 if (AOP_TYPE (left) != AOP_DPTR)
8254 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8255 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8256 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8260 /* We need to generate a load to DPTR indirect through DPTR. */
8261 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8263 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8264 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8265 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8266 emitcode ("pop", "dph");
8267 emitcode ("pop", "dpl");
8269 _endLazyDPSEvaluation ();
8272 /* so dptr know contains the address */
8273 freeAsmop (left, NULL, ic, TRUE);
8274 aopOp (result, ic, FALSE, TRUE);
8276 /* if bit then unpack */
8277 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8278 genUnpackBits (result, "dptr", FPOINTER);
8281 size = AOP_SIZE (result);
8284 _startLazyDPSEvaluation ();
8291 emitcode ("movx", "a,@dptr");
8293 emitcode ("inc", "dptr");
8295 aopPut (AOP (result), "a", offset++);
8297 _endLazyDPSEvaluation ();
8300 freeAsmop (result, NULL, ic, TRUE);
8303 /*-----------------------------------------------------------------*/
8304 /* emitcodePointerGet - gget value from code space */
8305 /*-----------------------------------------------------------------*/
8307 emitcodePointerGet (operand * left,
8308 operand * result, iCode * ic)
8311 sym_link *retype = getSpec (operandType (result));
8313 aopOp (left, ic, FALSE, FALSE);
8315 /* if the operand is already in dptr
8316 then we do nothing else we move the value to dptr */
8317 if (AOP_TYPE (left) != AOP_STR)
8319 /* if this is remateriazable */
8320 if (AOP_TYPE (left) == AOP_IMMD)
8322 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8325 { /* we need to get it byte by byte */
8326 _startLazyDPSEvaluation ();
8327 if (AOP_TYPE (left) != AOP_DPTR)
8329 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8330 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8331 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8335 /* We need to generate a load to DPTR indirect through DPTR. */
8336 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8338 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8339 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8340 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8341 emitcode ("pop", "dph");
8342 emitcode ("pop", "dpl");
8344 _endLazyDPSEvaluation ();
8347 /* so dptr know contains the address */
8348 freeAsmop (left, NULL, ic, TRUE);
8349 aopOp (result, ic, FALSE, TRUE);
8351 /* if bit then unpack */
8352 if (IS_BITVAR (retype))
8353 genUnpackBits (result, "dptr", CPOINTER);
8356 size = AOP_SIZE (result);
8359 _startLazyDPSEvaluation ();
8365 emitcode ("clr", "a");
8366 emitcode ("movc", "a,@a+dptr");
8368 emitcode ("inc", "dptr");
8369 aopPut (AOP (result), "a", offset++);
8371 _endLazyDPSEvaluation ();
8374 freeAsmop (result, NULL, ic, TRUE);
8377 /*-----------------------------------------------------------------*/
8378 /* genGenPointerGet - gget value from generic pointer space */
8379 /*-----------------------------------------------------------------*/
8381 genGenPointerGet (operand * left,
8382 operand * result, iCode * ic)
8385 sym_link *retype = getSpec (operandType (result));
8386 sym_link *letype = getSpec (operandType (left));
8388 D (emitcode (";", "genGenPointerGet "); );
8390 aopOp (left, ic, FALSE, TRUE);
8392 /* if the operand is already in dptr
8393 then we do nothing else we move the value to dptr */
8394 if (AOP_TYPE (left) != AOP_STR)
8396 /* if this is remateriazable */
8397 if (AOP_TYPE (left) == AOP_IMMD)
8399 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8400 emitcode ("mov", "b,#%d", pointerCode (retype));
8403 { /* we need to get it byte by byte */
8404 _startLazyDPSEvaluation ();
8405 if (AOP(left)->type==AOP_DPTR2) {
8407 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8410 emitcode ("mov", "dpl,%s", l);
8411 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8414 emitcode ("mov", "dph,%s", l);
8415 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8418 emitcode ("mov", "dpx,%s", l);
8419 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8421 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8422 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8423 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8424 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8426 _endLazyDPSEvaluation ();
8429 /* so dptr know contains the address */
8430 freeAsmop (left, NULL, ic, TRUE);
8431 aopOp (result, ic, FALSE, TRUE);
8433 /* if bit then unpack */
8434 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8435 genUnpackBits (result, "dptr", GPOINTER);
8438 size = AOP_SIZE (result);
8443 emitcode ("lcall", "__gptrget");
8444 aopPut (AOP (result), "a", offset++);
8446 emitcode ("inc", "dptr");
8450 freeAsmop (result, NULL, ic, TRUE);
8453 /*-----------------------------------------------------------------*/
8454 /* genPointerGet - generate code for pointer get */
8455 /*-----------------------------------------------------------------*/
8457 genPointerGet (iCode * ic)
8459 operand *left, *result;
8460 sym_link *type, *etype;
8463 D (emitcode (";", "genPointerGet ");
8466 left = IC_LEFT (ic);
8467 result = IC_RESULT (ic);
8469 /* depending on the type of pointer we need to
8470 move it to the correct pointer register */
8471 type = operandType (left);
8472 etype = getSpec (type);
8473 /* if left is of type of pointer then it is simple */
8474 if (IS_PTR (type) && !IS_FUNC (type->next))
8475 p_type = DCL_TYPE (type);
8478 /* we have to go by the storage class */
8479 p_type = PTR_TYPE (SPEC_OCLS (etype));
8482 /* now that we have the pointer type we assign
8483 the pointer values */
8489 genNearPointerGet (left, result, ic);
8493 genPagedPointerGet (left, result, ic);
8497 genFarPointerGet (left, result, ic);
8501 emitcodePointerGet (left, result, ic);
8505 genGenPointerGet (left, result, ic);
8511 /*-----------------------------------------------------------------*/
8512 /* genPackBits - generates code for packed bit storage */
8513 /*-----------------------------------------------------------------*/
8515 genPackBits (sym_link * etype,
8517 char *rname, int p_type)
8525 blen = SPEC_BLEN (etype);
8526 bstr = SPEC_BSTR (etype);
8528 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8531 /* if the bit lenth is less than or */
8532 /* it exactly fits a byte then */
8533 if (SPEC_BLEN (etype) <= 8)
8535 shCount = SPEC_BSTR (etype);
8537 /* shift left acc */
8540 if (SPEC_BLEN (etype) < 8)
8541 { /* if smaller than a byte */
8547 emitcode ("mov", "b,a");
8548 emitcode ("mov", "a,@%s", rname);
8552 emitcode ("mov", "b,a");
8553 emitcode ("movx", "a,@dptr");
8557 emitcode ("push", "b");
8558 emitcode ("push", "acc");
8559 emitcode ("lcall", "__gptrget");
8560 emitcode ("pop", "b");
8564 emitcode ("anl", "a,#0x%02x", (unsigned char)
8565 ((unsigned char) (0xFF << (blen + bstr)) |
8566 (unsigned char) (0xFF >> (8 - bstr))));
8567 emitcode ("orl", "a,b");
8568 if (p_type == GPOINTER)
8569 emitcode ("pop", "b");
8576 emitcode ("mov", "@%s,a", rname);
8580 emitcode ("movx", "@dptr,a");
8584 emitcode ("lcall", "__gptrput");
8589 if (SPEC_BLEN (etype) <= 8)
8592 emitcode ("inc", "%s", rname);
8593 rLen = SPEC_BLEN (etype);
8595 /* now generate for lengths greater than one byte */
8599 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8611 emitcode ("mov", "@%s,a", rname);
8614 emitcode ("mov", "@%s,%s", rname, l);
8619 emitcode ("movx", "@dptr,a");
8624 emitcode ("lcall", "__gptrput");
8627 emitcode ("inc", "%s", rname);
8632 /* last last was not complete */
8635 /* save the byte & read byte */
8639 emitcode ("mov", "b,a");
8640 emitcode ("mov", "a,@%s", rname);
8644 emitcode ("mov", "b,a");
8645 emitcode ("movx", "a,@dptr");
8649 emitcode ("push", "b");
8650 emitcode ("push", "acc");
8651 emitcode ("lcall", "__gptrget");
8652 emitcode ("pop", "b");
8656 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8657 emitcode ("orl", "a,b");
8660 if (p_type == GPOINTER)
8661 emitcode ("pop", "b");
8667 emitcode ("mov", "@%s,a", rname);
8671 emitcode ("movx", "@dptr,a");
8675 emitcode ("lcall", "__gptrput");
8679 /*-----------------------------------------------------------------*/
8680 /* genDataPointerSet - remat pointer to data space */
8681 /*-----------------------------------------------------------------*/
8683 genDataPointerSet (operand * right,
8687 int size, offset = 0;
8688 char *l, buffer[256];
8690 aopOp (right, ic, FALSE, FALSE);
8692 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8693 size = AOP_SIZE (right);
8697 sprintf (buffer, "(%s + %d)", l + 1, offset);
8699 sprintf (buffer, "%s", l + 1);
8700 emitcode ("mov", "%s,%s", buffer,
8701 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8704 freeAsmop (right, NULL, ic, TRUE);
8705 freeAsmop (result, NULL, ic, TRUE);
8708 /*-----------------------------------------------------------------*/
8709 /* genNearPointerSet - emitcode for near pointer put */
8710 /*-----------------------------------------------------------------*/
8712 genNearPointerSet (operand * right,
8719 sym_link *retype, *letype;
8720 sym_link *ptype = operandType (result);
8722 retype = getSpec (operandType (right));
8723 letype = getSpec (ptype);
8725 aopOp (result, ic, FALSE, FALSE);
8727 /* if the result is rematerializable &
8728 in data space & not a bit variable */
8729 if (AOP_TYPE (result) == AOP_IMMD &&
8730 DCL_TYPE (ptype) == POINTER &&
8731 !IS_BITVAR (retype) &&
8732 !IS_BITVAR (letype))
8734 genDataPointerSet (right, result, ic);
8738 /* if the value is already in a pointer register
8739 then don't need anything more */
8740 if (!AOP_INPREG (AOP (result)))
8742 /* otherwise get a free pointer register */
8744 preg = getFreePtr (ic, &aop, FALSE);
8745 emitcode ("mov", "%s,%s",
8747 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8751 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8753 freeAsmop (result, NULL, ic, TRUE);
8754 aopOp (right, ic, FALSE, FALSE);
8756 /* if bitfield then unpack the bits */
8757 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8758 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8761 /* we have can just get the values */
8762 int size = AOP_SIZE (right);
8767 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8771 emitcode ("mov", "@%s,a", rname);
8774 emitcode ("mov", "@%s,%s", rname, l);
8776 emitcode ("inc", "%s", rname);
8781 /* now some housekeeping stuff */
8784 /* we had to allocate for this iCode */
8785 freeAsmop (NULL, aop, ic, TRUE);
8789 /* we did not allocate which means left
8790 already in a pointer register, then
8791 if size > 0 && this could be used again
8792 we have to point it back to where it
8794 if (AOP_SIZE (right) > 1 &&
8795 !OP_SYMBOL (result)->remat &&
8796 (OP_SYMBOL (result)->liveTo > ic->seq ||
8799 int size = AOP_SIZE (right) - 1;
8801 emitcode ("dec", "%s", rname);
8806 freeAsmop (right, NULL, ic, TRUE);
8811 /*-----------------------------------------------------------------*/
8812 /* genPagedPointerSet - emitcode for Paged pointer put */
8813 /*-----------------------------------------------------------------*/
8815 genPagedPointerSet (operand * right,
8822 sym_link *retype, *letype;
8824 retype = getSpec (operandType (right));
8825 letype = getSpec (operandType (result));
8827 aopOp (result, ic, FALSE, FALSE);
8829 /* if the value is already in a pointer register
8830 then don't need anything more */
8831 if (!AOP_INPREG (AOP (result)))
8833 /* otherwise get a free pointer register */
8835 preg = getFreePtr (ic, &aop, FALSE);
8836 emitcode ("mov", "%s,%s",
8838 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8842 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8844 freeAsmop (result, NULL, ic, TRUE);
8845 aopOp (right, ic, FALSE, FALSE);
8847 /* if bitfield then unpack the bits */
8848 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8849 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8852 /* we have can just get the values */
8853 int size = AOP_SIZE (right);
8858 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8861 emitcode ("movx", "@%s,a", rname);
8864 emitcode ("inc", "%s", rname);
8870 /* now some housekeeping stuff */
8873 /* we had to allocate for this iCode */
8874 freeAsmop (NULL, aop, ic, TRUE);
8878 /* we did not allocate which means left
8879 already in a pointer register, then
8880 if size > 0 && this could be used again
8881 we have to point it back to where it
8883 if (AOP_SIZE (right) > 1 &&
8884 !OP_SYMBOL (result)->remat &&
8885 (OP_SYMBOL (result)->liveTo > ic->seq ||
8888 int size = AOP_SIZE (right) - 1;
8890 emitcode ("dec", "%s", rname);
8895 freeAsmop (right, NULL, ic, TRUE);
8900 /*-----------------------------------------------------------------*/
8901 /* genFarPointerSet - set value from far space */
8902 /*-----------------------------------------------------------------*/
8904 genFarPointerSet (operand * right,
8905 operand * result, iCode * ic)
8908 sym_link *retype = getSpec (operandType (right));
8909 sym_link *letype = getSpec (operandType (result));
8911 aopOp (result, ic, FALSE, FALSE);
8913 /* if the operand is already in dptr
8914 then we do nothing else we move the value to dptr */
8915 if (AOP_TYPE (result) != AOP_STR)
8917 /* if this is remateriazable */
8918 if (AOP_TYPE (result) == AOP_IMMD)
8919 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8922 /* we need to get it byte by byte */
8923 _startLazyDPSEvaluation ();
8924 if (AOP_TYPE (result) != AOP_DPTR)
8926 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8927 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8928 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8932 /* We need to generate a load to DPTR indirect through DPTR. */
8933 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8935 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8936 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8937 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8938 emitcode ("pop", "dph");
8939 emitcode ("pop", "dpl");
8941 _endLazyDPSEvaluation ();
8944 /* so dptr know contains the address */
8945 freeAsmop (result, NULL, ic, TRUE);
8946 aopOp (right, ic, FALSE, TRUE);
8948 /* if bit then unpack */
8949 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8950 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8953 size = AOP_SIZE (right);
8956 _startLazyDPSEvaluation ();
8959 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8965 emitcode ("movx", "@dptr,a");
8967 emitcode ("inc", "dptr");
8969 _endLazyDPSEvaluation ();
8972 freeAsmop (right, NULL, ic, TRUE);
8975 /*-----------------------------------------------------------------*/
8976 /* genGenPointerSet - set value from generic pointer space */
8977 /*-----------------------------------------------------------------*/
8979 genGenPointerSet (operand * right,
8980 operand * result, iCode * ic)
8983 sym_link *retype = getSpec (operandType (right));
8984 sym_link *letype = getSpec (operandType (result));
8986 aopOp (result, ic, FALSE, TRUE);
8988 /* if the operand is already in dptr
8989 then we do nothing else we move the value to dptr */
8990 if (AOP_TYPE (result) != AOP_STR)
8992 _startLazyDPSEvaluation ();
8993 /* if this is remateriazable */
8994 if (AOP_TYPE (result) == AOP_IMMD)
8996 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8997 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9000 { /* we need to get it byte by byte */
9001 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9002 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9003 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9004 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9006 _endLazyDPSEvaluation ();
9008 /* so dptr know contains the address */
9009 freeAsmop (result, NULL, ic, TRUE);
9010 aopOp (right, ic, FALSE, TRUE);
9012 /* if bit then unpack */
9013 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9014 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9017 size = AOP_SIZE (right);
9020 _startLazyDPSEvaluation ();
9023 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9029 emitcode ("lcall", "__gptrput");
9031 emitcode ("inc", "dptr");
9033 _endLazyDPSEvaluation ();
9036 freeAsmop (right, NULL, ic, TRUE);
9039 /*-----------------------------------------------------------------*/
9040 /* genPointerSet - stores the value into a pointer location */
9041 /*-----------------------------------------------------------------*/
9043 genPointerSet (iCode * ic)
9045 operand *right, *result;
9046 sym_link *type, *etype;
9049 D (emitcode (";", "genPointerSet ");
9052 right = IC_RIGHT (ic);
9053 result = IC_RESULT (ic);
9055 /* depending on the type of pointer we need to
9056 move it to the correct pointer register */
9057 type = operandType (result);
9058 etype = getSpec (type);
9059 /* if left is of type of pointer then it is simple */
9060 if (IS_PTR (type) && !IS_FUNC (type->next))
9062 p_type = DCL_TYPE (type);
9066 /* we have to go by the storage class */
9067 p_type = PTR_TYPE (SPEC_OCLS (etype));
9070 /* now that we have the pointer type we assign
9071 the pointer values */
9077 genNearPointerSet (right, result, ic);
9081 genPagedPointerSet (right, result, ic);
9085 genFarPointerSet (right, result, ic);
9089 genGenPointerSet (right, result, ic);
9095 /*-----------------------------------------------------------------*/
9096 /* genIfx - generate code for Ifx statement */
9097 /*-----------------------------------------------------------------*/
9099 genIfx (iCode * ic, iCode * popIc)
9101 operand *cond = IC_COND (ic);
9104 D (emitcode (";", "genIfx "););
9106 aopOp (cond, ic, FALSE, FALSE);
9108 /* get the value into acc */
9109 if (AOP_TYPE (cond) != AOP_CRY)
9113 /* the result is now in the accumulator */
9114 freeAsmop (cond, NULL, ic, TRUE);
9116 /* if there was something to be popped then do it */
9120 /* if the condition is a bit variable */
9121 if (isbit && IS_ITEMP (cond) &&
9123 genIfxJump (ic, SPIL_LOC (cond)->rname);
9124 else if (isbit && !IS_ITEMP (cond))
9125 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9127 genIfxJump (ic, "a");
9132 /*-----------------------------------------------------------------*/
9133 /* genAddrOf - generates code for address of */
9134 /*-----------------------------------------------------------------*/
9136 genAddrOf (iCode * ic)
9138 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9141 D (emitcode (";", "genAddrOf ");
9144 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9146 /* if the operand is on the stack then we
9147 need to get the stack offset of this
9151 /* if it has an offset then we need to compute
9155 emitcode ("mov", "a,_bp");
9156 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9157 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9161 /* we can just move _bp */
9162 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9164 /* fill the result with zero */
9165 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9168 if (options.stack10bit && size < (FPTRSIZE - 1))
9171 "*** warning: pointer to stack var truncated.\n");
9178 if (options.stack10bit && offset == 2)
9180 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9184 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9191 /* object not on stack then we need the name */
9192 size = AOP_SIZE (IC_RESULT (ic));
9197 char s[SDCC_NAME_MAX];
9199 sprintf (s, "#(%s >> %d)",
9203 sprintf (s, "#%s", sym->rname);
9204 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9212 /*-----------------------------------------------------------------*/
9213 /* genFarFarAssign - assignment when both are in far space */
9214 /*-----------------------------------------------------------------*/
9216 genFarFarAssign (operand * result, operand * right, iCode * ic)
9218 int size = AOP_SIZE (right);
9220 symbol *rSym = NULL;
9224 /* quick & easy case. */
9225 D(emitcode(";","genFarFarAssign (1 byte case)"););
9226 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9227 freeAsmop (right, NULL, ic, FALSE);
9228 /* now assign DPTR to result */
9230 aopOp(result, ic, FALSE, FALSE);
9232 aopPut(AOP(result), "a", 0);
9233 freeAsmop(result, NULL, ic, FALSE);
9237 /* See if we've got an underlying symbol to abuse. */
9238 if (IS_SYMOP(result) && OP_SYMBOL(result))
9240 if (IS_TRUE_SYMOP(result))
9242 rSym = OP_SYMBOL(result);
9244 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9246 rSym = OP_SYMBOL(result)->usl.spillLoc;
9250 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9252 /* We can use the '390 auto-toggle feature to good effect here. */
9254 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9255 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9256 emitcode ("mov", "dptr,#%s", rSym->rname);
9257 /* DP2 = result, DP1 = right, DP1 is current. */
9260 emitcode("movx", "a,@dptr");
9261 emitcode("movx", "@dptr,a");
9264 emitcode("inc", "dptr");
9265 emitcode("inc", "dptr");
9268 emitcode("mov", "dps, #0");
9269 freeAsmop (right, NULL, ic, FALSE);
9273 D (emitcode (";", "genFarFarAssign"););
9274 aopOp (result, ic, TRUE, TRUE);
9276 _startLazyDPSEvaluation ();
9280 aopPut (AOP (result),
9281 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9284 _endLazyDPSEvaluation ();
9285 freeAsmop (result, NULL, ic, FALSE);
9286 freeAsmop (right, NULL, ic, FALSE);
9290 /*-----------------------------------------------------------------*/
9291 /* genAssign - generate code for assignment */
9292 /*-----------------------------------------------------------------*/
9294 genAssign (iCode * ic)
9296 operand *result, *right;
9298 unsigned long lit = 0L;
9300 D (emitcode (";", "genAssign ");
9303 result = IC_RESULT (ic);
9304 right = IC_RIGHT (ic);
9306 /* if they are the same */
9307 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9310 aopOp (right, ic, FALSE, FALSE);
9312 emitcode (";", "genAssign: resultIsFar = %s",
9313 isOperandInFarSpace (result) ?
9316 /* special case both in far space */
9317 if ((AOP_TYPE (right) == AOP_DPTR ||
9318 AOP_TYPE (right) == AOP_DPTR2) &&
9319 /* IS_TRUE_SYMOP(result) && */
9320 isOperandInFarSpace (result))
9322 genFarFarAssign (result, right, ic);
9326 aopOp (result, ic, TRUE, FALSE);
9328 /* if they are the same registers */
9329 if (sameRegs (AOP (right), AOP (result)))
9332 /* if the result is a bit */
9333 if (AOP_TYPE (result) == AOP_CRY)
9336 /* if the right size is a literal then
9337 we know what the value is */
9338 if (AOP_TYPE (right) == AOP_LIT)
9340 if (((int) operandLitValue (right)))
9341 aopPut (AOP (result), one, 0);
9343 aopPut (AOP (result), zero, 0);
9347 /* the right is also a bit variable */
9348 if (AOP_TYPE (right) == AOP_CRY)
9350 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9351 aopPut (AOP (result), "c", 0);
9357 aopPut (AOP (result), "a", 0);
9361 /* bit variables done */
9363 size = AOP_SIZE (result);
9365 if (AOP_TYPE (right) == AOP_LIT)
9366 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9369 (AOP_TYPE (result) != AOP_REG) &&
9370 (AOP_TYPE (right) == AOP_LIT) &&
9371 !IS_FLOAT (operandType (right)))
9373 _startLazyDPSEvaluation ();
9374 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9376 aopPut (AOP (result),
9377 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9382 /* And now fill the rest with zeros. */
9385 emitcode ("clr", "a");
9389 aopPut (AOP (result), "a", offset++);
9391 _endLazyDPSEvaluation ();
9395 _startLazyDPSEvaluation ();
9398 aopPut (AOP (result),
9399 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9403 _endLazyDPSEvaluation ();
9407 freeAsmop (right, NULL, ic, FALSE);
9408 freeAsmop (result, NULL, ic, TRUE);
9411 /*-----------------------------------------------------------------*/
9412 /* genJumpTab - generates code for jump table */
9413 /*-----------------------------------------------------------------*/
9415 genJumpTab (iCode * ic)
9420 D (emitcode (";", "genJumpTab ");
9423 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9424 /* get the condition into accumulator */
9425 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9427 /* multiply by four! */
9428 emitcode ("add", "a,acc");
9429 emitcode ("add", "a,acc");
9430 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9432 jtab = newiTempLabel (NULL);
9433 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9434 emitcode ("jmp", "@a+dptr");
9435 emitcode ("", "%05d$:", jtab->key + 100);
9436 /* now generate the jump labels */
9437 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9438 jtab = setNextItem (IC_JTLABELS (ic)))
9439 emitcode ("ljmp", "%05d$", jtab->key + 100);
9443 /*-----------------------------------------------------------------*/
9444 /* genCast - gen code for casting */
9445 /*-----------------------------------------------------------------*/
9447 genCast (iCode * ic)
9449 operand *result = IC_RESULT (ic);
9450 sym_link *ctype = operandType (IC_LEFT (ic));
9451 sym_link *rtype = operandType (IC_RIGHT (ic));
9452 operand *right = IC_RIGHT (ic);
9455 D (emitcode (";", "genCast ");
9458 /* if they are equivalent then do nothing */
9459 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9462 aopOp (right, ic, FALSE, FALSE);
9463 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9465 /* if the result is a bit */
9466 if (AOP_TYPE (result) == AOP_CRY)
9468 /* if the right size is a literal then
9469 we know what the value is */
9470 if (AOP_TYPE (right) == AOP_LIT)
9472 if (((int) operandLitValue (right)))
9473 aopPut (AOP (result), one, 0);
9475 aopPut (AOP (result), zero, 0);
9480 /* the right is also a bit variable */
9481 if (AOP_TYPE (right) == AOP_CRY)
9483 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9484 aopPut (AOP (result), "c", 0);
9490 aopPut (AOP (result), "a", 0);
9494 /* if they are the same size : or less */
9495 if (AOP_SIZE (result) <= AOP_SIZE (right))
9498 /* if they are in the same place */
9499 if (sameRegs (AOP (right), AOP (result)))
9502 /* if they in different places then copy */
9503 size = AOP_SIZE (result);
9505 _startLazyDPSEvaluation ();
9508 aopPut (AOP (result),
9509 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9513 _endLazyDPSEvaluation ();
9518 /* if the result is of type pointer */
9523 sym_link *type = operandType (right);
9525 /* pointer to generic pointer */
9526 if (IS_GENPTR (ctype))
9532 p_type = DCL_TYPE (type);
9536 #if OLD_CAST_BEHAVIOR
9537 /* KV: we are converting a non-pointer type to
9538 * a generic pointer. This (ifdef'd out) code
9539 * says that the resulting generic pointer
9540 * should have the same class as the storage
9541 * location of the non-pointer variable.
9543 * For example, converting an int (which happens
9544 * to be stored in DATA space) to a pointer results
9545 * in a DATA generic pointer; if the original int
9546 * in XDATA space, so will be the resulting pointer.
9548 * I don't like that behavior, and thus this change:
9549 * all such conversions will be forced to XDATA and
9550 * throw a warning. If you want some non-XDATA
9551 * type, or you want to suppress the warning, you
9552 * must go through an intermediate cast, like so:
9554 * char _generic *gp = (char _xdata *)(intVar);
9556 sym_link *etype = getSpec (type);
9558 /* we have to go by the storage class */
9559 if (SPEC_OCLS (etype) != generic)
9561 p_type = PTR_TYPE (SPEC_OCLS (etype));
9566 /* Converting unknown class (i.e. register variable)
9567 * to generic pointer. This is not good, but
9568 * we'll make a guess (and throw a warning).
9571 werror (W_INT_TO_GEN_PTR_CAST);
9575 /* the first two bytes are known */
9576 size = GPTRSIZE - 1;
9578 _startLazyDPSEvaluation ();
9581 aopPut (AOP (result),
9582 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9586 _endLazyDPSEvaluation ();
9588 /* the last byte depending on type */
9606 /* this should never happen */
9607 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9608 "got unknown pointer type");
9611 aopPut (AOP (result), l, GPTRSIZE - 1);
9615 /* just copy the pointers */
9616 size = AOP_SIZE (result);
9618 _startLazyDPSEvaluation ();
9621 aopPut (AOP (result),
9622 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9626 _endLazyDPSEvaluation ();
9630 /* so we now know that the size of destination is greater
9631 than the size of the source */
9632 /* we move to result for the size of source */
9633 size = AOP_SIZE (right);
9635 _startLazyDPSEvaluation ();
9638 aopPut (AOP (result),
9639 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9643 _endLazyDPSEvaluation ();
9645 /* now depending on the sign of the source && destination */
9646 size = AOP_SIZE (result) - AOP_SIZE (right);
9647 /* if unsigned or not an integral type */
9648 /* also, if the source is a bit, we don't need to sign extend, because
9649 * it can't possibly have set the sign bit.
9651 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9655 aopPut (AOP (result), zero, offset++);
9660 /* we need to extend the sign :{ */
9661 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9662 FALSE, FALSE, TRUE);
9664 emitcode ("rlc", "a");
9665 emitcode ("subb", "a,acc");
9667 aopPut (AOP (result), "a", offset++);
9670 /* we are done hurray !!!! */
9673 freeAsmop (right, NULL, ic, TRUE);
9674 freeAsmop (result, NULL, ic, TRUE);
9678 /*-----------------------------------------------------------------*/
9679 /* genDjnz - generate decrement & jump if not zero instrucion */
9680 /*-----------------------------------------------------------------*/
9682 genDjnz (iCode * ic, iCode * ifx)
9688 /* if the if condition has a false label
9689 then we cannot save */
9693 /* if the minus is not of the form
9695 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9696 !IS_OP_LITERAL (IC_RIGHT (ic)))
9699 if (operandLitValue (IC_RIGHT (ic)) != 1)
9702 /* if the size of this greater than one then no
9704 if (getSize (operandType (IC_RESULT (ic))) > 1)
9707 /* otherwise we can save BIG */
9708 D(emitcode(";", "genDjnz"););
9710 lbl = newiTempLabel (NULL);
9711 lbl1 = newiTempLabel (NULL);
9713 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9715 if (AOP_NEEDSACC(IC_RESULT(ic)))
9717 /* If the result is accessed indirectly via
9718 * the accumulator, we must explicitly write
9719 * it back after the decrement.
9721 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9723 if (strcmp(rByte, "a"))
9725 /* Something is hopelessly wrong */
9726 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9727 __FILE__, __LINE__);
9728 /* We can just give up; the generated code will be inefficient,
9731 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9734 emitcode ("dec", "%s", rByte);
9735 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9736 emitcode ("jnz", "%05d$", lbl->key + 100);
9738 else if (IS_AOP_PREG (IC_RESULT (ic)))
9740 emitcode ("dec", "%s",
9741 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9742 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9743 emitcode ("jnz", "%05d$", lbl->key + 100);
9747 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9750 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9751 emitcode ("", "%05d$:", lbl->key + 100);
9752 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9753 emitcode ("", "%05d$:", lbl1->key + 100);
9755 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9760 /*-----------------------------------------------------------------*/
9761 /* genReceive - generate code for a receive iCode */
9762 /*-----------------------------------------------------------------*/
9764 genReceive (iCode * ic)
9767 D (emitcode (";", "genReceive ");
9770 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9771 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9772 IS_TRUE_SYMOP (IC_RESULT (ic))))
9774 int size = getSize (operandType (IC_RESULT (ic)));
9775 int offset = fReturnSizeDS390 - size;
9778 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9779 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9782 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9783 size = AOP_SIZE (IC_RESULT (ic));
9787 emitcode ("pop", "acc");
9788 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9795 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9797 assignResultValue (IC_RESULT (ic));
9800 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9803 /*-----------------------------------------------------------------*/
9804 /* gen390Code - generate code for Dallas 390 based controllers */
9805 /*-----------------------------------------------------------------*/
9807 gen390Code (iCode * lic)
9812 lineHead = lineCurr = NULL;
9816 /* print the allocation information */
9818 printAllocInfo (currFunc, codeOutFile);
9820 /* if debug information required */
9821 if (options.debug && currFunc)
9823 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9825 if (IS_STATIC (currFunc->etype))
9826 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9828 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9831 /* stack pointer name */
9832 if (options.useXstack)
9838 for (ic = lic; ic; ic = ic->next)
9841 if (cln != ic->lineno)
9846 emitcode ("", "C$%s$%d$%d$%d ==.",
9847 FileBaseName (ic->filename), ic->lineno,
9848 ic->level, ic->block);
9851 emitcode (";", "%s %d", ic->filename, ic->lineno);
9854 /* if the result is marked as
9855 spilt and rematerializable or code for
9856 this has already been generated then
9858 if (resultRemat (ic) || ic->generated)
9861 /* depending on the operation */
9881 /* IPOP happens only when trying to restore a
9882 spilt live range, if there is an ifx statement
9883 following this pop then the if statement might
9884 be using some of the registers being popped which
9885 would destory the contents of the register so
9886 we need to check for this condition and handle it */
9888 ic->next->op == IFX &&
9889 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9890 genIfx (ic->next, ic);
9908 genEndFunction (ic);
9928 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9945 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9949 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9956 /* note these two are xlated by algebraic equivalence
9957 during parsing SDCC.y */
9958 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9959 "got '>=' or '<=' shouldn't have come here");
9963 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9975 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9979 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9983 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10007 genRightShift (ic);
10010 case GET_VALUE_AT_ADDRESS:
10011 genPointerGet (ic);
10015 if (POINTER_SET (ic))
10016 genPointerSet (ic);
10042 addSet (&_G.sendSet, ic);
10051 /* now we are ready to call the
10052 peep hole optimizer */
10053 if (!options.nopeep)
10054 peepHole (&lineHead);
10056 /* now do the actual printing */
10057 printLine (lineHead, codeOutFile);