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 if (!size && lit==-1) {
3846 emitcode ("dec", "a");
3848 emitcode ("add", "a,#0x%02x",
3849 (unsigned int) (lit & 0x0FFL));
3852 emitcode ("addc", "a,#0x%02x",
3853 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3859 emitcode ("push", "acc");
3863 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3867 _endLazyDPSEvaluation ();
3871 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3873 size = getDataSize (IC_LEFT (ic));
3874 rSize = getDataSize (IC_RESULT (ic));
3876 ADJUST_PUSHED_RESULT(size, rSize);
3878 _startLazyDPSEvaluation ();
3881 emitcode ("pop", "acc");
3882 aopPut (AOP (IC_RESULT (ic)), "a", size);
3884 _endLazyDPSEvaluation ();
3887 adjustArithmeticResult (ic);
3890 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3891 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3892 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3896 /*-----------------------------------------------------------------*/
3897 /* genMultbits :- multiplication of bits */
3898 /*-----------------------------------------------------------------*/
3900 genMultbits (operand * left,
3904 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3905 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3910 /*-----------------------------------------------------------------*/
3911 /* genMultOneByte : 8*8=8/16 bit multiplication */
3912 /*-----------------------------------------------------------------*/
3914 genMultOneByte (operand * left,
3918 sym_link *opetype = operandType (result);
3920 int size=AOP_SIZE(result);
3922 if (size<1 || size>2) {
3923 // this should never happen
3924 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3925 AOP_SIZE(result), __FILE__, lineno);
3929 /* (if two literals: the value is computed before) */
3930 /* if one literal, literal on the right */
3931 if (AOP_TYPE (left) == AOP_LIT)
3936 emitcode (";", "swapped left and right");
3939 if (SPEC_USIGN(opetype)
3940 // ignore the sign of left and right, what else can we do?
3941 || (SPEC_USIGN(operandType(left)) &&
3942 SPEC_USIGN(operandType(right)))) {
3943 // just an unsigned 8*8=8/16 multiply
3944 //emitcode (";","unsigned");
3945 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3946 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3947 emitcode ("mul", "ab");
3948 aopPut (AOP (result), "a", 0);
3950 aopPut (AOP (result), "b", 1);
3955 // we have to do a signed multiply
3957 emitcode (";", "signed");
3958 emitcode ("clr", "F0"); // reset sign flag
3959 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3961 lbl=newiTempLabel(NULL);
3962 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3963 // left side is negative, 8-bit two's complement, this fails for -128
3964 emitcode ("setb", "F0"); // set sign flag
3965 emitcode ("cpl", "a");
3966 emitcode ("inc", "a");
3968 emitcode ("", "%05d$:", lbl->key+100);
3971 if (AOP_TYPE(right)==AOP_LIT) {
3972 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3973 /* AND literal negative */
3974 if ((int) val < 0) {
3975 emitcode ("cpl", "F0"); // complement sign flag
3976 emitcode ("mov", "b,#0x%02x", -val);
3978 emitcode ("mov", "b,#0x%02x", val);
3981 lbl=newiTempLabel(NULL);
3982 emitcode ("mov", "b,a");
3983 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3984 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3985 // right side is negative, 8-bit two's complement
3986 emitcode ("cpl", "F0"); // complement sign flag
3987 emitcode ("cpl", "a");
3988 emitcode ("inc", "a");
3989 emitcode ("", "%05d$:", lbl->key+100);
3991 emitcode ("mul", "ab");
3993 lbl=newiTempLabel(NULL);
3994 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3995 // only ONE op was negative, we have to do a 8/16-bit two's complement
3996 emitcode ("cpl", "a"); // lsb
3998 emitcode ("inc", "a");
4000 emitcode ("add", "a,#1");
4001 emitcode ("xch", "a,b");
4002 emitcode ("cpl", "a"); // msb
4003 emitcode ("addc", "a,#0");
4004 emitcode ("xch", "a,b");
4007 emitcode ("", "%05d$:", lbl->key+100);
4008 aopPut (AOP (result), "a", 0);
4010 aopPut (AOP (result), "b", 1);
4014 /*-----------------------------------------------------------------*/
4015 /* genMult - generates code for multiplication */
4016 /*-----------------------------------------------------------------*/
4018 genMult (iCode * ic)
4020 operand *left = IC_LEFT (ic);
4021 operand *right = IC_RIGHT (ic);
4022 operand *result = IC_RESULT (ic);
4024 D (emitcode (";", "genMult "););
4026 /* assign the amsops */
4029 /* special cases first */
4031 if (AOP_TYPE (left) == AOP_CRY &&
4032 AOP_TYPE (right) == AOP_CRY)
4034 genMultbits (left, right, result);
4038 /* if both are of size == 1 */
4039 if (AOP_SIZE (left) == 1 &&
4040 AOP_SIZE (right) == 1)
4042 genMultOneByte (left, right, result);
4046 /* should have been converted to function call */
4050 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4051 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4052 freeAsmop (result, NULL, ic, TRUE);
4055 /*-----------------------------------------------------------------*/
4056 /* genDivbits :- division of bits */
4057 /*-----------------------------------------------------------------*/
4059 genDivbits (operand * left,
4066 /* the result must be bit */
4067 LOAD_AB_FOR_DIV (left, right, l);
4068 emitcode ("div", "ab");
4069 emitcode ("rrc", "a");
4070 aopPut (AOP (result), "c", 0);
4073 /*-----------------------------------------------------------------*/
4074 /* genDivOneByte : 8 bit division */
4075 /*-----------------------------------------------------------------*/
4077 genDivOneByte (operand * left,
4081 sym_link *opetype = operandType (result);
4086 size = AOP_SIZE (result) - 1;
4088 /* signed or unsigned */
4089 if (SPEC_USIGN (opetype))
4091 /* unsigned is easy */
4092 LOAD_AB_FOR_DIV (left, right, l);
4093 emitcode ("div", "ab");
4094 aopPut (AOP (result), "a", 0);
4096 aopPut (AOP (result), zero, offset++);
4100 /* signed is a little bit more difficult */
4102 /* save the signs of the operands */
4103 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4105 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4106 emitcode ("push", "acc"); /* save it on the stack */
4108 /* now sign adjust for both left & right */
4109 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4111 lbl = newiTempLabel (NULL);
4112 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4113 emitcode ("cpl", "a");
4114 emitcode ("inc", "a");
4115 emitcode ("", "%05d$:", (lbl->key + 100));
4116 emitcode ("mov", "b,a");
4118 /* sign adjust left side */
4119 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4122 lbl = newiTempLabel (NULL);
4123 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4124 emitcode ("cpl", "a");
4125 emitcode ("inc", "a");
4126 emitcode ("", "%05d$:", (lbl->key + 100));
4128 /* now the division */
4129 emitcode ("nop", "; workaround for DS80C390 div bug.");
4130 emitcode ("div", "ab");
4131 /* we are interested in the lower order
4133 emitcode ("mov", "b,a");
4134 lbl = newiTempLabel (NULL);
4135 emitcode ("pop", "acc");
4136 /* if there was an over flow we don't
4137 adjust the sign of the result */
4138 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4139 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4141 emitcode ("clr", "a");
4142 emitcode ("subb", "a,b");
4143 emitcode ("mov", "b,a");
4144 emitcode ("", "%05d$:", (lbl->key + 100));
4146 /* now we are done */
4147 aopPut (AOP (result), "b", 0);
4150 emitcode ("mov", "c,b.7");
4151 emitcode ("subb", "a,acc");
4154 aopPut (AOP (result), "a", offset++);
4158 /*-----------------------------------------------------------------*/
4159 /* genDiv - generates code for division */
4160 /*-----------------------------------------------------------------*/
4164 operand *left = IC_LEFT (ic);
4165 operand *right = IC_RIGHT (ic);
4166 operand *result = IC_RESULT (ic);
4168 D (emitcode (";", "genDiv ");
4171 /* assign the amsops */
4174 /* special cases first */
4176 if (AOP_TYPE (left) == AOP_CRY &&
4177 AOP_TYPE (right) == AOP_CRY)
4179 genDivbits (left, right, result);
4183 /* if both are of size == 1 */
4184 if (AOP_SIZE (left) == 1 &&
4185 AOP_SIZE (right) == 1)
4187 genDivOneByte (left, right, result);
4191 /* should have been converted to function call */
4194 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4195 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4196 freeAsmop (result, NULL, ic, TRUE);
4199 /*-----------------------------------------------------------------*/
4200 /* genModbits :- modulus of bits */
4201 /*-----------------------------------------------------------------*/
4203 genModbits (operand * left,
4210 /* the result must be bit */
4211 LOAD_AB_FOR_DIV (left, right, l);
4212 emitcode ("div", "ab");
4213 emitcode ("mov", "a,b");
4214 emitcode ("rrc", "a");
4215 aopPut (AOP (result), "c", 0);
4218 /*-----------------------------------------------------------------*/
4219 /* genModOneByte : 8 bit modulus */
4220 /*-----------------------------------------------------------------*/
4222 genModOneByte (operand * left,
4226 sym_link *opetype = operandType (result);
4230 /* signed or unsigned */
4231 if (SPEC_USIGN (opetype))
4233 /* unsigned is easy */
4234 LOAD_AB_FOR_DIV (left, right, l);
4235 emitcode ("div", "ab");
4236 aopPut (AOP (result), "b", 0);
4240 /* signed is a little bit more difficult */
4242 /* save the signs of the operands */
4243 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4246 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4247 emitcode ("push", "acc"); /* save it on the stack */
4249 /* now sign adjust for both left & right */
4250 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4253 lbl = newiTempLabel (NULL);
4254 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4255 emitcode ("cpl", "a");
4256 emitcode ("inc", "a");
4257 emitcode ("", "%05d$:", (lbl->key + 100));
4258 emitcode ("mov", "b,a");
4260 /* sign adjust left side */
4261 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4264 lbl = newiTempLabel (NULL);
4265 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4266 emitcode ("cpl", "a");
4267 emitcode ("inc", "a");
4268 emitcode ("", "%05d$:", (lbl->key + 100));
4270 /* now the multiplication */
4271 emitcode ("nop", "; workaround for DS80C390 div bug.");
4272 emitcode ("div", "ab");
4273 /* we are interested in the lower order
4275 lbl = newiTempLabel (NULL);
4276 emitcode ("pop", "acc");
4277 /* if there was an over flow we don't
4278 adjust the sign of the result */
4279 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4280 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4282 emitcode ("clr", "a");
4283 emitcode ("subb", "a,b");
4284 emitcode ("mov", "b,a");
4285 emitcode ("", "%05d$:", (lbl->key + 100));
4287 /* now we are done */
4288 aopPut (AOP (result), "b", 0);
4292 /*-----------------------------------------------------------------*/
4293 /* genMod - generates code for division */
4294 /*-----------------------------------------------------------------*/
4298 operand *left = IC_LEFT (ic);
4299 operand *right = IC_RIGHT (ic);
4300 operand *result = IC_RESULT (ic);
4302 D (emitcode (";", "genMod ");
4305 /* assign the amsops */
4308 /* special cases first */
4310 if (AOP_TYPE (left) == AOP_CRY &&
4311 AOP_TYPE (right) == AOP_CRY)
4313 genModbits (left, right, result);
4317 /* if both are of size == 1 */
4318 if (AOP_SIZE (left) == 1 &&
4319 AOP_SIZE (right) == 1)
4321 genModOneByte (left, right, result);
4325 /* should have been converted to function call */
4329 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4330 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4331 freeAsmop (result, NULL, ic, TRUE);
4334 /*-----------------------------------------------------------------*/
4335 /* genIfxJump :- will create a jump depending on the ifx */
4336 /*-----------------------------------------------------------------*/
4338 genIfxJump (iCode * ic, char *jval)
4341 symbol *tlbl = newiTempLabel (NULL);
4344 D (emitcode (";", "genIfxJump ");
4347 /* if true label then we jump if condition
4351 jlbl = IC_TRUE (ic);
4352 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4353 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4357 /* false label is present */
4358 jlbl = IC_FALSE (ic);
4359 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4360 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4362 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4363 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4365 emitcode (inst, "%05d$", tlbl->key + 100);
4366 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4367 emitcode ("", "%05d$:", tlbl->key + 100);
4369 /* mark the icode as generated */
4373 /*-----------------------------------------------------------------*/
4374 /* genCmp :- greater or less than comparison */
4375 /*-----------------------------------------------------------------*/
4377 genCmp (operand * left, operand * right,
4378 iCode * ic, iCode * ifx, int sign)
4380 int size, offset = 0;
4381 unsigned long lit = 0L;
4384 D (emitcode (";", "genCmp");
4387 result = IC_RESULT (ic);
4389 /* if left & right are bit variables */
4390 if (AOP_TYPE (left) == AOP_CRY &&
4391 AOP_TYPE (right) == AOP_CRY)
4393 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4394 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4398 /* subtract right from left if at the
4399 end the carry flag is set then we know that
4400 left is greater than right */
4401 size = max (AOP_SIZE (left), AOP_SIZE (right));
4403 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4404 if ((size == 1) && !sign &&
4405 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4407 symbol *lbl = newiTempLabel (NULL);
4408 emitcode ("cjne", "%s,%s,%05d$",
4409 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4410 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4412 emitcode ("", "%05d$:", lbl->key + 100);
4416 if (AOP_TYPE (right) == AOP_LIT)
4418 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4419 /* optimize if(x < 0) or if(x >= 0) */
4428 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4430 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4431 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4433 aopOp (result, ic, FALSE, FALSE);
4435 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4437 freeAsmop (result, NULL, ic, TRUE);
4438 genIfxJump (ifx, "acc.7");
4443 emitcode ("rlc", "a");
4445 goto release_freedLR;
4453 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4454 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4455 emitcode (";", "genCmp #2");
4456 if (sign && (size == 0))
4458 emitcode (";", "genCmp #3");
4459 emitcode ("xrl", "a,#0x80");
4460 if (AOP_TYPE (right) == AOP_LIT)
4462 unsigned long lit = (unsigned long)
4463 floatFromVal (AOP (right)->aopu.aop_lit);
4464 emitcode (";", "genCmp #3.1");
4465 emitcode ("subb", "a,#0x%02x",
4466 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4470 emitcode (";", "genCmp #3.2");
4471 if (AOP_NEEDSACC (right))
4473 emitcode ("push", "acc");
4475 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4476 FALSE, FALSE, FALSE));
4477 emitcode ("xrl", "b,#0x80");
4478 if (AOP_NEEDSACC (right))
4480 emitcode ("pop", "acc");
4482 emitcode ("subb", "a,b");
4489 emitcode (";", "genCmp #4");
4490 if (AOP_NEEDSACC (right))
4493 emitcode (";", "genCmp #4.1");
4494 emitcode ("xch", "a, b");
4495 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4496 emitcode ("xch", "a, b");
4501 emitcode (";", "genCmp #4.2");
4502 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4505 emitcode ("subb", "a,%s", s);
4512 /* Don't need the left & right operands any more; do need the result. */
4513 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4514 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516 aopOp (result, ic, FALSE, FALSE);
4520 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4526 /* if the result is used in the next
4527 ifx conditional branch then generate
4528 code a little differently */
4531 genIfxJump (ifx, "c");
4537 /* leave the result in acc */
4539 freeAsmop (result, NULL, ic, TRUE);
4542 /*-----------------------------------------------------------------*/
4543 /* genCmpGt :- greater than comparison */
4544 /*-----------------------------------------------------------------*/
4546 genCmpGt (iCode * ic, iCode * ifx)
4548 operand *left, *right;
4549 sym_link *letype, *retype;
4552 D (emitcode (";", "genCmpGt ");
4555 left = IC_LEFT (ic);
4556 right = IC_RIGHT (ic);
4558 letype = getSpec (operandType (left));
4559 retype = getSpec (operandType (right));
4560 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4562 /* assign the left & right amsops */
4565 genCmp (right, left, ic, ifx, sign);
4568 /*-----------------------------------------------------------------*/
4569 /* genCmpLt - less than comparisons */
4570 /*-----------------------------------------------------------------*/
4572 genCmpLt (iCode * ic, iCode * ifx)
4574 operand *left, *right;
4575 sym_link *letype, *retype;
4578 D (emitcode (";", "genCmpLt "););
4580 left = IC_LEFT (ic);
4581 right = IC_RIGHT (ic);
4583 letype = getSpec (operandType (left));
4584 retype = getSpec (operandType (right));
4585 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4587 /* assign the left & right amsops */
4590 genCmp (left, right, ic, ifx, sign);
4593 /*-----------------------------------------------------------------*/
4594 /* gencjneshort - compare and jump if not equal */
4595 /*-----------------------------------------------------------------*/
4597 gencjneshort (operand * left, operand * right, symbol * lbl)
4599 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4601 unsigned long lit = 0L;
4603 D (emitcode (";", "gencjneshort");
4606 /* if the left side is a literal or
4607 if the right is in a pointer register and left
4609 if ((AOP_TYPE (left) == AOP_LIT) ||
4610 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4617 if (AOP_TYPE (right) == AOP_LIT)
4618 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4620 if (opIsGptr (left) || opIsGptr (right))
4622 /* We are comparing a generic pointer to something.
4623 * Exclude the generic type byte from the comparison.
4626 D (emitcode (";", "cjneshort: generic ptr special case.");
4631 /* if the right side is a literal then anything goes */
4632 if (AOP_TYPE (right) == AOP_LIT &&
4633 AOP_TYPE (left) != AOP_DIR)
4637 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4639 emitcode ("cjne", "a,%s,%05d$",
4640 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4646 /* if the right side is in a register or in direct space or
4647 if the left is a pointer register & right is not */
4648 else if (AOP_TYPE (right) == AOP_REG ||
4649 AOP_TYPE (right) == AOP_DIR ||
4650 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4651 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4655 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4656 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4657 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4658 emitcode ("jnz", "%05d$", lbl->key + 100);
4660 emitcode ("cjne", "a,%s,%05d$",
4661 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4668 /* right is a pointer reg need both a & b */
4671 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4672 if (strcmp (l, "b"))
4673 emitcode ("mov", "b,%s", l);
4674 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4675 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4681 /*-----------------------------------------------------------------*/
4682 /* gencjne - compare and jump if not equal */
4683 /*-----------------------------------------------------------------*/
4685 gencjne (operand * left, operand * right, symbol * lbl)
4687 symbol *tlbl = newiTempLabel (NULL);
4689 D (emitcode (";", "gencjne");
4692 gencjneshort (left, right, lbl);
4694 emitcode ("mov", "a,%s", one);
4695 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4696 emitcode ("", "%05d$:", lbl->key + 100);
4697 emitcode ("clr", "a");
4698 emitcode ("", "%05d$:", tlbl->key + 100);
4701 /*-----------------------------------------------------------------*/
4702 /* genCmpEq - generates code for equal to */
4703 /*-----------------------------------------------------------------*/
4705 genCmpEq (iCode * ic, iCode * ifx)
4707 operand *left, *right, *result;
4709 D (emitcode (";", "genCmpEq ");
4713 AOP_SET_LOCALS (ic);
4715 /* if literal, literal on the right or
4716 if the right is in a pointer register and left
4718 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4719 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4721 operand *t = IC_RIGHT (ic);
4722 IC_RIGHT (ic) = IC_LEFT (ic);
4726 if (ifx && /* !AOP_SIZE(result) */
4727 OP_SYMBOL (result) &&
4728 OP_SYMBOL (result)->regType == REG_CND)
4731 /* if they are both bit variables */
4732 if (AOP_TYPE (left) == AOP_CRY &&
4733 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4735 if (AOP_TYPE (right) == AOP_LIT)
4737 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4740 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4741 emitcode ("cpl", "c");
4745 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4749 emitcode ("clr", "c");
4751 /* AOP_TYPE(right) == AOP_CRY */
4755 symbol *lbl = newiTempLabel (NULL);
4756 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4757 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4758 emitcode ("cpl", "c");
4759 emitcode ("", "%05d$:", (lbl->key + 100));
4761 /* if true label then we jump if condition
4763 tlbl = newiTempLabel (NULL);
4766 emitcode ("jnc", "%05d$", tlbl->key + 100);
4767 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4771 emitcode ("jc", "%05d$", tlbl->key + 100);
4772 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4774 emitcode ("", "%05d$:", tlbl->key + 100);
4778 tlbl = newiTempLabel (NULL);
4779 gencjneshort (left, right, tlbl);
4782 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4783 emitcode ("", "%05d$:", tlbl->key + 100);
4787 symbol *lbl = newiTempLabel (NULL);
4788 emitcode ("sjmp", "%05d$", lbl->key + 100);
4789 emitcode ("", "%05d$:", tlbl->key + 100);
4790 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4791 emitcode ("", "%05d$:", lbl->key + 100);
4794 /* mark the icode as generated */
4797 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4798 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4802 /* if they are both bit variables */
4803 if (AOP_TYPE (left) == AOP_CRY &&
4804 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4806 if (AOP_TYPE (right) == AOP_LIT)
4808 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4811 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4812 emitcode ("cpl", "c");
4816 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4820 emitcode ("clr", "c");
4822 /* AOP_TYPE(right) == AOP_CRY */
4826 symbol *lbl = newiTempLabel (NULL);
4827 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4828 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4829 emitcode ("cpl", "c");
4830 emitcode ("", "%05d$:", (lbl->key + 100));
4833 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4834 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4836 aopOp (result, ic, TRUE, FALSE);
4839 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4846 genIfxJump (ifx, "c");
4849 /* if the result is used in an arithmetic operation
4850 then put the result in place */
4855 gencjne (left, right, newiTempLabel (NULL));
4857 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4858 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4860 aopOp (result, ic, TRUE, FALSE);
4862 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4864 aopPut (AOP (result), "a", 0);
4869 genIfxJump (ifx, "a");
4872 /* if the result is used in an arithmetic operation
4873 then put the result in place */
4874 if (AOP_TYPE (result) != AOP_CRY)
4876 /* leave the result in acc */
4880 freeAsmop (result, NULL, ic, TRUE);
4883 /*-----------------------------------------------------------------*/
4884 /* ifxForOp - returns the icode containing the ifx for operand */
4885 /*-----------------------------------------------------------------*/
4887 ifxForOp (operand * op, iCode * ic)
4889 /* if true symbol then needs to be assigned */
4890 if (IS_TRUE_SYMOP (op))
4893 /* if this has register type condition and
4894 the next instruction is ifx with the same operand
4895 and live to of the operand is upto the ifx only then */
4897 ic->next->op == IFX &&
4898 IC_COND (ic->next)->key == op->key &&
4899 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4904 /*-----------------------------------------------------------------*/
4905 /* genAndOp - for && operation */
4906 /*-----------------------------------------------------------------*/
4908 genAndOp (iCode * ic)
4910 operand *left, *right, *result;
4913 D (emitcode (";", "genAndOp "););
4915 /* note here that && operations that are in an
4916 if statement are taken away by backPatchLabels
4917 only those used in arthmetic operations remain */
4919 AOP_SET_LOCALS (ic);
4921 /* if both are bit variables */
4922 if (AOP_TYPE (left) == AOP_CRY &&
4923 AOP_TYPE (right) == AOP_CRY)
4925 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4926 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4927 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4928 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4930 aopOp (result,ic,FALSE, FALSE);
4935 tlbl = newiTempLabel (NULL);
4937 emitcode ("jz", "%05d$", tlbl->key + 100);
4939 emitcode ("", "%05d$:", tlbl->key + 100);
4940 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4941 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943 aopOp (result,ic,FALSE, FALSE);
4946 freeAsmop (result, NULL, ic, TRUE);
4950 /*-----------------------------------------------------------------*/
4951 /* genOrOp - for || operation */
4952 /*-----------------------------------------------------------------*/
4954 genOrOp (iCode * ic)
4956 operand *left, *right, *result;
4959 D (emitcode (";", "genOrOp "););
4961 /* note here that || operations that are in an
4962 if statement are taken away by backPatchLabels
4963 only those used in arthmetic operations remain */
4965 AOP_SET_LOCALS (ic);
4967 /* if both are bit variables */
4968 if (AOP_TYPE (left) == AOP_CRY &&
4969 AOP_TYPE (right) == AOP_CRY)
4971 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4972 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4973 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4974 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4976 aopOp (result,ic,FALSE, FALSE);
4982 tlbl = newiTempLabel (NULL);
4984 emitcode ("jnz", "%05d$", tlbl->key + 100);
4986 emitcode ("", "%05d$:", tlbl->key + 100);
4987 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4988 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4990 aopOp (result,ic,FALSE, FALSE);
4995 freeAsmop (result, NULL, ic, TRUE);
4998 /*-----------------------------------------------------------------*/
4999 /* isLiteralBit - test if lit == 2^n */
5000 /*-----------------------------------------------------------------*/
5002 isLiteralBit (unsigned long lit)
5004 unsigned long pw[32] =
5005 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5006 0x100L, 0x200L, 0x400L, 0x800L,
5007 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5008 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5009 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5010 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5011 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5014 for (idx = 0; idx < 32; idx++)
5020 /*-----------------------------------------------------------------*/
5021 /* continueIfTrue - */
5022 /*-----------------------------------------------------------------*/
5024 continueIfTrue (iCode * ic)
5027 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5031 /*-----------------------------------------------------------------*/
5033 /*-----------------------------------------------------------------*/
5035 jumpIfTrue (iCode * ic)
5038 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5042 /*-----------------------------------------------------------------*/
5043 /* jmpTrueOrFalse - */
5044 /*-----------------------------------------------------------------*/
5046 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5048 // ugly but optimized by peephole
5051 symbol *nlbl = newiTempLabel (NULL);
5052 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5053 emitcode ("", "%05d$:", tlbl->key + 100);
5054 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5055 emitcode ("", "%05d$:", nlbl->key + 100);
5059 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5060 emitcode ("", "%05d$:", tlbl->key + 100);
5065 // Generate code to perform a bit-wise logic operation
5066 // on two operands in far space (assumed to already have been
5067 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5068 // in far space. This requires pushing the result on the stack
5069 // then popping it into the result.
5071 genFarFarLogicOp(iCode *ic, char *logicOp)
5073 int size, resultSize, compSize;
5076 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5077 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5078 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5080 _startLazyDPSEvaluation();
5081 for (size = compSize; (size--); offset++)
5083 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5084 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5085 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5087 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5088 emitcode ("push", "acc");
5090 _endLazyDPSEvaluation();
5092 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5093 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5094 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5096 resultSize = AOP_SIZE(IC_RESULT(ic));
5098 ADJUST_PUSHED_RESULT(compSize, resultSize);
5100 _startLazyDPSEvaluation();
5103 emitcode ("pop", "acc");
5104 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5106 _endLazyDPSEvaluation();
5107 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5111 /*-----------------------------------------------------------------*/
5112 /* genAnd - code for and */
5113 /*-----------------------------------------------------------------*/
5115 genAnd (iCode * ic, iCode * ifx)
5117 operand *left, *right, *result;
5118 int size, offset = 0;
5119 unsigned long lit = 0L;
5124 D (emitcode (";", "genAnd "););
5126 AOP_OP_3_NOFATAL (ic, pushResult);
5127 AOP_SET_LOCALS (ic);
5131 genFarFarLogicOp(ic, "anl");
5136 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5138 AOP_TYPE (left), AOP_TYPE (right));
5139 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5141 AOP_SIZE (left), AOP_SIZE (right));
5144 /* if left is a literal & right is not then exchange them */
5145 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5146 AOP_NEEDSACC (left))
5148 operand *tmp = right;
5153 /* if result = right then exchange them */
5154 if (sameRegs (AOP (result), AOP (right)))
5156 operand *tmp = right;
5161 /* if right is bit then exchange them */
5162 if (AOP_TYPE (right) == AOP_CRY &&
5163 AOP_TYPE (left) != AOP_CRY)
5165 operand *tmp = right;
5169 if (AOP_TYPE (right) == AOP_LIT)
5170 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5172 size = AOP_SIZE (result);
5175 // result = bit & yy;
5176 if (AOP_TYPE (left) == AOP_CRY)
5178 // c = bit & literal;
5179 if (AOP_TYPE (right) == AOP_LIT)
5183 if (size && sameRegs (AOP (result), AOP (left)))
5186 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5191 if (size && (AOP_TYPE (result) == AOP_CRY))
5193 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5196 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5201 emitcode ("clr", "c");
5206 if (AOP_TYPE (right) == AOP_CRY)
5209 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5210 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5215 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5217 emitcode ("rrc", "a");
5218 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5226 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5227 genIfxJump (ifx, "c");
5231 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5232 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5233 if ((AOP_TYPE (right) == AOP_LIT) &&
5234 (AOP_TYPE (result) == AOP_CRY) &&
5235 (AOP_TYPE (left) != AOP_CRY))
5237 int posbit = isLiteralBit (lit);
5242 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5245 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5251 sprintf (buffer, "acc.%d", posbit & 0x07);
5252 genIfxJump (ifx, buffer);
5259 symbol *tlbl = newiTempLabel (NULL);
5260 int sizel = AOP_SIZE (left);
5262 emitcode ("setb", "c");
5265 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5267 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5269 if ((posbit = isLiteralBit (bytelit)) != 0)
5270 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5273 if (bytelit != 0x0FFL)
5274 emitcode ("anl", "a,%s",
5275 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5276 emitcode ("jnz", "%05d$", tlbl->key + 100);
5281 // bit = left & literal
5284 emitcode ("clr", "c");
5285 emitcode ("", "%05d$:", tlbl->key + 100);
5287 // if(left & literal)
5291 jmpTrueOrFalse (ifx, tlbl);
5299 /* if left is same as result */
5300 if (sameRegs (AOP (result), AOP (left)))
5302 for (; size--; offset++)
5304 if (AOP_TYPE (right) == AOP_LIT)
5306 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5308 else if (bytelit == 0)
5309 aopPut (AOP (result), zero, offset);
5310 else if (IS_AOP_PREG (result))
5312 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5313 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5314 aopPut (AOP (result), "a", offset);
5317 emitcode ("anl", "%s,%s",
5318 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5319 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5323 if (AOP_TYPE (left) == AOP_ACC)
5324 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5327 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5328 if (IS_AOP_PREG (result))
5330 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5331 aopPut (AOP (result), "a", offset);
5335 emitcode ("anl", "%s,a",
5336 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5343 // left & result in different registers
5344 if (AOP_TYPE (result) == AOP_CRY)
5347 // if(size), result in bit
5348 // if(!size && ifx), conditional oper: if(left & right)
5349 symbol *tlbl = newiTempLabel (NULL);
5350 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5352 emitcode ("setb", "c");
5355 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5356 emitcode ("anl", "a,%s",
5357 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5359 if (AOP_TYPE(left)==AOP_ACC) {
5360 emitcode("mov", "b,a");
5361 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5362 emitcode("anl", "a,b");
5364 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5365 emitcode ("anl", "a,%s",
5366 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5369 emitcode ("jnz", "%05d$", tlbl->key + 100);
5375 emitcode ("", "%05d$:", tlbl->key + 100);
5379 jmpTrueOrFalse (ifx, tlbl);
5383 for (; (size--); offset++)
5386 // result = left & right
5387 if (AOP_TYPE (right) == AOP_LIT)
5389 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5391 aopPut (AOP (result),
5392 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5396 else if (bytelit == 0)
5398 aopPut (AOP (result), zero, offset);
5401 D (emitcode (";", "better literal AND.");
5403 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5404 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5405 FALSE, FALSE, FALSE));
5410 // faster than result <- left, anl result,right
5411 // and better if result is SFR
5412 if (AOP_TYPE (left) == AOP_ACC)
5414 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5415 FALSE, FALSE, FALSE));
5419 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5420 emitcode ("anl", "a,%s",
5421 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5424 aopPut (AOP (result), "a", offset);
5430 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5431 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5432 freeAsmop (result, NULL, ic, TRUE);
5436 /*-----------------------------------------------------------------*/
5437 /* genOr - code for or */
5438 /*-----------------------------------------------------------------*/
5440 genOr (iCode * ic, iCode * ifx)
5442 operand *left, *right, *result;
5443 int size, offset = 0;
5444 unsigned long lit = 0L;
5447 D (emitcode (";", "genOr "););
5449 AOP_OP_3_NOFATAL (ic, pushResult);
5450 AOP_SET_LOCALS (ic);
5454 genFarFarLogicOp(ic, "orl");
5460 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5462 AOP_TYPE (left), AOP_TYPE (right));
5463 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5465 AOP_SIZE (left), AOP_SIZE (right));
5468 /* if left is a literal & right is not then exchange them */
5469 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5470 AOP_NEEDSACC (left))
5472 operand *tmp = right;
5477 /* if result = right then exchange them */
5478 if (sameRegs (AOP (result), AOP (right)))
5480 operand *tmp = right;
5485 /* if right is bit then exchange them */
5486 if (AOP_TYPE (right) == AOP_CRY &&
5487 AOP_TYPE (left) != AOP_CRY)
5489 operand *tmp = right;
5493 if (AOP_TYPE (right) == AOP_LIT)
5494 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5496 size = AOP_SIZE (result);
5500 if (AOP_TYPE (left) == AOP_CRY)
5502 if (AOP_TYPE (right) == AOP_LIT)
5504 // c = bit & literal;
5507 // lit != 0 => result = 1
5508 if (AOP_TYPE (result) == AOP_CRY)
5511 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5513 continueIfTrue (ifx);
5516 emitcode ("setb", "c");
5520 // lit == 0 => result = left
5521 if (size && sameRegs (AOP (result), AOP (left)))
5523 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5528 if (AOP_TYPE (right) == AOP_CRY)
5531 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5532 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5537 symbol *tlbl = newiTempLabel (NULL);
5538 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5539 emitcode ("setb", "c");
5540 emitcode ("jb", "%s,%05d$",
5541 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5543 emitcode ("jnz", "%05d$", tlbl->key + 100);
5544 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5546 jmpTrueOrFalse (ifx, tlbl);
5552 emitcode ("", "%05d$:", tlbl->key + 100);
5561 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5562 genIfxJump (ifx, "c");
5566 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5567 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5568 if ((AOP_TYPE (right) == AOP_LIT) &&
5569 (AOP_TYPE (result) == AOP_CRY) &&
5570 (AOP_TYPE (left) != AOP_CRY))
5576 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5578 continueIfTrue (ifx);
5583 // lit = 0, result = boolean(left)
5585 emitcode ("setb", "c");
5589 symbol *tlbl = newiTempLabel (NULL);
5590 emitcode ("jnz", "%05d$", tlbl->key + 100);
5592 emitcode ("", "%05d$:", tlbl->key + 100);
5596 genIfxJump (ifx, "a");
5604 /* if left is same as result */
5605 if (sameRegs (AOP (result), AOP (left)))
5607 for (; size--; offset++)
5609 if (AOP_TYPE (right) == AOP_LIT)
5611 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5617 if (IS_AOP_PREG (left))
5619 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5620 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5621 aopPut (AOP (result), "a", offset);
5625 emitcode ("orl", "%s,%s",
5626 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5627 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5633 if (AOP_TYPE (left) == AOP_ACC)
5635 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5639 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5640 if (IS_AOP_PREG (left))
5642 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5643 aopPut (AOP (result), "a", offset);
5647 emitcode ("orl", "%s,a",
5648 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5656 // left & result in different registers
5657 if (AOP_TYPE (result) == AOP_CRY)
5660 // if(size), result in bit
5661 // if(!size && ifx), conditional oper: if(left | right)
5662 symbol *tlbl = newiTempLabel (NULL);
5663 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5665 emitcode ("setb", "c");
5668 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5669 emitcode ("orl", "a,%s",
5670 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5672 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5673 emitcode ("orl", "a,%s",
5674 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5676 emitcode ("jnz", "%05d$", tlbl->key + 100);
5682 emitcode ("", "%05d$:", tlbl->key + 100);
5686 jmpTrueOrFalse (ifx, tlbl);
5690 for (; (size--); offset++)
5693 // result = left & right
5694 if (AOP_TYPE (right) == AOP_LIT)
5696 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5698 aopPut (AOP (result),
5699 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5703 D (emitcode (";", "better literal OR.");
5705 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5706 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5707 FALSE, FALSE, FALSE));
5712 // faster than result <- left, anl result,right
5713 // and better if result is SFR
5714 if (AOP_TYPE (left) == AOP_ACC)
5716 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5717 FALSE, FALSE, FALSE));
5721 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5722 emitcode ("orl", "a,%s",
5723 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5726 aopPut (AOP (result), "a", offset);
5732 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5733 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5734 freeAsmop (result, NULL, ic, TRUE);
5737 /*-----------------------------------------------------------------*/
5738 /* genXor - code for xclusive or */
5739 /*-----------------------------------------------------------------*/
5741 genXor (iCode * ic, iCode * ifx)
5743 operand *left, *right, *result;
5744 int size, offset = 0;
5745 unsigned long lit = 0L;
5748 D (emitcode (";", "genXor "););
5750 AOP_OP_3_NOFATAL (ic, pushResult);
5751 AOP_SET_LOCALS (ic);
5755 genFarFarLogicOp(ic, "xrl");
5760 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5762 AOP_TYPE (left), AOP_TYPE (right));
5763 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5765 AOP_SIZE (left), AOP_SIZE (right));
5768 /* if left is a literal & right is not ||
5769 if left needs acc & right does not */
5770 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5771 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5773 operand *tmp = right;
5778 /* if result = right then exchange them */
5779 if (sameRegs (AOP (result), AOP (right)))
5781 operand *tmp = right;
5786 /* if right is bit then exchange them */
5787 if (AOP_TYPE (right) == AOP_CRY &&
5788 AOP_TYPE (left) != AOP_CRY)
5790 operand *tmp = right;
5794 if (AOP_TYPE (right) == AOP_LIT)
5795 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5797 size = AOP_SIZE (result);
5801 if (AOP_TYPE (left) == AOP_CRY)
5803 if (AOP_TYPE (right) == AOP_LIT)
5805 // c = bit & literal;
5808 // lit>>1 != 0 => result = 1
5809 if (AOP_TYPE (result) == AOP_CRY)
5812 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5814 continueIfTrue (ifx);
5817 emitcode ("setb", "c");
5824 // lit == 0, result = left
5825 if (size && sameRegs (AOP (result), AOP (left)))
5827 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5831 // lit == 1, result = not(left)
5832 if (size && sameRegs (AOP (result), AOP (left)))
5834 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5839 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5840 emitcode ("cpl", "c");
5849 symbol *tlbl = newiTempLabel (NULL);
5850 if (AOP_TYPE (right) == AOP_CRY)
5853 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5857 int sizer = AOP_SIZE (right);
5859 // if val>>1 != 0, result = 1
5860 emitcode ("setb", "c");
5863 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5865 // test the msb of the lsb
5866 emitcode ("anl", "a,#0xfe");
5867 emitcode ("jnz", "%05d$", tlbl->key + 100);
5871 emitcode ("rrc", "a");
5873 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5874 emitcode ("cpl", "c");
5875 emitcode ("", "%05d$:", (tlbl->key + 100));
5882 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5883 genIfxJump (ifx, "c");
5887 if (sameRegs (AOP (result), AOP (left)))
5889 /* if left is same as result */
5890 for (; size--; offset++)
5892 if (AOP_TYPE (right) == AOP_LIT)
5894 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5896 else if (IS_AOP_PREG (left))
5898 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5899 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5900 aopPut (AOP (result), "a", offset);
5903 emitcode ("xrl", "%s,%s",
5904 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5905 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5909 if (AOP_TYPE (left) == AOP_ACC)
5910 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5913 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5914 if (IS_AOP_PREG (left))
5916 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5917 aopPut (AOP (result), "a", offset);
5920 emitcode ("xrl", "%s,a",
5921 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5928 // left & result in different registers
5929 if (AOP_TYPE (result) == AOP_CRY)
5932 // if(size), result in bit
5933 // if(!size && ifx), conditional oper: if(left ^ right)
5934 symbol *tlbl = newiTempLabel (NULL);
5935 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5937 emitcode ("setb", "c");
5940 if ((AOP_TYPE (right) == AOP_LIT) &&
5941 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5943 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5947 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5948 emitcode ("xrl", "a,%s",
5949 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5951 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5952 emitcode ("xrl", "a,%s",
5953 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5956 emitcode ("jnz", "%05d$", tlbl->key + 100);
5962 emitcode ("", "%05d$:", tlbl->key + 100);
5966 jmpTrueOrFalse (ifx, tlbl);
5969 for (; (size--); offset++)
5972 // result = left & right
5973 if (AOP_TYPE (right) == AOP_LIT)
5975 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5977 aopPut (AOP (result),
5978 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5982 D (emitcode (";", "better literal XOR.");
5984 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5985 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5986 FALSE, FALSE, FALSE));
5990 // faster than result <- left, anl result,right
5991 // and better if result is SFR
5992 if (AOP_TYPE (left) == AOP_ACC)
5994 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5995 FALSE, FALSE, FALSE));
5999 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6000 emitcode ("xrl", "a,%s",
6001 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6004 aopPut (AOP (result), "a", offset);
6009 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6010 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6011 freeAsmop (result, NULL, ic, TRUE);
6014 /*-----------------------------------------------------------------*/
6015 /* genInline - write the inline code out */
6016 /*-----------------------------------------------------------------*/
6018 genInline (iCode * ic)
6020 char *buffer, *bp, *bp1;
6022 D (emitcode (";", "genInline ");
6025 _G.inLine += (!options.asmpeep);
6027 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6028 strcpy (buffer, IC_INLINE (ic));
6030 /* emit each line as a code */
6055 /* emitcode("",buffer); */
6056 _G.inLine -= (!options.asmpeep);
6059 /*-----------------------------------------------------------------*/
6060 /* genRRC - rotate right with carry */
6061 /*-----------------------------------------------------------------*/
6065 operand *left, *result;
6066 int size, offset = 0;
6069 D (emitcode (";", "genRRC ");
6072 /* rotate right with carry */
6073 left = IC_LEFT (ic);
6074 result = IC_RESULT (ic);
6075 aopOp (left, ic, FALSE, FALSE);
6076 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6078 /* move it to the result */
6079 size = AOP_SIZE (result);
6083 _startLazyDPSEvaluation ();
6086 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6088 emitcode ("rrc", "a");
6089 if (AOP_SIZE (result) > 1)
6090 aopPut (AOP (result), "a", offset--);
6092 _endLazyDPSEvaluation ();
6094 /* now we need to put the carry into the
6095 highest order byte of the result */
6096 if (AOP_SIZE (result) > 1)
6098 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6101 emitcode ("mov", "acc.7,c");
6102 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6103 freeAsmop (left, NULL, ic, TRUE);
6104 freeAsmop (result, NULL, ic, TRUE);
6107 /*-----------------------------------------------------------------*/
6108 /* genRLC - generate code for rotate left with carry */
6109 /*-----------------------------------------------------------------*/
6113 operand *left, *result;
6114 int size, offset = 0;
6117 D (emitcode (";", "genRLC ");
6120 /* rotate right with carry */
6121 left = IC_LEFT (ic);
6122 result = IC_RESULT (ic);
6123 aopOp (left, ic, FALSE, FALSE);
6124 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6126 /* move it to the result */
6127 size = AOP_SIZE (result);
6131 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6133 emitcode ("add", "a,acc");
6134 if (AOP_SIZE (result) > 1)
6136 aopPut (AOP (result), "a", offset++);
6139 _startLazyDPSEvaluation ();
6142 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6144 emitcode ("rlc", "a");
6145 if (AOP_SIZE (result) > 1)
6146 aopPut (AOP (result), "a", offset++);
6148 _endLazyDPSEvaluation ();
6150 /* now we need to put the carry into the
6151 highest order byte of the result */
6152 if (AOP_SIZE (result) > 1)
6154 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6157 emitcode ("mov", "acc.0,c");
6158 aopPut (AOP (result), "a", 0);
6159 freeAsmop (left, NULL, ic, TRUE);
6160 freeAsmop (result, NULL, ic, TRUE);
6163 /*-----------------------------------------------------------------*/
6164 /* genGetHbit - generates code get highest order bit */
6165 /*-----------------------------------------------------------------*/
6167 genGetHbit (iCode * ic)
6169 operand *left, *result;
6170 left = IC_LEFT (ic);
6171 result = IC_RESULT (ic);
6172 aopOp (left, ic, FALSE, FALSE);
6173 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6175 D (emitcode (";", "genGetHbit ");
6178 /* get the highest order byte into a */
6179 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6180 if (AOP_TYPE (result) == AOP_CRY)
6182 emitcode ("rlc", "a");
6187 emitcode ("rl", "a");
6188 emitcode ("anl", "a,#0x01");
6193 freeAsmop (left, NULL, ic, TRUE);
6194 freeAsmop (result, NULL, ic, TRUE);
6197 /*-----------------------------------------------------------------*/
6198 /* AccRol - rotate left accumulator by known count */
6199 /*-----------------------------------------------------------------*/
6201 AccRol (int shCount)
6203 shCount &= 0x0007; // shCount : 0..7
6210 emitcode ("rl", "a");
6213 emitcode ("rl", "a");
6214 emitcode ("rl", "a");
6217 emitcode ("swap", "a");
6218 emitcode ("rr", "a");
6221 emitcode ("swap", "a");
6224 emitcode ("swap", "a");
6225 emitcode ("rl", "a");
6228 emitcode ("rr", "a");
6229 emitcode ("rr", "a");
6232 emitcode ("rr", "a");
6237 /*-----------------------------------------------------------------*/
6238 /* AccLsh - left shift accumulator by known count */
6239 /*-----------------------------------------------------------------*/
6241 AccLsh (int shCount)
6246 emitcode ("add", "a,acc");
6247 else if (shCount == 2)
6249 emitcode ("add", "a,acc");
6250 emitcode ("add", "a,acc");
6254 /* rotate left accumulator */
6256 /* and kill the lower order bits */
6257 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6262 /*-----------------------------------------------------------------*/
6263 /* AccRsh - right shift accumulator by known count */
6264 /*-----------------------------------------------------------------*/
6266 AccRsh (int shCount)
6273 emitcode ("rrc", "a");
6277 /* rotate right accumulator */
6278 AccRol (8 - shCount);
6279 /* and kill the higher order bits */
6280 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6285 #ifdef BETTER_LITERAL_SHIFT
6286 /*-----------------------------------------------------------------*/
6287 /* AccSRsh - signed right shift accumulator by known count */
6288 /*-----------------------------------------------------------------*/
6290 AccSRsh (int shCount)
6297 emitcode ("mov", "c,acc.7");
6298 emitcode ("rrc", "a");
6300 else if (shCount == 2)
6302 emitcode ("mov", "c,acc.7");
6303 emitcode ("rrc", "a");
6304 emitcode ("mov", "c,acc.7");
6305 emitcode ("rrc", "a");
6309 tlbl = newiTempLabel (NULL);
6310 /* rotate right accumulator */
6311 AccRol (8 - shCount);
6312 /* and kill the higher order bits */
6313 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6314 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6315 emitcode ("orl", "a,#0x%02x",
6316 (unsigned char) ~SRMask[shCount]);
6317 emitcode ("", "%05d$:", tlbl->key + 100);
6323 #ifdef BETTER_LITERAL_SHIFT
6324 /*-----------------------------------------------------------------*/
6325 /* shiftR1Left2Result - shift right one byte from left to result */
6326 /*-----------------------------------------------------------------*/
6328 shiftR1Left2Result (operand * left, int offl,
6329 operand * result, int offr,
6330 int shCount, int sign)
6332 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6333 /* shift right accumulator */
6338 aopPut (AOP (result), "a", offr);
6342 #ifdef BETTER_LITERAL_SHIFT
6343 /*-----------------------------------------------------------------*/
6344 /* shiftL1Left2Result - shift left one byte from left to result */
6345 /*-----------------------------------------------------------------*/
6347 shiftL1Left2Result (operand * left, int offl,
6348 operand * result, int offr, int shCount)
6350 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6351 /* shift left accumulator */
6353 aopPut (AOP (result), "a", offr);
6357 #ifdef BETTER_LITERAL_SHIFT
6358 /*-----------------------------------------------------------------*/
6359 /* movLeft2Result - move byte from left to result */
6360 /*-----------------------------------------------------------------*/
6362 movLeft2Result (operand * left, int offl,
6363 operand * result, int offr, int sign)
6366 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6368 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6370 if (*l == '@' && (IS_AOP_PREG (result)))
6372 emitcode ("mov", "a,%s", l);
6373 aopPut (AOP (result), "a", offr);
6379 aopPut (AOP (result), l, offr);
6383 /* MSB sign in acc.7 ! */
6384 if (getDataSize (left) == offl + 1)
6386 emitcode ("mov", "a,%s", l);
6387 aopPut (AOP (result), "a", offr);
6395 #ifdef BETTER_LITERAL_SHIFT
6396 /*-----------------------------------------------------------------*/
6397 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6398 /*-----------------------------------------------------------------*/
6402 emitcode ("rrc", "a");
6403 emitcode ("xch", "a,%s", x);
6404 emitcode ("rrc", "a");
6405 emitcode ("xch", "a,%s", x);
6409 #ifdef BETTER_LITERAL_SHIFT
6411 /*-----------------------------------------------------------------*/
6412 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6413 /*-----------------------------------------------------------------*/
6417 emitcode ("xch", "a,%s", x);
6418 emitcode ("rlc", "a");
6419 emitcode ("xch", "a,%s", x);
6420 emitcode ("rlc", "a");
6424 #ifdef BETTER_LITERAL_SHIFT
6425 /*-----------------------------------------------------------------*/
6426 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6427 /*-----------------------------------------------------------------*/
6431 emitcode ("xch", "a,%s", x);
6432 emitcode ("add", "a,acc");
6433 emitcode ("xch", "a,%s", x);
6434 emitcode ("rlc", "a");
6438 #ifdef BETTER_LITERAL_SHIFT
6439 /*-----------------------------------------------------------------*/
6440 /* AccAXLsh - left shift a:x by known count (0..7) */
6441 /*-----------------------------------------------------------------*/
6443 AccAXLsh (char *x, int shCount)
6458 case 5: // AAAAABBB:CCCCCDDD
6460 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6462 emitcode ("anl", "a,#0x%02x",
6463 SLMask[shCount]); // BBB00000:CCCCCDDD
6465 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6467 AccRol (shCount); // DDDCCCCC:BBB00000
6469 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6471 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6473 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6475 emitcode ("anl", "a,#0x%02x",
6476 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6478 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6480 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6483 case 6: // AAAAAABB:CCCCCCDD
6484 emitcode ("anl", "a,#0x%02x",
6485 SRMask[shCount]); // 000000BB:CCCCCCDD
6486 emitcode ("mov", "c,acc.0"); // c = B
6487 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6489 AccAXRrl1 (x); // BCCCCCCD:D000000B
6490 AccAXRrl1 (x); // BBCCCCCC:DD000000
6492 emitcode("rrc","a");
6493 emitcode("xch","a,%s", x);
6494 emitcode("rrc","a");
6495 emitcode("mov","c,acc.0"); //<< get correct bit
6496 emitcode("xch","a,%s", x);
6498 emitcode("rrc","a");
6499 emitcode("xch","a,%s", x);
6500 emitcode("rrc","a");
6501 emitcode("xch","a,%s", x);
6504 case 7: // a:x <<= 7
6506 emitcode ("anl", "a,#0x%02x",
6507 SRMask[shCount]); // 0000000B:CCCCCCCD
6509 emitcode ("mov", "c,acc.0"); // c = B
6511 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6513 AccAXRrl1 (x); // BCCCCCCC:D0000000
6522 #ifdef BETTER_LITERAL_SHIFT
6524 /*-----------------------------------------------------------------*/
6525 /* AccAXRsh - right shift a:x known count (0..7) */
6526 /*-----------------------------------------------------------------*/
6528 AccAXRsh (char *x, int shCount)
6536 AccAXRrl1 (x); // 0->a:x
6541 AccAXRrl1 (x); // 0->a:x
6544 AccAXRrl1 (x); // 0->a:x
6549 case 5: // AAAAABBB:CCCCCDDD = a:x
6551 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6553 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6555 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6557 emitcode ("anl", "a,#0x%02x",
6558 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6560 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6562 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6564 emitcode ("anl", "a,#0x%02x",
6565 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6567 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6569 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6571 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6574 case 6: // AABBBBBB:CCDDDDDD
6576 emitcode ("mov", "c,acc.7");
6577 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6579 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6581 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6583 emitcode ("anl", "a,#0x%02x",
6584 SRMask[shCount]); // 000000AA:BBBBBBCC
6587 case 7: // ABBBBBBB:CDDDDDDD
6589 emitcode ("mov", "c,acc.7"); // c = A
6591 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6593 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6595 emitcode ("anl", "a,#0x%02x",
6596 SRMask[shCount]); // 0000000A:BBBBBBBC
6605 #ifdef BETTER_LITERAL_SHIFT
6606 /*-----------------------------------------------------------------*/
6607 /* AccAXRshS - right shift signed a:x known count (0..7) */
6608 /*-----------------------------------------------------------------*/
6610 AccAXRshS (char *x, int shCount)
6618 emitcode ("mov", "c,acc.7");
6619 AccAXRrl1 (x); // s->a:x
6623 emitcode ("mov", "c,acc.7");
6624 AccAXRrl1 (x); // s->a:x
6626 emitcode ("mov", "c,acc.7");
6627 AccAXRrl1 (x); // s->a:x
6632 case 5: // AAAAABBB:CCCCCDDD = a:x
6634 tlbl = newiTempLabel (NULL);
6635 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6637 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6639 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6641 emitcode ("anl", "a,#0x%02x",
6642 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6644 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6646 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6648 emitcode ("anl", "a,#0x%02x",
6649 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6651 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6653 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6655 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6657 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6658 emitcode ("orl", "a,#0x%02x",
6659 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6661 emitcode ("", "%05d$:", tlbl->key + 100);
6662 break; // SSSSAAAA:BBBCCCCC
6664 case 6: // AABBBBBB:CCDDDDDD
6666 tlbl = newiTempLabel (NULL);
6667 emitcode ("mov", "c,acc.7");
6668 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6670 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6672 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6674 emitcode ("anl", "a,#0x%02x",
6675 SRMask[shCount]); // 000000AA:BBBBBBCC
6677 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6678 emitcode ("orl", "a,#0x%02x",
6679 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6681 emitcode ("", "%05d$:", tlbl->key + 100);
6683 case 7: // ABBBBBBB:CDDDDDDD
6685 tlbl = newiTempLabel (NULL);
6686 emitcode ("mov", "c,acc.7"); // c = A
6688 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6690 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6692 emitcode ("anl", "a,#0x%02x",
6693 SRMask[shCount]); // 0000000A:BBBBBBBC
6695 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6696 emitcode ("orl", "a,#0x%02x",
6697 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6699 emitcode ("", "%05d$:", tlbl->key + 100);
6707 #ifdef BETTER_LITERAL_SHIFT
6709 _loadLeftIntoAx(char **lsb,
6715 // Get the initial value from left into a pair of registers.
6716 // MSB must be in A, LSB can be any register.
6718 // If the result is held in registers, it is an optimization
6719 // if the LSB can be held in the register which will hold the,
6720 // result LSB since this saves us from having to copy it into
6721 // the result following AccAXLsh.
6723 // If the result is addressed indirectly, this is not a gain.
6724 if (AOP_NEEDSACC(result))
6728 _startLazyDPSEvaluation();
6729 if (AOP_TYPE(left) == AOP_DPTR2)
6732 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6733 // get LSB in DP2_RESULT_REG.
6734 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6735 assert(!strcmp(leftByte, DP2_RESULT_REG));
6739 // get LSB into DP2_RESULT_REG
6740 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6741 if (strcmp(leftByte, DP2_RESULT_REG))
6743 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6746 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6747 assert(strcmp(leftByte, DP2_RESULT_REG));
6750 _endLazyDPSEvaluation();
6751 *lsb = DP2_RESULT_REG;
6755 if (sameRegs (AOP (result), AOP (left)) &&
6756 ((offl + MSB16) == offr))
6758 /* don't crash result[offr] */
6759 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6760 emitcode ("xch", "a,%s",
6761 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6765 movLeft2Result (left, offl, result, offr, 0);
6766 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6768 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6769 assert(strcmp(*lsb,"a"));
6774 _storeAxResults(char *lsb,
6778 _startLazyDPSEvaluation();
6779 if (AOP_NEEDSACC(result))
6781 /* We have to explicitly update the result LSB.
6783 emitcode("xch","a,%s", lsb);
6784 aopPut(AOP(result), "a", offr);
6785 emitcode("mov","a,%s", lsb);
6787 if (getDataSize (result) > 1)
6789 aopPut (AOP (result), "a", offr + MSB16);
6791 _endLazyDPSEvaluation();
6794 /*-----------------------------------------------------------------*/
6795 /* shiftL2Left2Result - shift left two bytes from left to result */
6796 /*-----------------------------------------------------------------*/
6798 shiftL2Left2Result (operand * left, int offl,
6799 operand * result, int offr, int shCount)
6803 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6805 AccAXLsh (lsb, shCount);
6807 _storeAxResults(lsb, result, offr);
6811 #ifdef BETTER_LITERAL_SHIFT
6812 /*-----------------------------------------------------------------*/
6813 /* shiftR2Left2Result - shift right two bytes from left to result */
6814 /*-----------------------------------------------------------------*/
6816 shiftR2Left2Result (operand * left, int offl,
6817 operand * result, int offr,
6818 int shCount, int sign)
6822 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6824 /* a:x >> shCount (x = lsb(result)) */
6827 AccAXRshS(lsb, shCount);
6831 AccAXRsh(lsb, shCount);
6834 _storeAxResults(lsb, result, offr);
6840 /*-----------------------------------------------------------------*/
6841 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6842 /*-----------------------------------------------------------------*/
6844 shiftLLeftOrResult (operand * left, int offl,
6845 operand * result, int offr, int shCount)
6847 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6848 /* shift left accumulator */
6850 /* or with result */
6851 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6852 /* back to result */
6853 aopPut (AOP (result), "a", offr);
6859 /*-----------------------------------------------------------------*/
6860 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6861 /*-----------------------------------------------------------------*/
6863 shiftRLeftOrResult (operand * left, int offl,
6864 operand * result, int offr, int shCount)
6866 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6867 /* shift right accumulator */
6869 /* or with result */
6870 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6871 /* back to result */
6872 aopPut (AOP (result), "a", offr);
6876 #ifdef BETTER_LITERAL_SHIFT
6877 /*-----------------------------------------------------------------*/
6878 /* genlshOne - left shift a one byte quantity by known count */
6879 /*-----------------------------------------------------------------*/
6881 genlshOne (operand * result, operand * left, int shCount)
6883 D (emitcode (";", "genlshOne "););
6884 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6888 #ifdef BETTER_LITERAL_SHIFT
6889 /*-----------------------------------------------------------------*/
6890 /* genlshTwo - left shift two bytes by known amount != 0 */
6891 /*-----------------------------------------------------------------*/
6893 genlshTwo (operand * result, operand * left, int shCount)
6897 D (emitcode (";", "genlshTwo "););
6899 size = getDataSize (result);
6901 /* if shCount >= 8 */
6906 _startLazyDPSEvaluation();
6912 _endLazyDPSEvaluation();
6913 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6914 aopPut (AOP (result), zero, LSB);
6918 movLeft2Result (left, LSB, result, MSB16, 0);
6919 aopPut (AOP (result), zero, LSB);
6920 _endLazyDPSEvaluation();
6925 aopPut (AOP (result), zero, LSB);
6926 _endLazyDPSEvaluation();
6930 /* 1 <= shCount <= 7 */
6935 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6939 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6947 /*-----------------------------------------------------------------*/
6948 /* shiftLLong - shift left one long from left to result */
6949 /* offl = LSB or MSB16 */
6950 /*-----------------------------------------------------------------*/
6952 shiftLLong (operand * left, operand * result, int offr)
6955 int size = AOP_SIZE (result);
6957 if (size >= LSB + offr)
6959 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6961 emitcode ("add", "a,acc");
6962 if (sameRegs (AOP (left), AOP (result)) &&
6963 size >= MSB16 + offr && offr != LSB)
6964 emitcode ("xch", "a,%s",
6965 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6967 aopPut (AOP (result), "a", LSB + offr);
6970 if (size >= MSB16 + offr)
6972 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6974 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6977 emitcode ("rlc", "a");
6978 if (sameRegs (AOP (left), AOP (result)) &&
6979 size >= MSB24 + offr && offr != LSB)
6980 emitcode ("xch", "a,%s",
6981 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6983 aopPut (AOP (result), "a", MSB16 + offr);
6986 if (size >= MSB24 + offr)
6988 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6990 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6993 emitcode ("rlc", "a");
6994 if (sameRegs (AOP (left), AOP (result)) &&
6995 size >= MSB32 + offr && offr != LSB)
6996 emitcode ("xch", "a,%s",
6997 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6999 aopPut (AOP (result), "a", MSB24 + offr);
7002 if (size > MSB32 + offr)
7004 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7006 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7009 emitcode ("rlc", "a");
7010 aopPut (AOP (result), "a", MSB32 + offr);
7013 aopPut (AOP (result), zero, LSB);
7019 /*-----------------------------------------------------------------*/
7020 /* genlshFour - shift four byte by a known amount != 0 */
7021 /*-----------------------------------------------------------------*/
7023 genlshFour (operand * result, operand * left, int shCount)
7027 D (emitcode (";", "genlshFour ");
7030 size = AOP_SIZE (result);
7032 /* if shifting more that 3 bytes */
7037 /* lowest order of left goes to the highest
7038 order of the destination */
7039 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7041 movLeft2Result (left, LSB, result, MSB32, 0);
7042 aopPut (AOP (result), zero, LSB);
7043 aopPut (AOP (result), zero, MSB16);
7044 aopPut (AOP (result), zero, MSB24);
7048 /* more than two bytes */
7049 else if (shCount >= 16)
7051 /* lower order two bytes goes to higher order two bytes */
7053 /* if some more remaining */
7055 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7058 movLeft2Result (left, MSB16, result, MSB32, 0);
7059 movLeft2Result (left, LSB, result, MSB24, 0);
7061 aopPut (AOP (result), zero, MSB16);
7062 aopPut (AOP (result), zero, LSB);
7066 /* if more than 1 byte */
7067 else if (shCount >= 8)
7069 /* lower order three bytes goes to higher order three bytes */
7074 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7076 movLeft2Result (left, LSB, result, MSB16, 0);
7082 movLeft2Result (left, MSB24, result, MSB32, 0);
7083 movLeft2Result (left, MSB16, result, MSB24, 0);
7084 movLeft2Result (left, LSB, result, MSB16, 0);
7085 aopPut (AOP (result), zero, LSB);
7087 else if (shCount == 1)
7088 shiftLLong (left, result, MSB16);
7091 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7092 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7093 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7094 aopPut (AOP (result), zero, LSB);
7099 /* 1 <= shCount <= 7 */
7100 else if (shCount <= 2)
7102 shiftLLong (left, result, LSB);
7104 shiftLLong (result, result, LSB);
7106 /* 3 <= shCount <= 7, optimize */
7109 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7110 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7111 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7116 #ifdef BETTER_LITERAL_SHIFT
7117 /*-----------------------------------------------------------------*/
7118 /* genLeftShiftLiteral - left shifting by known count */
7119 /*-----------------------------------------------------------------*/
7121 genLeftShiftLiteral (operand * left,
7126 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7129 size = getSize (operandType (result));
7131 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7133 /* We only handle certain easy cases so far. */
7135 && (shCount < (size * 8))
7139 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7143 freeAsmop (right, NULL, ic, TRUE);
7145 aopOp(left, ic, FALSE, FALSE);
7146 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7149 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7151 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7152 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7154 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7157 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7159 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7160 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7162 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7168 emitcode ("; shift left ", "result %d, left %d", size,
7172 /* I suppose that the left size >= result size */
7175 _startLazyDPSEvaluation();
7178 movLeft2Result (left, size, result, size, 0);
7180 _endLazyDPSEvaluation();
7182 else if (shCount >= (size * 8))
7184 _startLazyDPSEvaluation();
7187 aopPut (AOP (result), zero, size);
7189 _endLazyDPSEvaluation();
7196 genlshOne (result, left, shCount);
7200 genlshTwo (result, left, shCount);
7204 genlshFour (result, left, shCount);
7208 fprintf(stderr, "*** ack! mystery literal shift!\n");
7212 freeAsmop (left, NULL, ic, TRUE);
7213 freeAsmop (result, NULL, ic, TRUE);
7218 /*-----------------------------------------------------------------*/
7219 /* genLeftShift - generates code for left shifting */
7220 /*-----------------------------------------------------------------*/
7222 genLeftShift (iCode * ic)
7224 operand *left, *right, *result;
7227 symbol *tlbl, *tlbl1;
7229 D (emitcode (";", "genLeftShift "););
7231 right = IC_RIGHT (ic);
7232 left = IC_LEFT (ic);
7233 result = IC_RESULT (ic);
7235 aopOp (right, ic, FALSE, FALSE);
7238 #ifdef BETTER_LITERAL_SHIFT
7239 /* if the shift count is known then do it
7240 as efficiently as possible */
7241 if (AOP_TYPE (right) == AOP_LIT)
7243 if (genLeftShiftLiteral (left, right, result, ic))
7250 /* shift count is unknown then we have to form
7251 a loop get the loop count in B : Note: we take
7252 only the lower order byte since shifting
7253 more that 32 bits make no sense anyway, ( the
7254 largest size of an object can be only 32 bits ) */
7256 if (AOP_TYPE (right) == AOP_LIT)
7258 /* Really should be handled by genLeftShiftLiteral,
7259 * but since I'm too lazy to fix that today, at least we can make
7260 * some small improvement.
7262 emitcode("mov", "b,#0x%02x",
7263 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7267 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7268 emitcode ("inc", "b");
7270 freeAsmop (right, NULL, ic, TRUE);
7271 aopOp (left, ic, FALSE, FALSE);
7272 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7274 /* now move the left to the result if they are not the
7276 if (!sameRegs (AOP (left), AOP (result)) &&
7277 AOP_SIZE (result) > 1)
7280 size = AOP_SIZE (result);
7282 _startLazyDPSEvaluation ();
7285 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7286 if (*l == '@' && (IS_AOP_PREG (result)))
7289 emitcode ("mov", "a,%s", l);
7290 aopPut (AOP (result), "a", offset);
7293 aopPut (AOP (result), l, offset);
7296 _endLazyDPSEvaluation ();
7299 tlbl = newiTempLabel (NULL);
7300 size = AOP_SIZE (result);
7302 tlbl1 = newiTempLabel (NULL);
7304 /* if it is only one byte then */
7307 symbol *tlbl1 = newiTempLabel (NULL);
7309 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7311 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7312 emitcode ("", "%05d$:", tlbl->key + 100);
7313 emitcode ("add", "a,acc");
7314 emitcode ("", "%05d$:", tlbl1->key + 100);
7315 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7316 aopPut (AOP (result), "a", 0);
7320 reAdjustPreg (AOP (result));
7322 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7323 emitcode ("", "%05d$:", tlbl->key + 100);
7324 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7326 emitcode ("add", "a,acc");
7327 aopPut (AOP (result), "a", offset++);
7328 _startLazyDPSEvaluation ();
7331 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7333 emitcode ("rlc", "a");
7334 aopPut (AOP (result), "a", offset++);
7336 _endLazyDPSEvaluation ();
7337 reAdjustPreg (AOP (result));
7339 emitcode ("", "%05d$:", tlbl1->key + 100);
7340 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7342 freeAsmop (left, NULL, ic, TRUE);
7343 freeAsmop (result, NULL, ic, TRUE);
7346 #ifdef BETTER_LITERAL_SHIFT
7347 /*-----------------------------------------------------------------*/
7348 /* genrshOne - right shift a one byte quantity by known count */
7349 /*-----------------------------------------------------------------*/
7351 genrshOne (operand * result, operand * left,
7352 int shCount, int sign)
7354 D (emitcode (";", "genrshOne"););
7355 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7359 #ifdef BETTER_LITERAL_SHIFT
7360 /*-----------------------------------------------------------------*/
7361 /* genrshTwo - right shift two bytes by known amount != 0 */
7362 /*-----------------------------------------------------------------*/
7364 genrshTwo (operand * result, operand * left,
7365 int shCount, int sign)
7367 D (emitcode (";", "genrshTwo"););
7369 /* if shCount >= 8 */
7373 _startLazyDPSEvaluation();
7376 shiftR1Left2Result (left, MSB16, result, LSB,
7381 movLeft2Result (left, MSB16, result, LSB, sign);
7383 addSign (result, MSB16, sign);
7384 _endLazyDPSEvaluation();
7387 /* 1 <= shCount <= 7 */
7390 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7397 /*-----------------------------------------------------------------*/
7398 /* shiftRLong - shift right one long from left to result */
7399 /* offl = LSB or MSB16 */
7400 /*-----------------------------------------------------------------*/
7402 shiftRLong (operand * left, int offl,
7403 operand * result, int sign)
7405 int isSameRegs=sameRegs(AOP(left),AOP(result));
7407 if (isSameRegs && offl>1) {
7408 // we are in big trouble, but this shouldn't happen
7409 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7412 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7417 emitcode ("rlc", "a");
7418 emitcode ("subb", "a,acc");
7419 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7421 aopPut (AOP(result), zero, MSB32);
7426 emitcode ("clr", "c");
7428 emitcode ("mov", "c,acc.7");
7431 emitcode ("rrc", "a");
7433 if (isSameRegs && offl==MSB16) {
7434 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7436 aopPut (AOP (result), "a", MSB32);
7437 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7440 emitcode ("rrc", "a");
7441 if (isSameRegs && offl==1) {
7442 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7444 aopPut (AOP (result), "a", MSB24);
7445 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7447 emitcode ("rrc", "a");
7448 aopPut (AOP (result), "a", MSB16 - offl);
7452 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7453 emitcode ("rrc", "a");
7454 aopPut (AOP (result), "a", LSB);
7461 /*-----------------------------------------------------------------*/
7462 /* genrshFour - shift four byte by a known amount != 0 */
7463 /*-----------------------------------------------------------------*/
7465 genrshFour (operand * result, operand * left,
7466 int shCount, int sign)
7468 D (emitcode (";", "genrshFour");
7471 /* if shifting more that 3 bytes */
7476 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7478 movLeft2Result (left, MSB32, result, LSB, sign);
7479 addSign (result, MSB16, sign);
7481 else if (shCount >= 16)
7485 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7488 movLeft2Result (left, MSB24, result, LSB, 0);
7489 movLeft2Result (left, MSB32, result, MSB16, sign);
7491 addSign (result, MSB24, sign);
7493 else if (shCount >= 8)
7497 shiftRLong (left, MSB16, result, sign);
7498 else if (shCount == 0)
7500 movLeft2Result (left, MSB16, result, LSB, 0);
7501 movLeft2Result (left, MSB24, result, MSB16, 0);
7502 movLeft2Result (left, MSB32, result, MSB24, sign);
7503 addSign (result, MSB32, sign);
7507 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7508 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7509 /* the last shift is signed */
7510 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7511 addSign (result, MSB32, sign);
7515 { /* 1 <= shCount <= 7 */
7518 shiftRLong (left, LSB, result, sign);
7520 shiftRLong (result, LSB, result, sign);
7524 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7525 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7526 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7532 #ifdef BETTER_LITERAL_SHIFT
7533 /*-----------------------------------------------------------------*/
7534 /* genRightShiftLiteral - right shifting by known count */
7535 /*-----------------------------------------------------------------*/
7537 genRightShiftLiteral (operand * left,
7543 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7546 size = getSize (operandType (result));
7548 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7550 /* We only handle certain easy cases so far. */
7552 && (shCount < (size * 8))
7556 D(emitcode (";", "genRightShiftLiteral wimping out"););
7560 freeAsmop (right, NULL, ic, TRUE);
7562 aopOp (left, ic, FALSE, FALSE);
7563 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7566 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7570 /* test the LEFT size !!! */
7572 /* I suppose that the left size >= result size */
7575 size = getDataSize (result);
7576 _startLazyDPSEvaluation();
7579 movLeft2Result (left, size, result, size, 0);
7581 _endLazyDPSEvaluation();
7583 else if (shCount >= (size * 8))
7587 /* get sign in acc.7 */
7588 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7590 addSign (result, LSB, sign);
7597 genrshOne (result, left, shCount, sign);
7601 genrshTwo (result, left, shCount, sign);
7605 genrshFour (result, left, shCount, sign);
7612 freeAsmop (left, NULL, ic, TRUE);
7613 freeAsmop (result, NULL, ic, TRUE);
7619 /*-----------------------------------------------------------------*/
7620 /* genSignedRightShift - right shift of signed number */
7621 /*-----------------------------------------------------------------*/
7623 genSignedRightShift (iCode * ic)
7625 operand *right, *left, *result;
7628 symbol *tlbl, *tlbl1;
7630 D (emitcode (";", "genSignedRightShift "););
7632 /* we do it the hard way put the shift count in b
7633 and loop thru preserving the sign */
7635 right = IC_RIGHT (ic);
7636 left = IC_LEFT (ic);
7637 result = IC_RESULT (ic);
7639 aopOp (right, ic, FALSE, FALSE);
7641 #ifdef BETTER_LITERAL_SHIFT
7642 if (AOP_TYPE (right) == AOP_LIT)
7644 if (genRightShiftLiteral (left, right, result, ic, 1))
7650 /* shift count is unknown then we have to form
7651 a loop get the loop count in B : Note: we take
7652 only the lower order byte since shifting
7653 more that 32 bits make no sense anyway, ( the
7654 largest size of an object can be only 32 bits ) */
7656 if (AOP_TYPE (right) == AOP_LIT)
7658 /* Really should be handled by genRightShiftLiteral,
7659 * but since I'm too lazy to fix that today, at least we can make
7660 * some small improvement.
7662 emitcode("mov", "b,#0x%02x",
7663 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7667 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7668 emitcode ("inc", "b");
7670 freeAsmop (right, NULL, ic, TRUE);
7671 aopOp (left, ic, FALSE, FALSE);
7672 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7674 /* now move the left to the result if they are not the
7676 if (!sameRegs (AOP (left), AOP (result)) &&
7677 AOP_SIZE (result) > 1)
7680 size = AOP_SIZE (result);
7682 _startLazyDPSEvaluation ();
7685 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7686 if (*l == '@' && IS_AOP_PREG (result))
7689 emitcode ("mov", "a,%s", l);
7690 aopPut (AOP (result), "a", offset);
7693 aopPut (AOP (result), l, offset);
7696 _endLazyDPSEvaluation ();
7699 /* mov the highest order bit to OVR */
7700 tlbl = newiTempLabel (NULL);
7701 tlbl1 = newiTempLabel (NULL);
7703 size = AOP_SIZE (result);
7705 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7706 emitcode ("rlc", "a");
7707 emitcode ("mov", "ov,c");
7708 /* if it is only one byte then */
7711 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7713 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7714 emitcode ("", "%05d$:", tlbl->key + 100);
7715 emitcode ("mov", "c,ov");
7716 emitcode ("rrc", "a");
7717 emitcode ("", "%05d$:", tlbl1->key + 100);
7718 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7719 aopPut (AOP (result), "a", 0);
7723 reAdjustPreg (AOP (result));
7724 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7725 emitcode ("", "%05d$:", tlbl->key + 100);
7726 emitcode ("mov", "c,ov");
7727 _startLazyDPSEvaluation ();
7730 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7732 emitcode ("rrc", "a");
7733 aopPut (AOP (result), "a", offset--);
7735 _endLazyDPSEvaluation ();
7736 reAdjustPreg (AOP (result));
7737 emitcode ("", "%05d$:", tlbl1->key + 100);
7738 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7741 freeAsmop (left, NULL, ic, TRUE);
7742 freeAsmop (result, NULL, ic, TRUE);
7745 /*-----------------------------------------------------------------*/
7746 /* genRightShift - generate code for right shifting */
7747 /*-----------------------------------------------------------------*/
7749 genRightShift (iCode * ic)
7751 operand *right, *left, *result;
7755 symbol *tlbl, *tlbl1;
7757 D (emitcode (";", "genRightShift "););
7759 /* if signed then we do it the hard way preserve the
7760 sign bit moving it inwards */
7761 retype = getSpec (operandType (IC_RESULT (ic)));
7763 if (!SPEC_USIGN (retype))
7765 genSignedRightShift (ic);
7769 /* signed & unsigned types are treated the same : i.e. the
7770 signed is NOT propagated inwards : quoting from the
7771 ANSI - standard : "for E1 >> E2, is equivalent to division
7772 by 2**E2 if unsigned or if it has a non-negative value,
7773 otherwise the result is implementation defined ", MY definition
7774 is that the sign does not get propagated */
7776 right = IC_RIGHT (ic);
7777 left = IC_LEFT (ic);
7778 result = IC_RESULT (ic);
7780 aopOp (right, ic, FALSE, FALSE);
7782 #ifdef BETTER_LITERAL_SHIFT
7783 /* if the shift count is known then do it
7784 as efficiently as possible */
7785 if (AOP_TYPE (right) == AOP_LIT)
7787 if (genRightShiftLiteral (left, right, result, ic, 0))
7794 /* shift count is unknown then we have to form
7795 a loop get the loop count in B : Note: we take
7796 only the lower order byte since shifting
7797 more that 32 bits make no sense anyway, ( the
7798 largest size of an object can be only 32 bits ) */
7800 if (AOP_TYPE (right) == AOP_LIT)
7802 /* Really should be handled by genRightShiftLiteral,
7803 * but since I'm too lazy to fix that today, at least we can make
7804 * some small improvement.
7806 emitcode("mov", "b,#0x%02x",
7807 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7811 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7812 emitcode ("inc", "b");
7814 freeAsmop (right, NULL, ic, TRUE);
7815 aopOp (left, ic, FALSE, FALSE);
7816 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7818 /* now move the left to the result if they are not the
7820 if (!sameRegs (AOP (left), AOP (result)) &&
7821 AOP_SIZE (result) > 1)
7824 size = AOP_SIZE (result);
7826 _startLazyDPSEvaluation ();
7829 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7830 if (*l == '@' && IS_AOP_PREG (result))
7833 emitcode ("mov", "a,%s", l);
7834 aopPut (AOP (result), "a", offset);
7837 aopPut (AOP (result), l, offset);
7840 _endLazyDPSEvaluation ();
7843 tlbl = newiTempLabel (NULL);
7844 tlbl1 = newiTempLabel (NULL);
7845 size = AOP_SIZE (result);
7848 /* if it is only one byte then */
7851 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7853 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7854 emitcode ("", "%05d$:", tlbl->key + 100);
7856 emitcode ("rrc", "a");
7857 emitcode ("", "%05d$:", tlbl1->key + 100);
7858 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7859 aopPut (AOP (result), "a", 0);
7863 reAdjustPreg (AOP (result));
7864 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7865 emitcode ("", "%05d$:", tlbl->key + 100);
7867 _startLazyDPSEvaluation ();
7870 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7872 emitcode ("rrc", "a");
7873 aopPut (AOP (result), "a", offset--);
7875 _endLazyDPSEvaluation ();
7876 reAdjustPreg (AOP (result));
7878 emitcode ("", "%05d$:", tlbl1->key + 100);
7879 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7882 freeAsmop (left, NULL, ic, TRUE);
7883 freeAsmop (result, NULL, ic, TRUE);
7886 /*-----------------------------------------------------------------*/
7887 /* genUnpackBits - generates code for unpacking bits */
7888 /*-----------------------------------------------------------------*/
7890 genUnpackBits (operand * result, char *rname, int ptype)
7897 D (emitcode (";", "genUnpackBits ");
7900 etype = getSpec (operandType (result));
7902 /* read the first byte */
7908 emitcode ("mov", "a,@%s", rname);
7912 emitcode ("movx", "a,@%s", rname);
7916 emitcode ("movx", "a,@dptr");
7920 emitcode ("clr", "a");
7921 emitcode ("movc", "a", "@a+dptr");
7925 emitcode ("lcall", "__gptrget");
7929 /* if we have bitdisplacement then it fits */
7930 /* into this byte completely or if length is */
7931 /* less than a byte */
7932 if ((shCnt = SPEC_BSTR (etype)) ||
7933 (SPEC_BLEN (etype) <= 8))
7936 /* shift right acc */
7939 emitcode ("anl", "a,#0x%02x",
7940 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7941 aopPut (AOP (result), "a", offset);
7945 /* bit field did not fit in a byte */
7946 rlen = SPEC_BLEN (etype) - 8;
7947 aopPut (AOP (result), "a", offset++);
7956 emitcode ("inc", "%s", rname);
7957 emitcode ("mov", "a,@%s", rname);
7961 emitcode ("inc", "%s", rname);
7962 emitcode ("movx", "a,@%s", rname);
7966 emitcode ("inc", "dptr");
7967 emitcode ("movx", "a,@dptr");
7971 emitcode ("clr", "a");
7972 emitcode ("inc", "dptr");
7973 emitcode ("movc", "a", "@a+dptr");
7977 emitcode ("inc", "dptr");
7978 emitcode ("lcall", "__gptrget");
7983 /* if we are done */
7987 aopPut (AOP (result), "a", offset++);
7993 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7994 aopPut (AOP (result), "a", offset);
8001 /*-----------------------------------------------------------------*/
8002 /* genDataPointerGet - generates code when ptr offset is known */
8003 /*-----------------------------------------------------------------*/
8005 genDataPointerGet (operand * left,
8011 int size, offset = 0;
8012 aopOp (result, ic, TRUE, FALSE);
8014 /* get the string representation of the name */
8015 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8016 size = AOP_SIZE (result);
8017 _startLazyDPSEvaluation ();
8021 sprintf (buffer, "(%s + %d)", l + 1, offset);
8023 sprintf (buffer, "%s", l + 1);
8024 aopPut (AOP (result), buffer, offset++);
8026 _endLazyDPSEvaluation ();
8028 freeAsmop (left, NULL, ic, TRUE);
8029 freeAsmop (result, NULL, ic, TRUE);
8032 /*-----------------------------------------------------------------*/
8033 /* genNearPointerGet - emitcode for near pointer fetch */
8034 /*-----------------------------------------------------------------*/
8036 genNearPointerGet (operand * left,
8043 sym_link *rtype, *retype, *letype;
8044 sym_link *ltype = operandType (left);
8047 rtype = operandType (result);
8048 retype = getSpec (rtype);
8049 letype = getSpec (ltype);
8051 aopOp (left, ic, FALSE, FALSE);
8053 /* if left is rematerialisable and
8054 result is not bit variable type and
8055 the left is pointer to data space i.e
8056 lower 128 bytes of space */
8057 if (AOP_TYPE (left) == AOP_IMMD &&
8058 !IS_BITVAR (retype) &&
8059 !IS_BITVAR (letype) &&
8060 DCL_TYPE (ltype) == POINTER)
8062 genDataPointerGet (left, result, ic);
8066 /* if the value is already in a pointer register
8067 then don't need anything more */
8068 if (!AOP_INPREG (AOP (left)))
8070 /* otherwise get a free pointer register */
8072 preg = getFreePtr (ic, &aop, FALSE);
8073 emitcode ("mov", "%s,%s",
8075 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8079 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8081 freeAsmop (left, NULL, ic, TRUE);
8082 aopOp (result, ic, FALSE, FALSE);
8084 /* if bitfield then unpack the bits */
8085 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8086 genUnpackBits (result, rname, POINTER);
8089 /* we have can just get the values */
8090 int size = AOP_SIZE (result);
8095 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8098 emitcode ("mov", "a,@%s", rname);
8099 aopPut (AOP (result), "a", offset);
8103 sprintf (buffer, "@%s", rname);
8104 aopPut (AOP (result), buffer, offset);
8108 emitcode ("inc", "%s", rname);
8112 /* now some housekeeping stuff */
8115 /* we had to allocate for this iCode */
8116 freeAsmop (NULL, aop, ic, TRUE);
8120 /* we did not allocate which means left
8121 already in a pointer register, then
8122 if size > 0 && this could be used again
8123 we have to point it back to where it
8125 if (AOP_SIZE (result) > 1 &&
8126 !OP_SYMBOL (left)->remat &&
8127 (OP_SYMBOL (left)->liveTo > ic->seq ||
8130 int size = AOP_SIZE (result) - 1;
8132 emitcode ("dec", "%s", rname);
8137 freeAsmop (result, NULL, ic, TRUE);
8141 /*-----------------------------------------------------------------*/
8142 /* genPagedPointerGet - emitcode for paged pointer fetch */
8143 /*-----------------------------------------------------------------*/
8145 genPagedPointerGet (operand * left,
8152 sym_link *rtype, *retype, *letype;
8154 rtype = operandType (result);
8155 retype = getSpec (rtype);
8156 letype = getSpec (operandType (left));
8157 aopOp (left, ic, FALSE, FALSE);
8159 /* if the value is already in a pointer register
8160 then don't need anything more */
8161 if (!AOP_INPREG (AOP (left)))
8163 /* otherwise get a free pointer register */
8165 preg = getFreePtr (ic, &aop, FALSE);
8166 emitcode ("mov", "%s,%s",
8168 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8172 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8174 freeAsmop (left, NULL, ic, TRUE);
8175 aopOp (result, ic, FALSE, FALSE);
8177 /* if bitfield then unpack the bits */
8178 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8179 genUnpackBits (result, rname, PPOINTER);
8182 /* we have can just get the values */
8183 int size = AOP_SIZE (result);
8189 emitcode ("movx", "a,@%s", rname);
8190 aopPut (AOP (result), "a", offset);
8195 emitcode ("inc", "%s", rname);
8199 /* now some housekeeping stuff */
8202 /* we had to allocate for this iCode */
8203 freeAsmop (NULL, aop, ic, TRUE);
8207 /* we did not allocate which means left
8208 already in a pointer register, then
8209 if size > 0 && this could be used again
8210 we have to point it back to where it
8212 if (AOP_SIZE (result) > 1 &&
8213 !OP_SYMBOL (left)->remat &&
8214 (OP_SYMBOL (left)->liveTo > ic->seq ||
8217 int size = AOP_SIZE (result) - 1;
8219 emitcode ("dec", "%s", rname);
8224 freeAsmop (result, NULL, ic, TRUE);
8229 /*-----------------------------------------------------------------*/
8230 /* genFarPointerGet - gget value from far space */
8231 /*-----------------------------------------------------------------*/
8233 genFarPointerGet (operand * left,
8234 operand * result, iCode * ic)
8237 sym_link *retype = getSpec (operandType (result));
8238 sym_link *letype = getSpec (operandType (left));
8239 D (emitcode (";", "genFarPointerGet");
8242 aopOp (left, ic, FALSE, FALSE);
8244 /* if the operand is already in dptr
8245 then we do nothing else we move the value to dptr */
8246 if (AOP_TYPE (left) != AOP_STR)
8248 /* if this is remateriazable */
8249 if (AOP_TYPE (left) == AOP_IMMD)
8251 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8255 /* we need to get it byte by byte */
8256 _startLazyDPSEvaluation ();
8257 if (AOP_TYPE (left) != AOP_DPTR)
8259 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8260 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8261 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8265 /* We need to generate a load to DPTR indirect through DPTR. */
8266 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8268 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8269 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8270 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8271 emitcode ("pop", "dph");
8272 emitcode ("pop", "dpl");
8274 _endLazyDPSEvaluation ();
8277 /* so dptr know contains the address */
8278 freeAsmop (left, NULL, ic, TRUE);
8279 aopOp (result, ic, FALSE, TRUE);
8281 /* if bit then unpack */
8282 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8283 genUnpackBits (result, "dptr", FPOINTER);
8286 size = AOP_SIZE (result);
8289 _startLazyDPSEvaluation ();
8296 emitcode ("movx", "a,@dptr");
8298 emitcode ("inc", "dptr");
8300 aopPut (AOP (result), "a", offset++);
8302 _endLazyDPSEvaluation ();
8305 freeAsmop (result, NULL, ic, TRUE);
8308 /*-----------------------------------------------------------------*/
8309 /* emitcodePointerGet - gget value from code space */
8310 /*-----------------------------------------------------------------*/
8312 emitcodePointerGet (operand * left,
8313 operand * result, iCode * ic)
8316 sym_link *retype = getSpec (operandType (result));
8318 aopOp (left, ic, FALSE, FALSE);
8320 /* if the operand is already in dptr
8321 then we do nothing else we move the value to dptr */
8322 if (AOP_TYPE (left) != AOP_STR)
8324 /* if this is remateriazable */
8325 if (AOP_TYPE (left) == AOP_IMMD)
8327 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8330 { /* we need to get it byte by byte */
8331 _startLazyDPSEvaluation ();
8332 if (AOP_TYPE (left) != AOP_DPTR)
8334 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8335 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8336 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8340 /* We need to generate a load to DPTR indirect through DPTR. */
8341 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8343 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8344 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8345 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8346 emitcode ("pop", "dph");
8347 emitcode ("pop", "dpl");
8349 _endLazyDPSEvaluation ();
8352 /* so dptr know contains the address */
8353 freeAsmop (left, NULL, ic, TRUE);
8354 aopOp (result, ic, FALSE, TRUE);
8356 /* if bit then unpack */
8357 if (IS_BITVAR (retype))
8358 genUnpackBits (result, "dptr", CPOINTER);
8361 size = AOP_SIZE (result);
8364 _startLazyDPSEvaluation ();
8370 emitcode ("clr", "a");
8371 emitcode ("movc", "a,@a+dptr");
8373 emitcode ("inc", "dptr");
8374 aopPut (AOP (result), "a", offset++);
8376 _endLazyDPSEvaluation ();
8379 freeAsmop (result, NULL, ic, TRUE);
8382 /*-----------------------------------------------------------------*/
8383 /* genGenPointerGet - gget value from generic pointer space */
8384 /*-----------------------------------------------------------------*/
8386 genGenPointerGet (operand * left,
8387 operand * result, iCode * ic)
8390 sym_link *retype = getSpec (operandType (result));
8391 sym_link *letype = getSpec (operandType (left));
8393 D (emitcode (";", "genGenPointerGet "); );
8395 aopOp (left, ic, FALSE, TRUE);
8397 /* if the operand is already in dptr
8398 then we do nothing else we move the value to dptr */
8399 if (AOP_TYPE (left) != AOP_STR)
8401 /* if this is remateriazable */
8402 if (AOP_TYPE (left) == AOP_IMMD)
8404 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8405 emitcode ("mov", "b,#%d", pointerCode (retype));
8408 { /* we need to get it byte by byte */
8409 _startLazyDPSEvaluation ();
8410 if (AOP(left)->type==AOP_DPTR2) {
8412 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8415 emitcode ("mov", "dpl,%s", l);
8416 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8419 emitcode ("mov", "dph,%s", l);
8420 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8423 emitcode ("mov", "dpx,%s", l);
8424 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8426 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8427 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8428 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8429 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8431 _endLazyDPSEvaluation ();
8434 /* so dptr know contains the address */
8435 freeAsmop (left, NULL, ic, TRUE);
8436 aopOp (result, ic, FALSE, TRUE);
8438 /* if bit then unpack */
8439 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8440 genUnpackBits (result, "dptr", GPOINTER);
8443 size = AOP_SIZE (result);
8448 emitcode ("lcall", "__gptrget");
8449 aopPut (AOP (result), "a", offset++);
8451 emitcode ("inc", "dptr");
8455 freeAsmop (result, NULL, ic, TRUE);
8458 /*-----------------------------------------------------------------*/
8459 /* genPointerGet - generate code for pointer get */
8460 /*-----------------------------------------------------------------*/
8462 genPointerGet (iCode * ic)
8464 operand *left, *result;
8465 sym_link *type, *etype;
8468 D (emitcode (";", "genPointerGet ");
8471 left = IC_LEFT (ic);
8472 result = IC_RESULT (ic);
8474 /* depending on the type of pointer we need to
8475 move it to the correct pointer register */
8476 type = operandType (left);
8477 etype = getSpec (type);
8478 /* if left is of type of pointer then it is simple */
8479 if (IS_PTR (type) && !IS_FUNC (type->next))
8480 p_type = DCL_TYPE (type);
8483 /* we have to go by the storage class */
8484 p_type = PTR_TYPE (SPEC_OCLS (etype));
8487 /* now that we have the pointer type we assign
8488 the pointer values */
8494 genNearPointerGet (left, result, ic);
8498 genPagedPointerGet (left, result, ic);
8502 genFarPointerGet (left, result, ic);
8506 emitcodePointerGet (left, result, ic);
8510 genGenPointerGet (left, result, ic);
8516 /*-----------------------------------------------------------------*/
8517 /* genPackBits - generates code for packed bit storage */
8518 /*-----------------------------------------------------------------*/
8520 genPackBits (sym_link * etype,
8522 char *rname, int p_type)
8530 blen = SPEC_BLEN (etype);
8531 bstr = SPEC_BSTR (etype);
8533 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8536 /* if the bit lenth is less than or */
8537 /* it exactly fits a byte then */
8538 if (SPEC_BLEN (etype) <= 8)
8540 shCount = SPEC_BSTR (etype);
8542 /* shift left acc */
8545 if (SPEC_BLEN (etype) < 8)
8546 { /* if smaller than a byte */
8552 emitcode ("mov", "b,a");
8553 emitcode ("mov", "a,@%s", rname);
8557 emitcode ("mov", "b,a");
8558 emitcode ("movx", "a,@dptr");
8562 emitcode ("push", "b");
8563 emitcode ("push", "acc");
8564 emitcode ("lcall", "__gptrget");
8565 emitcode ("pop", "b");
8569 emitcode ("anl", "a,#0x%02x", (unsigned char)
8570 ((unsigned char) (0xFF << (blen + bstr)) |
8571 (unsigned char) (0xFF >> (8 - bstr))));
8572 emitcode ("orl", "a,b");
8573 if (p_type == GPOINTER)
8574 emitcode ("pop", "b");
8581 emitcode ("mov", "@%s,a", rname);
8585 emitcode ("movx", "@dptr,a");
8589 emitcode ("lcall", "__gptrput");
8594 if (SPEC_BLEN (etype) <= 8)
8597 emitcode ("inc", "%s", rname);
8598 rLen = SPEC_BLEN (etype);
8600 /* now generate for lengths greater than one byte */
8604 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8616 emitcode ("mov", "@%s,a", rname);
8619 emitcode ("mov", "@%s,%s", rname, l);
8624 emitcode ("movx", "@dptr,a");
8629 emitcode ("lcall", "__gptrput");
8632 emitcode ("inc", "%s", rname);
8637 /* last last was not complete */
8640 /* save the byte & read byte */
8644 emitcode ("mov", "b,a");
8645 emitcode ("mov", "a,@%s", rname);
8649 emitcode ("mov", "b,a");
8650 emitcode ("movx", "a,@dptr");
8654 emitcode ("push", "b");
8655 emitcode ("push", "acc");
8656 emitcode ("lcall", "__gptrget");
8657 emitcode ("pop", "b");
8661 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8662 emitcode ("orl", "a,b");
8665 if (p_type == GPOINTER)
8666 emitcode ("pop", "b");
8672 emitcode ("mov", "@%s,a", rname);
8676 emitcode ("movx", "@dptr,a");
8680 emitcode ("lcall", "__gptrput");
8684 /*-----------------------------------------------------------------*/
8685 /* genDataPointerSet - remat pointer to data space */
8686 /*-----------------------------------------------------------------*/
8688 genDataPointerSet (operand * right,
8692 int size, offset = 0;
8693 char *l, buffer[256];
8695 aopOp (right, ic, FALSE, FALSE);
8697 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8698 size = AOP_SIZE (right);
8702 sprintf (buffer, "(%s + %d)", l + 1, offset);
8704 sprintf (buffer, "%s", l + 1);
8705 emitcode ("mov", "%s,%s", buffer,
8706 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8709 freeAsmop (right, NULL, ic, TRUE);
8710 freeAsmop (result, NULL, ic, TRUE);
8713 /*-----------------------------------------------------------------*/
8714 /* genNearPointerSet - emitcode for near pointer put */
8715 /*-----------------------------------------------------------------*/
8717 genNearPointerSet (operand * right,
8724 sym_link *retype, *letype;
8725 sym_link *ptype = operandType (result);
8727 retype = getSpec (operandType (right));
8728 letype = getSpec (ptype);
8730 aopOp (result, ic, FALSE, FALSE);
8732 /* if the result is rematerializable &
8733 in data space & not a bit variable */
8734 if (AOP_TYPE (result) == AOP_IMMD &&
8735 DCL_TYPE (ptype) == POINTER &&
8736 !IS_BITVAR (retype) &&
8737 !IS_BITVAR (letype))
8739 genDataPointerSet (right, result, ic);
8743 /* if the value is already in a pointer register
8744 then don't need anything more */
8745 if (!AOP_INPREG (AOP (result)))
8747 /* otherwise get a free pointer register */
8749 preg = getFreePtr (ic, &aop, FALSE);
8750 emitcode ("mov", "%s,%s",
8752 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8756 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8758 freeAsmop (result, NULL, ic, TRUE);
8759 aopOp (right, ic, FALSE, FALSE);
8761 /* if bitfield then unpack the bits */
8762 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8763 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8766 /* we have can just get the values */
8767 int size = AOP_SIZE (right);
8772 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8776 emitcode ("mov", "@%s,a", rname);
8779 emitcode ("mov", "@%s,%s", rname, l);
8781 emitcode ("inc", "%s", rname);
8786 /* now some housekeeping stuff */
8789 /* we had to allocate for this iCode */
8790 freeAsmop (NULL, aop, ic, TRUE);
8794 /* we did not allocate which means left
8795 already in a pointer register, then
8796 if size > 0 && this could be used again
8797 we have to point it back to where it
8799 if (AOP_SIZE (right) > 1 &&
8800 !OP_SYMBOL (result)->remat &&
8801 (OP_SYMBOL (result)->liveTo > ic->seq ||
8804 int size = AOP_SIZE (right) - 1;
8806 emitcode ("dec", "%s", rname);
8811 freeAsmop (right, NULL, ic, TRUE);
8816 /*-----------------------------------------------------------------*/
8817 /* genPagedPointerSet - emitcode for Paged pointer put */
8818 /*-----------------------------------------------------------------*/
8820 genPagedPointerSet (operand * right,
8827 sym_link *retype, *letype;
8829 retype = getSpec (operandType (right));
8830 letype = getSpec (operandType (result));
8832 aopOp (result, ic, FALSE, FALSE);
8834 /* if the value is already in a pointer register
8835 then don't need anything more */
8836 if (!AOP_INPREG (AOP (result)))
8838 /* otherwise get a free pointer register */
8840 preg = getFreePtr (ic, &aop, FALSE);
8841 emitcode ("mov", "%s,%s",
8843 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8847 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8849 freeAsmop (result, NULL, ic, TRUE);
8850 aopOp (right, ic, FALSE, FALSE);
8852 /* if bitfield then unpack the bits */
8853 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8854 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8857 /* we have can just get the values */
8858 int size = AOP_SIZE (right);
8863 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8866 emitcode ("movx", "@%s,a", rname);
8869 emitcode ("inc", "%s", rname);
8875 /* now some housekeeping stuff */
8878 /* we had to allocate for this iCode */
8879 freeAsmop (NULL, aop, ic, TRUE);
8883 /* we did not allocate which means left
8884 already in a pointer register, then
8885 if size > 0 && this could be used again
8886 we have to point it back to where it
8888 if (AOP_SIZE (right) > 1 &&
8889 !OP_SYMBOL (result)->remat &&
8890 (OP_SYMBOL (result)->liveTo > ic->seq ||
8893 int size = AOP_SIZE (right) - 1;
8895 emitcode ("dec", "%s", rname);
8900 freeAsmop (right, NULL, ic, TRUE);
8905 /*-----------------------------------------------------------------*/
8906 /* genFarPointerSet - set value from far space */
8907 /*-----------------------------------------------------------------*/
8909 genFarPointerSet (operand * right,
8910 operand * result, iCode * ic)
8913 sym_link *retype = getSpec (operandType (right));
8914 sym_link *letype = getSpec (operandType (result));
8916 aopOp (result, ic, FALSE, FALSE);
8918 /* if the operand is already in dptr
8919 then we do nothing else we move the value to dptr */
8920 if (AOP_TYPE (result) != AOP_STR)
8922 /* if this is remateriazable */
8923 if (AOP_TYPE (result) == AOP_IMMD)
8924 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8927 /* we need to get it byte by byte */
8928 _startLazyDPSEvaluation ();
8929 if (AOP_TYPE (result) != AOP_DPTR)
8931 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8932 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8933 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8937 /* We need to generate a load to DPTR indirect through DPTR. */
8938 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8940 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8941 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8942 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8943 emitcode ("pop", "dph");
8944 emitcode ("pop", "dpl");
8946 _endLazyDPSEvaluation ();
8949 /* so dptr know contains the address */
8950 freeAsmop (result, NULL, ic, TRUE);
8951 aopOp (right, ic, FALSE, TRUE);
8953 /* if bit then unpack */
8954 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8955 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8958 size = AOP_SIZE (right);
8961 _startLazyDPSEvaluation ();
8964 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8970 emitcode ("movx", "@dptr,a");
8972 emitcode ("inc", "dptr");
8974 _endLazyDPSEvaluation ();
8977 freeAsmop (right, NULL, ic, TRUE);
8980 /*-----------------------------------------------------------------*/
8981 /* genGenPointerSet - set value from generic pointer space */
8982 /*-----------------------------------------------------------------*/
8984 genGenPointerSet (operand * right,
8985 operand * result, iCode * ic)
8988 sym_link *retype = getSpec (operandType (right));
8989 sym_link *letype = getSpec (operandType (result));
8991 aopOp (result, ic, FALSE, TRUE);
8993 /* if the operand is already in dptr
8994 then we do nothing else we move the value to dptr */
8995 if (AOP_TYPE (result) != AOP_STR)
8997 _startLazyDPSEvaluation ();
8998 /* if this is remateriazable */
8999 if (AOP_TYPE (result) == AOP_IMMD)
9001 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9002 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9005 { /* we need to get it byte by byte */
9006 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9007 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9008 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9009 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9011 _endLazyDPSEvaluation ();
9013 /* so dptr know contains the address */
9014 freeAsmop (result, NULL, ic, TRUE);
9015 aopOp (right, ic, FALSE, TRUE);
9017 /* if bit then unpack */
9018 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9019 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9022 size = AOP_SIZE (right);
9025 _startLazyDPSEvaluation ();
9028 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9034 emitcode ("lcall", "__gptrput");
9036 emitcode ("inc", "dptr");
9038 _endLazyDPSEvaluation ();
9041 freeAsmop (right, NULL, ic, TRUE);
9044 /*-----------------------------------------------------------------*/
9045 /* genPointerSet - stores the value into a pointer location */
9046 /*-----------------------------------------------------------------*/
9048 genPointerSet (iCode * ic)
9050 operand *right, *result;
9051 sym_link *type, *etype;
9054 D (emitcode (";", "genPointerSet ");
9057 right = IC_RIGHT (ic);
9058 result = IC_RESULT (ic);
9060 /* depending on the type of pointer we need to
9061 move it to the correct pointer register */
9062 type = operandType (result);
9063 etype = getSpec (type);
9064 /* if left is of type of pointer then it is simple */
9065 if (IS_PTR (type) && !IS_FUNC (type->next))
9067 p_type = DCL_TYPE (type);
9071 /* we have to go by the storage class */
9072 p_type = PTR_TYPE (SPEC_OCLS (etype));
9075 /* now that we have the pointer type we assign
9076 the pointer values */
9082 genNearPointerSet (right, result, ic);
9086 genPagedPointerSet (right, result, ic);
9090 genFarPointerSet (right, result, ic);
9094 genGenPointerSet (right, result, ic);
9100 /*-----------------------------------------------------------------*/
9101 /* genIfx - generate code for Ifx statement */
9102 /*-----------------------------------------------------------------*/
9104 genIfx (iCode * ic, iCode * popIc)
9106 operand *cond = IC_COND (ic);
9109 D (emitcode (";", "genIfx "););
9111 aopOp (cond, ic, FALSE, FALSE);
9113 /* get the value into acc */
9114 if (AOP_TYPE (cond) != AOP_CRY)
9118 /* the result is now in the accumulator */
9119 freeAsmop (cond, NULL, ic, TRUE);
9121 /* if there was something to be popped then do it */
9125 /* if the condition is a bit variable */
9126 if (isbit && IS_ITEMP (cond) &&
9128 genIfxJump (ic, SPIL_LOC (cond)->rname);
9129 else if (isbit && !IS_ITEMP (cond))
9130 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9132 genIfxJump (ic, "a");
9137 /*-----------------------------------------------------------------*/
9138 /* genAddrOf - generates code for address of */
9139 /*-----------------------------------------------------------------*/
9141 genAddrOf (iCode * ic)
9143 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9146 D (emitcode (";", "genAddrOf ");
9149 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9151 /* if the operand is on the stack then we
9152 need to get the stack offset of this
9156 /* if it has an offset then we need to compute
9160 emitcode ("mov", "a,_bp");
9161 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9162 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9166 /* we can just move _bp */
9167 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9169 /* fill the result with zero */
9170 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9173 if (options.stack10bit && size < (FPTRSIZE - 1))
9176 "*** warning: pointer to stack var truncated.\n");
9183 if (options.stack10bit && offset == 2)
9185 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9189 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9196 /* object not on stack then we need the name */
9197 size = AOP_SIZE (IC_RESULT (ic));
9202 char s[SDCC_NAME_MAX];
9204 sprintf (s, "#(%s >> %d)",
9208 sprintf (s, "#%s", sym->rname);
9209 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9213 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9217 /*-----------------------------------------------------------------*/
9218 /* genArrayInit - generates code for address of */
9219 /*-----------------------------------------------------------------*/
9221 genArrayInit (iCode * ic)
9225 int elementSize = 0, eIndex;
9226 unsigned val, lastVal;
9229 D (emitcode (";", "genArrayInit "););
9231 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9233 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9235 // Load immediate value into DPTR.
9236 emitcode("mov", "dptr, %s",
9237 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9239 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9241 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9242 "Unexpected operand to genArrayInit.\n");
9246 type = operandType(IC_LEFT(ic));
9248 if (type && type->next)
9250 elementSize = getSize(type->next);
9254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9255 "can't determine element size in genArrayInit.\n");
9259 iLoop = IC_ARRAYILIST(ic);
9264 bool firstpass = TRUE;
9266 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9267 iLoop->count, (int)iLoop->literalValue, elementSize);
9273 symbol *tlbl = NULL;
9275 count = ix > 256 ? 256 : ix;
9279 tlbl = newiTempLabel (NULL);
9280 if (firstpass || (count & 0xff))
9282 emitcode("mov", "b, #0x%x", count & 0xff);
9285 emitcode ("", "%05d$:", tlbl->key + 100);
9290 for (eIndex = 0; eIndex < elementSize; eIndex++)
9292 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9295 emitcode("mov", "a, #0x%x", val);
9299 emitcode("movx", "@dptr, a");
9300 emitcode("inc", "dptr");
9305 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9311 iLoop = iLoop->next;
9314 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9317 /*-----------------------------------------------------------------*/
9318 /* genFarFarAssign - assignment when both are in far space */
9319 /*-----------------------------------------------------------------*/
9321 genFarFarAssign (operand * result, operand * right, iCode * ic)
9323 int size = AOP_SIZE (right);
9325 symbol *rSym = NULL;
9329 /* quick & easy case. */
9330 D(emitcode(";","genFarFarAssign (1 byte case)"););
9331 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9332 freeAsmop (right, NULL, ic, FALSE);
9333 /* now assign DPTR to result */
9335 aopOp(result, ic, FALSE, FALSE);
9337 aopPut(AOP(result), "a", 0);
9338 freeAsmop(result, NULL, ic, FALSE);
9342 /* See if we've got an underlying symbol to abuse. */
9343 if (IS_SYMOP(result) && OP_SYMBOL(result))
9345 if (IS_TRUE_SYMOP(result))
9347 rSym = OP_SYMBOL(result);
9349 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9351 rSym = OP_SYMBOL(result)->usl.spillLoc;
9355 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9357 /* We can use the '390 auto-toggle feature to good effect here. */
9359 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9360 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9361 emitcode ("mov", "dptr,#%s", rSym->rname);
9362 /* DP2 = result, DP1 = right, DP1 is current. */
9365 emitcode("movx", "a,@dptr");
9366 emitcode("movx", "@dptr,a");
9369 emitcode("inc", "dptr");
9370 emitcode("inc", "dptr");
9373 emitcode("mov", "dps, #0");
9374 freeAsmop (right, NULL, ic, FALSE);
9378 D (emitcode (";", "genFarFarAssign"););
9379 aopOp (result, ic, TRUE, TRUE);
9381 _startLazyDPSEvaluation ();
9385 aopPut (AOP (result),
9386 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9389 _endLazyDPSEvaluation ();
9390 freeAsmop (result, NULL, ic, FALSE);
9391 freeAsmop (right, NULL, ic, FALSE);
9395 /*-----------------------------------------------------------------*/
9396 /* genAssign - generate code for assignment */
9397 /*-----------------------------------------------------------------*/
9399 genAssign (iCode * ic)
9401 operand *result, *right;
9403 unsigned long lit = 0L;
9405 D (emitcode (";", "genAssign ");
9408 result = IC_RESULT (ic);
9409 right = IC_RIGHT (ic);
9411 /* if they are the same */
9412 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9415 aopOp (right, ic, FALSE, FALSE);
9417 emitcode (";", "genAssign: resultIsFar = %s",
9418 isOperandInFarSpace (result) ?
9421 /* special case both in far space */
9422 if ((AOP_TYPE (right) == AOP_DPTR ||
9423 AOP_TYPE (right) == AOP_DPTR2) &&
9424 /* IS_TRUE_SYMOP(result) && */
9425 isOperandInFarSpace (result))
9427 genFarFarAssign (result, right, ic);
9431 aopOp (result, ic, TRUE, FALSE);
9433 /* if they are the same registers */
9434 if (sameRegs (AOP (right), AOP (result)))
9437 /* if the result is a bit */
9438 if (AOP_TYPE (result) == AOP_CRY)
9441 /* if the right size is a literal then
9442 we know what the value is */
9443 if (AOP_TYPE (right) == AOP_LIT)
9445 if (((int) operandLitValue (right)))
9446 aopPut (AOP (result), one, 0);
9448 aopPut (AOP (result), zero, 0);
9452 /* the right is also a bit variable */
9453 if (AOP_TYPE (right) == AOP_CRY)
9455 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9456 aopPut (AOP (result), "c", 0);
9462 aopPut (AOP (result), "a", 0);
9466 /* bit variables done */
9468 size = AOP_SIZE (result);
9470 if (AOP_TYPE (right) == AOP_LIT)
9471 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9474 (AOP_TYPE (result) != AOP_REG) &&
9475 (AOP_TYPE (right) == AOP_LIT) &&
9476 !IS_FLOAT (operandType (right)))
9478 _startLazyDPSEvaluation ();
9479 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9481 aopPut (AOP (result),
9482 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9487 /* And now fill the rest with zeros. */
9490 emitcode ("clr", "a");
9494 aopPut (AOP (result), "a", offset++);
9496 _endLazyDPSEvaluation ();
9500 _startLazyDPSEvaluation ();
9503 aopPut (AOP (result),
9504 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9508 _endLazyDPSEvaluation ();
9512 freeAsmop (right, NULL, ic, FALSE);
9513 freeAsmop (result, NULL, ic, TRUE);
9516 /*-----------------------------------------------------------------*/
9517 /* genJumpTab - generates code for jump table */
9518 /*-----------------------------------------------------------------*/
9520 genJumpTab (iCode * ic)
9525 D (emitcode (";", "genJumpTab ");
9528 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9529 /* get the condition into accumulator */
9530 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9532 /* multiply by four! */
9533 emitcode ("add", "a,acc");
9534 emitcode ("add", "a,acc");
9535 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9537 jtab = newiTempLabel (NULL);
9538 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9539 emitcode ("jmp", "@a+dptr");
9540 emitcode ("", "%05d$:", jtab->key + 100);
9541 /* now generate the jump labels */
9542 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9543 jtab = setNextItem (IC_JTLABELS (ic)))
9544 emitcode ("ljmp", "%05d$", jtab->key + 100);
9548 /*-----------------------------------------------------------------*/
9549 /* genCast - gen code for casting */
9550 /*-----------------------------------------------------------------*/
9552 genCast (iCode * ic)
9554 operand *result = IC_RESULT (ic);
9555 sym_link *ctype = operandType (IC_LEFT (ic));
9556 sym_link *rtype = operandType (IC_RIGHT (ic));
9557 operand *right = IC_RIGHT (ic);
9560 D (emitcode (";", "genCast ");
9563 /* if they are equivalent then do nothing */
9564 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9567 aopOp (right, ic, FALSE, FALSE);
9568 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9570 /* if the result is a bit */
9571 if (AOP_TYPE (result) == AOP_CRY)
9573 /* if the right size is a literal then
9574 we know what the value is */
9575 if (AOP_TYPE (right) == AOP_LIT)
9577 if (((int) operandLitValue (right)))
9578 aopPut (AOP (result), one, 0);
9580 aopPut (AOP (result), zero, 0);
9585 /* the right is also a bit variable */
9586 if (AOP_TYPE (right) == AOP_CRY)
9588 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9589 aopPut (AOP (result), "c", 0);
9595 aopPut (AOP (result), "a", 0);
9599 /* if they are the same size : or less */
9600 if (AOP_SIZE (result) <= AOP_SIZE (right))
9603 /* if they are in the same place */
9604 if (sameRegs (AOP (right), AOP (result)))
9607 /* if they in different places then copy */
9608 size = AOP_SIZE (result);
9610 _startLazyDPSEvaluation ();
9613 aopPut (AOP (result),
9614 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9618 _endLazyDPSEvaluation ();
9623 /* if the result is of type pointer */
9628 sym_link *type = operandType (right);
9630 /* pointer to generic pointer */
9631 if (IS_GENPTR (ctype))
9637 p_type = DCL_TYPE (type);
9641 #if OLD_CAST_BEHAVIOR
9642 /* KV: we are converting a non-pointer type to
9643 * a generic pointer. This (ifdef'd out) code
9644 * says that the resulting generic pointer
9645 * should have the same class as the storage
9646 * location of the non-pointer variable.
9648 * For example, converting an int (which happens
9649 * to be stored in DATA space) to a pointer results
9650 * in a DATA generic pointer; if the original int
9651 * in XDATA space, so will be the resulting pointer.
9653 * I don't like that behavior, and thus this change:
9654 * all such conversions will be forced to XDATA and
9655 * throw a warning. If you want some non-XDATA
9656 * type, or you want to suppress the warning, you
9657 * must go through an intermediate cast, like so:
9659 * char _generic *gp = (char _xdata *)(intVar);
9661 sym_link *etype = getSpec (type);
9663 /* we have to go by the storage class */
9664 if (SPEC_OCLS (etype) != generic)
9666 p_type = PTR_TYPE (SPEC_OCLS (etype));
9671 /* Converting unknown class (i.e. register variable)
9672 * to generic pointer. This is not good, but
9673 * we'll make a guess (and throw a warning).
9676 werror (W_INT_TO_GEN_PTR_CAST);
9680 /* the first two bytes are known */
9681 size = GPTRSIZE - 1;
9683 _startLazyDPSEvaluation ();
9686 aopPut (AOP (result),
9687 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9691 _endLazyDPSEvaluation ();
9693 /* the last byte depending on type */
9711 /* this should never happen */
9712 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9713 "got unknown pointer type");
9716 aopPut (AOP (result), l, GPTRSIZE - 1);
9720 /* just copy the pointers */
9721 size = AOP_SIZE (result);
9723 _startLazyDPSEvaluation ();
9726 aopPut (AOP (result),
9727 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9731 _endLazyDPSEvaluation ();
9735 /* so we now know that the size of destination is greater
9736 than the size of the source */
9737 /* we move to result for the size of source */
9738 size = AOP_SIZE (right);
9740 _startLazyDPSEvaluation ();
9743 aopPut (AOP (result),
9744 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9748 _endLazyDPSEvaluation ();
9750 /* now depending on the sign of the source && destination */
9751 size = AOP_SIZE (result) - AOP_SIZE (right);
9752 /* if unsigned or not an integral type */
9753 /* also, if the source is a bit, we don't need to sign extend, because
9754 * it can't possibly have set the sign bit.
9756 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9760 aopPut (AOP (result), zero, offset++);
9765 /* we need to extend the sign :{ */
9766 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9767 FALSE, FALSE, TRUE);
9769 emitcode ("rlc", "a");
9770 emitcode ("subb", "a,acc");
9772 aopPut (AOP (result), "a", offset++);
9775 /* we are done hurray !!!! */
9778 freeAsmop (right, NULL, ic, TRUE);
9779 freeAsmop (result, NULL, ic, TRUE);
9783 /*-----------------------------------------------------------------*/
9784 /* genDjnz - generate decrement & jump if not zero instrucion */
9785 /*-----------------------------------------------------------------*/
9787 genDjnz (iCode * ic, iCode * ifx)
9793 /* if the if condition has a false label
9794 then we cannot save */
9798 /* if the minus is not of the form
9800 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9801 !IS_OP_LITERAL (IC_RIGHT (ic)))
9804 if (operandLitValue (IC_RIGHT (ic)) != 1)
9807 /* if the size of this greater than one then no
9809 if (getSize (operandType (IC_RESULT (ic))) > 1)
9812 /* otherwise we can save BIG */
9813 D(emitcode(";", "genDjnz"););
9815 lbl = newiTempLabel (NULL);
9816 lbl1 = newiTempLabel (NULL);
9818 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9820 if (AOP_NEEDSACC(IC_RESULT(ic)))
9822 /* If the result is accessed indirectly via
9823 * the accumulator, we must explicitly write
9824 * it back after the decrement.
9826 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9828 if (strcmp(rByte, "a"))
9830 /* Something is hopelessly wrong */
9831 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9832 __FILE__, __LINE__);
9833 /* We can just give up; the generated code will be inefficient,
9836 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9839 emitcode ("dec", "%s", rByte);
9840 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9841 emitcode ("jnz", "%05d$", lbl->key + 100);
9843 else if (IS_AOP_PREG (IC_RESULT (ic)))
9845 emitcode ("dec", "%s",
9846 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9847 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9848 emitcode ("jnz", "%05d$", lbl->key + 100);
9852 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9855 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9856 emitcode ("", "%05d$:", lbl->key + 100);
9857 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9858 emitcode ("", "%05d$:", lbl1->key + 100);
9860 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9865 /*-----------------------------------------------------------------*/
9866 /* genReceive - generate code for a receive iCode */
9867 /*-----------------------------------------------------------------*/
9869 genReceive (iCode * ic)
9872 D (emitcode (";", "genReceive ");
9875 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9876 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9877 IS_TRUE_SYMOP (IC_RESULT (ic))))
9879 int size = getSize (operandType (IC_RESULT (ic)));
9880 int offset = fReturnSizeDS390 - size;
9883 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9884 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9887 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9888 size = AOP_SIZE (IC_RESULT (ic));
9892 emitcode ("pop", "acc");
9893 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9900 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9902 assignResultValue (IC_RESULT (ic));
9905 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9908 /*-----------------------------------------------------------------*/
9909 /* gen390Code - generate code for Dallas 390 based controllers */
9910 /*-----------------------------------------------------------------*/
9912 gen390Code (iCode * lic)
9917 lineHead = lineCurr = NULL;
9921 /* print the allocation information */
9923 printAllocInfo (currFunc, codeOutFile);
9925 /* if debug information required */
9926 if (options.debug && currFunc)
9928 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9930 if (IS_STATIC (currFunc->etype))
9931 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9933 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9936 /* stack pointer name */
9937 if (options.useXstack)
9943 for (ic = lic; ic; ic = ic->next)
9946 if (cln != ic->lineno)
9951 emitcode ("", "C$%s$%d$%d$%d ==.",
9952 FileBaseName (ic->filename), ic->lineno,
9953 ic->level, ic->block);
9956 emitcode (";", "%s %d", ic->filename, ic->lineno);
9959 /* if the result is marked as
9960 spilt and rematerializable or code for
9961 this has already been generated then
9963 if (resultRemat (ic) || ic->generated)
9966 /* depending on the operation */
9986 /* IPOP happens only when trying to restore a
9987 spilt live range, if there is an ifx statement
9988 following this pop then the if statement might
9989 be using some of the registers being popped which
9990 would destory the contents of the register so
9991 we need to check for this condition and handle it */
9993 ic->next->op == IFX &&
9994 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9995 genIfx (ic->next, ic);
10013 genEndFunction (ic);
10033 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10050 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10054 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10061 /* note these two are xlated by algebraic equivalence
10062 during parsing SDCC.y */
10063 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10064 "got '>=' or '<=' shouldn't have come here");
10068 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10080 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10084 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10088 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10112 genRightShift (ic);
10115 case GET_VALUE_AT_ADDRESS:
10116 genPointerGet (ic);
10120 if (POINTER_SET (ic))
10121 genPointerSet (ic);
10147 addSet (&_G.sendSet, ic);
10160 /* now we are ready to call the
10161 peep hole optimizer */
10162 if (!options.nopeep)
10163 peepHole (&lineHead);
10165 /* now do the actual printing */
10166 printLine (lineHead, codeOutFile);