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)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #define BETTER_LITERAL_SHIFT
53 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
66 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
67 static char *fReturn[] =
68 {"dpl", "dph", "dpx", "b", "a"};
69 static char *accUse[] =
72 static short rbank = -1;
86 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
93 #define MOVA(x) { char *_mova_tmp = strdup(x); \
94 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96 emitcode("mov","a,%s",_mova_tmp); \
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
122 /*-----------------------------------------------------------------*/
123 /* emitcode - writes the code into a file : for now it is simple */
124 /*-----------------------------------------------------------------*/
126 emitcode (char *inst, char *fmt,...)
129 char lb[INITIAL_INLINEASM];
137 sprintf (lb, "%s\t", inst);
139 sprintf (lb, "%s", inst);
140 vsprintf (lb + (strlen (lb)), fmt, ap);
143 vsprintf (lb, fmt, ap);
145 while (isspace (*lbp))
149 lineCurr = (lineCurr ?
150 connectLine (lineCurr, newLineNode (lb)) :
151 (lineHead = newLineNode (lb)));
152 lineCurr->isInline = _G.inLine;
153 lineCurr->isDebug = _G.debugLine;
157 /*-----------------------------------------------------------------*/
158 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
159 /*-----------------------------------------------------------------*/
161 getFreePtr (iCode * ic, asmop ** aopp, bool result)
163 bool r0iu = FALSE, r1iu = FALSE;
164 bool r0ou = FALSE, r1ou = FALSE;
166 /* the logic: if r0 & r1 used in the instruction
167 then we are in trouble otherwise */
169 /* first check if r0 & r1 are used by this
170 instruction, in which case we are in trouble */
171 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
172 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
177 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
178 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
180 /* if no usage of r0 then return it */
183 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
184 (*aopp)->type = AOP_R0;
186 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
189 /* if no usage of r1 then return it */
192 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
193 (*aopp)->type = AOP_R1;
195 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
198 /* now we know they both have usage */
199 /* if r0 not used in this instruction */
202 /* push it if not already pushed */
205 emitcode ("push", "%s",
206 ds390_regWithIdx (R0_IDX)->dname);
210 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
211 (*aopp)->type = AOP_R0;
213 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
216 /* if r1 not used then */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 ds390_regWithIdx (R1_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
229 (*aopp)->type = AOP_R1;
230 return ds390_regWithIdx (R1_IDX);
234 /* I said end of world but not quite end of world yet */
235 /* if this is a result then we can push it on the stack */
238 (*aopp)->type = AOP_STK;
242 /* other wise this is true end of the world */
243 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
244 "getFreePtr should never reach here");
248 /*-----------------------------------------------------------------*/
249 /* newAsmop - creates a new asmOp */
250 /*-----------------------------------------------------------------*/
252 newAsmop (short type)
256 aop = Safe_calloc (1, sizeof (asmop));
261 static int _currentDPS; /* Current processor DPS. */
262 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
263 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
265 /*-----------------------------------------------------------------*/
266 /* genSetDPTR: generate code to select which DPTR is in use (zero */
267 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
268 /* alternate DPTR (DPL1/DPH1/DPX1). */
269 /*-----------------------------------------------------------------*/
274 /* If we are doing lazy evaluation, simply note the desired
275 * change, but don't emit any code yet.
285 emitcode ("mov", "dps, #0x00");
289 emitcode ("mov", "dps, #0x01");
293 /*-----------------------------------------------------------------*/
294 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
296 /* Any code that operates on DPTR (NB: not on the individual */
297 /* components, like DPH) *must* call _flushLazyDPS() before using */
298 /* DPTR within a lazy DPS evaluation block. */
300 /* Note that aopPut and aopGet already contain the proper calls to */
301 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
302 /* DPS evaluation block. */
304 /* Also, _flushLazyDPS must be called before any flow control */
305 /* operations that could potentially branch out of the block. */
307 /* Lazy DPS evaluation is simply an optimization (though an */
308 /* important one), so if in doubt, leave it out. */
309 /*-----------------------------------------------------------------*/
311 _startLazyDPSEvaluation (void)
315 #ifdef BETTER_LITERAL_SHIFT
322 /*-----------------------------------------------------------------*/
323 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
324 /* desired one. Call before using DPTR within a lazy DPS evaluation */
326 /*-----------------------------------------------------------------*/
336 if (_desiredDPS != _currentDPS)
340 emitcode ("inc", "dps");
344 emitcode ("dec", "dps");
346 _currentDPS = _desiredDPS;
350 /*-----------------------------------------------------------------*/
351 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
353 /* Forces us back to the safe state (standard DPTR selected). */
354 /*-----------------------------------------------------------------*/
356 _endLazyDPSEvaluation (void)
358 #ifdef BETTER_LITERAL_SHIFT
377 /*-----------------------------------------------------------------*/
378 /* pointerCode - returns the code for a pointer type */
379 /*-----------------------------------------------------------------*/
381 pointerCode (sym_link * etype)
384 return PTR_TYPE (SPEC_OCLS (etype));
388 /*-----------------------------------------------------------------*/
389 /* aopForSym - for a true symbol */
390 /*-----------------------------------------------------------------*/
392 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
395 memmap *space = SPEC_OCLS (sym->etype);
397 /* if already has one */
401 /* assign depending on the storage class */
402 /* if it is on the stack or indirectly addressable */
403 /* space we need to assign either r0 or r1 to it */
404 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
406 sym->aop = aop = newAsmop (0);
407 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
408 aop->size = getSize (sym->type);
410 /* now assign the address of the variable to
411 the pointer register */
412 if (aop->type != AOP_STK)
418 emitcode ("push", "acc");
420 emitcode ("mov", "a,_bp");
421 emitcode ("add", "a,#0x%02x",
423 ((char) (sym->stack - _G.nRegsSaved)) :
424 ((char) sym->stack)) & 0xff);
425 emitcode ("mov", "%s,a",
426 aop->aopu.aop_ptr->name);
429 emitcode ("pop", "acc");
432 emitcode ("mov", "%s,#%s",
433 aop->aopu.aop_ptr->name,
435 aop->paged = space->paged;
438 aop->aopu.aop_stk = sym->stack;
442 if (sym->onStack && options.stack10bit)
444 /* It's on the 10 bit stack, which is located in
449 emitcode ("push", "acc");
451 emitcode ("mov", "a,_bp");
452 emitcode ("add", "a,#0x%02x",
454 ((char) (sym->stack - _G.nRegsSaved)) :
455 ((char) sym->stack)) & 0xff);
459 emitcode ("mov", "dpx1,#0x40");
460 emitcode ("mov", "dph1,#0x00");
461 emitcode ("mov", "dpl1, a");
465 emitcode ("mov", "dpx,#0x40");
466 emitcode ("mov", "dph,#0x00");
467 emitcode ("mov", "dpl, a");
471 emitcode ("pop", "acc");
473 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
474 aop->size = getSize (sym->type);
478 /* if in bit space */
479 if (IN_BITSPACE (space))
481 sym->aop = aop = newAsmop (AOP_CRY);
482 aop->aopu.aop_dir = sym->rname;
483 aop->size = getSize (sym->type);
486 /* if it is in direct space */
487 if (IN_DIRSPACE (space))
489 sym->aop = aop = newAsmop (AOP_DIR);
490 aop->aopu.aop_dir = sym->rname;
491 aop->size = getSize (sym->type);
495 /* special case for a function */
496 if (IS_FUNC (sym->type))
498 sym->aop = aop = newAsmop (AOP_IMMD);
499 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
500 strcpy (aop->aopu.aop_immd, sym->rname);
501 aop->size = FPTRSIZE;
505 /* only remaining is far space */
506 /* in which case DPTR gets the address */
507 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
512 emitcode ("mov", "dptr,#%s", sym->rname);
517 emitcode ("mov", "dptr,#%s", sym->rname);
519 aop->size = getSize (sym->type);
521 /* if it is in code space */
522 if (IN_CODESPACE (space))
528 /*-----------------------------------------------------------------*/
529 /* aopForRemat - rematerialzes an object */
530 /*-----------------------------------------------------------------*/
532 aopForRemat (symbol * sym)
534 iCode *ic = sym->rematiCode;
535 asmop *aop = newAsmop (AOP_IMMD);
542 val += (int) operandLitValue (IC_RIGHT (ic));
543 else if (ic->op == '-')
544 val -= (int) operandLitValue (IC_RIGHT (ic));
548 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
552 sprintf (buffer, "(%s %c 0x%04x)",
553 OP_SYMBOL (IC_LEFT (ic))->rname,
554 val >= 0 ? '+' : '-',
557 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
559 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
560 strcpy (aop->aopu.aop_immd, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
658 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
665 if (aop1->type != AOP_REG ||
666 aop2->type != AOP_REG)
669 if (aop1->size != aop2->size)
672 for (i = 0; i < aop1->size; i++)
673 if (aop1->aopu.aop_reg[i] !=
674 aop2->aopu.aop_reg[i])
680 /*-----------------------------------------------------------------*/
681 /* aopOp - allocates an asmop for an operand : */
682 /*-----------------------------------------------------------------*/
684 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
693 /* if this a literal */
694 if (IS_OP_LITERAL (op))
696 op->aop = aop = newAsmop (AOP_LIT);
697 aop->aopu.aop_lit = op->operand.valOperand;
698 aop->size = getSize (operandType (op));
702 /* if already has a asmop then continue */
706 /* if the underlying symbol has a aop */
707 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
709 op->aop = OP_SYMBOL (op)->aop;
713 /* if this is a true symbol */
714 if (IS_TRUE_SYMOP (op))
716 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
720 /* this is a temporary : this has
726 e) can be a return use only */
728 sym = OP_SYMBOL (op);
731 /* if the type is a conditional */
732 if (sym->regType == REG_CND)
734 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
739 /* if it is spilt then two situations
741 b) has a spill location */
742 if (sym->isspilt || sym->nRegs == 0)
745 /* rematerialize it NOW */
748 sym->aop = op->aop = aop =
750 aop->size = getSize (sym->type);
757 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
758 aop->size = getSize (sym->type);
759 for (i = 0; i < 2; i++)
760 aop->aopu.aop_str[i] = accUse[i];
770 /* a AOP_STR uses DPTR, but DPTR is already in use;
773 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
776 aop = op->aop = sym->aop = newAsmop (AOP_STR);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < (int) fReturnSizeDS390; i++)
779 aop->aopu.aop_str[i] = fReturn[i];
783 /* else spill location */
784 sym->aop = op->aop = aop =
785 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
786 aop->size = getSize (sym->type);
790 /* must be in a register */
791 sym->aop = op->aop = aop = newAsmop (AOP_REG);
792 aop->size = sym->nRegs;
793 for (i = 0; i < sym->nRegs; i++)
794 aop->aopu.aop_reg[i] = sym->regs[i];
797 /*-----------------------------------------------------------------*/
798 /* freeAsmop - free up the asmop given to an operand */
799 /*----------------------------------------------------------------*/
801 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
818 /* depending on the asmop type only three cases need work AOP_RO
819 , AOP_R1 && AOP_STK */
827 emitcode ("pop", "ar0");
831 bitVectUnSetBit (ic->rUsed, R0_IDX);
839 emitcode ("pop", "ar1");
843 bitVectUnSetBit (ic->rUsed, R1_IDX);
849 int stk = aop->aopu.aop_stk + aop->size;
850 bitVectUnSetBit (ic->rUsed, R0_IDX);
851 bitVectUnSetBit (ic->rUsed, R1_IDX);
853 getFreePtr (ic, &aop, FALSE);
855 if (options.stack10bit)
857 /* I'm not sure what to do here yet... */
860 "*** Warning: probably generating bad code for "
861 "10 bit stack mode.\n");
866 emitcode ("mov", "a,_bp");
867 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
868 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
872 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
877 emitcode ("pop", "acc");
878 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
881 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
884 freeAsmop (op, NULL, ic, TRUE);
887 emitcode ("pop", "ar0");
893 emitcode ("pop", "ar1");
900 /* all other cases just dealloc */
906 OP_SYMBOL (op)->aop = NULL;
907 /* if the symbol has a spill */
909 SPIL_LOC (op)->aop = NULL;
914 /*------------------------------------------------------------------*/
915 /* aopGet - for fetching value of the aop */
917 /* Set canClobberACC if you are sure it is OK to clobber the value */
918 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
919 /* just less efficient. */
920 /*------------------------------------------------------------------*/
932 /* offset is greater than
934 if (offset > (aop->size - 1) &&
935 aop->type != AOP_LIT)
938 /* depending on type */
944 /* if we need to increment it */
945 while (offset > aop->coff)
947 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
951 while (offset < aop->coff)
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
960 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
961 return (dname ? "acc" : "a");
963 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
964 rs = Safe_calloc (1, strlen (s) + 1);
971 if (aop->type == AOP_DPTR2)
976 emitcode ("xch", "a, %s", DP2_RESULT_REG);
982 while (offset > aop->coff)
984 emitcode ("inc", "dptr");
988 while (offset < aop->coff)
990 emitcode ("lcall", "__decdptr");
997 emitcode ("clr", "a");
998 emitcode ("movc", "a,@a+dptr");
1002 emitcode ("movx", "a,@dptr");
1005 if (aop->type == AOP_DPTR2)
1010 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011 return DP2_RESULT_REG;
1014 return (dname ? "acc" : "a");
1018 sprintf (s, "#%s", aop->aopu.aop_immd);
1020 sprintf (s, "#(%s >> %d)",
1025 aop->aopu.aop_immd);
1026 rs = Safe_calloc (1, strlen (s) + 1);
1032 sprintf (s, "(%s + %d)",
1036 sprintf (s, "%s", aop->aopu.aop_dir);
1037 rs = Safe_calloc (1, strlen (s) + 1);
1043 return aop->aopu.aop_reg[offset]->dname;
1045 return aop->aopu.aop_reg[offset]->name;
1048 emitcode ("clr", "a");
1049 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1050 emitcode ("rlc", "a");
1051 return (dname ? "acc" : "a");
1054 if (!offset && dname)
1056 return aop->aopu.aop_str[offset];
1059 return aopLiteral (aop->aopu.aop_lit, offset);
1063 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1067 return aop->aopu.aop_str[offset];
1071 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1072 "aopget got unsupported aop->type");
1075 /*-----------------------------------------------------------------*/
1076 /* aopPut - puts a string for a aop */
1077 /*-----------------------------------------------------------------*/
1079 aopPut (asmop * aop, char *s, int offset)
1083 if (aop->size && offset > (aop->size - 1))
1085 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1086 "aopPut got offset > aop->size");
1090 /* will assign value to value */
1091 /* depending on where it is ofcourse */
1096 sprintf (d, "(%s + %d)",
1097 aop->aopu.aop_dir, offset);
1099 sprintf (d, "%s", aop->aopu.aop_dir);
1102 emitcode ("mov", "%s,%s", d, s);
1107 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1108 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1111 strcmp (s, "r0") == 0 ||
1112 strcmp (s, "r1") == 0 ||
1113 strcmp (s, "r2") == 0 ||
1114 strcmp (s, "r3") == 0 ||
1115 strcmp (s, "r4") == 0 ||
1116 strcmp (s, "r5") == 0 ||
1117 strcmp (s, "r6") == 0 ||
1118 strcmp (s, "r7") == 0)
1119 emitcode ("mov", "%s,%s",
1120 aop->aopu.aop_reg[offset]->dname, s);
1122 emitcode ("mov", "%s,%s",
1123 aop->aopu.aop_reg[offset]->name, s);
1130 if (aop->type == AOP_DPTR2)
1138 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139 "aopPut writting to code space");
1143 while (offset > aop->coff)
1146 emitcode ("inc", "dptr");
1149 while (offset < aop->coff)
1152 emitcode ("lcall", "__decdptr");
1157 /* if not in accumulater */
1160 emitcode ("movx", "@dptr,a");
1162 if (aop->type == AOP_DPTR2)
1170 while (offset > aop->coff)
1173 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1175 while (offset < aop->coff)
1178 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1185 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1191 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1193 else if (strcmp (s, "r0") == 0 ||
1194 strcmp (s, "r1") == 0 ||
1195 strcmp (s, "r2") == 0 ||
1196 strcmp (s, "r3") == 0 ||
1197 strcmp (s, "r4") == 0 ||
1198 strcmp (s, "r5") == 0 ||
1199 strcmp (s, "r6") == 0 ||
1200 strcmp (s, "r7") == 0)
1203 sprintf (buffer, "a%s", s);
1204 emitcode ("mov", "@%s,%s",
1205 aop->aopu.aop_ptr->name, buffer);
1208 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1213 if (strcmp (s, "a") == 0)
1214 emitcode ("push", "acc");
1216 emitcode ("push", "%s", s);
1221 /* if bit variable */
1222 if (!aop->aopu.aop_dir)
1224 emitcode ("clr", "a");
1225 emitcode ("rlc", "a");
1230 emitcode ("clr", "%s", aop->aopu.aop_dir);
1232 emitcode ("setb", "%s", aop->aopu.aop_dir);
1233 else if (!strcmp (s, "c"))
1234 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237 if (strcmp (s, "a"))
1242 symbol *lbl = newiTempLabel (NULL);
1243 emitcode ("clr", "c");
1244 emitcode ("jz", "%05d$", lbl->key + 100);
1245 emitcode ("cpl", "c");
1246 emitcode ("", "%05d$:", lbl->key + 100);
1247 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1255 if (strcmp (aop->aopu.aop_str[offset], s))
1256 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1261 if (!offset && (strcmp (s, "acc") == 0))
1264 if (strcmp (aop->aopu.aop_str[offset], s))
1265 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1270 "aopPut got unsupported aop->type");
1277 /*--------------------------------------------------------------------*/
1278 /* reAdjustPreg - points a register back to where it should (coff==0) */
1279 /*--------------------------------------------------------------------*/
1281 reAdjustPreg (asmop * aop)
1283 if ((aop->coff==0) || (aop->size <= 1)) {
1292 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1296 if (aop->type == AOP_DPTR2)
1303 emitcode ("lcall", "__decdptr");
1306 if (aop->type == AOP_DPTR2)
1316 #define AOP(op) op->aop
1317 #define AOP_TYPE(op) AOP(op)->type
1318 #define AOP_SIZE(op) AOP(op)->size
1319 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1320 AOP_TYPE(x) == AOP_R0))
1322 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1323 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1326 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1327 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1328 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1330 /* Workaround for DS80C390 bug: div ab may return bogus results
1331 * if A is accessed in instruction immediately before the div.
1333 * Will be fixed in B4 rev of processor, Dallas claims.
1336 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1337 if (!AOP_NEEDSACC(RIGHT)) \
1339 /* We can load A first, then B, since \
1340 * B (the RIGHT operand) won't clobber A, \
1341 * thus avoiding touching A right before the div. \
1343 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1344 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1346 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1350 /* Just stuff in a nop after loading A. */ \
1351 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1352 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1354 emitcode("nop", "; workaround for DS80C390 div bug."); \
1357 /*-----------------------------------------------------------------*/
1358 /* genNotFloat - generates not for float operations */
1359 /*-----------------------------------------------------------------*/
1361 genNotFloat (operand * op, operand * res)
1367 D (emitcode (";", "genNotFloat ");
1370 /* we will put 127 in the first byte of
1372 aopPut (AOP (res), "#127", 0);
1373 size = AOP_SIZE (op) - 1;
1376 _startLazyDPSEvaluation ();
1377 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1382 emitcode ("orl", "a,%s",
1384 offset++, FALSE, FALSE, FALSE));
1386 _endLazyDPSEvaluation ();
1388 tlbl = newiTempLabel (NULL);
1389 aopPut (res->aop, one, 1);
1390 emitcode ("jz", "%05d$", (tlbl->key + 100));
1391 aopPut (res->aop, zero, 1);
1392 emitcode ("", "%05d$:", (tlbl->key + 100));
1394 size = res->aop->size - 2;
1396 /* put zeros in the rest */
1398 aopPut (res->aop, zero, offset++);
1401 /*-----------------------------------------------------------------*/
1402 /* opIsGptr: returns non-zero if the passed operand is */
1403 /* a generic pointer type. */
1404 /*-----------------------------------------------------------------*/
1406 opIsGptr (operand * op)
1408 sym_link *type = operandType (op);
1410 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1417 /*-----------------------------------------------------------------*/
1418 /* getDataSize - get the operand data size */
1419 /*-----------------------------------------------------------------*/
1421 getDataSize (operand * op)
1424 size = AOP_SIZE (op);
1425 if (size == GPTRSIZE)
1427 sym_link *type = operandType (op);
1428 if (IS_GENPTR (type))
1430 /* generic pointer; arithmetic operations
1431 * should ignore the high byte (pointer type).
1439 /*-----------------------------------------------------------------*/
1440 /* outAcc - output Acc */
1441 /*-----------------------------------------------------------------*/
1443 outAcc (operand * result)
1446 size = getDataSize (result);
1449 aopPut (AOP (result), "a", 0);
1452 /* unsigned or positive */
1455 aopPut (AOP (result), zero, offset++);
1460 /*-----------------------------------------------------------------*/
1461 /* outBitC - output a bit C */
1462 /*-----------------------------------------------------------------*/
1464 outBitC (operand * result)
1466 /* if the result is bit */
1467 if (AOP_TYPE (result) == AOP_CRY)
1469 aopPut (AOP (result), "c", 0);
1473 emitcode ("clr", "a");
1474 emitcode ("rlc", "a");
1479 /*-----------------------------------------------------------------*/
1480 /* toBoolean - emit code for orl a,operator(sizeop) */
1481 /*-----------------------------------------------------------------*/
1483 toBoolean (operand * oper)
1485 int size = AOP_SIZE (oper) - 1;
1489 /* The generic part of a generic pointer should
1490 * not participate in it's truth value.
1492 * i.e. 0x10000000 is zero.
1494 if (opIsGptr (oper))
1496 D (emitcode (";", "toBoolean: generic ptr special case.");
1501 _startLazyDPSEvaluation ();
1502 if (AOP_NEEDSACC (oper) && size)
1505 emitcode ("push", "b");
1506 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1510 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1516 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1520 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1523 _endLazyDPSEvaluation ();
1527 emitcode ("mov", "a,b");
1528 emitcode ("pop", "b");
1533 /*-----------------------------------------------------------------*/
1534 /* genNot - generate code for ! operation */
1535 /*-----------------------------------------------------------------*/
1540 sym_link *optype = operandType (IC_LEFT (ic));
1542 D (emitcode (";", "genNot ");
1545 /* assign asmOps to operand & result */
1546 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1547 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1549 /* if in bit space then a special case */
1550 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1552 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1553 emitcode ("cpl", "c");
1554 outBitC (IC_RESULT (ic));
1558 /* if type float then do float */
1559 if (IS_FLOAT (optype))
1561 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1565 toBoolean (IC_LEFT (ic));
1567 tlbl = newiTempLabel (NULL);
1568 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1569 emitcode ("", "%05d$:", tlbl->key + 100);
1570 outBitC (IC_RESULT (ic));
1573 /* release the aops */
1574 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1575 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1579 /*-----------------------------------------------------------------*/
1580 /* genCpl - generate code for complement */
1581 /*-----------------------------------------------------------------*/
1588 D (emitcode (";", "genCpl ");
1592 /* assign asmOps to operand & result */
1593 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1594 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1596 /* if both are in bit space then
1598 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1599 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1602 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1603 emitcode ("cpl", "c");
1604 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1608 size = AOP_SIZE (IC_RESULT (ic));
1609 _startLazyDPSEvaluation ();
1612 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1614 emitcode ("cpl", "a");
1615 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1617 _endLazyDPSEvaluation ();
1621 /* release the aops */
1622 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1623 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* genUminusFloat - unary minus for floating points */
1628 /*-----------------------------------------------------------------*/
1630 genUminusFloat (operand * op, operand * result)
1632 int size, offset = 0;
1634 /* for this we just need to flip the
1635 first it then copy the rest in place */
1636 D (emitcode (";", "genUminusFloat");
1639 _startLazyDPSEvaluation ();
1640 size = AOP_SIZE (op) - 1;
1641 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1644 emitcode ("cpl", "acc.7");
1645 aopPut (AOP (result), "a", 3);
1649 aopPut (AOP (result),
1650 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1654 _endLazyDPSEvaluation ();
1657 /*-----------------------------------------------------------------*/
1658 /* genUminus - unary minus code generation */
1659 /*-----------------------------------------------------------------*/
1661 genUminus (iCode * ic)
1664 sym_link *optype, *rtype;
1666 D (emitcode (";", "genUminus ");
1671 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1672 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1674 /* if both in bit space then special
1676 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1677 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1680 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1681 emitcode ("cpl", "c");
1682 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1686 optype = operandType (IC_LEFT (ic));
1687 rtype = operandType (IC_RESULT (ic));
1689 /* if float then do float stuff */
1690 if (IS_FLOAT (optype))
1692 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1696 /* otherwise subtract from zero */
1697 size = AOP_SIZE (IC_LEFT (ic));
1699 _startLazyDPSEvaluation ();
1702 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1703 if (!strcmp (l, "a"))
1707 emitcode ("cpl", "a");
1708 emitcode ("addc", "a,#0");
1714 emitcode ("clr", "a");
1715 emitcode ("subb", "a,%s", l);
1717 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1719 _endLazyDPSEvaluation ();
1721 /* if any remaining bytes in the result */
1722 /* we just need to propagate the sign */
1723 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1725 emitcode ("rlc", "a");
1726 emitcode ("subb", "a,acc");
1728 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1732 /* release the aops */
1733 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1734 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1737 /*-----------------------------------------------------------------*/
1738 /* saveRegisters - will look for a call and save the registers */
1739 /*-----------------------------------------------------------------*/
1741 saveRegisters (iCode * lic)
1749 for (ic = lic; ic; ic = ic->next)
1750 if (ic->op == CALL || ic->op == PCALL)
1755 fprintf (stderr, "found parameter push with no function call\n");
1759 /* if the registers have been saved already then
1761 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1764 /* find the registers in use at this time
1765 and push them away to safety */
1766 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1770 if (options.useXstack)
1772 if (bitVectBitValue (rsave, R0_IDX))
1773 emitcode ("mov", "b,r0");
1774 emitcode ("mov", "r0,%s", spname);
1775 for (i = 0; i < ds390_nRegs; i++)
1777 if (bitVectBitValue (rsave, i))
1780 emitcode ("mov", "a,b");
1782 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1783 emitcode ("movx", "@r0,a");
1784 emitcode ("inc", "r0");
1787 emitcode ("mov", "%s,r0", spname);
1788 if (bitVectBitValue (rsave, R0_IDX))
1789 emitcode ("mov", "r0,b");
1792 for (i = 0; i < ds390_nRegs; i++)
1794 if (bitVectBitValue (rsave, i))
1795 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1798 detype = getSpec (operandType (IC_LEFT (ic)));
1800 #if 0 // why should we do this here??? jwk20011105
1802 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1803 IS_ISR (currFunc->etype) &&
1805 saveRBank (SPEC_BANK (detype), ic, TRUE);
1809 /*-----------------------------------------------------------------*/
1810 /* unsaveRegisters - pop the pushed registers */
1811 /*-----------------------------------------------------------------*/
1813 unsaveRegisters (iCode * ic)
1817 /* find the registers in use at this time
1818 and push them away to safety */
1819 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1822 if (options.useXstack)
1824 emitcode ("mov", "r0,%s", spname);
1825 for (i = ds390_nRegs; i >= 0; i--)
1827 if (bitVectBitValue (rsave, i))
1829 emitcode ("dec", "r0");
1830 emitcode ("movx", "a,@r0");
1832 emitcode ("mov", "b,a");
1834 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1838 emitcode ("mov", "%s,r0", spname);
1839 if (bitVectBitValue (rsave, R0_IDX))
1840 emitcode ("mov", "r0,b");
1843 for (i = ds390_nRegs; i >= 0; i--)
1845 if (bitVectBitValue (rsave, i))
1846 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1852 /*-----------------------------------------------------------------*/
1854 /*-----------------------------------------------------------------*/
1856 pushSide (operand * oper, int size)
1859 _startLazyDPSEvaluation ();
1862 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1863 if (AOP_TYPE (oper) != AOP_REG &&
1864 AOP_TYPE (oper) != AOP_DIR &&
1867 emitcode ("mov", "a,%s", l);
1868 emitcode ("push", "acc");
1871 emitcode ("push", "%s", l);
1873 _endLazyDPSEvaluation ();
1876 /*-----------------------------------------------------------------*/
1877 /* assignResultValue - */
1878 /*-----------------------------------------------------------------*/
1880 assignResultValue (operand * oper)
1883 int size = AOP_SIZE (oper);
1885 _startLazyDPSEvaluation ();
1888 aopPut (AOP (oper), fReturn[offset], offset);
1891 _endLazyDPSEvaluation ();
1895 /*-----------------------------------------------------------------*/
1896 /* genXpush - pushes onto the external stack */
1897 /*-----------------------------------------------------------------*/
1899 genXpush (iCode * ic)
1901 asmop *aop = newAsmop (0);
1903 int size, offset = 0;
1905 D (emitcode (";", "genXpush ");
1908 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1909 r = getFreePtr (ic, &aop, FALSE);
1912 emitcode ("mov", "%s,_spx", r->name);
1914 size = AOP_SIZE (IC_LEFT (ic));
1915 _startLazyDPSEvaluation ();
1919 char *l = aopGet (AOP (IC_LEFT (ic)),
1920 offset++, FALSE, FALSE, TRUE);
1922 emitcode ("movx", "@%s,a", r->name);
1923 emitcode ("inc", "%s", r->name);
1926 _endLazyDPSEvaluation ();
1929 emitcode ("mov", "_spx,%s", r->name);
1931 freeAsmop (NULL, aop, ic, TRUE);
1932 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1935 /*-----------------------------------------------------------------*/
1936 /* genIpush - genrate code for pushing this gets a little complex */
1937 /*-----------------------------------------------------------------*/
1939 genIpush (iCode * ic)
1941 int size, offset = 0;
1944 D (emitcode (";", "genIpush ");
1947 /* if this is not a parm push : ie. it is spill push
1948 and spill push is always done on the local stack */
1952 /* and the item is spilt then do nothing */
1953 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1956 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1957 size = AOP_SIZE (IC_LEFT (ic));
1958 /* push it on the stack */
1959 _startLazyDPSEvaluation ();
1962 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1968 emitcode ("push", "%s", l);
1970 _endLazyDPSEvaluation ();
1974 /* this is a paramter push: in this case we call
1975 the routine to find the call and save those
1976 registers that need to be saved */
1979 /* if use external stack then call the external
1980 stack pushing routine */
1981 if (options.useXstack)
1987 /* then do the push */
1988 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1990 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1991 size = AOP_SIZE (IC_LEFT (ic));
1993 _startLazyDPSEvaluation ();
1996 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1997 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1998 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2001 emitcode ("mov", "a,%s", l);
2002 emitcode ("push", "acc");
2005 emitcode ("push", "%s", l);
2007 _endLazyDPSEvaluation ();
2009 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genIpop - recover the registers: can happen only for spilling */
2014 /*-----------------------------------------------------------------*/
2016 genIpop (iCode * ic)
2020 D (emitcode (";", "genIpop ");
2024 /* if the temp was not pushed then */
2025 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2028 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2029 size = AOP_SIZE (IC_LEFT (ic));
2030 offset = (size - 1);
2031 _startLazyDPSEvaluation ();
2034 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2035 FALSE, TRUE, TRUE));
2037 _endLazyDPSEvaluation ();
2039 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2042 /*-----------------------------------------------------------------*/
2043 /* unsaveRBank - restores the resgister bank from stack */
2044 /*-----------------------------------------------------------------*/
2046 unsaveRBank (int bank, iCode * ic, bool popPsw)
2054 if (options.useXstack)
2057 r = getFreePtr (ic, &aop, FALSE);
2060 emitcode ("mov", "%s,_spx", r->name);
2061 emitcode ("movx", "a,@%s", r->name);
2062 emitcode ("mov", "psw,a");
2063 emitcode ("dec", "%s", r->name);
2067 emitcode ("pop", "psw");
2070 for (i = (ds390_nRegs - 1); i >= 0; i--)
2072 if (options.useXstack)
2074 emitcode ("movx", "a,@%s", r->name);
2075 emitcode ("mov", "(%s+%d),a",
2076 regs390[i].base, 8 * bank + regs390[i].offset);
2077 emitcode ("dec", "%s", r->name);
2081 emitcode ("pop", "(%s+%d)",
2082 regs390[i].base, 8 * bank + regs390[i].offset);
2085 if (options.useXstack)
2088 emitcode ("mov", "_spx,%s", r->name);
2089 freeAsmop (NULL, aop, ic, TRUE);
2094 /*-----------------------------------------------------------------*/
2095 /* saveRBank - saves an entire register bank on the stack */
2096 /*-----------------------------------------------------------------*/
2098 saveRBank (int bank, iCode * ic, bool pushPsw)
2104 if (options.useXstack)
2108 r = getFreePtr (ic, &aop, FALSE);
2109 emitcode ("mov", "%s,_spx", r->name);
2113 for (i = 0; i < ds390_nRegs; i++)
2115 if (options.useXstack)
2117 emitcode ("inc", "%s", r->name);
2118 emitcode ("mov", "a,(%s+%d)",
2119 regs390[i].base, 8 * bank + regs390[i].offset);
2120 emitcode ("movx", "@%s,a", r->name);
2123 emitcode ("push", "(%s+%d)",
2124 regs390[i].base, 8 * bank + regs390[i].offset);
2129 if (options.useXstack)
2131 emitcode ("mov", "a,psw");
2132 emitcode ("movx", "@%s,a", r->name);
2133 emitcode ("inc", "%s", r->name);
2134 emitcode ("mov", "_spx,%s", r->name);
2135 freeAsmop (NULL, aop, ic, TRUE);
2139 emitcode ("push", "psw");
2141 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2147 /*-----------------------------------------------------------------*/
2148 /* genCall - generates a call statement */
2149 /*-----------------------------------------------------------------*/
2151 genCall (iCode * ic)
2155 D (emitcode (";", "genCall "););
2157 /* if we are calling a function that is not using
2158 the same register bank then we need to save the
2159 destination registers on the stack */
2160 detype = getSpec (operandType (IC_LEFT (ic)));
2162 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2163 IS_ISR (currFunc->etype) &&
2165 saveRBank (SPEC_BANK (detype), ic, TRUE);
2166 } else /* no need to save if we just saved the whole bank */ {
2167 /* if caller saves & we have not saved then */
2172 /* if send set is not empty the assign */
2173 /* We've saved all the registers we care about;
2174 * therefore, we may clobber any register not used
2175 * in the calling convention (i.e. anything not in
2182 for (sic = setFirstItem (_G.sendSet); sic;
2183 sic = setNextItem (_G.sendSet))
2185 int size, offset = 0;
2187 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2188 size = AOP_SIZE (IC_LEFT (sic));
2190 _startLazyDPSEvaluation ();
2193 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2194 FALSE, FALSE, TRUE);
2195 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2197 emitcode("mov", "%s,%s", regs390[offset].name, l);
2199 else if (strcmp (l, fReturn[offset]))
2201 emitcode ("mov", "%s,%s",
2207 _endLazyDPSEvaluation ();
2208 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2210 size = AOP_SIZE (IC_LEFT (sic));
2218 emitcode("mov", "%s,%s",
2219 fReturn[size], regs390[size].name);
2222 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2228 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2229 OP_SYMBOL (IC_LEFT (ic))->rname :
2230 OP_SYMBOL (IC_LEFT (ic))->name));
2232 /* if we need assign a result value */
2233 if ((IS_ITEMP (IC_RESULT (ic)) &&
2234 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2235 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2236 IS_TRUE_SYMOP (IC_RESULT (ic)))
2238 if (isOperandInFarSpace (IC_RESULT (ic))
2239 && getSize (operandType (IC_RESULT (ic))) <= 2)
2241 int size = getSize (operandType (IC_RESULT (ic)));
2243 /* Special case for 1 or 2 byte return in far space. */
2247 emitcode ("mov", "b,%s", fReturn[1]);
2250 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2251 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2255 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2257 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2262 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2265 assignResultValue (IC_RESULT (ic));
2267 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2271 /* adjust the stack for parameters if
2276 if (ic->parmBytes > 3)
2278 emitcode ("mov", "a,%s", spname);
2279 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2280 emitcode ("mov", "%s,a", spname);
2283 for (i = 0; i < ic->parmBytes; i++)
2284 emitcode ("dec", "%s", spname);
2288 /* if register bank was saved then pop them */
2290 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2292 /* if we hade saved some registers then unsave them */
2293 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2294 unsaveRegisters (ic);
2299 /*-----------------------------------------------------------------*/
2300 /* genPcall - generates a call by pointer statement */
2301 /*-----------------------------------------------------------------*/
2303 genPcall (iCode * ic)
2306 symbol *rlbl = newiTempLabel (NULL);
2308 D (emitcode (";", "genPcall ");
2312 /* if caller saves & we have not saved then */
2316 /* if we are calling a function that is not using
2317 the same register bank then we need to save the
2318 destination registers on the stack */
2319 detype = getSpec (operandType (IC_LEFT (ic)));
2321 IS_ISR (currFunc->etype) &&
2322 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2323 saveRBank (SPEC_BANK (detype), ic, TRUE);
2326 /* push the return address on to the stack */
2327 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2328 emitcode ("push", "acc");
2329 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2330 emitcode ("push", "acc");
2332 if (options.model == MODEL_FLAT24)
2334 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2335 emitcode ("push", "acc");
2338 /* now push the calling address */
2339 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2341 pushSide (IC_LEFT (ic), FPTRSIZE);
2343 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2345 /* if send set is not empty the assign */
2350 for (sic = setFirstItem (_G.sendSet); sic;
2351 sic = setNextItem (_G.sendSet))
2353 int size, offset = 0;
2355 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2356 size = AOP_SIZE (IC_LEFT (sic));
2357 _startLazyDPSEvaluation ();
2360 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2361 FALSE, FALSE, TRUE);
2362 if (strcmp (l, fReturn[offset]))
2364 emitcode ("mov", "%s,%s",
2370 _endLazyDPSEvaluation ();
2371 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2376 emitcode ("ret", "");
2377 emitcode ("", "%05d$:", (rlbl->key + 100));
2380 /* if we need assign a result value */
2381 if ((IS_ITEMP (IC_RESULT (ic)) &&
2382 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2383 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2384 IS_TRUE_SYMOP (IC_RESULT (ic)))
2388 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2391 assignResultValue (IC_RESULT (ic));
2393 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2396 /* adjust the stack for parameters if
2401 if (ic->parmBytes > 3)
2403 emitcode ("mov", "a,%s", spname);
2404 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2405 emitcode ("mov", "%s,a", spname);
2408 for (i = 0; i < ic->parmBytes; i++)
2409 emitcode ("dec", "%s", spname);
2413 /* if register bank was saved then unsave them */
2415 (SPEC_BANK (currFunc->etype) !=
2416 SPEC_BANK (detype)))
2417 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2419 /* if we hade saved some registers then
2422 unsaveRegisters (ic);
2426 /*-----------------------------------------------------------------*/
2427 /* resultRemat - result is rematerializable */
2428 /*-----------------------------------------------------------------*/
2430 resultRemat (iCode * ic)
2432 if (SKIP_IC (ic) || ic->op == IFX)
2435 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2437 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2438 if (sym->remat && !POINTER_SET (ic))
2445 #if defined(__BORLANDC__) || defined(_MSC_VER)
2446 #define STRCASECMP stricmp
2448 #define STRCASECMP strcasecmp
2451 /*-----------------------------------------------------------------*/
2452 /* inExcludeList - return 1 if the string is in exclude Reg list */
2453 /*-----------------------------------------------------------------*/
2455 inExcludeList (char *s)
2459 if (options.excludeRegs[i] &&
2460 STRCASECMP (options.excludeRegs[i], "none") == 0)
2463 for (i = 0; options.excludeRegs[i]; i++)
2465 if (options.excludeRegs[i] &&
2466 STRCASECMP (s, options.excludeRegs[i]) == 0)
2472 /*-----------------------------------------------------------------*/
2473 /* genFunction - generated code for function entry */
2474 /*-----------------------------------------------------------------*/
2476 genFunction (iCode * ic)
2481 D (emitcode (";", "genFunction ");
2485 /* create the function header */
2486 emitcode (";", "-----------------------------------------");
2487 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2488 emitcode (";", "-----------------------------------------");
2490 emitcode ("", "%s:", sym->rname);
2491 fetype = getSpec (operandType (IC_LEFT (ic)));
2493 /* if critical function then turn interrupts off */
2494 if (SPEC_CRTCL (fetype))
2495 emitcode ("clr", "ea");
2497 /* here we need to generate the equates for the
2498 register bank if required */
2499 if (SPEC_BANK (fetype) != rbank)
2503 rbank = SPEC_BANK (fetype);
2504 for (i = 0; i < ds390_nRegs; i++)
2506 if (strcmp (regs390[i].base, "0") == 0)
2507 emitcode ("", "%s = 0x%02x",
2509 8 * rbank + regs390[i].offset);
2511 emitcode ("", "%s = %s + 0x%02x",
2514 8 * rbank + regs390[i].offset);
2518 /* if this is an interrupt service routine then
2519 save acc, b, dpl, dph */
2520 if (IS_ISR (sym->etype))
2523 if (!inExcludeList ("acc"))
2524 emitcode ("push", "acc");
2525 if (!inExcludeList ("b"))
2526 emitcode ("push", "b");
2527 if (!inExcludeList ("dpl"))
2528 emitcode ("push", "dpl");
2529 if (!inExcludeList ("dph"))
2530 emitcode ("push", "dph");
2531 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2533 emitcode ("push", "dpx");
2534 /* Make sure we're using standard DPTR */
2535 emitcode ("push", "dps");
2536 emitcode ("mov", "dps, #0x00");
2537 if (options.stack10bit)
2539 /* This ISR could conceivably use DPTR2. Better save it. */
2540 emitcode ("push", "dpl1");
2541 emitcode ("push", "dph1");
2542 emitcode ("push", "dpx1");
2543 emitcode ("push", DP2_RESULT_REG);
2546 /* if this isr has no bank i.e. is going to
2547 run with bank 0 , then we need to save more
2549 if (!SPEC_BANK (sym->etype))
2552 /* if this function does not call any other
2553 function then we can be economical and
2554 save only those registers that are used */
2559 /* if any registers used */
2562 /* save the registers used */
2563 for (i = 0; i < sym->regsUsed->size; i++)
2565 if (bitVectBitValue (sym->regsUsed, i) ||
2566 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2567 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2574 /* this function has a function call cannot
2575 determines register usage so we will have to push the
2577 saveRBank (0, ic, FALSE);
2583 /* if callee-save to be used for this function
2584 then save the registers being used in this function */
2585 if (sym->calleeSave)
2589 /* if any registers used */
2592 /* save the registers used */
2593 for (i = 0; i < sym->regsUsed->size; i++)
2595 if (bitVectBitValue (sym->regsUsed, i) ||
2596 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2598 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2606 /* set the register bank to the desired value */
2607 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2609 emitcode ("push", "psw");
2610 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2613 if (IS_RENT (sym->etype) || options.stackAuto)
2616 if (options.useXstack)
2618 emitcode ("mov", "r0,%s", spname);
2619 emitcode ("mov", "a,_bp");
2620 emitcode ("movx", "@r0,a");
2621 emitcode ("inc", "%s", spname);
2625 /* set up the stack */
2626 emitcode ("push", "_bp"); /* save the callers stack */
2628 emitcode ("mov", "_bp,%s", spname);
2631 /* adjust the stack for the function */
2637 werror (W_STACK_OVERFLOW, sym->name);
2639 if (i > 3 && sym->recvSize < 4)
2642 emitcode ("mov", "a,sp");
2643 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2644 emitcode ("mov", "sp,a");
2649 emitcode ("inc", "sp");
2655 emitcode ("mov", "a,_spx");
2656 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2657 emitcode ("mov", "_spx,a");
2662 /*-----------------------------------------------------------------*/
2663 /* genEndFunction - generates epilogue for functions */
2664 /*-----------------------------------------------------------------*/
2666 genEndFunction (iCode * ic)
2668 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2670 D (emitcode (";", "genEndFunction ");
2673 if (IS_RENT (sym->etype) || options.stackAuto)
2675 emitcode ("mov", "%s,_bp", spname);
2678 /* if use external stack but some variables were
2679 added to the local stack then decrement the
2681 if (options.useXstack && sym->stack)
2683 emitcode ("mov", "a,sp");
2684 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2685 emitcode ("mov", "sp,a");
2689 if ((IS_RENT (sym->etype) || options.stackAuto))
2691 if (options.useXstack)
2693 emitcode ("mov", "r0,%s", spname);
2694 emitcode ("movx", "a,@r0");
2695 emitcode ("mov", "_bp,a");
2696 emitcode ("dec", "%s", spname);
2700 emitcode ("pop", "_bp");
2704 /* restore the register bank */
2705 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2706 emitcode ("pop", "psw");
2708 if (IS_ISR (sym->etype))
2711 /* now we need to restore the registers */
2712 /* if this isr has no bank i.e. is going to
2713 run with bank 0 , then we need to save more
2715 if (!SPEC_BANK (sym->etype))
2718 /* if this function does not call any other
2719 function then we can be economical and
2720 save only those registers that are used */
2725 /* if any registers used */
2728 /* save the registers used */
2729 for (i = sym->regsUsed->size; i >= 0; i--)
2731 if (bitVectBitValue (sym->regsUsed, i) ||
2732 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2733 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2740 /* this function has a function call cannot
2741 determines register usage so we will have to pop the
2743 unsaveRBank (0, ic, FALSE);
2747 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2749 if (options.stack10bit)
2751 emitcode ("pop", DP2_RESULT_REG);
2752 emitcode ("pop", "dpx1");
2753 emitcode ("pop", "dph1");
2754 emitcode ("pop", "dpl1");
2756 emitcode ("pop", "dps");
2757 emitcode ("pop", "dpx");
2759 if (!inExcludeList ("dph"))
2760 emitcode ("pop", "dph");
2761 if (!inExcludeList ("dpl"))
2762 emitcode ("pop", "dpl");
2763 if (!inExcludeList ("b"))
2764 emitcode ("pop", "b");
2765 if (!inExcludeList ("acc"))
2766 emitcode ("pop", "acc");
2768 if (SPEC_CRTCL (sym->etype))
2769 emitcode ("setb", "ea");
2771 /* if debug then send end of function */
2772 /* if (options.debug && currFunc) { */
2776 emitcode ("", "C$%s$%d$%d$%d ==.",
2777 FileBaseName (ic->filename), currFunc->lastLine,
2778 ic->level, ic->block);
2779 if (IS_STATIC (currFunc->etype))
2780 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2782 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2786 emitcode ("reti", "");
2790 if (SPEC_CRTCL (sym->etype))
2791 emitcode ("setb", "ea");
2793 if (sym->calleeSave)
2797 /* if any registers used */
2800 /* save the registers used */
2801 for (i = sym->regsUsed->size; i >= 0; i--)
2803 if (bitVectBitValue (sym->regsUsed, i) ||
2804 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2805 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2811 /* if debug then send end of function */
2815 emitcode ("", "C$%s$%d$%d$%d ==.",
2816 FileBaseName (ic->filename), currFunc->lastLine,
2817 ic->level, ic->block);
2818 if (IS_STATIC (currFunc->etype))
2819 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2821 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2825 emitcode ("ret", "");
2830 /*-----------------------------------------------------------------*/
2831 /* genRet - generate code for return statement */
2832 /*-----------------------------------------------------------------*/
2836 int size, offset = 0, pushed = 0;
2838 D (emitcode (";", "genRet ");
2841 /* if we have no return value then
2842 just generate the "ret" */
2846 /* we have something to return then
2847 move the return value into place */
2848 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2849 size = AOP_SIZE (IC_LEFT (ic));
2851 _startLazyDPSEvaluation ();
2855 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2857 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2858 FALSE, TRUE, FALSE);
2859 emitcode ("push", "%s", l);
2864 /* Since A is the last element of fReturn,
2865 * is is OK to clobber it in the aopGet.
2867 l = aopGet (AOP (IC_LEFT (ic)), offset,
2868 FALSE, FALSE, TRUE);
2869 if (strcmp (fReturn[offset], l))
2870 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2873 _endLazyDPSEvaluation ();
2880 if (strcmp (fReturn[pushed], "a"))
2881 emitcode ("pop", fReturn[pushed]);
2883 emitcode ("pop", "acc");
2886 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2889 /* generate a jump to the return label
2890 if the next is not the return statement */
2891 if (!(ic->next && ic->next->op == LABEL &&
2892 IC_LABEL (ic->next) == returnLabel))
2894 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2898 /*-----------------------------------------------------------------*/
2899 /* genLabel - generates a label */
2900 /*-----------------------------------------------------------------*/
2902 genLabel (iCode * ic)
2904 /* special case never generate */
2905 if (IC_LABEL (ic) == entryLabel)
2908 D (emitcode (";", "genLabel ");
2911 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2914 /*-----------------------------------------------------------------*/
2915 /* genGoto - generates a ljmp */
2916 /*-----------------------------------------------------------------*/
2918 genGoto (iCode * ic)
2920 D (emitcode (";", "genGoto ");
2922 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2925 /*-----------------------------------------------------------------*/
2926 /* findLabelBackwards: walks back through the iCode chain looking */
2927 /* for the given label. Returns number of iCode instructions */
2928 /* between that label and given ic. */
2929 /* Returns zero if label not found. */
2930 /*-----------------------------------------------------------------*/
2932 findLabelBackwards (iCode * ic, int key)
2941 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2943 /* printf("findLabelBackwards = %d\n", count); */
2951 /*-----------------------------------------------------------------*/
2952 /* genPlusIncr :- does addition with increment if possible */
2953 /*-----------------------------------------------------------------*/
2955 genPlusIncr (iCode * ic)
2957 unsigned int icount;
2958 unsigned int size = getDataSize (IC_RESULT (ic));
2960 /* will try to generate an increment */
2961 /* if the right side is not a literal
2963 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2966 /* if the literal value of the right hand side
2967 is greater than 4 then it is not worth it */
2968 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2971 /* if increment 16 bits in register */
2973 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2974 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2975 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2983 /* If the next instruction is a goto and the goto target
2984 * is <= 5 instructions previous to this, we can generate
2985 * jumps straight to that target.
2987 if (ic->next && ic->next->op == GOTO
2988 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2991 emitcode (";", "tail increment optimized (range %d)", labelRange);
2992 tlbl = IC_LABEL (ic->next);
2997 tlbl = newiTempLabel (NULL);
3000 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3001 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3002 IS_AOP_PREG (IC_RESULT (ic)))
3003 emitcode ("cjne", "%s,#0x00,%05d$"
3004 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3008 emitcode ("clr", "a");
3009 emitcode ("cjne", "a,%s,%05d$"
3010 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3014 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3017 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3018 IS_AOP_PREG (IC_RESULT (ic)))
3019 emitcode ("cjne", "%s,#0x00,%05d$"
3020 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3023 emitcode ("cjne", "a,%s,%05d$"
3024 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3027 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3031 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3032 IS_AOP_PREG (IC_RESULT (ic)))
3033 emitcode ("cjne", "%s,#0x00,%05d$"
3034 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3038 emitcode ("cjne", "a,%s,%05d$"
3039 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3042 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3047 emitcode ("", "%05d$:", tlbl->key + 100);
3052 /* if the sizes are greater than 1 then we cannot */
3053 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3054 AOP_SIZE (IC_LEFT (ic)) > 1)
3057 /* we can if the aops of the left & result match or
3058 if they are in registers and the registers are the
3061 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3062 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3063 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3068 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3069 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3070 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3075 _startLazyDPSEvaluation ();
3078 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3080 _endLazyDPSEvaluation ();
3089 /*-----------------------------------------------------------------*/
3090 /* outBitAcc - output a bit in acc */
3091 /*-----------------------------------------------------------------*/
3093 outBitAcc (operand * result)
3095 symbol *tlbl = newiTempLabel (NULL);
3096 /* if the result is a bit */
3097 if (AOP_TYPE (result) == AOP_CRY)
3099 aopPut (AOP (result), "a", 0);
3103 emitcode ("jz", "%05d$", tlbl->key + 100);
3104 emitcode ("mov", "a,%s", one);
3105 emitcode ("", "%05d$:", tlbl->key + 100);
3110 /*-----------------------------------------------------------------*/
3111 /* genPlusBits - generates code for addition of two bits */
3112 /*-----------------------------------------------------------------*/
3114 genPlusBits (iCode * ic)
3116 D (emitcode (";", "genPlusBits ");
3118 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3120 symbol *lbl = newiTempLabel (NULL);
3121 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3122 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3123 emitcode ("cpl", "c");
3124 emitcode ("", "%05d$:", (lbl->key + 100));
3125 outBitC (IC_RESULT (ic));
3129 emitcode ("clr", "a");
3130 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3131 emitcode ("rlc", "a");
3132 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3133 emitcode ("addc", "a,#0x00");
3134 outAcc (IC_RESULT (ic));
3139 adjustArithmeticResult (iCode * ic)
3141 if (opIsGptr (IC_RESULT (ic)) &&
3142 opIsGptr (IC_LEFT (ic)) &&
3143 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3145 aopPut (AOP (IC_RESULT (ic)),
3146 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3150 if (opIsGptr (IC_RESULT (ic)) &&
3151 opIsGptr (IC_RIGHT (ic)) &&
3152 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3154 aopPut (AOP (IC_RESULT (ic)),
3155 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3159 if (opIsGptr (IC_RESULT (ic)) &&
3160 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3161 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3162 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3163 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3166 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3167 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3171 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3172 // (because all three operands are in far space).
3173 #define AOP_OP_3(ic) \
3174 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3175 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3176 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3177 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3178 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3179 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3181 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3183 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3186 // Macro to aopOp all three operands of an ic. If this cannot be done,
3187 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3188 // will be set TRUE. The caller must then handle the case specially, noting
3189 // that the IC_RESULT operand is not aopOp'd.
3190 #define AOP_OP_3_NOFATAL(ic, rc) \
3191 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3192 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3193 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3194 isOperandInFarSpace(IC_RESULT(ic))) \
3196 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3201 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3202 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3204 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3205 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3207 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3209 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3213 // aopOp the left & right operands of an ic.
3214 #define AOP_OP_2(ic) \
3215 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3216 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3218 // convienience macro.
3219 #define AOP_SET_LOCALS(ic) \
3220 left = IC_LEFT(ic); \
3221 right = IC_RIGHT(ic); \
3222 result = IC_RESULT(ic);
3225 // Given an integer value of pushedSize bytes on the stack,
3226 // adjust it to be resultSize bytes, either by discarding
3227 // the most significant bytes or by zero-padding.
3229 // On exit from this macro, pushedSize will have been adjusted to
3230 // equal resultSize, and ACC may be trashed.
3231 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3232 /* If the pushed data is bigger than the result, \
3233 * simply discard unused bytes. Icky, but works. \
3235 while (pushedSize > resultSize) \
3237 D (emitcode (";", "discarding unused result byte."););\
3238 emitcode ("pop", "acc"); \
3241 if (pushedSize < resultSize) \
3243 emitcode ("clr", "a"); \
3244 /* Conversly, we haven't pushed enough here. \
3245 * just zero-pad, and all is well. \
3247 while (pushedSize < resultSize) \
3249 emitcode("push", "acc"); \
3253 assert(pushedSize == resultSize);
3255 /*-----------------------------------------------------------------*/
3256 /* genPlus - generates code for addition */
3257 /*-----------------------------------------------------------------*/
3259 genPlus (iCode * ic)
3261 int size, offset = 0;
3262 bool pushResult = FALSE;
3265 D (emitcode (";", "genPlus "););
3267 /* special cases :- */
3269 AOP_OP_3_NOFATAL (ic, pushResult);
3272 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3277 /* if literal, literal on the right or
3278 if left requires ACC or right is already
3280 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3281 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3282 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3284 operand *t = IC_RIGHT (ic);
3285 IC_RIGHT (ic) = IC_LEFT (ic);
3287 emitcode (";", "Swapped plus args.");
3290 /* if both left & right are in bit
3292 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3293 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3299 /* if left in bit space & right literal */
3300 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3301 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3303 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3304 /* if result in bit space */
3305 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3307 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3308 emitcode ("cpl", "c");
3309 outBitC (IC_RESULT (ic));
3313 size = getDataSize (IC_RESULT (ic));
3314 _startLazyDPSEvaluation ();
3317 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3318 emitcode ("addc", "a,#00");
3319 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3321 _endLazyDPSEvaluation ();
3326 /* if I can do an increment instead
3327 of add then GOOD for ME */
3328 if (genPlusIncr (ic) == TRUE)
3330 emitcode (";", "did genPlusIncr");
3335 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3337 _startLazyDPSEvaluation ();
3340 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3342 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3344 emitcode ("add", "a,%s",
3345 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3347 emitcode ("addc", "a,%s",
3348 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3352 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3354 /* right is going to use ACC or we would have taken the
3357 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3358 D(emitcode(";", "+ AOP_ACC special case."););
3359 emitcode("xch", "a, %s", DP2_RESULT_REG);
3361 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3364 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3366 emitcode("add", "a, %s", DP2_RESULT_REG);
3370 emitcode ("add", "a,%s",
3371 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3376 emitcode ("addc", "a,%s",
3377 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3382 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3386 emitcode ("push", "acc");
3390 _endLazyDPSEvaluation ();
3394 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3396 size = getDataSize (IC_LEFT (ic));
3397 rSize = getDataSize (IC_RESULT (ic));
3399 ADJUST_PUSHED_RESULT(size, rSize);
3401 _startLazyDPSEvaluation ();
3404 emitcode ("pop", "acc");
3405 aopPut (AOP (IC_RESULT (ic)), "a", size);
3407 _endLazyDPSEvaluation ();
3410 adjustArithmeticResult (ic);
3413 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3414 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3415 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3418 /*-----------------------------------------------------------------*/
3419 /* genMinusDec :- does subtraction with deccrement if possible */
3420 /*-----------------------------------------------------------------*/
3422 genMinusDec (iCode * ic)
3424 unsigned int icount;
3425 unsigned int size = getDataSize (IC_RESULT (ic));
3427 /* will try to generate an increment */
3428 /* if the right side is not a literal
3430 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3433 /* if the literal value of the right hand side
3434 is greater than 4 then it is not worth it */
3435 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3438 /* if decrement 16 bits in register */
3439 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3440 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3441 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3449 /* If the next instruction is a goto and the goto target
3450 * is <= 5 instructions previous to this, we can generate
3451 * jumps straight to that target.
3453 if (ic->next && ic->next->op == GOTO
3454 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3457 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3458 tlbl = IC_LABEL (ic->next);
3463 tlbl = newiTempLabel (NULL);
3467 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3468 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3469 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3470 IS_AOP_PREG (IC_RESULT (ic)))
3471 emitcode ("cjne", "%s,#0xff,%05d$"
3472 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3476 emitcode ("mov", "a,#0xff");
3477 emitcode ("cjne", "a,%s,%05d$"
3478 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3481 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3484 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3485 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3486 IS_AOP_PREG (IC_RESULT (ic)))
3487 emitcode ("cjne", "%s,#0xff,%05d$"
3488 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3492 emitcode ("cjne", "a,%s,%05d$"
3493 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3496 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3500 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3501 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3502 IS_AOP_PREG (IC_RESULT (ic)))
3503 emitcode ("cjne", "%s,#0xff,%05d$"
3504 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3508 emitcode ("cjne", "a,%s,%05d$"
3509 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3512 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3516 emitcode ("", "%05d$:", tlbl->key + 100);
3521 /* if the sizes are greater than 1 then we cannot */
3522 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3523 AOP_SIZE (IC_LEFT (ic)) > 1)
3526 /* we can if the aops of the left & result match or
3527 if they are in registers and the registers are the
3530 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3531 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3532 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3535 _startLazyDPSEvaluation ();
3538 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3540 _endLazyDPSEvaluation ();
3548 /*-----------------------------------------------------------------*/
3549 /* addSign - complete with sign */
3550 /*-----------------------------------------------------------------*/
3552 addSign (operand * result, int offset, int sign)
3554 int size = (getDataSize (result) - offset);
3557 _startLazyDPSEvaluation();
3560 emitcode ("rlc", "a");
3561 emitcode ("subb", "a,acc");
3564 aopPut (AOP (result), "a", offset++);
3571 aopPut (AOP (result), zero, offset++);
3574 _endLazyDPSEvaluation();
3578 /*-----------------------------------------------------------------*/
3579 /* genMinusBits - generates code for subtraction of two bits */
3580 /*-----------------------------------------------------------------*/
3582 genMinusBits (iCode * ic)
3584 symbol *lbl = newiTempLabel (NULL);
3586 D (emitcode (";", "genMinusBits "););
3588 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3590 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3591 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3592 emitcode ("cpl", "c");
3593 emitcode ("", "%05d$:", (lbl->key + 100));
3594 outBitC (IC_RESULT (ic));
3598 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3599 emitcode ("subb", "a,acc");
3600 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3601 emitcode ("inc", "a");
3602 emitcode ("", "%05d$:", (lbl->key + 100));
3603 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3604 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3608 /*-----------------------------------------------------------------*/
3609 /* genMinus - generates code for subtraction */
3610 /*-----------------------------------------------------------------*/
3612 genMinus (iCode * ic)
3614 int size, offset = 0;
3616 unsigned long lit = 0L;
3617 bool pushResult = FALSE;
3619 D (emitcode (";", "genMinus "););
3621 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3622 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3623 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3624 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3630 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3632 /* special cases :- */
3633 /* if both left & right are in bit space */
3634 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3635 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3641 /* if I can do an decrement instead
3642 of subtract then GOOD for ME */
3643 if (genMinusDec (ic) == TRUE)
3648 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3650 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3656 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3661 /* if literal, add a,#-lit, else normal subb */
3662 _startLazyDPSEvaluation ();
3665 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3666 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3667 emitcode ("subb", "a,%s",
3668 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3671 /* first add without previous c */
3673 emitcode ("add", "a,#0x%02x",
3674 (unsigned int) (lit & 0x0FFL));
3676 emitcode ("addc", "a,#0x%02x",
3677 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3682 emitcode ("push", "acc");
3686 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3690 _endLazyDPSEvaluation ();
3694 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3696 size = getDataSize (IC_LEFT (ic));
3697 rSize = getDataSize (IC_RESULT (ic));
3699 ADJUST_PUSHED_RESULT(size, rSize);
3701 _startLazyDPSEvaluation ();
3704 emitcode ("pop", "acc");
3705 aopPut (AOP (IC_RESULT (ic)), "a", size);
3707 _endLazyDPSEvaluation ();
3710 adjustArithmeticResult (ic);
3713 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3714 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3715 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3719 /*-----------------------------------------------------------------*/
3720 /* genMultbits :- multiplication of bits */
3721 /*-----------------------------------------------------------------*/
3723 genMultbits (operand * left,
3727 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3728 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3733 /*-----------------------------------------------------------------*/
3734 /* genMultOneByte : 8*8=8/16 bit multiplication */
3735 /*-----------------------------------------------------------------*/
3737 genMultOneByte (operand * left,
3741 sym_link *opetype = operandType (result);
3743 int size=AOP_SIZE(result);
3745 if (size<1 || size>2) {
3746 // this should never happen
3747 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3748 AOP_SIZE(result), __FILE__, lineno);
3752 /* (if two literals: the value is computed before) */
3753 /* if one literal, literal on the right */
3754 if (AOP_TYPE (left) == AOP_LIT)
3759 emitcode (";", "swapped left and right");
3762 if (SPEC_USIGN(opetype)
3763 // ignore the sign of left and right, what else can we do?
3764 || (SPEC_USIGN(operandType(left)) &&
3765 SPEC_USIGN(operandType(right)))) {
3766 // just an unsigned 8*8=8/16 multiply
3767 //emitcode (";","unsigned");
3768 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3769 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3770 emitcode ("mul", "ab");
3771 aopPut (AOP (result), "a", 0);
3773 aopPut (AOP (result), "b", 1);
3778 // we have to do a signed multiply
3780 emitcode (";", "signed");
3781 emitcode ("clr", "F0"); // reset sign flag
3782 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3783 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3785 lbl=newiTempLabel(NULL);
3786 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3787 // left side is negative, 8-bit two's complement, this fails for -128
3788 emitcode ("setb", "F0"); // set sign flag
3789 emitcode ("cpl", "a");
3790 emitcode ("inc", "a");
3792 emitcode ("", "%05d$:", lbl->key+100);
3793 emitcode ("xch", "a,b");
3796 if (AOP_TYPE(right)==AOP_LIT) {
3797 /* AND literal negative */
3798 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3799 // two's complement for literal<0
3800 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3801 emitcode ("cpl", "a");
3802 emitcode ("inc", "a");
3805 lbl=newiTempLabel(NULL);
3806 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3807 // right side is negative, 8-bit two's complement
3808 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3809 emitcode ("cpl", "a");
3810 emitcode ("inc", "a");
3811 emitcode ("", "%05d$:", lbl->key+100);
3813 emitcode ("mul", "ab");
3815 lbl=newiTempLabel(NULL);
3816 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3817 // only ONE op was negative, we have to do a 8/16-bit two's complement
3818 emitcode ("cpl", "a"); // lsb
3820 emitcode ("inc", "a");
3822 emitcode ("add", "a,#1");
3823 emitcode ("xch", "a,b");
3824 emitcode ("cpl", "a"); // msb
3825 emitcode ("addc", "a,#0");
3826 emitcode ("xch", "a,b");
3829 emitcode ("", "%05d$:", lbl->key+100);
3830 aopPut (AOP (result), "a", 0);
3832 aopPut (AOP (result), "b", 1);
3836 /*-----------------------------------------------------------------*/
3837 /* genMult - generates code for multiplication */
3838 /*-----------------------------------------------------------------*/
3840 genMult (iCode * ic)
3842 operand *left = IC_LEFT (ic);
3843 operand *right = IC_RIGHT (ic);
3844 operand *result = IC_RESULT (ic);
3846 D (emitcode (";", "genMult "););
3848 /* assign the amsops */
3851 /* special cases first */
3853 if (AOP_TYPE (left) == AOP_CRY &&
3854 AOP_TYPE (right) == AOP_CRY)
3856 genMultbits (left, right, result);
3860 /* if both are of size == 1 */
3861 if (AOP_SIZE (left) == 1 &&
3862 AOP_SIZE (right) == 1)
3864 genMultOneByte (left, right, result);
3868 /* should have been converted to function call */
3872 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3873 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3874 freeAsmop (result, NULL, ic, TRUE);
3877 /*-----------------------------------------------------------------*/
3878 /* genDivbits :- division of bits */
3879 /*-----------------------------------------------------------------*/
3881 genDivbits (operand * left,
3888 /* the result must be bit */
3889 LOAD_AB_FOR_DIV (left, right, l);
3890 emitcode ("div", "ab");
3891 emitcode ("rrc", "a");
3892 aopPut (AOP (result), "c", 0);
3895 /*-----------------------------------------------------------------*/
3896 /* genDivOneByte : 8 bit division */
3897 /*-----------------------------------------------------------------*/
3899 genDivOneByte (operand * left,
3903 sym_link *opetype = operandType (result);
3908 size = AOP_SIZE (result) - 1;
3910 /* signed or unsigned */
3911 if (SPEC_USIGN (opetype))
3913 /* unsigned is easy */
3914 LOAD_AB_FOR_DIV (left, right, l);
3915 emitcode ("div", "ab");
3916 aopPut (AOP (result), "a", 0);
3918 aopPut (AOP (result), zero, offset++);
3922 /* signed is a little bit more difficult */
3924 /* save the signs of the operands */
3925 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3927 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3928 emitcode ("push", "acc"); /* save it on the stack */
3930 /* now sign adjust for both left & right */
3931 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3933 lbl = newiTempLabel (NULL);
3934 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3935 emitcode ("cpl", "a");
3936 emitcode ("inc", "a");
3937 emitcode ("", "%05d$:", (lbl->key + 100));
3938 emitcode ("mov", "b,a");
3940 /* sign adjust left side */
3941 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3944 lbl = newiTempLabel (NULL);
3945 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3946 emitcode ("cpl", "a");
3947 emitcode ("inc", "a");
3948 emitcode ("", "%05d$:", (lbl->key + 100));
3950 /* now the division */
3951 emitcode ("nop", "; workaround for DS80C390 div bug.");
3952 emitcode ("div", "ab");
3953 /* we are interested in the lower order
3955 emitcode ("mov", "b,a");
3956 lbl = newiTempLabel (NULL);
3957 emitcode ("pop", "acc");
3958 /* if there was an over flow we don't
3959 adjust the sign of the result */
3960 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3961 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3963 emitcode ("clr", "a");
3964 emitcode ("subb", "a,b");
3965 emitcode ("mov", "b,a");
3966 emitcode ("", "%05d$:", (lbl->key + 100));
3968 /* now we are done */
3969 aopPut (AOP (result), "b", 0);
3972 emitcode ("mov", "c,b.7");
3973 emitcode ("subb", "a,acc");
3976 aopPut (AOP (result), "a", offset++);
3980 /*-----------------------------------------------------------------*/
3981 /* genDiv - generates code for division */
3982 /*-----------------------------------------------------------------*/
3986 operand *left = IC_LEFT (ic);
3987 operand *right = IC_RIGHT (ic);
3988 operand *result = IC_RESULT (ic);
3990 D (emitcode (";", "genDiv ");
3993 /* assign the amsops */
3996 /* special cases first */
3998 if (AOP_TYPE (left) == AOP_CRY &&
3999 AOP_TYPE (right) == AOP_CRY)
4001 genDivbits (left, right, result);
4005 /* if both are of size == 1 */
4006 if (AOP_SIZE (left) == 1 &&
4007 AOP_SIZE (right) == 1)
4009 genDivOneByte (left, right, result);
4013 /* should have been converted to function call */
4016 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4017 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4018 freeAsmop (result, NULL, ic, TRUE);
4021 /*-----------------------------------------------------------------*/
4022 /* genModbits :- modulus of bits */
4023 /*-----------------------------------------------------------------*/
4025 genModbits (operand * left,
4032 /* the result must be bit */
4033 LOAD_AB_FOR_DIV (left, right, l);
4034 emitcode ("div", "ab");
4035 emitcode ("mov", "a,b");
4036 emitcode ("rrc", "a");
4037 aopPut (AOP (result), "c", 0);
4040 /*-----------------------------------------------------------------*/
4041 /* genModOneByte : 8 bit modulus */
4042 /*-----------------------------------------------------------------*/
4044 genModOneByte (operand * left,
4048 sym_link *opetype = operandType (result);
4052 /* signed or unsigned */
4053 if (SPEC_USIGN (opetype))
4055 /* unsigned is easy */
4056 LOAD_AB_FOR_DIV (left, right, l);
4057 emitcode ("div", "ab");
4058 aopPut (AOP (result), "b", 0);
4062 /* signed is a little bit more difficult */
4064 /* save the signs of the operands */
4065 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4068 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4069 emitcode ("push", "acc"); /* save it on the stack */
4071 /* now sign adjust for both left & right */
4072 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4075 lbl = newiTempLabel (NULL);
4076 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4077 emitcode ("cpl", "a");
4078 emitcode ("inc", "a");
4079 emitcode ("", "%05d$:", (lbl->key + 100));
4080 emitcode ("mov", "b,a");
4082 /* sign adjust left side */
4083 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4086 lbl = newiTempLabel (NULL);
4087 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4088 emitcode ("cpl", "a");
4089 emitcode ("inc", "a");
4090 emitcode ("", "%05d$:", (lbl->key + 100));
4092 /* now the multiplication */
4093 emitcode ("nop", "; workaround for DS80C390 div bug.");
4094 emitcode ("div", "ab");
4095 /* we are interested in the lower order
4097 lbl = newiTempLabel (NULL);
4098 emitcode ("pop", "acc");
4099 /* if there was an over flow we don't
4100 adjust the sign of the result */
4101 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4102 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4104 emitcode ("clr", "a");
4105 emitcode ("subb", "a,b");
4106 emitcode ("mov", "b,a");
4107 emitcode ("", "%05d$:", (lbl->key + 100));
4109 /* now we are done */
4110 aopPut (AOP (result), "b", 0);
4114 /*-----------------------------------------------------------------*/
4115 /* genMod - generates code for division */
4116 /*-----------------------------------------------------------------*/
4120 operand *left = IC_LEFT (ic);
4121 operand *right = IC_RIGHT (ic);
4122 operand *result = IC_RESULT (ic);
4124 D (emitcode (";", "genMod ");
4127 /* assign the amsops */
4130 /* special cases first */
4132 if (AOP_TYPE (left) == AOP_CRY &&
4133 AOP_TYPE (right) == AOP_CRY)
4135 genModbits (left, right, result);
4139 /* if both are of size == 1 */
4140 if (AOP_SIZE (left) == 1 &&
4141 AOP_SIZE (right) == 1)
4143 genModOneByte (left, right, result);
4147 /* should have been converted to function call */
4151 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4152 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4153 freeAsmop (result, NULL, ic, TRUE);
4156 /*-----------------------------------------------------------------*/
4157 /* genIfxJump :- will create a jump depending on the ifx */
4158 /*-----------------------------------------------------------------*/
4160 genIfxJump (iCode * ic, char *jval)
4163 symbol *tlbl = newiTempLabel (NULL);
4166 D (emitcode (";", "genIfxJump ");
4169 /* if true label then we jump if condition
4173 jlbl = IC_TRUE (ic);
4174 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4175 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4179 /* false label is present */
4180 jlbl = IC_FALSE (ic);
4181 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4182 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4184 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4185 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4187 emitcode (inst, "%05d$", tlbl->key + 100);
4188 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4189 emitcode ("", "%05d$:", tlbl->key + 100);
4191 /* mark the icode as generated */
4195 /*-----------------------------------------------------------------*/
4196 /* genCmp :- greater or less than comparison */
4197 /*-----------------------------------------------------------------*/
4199 genCmp (operand * left, operand * right,
4200 iCode * ic, iCode * ifx, int sign)
4202 int size, offset = 0;
4203 unsigned long lit = 0L;
4206 D (emitcode (";", "genCmp");
4209 result = IC_RESULT (ic);
4211 /* if left & right are bit variables */
4212 if (AOP_TYPE (left) == AOP_CRY &&
4213 AOP_TYPE (right) == AOP_CRY)
4215 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4216 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4220 /* subtract right from left if at the
4221 end the carry flag is set then we know that
4222 left is greater than right */
4223 size = max (AOP_SIZE (left), AOP_SIZE (right));
4225 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4226 if ((size == 1) && !sign &&
4227 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4229 symbol *lbl = newiTempLabel (NULL);
4230 emitcode ("cjne", "%s,%s,%05d$",
4231 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4232 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4234 emitcode ("", "%05d$:", lbl->key + 100);
4238 if (AOP_TYPE (right) == AOP_LIT)
4240 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4241 /* optimize if(x < 0) or if(x >= 0) */
4250 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4252 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4253 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4255 aopOp (result, ic, FALSE, FALSE);
4257 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4259 freeAsmop (result, NULL, ic, TRUE);
4260 genIfxJump (ifx, "acc.7");
4265 emitcode ("rlc", "a");
4267 goto release_freedLR;
4275 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4276 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4277 emitcode (";", "genCmp #2");
4278 if (sign && (size == 0))
4280 emitcode (";", "genCmp #3");
4281 emitcode ("xrl", "a,#0x80");
4282 if (AOP_TYPE (right) == AOP_LIT)
4284 unsigned long lit = (unsigned long)
4285 floatFromVal (AOP (right)->aopu.aop_lit);
4286 emitcode (";", "genCmp #3.1");
4287 emitcode ("subb", "a,#0x%02x",
4288 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4292 emitcode (";", "genCmp #3.2");
4293 if (AOP_NEEDSACC (right))
4295 emitcode ("push", "acc");
4297 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4298 FALSE, FALSE, FALSE));
4299 emitcode ("xrl", "b,#0x80");
4300 if (AOP_NEEDSACC (right))
4302 emitcode ("pop", "acc");
4304 emitcode ("subb", "a,b");
4311 emitcode (";", "genCmp #4");
4312 if (AOP_NEEDSACC (right))
4315 emitcode (";", "genCmp #4.1");
4316 emitcode ("xch", "a, b");
4317 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4318 emitcode ("xch", "a, b");
4323 emitcode (";", "genCmp #4.2");
4324 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4327 emitcode ("subb", "a,%s", s);
4334 /* Don't need the left & right operands any more; do need the result. */
4335 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4336 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4338 aopOp (result, ic, FALSE, FALSE);
4342 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4348 /* if the result is used in the next
4349 ifx conditional branch then generate
4350 code a little differently */
4353 genIfxJump (ifx, "c");
4359 /* leave the result in acc */
4361 freeAsmop (result, NULL, ic, TRUE);
4364 /*-----------------------------------------------------------------*/
4365 /* genCmpGt :- greater than comparison */
4366 /*-----------------------------------------------------------------*/
4368 genCmpGt (iCode * ic, iCode * ifx)
4370 operand *left, *right;
4371 sym_link *letype, *retype;
4374 D (emitcode (";", "genCmpGt ");
4377 left = IC_LEFT (ic);
4378 right = IC_RIGHT (ic);
4380 letype = getSpec (operandType (left));
4381 retype = getSpec (operandType (right));
4382 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4384 /* assign the left & right amsops */
4387 genCmp (right, left, ic, ifx, sign);
4390 /*-----------------------------------------------------------------*/
4391 /* genCmpLt - less than comparisons */
4392 /*-----------------------------------------------------------------*/
4394 genCmpLt (iCode * ic, iCode * ifx)
4396 operand *left, *right;
4397 sym_link *letype, *retype;
4400 D (emitcode (";", "genCmpLt "););
4402 left = IC_LEFT (ic);
4403 right = IC_RIGHT (ic);
4405 letype = getSpec (operandType (left));
4406 retype = getSpec (operandType (right));
4407 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4409 /* assign the left & right amsops */
4412 genCmp (left, right, ic, ifx, sign);
4415 /*-----------------------------------------------------------------*/
4416 /* gencjneshort - compare and jump if not equal */
4417 /*-----------------------------------------------------------------*/
4419 gencjneshort (operand * left, operand * right, symbol * lbl)
4421 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4423 unsigned long lit = 0L;
4425 D (emitcode (";", "gencjneshort");
4428 /* if the left side is a literal or
4429 if the right is in a pointer register and left
4431 if ((AOP_TYPE (left) == AOP_LIT) ||
4432 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4439 if (AOP_TYPE (right) == AOP_LIT)
4440 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4442 if (opIsGptr (left) || opIsGptr (right))
4444 /* We are comparing a generic pointer to something.
4445 * Exclude the generic type byte from the comparison.
4448 D (emitcode (";", "cjneshort: generic ptr special case.");
4453 /* if the right side is a literal then anything goes */
4454 if (AOP_TYPE (right) == AOP_LIT &&
4455 AOP_TYPE (left) != AOP_DIR)
4459 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4461 emitcode ("cjne", "a,%s,%05d$",
4462 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4468 /* if the right side is in a register or in direct space or
4469 if the left is a pointer register & right is not */
4470 else if (AOP_TYPE (right) == AOP_REG ||
4471 AOP_TYPE (right) == AOP_DIR ||
4472 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4473 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4477 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4478 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4479 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4480 emitcode ("jnz", "%05d$", lbl->key + 100);
4482 emitcode ("cjne", "a,%s,%05d$",
4483 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4490 /* right is a pointer reg need both a & b */
4493 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4494 if (strcmp (l, "b"))
4495 emitcode ("mov", "b,%s", l);
4496 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4497 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4503 /*-----------------------------------------------------------------*/
4504 /* gencjne - compare and jump if not equal */
4505 /*-----------------------------------------------------------------*/
4507 gencjne (operand * left, operand * right, symbol * lbl)
4509 symbol *tlbl = newiTempLabel (NULL);
4511 D (emitcode (";", "gencjne");
4514 gencjneshort (left, right, lbl);
4516 emitcode ("mov", "a,%s", one);
4517 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4518 emitcode ("", "%05d$:", lbl->key + 100);
4519 emitcode ("clr", "a");
4520 emitcode ("", "%05d$:", tlbl->key + 100);
4523 /*-----------------------------------------------------------------*/
4524 /* genCmpEq - generates code for equal to */
4525 /*-----------------------------------------------------------------*/
4527 genCmpEq (iCode * ic, iCode * ifx)
4529 operand *left, *right, *result;
4531 D (emitcode (";", "genCmpEq ");
4535 AOP_SET_LOCALS (ic);
4537 /* if literal, literal on the right or
4538 if the right is in a pointer register and left
4540 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4541 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4543 operand *t = IC_RIGHT (ic);
4544 IC_RIGHT (ic) = IC_LEFT (ic);
4548 if (ifx && /* !AOP_SIZE(result) */
4549 OP_SYMBOL (result) &&
4550 OP_SYMBOL (result)->regType == REG_CND)
4553 /* if they are both bit variables */
4554 if (AOP_TYPE (left) == AOP_CRY &&
4555 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4557 if (AOP_TYPE (right) == AOP_LIT)
4559 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4562 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4563 emitcode ("cpl", "c");
4567 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4571 emitcode ("clr", "c");
4573 /* AOP_TYPE(right) == AOP_CRY */
4577 symbol *lbl = newiTempLabel (NULL);
4578 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4579 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4580 emitcode ("cpl", "c");
4581 emitcode ("", "%05d$:", (lbl->key + 100));
4583 /* if true label then we jump if condition
4585 tlbl = newiTempLabel (NULL);
4588 emitcode ("jnc", "%05d$", tlbl->key + 100);
4589 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4593 emitcode ("jc", "%05d$", tlbl->key + 100);
4594 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4596 emitcode ("", "%05d$:", tlbl->key + 100);
4600 tlbl = newiTempLabel (NULL);
4601 gencjneshort (left, right, tlbl);
4604 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4605 emitcode ("", "%05d$:", tlbl->key + 100);
4609 symbol *lbl = newiTempLabel (NULL);
4610 emitcode ("sjmp", "%05d$", lbl->key + 100);
4611 emitcode ("", "%05d$:", tlbl->key + 100);
4612 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4613 emitcode ("", "%05d$:", lbl->key + 100);
4616 /* mark the icode as generated */
4619 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4624 /* if they are both bit variables */
4625 if (AOP_TYPE (left) == AOP_CRY &&
4626 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4628 if (AOP_TYPE (right) == AOP_LIT)
4630 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4633 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4634 emitcode ("cpl", "c");
4638 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4642 emitcode ("clr", "c");
4644 /* AOP_TYPE(right) == AOP_CRY */
4648 symbol *lbl = newiTempLabel (NULL);
4649 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4650 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4651 emitcode ("cpl", "c");
4652 emitcode ("", "%05d$:", (lbl->key + 100));
4655 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4656 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4658 aopOp (result, ic, TRUE, FALSE);
4661 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4668 genIfxJump (ifx, "c");
4671 /* if the result is used in an arithmetic operation
4672 then put the result in place */
4677 gencjne (left, right, newiTempLabel (NULL));
4679 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4680 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4682 aopOp (result, ic, TRUE, FALSE);
4684 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4686 aopPut (AOP (result), "a", 0);
4691 genIfxJump (ifx, "a");
4694 /* if the result is used in an arithmetic operation
4695 then put the result in place */
4696 if (AOP_TYPE (result) != AOP_CRY)
4698 /* leave the result in acc */
4702 freeAsmop (result, NULL, ic, TRUE);
4705 /*-----------------------------------------------------------------*/
4706 /* ifxForOp - returns the icode containing the ifx for operand */
4707 /*-----------------------------------------------------------------*/
4709 ifxForOp (operand * op, iCode * ic)
4711 /* if true symbol then needs to be assigned */
4712 if (IS_TRUE_SYMOP (op))
4715 /* if this has register type condition and
4716 the next instruction is ifx with the same operand
4717 and live to of the operand is upto the ifx only then */
4719 ic->next->op == IFX &&
4720 IC_COND (ic->next)->key == op->key &&
4721 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4726 /*-----------------------------------------------------------------*/
4727 /* genAndOp - for && operation */
4728 /*-----------------------------------------------------------------*/
4730 genAndOp (iCode * ic)
4732 operand *left, *right, *result;
4735 D (emitcode (";", "genAndOp "););
4737 /* note here that && operations that are in an
4738 if statement are taken away by backPatchLabels
4739 only those used in arthmetic operations remain */
4741 AOP_SET_LOCALS (ic);
4743 /* if both are bit variables */
4744 if (AOP_TYPE (left) == AOP_CRY &&
4745 AOP_TYPE (right) == AOP_CRY)
4747 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4748 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4749 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4752 aopOp (result,ic,FALSE, FALSE);
4757 tlbl = newiTempLabel (NULL);
4759 emitcode ("jz", "%05d$", tlbl->key + 100);
4761 emitcode ("", "%05d$:", tlbl->key + 100);
4762 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4763 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4765 aopOp (result,ic,FALSE, FALSE);
4768 freeAsmop (result, NULL, ic, TRUE);
4772 /*-----------------------------------------------------------------*/
4773 /* genOrOp - for || operation */
4774 /*-----------------------------------------------------------------*/
4776 genOrOp (iCode * ic)
4778 operand *left, *right, *result;
4781 D (emitcode (";", "genOrOp "););
4783 /* note here that || operations that are in an
4784 if statement are taken away by backPatchLabels
4785 only those used in arthmetic operations remain */
4787 AOP_SET_LOCALS (ic);
4789 /* if both are bit variables */
4790 if (AOP_TYPE (left) == AOP_CRY &&
4791 AOP_TYPE (right) == AOP_CRY)
4793 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4794 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4795 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4796 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4798 aopOp (result,ic,FALSE, FALSE);
4804 tlbl = newiTempLabel (NULL);
4806 emitcode ("jnz", "%05d$", tlbl->key + 100);
4808 emitcode ("", "%05d$:", tlbl->key + 100);
4809 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4810 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4812 aopOp (result,ic,FALSE, FALSE);
4817 freeAsmop (result, NULL, ic, TRUE);
4820 /*-----------------------------------------------------------------*/
4821 /* isLiteralBit - test if lit == 2^n */
4822 /*-----------------------------------------------------------------*/
4824 isLiteralBit (unsigned long lit)
4826 unsigned long pw[32] =
4827 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4828 0x100L, 0x200L, 0x400L, 0x800L,
4829 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4830 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4831 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4832 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4833 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4836 for (idx = 0; idx < 32; idx++)
4842 /*-----------------------------------------------------------------*/
4843 /* continueIfTrue - */
4844 /*-----------------------------------------------------------------*/
4846 continueIfTrue (iCode * ic)
4849 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4853 /*-----------------------------------------------------------------*/
4855 /*-----------------------------------------------------------------*/
4857 jumpIfTrue (iCode * ic)
4860 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4864 /*-----------------------------------------------------------------*/
4865 /* jmpTrueOrFalse - */
4866 /*-----------------------------------------------------------------*/
4868 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4870 // ugly but optimized by peephole
4873 symbol *nlbl = newiTempLabel (NULL);
4874 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4875 emitcode ("", "%05d$:", tlbl->key + 100);
4876 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4877 emitcode ("", "%05d$:", nlbl->key + 100);
4881 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4882 emitcode ("", "%05d$:", tlbl->key + 100);
4887 // Generate code to perform a bit-wise logic operation
4888 // on two operands in far space (assumed to already have been
4889 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4890 // in far space. This requires pushing the result on the stack
4891 // then popping it into the result.
4893 genFarFarLogicOp(iCode *ic, char *logicOp)
4895 int size, resultSize, compSize;
4898 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4899 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4900 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4902 _startLazyDPSEvaluation();
4903 for (size = compSize; (size--); offset++)
4905 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4906 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4907 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4909 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4910 emitcode ("push", "acc");
4912 _endLazyDPSEvaluation();
4914 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4915 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4916 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4918 resultSize = AOP_SIZE(IC_RESULT(ic));
4920 ADJUST_PUSHED_RESULT(compSize, resultSize);
4922 _startLazyDPSEvaluation();
4925 emitcode ("pop", "acc");
4926 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4928 _endLazyDPSEvaluation();
4929 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4933 /*-----------------------------------------------------------------*/
4934 /* genAnd - code for and */
4935 /*-----------------------------------------------------------------*/
4937 genAnd (iCode * ic, iCode * ifx)
4939 operand *left, *right, *result;
4940 int size, offset = 0;
4941 unsigned long lit = 0L;
4946 D (emitcode (";", "genAnd "););
4948 AOP_OP_3_NOFATAL (ic, pushResult);
4949 AOP_SET_LOCALS (ic);
4953 genFarFarLogicOp(ic, "anl");
4958 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4960 AOP_TYPE (left), AOP_TYPE (right));
4961 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4963 AOP_SIZE (left), AOP_SIZE (right));
4966 /* if left is a literal & right is not then exchange them */
4967 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4968 AOP_NEEDSACC (left))
4970 operand *tmp = right;
4975 /* if result = right then exchange them */
4976 if (sameRegs (AOP (result), AOP (right)))
4978 operand *tmp = right;
4983 /* if right is bit then exchange them */
4984 if (AOP_TYPE (right) == AOP_CRY &&
4985 AOP_TYPE (left) != AOP_CRY)
4987 operand *tmp = right;
4991 if (AOP_TYPE (right) == AOP_LIT)
4992 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4994 size = AOP_SIZE (result);
4997 // result = bit & yy;
4998 if (AOP_TYPE (left) == AOP_CRY)
5000 // c = bit & literal;
5001 if (AOP_TYPE (right) == AOP_LIT)
5005 if (size && sameRegs (AOP (result), AOP (left)))
5008 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5013 if (size && (AOP_TYPE (result) == AOP_CRY))
5015 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5018 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5023 emitcode ("clr", "c");
5028 if (AOP_TYPE (right) == AOP_CRY)
5031 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5032 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5037 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5039 emitcode ("rrc", "a");
5040 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5048 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5049 genIfxJump (ifx, "c");
5053 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5054 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5055 if ((AOP_TYPE (right) == AOP_LIT) &&
5056 (AOP_TYPE (result) == AOP_CRY) &&
5057 (AOP_TYPE (left) != AOP_CRY))
5059 int posbit = isLiteralBit (lit);
5064 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5067 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5073 sprintf (buffer, "acc.%d", posbit & 0x07);
5074 genIfxJump (ifx, buffer);
5081 symbol *tlbl = newiTempLabel (NULL);
5082 int sizel = AOP_SIZE (left);
5084 emitcode ("setb", "c");
5087 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5089 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5091 if ((posbit = isLiteralBit (bytelit)) != 0)
5092 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5095 if (bytelit != 0x0FFL)
5096 emitcode ("anl", "a,%s",
5097 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5098 emitcode ("jnz", "%05d$", tlbl->key + 100);
5103 // bit = left & literal
5106 emitcode ("clr", "c");
5107 emitcode ("", "%05d$:", tlbl->key + 100);
5109 // if(left & literal)
5113 jmpTrueOrFalse (ifx, tlbl);
5121 /* if left is same as result */
5122 if (sameRegs (AOP (result), AOP (left)))
5124 for (; size--; offset++)
5126 if (AOP_TYPE (right) == AOP_LIT)
5128 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5130 else if (bytelit == 0)
5131 aopPut (AOP (result), zero, offset);
5132 else if (IS_AOP_PREG (result))
5134 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5135 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5136 aopPut (AOP (result), "a", offset);
5139 emitcode ("anl", "%s,%s",
5140 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5141 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5145 if (AOP_TYPE (left) == AOP_ACC)
5146 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5149 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5150 if (IS_AOP_PREG (result))
5152 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5153 aopPut (AOP (result), "a", offset);
5157 emitcode ("anl", "%s,a",
5158 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5165 // left & result in different registers
5166 if (AOP_TYPE (result) == AOP_CRY)
5169 // if(size), result in bit
5170 // if(!size && ifx), conditional oper: if(left & right)
5171 symbol *tlbl = newiTempLabel (NULL);
5172 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5174 emitcode ("setb", "c");
5177 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5178 emitcode ("anl", "a,%s",
5179 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5180 emitcode ("jnz", "%05d$", tlbl->key + 100);
5186 emitcode ("", "%05d$:", tlbl->key + 100);
5190 jmpTrueOrFalse (ifx, tlbl);
5194 for (; (size--); offset++)
5197 // result = left & right
5198 if (AOP_TYPE (right) == AOP_LIT)
5200 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5202 aopPut (AOP (result),
5203 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5207 else if (bytelit == 0)
5209 aopPut (AOP (result), zero, offset);
5212 D (emitcode (";", "better literal AND.");
5214 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5215 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5216 FALSE, FALSE, FALSE));
5221 // faster than result <- left, anl result,right
5222 // and better if result is SFR
5223 if (AOP_TYPE (left) == AOP_ACC)
5225 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5226 FALSE, FALSE, FALSE));
5230 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5231 emitcode ("anl", "a,%s",
5232 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5235 aopPut (AOP (result), "a", offset);
5241 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5242 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5243 freeAsmop (result, NULL, ic, TRUE);
5247 /*-----------------------------------------------------------------*/
5248 /* genOr - code for or */
5249 /*-----------------------------------------------------------------*/
5251 genOr (iCode * ic, iCode * ifx)
5253 operand *left, *right, *result;
5254 int size, offset = 0;
5255 unsigned long lit = 0L;
5258 D (emitcode (";", "genOr "););
5260 AOP_OP_3_NOFATAL (ic, pushResult);
5261 AOP_SET_LOCALS (ic);
5265 genFarFarLogicOp(ic, "orl");
5271 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5273 AOP_TYPE (left), AOP_TYPE (right));
5274 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5276 AOP_SIZE (left), AOP_SIZE (right));
5279 /* if left is a literal & right is not then exchange them */
5280 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5281 AOP_NEEDSACC (left))
5283 operand *tmp = right;
5288 /* if result = right then exchange them */
5289 if (sameRegs (AOP (result), AOP (right)))
5291 operand *tmp = right;
5296 /* if right is bit then exchange them */
5297 if (AOP_TYPE (right) == AOP_CRY &&
5298 AOP_TYPE (left) != AOP_CRY)
5300 operand *tmp = right;
5304 if (AOP_TYPE (right) == AOP_LIT)
5305 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5307 size = AOP_SIZE (result);
5311 if (AOP_TYPE (left) == AOP_CRY)
5313 if (AOP_TYPE (right) == AOP_LIT)
5315 // c = bit & literal;
5318 // lit != 0 => result = 1
5319 if (AOP_TYPE (result) == AOP_CRY)
5322 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5324 continueIfTrue (ifx);
5327 emitcode ("setb", "c");
5331 // lit == 0 => result = left
5332 if (size && sameRegs (AOP (result), AOP (left)))
5334 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5339 if (AOP_TYPE (right) == AOP_CRY)
5342 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5343 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5348 symbol *tlbl = newiTempLabel (NULL);
5349 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5350 emitcode ("setb", "c");
5351 emitcode ("jb", "%s,%05d$",
5352 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5354 emitcode ("jnz", "%05d$", tlbl->key + 100);
5355 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5357 jmpTrueOrFalse (ifx, tlbl);
5363 emitcode ("", "%05d$:", tlbl->key + 100);
5372 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5373 genIfxJump (ifx, "c");
5377 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5378 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5379 if ((AOP_TYPE (right) == AOP_LIT) &&
5380 (AOP_TYPE (result) == AOP_CRY) &&
5381 (AOP_TYPE (left) != AOP_CRY))
5387 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5389 continueIfTrue (ifx);
5394 // lit = 0, result = boolean(left)
5396 emitcode ("setb", "c");
5400 symbol *tlbl = newiTempLabel (NULL);
5401 emitcode ("jnz", "%05d$", tlbl->key + 100);
5403 emitcode ("", "%05d$:", tlbl->key + 100);
5407 genIfxJump (ifx, "a");
5415 /* if left is same as result */
5416 if (sameRegs (AOP (result), AOP (left)))
5418 for (; size--; offset++)
5420 if (AOP_TYPE (right) == AOP_LIT)
5422 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5428 if (IS_AOP_PREG (left))
5430 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5431 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5432 aopPut (AOP (result), "a", offset);
5436 emitcode ("orl", "%s,%s",
5437 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5438 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5444 if (AOP_TYPE (left) == AOP_ACC)
5446 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5450 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5451 if (IS_AOP_PREG (left))
5453 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5454 aopPut (AOP (result), "a", offset);
5458 emitcode ("orl", "%s,a",
5459 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5467 // left & result in different registers
5468 if (AOP_TYPE (result) == AOP_CRY)
5471 // if(size), result in bit
5472 // if(!size && ifx), conditional oper: if(left | right)
5473 symbol *tlbl = newiTempLabel (NULL);
5474 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5476 emitcode ("setb", "c");
5479 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5480 emitcode ("orl", "a,%s",
5481 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5482 emitcode ("jnz", "%05d$", tlbl->key + 100);
5488 emitcode ("", "%05d$:", tlbl->key + 100);
5492 jmpTrueOrFalse (ifx, tlbl);
5496 for (; (size--); offset++)
5499 // result = left & right
5500 if (AOP_TYPE (right) == AOP_LIT)
5502 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5504 aopPut (AOP (result),
5505 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5509 D (emitcode (";", "better literal OR.");
5511 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5512 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5513 FALSE, FALSE, FALSE));
5518 // faster than result <- left, anl result,right
5519 // and better if result is SFR
5520 if (AOP_TYPE (left) == AOP_ACC)
5522 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5523 FALSE, FALSE, FALSE));
5527 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5528 emitcode ("orl", "a,%s",
5529 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5532 aopPut (AOP (result), "a", offset);
5538 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5539 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5540 freeAsmop (result, NULL, ic, TRUE);
5543 /*-----------------------------------------------------------------*/
5544 /* genXor - code for xclusive or */
5545 /*-----------------------------------------------------------------*/
5547 genXor (iCode * ic, iCode * ifx)
5549 operand *left, *right, *result;
5550 int size, offset = 0;
5551 unsigned long lit = 0L;
5554 D (emitcode (";", "genXor "););
5556 AOP_OP_3_NOFATAL (ic, pushResult);
5557 AOP_SET_LOCALS (ic);
5561 genFarFarLogicOp(ic, "xrl");
5566 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5568 AOP_TYPE (left), AOP_TYPE (right));
5569 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5571 AOP_SIZE (left), AOP_SIZE (right));
5574 /* if left is a literal & right is not ||
5575 if left needs acc & right does not */
5576 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5577 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5579 operand *tmp = right;
5584 /* if result = right then exchange them */
5585 if (sameRegs (AOP (result), AOP (right)))
5587 operand *tmp = right;
5592 /* if right is bit then exchange them */
5593 if (AOP_TYPE (right) == AOP_CRY &&
5594 AOP_TYPE (left) != AOP_CRY)
5596 operand *tmp = right;
5600 if (AOP_TYPE (right) == AOP_LIT)
5601 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5603 size = AOP_SIZE (result);
5607 if (AOP_TYPE (left) == AOP_CRY)
5609 if (AOP_TYPE (right) == AOP_LIT)
5611 // c = bit & literal;
5614 // lit>>1 != 0 => result = 1
5615 if (AOP_TYPE (result) == AOP_CRY)
5618 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5620 continueIfTrue (ifx);
5623 emitcode ("setb", "c");
5630 // lit == 0, result = left
5631 if (size && sameRegs (AOP (result), AOP (left)))
5633 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5637 // lit == 1, result = not(left)
5638 if (size && sameRegs (AOP (result), AOP (left)))
5640 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5645 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5646 emitcode ("cpl", "c");
5655 symbol *tlbl = newiTempLabel (NULL);
5656 if (AOP_TYPE (right) == AOP_CRY)
5659 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5663 int sizer = AOP_SIZE (right);
5665 // if val>>1 != 0, result = 1
5666 emitcode ("setb", "c");
5669 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5671 // test the msb of the lsb
5672 emitcode ("anl", "a,#0xfe");
5673 emitcode ("jnz", "%05d$", tlbl->key + 100);
5677 emitcode ("rrc", "a");
5679 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5680 emitcode ("cpl", "c");
5681 emitcode ("", "%05d$:", (tlbl->key + 100));
5688 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5689 genIfxJump (ifx, "c");
5693 if (sameRegs (AOP (result), AOP (left)))
5695 /* if left is same as result */
5696 for (; size--; offset++)
5698 if (AOP_TYPE (right) == AOP_LIT)
5700 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5702 else if (IS_AOP_PREG (left))
5704 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5705 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5706 aopPut (AOP (result), "a", offset);
5709 emitcode ("xrl", "%s,%s",
5710 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5711 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5715 if (AOP_TYPE (left) == AOP_ACC)
5716 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5719 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5720 if (IS_AOP_PREG (left))
5722 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5723 aopPut (AOP (result), "a", offset);
5726 emitcode ("xrl", "%s,a",
5727 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5734 // left & result in different registers
5735 if (AOP_TYPE (result) == AOP_CRY)
5738 // if(size), result in bit
5739 // if(!size && ifx), conditional oper: if(left ^ right)
5740 symbol *tlbl = newiTempLabel (NULL);
5741 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5743 emitcode ("setb", "c");
5746 if ((AOP_TYPE (right) == AOP_LIT) &&
5747 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5749 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5753 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5754 emitcode ("xrl", "a,%s",
5755 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5757 emitcode ("jnz", "%05d$", tlbl->key + 100);
5763 emitcode ("", "%05d$:", tlbl->key + 100);
5767 jmpTrueOrFalse (ifx, tlbl);
5770 for (; (size--); offset++)
5773 // result = left & right
5774 if (AOP_TYPE (right) == AOP_LIT)
5776 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5778 aopPut (AOP (result),
5779 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5783 D (emitcode (";", "better literal XOR.");
5785 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5786 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5787 FALSE, FALSE, FALSE));
5791 // faster than result <- left, anl result,right
5792 // and better if result is SFR
5793 if (AOP_TYPE (left) == AOP_ACC)
5795 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5796 FALSE, FALSE, FALSE));
5800 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5801 emitcode ("xrl", "a,%s",
5802 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5805 aopPut (AOP (result), "a", offset);
5810 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5811 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5812 freeAsmop (result, NULL, ic, TRUE);
5815 /*-----------------------------------------------------------------*/
5816 /* genInline - write the inline code out */
5817 /*-----------------------------------------------------------------*/
5819 genInline (iCode * ic)
5821 char *buffer, *bp, *bp1;
5823 D (emitcode (";", "genInline ");
5826 _G.inLine += (!options.asmpeep);
5828 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5829 strcpy (buffer, IC_INLINE (ic));
5831 /* emit each line as a code */
5856 /* emitcode("",buffer); */
5857 _G.inLine -= (!options.asmpeep);
5860 /*-----------------------------------------------------------------*/
5861 /* genRRC - rotate right with carry */
5862 /*-----------------------------------------------------------------*/
5866 operand *left, *result;
5867 int size, offset = 0;
5870 D (emitcode (";", "genRRC ");
5873 /* rotate right with carry */
5874 left = IC_LEFT (ic);
5875 result = IC_RESULT (ic);
5876 aopOp (left, ic, FALSE, FALSE);
5877 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5879 /* move it to the result */
5880 size = AOP_SIZE (result);
5884 _startLazyDPSEvaluation ();
5887 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5889 emitcode ("rrc", "a");
5890 if (AOP_SIZE (result) > 1)
5891 aopPut (AOP (result), "a", offset--);
5893 _endLazyDPSEvaluation ();
5895 /* now we need to put the carry into the
5896 highest order byte of the result */
5897 if (AOP_SIZE (result) > 1)
5899 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5902 emitcode ("mov", "acc.7,c");
5903 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5904 freeAsmop (left, NULL, ic, TRUE);
5905 freeAsmop (result, NULL, ic, TRUE);
5908 /*-----------------------------------------------------------------*/
5909 /* genRLC - generate code for rotate left with carry */
5910 /*-----------------------------------------------------------------*/
5914 operand *left, *result;
5915 int size, offset = 0;
5918 D (emitcode (";", "genRLC ");
5921 /* rotate right with carry */
5922 left = IC_LEFT (ic);
5923 result = IC_RESULT (ic);
5924 aopOp (left, ic, FALSE, FALSE);
5925 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5927 /* move it to the result */
5928 size = AOP_SIZE (result);
5932 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5934 emitcode ("add", "a,acc");
5935 if (AOP_SIZE (result) > 1)
5937 aopPut (AOP (result), "a", offset++);
5940 _startLazyDPSEvaluation ();
5943 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5945 emitcode ("rlc", "a");
5946 if (AOP_SIZE (result) > 1)
5947 aopPut (AOP (result), "a", offset++);
5949 _endLazyDPSEvaluation ();
5951 /* now we need to put the carry into the
5952 highest order byte of the result */
5953 if (AOP_SIZE (result) > 1)
5955 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5958 emitcode ("mov", "acc.0,c");
5959 aopPut (AOP (result), "a", 0);
5960 freeAsmop (left, NULL, ic, TRUE);
5961 freeAsmop (result, NULL, ic, TRUE);
5964 /*-----------------------------------------------------------------*/
5965 /* genGetHbit - generates code get highest order bit */
5966 /*-----------------------------------------------------------------*/
5968 genGetHbit (iCode * ic)
5970 operand *left, *result;
5971 left = IC_LEFT (ic);
5972 result = IC_RESULT (ic);
5973 aopOp (left, ic, FALSE, FALSE);
5974 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5976 D (emitcode (";", "genGetHbit ");
5979 /* get the highest order byte into a */
5980 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5981 if (AOP_TYPE (result) == AOP_CRY)
5983 emitcode ("rlc", "a");
5988 emitcode ("rl", "a");
5989 emitcode ("anl", "a,#0x01");
5994 freeAsmop (left, NULL, ic, TRUE);
5995 freeAsmop (result, NULL, ic, TRUE);
5998 /*-----------------------------------------------------------------*/
5999 /* AccRol - rotate left accumulator by known count */
6000 /*-----------------------------------------------------------------*/
6002 AccRol (int shCount)
6004 shCount &= 0x0007; // shCount : 0..7
6011 emitcode ("rl", "a");
6014 emitcode ("rl", "a");
6015 emitcode ("rl", "a");
6018 emitcode ("swap", "a");
6019 emitcode ("rr", "a");
6022 emitcode ("swap", "a");
6025 emitcode ("swap", "a");
6026 emitcode ("rl", "a");
6029 emitcode ("rr", "a");
6030 emitcode ("rr", "a");
6033 emitcode ("rr", "a");
6038 /*-----------------------------------------------------------------*/
6039 /* AccLsh - left shift accumulator by known count */
6040 /*-----------------------------------------------------------------*/
6042 AccLsh (int shCount)
6047 emitcode ("add", "a,acc");
6048 else if (shCount == 2)
6050 emitcode ("add", "a,acc");
6051 emitcode ("add", "a,acc");
6055 /* rotate left accumulator */
6057 /* and kill the lower order bits */
6058 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6063 /*-----------------------------------------------------------------*/
6064 /* AccRsh - right shift accumulator by known count */
6065 /*-----------------------------------------------------------------*/
6067 AccRsh (int shCount)
6074 emitcode ("rrc", "a");
6078 /* rotate right accumulator */
6079 AccRol (8 - shCount);
6080 /* and kill the higher order bits */
6081 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6086 #ifdef BETTER_LITERAL_SHIFT
6087 /*-----------------------------------------------------------------*/
6088 /* AccSRsh - signed right shift accumulator by known count */
6089 /*-----------------------------------------------------------------*/
6091 AccSRsh (int shCount)
6098 emitcode ("mov", "c,acc.7");
6099 emitcode ("rrc", "a");
6101 else if (shCount == 2)
6103 emitcode ("mov", "c,acc.7");
6104 emitcode ("rrc", "a");
6105 emitcode ("mov", "c,acc.7");
6106 emitcode ("rrc", "a");
6110 tlbl = newiTempLabel (NULL);
6111 /* rotate right accumulator */
6112 AccRol (8 - shCount);
6113 /* and kill the higher order bits */
6114 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6115 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6116 emitcode ("orl", "a,#0x%02x",
6117 (unsigned char) ~SRMask[shCount]);
6118 emitcode ("", "%05d$:", tlbl->key + 100);
6124 #ifdef BETTER_LITERAL_SHIFT
6125 /*-----------------------------------------------------------------*/
6126 /* shiftR1Left2Result - shift right one byte from left to result */
6127 /*-----------------------------------------------------------------*/
6129 shiftR1Left2Result (operand * left, int offl,
6130 operand * result, int offr,
6131 int shCount, int sign)
6133 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6134 /* shift right accumulator */
6139 aopPut (AOP (result), "a", offr);
6143 #ifdef BETTER_LITERAL_SHIFT
6144 /*-----------------------------------------------------------------*/
6145 /* shiftL1Left2Result - shift left one byte from left to result */
6146 /*-----------------------------------------------------------------*/
6148 shiftL1Left2Result (operand * left, int offl,
6149 operand * result, int offr, int shCount)
6151 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6152 /* shift left accumulator */
6154 aopPut (AOP (result), "a", offr);
6158 #ifdef BETTER_LITERAL_SHIFT
6159 /*-----------------------------------------------------------------*/
6160 /* movLeft2Result - move byte from left to result */
6161 /*-----------------------------------------------------------------*/
6163 movLeft2Result (operand * left, int offl,
6164 operand * result, int offr, int sign)
6167 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6169 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6171 if (*l == '@' && (IS_AOP_PREG (result)))
6173 emitcode ("mov", "a,%s", l);
6174 aopPut (AOP (result), "a", offr);
6180 aopPut (AOP (result), l, offr);
6184 /* MSB sign in acc.7 ! */
6185 if (getDataSize (left) == offl + 1)
6187 emitcode ("mov", "a,%s", l);
6188 aopPut (AOP (result), "a", offr);
6196 #ifdef BETTER_LITERAL_SHIFT
6197 /*-----------------------------------------------------------------*/
6198 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6199 /*-----------------------------------------------------------------*/
6203 emitcode ("rrc", "a");
6204 emitcode ("xch", "a,%s", x);
6205 emitcode ("rrc", "a");
6206 emitcode ("xch", "a,%s", x);
6210 #ifdef BETTER_LITERAL_SHIFT
6212 /*-----------------------------------------------------------------*/
6213 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6214 /*-----------------------------------------------------------------*/
6218 emitcode ("xch", "a,%s", x);
6219 emitcode ("rlc", "a");
6220 emitcode ("xch", "a,%s", x);
6221 emitcode ("rlc", "a");
6225 #ifdef BETTER_LITERAL_SHIFT
6226 /*-----------------------------------------------------------------*/
6227 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6228 /*-----------------------------------------------------------------*/
6232 emitcode ("xch", "a,%s", x);
6233 emitcode ("add", "a,acc");
6234 emitcode ("xch", "a,%s", x);
6235 emitcode ("rlc", "a");
6239 #ifdef BETTER_LITERAL_SHIFT
6240 /*-----------------------------------------------------------------*/
6241 /* AccAXLsh - left shift a:x by known count (0..7) */
6242 /*-----------------------------------------------------------------*/
6244 AccAXLsh (char *x, int shCount)
6259 case 5: // AAAAABBB:CCCCCDDD
6261 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6263 emitcode ("anl", "a,#0x%02x",
6264 SLMask[shCount]); // BBB00000:CCCCCDDD
6266 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6268 AccRol (shCount); // DDDCCCCC:BBB00000
6270 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6272 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6274 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6276 emitcode ("anl", "a,#0x%02x",
6277 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6279 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6281 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6284 case 6: // AAAAAABB:CCCCCCDD
6285 emitcode ("anl", "a,#0x%02x",
6286 SRMask[shCount]); // 000000BB:CCCCCCDD
6287 emitcode ("mov", "c,acc.0"); // c = B
6288 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6290 AccAXRrl1 (x); // BCCCCCCD:D000000B
6291 AccAXRrl1 (x); // BBCCCCCC:DD000000
6293 emitcode("rrc","a");
6294 emitcode("xch","a,%s", x);
6295 emitcode("rrc","a");
6296 emitcode("mov","c,acc.0"); //<< get correct bit
6297 emitcode("xch","a,%s", x);
6299 emitcode("rrc","a");
6300 emitcode("xch","a,%s", x);
6301 emitcode("rrc","a");
6302 emitcode("xch","a,%s", x);
6305 case 7: // a:x <<= 7
6307 emitcode ("anl", "a,#0x%02x",
6308 SRMask[shCount]); // 0000000B:CCCCCCCD
6310 emitcode ("mov", "c,acc.0"); // c = B
6312 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6314 AccAXRrl1 (x); // BCCCCCCC:D0000000
6323 #ifdef BETTER_LITERAL_SHIFT
6325 /*-----------------------------------------------------------------*/
6326 /* AccAXRsh - right shift a:x known count (0..7) */
6327 /*-----------------------------------------------------------------*/
6329 AccAXRsh (char *x, int shCount)
6337 AccAXRrl1 (x); // 0->a:x
6342 AccAXRrl1 (x); // 0->a:x
6345 AccAXRrl1 (x); // 0->a:x
6350 case 5: // AAAAABBB:CCCCCDDD = a:x
6352 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6354 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6356 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6358 emitcode ("anl", "a,#0x%02x",
6359 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6361 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6363 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6365 emitcode ("anl", "a,#0x%02x",
6366 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6368 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6370 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6372 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6375 case 6: // AABBBBBB:CCDDDDDD
6377 emitcode ("mov", "c,acc.7");
6378 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6380 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6382 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6384 emitcode ("anl", "a,#0x%02x",
6385 SRMask[shCount]); // 000000AA:BBBBBBCC
6388 case 7: // ABBBBBBB:CDDDDDDD
6390 emitcode ("mov", "c,acc.7"); // c = A
6392 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6394 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6396 emitcode ("anl", "a,#0x%02x",
6397 SRMask[shCount]); // 0000000A:BBBBBBBC
6406 #ifdef BETTER_LITERAL_SHIFT
6408 /*-----------------------------------------------------------------*/
6409 /* AccAXRshS - right shift signed a:x known count (0..7) */
6410 /*-----------------------------------------------------------------*/
6412 AccAXRshS (char *x, int shCount)
6420 emitcode ("mov", "c,acc.7");
6421 AccAXRrl1 (x); // s->a:x
6425 emitcode ("mov", "c,acc.7");
6426 AccAXRrl1 (x); // s->a:x
6428 emitcode ("mov", "c,acc.7");
6429 AccAXRrl1 (x); // s->a:x
6434 case 5: // AAAAABBB:CCCCCDDD = a:x
6436 tlbl = newiTempLabel (NULL);
6437 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6439 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6441 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6443 emitcode ("anl", "a,#0x%02x",
6444 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6446 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6448 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6450 emitcode ("anl", "a,#0x%02x",
6451 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6453 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6455 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6457 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6459 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6460 emitcode ("orl", "a,#0x%02x",
6461 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6463 emitcode ("", "%05d$:", tlbl->key + 100);
6464 break; // SSSSAAAA:BBBCCCCC
6466 case 6: // AABBBBBB:CCDDDDDD
6468 tlbl = newiTempLabel (NULL);
6469 emitcode ("mov", "c,acc.7");
6470 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6472 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6474 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6476 emitcode ("anl", "a,#0x%02x",
6477 SRMask[shCount]); // 000000AA:BBBBBBCC
6479 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6480 emitcode ("orl", "a,#0x%02x",
6481 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6483 emitcode ("", "%05d$:", tlbl->key + 100);
6485 case 7: // ABBBBBBB:CDDDDDDD
6487 tlbl = newiTempLabel (NULL);
6488 emitcode ("mov", "c,acc.7"); // c = A
6490 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6492 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6494 emitcode ("anl", "a,#0x%02x",
6495 SRMask[shCount]); // 0000000A:BBBBBBBC
6497 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6498 emitcode ("orl", "a,#0x%02x",
6499 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6501 emitcode ("", "%05d$:", tlbl->key + 100);
6509 #ifdef BETTER_LITERAL_SHIFT
6511 _loadLeftIntoAx(char **lsb,
6517 // Get the initial value from left into a pair of registers.
6518 // MSB must be in A, LSB can be any register.
6520 // If the result is held in registers, it is an optimization
6521 // if the LSB can be held in the register which will hold the,
6522 // result LSB since this saves us from having to copy it into
6523 // the result following AccAXLsh.
6525 // If the result is addressed indirectly, this is not a gain.
6526 if (AOP_NEEDSACC(result))
6530 _startLazyDPSEvaluation();
6531 if (AOP_TYPE(left) == AOP_DPTR2)
6534 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6535 // get LSB in DP2_RESULT_REG.
6536 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6537 assert(!strcmp(leftByte, DP2_RESULT_REG));
6541 // get LSB into DP2_RESULT_REG
6542 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6543 if (strcmp(leftByte, DP2_RESULT_REG))
6545 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6548 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6549 assert(strcmp(leftByte, DP2_RESULT_REG));
6552 _endLazyDPSEvaluation();
6553 *lsb = DP2_RESULT_REG;
6557 if (sameRegs (AOP (result), AOP (left)) &&
6558 ((offl + MSB16) == offr))
6560 /* don't crash result[offr] */
6561 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6562 emitcode ("xch", "a,%s",
6563 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6567 movLeft2Result (left, offl, result, offr, 0);
6568 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6570 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6571 assert(strcmp(*lsb,"a"));
6576 _storeAxResults(char *lsb,
6580 _startLazyDPSEvaluation();
6581 if (AOP_NEEDSACC(result))
6583 /* We have to explicitly update the result LSB.
6585 emitcode("xch","a,%s", lsb);
6586 aopPut(AOP(result), "a", offr);
6587 emitcode("mov","a,%s", lsb);
6589 if (getDataSize (result) > 1)
6591 aopPut (AOP (result), "a", offr + MSB16);
6593 _endLazyDPSEvaluation();
6596 /*-----------------------------------------------------------------*/
6597 /* shiftL2Left2Result - shift left two bytes from left to result */
6598 /*-----------------------------------------------------------------*/
6600 shiftL2Left2Result (operand * left, int offl,
6601 operand * result, int offr, int shCount)
6605 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6607 AccAXLsh (lsb, shCount);
6609 _storeAxResults(lsb, result, offr);
6613 #ifdef BETTER_LITERAL_SHIFT
6614 /*-----------------------------------------------------------------*/
6615 /* shiftR2Left2Result - shift right two bytes from left to result */
6616 /*-----------------------------------------------------------------*/
6618 shiftR2Left2Result (operand * left, int offl,
6619 operand * result, int offr,
6620 int shCount, int sign)
6624 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6626 /* a:x >> shCount (x = lsb(result)) */
6629 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6633 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6636 _storeAxResults(lsb, result, offr);
6642 /*-----------------------------------------------------------------*/
6643 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6644 /*-----------------------------------------------------------------*/
6646 shiftLLeftOrResult (operand * left, int offl,
6647 operand * result, int offr, int shCount)
6649 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6650 /* shift left accumulator */
6652 /* or with result */
6653 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6654 /* back to result */
6655 aopPut (AOP (result), "a", offr);
6661 /*-----------------------------------------------------------------*/
6662 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6663 /*-----------------------------------------------------------------*/
6665 shiftRLeftOrResult (operand * left, int offl,
6666 operand * result, int offr, int shCount)
6668 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6669 /* shift right accumulator */
6671 /* or with result */
6672 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6673 /* back to result */
6674 aopPut (AOP (result), "a", offr);
6678 #ifdef BETTER_LITERAL_SHIFT
6679 /*-----------------------------------------------------------------*/
6680 /* genlshOne - left shift a one byte quantity by known count */
6681 /*-----------------------------------------------------------------*/
6683 genlshOne (operand * result, operand * left, int shCount)
6685 D (emitcode (";", "genlshOne "););
6686 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6690 #ifdef BETTER_LITERAL_SHIFT
6691 /*-----------------------------------------------------------------*/
6692 /* genlshTwo - left shift two bytes by known amount != 0 */
6693 /*-----------------------------------------------------------------*/
6695 genlshTwo (operand * result, operand * left, int shCount)
6699 D (emitcode (";", "genlshTwo "););
6701 size = getDataSize (result);
6703 /* if shCount >= 8 */
6708 _startLazyDPSEvaluation();
6714 _endLazyDPSEvaluation();
6715 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6716 aopPut (AOP (result), zero, LSB);
6720 movLeft2Result (left, LSB, result, MSB16, 0);
6721 aopPut (AOP (result), zero, LSB);
6722 _endLazyDPSEvaluation();
6727 aopPut (AOP (result), zero, LSB);
6728 _endLazyDPSEvaluation();
6732 /* 1 <= shCount <= 7 */
6737 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6741 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6749 /*-----------------------------------------------------------------*/
6750 /* shiftLLong - shift left one long from left to result */
6751 /* offl = LSB or MSB16 */
6752 /*-----------------------------------------------------------------*/
6754 shiftLLong (operand * left, operand * result, int offr)
6757 int size = AOP_SIZE (result);
6759 if (size >= LSB + offr)
6761 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6763 emitcode ("add", "a,acc");
6764 if (sameRegs (AOP (left), AOP (result)) &&
6765 size >= MSB16 + offr && offr != LSB)
6766 emitcode ("xch", "a,%s",
6767 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6769 aopPut (AOP (result), "a", LSB + offr);
6772 if (size >= MSB16 + offr)
6774 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6776 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6779 emitcode ("rlc", "a");
6780 if (sameRegs (AOP (left), AOP (result)) &&
6781 size >= MSB24 + offr && offr != LSB)
6782 emitcode ("xch", "a,%s",
6783 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6785 aopPut (AOP (result), "a", MSB16 + offr);
6788 if (size >= MSB24 + offr)
6790 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6792 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6795 emitcode ("rlc", "a");
6796 if (sameRegs (AOP (left), AOP (result)) &&
6797 size >= MSB32 + offr && offr != LSB)
6798 emitcode ("xch", "a,%s",
6799 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6801 aopPut (AOP (result), "a", MSB24 + offr);
6804 if (size > MSB32 + offr)
6806 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6808 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6811 emitcode ("rlc", "a");
6812 aopPut (AOP (result), "a", MSB32 + offr);
6815 aopPut (AOP (result), zero, LSB);
6821 /*-----------------------------------------------------------------*/
6822 /* genlshFour - shift four byte by a known amount != 0 */
6823 /*-----------------------------------------------------------------*/
6825 genlshFour (operand * result, operand * left, int shCount)
6829 D (emitcode (";", "genlshFour ");
6832 size = AOP_SIZE (result);
6834 /* if shifting more that 3 bytes */
6839 /* lowest order of left goes to the highest
6840 order of the destination */
6841 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6843 movLeft2Result (left, LSB, result, MSB32, 0);
6844 aopPut (AOP (result), zero, LSB);
6845 aopPut (AOP (result), zero, MSB16);
6846 aopPut (AOP (result), zero, MSB24);
6850 /* more than two bytes */
6851 else if (shCount >= 16)
6853 /* lower order two bytes goes to higher order two bytes */
6855 /* if some more remaining */
6857 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6860 movLeft2Result (left, MSB16, result, MSB32, 0);
6861 movLeft2Result (left, LSB, result, MSB24, 0);
6863 aopPut (AOP (result), zero, MSB16);
6864 aopPut (AOP (result), zero, LSB);
6868 /* if more than 1 byte */
6869 else if (shCount >= 8)
6871 /* lower order three bytes goes to higher order three bytes */
6876 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6878 movLeft2Result (left, LSB, result, MSB16, 0);
6884 movLeft2Result (left, MSB24, result, MSB32, 0);
6885 movLeft2Result (left, MSB16, result, MSB24, 0);
6886 movLeft2Result (left, LSB, result, MSB16, 0);
6887 aopPut (AOP (result), zero, LSB);
6889 else if (shCount == 1)
6890 shiftLLong (left, result, MSB16);
6893 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6894 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6895 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6896 aopPut (AOP (result), zero, LSB);
6901 /* 1 <= shCount <= 7 */
6902 else if (shCount <= 2)
6904 shiftLLong (left, result, LSB);
6906 shiftLLong (result, result, LSB);
6908 /* 3 <= shCount <= 7, optimize */
6911 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6912 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6913 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6918 #ifdef BETTER_LITERAL_SHIFT
6919 /*-----------------------------------------------------------------*/
6920 /* genLeftShiftLiteral - left shifting by known count */
6921 /*-----------------------------------------------------------------*/
6923 genLeftShiftLiteral (operand * left,
6928 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6931 size = getSize (operandType (result));
6933 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6935 /* We only handle certain easy cases so far. */
6937 && (shCount < (size * 8))
6941 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6945 freeAsmop (right, NULL, ic, TRUE);
6947 aopOp(left, ic, FALSE, FALSE);
6948 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6951 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6953 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6954 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6956 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6959 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6961 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6962 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6964 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6970 emitcode ("; shift left ", "result %d, left %d", size,
6974 /* I suppose that the left size >= result size */
6977 _startLazyDPSEvaluation();
6980 movLeft2Result (left, size, result, size, 0);
6982 _endLazyDPSEvaluation();
6984 else if (shCount >= (size * 8))
6986 _startLazyDPSEvaluation();
6989 aopPut (AOP (result), zero, size);
6991 _endLazyDPSEvaluation();
6998 genlshOne (result, left, shCount);
7002 genlshTwo (result, left, shCount);
7006 genlshFour (result, left, shCount);
7010 fprintf(stderr, "*** ack! mystery literal shift!\n");
7014 freeAsmop (left, NULL, ic, TRUE);
7015 freeAsmop (result, NULL, ic, TRUE);
7020 /*-----------------------------------------------------------------*/
7021 /* genLeftShift - generates code for left shifting */
7022 /*-----------------------------------------------------------------*/
7024 genLeftShift (iCode * ic)
7026 operand *left, *right, *result;
7029 symbol *tlbl, *tlbl1;
7031 D (emitcode (";", "genLeftShift "););
7033 right = IC_RIGHT (ic);
7034 left = IC_LEFT (ic);
7035 result = IC_RESULT (ic);
7037 aopOp (right, ic, FALSE, FALSE);
7040 #ifdef BETTER_LITERAL_SHIFT
7041 /* if the shift count is known then do it
7042 as efficiently as possible */
7043 if (AOP_TYPE (right) == AOP_LIT)
7045 if (genLeftShiftLiteral (left, right, result, ic))
7052 /* shift count is unknown then we have to form
7053 a loop get the loop count in B : Note: we take
7054 only the lower order byte since shifting
7055 more that 32 bits make no sense anyway, ( the
7056 largest size of an object can be only 32 bits ) */
7058 if (AOP_TYPE (right) == AOP_LIT)
7060 /* Really should be handled by genLeftShiftLiteral,
7061 * but since I'm too lazy to fix that today, at least we can make
7062 * some small improvement.
7064 emitcode("mov", "b,#0x%02x",
7065 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7069 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7070 emitcode ("inc", "b");
7072 freeAsmop (right, NULL, ic, TRUE);
7073 aopOp (left, ic, FALSE, FALSE);
7074 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7076 /* now move the left to the result if they are not the
7078 if (!sameRegs (AOP (left), AOP (result)) &&
7079 AOP_SIZE (result) > 1)
7082 size = AOP_SIZE (result);
7084 _startLazyDPSEvaluation ();
7087 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7088 if (*l == '@' && (IS_AOP_PREG (result)))
7091 emitcode ("mov", "a,%s", l);
7092 aopPut (AOP (result), "a", offset);
7095 aopPut (AOP (result), l, offset);
7098 _endLazyDPSEvaluation ();
7101 tlbl = newiTempLabel (NULL);
7102 size = AOP_SIZE (result);
7104 tlbl1 = newiTempLabel (NULL);
7106 /* if it is only one byte then */
7109 symbol *tlbl1 = newiTempLabel (NULL);
7111 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7113 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7114 emitcode ("", "%05d$:", tlbl->key + 100);
7115 emitcode ("add", "a,acc");
7116 emitcode ("", "%05d$:", tlbl1->key + 100);
7117 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7118 aopPut (AOP (result), "a", 0);
7122 reAdjustPreg (AOP (result));
7124 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7125 emitcode ("", "%05d$:", tlbl->key + 100);
7126 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7128 emitcode ("add", "a,acc");
7129 aopPut (AOP (result), "a", offset++);
7130 _startLazyDPSEvaluation ();
7133 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7135 emitcode ("rlc", "a");
7136 aopPut (AOP (result), "a", offset++);
7138 _endLazyDPSEvaluation ();
7139 reAdjustPreg (AOP (result));
7141 emitcode ("", "%05d$:", tlbl1->key + 100);
7142 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7144 freeAsmop (left, NULL, ic, TRUE);
7145 freeAsmop (result, NULL, ic, TRUE);
7148 #ifdef BETTER_LITERAL_SHIFT
7149 /*-----------------------------------------------------------------*/
7150 /* genrshOne - right shift a one byte quantity by known count */
7151 /*-----------------------------------------------------------------*/
7153 genrshOne (operand * result, operand * left,
7154 int shCount, int sign)
7156 D (emitcode (";", "genrshOne"););
7157 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7161 #ifdef BETTER_LITERAL_SHIFT
7162 /*-----------------------------------------------------------------*/
7163 /* genrshTwo - right shift two bytes by known amount != 0 */
7164 /*-----------------------------------------------------------------*/
7166 genrshTwo (operand * result, operand * left,
7167 int shCount, int sign)
7169 D (emitcode (";", "genrshTwo"););
7171 /* if shCount >= 8 */
7175 _startLazyDPSEvaluation();
7178 shiftR1Left2Result (left, MSB16, result, LSB,
7183 movLeft2Result (left, MSB16, result, LSB, sign);
7185 addSign (result, MSB16, sign);
7186 _endLazyDPSEvaluation();
7189 /* 1 <= shCount <= 7 */
7192 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7199 /*-----------------------------------------------------------------*/
7200 /* shiftRLong - shift right one long from left to result */
7201 /* offl = LSB or MSB16 */
7202 /*-----------------------------------------------------------------*/
7204 shiftRLong (operand * left, int offl,
7205 operand * result, int sign)
7208 emitcode ("clr", "c");
7209 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7211 emitcode ("mov", "c,acc.7");
7212 emitcode ("rrc", "a");
7213 aopPut (AOP (result), "a", MSB32 - offl);
7215 /* add sign of "a" */
7216 addSign (result, MSB32, sign);
7218 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7219 emitcode ("rrc", "a");
7220 aopPut (AOP (result), "a", MSB24 - offl);
7222 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7223 emitcode ("rrc", "a");
7224 aopPut (AOP (result), "a", MSB16 - offl);
7228 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7229 emitcode ("rrc", "a");
7230 aopPut (AOP (result), "a", LSB);
7237 /*-----------------------------------------------------------------*/
7238 /* genrshFour - shift four byte by a known amount != 0 */
7239 /*-----------------------------------------------------------------*/
7241 genrshFour (operand * result, operand * left,
7242 int shCount, int sign)
7244 D (emitcode (";", "genrshFour");
7247 /* if shifting more that 3 bytes */
7252 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7254 movLeft2Result (left, MSB32, result, LSB, sign);
7255 addSign (result, MSB16, sign);
7257 else if (shCount >= 16)
7261 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7264 movLeft2Result (left, MSB24, result, LSB, 0);
7265 movLeft2Result (left, MSB32, result, MSB16, sign);
7267 addSign (result, MSB24, sign);
7269 else if (shCount >= 8)
7273 shiftRLong (left, MSB16, result, sign);
7274 else if (shCount == 0)
7276 movLeft2Result (left, MSB16, result, LSB, 0);
7277 movLeft2Result (left, MSB24, result, MSB16, 0);
7278 movLeft2Result (left, MSB32, result, MSB24, sign);
7279 addSign (result, MSB32, sign);
7283 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7284 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7285 /* the last shift is signed */
7286 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7287 addSign (result, MSB32, sign);
7291 { /* 1 <= shCount <= 7 */
7294 shiftRLong (left, LSB, result, sign);
7296 shiftRLong (result, LSB, result, sign);
7300 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7301 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7302 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7308 #ifdef BETTER_LITERAL_SHIFT
7309 /*-----------------------------------------------------------------*/
7310 /* genRightShiftLiteral - right shifting by known count */
7311 /*-----------------------------------------------------------------*/
7313 genRightShiftLiteral (operand * left,
7319 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7322 size = getSize (operandType (result));
7324 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7326 /* We only handle certain easy cases so far. */
7328 && (shCount < (size * 8))
7332 D(emitcode (";", "genRightShiftLiteral wimping out"););
7336 freeAsmop (right, NULL, ic, TRUE);
7338 aopOp (left, ic, FALSE, FALSE);
7339 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7342 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7346 /* test the LEFT size !!! */
7348 /* I suppose that the left size >= result size */
7351 size = getDataSize (result);
7352 _startLazyDPSEvaluation();
7355 movLeft2Result (left, size, result, size, 0);
7357 _endLazyDPSEvaluation();
7359 else if (shCount >= (size * 8))
7363 /* get sign in acc.7 */
7364 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7366 addSign (result, LSB, sign);
7373 genrshOne (result, left, shCount, sign);
7377 genrshTwo (result, left, shCount, sign);
7381 genrshFour (result, left, shCount, sign);
7388 freeAsmop (left, NULL, ic, TRUE);
7389 freeAsmop (result, NULL, ic, TRUE);
7395 /*-----------------------------------------------------------------*/
7396 /* genSignedRightShift - right shift of signed number */
7397 /*-----------------------------------------------------------------*/
7399 genSignedRightShift (iCode * ic)
7401 operand *right, *left, *result;
7404 symbol *tlbl, *tlbl1;
7406 D (emitcode (";", "genSignedRightShift "););
7408 /* we do it the hard way put the shift count in b
7409 and loop thru preserving the sign */
7411 right = IC_RIGHT (ic);
7412 left = IC_LEFT (ic);
7413 result = IC_RESULT (ic);
7415 aopOp (right, ic, FALSE, FALSE);
7417 #ifdef BETTER_LITERAL_SHIFT
7418 if (AOP_TYPE (right) == AOP_LIT)
7420 if (genRightShiftLiteral (left, right, result, ic, 1))
7426 /* shift count is unknown then we have to form
7427 a loop get the loop count in B : Note: we take
7428 only the lower order byte since shifting
7429 more that 32 bits make no sense anyway, ( the
7430 largest size of an object can be only 32 bits ) */
7432 if (AOP_TYPE (right) == AOP_LIT)
7434 /* Really should be handled by genRightShiftLiteral,
7435 * but since I'm too lazy to fix that today, at least we can make
7436 * some small improvement.
7438 emitcode("mov", "b,#0x%02x",
7439 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7443 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7444 emitcode ("inc", "b");
7446 freeAsmop (right, NULL, ic, TRUE);
7447 aopOp (left, ic, FALSE, FALSE);
7448 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7450 /* now move the left to the result if they are not the
7452 if (!sameRegs (AOP (left), AOP (result)) &&
7453 AOP_SIZE (result) > 1)
7456 size = AOP_SIZE (result);
7458 _startLazyDPSEvaluation ();
7461 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7462 if (*l == '@' && IS_AOP_PREG (result))
7465 emitcode ("mov", "a,%s", l);
7466 aopPut (AOP (result), "a", offset);
7469 aopPut (AOP (result), l, offset);
7472 _endLazyDPSEvaluation ();
7475 /* mov the highest order bit to OVR */
7476 tlbl = newiTempLabel (NULL);
7477 tlbl1 = newiTempLabel (NULL);
7479 size = AOP_SIZE (result);
7481 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7482 emitcode ("rlc", "a");
7483 emitcode ("mov", "ov,c");
7484 /* if it is only one byte then */
7487 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7489 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7490 emitcode ("", "%05d$:", tlbl->key + 100);
7491 emitcode ("mov", "c,ov");
7492 emitcode ("rrc", "a");
7493 emitcode ("", "%05d$:", tlbl1->key + 100);
7494 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7495 aopPut (AOP (result), "a", 0);
7499 reAdjustPreg (AOP (result));
7500 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7501 emitcode ("", "%05d$:", tlbl->key + 100);
7502 emitcode ("mov", "c,ov");
7503 _startLazyDPSEvaluation ();
7506 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7508 emitcode ("rrc", "a");
7509 aopPut (AOP (result), "a", offset--);
7511 _endLazyDPSEvaluation ();
7512 reAdjustPreg (AOP (result));
7513 emitcode ("", "%05d$:", tlbl1->key + 100);
7514 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7517 freeAsmop (left, NULL, ic, TRUE);
7518 freeAsmop (result, NULL, ic, TRUE);
7521 /*-----------------------------------------------------------------*/
7522 /* genRightShift - generate code for right shifting */
7523 /*-----------------------------------------------------------------*/
7525 genRightShift (iCode * ic)
7527 operand *right, *left, *result;
7531 symbol *tlbl, *tlbl1;
7533 D (emitcode (";", "genRightShift "););
7535 /* if signed then we do it the hard way preserve the
7536 sign bit moving it inwards */
7537 retype = getSpec (operandType (IC_RESULT (ic)));
7539 if (!SPEC_USIGN (retype))
7541 genSignedRightShift (ic);
7545 /* signed & unsigned types are treated the same : i.e. the
7546 signed is NOT propagated inwards : quoting from the
7547 ANSI - standard : "for E1 >> E2, is equivalent to division
7548 by 2**E2 if unsigned or if it has a non-negative value,
7549 otherwise the result is implementation defined ", MY definition
7550 is that the sign does not get propagated */
7552 right = IC_RIGHT (ic);
7553 left = IC_LEFT (ic);
7554 result = IC_RESULT (ic);
7556 aopOp (right, ic, FALSE, FALSE);
7558 #ifdef BETTER_LITERAL_SHIFT
7559 /* if the shift count is known then do it
7560 as efficiently as possible */
7561 if (AOP_TYPE (right) == AOP_LIT)
7563 if (genRightShiftLiteral (left, right, result, ic, 0))
7570 /* shift count is unknown then we have to form
7571 a loop get the loop count in B : Note: we take
7572 only the lower order byte since shifting
7573 more that 32 bits make no sense anyway, ( the
7574 largest size of an object can be only 32 bits ) */
7576 if (AOP_TYPE (right) == AOP_LIT)
7578 /* Really should be handled by genRightShiftLiteral,
7579 * but since I'm too lazy to fix that today, at least we can make
7580 * some small improvement.
7582 emitcode("mov", "b,#0x%02x",
7583 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7587 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7588 emitcode ("inc", "b");
7590 freeAsmop (right, NULL, ic, TRUE);
7591 aopOp (left, ic, FALSE, FALSE);
7592 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7594 /* now move the left to the result if they are not the
7596 if (!sameRegs (AOP (left), AOP (result)) &&
7597 AOP_SIZE (result) > 1)
7600 size = AOP_SIZE (result);
7602 _startLazyDPSEvaluation ();
7605 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7606 if (*l == '@' && IS_AOP_PREG (result))
7609 emitcode ("mov", "a,%s", l);
7610 aopPut (AOP (result), "a", offset);
7613 aopPut (AOP (result), l, offset);
7616 _endLazyDPSEvaluation ();
7619 tlbl = newiTempLabel (NULL);
7620 tlbl1 = newiTempLabel (NULL);
7621 size = AOP_SIZE (result);
7624 /* if it is only one byte then */
7627 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7629 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7630 emitcode ("", "%05d$:", tlbl->key + 100);
7632 emitcode ("rrc", "a");
7633 emitcode ("", "%05d$:", tlbl1->key + 100);
7634 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7635 aopPut (AOP (result), "a", 0);
7639 reAdjustPreg (AOP (result));
7640 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7641 emitcode ("", "%05d$:", tlbl->key + 100);
7643 _startLazyDPSEvaluation ();
7646 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7648 emitcode ("rrc", "a");
7649 aopPut (AOP (result), "a", offset--);
7651 _endLazyDPSEvaluation ();
7652 reAdjustPreg (AOP (result));
7654 emitcode ("", "%05d$:", tlbl1->key + 100);
7655 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7658 freeAsmop (left, NULL, ic, TRUE);
7659 freeAsmop (result, NULL, ic, TRUE);
7662 /*-----------------------------------------------------------------*/
7663 /* genUnpackBits - generates code for unpacking bits */
7664 /*-----------------------------------------------------------------*/
7666 genUnpackBits (operand * result, char *rname, int ptype)
7673 D (emitcode (";", "genUnpackBits ");
7676 etype = getSpec (operandType (result));
7678 /* read the first byte */
7684 emitcode ("mov", "a,@%s", rname);
7688 emitcode ("movx", "a,@%s", rname);
7692 emitcode ("movx", "a,@dptr");
7696 emitcode ("clr", "a");
7697 emitcode ("movc", "a", "@a+dptr");
7701 emitcode ("lcall", "__gptrget");
7705 /* if we have bitdisplacement then it fits */
7706 /* into this byte completely or if length is */
7707 /* less than a byte */
7708 if ((shCnt = SPEC_BSTR (etype)) ||
7709 (SPEC_BLEN (etype) <= 8))
7712 /* shift right acc */
7715 emitcode ("anl", "a,#0x%02x",
7716 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7717 aopPut (AOP (result), "a", offset);
7721 /* bit field did not fit in a byte */
7722 rlen = SPEC_BLEN (etype) - 8;
7723 aopPut (AOP (result), "a", offset++);
7732 emitcode ("inc", "%s", rname);
7733 emitcode ("mov", "a,@%s", rname);
7737 emitcode ("inc", "%s", rname);
7738 emitcode ("movx", "a,@%s", rname);
7742 emitcode ("inc", "dptr");
7743 emitcode ("movx", "a,@dptr");
7747 emitcode ("clr", "a");
7748 emitcode ("inc", "dptr");
7749 emitcode ("movc", "a", "@a+dptr");
7753 emitcode ("inc", "dptr");
7754 emitcode ("lcall", "__gptrget");
7759 /* if we are done */
7763 aopPut (AOP (result), "a", offset++);
7769 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7770 aopPut (AOP (result), "a", offset);
7777 /*-----------------------------------------------------------------*/
7778 /* genDataPointerGet - generates code when ptr offset is known */
7779 /*-----------------------------------------------------------------*/
7781 genDataPointerGet (operand * left,
7787 int size, offset = 0;
7788 aopOp (result, ic, TRUE, FALSE);
7790 /* get the string representation of the name */
7791 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7792 size = AOP_SIZE (result);
7793 _startLazyDPSEvaluation ();
7797 sprintf (buffer, "(%s + %d)", l + 1, offset);
7799 sprintf (buffer, "%s", l + 1);
7800 aopPut (AOP (result), buffer, offset++);
7802 _endLazyDPSEvaluation ();
7804 freeAsmop (left, NULL, ic, TRUE);
7805 freeAsmop (result, NULL, ic, TRUE);
7808 /*-----------------------------------------------------------------*/
7809 /* genNearPointerGet - emitcode for near pointer fetch */
7810 /*-----------------------------------------------------------------*/
7812 genNearPointerGet (operand * left,
7819 sym_link *rtype, *retype, *letype;
7820 sym_link *ltype = operandType (left);
7823 rtype = operandType (result);
7824 retype = getSpec (rtype);
7825 letype = getSpec (ltype);
7827 aopOp (left, ic, FALSE, FALSE);
7829 /* if left is rematerialisable and
7830 result is not bit variable type and
7831 the left is pointer to data space i.e
7832 lower 128 bytes of space */
7833 if (AOP_TYPE (left) == AOP_IMMD &&
7834 !IS_BITVAR (retype) &&
7835 !IS_BITVAR (letype) &&
7836 DCL_TYPE (ltype) == POINTER)
7838 genDataPointerGet (left, result, ic);
7842 /* if the value is already in a pointer register
7843 then don't need anything more */
7844 if (!AOP_INPREG (AOP (left)))
7846 /* otherwise get a free pointer register */
7848 preg = getFreePtr (ic, &aop, FALSE);
7849 emitcode ("mov", "%s,%s",
7851 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7855 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7857 freeAsmop (left, NULL, ic, TRUE);
7858 aopOp (result, ic, FALSE, FALSE);
7860 /* if bitfield then unpack the bits */
7861 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7862 genUnpackBits (result, rname, POINTER);
7865 /* we have can just get the values */
7866 int size = AOP_SIZE (result);
7871 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7874 emitcode ("mov", "a,@%s", rname);
7875 aopPut (AOP (result), "a", offset);
7879 sprintf (buffer, "@%s", rname);
7880 aopPut (AOP (result), buffer, offset);
7884 emitcode ("inc", "%s", rname);
7888 /* now some housekeeping stuff */
7891 /* we had to allocate for this iCode */
7892 freeAsmop (NULL, aop, ic, TRUE);
7896 /* we did not allocate which means left
7897 already in a pointer register, then
7898 if size > 0 && this could be used again
7899 we have to point it back to where it
7901 if (AOP_SIZE (result) > 1 &&
7902 !OP_SYMBOL (left)->remat &&
7903 (OP_SYMBOL (left)->liveTo > ic->seq ||
7906 int size = AOP_SIZE (result) - 1;
7908 emitcode ("dec", "%s", rname);
7913 freeAsmop (result, NULL, ic, TRUE);
7917 /*-----------------------------------------------------------------*/
7918 /* genPagedPointerGet - emitcode for paged pointer fetch */
7919 /*-----------------------------------------------------------------*/
7921 genPagedPointerGet (operand * left,
7928 sym_link *rtype, *retype, *letype;
7930 rtype = operandType (result);
7931 retype = getSpec (rtype);
7932 letype = getSpec (operandType (left));
7933 aopOp (left, ic, FALSE, FALSE);
7935 /* if the value is already in a pointer register
7936 then don't need anything more */
7937 if (!AOP_INPREG (AOP (left)))
7939 /* otherwise get a free pointer register */
7941 preg = getFreePtr (ic, &aop, FALSE);
7942 emitcode ("mov", "%s,%s",
7944 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7948 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7950 freeAsmop (left, NULL, ic, TRUE);
7951 aopOp (result, ic, FALSE, FALSE);
7953 /* if bitfield then unpack the bits */
7954 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7955 genUnpackBits (result, rname, PPOINTER);
7958 /* we have can just get the values */
7959 int size = AOP_SIZE (result);
7965 emitcode ("movx", "a,@%s", rname);
7966 aopPut (AOP (result), "a", offset);
7971 emitcode ("inc", "%s", rname);
7975 /* now some housekeeping stuff */
7978 /* we had to allocate for this iCode */
7979 freeAsmop (NULL, aop, ic, TRUE);
7983 /* we did not allocate which means left
7984 already in a pointer register, then
7985 if size > 0 && this could be used again
7986 we have to point it back to where it
7988 if (AOP_SIZE (result) > 1 &&
7989 !OP_SYMBOL (left)->remat &&
7990 (OP_SYMBOL (left)->liveTo > ic->seq ||
7993 int size = AOP_SIZE (result) - 1;
7995 emitcode ("dec", "%s", rname);
8000 freeAsmop (result, NULL, ic, TRUE);
8005 /*-----------------------------------------------------------------*/
8006 /* genFarPointerGet - gget value from far space */
8007 /*-----------------------------------------------------------------*/
8009 genFarPointerGet (operand * left,
8010 operand * result, iCode * ic)
8013 sym_link *retype = getSpec (operandType (result));
8014 sym_link *letype = getSpec (operandType (left));
8015 D (emitcode (";", "genFarPointerGet");
8018 aopOp (left, ic, FALSE, FALSE);
8020 /* if the operand is already in dptr
8021 then we do nothing else we move the value to dptr */
8022 if (AOP_TYPE (left) != AOP_STR)
8024 /* if this is remateriazable */
8025 if (AOP_TYPE (left) == AOP_IMMD)
8027 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8031 /* we need to get it byte by byte */
8032 _startLazyDPSEvaluation ();
8033 if (AOP_TYPE (left) != AOP_DPTR)
8035 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8036 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8037 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8041 /* We need to generate a load to DPTR indirect through DPTR. */
8042 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8044 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8045 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8046 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8047 emitcode ("pop", "dph");
8048 emitcode ("pop", "dpl");
8050 _endLazyDPSEvaluation ();
8053 /* so dptr know contains the address */
8054 freeAsmop (left, NULL, ic, TRUE);
8055 aopOp (result, ic, FALSE, TRUE);
8057 /* if bit then unpack */
8058 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8059 genUnpackBits (result, "dptr", FPOINTER);
8062 size = AOP_SIZE (result);
8065 _startLazyDPSEvaluation ();
8072 emitcode ("movx", "a,@dptr");
8074 emitcode ("inc", "dptr");
8076 aopPut (AOP (result), "a", offset++);
8078 _endLazyDPSEvaluation ();
8081 freeAsmop (result, NULL, ic, TRUE);
8084 /*-----------------------------------------------------------------*/
8085 /* emitcodePointerGet - gget value from code space */
8086 /*-----------------------------------------------------------------*/
8088 emitcodePointerGet (operand * left,
8089 operand * result, iCode * ic)
8092 sym_link *retype = getSpec (operandType (result));
8094 aopOp (left, ic, FALSE, FALSE);
8096 /* if the operand is already in dptr
8097 then we do nothing else we move the value to dptr */
8098 if (AOP_TYPE (left) != AOP_STR)
8100 /* if this is remateriazable */
8101 if (AOP_TYPE (left) == AOP_IMMD)
8103 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8106 { /* we need to get it byte by byte */
8107 _startLazyDPSEvaluation ();
8108 if (AOP_TYPE (left) != AOP_DPTR)
8110 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8111 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8112 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8116 /* We need to generate a load to DPTR indirect through DPTR. */
8117 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8119 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8120 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8121 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8122 emitcode ("pop", "dph");
8123 emitcode ("pop", "dpl");
8125 _endLazyDPSEvaluation ();
8128 /* so dptr know contains the address */
8129 freeAsmop (left, NULL, ic, TRUE);
8130 aopOp (result, ic, FALSE, TRUE);
8132 /* if bit then unpack */
8133 if (IS_BITVAR (retype))
8134 genUnpackBits (result, "dptr", CPOINTER);
8137 size = AOP_SIZE (result);
8140 _startLazyDPSEvaluation ();
8146 emitcode ("clr", "a");
8147 emitcode ("movc", "a,@a+dptr");
8149 emitcode ("inc", "dptr");
8150 aopPut (AOP (result), "a", offset++);
8152 _endLazyDPSEvaluation ();
8155 freeAsmop (result, NULL, ic, TRUE);
8158 /*-----------------------------------------------------------------*/
8159 /* genGenPointerGet - gget value from generic pointer space */
8160 /*-----------------------------------------------------------------*/
8162 genGenPointerGet (operand * left,
8163 operand * result, iCode * ic)
8166 sym_link *retype = getSpec (operandType (result));
8167 sym_link *letype = getSpec (operandType (left));
8169 D (emitcode (";", "genGenPointerGet "); );
8171 aopOp (left, ic, FALSE, TRUE);
8173 /* if the operand is already in dptr
8174 then we do nothing else we move the value to dptr */
8175 if (AOP_TYPE (left) != AOP_STR)
8177 /* if this is remateriazable */
8178 if (AOP_TYPE (left) == AOP_IMMD)
8180 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8181 emitcode ("mov", "b,#%d", pointerCode (retype));
8184 { /* we need to get it byte by byte */
8185 _startLazyDPSEvaluation ();
8186 if (AOP(left)->type==AOP_DPTR2) {
8188 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8191 emitcode ("mov", "dpl,%s", l);
8192 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8195 emitcode ("mov", "dph,%s", l);
8196 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8199 emitcode ("mov", "dpx,%s", l);
8200 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8202 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8203 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8204 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8205 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8207 _endLazyDPSEvaluation ();
8210 /* so dptr know contains the address */
8211 freeAsmop (left, NULL, ic, TRUE);
8212 aopOp (result, ic, FALSE, TRUE);
8214 /* if bit then unpack */
8215 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8216 genUnpackBits (result, "dptr", GPOINTER);
8219 size = AOP_SIZE (result);
8224 emitcode ("lcall", "__gptrget");
8225 aopPut (AOP (result), "a", offset++);
8227 emitcode ("inc", "dptr");
8231 freeAsmop (result, NULL, ic, TRUE);
8234 /*-----------------------------------------------------------------*/
8235 /* genPointerGet - generate code for pointer get */
8236 /*-----------------------------------------------------------------*/
8238 genPointerGet (iCode * ic)
8240 operand *left, *result;
8241 sym_link *type, *etype;
8244 D (emitcode (";", "genPointerGet ");
8247 left = IC_LEFT (ic);
8248 result = IC_RESULT (ic);
8250 /* depending on the type of pointer we need to
8251 move it to the correct pointer register */
8252 type = operandType (left);
8253 etype = getSpec (type);
8254 /* if left is of type of pointer then it is simple */
8255 if (IS_PTR (type) && !IS_FUNC (type->next))
8256 p_type = DCL_TYPE (type);
8259 /* we have to go by the storage class */
8260 p_type = PTR_TYPE (SPEC_OCLS (etype));
8263 /* now that we have the pointer type we assign
8264 the pointer values */
8270 genNearPointerGet (left, result, ic);
8274 genPagedPointerGet (left, result, ic);
8278 genFarPointerGet (left, result, ic);
8282 emitcodePointerGet (left, result, ic);
8286 genGenPointerGet (left, result, ic);
8292 /*-----------------------------------------------------------------*/
8293 /* genPackBits - generates code for packed bit storage */
8294 /*-----------------------------------------------------------------*/
8296 genPackBits (sym_link * etype,
8298 char *rname, int p_type)
8306 blen = SPEC_BLEN (etype);
8307 bstr = SPEC_BSTR (etype);
8309 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8312 /* if the bit lenth is less than or */
8313 /* it exactly fits a byte then */
8314 if (SPEC_BLEN (etype) <= 8)
8316 shCount = SPEC_BSTR (etype);
8318 /* shift left acc */
8321 if (SPEC_BLEN (etype) < 8)
8322 { /* if smaller than a byte */
8328 emitcode ("mov", "b,a");
8329 emitcode ("mov", "a,@%s", rname);
8333 emitcode ("mov", "b,a");
8334 emitcode ("movx", "a,@dptr");
8338 emitcode ("push", "b");
8339 emitcode ("push", "acc");
8340 emitcode ("lcall", "__gptrget");
8341 emitcode ("pop", "b");
8345 emitcode ("anl", "a,#0x%02x", (unsigned char)
8346 ((unsigned char) (0xFF << (blen + bstr)) |
8347 (unsigned char) (0xFF >> (8 - bstr))));
8348 emitcode ("orl", "a,b");
8349 if (p_type == GPOINTER)
8350 emitcode ("pop", "b");
8357 emitcode ("mov", "@%s,a", rname);
8361 emitcode ("movx", "@dptr,a");
8365 emitcode ("lcall", "__gptrput");
8370 if (SPEC_BLEN (etype) <= 8)
8373 emitcode ("inc", "%s", rname);
8374 rLen = SPEC_BLEN (etype);
8376 /* now generate for lengths greater than one byte */
8380 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8392 emitcode ("mov", "@%s,a", rname);
8395 emitcode ("mov", "@%s,%s", rname, l);
8400 emitcode ("movx", "@dptr,a");
8405 emitcode ("lcall", "__gptrput");
8408 emitcode ("inc", "%s", rname);
8413 /* last last was not complete */
8416 /* save the byte & read byte */
8420 emitcode ("mov", "b,a");
8421 emitcode ("mov", "a,@%s", rname);
8425 emitcode ("mov", "b,a");
8426 emitcode ("movx", "a,@dptr");
8430 emitcode ("push", "b");
8431 emitcode ("push", "acc");
8432 emitcode ("lcall", "__gptrget");
8433 emitcode ("pop", "b");
8437 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8438 emitcode ("orl", "a,b");
8441 if (p_type == GPOINTER)
8442 emitcode ("pop", "b");
8448 emitcode ("mov", "@%s,a", rname);
8452 emitcode ("movx", "@dptr,a");
8456 emitcode ("lcall", "__gptrput");
8460 /*-----------------------------------------------------------------*/
8461 /* genDataPointerSet - remat pointer to data space */
8462 /*-----------------------------------------------------------------*/
8464 genDataPointerSet (operand * right,
8468 int size, offset = 0;
8469 char *l, buffer[256];
8471 aopOp (right, ic, FALSE, FALSE);
8473 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8474 size = AOP_SIZE (right);
8478 sprintf (buffer, "(%s + %d)", l + 1, offset);
8480 sprintf (buffer, "%s", l + 1);
8481 emitcode ("mov", "%s,%s", buffer,
8482 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8485 freeAsmop (right, NULL, ic, TRUE);
8486 freeAsmop (result, NULL, ic, TRUE);
8489 /*-----------------------------------------------------------------*/
8490 /* genNearPointerSet - emitcode for near pointer put */
8491 /*-----------------------------------------------------------------*/
8493 genNearPointerSet (operand * right,
8500 sym_link *retype, *letype;
8501 sym_link *ptype = operandType (result);
8503 retype = getSpec (operandType (right));
8504 letype = getSpec (ptype);
8506 aopOp (result, ic, FALSE, FALSE);
8508 /* if the result is rematerializable &
8509 in data space & not a bit variable */
8510 if (AOP_TYPE (result) == AOP_IMMD &&
8511 DCL_TYPE (ptype) == POINTER &&
8512 !IS_BITVAR (retype) &&
8513 !IS_BITVAR (letype))
8515 genDataPointerSet (right, result, ic);
8519 /* if the value is already in a pointer register
8520 then don't need anything more */
8521 if (!AOP_INPREG (AOP (result)))
8523 /* otherwise get a free pointer register */
8525 preg = getFreePtr (ic, &aop, FALSE);
8526 emitcode ("mov", "%s,%s",
8528 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8532 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8534 freeAsmop (result, NULL, ic, TRUE);
8535 aopOp (right, ic, FALSE, FALSE);
8537 /* if bitfield then unpack the bits */
8538 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8539 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8542 /* we have can just get the values */
8543 int size = AOP_SIZE (right);
8548 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8552 emitcode ("mov", "@%s,a", rname);
8555 emitcode ("mov", "@%s,%s", rname, l);
8557 emitcode ("inc", "%s", rname);
8562 /* now some housekeeping stuff */
8565 /* we had to allocate for this iCode */
8566 freeAsmop (NULL, aop, ic, TRUE);
8570 /* we did not allocate which means left
8571 already in a pointer register, then
8572 if size > 0 && this could be used again
8573 we have to point it back to where it
8575 if (AOP_SIZE (right) > 1 &&
8576 !OP_SYMBOL (result)->remat &&
8577 (OP_SYMBOL (result)->liveTo > ic->seq ||
8580 int size = AOP_SIZE (right) - 1;
8582 emitcode ("dec", "%s", rname);
8587 freeAsmop (right, NULL, ic, TRUE);
8592 /*-----------------------------------------------------------------*/
8593 /* genPagedPointerSet - emitcode for Paged pointer put */
8594 /*-----------------------------------------------------------------*/
8596 genPagedPointerSet (operand * right,
8603 sym_link *retype, *letype;
8605 retype = getSpec (operandType (right));
8606 letype = getSpec (operandType (result));
8608 aopOp (result, ic, FALSE, FALSE);
8610 /* if the value is already in a pointer register
8611 then don't need anything more */
8612 if (!AOP_INPREG (AOP (result)))
8614 /* otherwise get a free pointer register */
8616 preg = getFreePtr (ic, &aop, FALSE);
8617 emitcode ("mov", "%s,%s",
8619 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8623 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8625 freeAsmop (result, NULL, ic, TRUE);
8626 aopOp (right, ic, FALSE, FALSE);
8628 /* if bitfield then unpack the bits */
8629 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8630 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8633 /* we have can just get the values */
8634 int size = AOP_SIZE (right);
8639 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8642 emitcode ("movx", "@%s,a", rname);
8645 emitcode ("inc", "%s", rname);
8651 /* now some housekeeping stuff */
8654 /* we had to allocate for this iCode */
8655 freeAsmop (NULL, aop, ic, TRUE);
8659 /* we did not allocate which means left
8660 already in a pointer register, then
8661 if size > 0 && this could be used again
8662 we have to point it back to where it
8664 if (AOP_SIZE (right) > 1 &&
8665 !OP_SYMBOL (result)->remat &&
8666 (OP_SYMBOL (result)->liveTo > ic->seq ||
8669 int size = AOP_SIZE (right) - 1;
8671 emitcode ("dec", "%s", rname);
8676 freeAsmop (right, NULL, ic, TRUE);
8681 /*-----------------------------------------------------------------*/
8682 /* genFarPointerSet - set value from far space */
8683 /*-----------------------------------------------------------------*/
8685 genFarPointerSet (operand * right,
8686 operand * result, iCode * ic)
8689 sym_link *retype = getSpec (operandType (right));
8690 sym_link *letype = getSpec (operandType (result));
8692 aopOp (result, ic, FALSE, FALSE);
8694 /* if the operand is already in dptr
8695 then we do nothing else we move the value to dptr */
8696 if (AOP_TYPE (result) != AOP_STR)
8698 /* if this is remateriazable */
8699 if (AOP_TYPE (result) == AOP_IMMD)
8700 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8703 /* we need to get it byte by byte */
8704 _startLazyDPSEvaluation ();
8705 if (AOP_TYPE (result) != AOP_DPTR)
8707 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8708 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8709 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8713 /* We need to generate a load to DPTR indirect through DPTR. */
8714 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8716 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8717 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8718 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8719 emitcode ("pop", "dph");
8720 emitcode ("pop", "dpl");
8722 _endLazyDPSEvaluation ();
8725 /* so dptr know contains the address */
8726 freeAsmop (result, NULL, ic, TRUE);
8727 aopOp (right, ic, FALSE, TRUE);
8729 /* if bit then unpack */
8730 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8731 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8734 size = AOP_SIZE (right);
8737 _startLazyDPSEvaluation ();
8740 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8746 emitcode ("movx", "@dptr,a");
8748 emitcode ("inc", "dptr");
8750 _endLazyDPSEvaluation ();
8753 freeAsmop (right, NULL, ic, TRUE);
8756 /*-----------------------------------------------------------------*/
8757 /* genGenPointerSet - set value from generic pointer space */
8758 /*-----------------------------------------------------------------*/
8760 genGenPointerSet (operand * right,
8761 operand * result, iCode * ic)
8764 sym_link *retype = getSpec (operandType (right));
8765 sym_link *letype = getSpec (operandType (result));
8767 aopOp (result, ic, FALSE, TRUE);
8769 /* if the operand is already in dptr
8770 then we do nothing else we move the value to dptr */
8771 if (AOP_TYPE (result) != AOP_STR)
8773 _startLazyDPSEvaluation ();
8774 /* if this is remateriazable */
8775 if (AOP_TYPE (result) == AOP_IMMD)
8777 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8778 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8781 { /* we need to get it byte by byte */
8782 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8783 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8784 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8785 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8787 _endLazyDPSEvaluation ();
8789 /* so dptr know contains the address */
8790 freeAsmop (result, NULL, ic, TRUE);
8791 aopOp (right, ic, FALSE, TRUE);
8793 /* if bit then unpack */
8794 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8795 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8798 size = AOP_SIZE (right);
8801 _startLazyDPSEvaluation ();
8804 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8810 emitcode ("lcall", "__gptrput");
8812 emitcode ("inc", "dptr");
8814 _endLazyDPSEvaluation ();
8817 freeAsmop (right, NULL, ic, TRUE);
8820 /*-----------------------------------------------------------------*/
8821 /* genPointerSet - stores the value into a pointer location */
8822 /*-----------------------------------------------------------------*/
8824 genPointerSet (iCode * ic)
8826 operand *right, *result;
8827 sym_link *type, *etype;
8830 D (emitcode (";", "genPointerSet ");
8833 right = IC_RIGHT (ic);
8834 result = IC_RESULT (ic);
8836 /* depending on the type of pointer we need to
8837 move it to the correct pointer register */
8838 type = operandType (result);
8839 etype = getSpec (type);
8840 /* if left is of type of pointer then it is simple */
8841 if (IS_PTR (type) && !IS_FUNC (type->next))
8843 p_type = DCL_TYPE (type);
8847 /* we have to go by the storage class */
8848 p_type = PTR_TYPE (SPEC_OCLS (etype));
8851 /* now that we have the pointer type we assign
8852 the pointer values */
8858 genNearPointerSet (right, result, ic);
8862 genPagedPointerSet (right, result, ic);
8866 genFarPointerSet (right, result, ic);
8870 genGenPointerSet (right, result, ic);
8876 /*-----------------------------------------------------------------*/
8877 /* genIfx - generate code for Ifx statement */
8878 /*-----------------------------------------------------------------*/
8880 genIfx (iCode * ic, iCode * popIc)
8882 operand *cond = IC_COND (ic);
8885 D (emitcode (";", "genIfx "););
8887 aopOp (cond, ic, FALSE, FALSE);
8889 /* get the value into acc */
8890 if (AOP_TYPE (cond) != AOP_CRY)
8894 /* the result is now in the accumulator */
8895 freeAsmop (cond, NULL, ic, TRUE);
8897 /* if there was something to be popped then do it */
8901 /* if the condition is a bit variable */
8902 if (isbit && IS_ITEMP (cond) &&
8904 genIfxJump (ic, SPIL_LOC (cond)->rname);
8905 else if (isbit && !IS_ITEMP (cond))
8906 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8908 genIfxJump (ic, "a");
8913 /*-----------------------------------------------------------------*/
8914 /* genAddrOf - generates code for address of */
8915 /*-----------------------------------------------------------------*/
8917 genAddrOf (iCode * ic)
8919 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8922 D (emitcode (";", "genAddrOf ");
8925 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8927 /* if the operand is on the stack then we
8928 need to get the stack offset of this
8932 /* if it has an offset then we need to compute
8936 emitcode ("mov", "a,_bp");
8937 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8938 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8942 /* we can just move _bp */
8943 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8945 /* fill the result with zero */
8946 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8949 if (options.stack10bit && size < (FPTRSIZE - 1))
8952 "*** warning: pointer to stack var truncated.\n");
8959 if (options.stack10bit && offset == 2)
8961 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8965 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8972 /* object not on stack then we need the name */
8973 size = AOP_SIZE (IC_RESULT (ic));
8978 char s[SDCC_NAME_MAX];
8980 sprintf (s, "#(%s >> %d)",
8984 sprintf (s, "#%s", sym->rname);
8985 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8989 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8993 /*-----------------------------------------------------------------*/
8994 /* genFarFarAssign - assignment when both are in far space */
8995 /*-----------------------------------------------------------------*/
8997 genFarFarAssign (operand * result, operand * right, iCode * ic)
8999 int size = AOP_SIZE (right);
9001 symbol *rSym = NULL;
9005 /* quick & easy case. */
9006 D(emitcode(";","genFarFarAssign (1 byte case)"););
9007 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9008 freeAsmop (right, NULL, ic, FALSE);
9009 /* now assign DPTR to result */
9011 aopOp(result, ic, FALSE, FALSE);
9013 aopPut(AOP(result), "a", 0);
9014 freeAsmop(result, NULL, ic, FALSE);
9018 /* See if we've got an underlying symbol to abuse. */
9019 if (IS_SYMOP(result) && OP_SYMBOL(result))
9021 if (IS_TRUE_SYMOP(result))
9023 rSym = OP_SYMBOL(result);
9025 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9027 rSym = OP_SYMBOL(result)->usl.spillLoc;
9031 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9033 /* We can use the '390 auto-toggle feature to good effect here. */
9035 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9036 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9037 emitcode ("mov", "dptr,#%s", rSym->rname);
9038 /* DP2 = result, DP1 = right, DP1 is current. */
9041 emitcode("movx", "a,@dptr");
9042 emitcode("movx", "@dptr,a");
9045 emitcode("inc", "dptr");
9046 emitcode("inc", "dptr");
9049 emitcode("mov", "dps, #0");
9050 freeAsmop (right, NULL, ic, FALSE);
9054 D (emitcode (";", "genFarFarAssign"););
9055 aopOp (result, ic, TRUE, TRUE);
9057 _startLazyDPSEvaluation ();
9061 aopPut (AOP (result),
9062 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9065 _endLazyDPSEvaluation ();
9066 freeAsmop (result, NULL, ic, FALSE);
9067 freeAsmop (right, NULL, ic, FALSE);
9071 /*-----------------------------------------------------------------*/
9072 /* genAssign - generate code for assignment */
9073 /*-----------------------------------------------------------------*/
9075 genAssign (iCode * ic)
9077 operand *result, *right;
9079 unsigned long lit = 0L;
9081 D (emitcode (";", "genAssign ");
9084 result = IC_RESULT (ic);
9085 right = IC_RIGHT (ic);
9087 /* if they are the same */
9088 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9091 aopOp (right, ic, FALSE, FALSE);
9093 emitcode (";", "genAssign: resultIsFar = %s",
9094 isOperandInFarSpace (result) ?
9097 /* special case both in far space */
9098 if ((AOP_TYPE (right) == AOP_DPTR ||
9099 AOP_TYPE (right) == AOP_DPTR2) &&
9100 /* IS_TRUE_SYMOP(result) && */
9101 isOperandInFarSpace (result))
9103 genFarFarAssign (result, right, ic);
9107 aopOp (result, ic, TRUE, FALSE);
9109 /* if they are the same registers */
9110 if (sameRegs (AOP (right), AOP (result)))
9113 /* if the result is a bit */
9114 if (AOP_TYPE (result) == AOP_CRY)
9117 /* if the right size is a literal then
9118 we know what the value is */
9119 if (AOP_TYPE (right) == AOP_LIT)
9121 if (((int) operandLitValue (right)))
9122 aopPut (AOP (result), one, 0);
9124 aopPut (AOP (result), zero, 0);
9128 /* the right is also a bit variable */
9129 if (AOP_TYPE (right) == AOP_CRY)
9131 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9132 aopPut (AOP (result), "c", 0);
9138 aopPut (AOP (result), "a", 0);
9142 /* bit variables done */
9144 size = AOP_SIZE (result);
9146 if (AOP_TYPE (right) == AOP_LIT)
9147 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9150 (AOP_TYPE (result) != AOP_REG) &&
9151 (AOP_TYPE (right) == AOP_LIT) &&
9152 !IS_FLOAT (operandType (right)))
9154 _startLazyDPSEvaluation ();
9155 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9157 aopPut (AOP (result),
9158 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9163 /* And now fill the rest with zeros. */
9166 emitcode ("clr", "a");
9170 aopPut (AOP (result), "a", offset++);
9172 _endLazyDPSEvaluation ();
9176 _startLazyDPSEvaluation ();
9179 aopPut (AOP (result),
9180 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9184 _endLazyDPSEvaluation ();
9188 freeAsmop (right, NULL, ic, FALSE);
9189 freeAsmop (result, NULL, ic, TRUE);
9192 /*-----------------------------------------------------------------*/
9193 /* genJumpTab - generates code for jump table */
9194 /*-----------------------------------------------------------------*/
9196 genJumpTab (iCode * ic)
9201 D (emitcode (";", "genJumpTab ");
9204 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9205 /* get the condition into accumulator */
9206 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9208 /* multiply by four! */
9209 emitcode ("add", "a,acc");
9210 emitcode ("add", "a,acc");
9211 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9213 jtab = newiTempLabel (NULL);
9214 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9215 emitcode ("jmp", "@a+dptr");
9216 emitcode ("", "%05d$:", jtab->key + 100);
9217 /* now generate the jump labels */
9218 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9219 jtab = setNextItem (IC_JTLABELS (ic)))
9220 emitcode ("ljmp", "%05d$", jtab->key + 100);
9224 /*-----------------------------------------------------------------*/
9225 /* genCast - gen code for casting */
9226 /*-----------------------------------------------------------------*/
9228 genCast (iCode * ic)
9230 operand *result = IC_RESULT (ic);
9231 sym_link *ctype = operandType (IC_LEFT (ic));
9232 sym_link *rtype = operandType (IC_RIGHT (ic));
9233 operand *right = IC_RIGHT (ic);
9236 D (emitcode (";", "genCast ");
9239 /* if they are equivalent then do nothing */
9240 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9243 aopOp (right, ic, FALSE, FALSE);
9244 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9246 /* if the result is a bit */
9247 if (AOP_TYPE (result) == AOP_CRY)
9249 /* if the right size is a literal then
9250 we know what the value is */
9251 if (AOP_TYPE (right) == AOP_LIT)
9253 if (((int) operandLitValue (right)))
9254 aopPut (AOP (result), one, 0);
9256 aopPut (AOP (result), zero, 0);
9261 /* the right is also a bit variable */
9262 if (AOP_TYPE (right) == AOP_CRY)
9264 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9265 aopPut (AOP (result), "c", 0);
9271 aopPut (AOP (result), "a", 0);
9275 /* if they are the same size : or less */
9276 if (AOP_SIZE (result) <= AOP_SIZE (right))
9279 /* if they are in the same place */
9280 if (sameRegs (AOP (right), AOP (result)))
9283 /* if they in different places then copy */
9284 size = AOP_SIZE (result);
9286 _startLazyDPSEvaluation ();
9289 aopPut (AOP (result),
9290 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9294 _endLazyDPSEvaluation ();
9299 /* if the result is of type pointer */
9304 sym_link *type = operandType (right);
9306 /* pointer to generic pointer */
9307 if (IS_GENPTR (ctype))
9313 p_type = DCL_TYPE (type);
9317 #if OLD_CAST_BEHAVIOR
9318 /* KV: we are converting a non-pointer type to
9319 * a generic pointer. This (ifdef'd out) code
9320 * says that the resulting generic pointer
9321 * should have the same class as the storage
9322 * location of the non-pointer variable.
9324 * For example, converting an int (which happens
9325 * to be stored in DATA space) to a pointer results
9326 * in a DATA generic pointer; if the original int
9327 * in XDATA space, so will be the resulting pointer.
9329 * I don't like that behavior, and thus this change:
9330 * all such conversions will be forced to XDATA and
9331 * throw a warning. If you want some non-XDATA
9332 * type, or you want to suppress the warning, you
9333 * must go through an intermediate cast, like so:
9335 * char _generic *gp = (char _xdata *)(intVar);
9337 sym_link *etype = getSpec (type);
9339 /* we have to go by the storage class */
9340 if (SPEC_OCLS (etype) != generic)
9342 p_type = PTR_TYPE (SPEC_OCLS (etype));
9347 /* Converting unknown class (i.e. register variable)
9348 * to generic pointer. This is not good, but
9349 * we'll make a guess (and throw a warning).
9352 werror (W_INT_TO_GEN_PTR_CAST);
9356 /* the first two bytes are known */
9357 size = GPTRSIZE - 1;
9359 _startLazyDPSEvaluation ();
9362 aopPut (AOP (result),
9363 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9367 _endLazyDPSEvaluation ();
9369 /* the last byte depending on type */
9387 /* this should never happen */
9388 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9389 "got unknown pointer type");
9392 aopPut (AOP (result), l, GPTRSIZE - 1);
9396 /* just copy the pointers */
9397 size = AOP_SIZE (result);
9399 _startLazyDPSEvaluation ();
9402 aopPut (AOP (result),
9403 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9407 _endLazyDPSEvaluation ();
9411 /* so we now know that the size of destination is greater
9412 than the size of the source */
9413 /* we move to result for the size of source */
9414 size = AOP_SIZE (right);
9416 _startLazyDPSEvaluation ();
9419 aopPut (AOP (result),
9420 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9424 _endLazyDPSEvaluation ();
9426 /* now depending on the sign of the source && destination */
9427 size = AOP_SIZE (result) - AOP_SIZE (right);
9428 /* if unsigned or not an integral type */
9429 /* also, if the source is a bit, we don't need to sign extend, because
9430 * it can't possibly have set the sign bit.
9432 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9436 aopPut (AOP (result), zero, offset++);
9441 /* we need to extend the sign :{ */
9442 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9443 FALSE, FALSE, TRUE);
9445 emitcode ("rlc", "a");
9446 emitcode ("subb", "a,acc");
9448 aopPut (AOP (result), "a", offset++);
9451 /* we are done hurray !!!! */
9454 freeAsmop (right, NULL, ic, TRUE);
9455 freeAsmop (result, NULL, ic, TRUE);
9459 /*-----------------------------------------------------------------*/
9460 /* genDjnz - generate decrement & jump if not zero instrucion */
9461 /*-----------------------------------------------------------------*/
9463 genDjnz (iCode * ic, iCode * ifx)
9469 /* if the if condition has a false label
9470 then we cannot save */
9474 /* if the minus is not of the form
9476 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9477 !IS_OP_LITERAL (IC_RIGHT (ic)))
9480 if (operandLitValue (IC_RIGHT (ic)) != 1)
9483 /* if the size of this greater than one then no
9485 if (getSize (operandType (IC_RESULT (ic))) > 1)
9488 /* otherwise we can save BIG */
9489 D(emitcode(";", "genDjnz"););
9491 lbl = newiTempLabel (NULL);
9492 lbl1 = newiTempLabel (NULL);
9494 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9496 if (AOP_NEEDSACC(IC_RESULT(ic)))
9498 /* If the result is accessed indirectly via
9499 * the accumulator, we must explicitly write
9500 * it back after the decrement.
9502 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9504 if (strcmp(rByte, "a"))
9506 /* Something is hopelessly wrong */
9507 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9508 __FILE__, __LINE__);
9509 /* We can just give up; the generated code will be inefficient,
9512 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9515 emitcode ("dec", "%s", rByte);
9516 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9517 emitcode ("jnz", "%05d$", lbl->key + 100);
9519 else if (IS_AOP_PREG (IC_RESULT (ic)))
9521 emitcode ("dec", "%s",
9522 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9523 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9524 emitcode ("jnz", "%05d$", lbl->key + 100);
9528 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9531 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9532 emitcode ("", "%05d$:", lbl->key + 100);
9533 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9534 emitcode ("", "%05d$:", lbl1->key + 100);
9536 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9541 /*-----------------------------------------------------------------*/
9542 /* genReceive - generate code for a receive iCode */
9543 /*-----------------------------------------------------------------*/
9545 genReceive (iCode * ic)
9548 D (emitcode (";", "genReceive ");
9551 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9552 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9553 IS_TRUE_SYMOP (IC_RESULT (ic))))
9555 int size = getSize (operandType (IC_RESULT (ic)));
9556 int offset = fReturnSizeDS390 - size;
9559 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9560 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9563 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9564 size = AOP_SIZE (IC_RESULT (ic));
9568 emitcode ("pop", "acc");
9569 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9576 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9578 assignResultValue (IC_RESULT (ic));
9581 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9584 /*-----------------------------------------------------------------*/
9585 /* gen390Code - generate code for Dallas 390 based controllers */
9586 /*-----------------------------------------------------------------*/
9588 gen390Code (iCode * lic)
9593 lineHead = lineCurr = NULL;
9597 /* print the allocation information */
9599 printAllocInfo (currFunc, codeOutFile);
9601 /* if debug information required */
9602 if (options.debug && currFunc)
9604 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9606 if (IS_STATIC (currFunc->etype))
9607 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9609 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9612 /* stack pointer name */
9613 if (options.useXstack)
9619 for (ic = lic; ic; ic = ic->next)
9622 if (cln != ic->lineno)
9627 emitcode ("", "C$%s$%d$%d$%d ==.",
9628 FileBaseName (ic->filename), ic->lineno,
9629 ic->level, ic->block);
9632 emitcode (";", "%s %d", ic->filename, ic->lineno);
9635 /* if the result is marked as
9636 spilt and rematerializable or code for
9637 this has already been generated then
9639 if (resultRemat (ic) || ic->generated)
9642 /* depending on the operation */
9662 /* IPOP happens only when trying to restore a
9663 spilt live range, if there is an ifx statement
9664 following this pop then the if statement might
9665 be using some of the registers being popped which
9666 would destory the contents of the register so
9667 we need to check for this condition and handle it */
9669 ic->next->op == IFX &&
9670 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9671 genIfx (ic->next, ic);
9689 genEndFunction (ic);
9709 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9726 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9730 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9737 /* note these two are xlated by algebraic equivalence
9738 during parsing SDCC.y */
9739 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9740 "got '>=' or '<=' shouldn't have come here");
9744 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9756 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9760 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9764 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9791 case GET_VALUE_AT_ADDRESS:
9796 if (POINTER_SET (ic))
9823 addSet (&_G.sendSet, ic);
9832 /* now we are ready to call the
9833 peep hole optimizer */
9834 if (!options.nopeep)
9835 peepHole (&lineHead);
9837 /* now do the actual printing */
9838 printLine (lineHead, codeOutFile);