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)
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 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3354 emitcode ("add", "a,%s",
3355 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3357 emitcode ("addc", "a,%s",
3358 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3362 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3366 emitcode ("push", "acc");
3370 _endLazyDPSEvaluation ();
3374 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3376 size = getDataSize (IC_LEFT (ic));
3377 rSize = getDataSize (IC_RESULT (ic));
3379 ADJUST_PUSHED_RESULT(size, rSize);
3381 _startLazyDPSEvaluation ();
3384 emitcode ("pop", "acc");
3385 aopPut (AOP (IC_RESULT (ic)), "a", size);
3387 _endLazyDPSEvaluation ();
3390 adjustArithmeticResult (ic);
3393 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3394 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3395 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3398 /*-----------------------------------------------------------------*/
3399 /* genMinusDec :- does subtraction with deccrement if possible */
3400 /*-----------------------------------------------------------------*/
3402 genMinusDec (iCode * ic)
3404 unsigned int icount;
3405 unsigned int size = getDataSize (IC_RESULT (ic));
3407 /* will try to generate an increment */
3408 /* if the right side is not a literal
3410 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3413 /* if the literal value of the right hand side
3414 is greater than 4 then it is not worth it */
3415 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3418 /* if decrement 16 bits in register */
3419 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3420 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3421 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3429 /* If the next instruction is a goto and the goto target
3430 * is <= 5 instructions previous to this, we can generate
3431 * jumps straight to that target.
3433 if (ic->next && ic->next->op == GOTO
3434 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3437 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3438 tlbl = IC_LABEL (ic->next);
3443 tlbl = newiTempLabel (NULL);
3447 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3448 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3449 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3450 IS_AOP_PREG (IC_RESULT (ic)))
3451 emitcode ("cjne", "%s,#0xff,%05d$"
3452 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3456 emitcode ("mov", "a,#0xff");
3457 emitcode ("cjne", "a,%s,%05d$"
3458 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3461 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3464 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3465 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3466 IS_AOP_PREG (IC_RESULT (ic)))
3467 emitcode ("cjne", "%s,#0xff,%05d$"
3468 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3472 emitcode ("cjne", "a,%s,%05d$"
3473 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3476 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3480 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3481 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3482 IS_AOP_PREG (IC_RESULT (ic)))
3483 emitcode ("cjne", "%s,#0xff,%05d$"
3484 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3488 emitcode ("cjne", "a,%s,%05d$"
3489 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3492 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3496 emitcode ("", "%05d$:", tlbl->key + 100);
3501 /* if the sizes are greater than 1 then we cannot */
3502 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3503 AOP_SIZE (IC_LEFT (ic)) > 1)
3506 /* we can if the aops of the left & result match or
3507 if they are in registers and the registers are the
3510 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3511 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3512 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3515 _startLazyDPSEvaluation ();
3518 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3520 _endLazyDPSEvaluation ();
3528 /*-----------------------------------------------------------------*/
3529 /* addSign - complete with sign */
3530 /*-----------------------------------------------------------------*/
3532 addSign (operand * result, int offset, int sign)
3534 int size = (getDataSize (result) - offset);
3537 _startLazyDPSEvaluation();
3540 emitcode ("rlc", "a");
3541 emitcode ("subb", "a,acc");
3544 aopPut (AOP (result), "a", offset++);
3551 aopPut (AOP (result), zero, offset++);
3554 _endLazyDPSEvaluation();
3558 /*-----------------------------------------------------------------*/
3559 /* genMinusBits - generates code for subtraction of two bits */
3560 /*-----------------------------------------------------------------*/
3562 genMinusBits (iCode * ic)
3564 symbol *lbl = newiTempLabel (NULL);
3566 D (emitcode (";", "genMinusBits "););
3568 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3570 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3571 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3572 emitcode ("cpl", "c");
3573 emitcode ("", "%05d$:", (lbl->key + 100));
3574 outBitC (IC_RESULT (ic));
3578 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3579 emitcode ("subb", "a,acc");
3580 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3581 emitcode ("inc", "a");
3582 emitcode ("", "%05d$:", (lbl->key + 100));
3583 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3584 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3588 /*-----------------------------------------------------------------*/
3589 /* genMinus - generates code for subtraction */
3590 /*-----------------------------------------------------------------*/
3592 genMinus (iCode * ic)
3594 int size, offset = 0;
3596 unsigned long lit = 0L;
3597 bool pushResult = FALSE;
3599 D (emitcode (";", "genMinus "););
3601 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3602 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3603 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3604 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3610 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3612 /* special cases :- */
3613 /* if both left & right are in bit space */
3614 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3615 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3621 /* if I can do an decrement instead
3622 of subtract then GOOD for ME */
3623 if (genMinusDec (ic) == TRUE)
3628 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3630 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3636 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3641 /* if literal, add a,#-lit, else normal subb */
3642 _startLazyDPSEvaluation ();
3645 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3646 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3647 emitcode ("subb", "a,%s",
3648 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3651 /* first add without previous c */
3653 emitcode ("add", "a,#0x%02x",
3654 (unsigned int) (lit & 0x0FFL));
3656 emitcode ("addc", "a,#0x%02x",
3657 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3662 emitcode ("push", "acc");
3666 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3670 _endLazyDPSEvaluation ();
3674 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3676 size = getDataSize (IC_LEFT (ic));
3677 rSize = getDataSize (IC_RESULT (ic));
3679 ADJUST_PUSHED_RESULT(size, rSize);
3681 _startLazyDPSEvaluation ();
3684 emitcode ("pop", "acc");
3685 aopPut (AOP (IC_RESULT (ic)), "a", size);
3687 _endLazyDPSEvaluation ();
3690 adjustArithmeticResult (ic);
3693 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3694 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3695 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3699 /*-----------------------------------------------------------------*/
3700 /* genMultbits :- multiplication of bits */
3701 /*-----------------------------------------------------------------*/
3703 genMultbits (operand * left,
3707 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3708 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3713 /*-----------------------------------------------------------------*/
3714 /* genMultOneByte : 8*8=8/16 bit multiplication */
3715 /*-----------------------------------------------------------------*/
3717 genMultOneByte (operand * left,
3721 sym_link *opetype = operandType (result);
3723 int size=AOP_SIZE(result);
3725 if (size<1 || size>2) {
3726 // this should never happen
3727 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3728 AOP_SIZE(result), __FILE__, lineno);
3732 /* (if two literals: the value is computed before) */
3733 /* if one literal, literal on the right */
3734 if (AOP_TYPE (left) == AOP_LIT)
3739 emitcode (";", "swapped left and right");
3742 if (SPEC_USIGN(opetype)
3743 // ignore the sign of left and right, what else can we do?
3744 || (SPEC_USIGN(operandType(left)) &&
3745 SPEC_USIGN(operandType(right)))) {
3746 // just an unsigned 8*8=8/16 multiply
3747 //emitcode (";","unsigned");
3748 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3749 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3750 emitcode ("mul", "ab");
3751 aopPut (AOP (result), "a", 0);
3753 aopPut (AOP (result), "b", 1);
3758 // we have to do a signed multiply
3760 emitcode (";", "signed");
3761 emitcode ("clr", "F0"); // reset sign flag
3762 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3763 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3765 lbl=newiTempLabel(NULL);
3766 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3767 // left side is negative, 8-bit two's complement, this fails for -128
3768 emitcode ("setb", "F0"); // set sign flag
3769 emitcode ("cpl", "a");
3770 emitcode ("inc", "a");
3772 emitcode ("", "%05d$:", lbl->key+100);
3773 emitcode ("xch", "a,b");
3776 if (AOP_TYPE(right)==AOP_LIT) {
3777 /* AND literal negative */
3778 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3779 // two's complement for literal<0
3780 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3781 emitcode ("cpl", "a");
3782 emitcode ("inc", "a");
3785 lbl=newiTempLabel(NULL);
3786 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3787 // right side is negative, 8-bit two's complement
3788 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3789 emitcode ("cpl", "a");
3790 emitcode ("inc", "a");
3791 emitcode ("", "%05d$:", lbl->key+100);
3793 emitcode ("mul", "ab");
3795 lbl=newiTempLabel(NULL);
3796 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3797 // only ONE op was negative, we have to do a 8/16-bit two's complement
3798 emitcode ("cpl", "a"); // lsb
3800 emitcode ("inc", "a");
3802 emitcode ("add", "a,#1");
3803 emitcode ("xch", "a,b");
3804 emitcode ("cpl", "a"); // msb
3805 emitcode ("addc", "a,#0");
3806 emitcode ("xch", "a,b");
3809 emitcode ("", "%05d$:", lbl->key+100);
3810 aopPut (AOP (result), "a", 0);
3812 aopPut (AOP (result), "b", 1);
3816 /*-----------------------------------------------------------------*/
3817 /* genMult - generates code for multiplication */
3818 /*-----------------------------------------------------------------*/
3820 genMult (iCode * ic)
3822 operand *left = IC_LEFT (ic);
3823 operand *right = IC_RIGHT (ic);
3824 operand *result = IC_RESULT (ic);
3826 D (emitcode (";", "genMult "););
3828 /* assign the amsops */
3831 /* special cases first */
3833 if (AOP_TYPE (left) == AOP_CRY &&
3834 AOP_TYPE (right) == AOP_CRY)
3836 genMultbits (left, right, result);
3840 /* if both are of size == 1 */
3841 if (AOP_SIZE (left) == 1 &&
3842 AOP_SIZE (right) == 1)
3844 genMultOneByte (left, right, result);
3848 /* should have been converted to function call */
3852 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3853 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3854 freeAsmop (result, NULL, ic, TRUE);
3857 /*-----------------------------------------------------------------*/
3858 /* genDivbits :- division of bits */
3859 /*-----------------------------------------------------------------*/
3861 genDivbits (operand * left,
3868 /* the result must be bit */
3869 LOAD_AB_FOR_DIV (left, right, l);
3870 emitcode ("div", "ab");
3871 emitcode ("rrc", "a");
3872 aopPut (AOP (result), "c", 0);
3875 /*-----------------------------------------------------------------*/
3876 /* genDivOneByte : 8 bit division */
3877 /*-----------------------------------------------------------------*/
3879 genDivOneByte (operand * left,
3883 sym_link *opetype = operandType (result);
3888 size = AOP_SIZE (result) - 1;
3890 /* signed or unsigned */
3891 if (SPEC_USIGN (opetype))
3893 /* unsigned is easy */
3894 LOAD_AB_FOR_DIV (left, right, l);
3895 emitcode ("div", "ab");
3896 aopPut (AOP (result), "a", 0);
3898 aopPut (AOP (result), zero, offset++);
3902 /* signed is a little bit more difficult */
3904 /* save the signs of the operands */
3905 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3907 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3908 emitcode ("push", "acc"); /* save it on the stack */
3910 /* now sign adjust for both left & right */
3911 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3913 lbl = newiTempLabel (NULL);
3914 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3915 emitcode ("cpl", "a");
3916 emitcode ("inc", "a");
3917 emitcode ("", "%05d$:", (lbl->key + 100));
3918 emitcode ("mov", "b,a");
3920 /* sign adjust left side */
3921 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3924 lbl = newiTempLabel (NULL);
3925 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3926 emitcode ("cpl", "a");
3927 emitcode ("inc", "a");
3928 emitcode ("", "%05d$:", (lbl->key + 100));
3930 /* now the division */
3931 emitcode ("nop", "; workaround for DS80C390 div bug.");
3932 emitcode ("div", "ab");
3933 /* we are interested in the lower order
3935 emitcode ("mov", "b,a");
3936 lbl = newiTempLabel (NULL);
3937 emitcode ("pop", "acc");
3938 /* if there was an over flow we don't
3939 adjust the sign of the result */
3940 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3941 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3943 emitcode ("clr", "a");
3944 emitcode ("subb", "a,b");
3945 emitcode ("mov", "b,a");
3946 emitcode ("", "%05d$:", (lbl->key + 100));
3948 /* now we are done */
3949 aopPut (AOP (result), "b", 0);
3952 emitcode ("mov", "c,b.7");
3953 emitcode ("subb", "a,acc");
3956 aopPut (AOP (result), "a", offset++);
3960 /*-----------------------------------------------------------------*/
3961 /* genDiv - generates code for division */
3962 /*-----------------------------------------------------------------*/
3966 operand *left = IC_LEFT (ic);
3967 operand *right = IC_RIGHT (ic);
3968 operand *result = IC_RESULT (ic);
3970 D (emitcode (";", "genDiv ");
3973 /* assign the amsops */
3976 /* special cases first */
3978 if (AOP_TYPE (left) == AOP_CRY &&
3979 AOP_TYPE (right) == AOP_CRY)
3981 genDivbits (left, right, result);
3985 /* if both are of size == 1 */
3986 if (AOP_SIZE (left) == 1 &&
3987 AOP_SIZE (right) == 1)
3989 genDivOneByte (left, right, result);
3993 /* should have been converted to function call */
3996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3998 freeAsmop (result, NULL, ic, TRUE);
4001 /*-----------------------------------------------------------------*/
4002 /* genModbits :- modulus of bits */
4003 /*-----------------------------------------------------------------*/
4005 genModbits (operand * left,
4012 /* the result must be bit */
4013 LOAD_AB_FOR_DIV (left, right, l);
4014 emitcode ("div", "ab");
4015 emitcode ("mov", "a,b");
4016 emitcode ("rrc", "a");
4017 aopPut (AOP (result), "c", 0);
4020 /*-----------------------------------------------------------------*/
4021 /* genModOneByte : 8 bit modulus */
4022 /*-----------------------------------------------------------------*/
4024 genModOneByte (operand * left,
4028 sym_link *opetype = operandType (result);
4032 /* signed or unsigned */
4033 if (SPEC_USIGN (opetype))
4035 /* unsigned is easy */
4036 LOAD_AB_FOR_DIV (left, right, l);
4037 emitcode ("div", "ab");
4038 aopPut (AOP (result), "b", 0);
4042 /* signed is a little bit more difficult */
4044 /* save the signs of the operands */
4045 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4048 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4049 emitcode ("push", "acc"); /* save it on the stack */
4051 /* now sign adjust for both left & right */
4052 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4055 lbl = newiTempLabel (NULL);
4056 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4057 emitcode ("cpl", "a");
4058 emitcode ("inc", "a");
4059 emitcode ("", "%05d$:", (lbl->key + 100));
4060 emitcode ("mov", "b,a");
4062 /* sign adjust left side */
4063 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4066 lbl = newiTempLabel (NULL);
4067 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4068 emitcode ("cpl", "a");
4069 emitcode ("inc", "a");
4070 emitcode ("", "%05d$:", (lbl->key + 100));
4072 /* now the multiplication */
4073 emitcode ("nop", "; workaround for DS80C390 div bug.");
4074 emitcode ("div", "ab");
4075 /* we are interested in the lower order
4077 lbl = newiTempLabel (NULL);
4078 emitcode ("pop", "acc");
4079 /* if there was an over flow we don't
4080 adjust the sign of the result */
4081 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4082 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4084 emitcode ("clr", "a");
4085 emitcode ("subb", "a,b");
4086 emitcode ("mov", "b,a");
4087 emitcode ("", "%05d$:", (lbl->key + 100));
4089 /* now we are done */
4090 aopPut (AOP (result), "b", 0);
4094 /*-----------------------------------------------------------------*/
4095 /* genMod - generates code for division */
4096 /*-----------------------------------------------------------------*/
4100 operand *left = IC_LEFT (ic);
4101 operand *right = IC_RIGHT (ic);
4102 operand *result = IC_RESULT (ic);
4104 D (emitcode (";", "genMod ");
4107 /* assign the amsops */
4110 /* special cases first */
4112 if (AOP_TYPE (left) == AOP_CRY &&
4113 AOP_TYPE (right) == AOP_CRY)
4115 genModbits (left, right, result);
4119 /* if both are of size == 1 */
4120 if (AOP_SIZE (left) == 1 &&
4121 AOP_SIZE (right) == 1)
4123 genModOneByte (left, right, result);
4127 /* should have been converted to function call */
4131 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4132 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4133 freeAsmop (result, NULL, ic, TRUE);
4136 /*-----------------------------------------------------------------*/
4137 /* genIfxJump :- will create a jump depending on the ifx */
4138 /*-----------------------------------------------------------------*/
4140 genIfxJump (iCode * ic, char *jval)
4143 symbol *tlbl = newiTempLabel (NULL);
4146 D (emitcode (";", "genIfxJump ");
4149 /* if true label then we jump if condition
4153 jlbl = IC_TRUE (ic);
4154 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4155 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4159 /* false label is present */
4160 jlbl = IC_FALSE (ic);
4161 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4162 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4164 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4165 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4167 emitcode (inst, "%05d$", tlbl->key + 100);
4168 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4169 emitcode ("", "%05d$:", tlbl->key + 100);
4171 /* mark the icode as generated */
4175 /*-----------------------------------------------------------------*/
4176 /* genCmp :- greater or less than comparison */
4177 /*-----------------------------------------------------------------*/
4179 genCmp (operand * left, operand * right,
4180 iCode * ic, iCode * ifx, int sign)
4182 int size, offset = 0;
4183 unsigned long lit = 0L;
4186 D (emitcode (";", "genCmp");
4189 result = IC_RESULT (ic);
4191 /* if left & right are bit variables */
4192 if (AOP_TYPE (left) == AOP_CRY &&
4193 AOP_TYPE (right) == AOP_CRY)
4195 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4196 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4200 /* subtract right from left if at the
4201 end the carry flag is set then we know that
4202 left is greater than right */
4203 size = max (AOP_SIZE (left), AOP_SIZE (right));
4205 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4206 if ((size == 1) && !sign &&
4207 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4209 symbol *lbl = newiTempLabel (NULL);
4210 emitcode ("cjne", "%s,%s,%05d$",
4211 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4212 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4214 emitcode ("", "%05d$:", lbl->key + 100);
4218 if (AOP_TYPE (right) == AOP_LIT)
4220 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4221 /* optimize if(x < 0) or if(x >= 0) */
4230 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4232 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4233 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4235 aopOp (result, ic, FALSE, FALSE);
4237 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4239 freeAsmop (result, NULL, ic, TRUE);
4240 genIfxJump (ifx, "acc.7");
4245 emitcode ("rlc", "a");
4247 goto release_freedLR;
4255 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4256 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4257 emitcode (";", "genCmp #2");
4258 if (sign && (size == 0))
4260 emitcode (";", "genCmp #3");
4261 emitcode ("xrl", "a,#0x80");
4262 if (AOP_TYPE (right) == AOP_LIT)
4264 unsigned long lit = (unsigned long)
4265 floatFromVal (AOP (right)->aopu.aop_lit);
4266 emitcode (";", "genCmp #3.1");
4267 emitcode ("subb", "a,#0x%02x",
4268 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4272 emitcode (";", "genCmp #3.2");
4273 if (AOP_NEEDSACC (right))
4275 emitcode ("push", "acc");
4277 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4278 FALSE, FALSE, FALSE));
4279 emitcode ("xrl", "b,#0x80");
4280 if (AOP_NEEDSACC (right))
4282 emitcode ("pop", "acc");
4284 emitcode ("subb", "a,b");
4291 emitcode (";", "genCmp #4");
4292 if (AOP_NEEDSACC (right))
4295 emitcode (";", "genCmp #4.1");
4296 emitcode ("xch", "a, b");
4297 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4298 emitcode ("xch", "a, b");
4303 emitcode (";", "genCmp #4.2");
4304 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4307 emitcode ("subb", "a,%s", s);
4314 /* Don't need the left & right operands any more; do need the result. */
4315 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4316 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4318 aopOp (result, ic, FALSE, FALSE);
4322 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4328 /* if the result is used in the next
4329 ifx conditional branch then generate
4330 code a little differently */
4333 genIfxJump (ifx, "c");
4339 /* leave the result in acc */
4341 freeAsmop (result, NULL, ic, TRUE);
4344 /*-----------------------------------------------------------------*/
4345 /* genCmpGt :- greater than comparison */
4346 /*-----------------------------------------------------------------*/
4348 genCmpGt (iCode * ic, iCode * ifx)
4350 operand *left, *right;
4351 sym_link *letype, *retype;
4354 D (emitcode (";", "genCmpGt ");
4357 left = IC_LEFT (ic);
4358 right = IC_RIGHT (ic);
4360 letype = getSpec (operandType (left));
4361 retype = getSpec (operandType (right));
4362 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4364 /* assign the left & right amsops */
4367 genCmp (right, left, ic, ifx, sign);
4370 /*-----------------------------------------------------------------*/
4371 /* genCmpLt - less than comparisons */
4372 /*-----------------------------------------------------------------*/
4374 genCmpLt (iCode * ic, iCode * ifx)
4376 operand *left, *right;
4377 sym_link *letype, *retype;
4380 D (emitcode (";", "genCmpLt "););
4382 left = IC_LEFT (ic);
4383 right = IC_RIGHT (ic);
4385 letype = getSpec (operandType (left));
4386 retype = getSpec (operandType (right));
4387 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4389 /* assign the left & right amsops */
4392 genCmp (left, right, ic, ifx, sign);
4395 /*-----------------------------------------------------------------*/
4396 /* gencjneshort - compare and jump if not equal */
4397 /*-----------------------------------------------------------------*/
4399 gencjneshort (operand * left, operand * right, symbol * lbl)
4401 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4403 unsigned long lit = 0L;
4405 D (emitcode (";", "gencjneshort");
4408 /* if the left side is a literal or
4409 if the right is in a pointer register and left
4411 if ((AOP_TYPE (left) == AOP_LIT) ||
4412 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4419 if (AOP_TYPE (right) == AOP_LIT)
4420 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4422 if (opIsGptr (left) || opIsGptr (right))
4424 /* We are comparing a generic pointer to something.
4425 * Exclude the generic type byte from the comparison.
4428 D (emitcode (";", "cjneshort: generic ptr special case.");
4433 /* if the right side is a literal then anything goes */
4434 if (AOP_TYPE (right) == AOP_LIT &&
4435 AOP_TYPE (left) != AOP_DIR)
4439 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4441 emitcode ("cjne", "a,%s,%05d$",
4442 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4448 /* if the right side is in a register or in direct space or
4449 if the left is a pointer register & right is not */
4450 else if (AOP_TYPE (right) == AOP_REG ||
4451 AOP_TYPE (right) == AOP_DIR ||
4452 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4453 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4457 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4458 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4459 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4460 emitcode ("jnz", "%05d$", lbl->key + 100);
4462 emitcode ("cjne", "a,%s,%05d$",
4463 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4470 /* right is a pointer reg need both a & b */
4473 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4474 if (strcmp (l, "b"))
4475 emitcode ("mov", "b,%s", l);
4476 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4477 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4483 /*-----------------------------------------------------------------*/
4484 /* gencjne - compare and jump if not equal */
4485 /*-----------------------------------------------------------------*/
4487 gencjne (operand * left, operand * right, symbol * lbl)
4489 symbol *tlbl = newiTempLabel (NULL);
4491 D (emitcode (";", "gencjne");
4494 gencjneshort (left, right, lbl);
4496 emitcode ("mov", "a,%s", one);
4497 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4498 emitcode ("", "%05d$:", lbl->key + 100);
4499 emitcode ("clr", "a");
4500 emitcode ("", "%05d$:", tlbl->key + 100);
4503 /*-----------------------------------------------------------------*/
4504 /* genCmpEq - generates code for equal to */
4505 /*-----------------------------------------------------------------*/
4507 genCmpEq (iCode * ic, iCode * ifx)
4509 operand *left, *right, *result;
4511 D (emitcode (";", "genCmpEq ");
4515 AOP_SET_LOCALS (ic);
4517 /* if literal, literal on the right or
4518 if the right is in a pointer register and left
4520 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4521 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4523 operand *t = IC_RIGHT (ic);
4524 IC_RIGHT (ic) = IC_LEFT (ic);
4528 if (ifx && /* !AOP_SIZE(result) */
4529 OP_SYMBOL (result) &&
4530 OP_SYMBOL (result)->regType == REG_CND)
4533 /* if they are both bit variables */
4534 if (AOP_TYPE (left) == AOP_CRY &&
4535 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4537 if (AOP_TYPE (right) == AOP_LIT)
4539 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4542 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4543 emitcode ("cpl", "c");
4547 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4551 emitcode ("clr", "c");
4553 /* AOP_TYPE(right) == AOP_CRY */
4557 symbol *lbl = newiTempLabel (NULL);
4558 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4559 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4560 emitcode ("cpl", "c");
4561 emitcode ("", "%05d$:", (lbl->key + 100));
4563 /* if true label then we jump if condition
4565 tlbl = newiTempLabel (NULL);
4568 emitcode ("jnc", "%05d$", tlbl->key + 100);
4569 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4573 emitcode ("jc", "%05d$", tlbl->key + 100);
4574 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4576 emitcode ("", "%05d$:", tlbl->key + 100);
4580 tlbl = newiTempLabel (NULL);
4581 gencjneshort (left, right, tlbl);
4584 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4585 emitcode ("", "%05d$:", tlbl->key + 100);
4589 symbol *lbl = newiTempLabel (NULL);
4590 emitcode ("sjmp", "%05d$", lbl->key + 100);
4591 emitcode ("", "%05d$:", tlbl->key + 100);
4592 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4593 emitcode ("", "%05d$:", lbl->key + 100);
4596 /* mark the icode as generated */
4599 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4600 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604 /* if they are both bit variables */
4605 if (AOP_TYPE (left) == AOP_CRY &&
4606 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4608 if (AOP_TYPE (right) == AOP_LIT)
4610 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4613 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4614 emitcode ("cpl", "c");
4618 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4622 emitcode ("clr", "c");
4624 /* AOP_TYPE(right) == AOP_CRY */
4628 symbol *lbl = newiTempLabel (NULL);
4629 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4630 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4631 emitcode ("cpl", "c");
4632 emitcode ("", "%05d$:", (lbl->key + 100));
4635 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4638 aopOp (result, ic, TRUE, FALSE);
4641 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4648 genIfxJump (ifx, "c");
4651 /* if the result is used in an arithmetic operation
4652 then put the result in place */
4657 gencjne (left, right, newiTempLabel (NULL));
4659 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4660 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4662 aopOp (result, ic, TRUE, FALSE);
4664 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4666 aopPut (AOP (result), "a", 0);
4671 genIfxJump (ifx, "a");
4674 /* if the result is used in an arithmetic operation
4675 then put the result in place */
4676 if (AOP_TYPE (result) != AOP_CRY)
4678 /* leave the result in acc */
4682 freeAsmop (result, NULL, ic, TRUE);
4685 /*-----------------------------------------------------------------*/
4686 /* ifxForOp - returns the icode containing the ifx for operand */
4687 /*-----------------------------------------------------------------*/
4689 ifxForOp (operand * op, iCode * ic)
4691 /* if true symbol then needs to be assigned */
4692 if (IS_TRUE_SYMOP (op))
4695 /* if this has register type condition and
4696 the next instruction is ifx with the same operand
4697 and live to of the operand is upto the ifx only then */
4699 ic->next->op == IFX &&
4700 IC_COND (ic->next)->key == op->key &&
4701 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4706 /*-----------------------------------------------------------------*/
4707 /* genAndOp - for && operation */
4708 /*-----------------------------------------------------------------*/
4710 genAndOp (iCode * ic)
4712 operand *left, *right, *result;
4715 D (emitcode (";", "genAndOp "););
4717 /* note here that && operations that are in an
4718 if statement are taken away by backPatchLabels
4719 only those used in arthmetic operations remain */
4721 AOP_SET_LOCALS (ic);
4723 /* if both are bit variables */
4724 if (AOP_TYPE (left) == AOP_CRY &&
4725 AOP_TYPE (right) == AOP_CRY)
4727 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4728 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4729 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4730 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4732 aopOp (result,ic,FALSE, FALSE);
4737 tlbl = newiTempLabel (NULL);
4739 emitcode ("jz", "%05d$", tlbl->key + 100);
4741 emitcode ("", "%05d$:", tlbl->key + 100);
4742 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4743 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4745 aopOp (result,ic,FALSE, FALSE);
4748 freeAsmop (result, NULL, ic, TRUE);
4752 /*-----------------------------------------------------------------*/
4753 /* genOrOp - for || operation */
4754 /*-----------------------------------------------------------------*/
4756 genOrOp (iCode * ic)
4758 operand *left, *right, *result;
4761 D (emitcode (";", "genOrOp "););
4763 /* note here that || operations that are in an
4764 if statement are taken away by backPatchLabels
4765 only those used in arthmetic operations remain */
4767 AOP_SET_LOCALS (ic);
4769 /* if both are bit variables */
4770 if (AOP_TYPE (left) == AOP_CRY &&
4771 AOP_TYPE (right) == AOP_CRY)
4773 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4774 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4775 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4776 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4778 aopOp (result,ic,FALSE, FALSE);
4784 tlbl = newiTempLabel (NULL);
4786 emitcode ("jnz", "%05d$", tlbl->key + 100);
4788 emitcode ("", "%05d$:", tlbl->key + 100);
4789 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4790 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4792 aopOp (result,ic,FALSE, FALSE);
4797 freeAsmop (result, NULL, ic, TRUE);
4800 /*-----------------------------------------------------------------*/
4801 /* isLiteralBit - test if lit == 2^n */
4802 /*-----------------------------------------------------------------*/
4804 isLiteralBit (unsigned long lit)
4806 unsigned long pw[32] =
4807 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4808 0x100L, 0x200L, 0x400L, 0x800L,
4809 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4810 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4811 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4812 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4813 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4816 for (idx = 0; idx < 32; idx++)
4822 /*-----------------------------------------------------------------*/
4823 /* continueIfTrue - */
4824 /*-----------------------------------------------------------------*/
4826 continueIfTrue (iCode * ic)
4829 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4833 /*-----------------------------------------------------------------*/
4835 /*-----------------------------------------------------------------*/
4837 jumpIfTrue (iCode * ic)
4840 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4844 /*-----------------------------------------------------------------*/
4845 /* jmpTrueOrFalse - */
4846 /*-----------------------------------------------------------------*/
4848 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4850 // ugly but optimized by peephole
4853 symbol *nlbl = newiTempLabel (NULL);
4854 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4855 emitcode ("", "%05d$:", tlbl->key + 100);
4856 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4857 emitcode ("", "%05d$:", nlbl->key + 100);
4861 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4862 emitcode ("", "%05d$:", tlbl->key + 100);
4867 // Generate code to perform a bit-wise logic operation
4868 // on two operands in far space (assumed to already have been
4869 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4870 // in far space. This requires pushing the result on the stack
4871 // then popping it into the result.
4873 genFarFarLogicOp(iCode *ic, char *logicOp)
4875 int size, resultSize, compSize;
4878 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4879 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4880 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4882 _startLazyDPSEvaluation();
4883 for (size = compSize; (size--); offset++)
4885 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4886 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4887 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4889 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4890 emitcode ("push", "acc");
4892 _endLazyDPSEvaluation();
4894 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4895 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4896 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4898 resultSize = AOP_SIZE(IC_RESULT(ic));
4900 ADJUST_PUSHED_RESULT(compSize, resultSize);
4902 _startLazyDPSEvaluation();
4905 emitcode ("pop", "acc");
4906 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4908 _endLazyDPSEvaluation();
4909 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4913 /*-----------------------------------------------------------------*/
4914 /* genAnd - code for and */
4915 /*-----------------------------------------------------------------*/
4917 genAnd (iCode * ic, iCode * ifx)
4919 operand *left, *right, *result;
4920 int size, offset = 0;
4921 unsigned long lit = 0L;
4926 D (emitcode (";", "genAnd "););
4928 AOP_OP_3_NOFATAL (ic, pushResult);
4929 AOP_SET_LOCALS (ic);
4933 genFarFarLogicOp(ic, "anl");
4938 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4940 AOP_TYPE (left), AOP_TYPE (right));
4941 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4943 AOP_SIZE (left), AOP_SIZE (right));
4946 /* if left is a literal & right is not then exchange them */
4947 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4948 AOP_NEEDSACC (left))
4950 operand *tmp = right;
4955 /* if result = right then exchange them */
4956 if (sameRegs (AOP (result), AOP (right)))
4958 operand *tmp = right;
4963 /* if right is bit then exchange them */
4964 if (AOP_TYPE (right) == AOP_CRY &&
4965 AOP_TYPE (left) != AOP_CRY)
4967 operand *tmp = right;
4971 if (AOP_TYPE (right) == AOP_LIT)
4972 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4974 size = AOP_SIZE (result);
4977 // result = bit & yy;
4978 if (AOP_TYPE (left) == AOP_CRY)
4980 // c = bit & literal;
4981 if (AOP_TYPE (right) == AOP_LIT)
4985 if (size && sameRegs (AOP (result), AOP (left)))
4988 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4993 if (size && (AOP_TYPE (result) == AOP_CRY))
4995 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4998 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5003 emitcode ("clr", "c");
5008 if (AOP_TYPE (right) == AOP_CRY)
5011 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5012 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5017 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5019 emitcode ("rrc", "a");
5020 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5028 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5029 genIfxJump (ifx, "c");
5033 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5034 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5035 if ((AOP_TYPE (right) == AOP_LIT) &&
5036 (AOP_TYPE (result) == AOP_CRY) &&
5037 (AOP_TYPE (left) != AOP_CRY))
5039 int posbit = isLiteralBit (lit);
5044 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5047 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5053 sprintf (buffer, "acc.%d", posbit & 0x07);
5054 genIfxJump (ifx, buffer);
5061 symbol *tlbl = newiTempLabel (NULL);
5062 int sizel = AOP_SIZE (left);
5064 emitcode ("setb", "c");
5067 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5069 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5071 if ((posbit = isLiteralBit (bytelit)) != 0)
5072 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5075 if (bytelit != 0x0FFL)
5076 emitcode ("anl", "a,%s",
5077 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5078 emitcode ("jnz", "%05d$", tlbl->key + 100);
5083 // bit = left & literal
5086 emitcode ("clr", "c");
5087 emitcode ("", "%05d$:", tlbl->key + 100);
5089 // if(left & literal)
5093 jmpTrueOrFalse (ifx, tlbl);
5101 /* if left is same as result */
5102 if (sameRegs (AOP (result), AOP (left)))
5104 for (; size--; offset++)
5106 if (AOP_TYPE (right) == AOP_LIT)
5108 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5110 else if (bytelit == 0)
5111 aopPut (AOP (result), zero, offset);
5112 else if (IS_AOP_PREG (result))
5114 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5115 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5116 aopPut (AOP (result), "a", offset);
5119 emitcode ("anl", "%s,%s",
5120 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5121 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5125 if (AOP_TYPE (left) == AOP_ACC)
5126 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5129 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5130 if (IS_AOP_PREG (result))
5132 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5133 aopPut (AOP (result), "a", offset);
5137 emitcode ("anl", "%s,a",
5138 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5145 // left & result in different registers
5146 if (AOP_TYPE (result) == AOP_CRY)
5149 // if(size), result in bit
5150 // if(!size && ifx), conditional oper: if(left & right)
5151 symbol *tlbl = newiTempLabel (NULL);
5152 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5154 emitcode ("setb", "c");
5157 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5158 emitcode ("anl", "a,%s",
5159 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5160 emitcode ("jnz", "%05d$", tlbl->key + 100);
5166 emitcode ("", "%05d$:", tlbl->key + 100);
5170 jmpTrueOrFalse (ifx, tlbl);
5174 for (; (size--); offset++)
5177 // result = left & right
5178 if (AOP_TYPE (right) == AOP_LIT)
5180 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5182 aopPut (AOP (result),
5183 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5187 else if (bytelit == 0)
5189 aopPut (AOP (result), zero, offset);
5192 D (emitcode (";", "better literal AND.");
5194 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5195 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5196 FALSE, FALSE, FALSE));
5201 // faster than result <- left, anl result,right
5202 // and better if result is SFR
5203 if (AOP_TYPE (left) == AOP_ACC)
5205 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5206 FALSE, FALSE, FALSE));
5210 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5211 emitcode ("anl", "a,%s",
5212 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5215 aopPut (AOP (result), "a", offset);
5221 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5222 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5223 freeAsmop (result, NULL, ic, TRUE);
5227 /*-----------------------------------------------------------------*/
5228 /* genOr - code for or */
5229 /*-----------------------------------------------------------------*/
5231 genOr (iCode * ic, iCode * ifx)
5233 operand *left, *right, *result;
5234 int size, offset = 0;
5235 unsigned long lit = 0L;
5238 D (emitcode (";", "genOr "););
5240 AOP_OP_3_NOFATAL (ic, pushResult);
5241 AOP_SET_LOCALS (ic);
5245 genFarFarLogicOp(ic, "orl");
5251 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5253 AOP_TYPE (left), AOP_TYPE (right));
5254 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5256 AOP_SIZE (left), AOP_SIZE (right));
5259 /* if left is a literal & right is not then exchange them */
5260 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5261 AOP_NEEDSACC (left))
5263 operand *tmp = right;
5268 /* if result = right then exchange them */
5269 if (sameRegs (AOP (result), AOP (right)))
5271 operand *tmp = right;
5276 /* if right is bit then exchange them */
5277 if (AOP_TYPE (right) == AOP_CRY &&
5278 AOP_TYPE (left) != AOP_CRY)
5280 operand *tmp = right;
5284 if (AOP_TYPE (right) == AOP_LIT)
5285 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5287 size = AOP_SIZE (result);
5291 if (AOP_TYPE (left) == AOP_CRY)
5293 if (AOP_TYPE (right) == AOP_LIT)
5295 // c = bit & literal;
5298 // lit != 0 => result = 1
5299 if (AOP_TYPE (result) == AOP_CRY)
5302 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5304 continueIfTrue (ifx);
5307 emitcode ("setb", "c");
5311 // lit == 0 => result = left
5312 if (size && sameRegs (AOP (result), AOP (left)))
5314 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5319 if (AOP_TYPE (right) == AOP_CRY)
5322 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5323 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5328 symbol *tlbl = newiTempLabel (NULL);
5329 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5330 emitcode ("setb", "c");
5331 emitcode ("jb", "%s,%05d$",
5332 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5334 emitcode ("jnz", "%05d$", tlbl->key + 100);
5335 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5337 jmpTrueOrFalse (ifx, tlbl);
5343 emitcode ("", "%05d$:", tlbl->key + 100);
5352 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5353 genIfxJump (ifx, "c");
5357 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5358 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5359 if ((AOP_TYPE (right) == AOP_LIT) &&
5360 (AOP_TYPE (result) == AOP_CRY) &&
5361 (AOP_TYPE (left) != AOP_CRY))
5367 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5369 continueIfTrue (ifx);
5374 // lit = 0, result = boolean(left)
5376 emitcode ("setb", "c");
5380 symbol *tlbl = newiTempLabel (NULL);
5381 emitcode ("jnz", "%05d$", tlbl->key + 100);
5383 emitcode ("", "%05d$:", tlbl->key + 100);
5387 genIfxJump (ifx, "a");
5395 /* if left is same as result */
5396 if (sameRegs (AOP (result), AOP (left)))
5398 for (; size--; offset++)
5400 if (AOP_TYPE (right) == AOP_LIT)
5402 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5408 if (IS_AOP_PREG (left))
5410 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5411 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5412 aopPut (AOP (result), "a", offset);
5416 emitcode ("orl", "%s,%s",
5417 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5418 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5424 if (AOP_TYPE (left) == AOP_ACC)
5426 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5430 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5431 if (IS_AOP_PREG (left))
5433 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5434 aopPut (AOP (result), "a", offset);
5438 emitcode ("orl", "%s,a",
5439 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5447 // left & result in different registers
5448 if (AOP_TYPE (result) == AOP_CRY)
5451 // if(size), result in bit
5452 // if(!size && ifx), conditional oper: if(left | right)
5453 symbol *tlbl = newiTempLabel (NULL);
5454 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5456 emitcode ("setb", "c");
5459 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5460 emitcode ("orl", "a,%s",
5461 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5462 emitcode ("jnz", "%05d$", tlbl->key + 100);
5468 emitcode ("", "%05d$:", tlbl->key + 100);
5472 jmpTrueOrFalse (ifx, tlbl);
5476 for (; (size--); offset++)
5479 // result = left & right
5480 if (AOP_TYPE (right) == AOP_LIT)
5482 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5484 aopPut (AOP (result),
5485 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5489 D (emitcode (";", "better literal OR.");
5491 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5492 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5493 FALSE, FALSE, FALSE));
5498 // faster than result <- left, anl result,right
5499 // and better if result is SFR
5500 if (AOP_TYPE (left) == AOP_ACC)
5502 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5503 FALSE, FALSE, FALSE));
5507 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5508 emitcode ("orl", "a,%s",
5509 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5512 aopPut (AOP (result), "a", offset);
5518 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5519 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5520 freeAsmop (result, NULL, ic, TRUE);
5523 /*-----------------------------------------------------------------*/
5524 /* genXor - code for xclusive or */
5525 /*-----------------------------------------------------------------*/
5527 genXor (iCode * ic, iCode * ifx)
5529 operand *left, *right, *result;
5530 int size, offset = 0;
5531 unsigned long lit = 0L;
5534 D (emitcode (";", "genXor "););
5536 AOP_OP_3_NOFATAL (ic, pushResult);
5537 AOP_SET_LOCALS (ic);
5541 genFarFarLogicOp(ic, "xrl");
5546 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5548 AOP_TYPE (left), AOP_TYPE (right));
5549 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5551 AOP_SIZE (left), AOP_SIZE (right));
5554 /* if left is a literal & right is not ||
5555 if left needs acc & right does not */
5556 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5557 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5559 operand *tmp = right;
5564 /* if result = right then exchange them */
5565 if (sameRegs (AOP (result), AOP (right)))
5567 operand *tmp = right;
5572 /* if right is bit then exchange them */
5573 if (AOP_TYPE (right) == AOP_CRY &&
5574 AOP_TYPE (left) != AOP_CRY)
5576 operand *tmp = right;
5580 if (AOP_TYPE (right) == AOP_LIT)
5581 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5583 size = AOP_SIZE (result);
5587 if (AOP_TYPE (left) == AOP_CRY)
5589 if (AOP_TYPE (right) == AOP_LIT)
5591 // c = bit & literal;
5594 // lit>>1 != 0 => result = 1
5595 if (AOP_TYPE (result) == AOP_CRY)
5598 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5600 continueIfTrue (ifx);
5603 emitcode ("setb", "c");
5610 // lit == 0, result = left
5611 if (size && sameRegs (AOP (result), AOP (left)))
5613 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5617 // lit == 1, result = not(left)
5618 if (size && sameRegs (AOP (result), AOP (left)))
5620 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5625 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5626 emitcode ("cpl", "c");
5635 symbol *tlbl = newiTempLabel (NULL);
5636 if (AOP_TYPE (right) == AOP_CRY)
5639 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5643 int sizer = AOP_SIZE (right);
5645 // if val>>1 != 0, result = 1
5646 emitcode ("setb", "c");
5649 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5651 // test the msb of the lsb
5652 emitcode ("anl", "a,#0xfe");
5653 emitcode ("jnz", "%05d$", tlbl->key + 100);
5657 emitcode ("rrc", "a");
5659 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5660 emitcode ("cpl", "c");
5661 emitcode ("", "%05d$:", (tlbl->key + 100));
5668 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5669 genIfxJump (ifx, "c");
5673 if (sameRegs (AOP (result), AOP (left)))
5675 /* if left is same as result */
5676 for (; size--; offset++)
5678 if (AOP_TYPE (right) == AOP_LIT)
5680 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5682 else if (IS_AOP_PREG (left))
5684 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5685 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5686 aopPut (AOP (result), "a", offset);
5689 emitcode ("xrl", "%s,%s",
5690 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5691 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5695 if (AOP_TYPE (left) == AOP_ACC)
5696 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5699 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5700 if (IS_AOP_PREG (left))
5702 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5703 aopPut (AOP (result), "a", offset);
5706 emitcode ("xrl", "%s,a",
5707 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5714 // left & result in different registers
5715 if (AOP_TYPE (result) == AOP_CRY)
5718 // if(size), result in bit
5719 // if(!size && ifx), conditional oper: if(left ^ right)
5720 symbol *tlbl = newiTempLabel (NULL);
5721 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5723 emitcode ("setb", "c");
5726 if ((AOP_TYPE (right) == AOP_LIT) &&
5727 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5729 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5733 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5734 emitcode ("xrl", "a,%s",
5735 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5737 emitcode ("jnz", "%05d$", tlbl->key + 100);
5743 emitcode ("", "%05d$:", tlbl->key + 100);
5747 jmpTrueOrFalse (ifx, tlbl);
5750 for (; (size--); offset++)
5753 // result = left & right
5754 if (AOP_TYPE (right) == AOP_LIT)
5756 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5758 aopPut (AOP (result),
5759 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5763 D (emitcode (";", "better literal XOR.");
5765 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5766 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5767 FALSE, FALSE, FALSE));
5771 // faster than result <- left, anl result,right
5772 // and better if result is SFR
5773 if (AOP_TYPE (left) == AOP_ACC)
5775 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5776 FALSE, FALSE, FALSE));
5780 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5781 emitcode ("xrl", "a,%s",
5782 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5785 aopPut (AOP (result), "a", offset);
5790 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5791 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5792 freeAsmop (result, NULL, ic, TRUE);
5795 /*-----------------------------------------------------------------*/
5796 /* genInline - write the inline code out */
5797 /*-----------------------------------------------------------------*/
5799 genInline (iCode * ic)
5801 char *buffer, *bp, *bp1;
5803 D (emitcode (";", "genInline ");
5806 _G.inLine += (!options.asmpeep);
5808 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5809 strcpy (buffer, IC_INLINE (ic));
5811 /* emit each line as a code */
5836 /* emitcode("",buffer); */
5837 _G.inLine -= (!options.asmpeep);
5840 /*-----------------------------------------------------------------*/
5841 /* genRRC - rotate right with carry */
5842 /*-----------------------------------------------------------------*/
5846 operand *left, *result;
5847 int size, offset = 0;
5850 D (emitcode (";", "genRRC ");
5853 /* rotate right with carry */
5854 left = IC_LEFT (ic);
5855 result = IC_RESULT (ic);
5856 aopOp (left, ic, FALSE, FALSE);
5857 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5859 /* move it to the result */
5860 size = AOP_SIZE (result);
5864 _startLazyDPSEvaluation ();
5867 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5869 emitcode ("rrc", "a");
5870 if (AOP_SIZE (result) > 1)
5871 aopPut (AOP (result), "a", offset--);
5873 _endLazyDPSEvaluation ();
5875 /* now we need to put the carry into the
5876 highest order byte of the result */
5877 if (AOP_SIZE (result) > 1)
5879 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5882 emitcode ("mov", "acc.7,c");
5883 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5884 freeAsmop (left, NULL, ic, TRUE);
5885 freeAsmop (result, NULL, ic, TRUE);
5888 /*-----------------------------------------------------------------*/
5889 /* genRLC - generate code for rotate left with carry */
5890 /*-----------------------------------------------------------------*/
5894 operand *left, *result;
5895 int size, offset = 0;
5898 D (emitcode (";", "genRLC ");
5901 /* rotate right with carry */
5902 left = IC_LEFT (ic);
5903 result = IC_RESULT (ic);
5904 aopOp (left, ic, FALSE, FALSE);
5905 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5907 /* move it to the result */
5908 size = AOP_SIZE (result);
5912 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5914 emitcode ("add", "a,acc");
5915 if (AOP_SIZE (result) > 1)
5917 aopPut (AOP (result), "a", offset++);
5920 _startLazyDPSEvaluation ();
5923 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5925 emitcode ("rlc", "a");
5926 if (AOP_SIZE (result) > 1)
5927 aopPut (AOP (result), "a", offset++);
5929 _endLazyDPSEvaluation ();
5931 /* now we need to put the carry into the
5932 highest order byte of the result */
5933 if (AOP_SIZE (result) > 1)
5935 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5938 emitcode ("mov", "acc.0,c");
5939 aopPut (AOP (result), "a", 0);
5940 freeAsmop (left, NULL, ic, TRUE);
5941 freeAsmop (result, NULL, ic, TRUE);
5944 /*-----------------------------------------------------------------*/
5945 /* genGetHbit - generates code get highest order bit */
5946 /*-----------------------------------------------------------------*/
5948 genGetHbit (iCode * ic)
5950 operand *left, *result;
5951 left = IC_LEFT (ic);
5952 result = IC_RESULT (ic);
5953 aopOp (left, ic, FALSE, FALSE);
5954 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5956 D (emitcode (";", "genGetHbit ");
5959 /* get the highest order byte into a */
5960 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5961 if (AOP_TYPE (result) == AOP_CRY)
5963 emitcode ("rlc", "a");
5968 emitcode ("rl", "a");
5969 emitcode ("anl", "a,#0x01");
5974 freeAsmop (left, NULL, ic, TRUE);
5975 freeAsmop (result, NULL, ic, TRUE);
5978 /*-----------------------------------------------------------------*/
5979 /* AccRol - rotate left accumulator by known count */
5980 /*-----------------------------------------------------------------*/
5982 AccRol (int shCount)
5984 shCount &= 0x0007; // shCount : 0..7
5991 emitcode ("rl", "a");
5994 emitcode ("rl", "a");
5995 emitcode ("rl", "a");
5998 emitcode ("swap", "a");
5999 emitcode ("rr", "a");
6002 emitcode ("swap", "a");
6005 emitcode ("swap", "a");
6006 emitcode ("rl", "a");
6009 emitcode ("rr", "a");
6010 emitcode ("rr", "a");
6013 emitcode ("rr", "a");
6018 /*-----------------------------------------------------------------*/
6019 /* AccLsh - left shift accumulator by known count */
6020 /*-----------------------------------------------------------------*/
6022 AccLsh (int shCount)
6027 emitcode ("add", "a,acc");
6028 else if (shCount == 2)
6030 emitcode ("add", "a,acc");
6031 emitcode ("add", "a,acc");
6035 /* rotate left accumulator */
6037 /* and kill the lower order bits */
6038 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6043 /*-----------------------------------------------------------------*/
6044 /* AccRsh - right shift accumulator by known count */
6045 /*-----------------------------------------------------------------*/
6047 AccRsh (int shCount)
6054 emitcode ("rrc", "a");
6058 /* rotate right accumulator */
6059 AccRol (8 - shCount);
6060 /* and kill the higher order bits */
6061 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6066 #ifdef BETTER_LITERAL_SHIFT
6067 /*-----------------------------------------------------------------*/
6068 /* AccSRsh - signed right shift accumulator by known count */
6069 /*-----------------------------------------------------------------*/
6071 AccSRsh (int shCount)
6078 emitcode ("mov", "c,acc.7");
6079 emitcode ("rrc", "a");
6081 else if (shCount == 2)
6083 emitcode ("mov", "c,acc.7");
6084 emitcode ("rrc", "a");
6085 emitcode ("mov", "c,acc.7");
6086 emitcode ("rrc", "a");
6090 tlbl = newiTempLabel (NULL);
6091 /* rotate right accumulator */
6092 AccRol (8 - shCount);
6093 /* and kill the higher order bits */
6094 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6095 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6096 emitcode ("orl", "a,#0x%02x",
6097 (unsigned char) ~SRMask[shCount]);
6098 emitcode ("", "%05d$:", tlbl->key + 100);
6104 #ifdef BETTER_LITERAL_SHIFT
6105 /*-----------------------------------------------------------------*/
6106 /* shiftR1Left2Result - shift right one byte from left to result */
6107 /*-----------------------------------------------------------------*/
6109 shiftR1Left2Result (operand * left, int offl,
6110 operand * result, int offr,
6111 int shCount, int sign)
6113 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6114 /* shift right accumulator */
6119 aopPut (AOP (result), "a", offr);
6123 #ifdef BETTER_LITERAL_SHIFT
6124 /*-----------------------------------------------------------------*/
6125 /* shiftL1Left2Result - shift left one byte from left to result */
6126 /*-----------------------------------------------------------------*/
6128 shiftL1Left2Result (operand * left, int offl,
6129 operand * result, int offr, int shCount)
6131 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6132 /* shift left accumulator */
6134 aopPut (AOP (result), "a", offr);
6138 #ifdef BETTER_LITERAL_SHIFT
6139 /*-----------------------------------------------------------------*/
6140 /* movLeft2Result - move byte from left to result */
6141 /*-----------------------------------------------------------------*/
6143 movLeft2Result (operand * left, int offl,
6144 operand * result, int offr, int sign)
6147 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6149 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6151 if (*l == '@' && (IS_AOP_PREG (result)))
6153 emitcode ("mov", "a,%s", l);
6154 aopPut (AOP (result), "a", offr);
6160 aopPut (AOP (result), l, offr);
6164 /* MSB sign in acc.7 ! */
6165 if (getDataSize (left) == offl + 1)
6167 emitcode ("mov", "a,%s", l);
6168 aopPut (AOP (result), "a", offr);
6176 #ifdef BETTER_LITERAL_SHIFT
6177 /*-----------------------------------------------------------------*/
6178 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6179 /*-----------------------------------------------------------------*/
6183 emitcode ("rrc", "a");
6184 emitcode ("xch", "a,%s", x);
6185 emitcode ("rrc", "a");
6186 emitcode ("xch", "a,%s", x);
6190 #ifdef BETTER_LITERAL_SHIFT
6192 /*-----------------------------------------------------------------*/
6193 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6194 /*-----------------------------------------------------------------*/
6198 emitcode ("xch", "a,%s", x);
6199 emitcode ("rlc", "a");
6200 emitcode ("xch", "a,%s", x);
6201 emitcode ("rlc", "a");
6205 #ifdef BETTER_LITERAL_SHIFT
6206 /*-----------------------------------------------------------------*/
6207 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6208 /*-----------------------------------------------------------------*/
6212 emitcode ("xch", "a,%s", x);
6213 emitcode ("add", "a,acc");
6214 emitcode ("xch", "a,%s", x);
6215 emitcode ("rlc", "a");
6219 #ifdef BETTER_LITERAL_SHIFT
6220 /*-----------------------------------------------------------------*/
6221 /* AccAXLsh - left shift a:x by known count (0..7) */
6222 /*-----------------------------------------------------------------*/
6224 AccAXLsh (char *x, int shCount)
6239 case 5: // AAAAABBB:CCCCCDDD
6241 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6243 emitcode ("anl", "a,#0x%02x",
6244 SLMask[shCount]); // BBB00000:CCCCCDDD
6246 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6248 AccRol (shCount); // DDDCCCCC:BBB00000
6250 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6252 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6254 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6256 emitcode ("anl", "a,#0x%02x",
6257 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6259 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6261 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6264 case 6: // AAAAAABB:CCCCCCDD
6265 emitcode ("anl", "a,#0x%02x",
6266 SRMask[shCount]); // 000000BB:CCCCCCDD
6267 emitcode ("mov", "c,acc.0"); // c = B
6268 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6270 AccAXRrl1 (x); // BCCCCCCD:D000000B
6271 AccAXRrl1 (x); // BBCCCCCC:DD000000
6273 emitcode("rrc","a");
6274 emitcode("xch","a,%s", x);
6275 emitcode("rrc","a");
6276 emitcode("mov","c,acc.0"); //<< get correct bit
6277 emitcode("xch","a,%s", x);
6279 emitcode("rrc","a");
6280 emitcode("xch","a,%s", x);
6281 emitcode("rrc","a");
6282 emitcode("xch","a,%s", x);
6285 case 7: // a:x <<= 7
6287 emitcode ("anl", "a,#0x%02x",
6288 SRMask[shCount]); // 0000000B:CCCCCCCD
6290 emitcode ("mov", "c,acc.0"); // c = B
6292 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6294 AccAXRrl1 (x); // BCCCCCCC:D0000000
6303 #ifdef BETTER_LITERAL_SHIFT
6305 /*-----------------------------------------------------------------*/
6306 /* AccAXRsh - right shift a:x known count (0..7) */
6307 /*-----------------------------------------------------------------*/
6309 AccAXRsh (char *x, int shCount)
6317 AccAXRrl1 (x); // 0->a:x
6322 AccAXRrl1 (x); // 0->a:x
6325 AccAXRrl1 (x); // 0->a:x
6330 case 5: // AAAAABBB:CCCCCDDD = a:x
6332 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6334 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6336 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6338 emitcode ("anl", "a,#0x%02x",
6339 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6341 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6343 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6345 emitcode ("anl", "a,#0x%02x",
6346 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6348 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6350 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6352 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6355 case 6: // AABBBBBB:CCDDDDDD
6357 emitcode ("mov", "c,acc.7");
6358 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6360 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6362 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6364 emitcode ("anl", "a,#0x%02x",
6365 SRMask[shCount]); // 000000AA:BBBBBBCC
6368 case 7: // ABBBBBBB:CDDDDDDD
6370 emitcode ("mov", "c,acc.7"); // c = A
6372 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6374 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6376 emitcode ("anl", "a,#0x%02x",
6377 SRMask[shCount]); // 0000000A:BBBBBBBC
6386 #ifdef BETTER_LITERAL_SHIFT
6388 /*-----------------------------------------------------------------*/
6389 /* AccAXRshS - right shift signed a:x known count (0..7) */
6390 /*-----------------------------------------------------------------*/
6392 AccAXRshS (char *x, int shCount)
6400 emitcode ("mov", "c,acc.7");
6401 AccAXRrl1 (x); // s->a:x
6405 emitcode ("mov", "c,acc.7");
6406 AccAXRrl1 (x); // s->a:x
6408 emitcode ("mov", "c,acc.7");
6409 AccAXRrl1 (x); // s->a:x
6414 case 5: // AAAAABBB:CCCCCDDD = a:x
6416 tlbl = newiTempLabel (NULL);
6417 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6419 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6421 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6423 emitcode ("anl", "a,#0x%02x",
6424 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6426 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6428 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6430 emitcode ("anl", "a,#0x%02x",
6431 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6433 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6435 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6437 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6439 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6440 emitcode ("orl", "a,#0x%02x",
6441 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6443 emitcode ("", "%05d$:", tlbl->key + 100);
6444 break; // SSSSAAAA:BBBCCCCC
6446 case 6: // AABBBBBB:CCDDDDDD
6448 tlbl = newiTempLabel (NULL);
6449 emitcode ("mov", "c,acc.7");
6450 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6452 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6454 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6456 emitcode ("anl", "a,#0x%02x",
6457 SRMask[shCount]); // 000000AA:BBBBBBCC
6459 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6460 emitcode ("orl", "a,#0x%02x",
6461 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6463 emitcode ("", "%05d$:", tlbl->key + 100);
6465 case 7: // ABBBBBBB:CDDDDDDD
6467 tlbl = newiTempLabel (NULL);
6468 emitcode ("mov", "c,acc.7"); // c = A
6470 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6472 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6474 emitcode ("anl", "a,#0x%02x",
6475 SRMask[shCount]); // 0000000A:BBBBBBBC
6477 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6478 emitcode ("orl", "a,#0x%02x",
6479 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6481 emitcode ("", "%05d$:", tlbl->key + 100);
6489 #ifdef BETTER_LITERAL_SHIFT
6491 _loadLeftIntoAx(char **lsb,
6497 // Get the initial value from left into a pair of registers.
6498 // MSB must be in A, LSB can be any register.
6500 // If the result is held in registers, it is an optimization
6501 // if the LSB can be held in the register which will hold the,
6502 // result LSB since this saves us from having to copy it into
6503 // the result following AccAXLsh.
6505 // If the result is addressed indirectly, this is not a gain.
6506 if (AOP_NEEDSACC(result))
6510 _startLazyDPSEvaluation();
6511 if (AOP_TYPE(left) == AOP_DPTR2)
6514 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6515 // get LSB in DP2_RESULT_REG.
6516 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6517 assert(!strcmp(leftByte, DP2_RESULT_REG));
6521 // get LSB into DP2_RESULT_REG
6522 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6523 if (strcmp(leftByte, DP2_RESULT_REG))
6525 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6528 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6529 assert(strcmp(leftByte, DP2_RESULT_REG));
6532 _endLazyDPSEvaluation();
6533 *lsb = DP2_RESULT_REG;
6537 if (sameRegs (AOP (result), AOP (left)) &&
6538 ((offl + MSB16) == offr))
6540 /* don't crash result[offr] */
6541 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6542 emitcode ("xch", "a,%s",
6543 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6547 movLeft2Result (left, offl, result, offr, 0);
6548 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6550 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6551 assert(strcmp(*lsb,"a"));
6556 _storeAxResults(char *lsb,
6560 _startLazyDPSEvaluation();
6561 if (AOP_NEEDSACC(result))
6563 /* We have to explicitly update the result LSB.
6565 emitcode("xch","a,%s", lsb);
6566 aopPut(AOP(result), "a", offr);
6567 emitcode("mov","a,%s", lsb);
6569 if (getDataSize (result) > 1)
6571 aopPut (AOP (result), "a", offr + MSB16);
6573 _endLazyDPSEvaluation();
6576 /*-----------------------------------------------------------------*/
6577 /* shiftL2Left2Result - shift left two bytes from left to result */
6578 /*-----------------------------------------------------------------*/
6580 shiftL2Left2Result (operand * left, int offl,
6581 operand * result, int offr, int shCount)
6585 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6587 AccAXLsh (lsb, shCount);
6589 _storeAxResults(lsb, result, offr);
6593 #ifdef BETTER_LITERAL_SHIFT
6594 /*-----------------------------------------------------------------*/
6595 /* shiftR2Left2Result - shift right two bytes from left to result */
6596 /*-----------------------------------------------------------------*/
6598 shiftR2Left2Result (operand * left, int offl,
6599 operand * result, int offr,
6600 int shCount, int sign)
6604 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6606 /* a:x >> shCount (x = lsb(result)) */
6609 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6613 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6616 _storeAxResults(lsb, result, offr);
6622 /*-----------------------------------------------------------------*/
6623 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6624 /*-----------------------------------------------------------------*/
6626 shiftLLeftOrResult (operand * left, int offl,
6627 operand * result, int offr, int shCount)
6629 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6630 /* shift left accumulator */
6632 /* or with result */
6633 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6634 /* back to result */
6635 aopPut (AOP (result), "a", offr);
6641 /*-----------------------------------------------------------------*/
6642 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6643 /*-----------------------------------------------------------------*/
6645 shiftRLeftOrResult (operand * left, int offl,
6646 operand * result, int offr, int shCount)
6648 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6649 /* shift right accumulator */
6651 /* or with result */
6652 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6653 /* back to result */
6654 aopPut (AOP (result), "a", offr);
6658 #ifdef BETTER_LITERAL_SHIFT
6659 /*-----------------------------------------------------------------*/
6660 /* genlshOne - left shift a one byte quantity by known count */
6661 /*-----------------------------------------------------------------*/
6663 genlshOne (operand * result, operand * left, int shCount)
6665 D (emitcode (";", "genlshOne "););
6666 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6670 #ifdef BETTER_LITERAL_SHIFT
6671 /*-----------------------------------------------------------------*/
6672 /* genlshTwo - left shift two bytes by known amount != 0 */
6673 /*-----------------------------------------------------------------*/
6675 genlshTwo (operand * result, operand * left, int shCount)
6679 D (emitcode (";", "genlshTwo "););
6681 size = getDataSize (result);
6683 /* if shCount >= 8 */
6688 _startLazyDPSEvaluation();
6694 _endLazyDPSEvaluation();
6695 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6696 aopPut (AOP (result), zero, LSB);
6700 movLeft2Result (left, LSB, result, MSB16, 0);
6701 aopPut (AOP (result), zero, LSB);
6702 _endLazyDPSEvaluation();
6707 aopPut (AOP (result), zero, LSB);
6708 _endLazyDPSEvaluation();
6712 /* 1 <= shCount <= 7 */
6717 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6721 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6729 /*-----------------------------------------------------------------*/
6730 /* shiftLLong - shift left one long from left to result */
6731 /* offl = LSB or MSB16 */
6732 /*-----------------------------------------------------------------*/
6734 shiftLLong (operand * left, operand * result, int offr)
6737 int size = AOP_SIZE (result);
6739 if (size >= LSB + offr)
6741 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6743 emitcode ("add", "a,acc");
6744 if (sameRegs (AOP (left), AOP (result)) &&
6745 size >= MSB16 + offr && offr != LSB)
6746 emitcode ("xch", "a,%s",
6747 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6749 aopPut (AOP (result), "a", LSB + offr);
6752 if (size >= MSB16 + offr)
6754 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6756 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6759 emitcode ("rlc", "a");
6760 if (sameRegs (AOP (left), AOP (result)) &&
6761 size >= MSB24 + offr && offr != LSB)
6762 emitcode ("xch", "a,%s",
6763 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6765 aopPut (AOP (result), "a", MSB16 + offr);
6768 if (size >= MSB24 + offr)
6770 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6772 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6775 emitcode ("rlc", "a");
6776 if (sameRegs (AOP (left), AOP (result)) &&
6777 size >= MSB32 + offr && offr != LSB)
6778 emitcode ("xch", "a,%s",
6779 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6781 aopPut (AOP (result), "a", MSB24 + offr);
6784 if (size > MSB32 + offr)
6786 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6788 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6791 emitcode ("rlc", "a");
6792 aopPut (AOP (result), "a", MSB32 + offr);
6795 aopPut (AOP (result), zero, LSB);
6801 /*-----------------------------------------------------------------*/
6802 /* genlshFour - shift four byte by a known amount != 0 */
6803 /*-----------------------------------------------------------------*/
6805 genlshFour (operand * result, operand * left, int shCount)
6809 D (emitcode (";", "genlshFour ");
6812 size = AOP_SIZE (result);
6814 /* if shifting more that 3 bytes */
6819 /* lowest order of left goes to the highest
6820 order of the destination */
6821 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6823 movLeft2Result (left, LSB, result, MSB32, 0);
6824 aopPut (AOP (result), zero, LSB);
6825 aopPut (AOP (result), zero, MSB16);
6826 aopPut (AOP (result), zero, MSB24);
6830 /* more than two bytes */
6831 else if (shCount >= 16)
6833 /* lower order two bytes goes to higher order two bytes */
6835 /* if some more remaining */
6837 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6840 movLeft2Result (left, MSB16, result, MSB32, 0);
6841 movLeft2Result (left, LSB, result, MSB24, 0);
6843 aopPut (AOP (result), zero, MSB16);
6844 aopPut (AOP (result), zero, LSB);
6848 /* if more than 1 byte */
6849 else if (shCount >= 8)
6851 /* lower order three bytes goes to higher order three bytes */
6856 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6858 movLeft2Result (left, LSB, result, MSB16, 0);
6864 movLeft2Result (left, MSB24, result, MSB32, 0);
6865 movLeft2Result (left, MSB16, result, MSB24, 0);
6866 movLeft2Result (left, LSB, result, MSB16, 0);
6867 aopPut (AOP (result), zero, LSB);
6869 else if (shCount == 1)
6870 shiftLLong (left, result, MSB16);
6873 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6874 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6875 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6876 aopPut (AOP (result), zero, LSB);
6881 /* 1 <= shCount <= 7 */
6882 else if (shCount <= 2)
6884 shiftLLong (left, result, LSB);
6886 shiftLLong (result, result, LSB);
6888 /* 3 <= shCount <= 7, optimize */
6891 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6892 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6893 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6898 #ifdef BETTER_LITERAL_SHIFT
6899 /*-----------------------------------------------------------------*/
6900 /* genLeftShiftLiteral - left shifting by known count */
6901 /*-----------------------------------------------------------------*/
6903 genLeftShiftLiteral (operand * left,
6908 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6911 size = getSize (operandType (result));
6913 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6915 /* We only handle certain easy cases so far. */
6917 && (shCount < (size * 8))
6921 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6925 freeAsmop (right, NULL, ic, TRUE);
6927 aopOp(left, ic, FALSE, FALSE);
6928 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6931 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6933 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6934 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6936 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6939 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6941 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6942 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6944 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6950 emitcode ("; shift left ", "result %d, left %d", size,
6954 /* I suppose that the left size >= result size */
6957 _startLazyDPSEvaluation();
6960 movLeft2Result (left, size, result, size, 0);
6962 _endLazyDPSEvaluation();
6964 else if (shCount >= (size * 8))
6966 _startLazyDPSEvaluation();
6969 aopPut (AOP (result), zero, size);
6971 _endLazyDPSEvaluation();
6978 genlshOne (result, left, shCount);
6982 genlshTwo (result, left, shCount);
6986 genlshFour (result, left, shCount);
6990 fprintf(stderr, "*** ack! mystery literal shift!\n");
6994 freeAsmop (left, NULL, ic, TRUE);
6995 freeAsmop (result, NULL, ic, TRUE);
7000 /*-----------------------------------------------------------------*/
7001 /* genLeftShift - generates code for left shifting */
7002 /*-----------------------------------------------------------------*/
7004 genLeftShift (iCode * ic)
7006 operand *left, *right, *result;
7009 symbol *tlbl, *tlbl1;
7011 D (emitcode (";", "genLeftShift "););
7013 right = IC_RIGHT (ic);
7014 left = IC_LEFT (ic);
7015 result = IC_RESULT (ic);
7017 aopOp (right, ic, FALSE, FALSE);
7020 #ifdef BETTER_LITERAL_SHIFT
7021 /* if the shift count is known then do it
7022 as efficiently as possible */
7023 if (AOP_TYPE (right) == AOP_LIT)
7025 if (genLeftShiftLiteral (left, right, result, ic))
7032 /* shift count is unknown then we have to form
7033 a loop get the loop count in B : Note: we take
7034 only the lower order byte since shifting
7035 more that 32 bits make no sense anyway, ( the
7036 largest size of an object can be only 32 bits ) */
7038 if (AOP_TYPE (right) == AOP_LIT)
7040 /* Really should be handled by genLeftShiftLiteral,
7041 * but since I'm too lazy to fix that today, at least we can make
7042 * some small improvement.
7044 emitcode("mov", "b,#0x%02x",
7045 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7049 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7050 emitcode ("inc", "b");
7052 freeAsmop (right, NULL, ic, TRUE);
7053 aopOp (left, ic, FALSE, FALSE);
7054 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7056 /* now move the left to the result if they are not the
7058 if (!sameRegs (AOP (left), AOP (result)) &&
7059 AOP_SIZE (result) > 1)
7062 size = AOP_SIZE (result);
7064 _startLazyDPSEvaluation ();
7067 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7068 if (*l == '@' && (IS_AOP_PREG (result)))
7071 emitcode ("mov", "a,%s", l);
7072 aopPut (AOP (result), "a", offset);
7075 aopPut (AOP (result), l, offset);
7078 _endLazyDPSEvaluation ();
7081 tlbl = newiTempLabel (NULL);
7082 size = AOP_SIZE (result);
7084 tlbl1 = newiTempLabel (NULL);
7086 /* if it is only one byte then */
7089 symbol *tlbl1 = newiTempLabel (NULL);
7091 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7093 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7094 emitcode ("", "%05d$:", tlbl->key + 100);
7095 emitcode ("add", "a,acc");
7096 emitcode ("", "%05d$:", tlbl1->key + 100);
7097 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7098 aopPut (AOP (result), "a", 0);
7102 reAdjustPreg (AOP (result));
7104 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7105 emitcode ("", "%05d$:", tlbl->key + 100);
7106 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7108 emitcode ("add", "a,acc");
7109 aopPut (AOP (result), "a", offset++);
7110 _startLazyDPSEvaluation ();
7113 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7115 emitcode ("rlc", "a");
7116 aopPut (AOP (result), "a", offset++);
7118 _endLazyDPSEvaluation ();
7119 reAdjustPreg (AOP (result));
7121 emitcode ("", "%05d$:", tlbl1->key + 100);
7122 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7124 freeAsmop (left, NULL, ic, TRUE);
7125 freeAsmop (result, NULL, ic, TRUE);
7128 #ifdef BETTER_LITERAL_SHIFT
7129 /*-----------------------------------------------------------------*/
7130 /* genrshOne - right shift a one byte quantity by known count */
7131 /*-----------------------------------------------------------------*/
7133 genrshOne (operand * result, operand * left,
7134 int shCount, int sign)
7136 D (emitcode (";", "genrshOne"););
7137 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7141 #ifdef BETTER_LITERAL_SHIFT
7142 /*-----------------------------------------------------------------*/
7143 /* genrshTwo - right shift two bytes by known amount != 0 */
7144 /*-----------------------------------------------------------------*/
7146 genrshTwo (operand * result, operand * left,
7147 int shCount, int sign)
7149 D (emitcode (";", "genrshTwo"););
7151 /* if shCount >= 8 */
7155 _startLazyDPSEvaluation();
7158 shiftR1Left2Result (left, MSB16, result, LSB,
7163 movLeft2Result (left, MSB16, result, LSB, sign);
7165 addSign (result, MSB16, sign);
7166 _endLazyDPSEvaluation();
7169 /* 1 <= shCount <= 7 */
7172 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7179 /*-----------------------------------------------------------------*/
7180 /* shiftRLong - shift right one long from left to result */
7181 /* offl = LSB or MSB16 */
7182 /*-----------------------------------------------------------------*/
7184 shiftRLong (operand * left, int offl,
7185 operand * result, int sign)
7188 emitcode ("clr", "c");
7189 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7191 emitcode ("mov", "c,acc.7");
7192 emitcode ("rrc", "a");
7193 aopPut (AOP (result), "a", MSB32 - offl);
7195 /* add sign of "a" */
7196 addSign (result, MSB32, sign);
7198 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7199 emitcode ("rrc", "a");
7200 aopPut (AOP (result), "a", MSB24 - offl);
7202 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7203 emitcode ("rrc", "a");
7204 aopPut (AOP (result), "a", MSB16 - offl);
7208 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7209 emitcode ("rrc", "a");
7210 aopPut (AOP (result), "a", LSB);
7217 /*-----------------------------------------------------------------*/
7218 /* genrshFour - shift four byte by a known amount != 0 */
7219 /*-----------------------------------------------------------------*/
7221 genrshFour (operand * result, operand * left,
7222 int shCount, int sign)
7224 D (emitcode (";", "genrshFour");
7227 /* if shifting more that 3 bytes */
7232 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7234 movLeft2Result (left, MSB32, result, LSB, sign);
7235 addSign (result, MSB16, sign);
7237 else if (shCount >= 16)
7241 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7244 movLeft2Result (left, MSB24, result, LSB, 0);
7245 movLeft2Result (left, MSB32, result, MSB16, sign);
7247 addSign (result, MSB24, sign);
7249 else if (shCount >= 8)
7253 shiftRLong (left, MSB16, result, sign);
7254 else if (shCount == 0)
7256 movLeft2Result (left, MSB16, result, LSB, 0);
7257 movLeft2Result (left, MSB24, result, MSB16, 0);
7258 movLeft2Result (left, MSB32, result, MSB24, sign);
7259 addSign (result, MSB32, sign);
7263 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7264 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7265 /* the last shift is signed */
7266 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7267 addSign (result, MSB32, sign);
7271 { /* 1 <= shCount <= 7 */
7274 shiftRLong (left, LSB, result, sign);
7276 shiftRLong (result, LSB, result, sign);
7280 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7281 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7282 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7288 #ifdef BETTER_LITERAL_SHIFT
7289 /*-----------------------------------------------------------------*/
7290 /* genRightShiftLiteral - right shifting by known count */
7291 /*-----------------------------------------------------------------*/
7293 genRightShiftLiteral (operand * left,
7299 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7302 size = getSize (operandType (result));
7304 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7306 /* We only handle certain easy cases so far. */
7308 && (shCount < (size * 8))
7312 D(emitcode (";", "genRightShiftLiteral wimping out"););
7316 freeAsmop (right, NULL, ic, TRUE);
7318 aopOp (left, ic, FALSE, FALSE);
7319 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7322 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7326 /* test the LEFT size !!! */
7328 /* I suppose that the left size >= result size */
7331 size = getDataSize (result);
7332 _startLazyDPSEvaluation();
7335 movLeft2Result (left, size, result, size, 0);
7337 _endLazyDPSEvaluation();
7339 else if (shCount >= (size * 8))
7343 /* get sign in acc.7 */
7344 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7346 addSign (result, LSB, sign);
7353 genrshOne (result, left, shCount, sign);
7357 genrshTwo (result, left, shCount, sign);
7361 genrshFour (result, left, shCount, sign);
7368 freeAsmop (left, NULL, ic, TRUE);
7369 freeAsmop (result, NULL, ic, TRUE);
7375 /*-----------------------------------------------------------------*/
7376 /* genSignedRightShift - right shift of signed number */
7377 /*-----------------------------------------------------------------*/
7379 genSignedRightShift (iCode * ic)
7381 operand *right, *left, *result;
7384 symbol *tlbl, *tlbl1;
7386 D (emitcode (";", "genSignedRightShift "););
7388 /* we do it the hard way put the shift count in b
7389 and loop thru preserving the sign */
7391 right = IC_RIGHT (ic);
7392 left = IC_LEFT (ic);
7393 result = IC_RESULT (ic);
7395 aopOp (right, ic, FALSE, FALSE);
7397 #ifdef BETTER_LITERAL_SHIFT
7398 if (AOP_TYPE (right) == AOP_LIT)
7400 if (genRightShiftLiteral (left, right, result, ic, 1))
7406 /* shift count is unknown then we have to form
7407 a loop get the loop count in B : Note: we take
7408 only the lower order byte since shifting
7409 more that 32 bits make no sense anyway, ( the
7410 largest size of an object can be only 32 bits ) */
7412 if (AOP_TYPE (right) == AOP_LIT)
7414 /* Really should be handled by genRightShiftLiteral,
7415 * but since I'm too lazy to fix that today, at least we can make
7416 * some small improvement.
7418 emitcode("mov", "b,#0x%02x",
7419 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7423 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7424 emitcode ("inc", "b");
7426 freeAsmop (right, NULL, ic, TRUE);
7427 aopOp (left, ic, FALSE, FALSE);
7428 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7430 /* now move the left to the result if they are not the
7432 if (!sameRegs (AOP (left), AOP (result)) &&
7433 AOP_SIZE (result) > 1)
7436 size = AOP_SIZE (result);
7438 _startLazyDPSEvaluation ();
7441 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7442 if (*l == '@' && IS_AOP_PREG (result))
7445 emitcode ("mov", "a,%s", l);
7446 aopPut (AOP (result), "a", offset);
7449 aopPut (AOP (result), l, offset);
7452 _endLazyDPSEvaluation ();
7455 /* mov the highest order bit to OVR */
7456 tlbl = newiTempLabel (NULL);
7457 tlbl1 = newiTempLabel (NULL);
7459 size = AOP_SIZE (result);
7461 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7462 emitcode ("rlc", "a");
7463 emitcode ("mov", "ov,c");
7464 /* if it is only one byte then */
7467 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7469 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7470 emitcode ("", "%05d$:", tlbl->key + 100);
7471 emitcode ("mov", "c,ov");
7472 emitcode ("rrc", "a");
7473 emitcode ("", "%05d$:", tlbl1->key + 100);
7474 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7475 aopPut (AOP (result), "a", 0);
7479 reAdjustPreg (AOP (result));
7480 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7481 emitcode ("", "%05d$:", tlbl->key + 100);
7482 emitcode ("mov", "c,ov");
7483 _startLazyDPSEvaluation ();
7486 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7488 emitcode ("rrc", "a");
7489 aopPut (AOP (result), "a", offset--);
7491 _endLazyDPSEvaluation ();
7492 reAdjustPreg (AOP (result));
7493 emitcode ("", "%05d$:", tlbl1->key + 100);
7494 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7497 freeAsmop (left, NULL, ic, TRUE);
7498 freeAsmop (result, NULL, ic, TRUE);
7501 /*-----------------------------------------------------------------*/
7502 /* genRightShift - generate code for right shifting */
7503 /*-----------------------------------------------------------------*/
7505 genRightShift (iCode * ic)
7507 operand *right, *left, *result;
7511 symbol *tlbl, *tlbl1;
7513 D (emitcode (";", "genRightShift "););
7515 /* if signed then we do it the hard way preserve the
7516 sign bit moving it inwards */
7517 retype = getSpec (operandType (IC_RESULT (ic)));
7519 if (!SPEC_USIGN (retype))
7521 genSignedRightShift (ic);
7525 /* signed & unsigned types are treated the same : i.e. the
7526 signed is NOT propagated inwards : quoting from the
7527 ANSI - standard : "for E1 >> E2, is equivalent to division
7528 by 2**E2 if unsigned or if it has a non-negative value,
7529 otherwise the result is implementation defined ", MY definition
7530 is that the sign does not get propagated */
7532 right = IC_RIGHT (ic);
7533 left = IC_LEFT (ic);
7534 result = IC_RESULT (ic);
7536 aopOp (right, ic, FALSE, FALSE);
7538 #ifdef BETTER_LITERAL_SHIFT
7539 /* if the shift count is known then do it
7540 as efficiently as possible */
7541 if (AOP_TYPE (right) == AOP_LIT)
7543 if (genRightShiftLiteral (left, right, result, ic, 0))
7550 /* shift count is unknown then we have to form
7551 a loop get the loop count in B : Note: we take
7552 only the lower order byte since shifting
7553 more that 32 bits make no sense anyway, ( the
7554 largest size of an object can be only 32 bits ) */
7556 if (AOP_TYPE (right) == AOP_LIT)
7558 /* Really should be handled by genRightShiftLiteral,
7559 * but since I'm too lazy to fix that today, at least we can make
7560 * some small improvement.
7562 emitcode("mov", "b,#0x%02x",
7563 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7567 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7568 emitcode ("inc", "b");
7570 freeAsmop (right, NULL, ic, TRUE);
7571 aopOp (left, ic, FALSE, FALSE);
7572 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7574 /* now move the left to the result if they are not the
7576 if (!sameRegs (AOP (left), AOP (result)) &&
7577 AOP_SIZE (result) > 1)
7580 size = AOP_SIZE (result);
7582 _startLazyDPSEvaluation ();
7585 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7586 if (*l == '@' && IS_AOP_PREG (result))
7589 emitcode ("mov", "a,%s", l);
7590 aopPut (AOP (result), "a", offset);
7593 aopPut (AOP (result), l, offset);
7596 _endLazyDPSEvaluation ();
7599 tlbl = newiTempLabel (NULL);
7600 tlbl1 = newiTempLabel (NULL);
7601 size = AOP_SIZE (result);
7604 /* if it is only one byte then */
7607 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7609 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7610 emitcode ("", "%05d$:", tlbl->key + 100);
7612 emitcode ("rrc", "a");
7613 emitcode ("", "%05d$:", tlbl1->key + 100);
7614 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7615 aopPut (AOP (result), "a", 0);
7619 reAdjustPreg (AOP (result));
7620 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7621 emitcode ("", "%05d$:", tlbl->key + 100);
7623 _startLazyDPSEvaluation ();
7626 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7628 emitcode ("rrc", "a");
7629 aopPut (AOP (result), "a", offset--);
7631 _endLazyDPSEvaluation ();
7632 reAdjustPreg (AOP (result));
7634 emitcode ("", "%05d$:", tlbl1->key + 100);
7635 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7638 freeAsmop (left, NULL, ic, TRUE);
7639 freeAsmop (result, NULL, ic, TRUE);
7642 /*-----------------------------------------------------------------*/
7643 /* genUnpackBits - generates code for unpacking bits */
7644 /*-----------------------------------------------------------------*/
7646 genUnpackBits (operand * result, char *rname, int ptype)
7653 D (emitcode (";", "genUnpackBits ");
7656 etype = getSpec (operandType (result));
7658 /* read the first byte */
7664 emitcode ("mov", "a,@%s", rname);
7668 emitcode ("movx", "a,@%s", rname);
7672 emitcode ("movx", "a,@dptr");
7676 emitcode ("clr", "a");
7677 emitcode ("movc", "a", "@a+dptr");
7681 emitcode ("lcall", "__gptrget");
7685 /* if we have bitdisplacement then it fits */
7686 /* into this byte completely or if length is */
7687 /* less than a byte */
7688 if ((shCnt = SPEC_BSTR (etype)) ||
7689 (SPEC_BLEN (etype) <= 8))
7692 /* shift right acc */
7695 emitcode ("anl", "a,#0x%02x",
7696 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7697 aopPut (AOP (result), "a", offset);
7701 /* bit field did not fit in a byte */
7702 rlen = SPEC_BLEN (etype) - 8;
7703 aopPut (AOP (result), "a", offset++);
7712 emitcode ("inc", "%s", rname);
7713 emitcode ("mov", "a,@%s", rname);
7717 emitcode ("inc", "%s", rname);
7718 emitcode ("movx", "a,@%s", rname);
7722 emitcode ("inc", "dptr");
7723 emitcode ("movx", "a,@dptr");
7727 emitcode ("clr", "a");
7728 emitcode ("inc", "dptr");
7729 emitcode ("movc", "a", "@a+dptr");
7733 emitcode ("inc", "dptr");
7734 emitcode ("lcall", "__gptrget");
7739 /* if we are done */
7743 aopPut (AOP (result), "a", offset++);
7749 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7750 aopPut (AOP (result), "a", offset);
7757 /*-----------------------------------------------------------------*/
7758 /* genDataPointerGet - generates code when ptr offset is known */
7759 /*-----------------------------------------------------------------*/
7761 genDataPointerGet (operand * left,
7767 int size, offset = 0;
7768 aopOp (result, ic, TRUE, FALSE);
7770 /* get the string representation of the name */
7771 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7772 size = AOP_SIZE (result);
7773 _startLazyDPSEvaluation ();
7777 sprintf (buffer, "(%s + %d)", l + 1, offset);
7779 sprintf (buffer, "%s", l + 1);
7780 aopPut (AOP (result), buffer, offset++);
7782 _endLazyDPSEvaluation ();
7784 freeAsmop (left, NULL, ic, TRUE);
7785 freeAsmop (result, NULL, ic, TRUE);
7788 /*-----------------------------------------------------------------*/
7789 /* genNearPointerGet - emitcode for near pointer fetch */
7790 /*-----------------------------------------------------------------*/
7792 genNearPointerGet (operand * left,
7799 sym_link *rtype, *retype, *letype;
7800 sym_link *ltype = operandType (left);
7803 rtype = operandType (result);
7804 retype = getSpec (rtype);
7805 letype = getSpec (ltype);
7807 aopOp (left, ic, FALSE, FALSE);
7809 /* if left is rematerialisable and
7810 result is not bit variable type and
7811 the left is pointer to data space i.e
7812 lower 128 bytes of space */
7813 if (AOP_TYPE (left) == AOP_IMMD &&
7814 !IS_BITVAR (retype) &&
7815 !IS_BITVAR (letype) &&
7816 DCL_TYPE (ltype) == POINTER)
7818 genDataPointerGet (left, result, ic);
7822 /* if the value is already in a pointer register
7823 then don't need anything more */
7824 if (!AOP_INPREG (AOP (left)))
7826 /* otherwise get a free pointer register */
7828 preg = getFreePtr (ic, &aop, FALSE);
7829 emitcode ("mov", "%s,%s",
7831 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7835 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7837 freeAsmop (left, NULL, ic, TRUE);
7838 aopOp (result, ic, FALSE, FALSE);
7840 /* if bitfield then unpack the bits */
7841 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7842 genUnpackBits (result, rname, POINTER);
7845 /* we have can just get the values */
7846 int size = AOP_SIZE (result);
7851 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7854 emitcode ("mov", "a,@%s", rname);
7855 aopPut (AOP (result), "a", offset);
7859 sprintf (buffer, "@%s", rname);
7860 aopPut (AOP (result), buffer, offset);
7864 emitcode ("inc", "%s", rname);
7868 /* now some housekeeping stuff */
7871 /* we had to allocate for this iCode */
7872 freeAsmop (NULL, aop, ic, TRUE);
7876 /* we did not allocate which means left
7877 already in a pointer register, then
7878 if size > 0 && this could be used again
7879 we have to point it back to where it
7881 if (AOP_SIZE (result) > 1 &&
7882 !OP_SYMBOL (left)->remat &&
7883 (OP_SYMBOL (left)->liveTo > ic->seq ||
7886 int size = AOP_SIZE (result) - 1;
7888 emitcode ("dec", "%s", rname);
7893 freeAsmop (result, NULL, ic, TRUE);
7897 /*-----------------------------------------------------------------*/
7898 /* genPagedPointerGet - emitcode for paged pointer fetch */
7899 /*-----------------------------------------------------------------*/
7901 genPagedPointerGet (operand * left,
7908 sym_link *rtype, *retype, *letype;
7910 rtype = operandType (result);
7911 retype = getSpec (rtype);
7912 letype = getSpec (operandType (left));
7913 aopOp (left, ic, FALSE, FALSE);
7915 /* if the value is already in a pointer register
7916 then don't need anything more */
7917 if (!AOP_INPREG (AOP (left)))
7919 /* otherwise get a free pointer register */
7921 preg = getFreePtr (ic, &aop, FALSE);
7922 emitcode ("mov", "%s,%s",
7924 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7928 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7930 freeAsmop (left, NULL, ic, TRUE);
7931 aopOp (result, ic, FALSE, FALSE);
7933 /* if bitfield then unpack the bits */
7934 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7935 genUnpackBits (result, rname, PPOINTER);
7938 /* we have can just get the values */
7939 int size = AOP_SIZE (result);
7945 emitcode ("movx", "a,@%s", rname);
7946 aopPut (AOP (result), "a", offset);
7951 emitcode ("inc", "%s", rname);
7955 /* now some housekeeping stuff */
7958 /* we had to allocate for this iCode */
7959 freeAsmop (NULL, aop, ic, TRUE);
7963 /* we did not allocate which means left
7964 already in a pointer register, then
7965 if size > 0 && this could be used again
7966 we have to point it back to where it
7968 if (AOP_SIZE (result) > 1 &&
7969 !OP_SYMBOL (left)->remat &&
7970 (OP_SYMBOL (left)->liveTo > ic->seq ||
7973 int size = AOP_SIZE (result) - 1;
7975 emitcode ("dec", "%s", rname);
7980 freeAsmop (result, NULL, ic, TRUE);
7985 /*-----------------------------------------------------------------*/
7986 /* genFarPointerGet - gget value from far space */
7987 /*-----------------------------------------------------------------*/
7989 genFarPointerGet (operand * left,
7990 operand * result, iCode * ic)
7993 sym_link *retype = getSpec (operandType (result));
7994 sym_link *letype = getSpec (operandType (left));
7995 D (emitcode (";", "genFarPointerGet");
7998 aopOp (left, ic, FALSE, FALSE);
8000 /* if the operand is already in dptr
8001 then we do nothing else we move the value to dptr */
8002 if (AOP_TYPE (left) != AOP_STR)
8004 /* if this is remateriazable */
8005 if (AOP_TYPE (left) == AOP_IMMD)
8007 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8011 /* we need to get it byte by byte */
8012 _startLazyDPSEvaluation ();
8013 if (AOP_TYPE (left) != AOP_DPTR)
8015 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8016 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8017 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8021 /* We need to generate a load to DPTR indirect through DPTR. */
8022 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8024 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8025 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8026 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8027 emitcode ("pop", "dph");
8028 emitcode ("pop", "dpl");
8030 _endLazyDPSEvaluation ();
8033 /* so dptr know contains the address */
8034 freeAsmop (left, NULL, ic, TRUE);
8035 aopOp (result, ic, FALSE, TRUE);
8037 /* if bit then unpack */
8038 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8039 genUnpackBits (result, "dptr", FPOINTER);
8042 size = AOP_SIZE (result);
8045 _startLazyDPSEvaluation ();
8052 emitcode ("movx", "a,@dptr");
8054 emitcode ("inc", "dptr");
8056 aopPut (AOP (result), "a", offset++);
8058 _endLazyDPSEvaluation ();
8061 freeAsmop (result, NULL, ic, TRUE);
8064 /*-----------------------------------------------------------------*/
8065 /* emitcodePointerGet - gget value from code space */
8066 /*-----------------------------------------------------------------*/
8068 emitcodePointerGet (operand * left,
8069 operand * result, iCode * ic)
8072 sym_link *retype = getSpec (operandType (result));
8074 aopOp (left, ic, FALSE, FALSE);
8076 /* if the operand is already in dptr
8077 then we do nothing else we move the value to dptr */
8078 if (AOP_TYPE (left) != AOP_STR)
8080 /* if this is remateriazable */
8081 if (AOP_TYPE (left) == AOP_IMMD)
8083 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8086 { /* we need to get it byte by byte */
8087 _startLazyDPSEvaluation ();
8088 if (AOP_TYPE (left) != AOP_DPTR)
8090 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8091 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8092 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8096 /* We need to generate a load to DPTR indirect through DPTR. */
8097 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8099 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8100 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8101 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8102 emitcode ("pop", "dph");
8103 emitcode ("pop", "dpl");
8105 _endLazyDPSEvaluation ();
8108 /* so dptr know contains the address */
8109 freeAsmop (left, NULL, ic, TRUE);
8110 aopOp (result, ic, FALSE, TRUE);
8112 /* if bit then unpack */
8113 if (IS_BITVAR (retype))
8114 genUnpackBits (result, "dptr", CPOINTER);
8117 size = AOP_SIZE (result);
8120 _startLazyDPSEvaluation ();
8126 emitcode ("clr", "a");
8127 emitcode ("movc", "a,@a+dptr");
8129 emitcode ("inc", "dptr");
8130 aopPut (AOP (result), "a", offset++);
8132 _endLazyDPSEvaluation ();
8135 freeAsmop (result, NULL, ic, TRUE);
8138 /*-----------------------------------------------------------------*/
8139 /* genGenPointerGet - gget value from generic pointer space */
8140 /*-----------------------------------------------------------------*/
8142 genGenPointerGet (operand * left,
8143 operand * result, iCode * ic)
8146 sym_link *retype = getSpec (operandType (result));
8147 sym_link *letype = getSpec (operandType (left));
8149 D (emitcode (";", "genGenPointerGet "); );
8151 aopOp (left, ic, FALSE, TRUE);
8153 /* if the operand is already in dptr
8154 then we do nothing else we move the value to dptr */
8155 if (AOP_TYPE (left) != AOP_STR)
8157 /* if this is remateriazable */
8158 if (AOP_TYPE (left) == AOP_IMMD)
8160 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8161 emitcode ("mov", "b,#%d", pointerCode (retype));
8164 { /* we need to get it byte by byte */
8165 _startLazyDPSEvaluation ();
8166 if (AOP(left)->type==AOP_DPTR2) {
8168 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8171 emitcode ("mov", "dpl,%s", l);
8172 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8175 emitcode ("mov", "dph,%s", l);
8176 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8179 emitcode ("mov", "dpx,%s", l);
8180 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8182 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8183 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8184 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8185 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8187 _endLazyDPSEvaluation ();
8190 /* so dptr know contains the address */
8191 freeAsmop (left, NULL, ic, TRUE);
8192 aopOp (result, ic, FALSE, TRUE);
8194 /* if bit then unpack */
8195 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8196 genUnpackBits (result, "dptr", GPOINTER);
8199 size = AOP_SIZE (result);
8204 emitcode ("lcall", "__gptrget");
8205 aopPut (AOP (result), "a", offset++);
8207 emitcode ("inc", "dptr");
8211 freeAsmop (result, NULL, ic, TRUE);
8214 /*-----------------------------------------------------------------*/
8215 /* genPointerGet - generate code for pointer get */
8216 /*-----------------------------------------------------------------*/
8218 genPointerGet (iCode * ic)
8220 operand *left, *result;
8221 sym_link *type, *etype;
8224 D (emitcode (";", "genPointerGet ");
8227 left = IC_LEFT (ic);
8228 result = IC_RESULT (ic);
8230 /* depending on the type of pointer we need to
8231 move it to the correct pointer register */
8232 type = operandType (left);
8233 etype = getSpec (type);
8234 /* if left is of type of pointer then it is simple */
8235 if (IS_PTR (type) && !IS_FUNC (type->next))
8236 p_type = DCL_TYPE (type);
8239 /* we have to go by the storage class */
8240 p_type = PTR_TYPE (SPEC_OCLS (etype));
8243 /* now that we have the pointer type we assign
8244 the pointer values */
8250 genNearPointerGet (left, result, ic);
8254 genPagedPointerGet (left, result, ic);
8258 genFarPointerGet (left, result, ic);
8262 emitcodePointerGet (left, result, ic);
8266 genGenPointerGet (left, result, ic);
8272 /*-----------------------------------------------------------------*/
8273 /* genPackBits - generates code for packed bit storage */
8274 /*-----------------------------------------------------------------*/
8276 genPackBits (sym_link * etype,
8278 char *rname, int p_type)
8286 blen = SPEC_BLEN (etype);
8287 bstr = SPEC_BSTR (etype);
8289 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8292 /* if the bit lenth is less than or */
8293 /* it exactly fits a byte then */
8294 if (SPEC_BLEN (etype) <= 8)
8296 shCount = SPEC_BSTR (etype);
8298 /* shift left acc */
8301 if (SPEC_BLEN (etype) < 8)
8302 { /* if smaller than a byte */
8308 emitcode ("mov", "b,a");
8309 emitcode ("mov", "a,@%s", rname);
8313 emitcode ("mov", "b,a");
8314 emitcode ("movx", "a,@dptr");
8318 emitcode ("push", "b");
8319 emitcode ("push", "acc");
8320 emitcode ("lcall", "__gptrget");
8321 emitcode ("pop", "b");
8325 emitcode ("anl", "a,#0x%02x", (unsigned char)
8326 ((unsigned char) (0xFF << (blen + bstr)) |
8327 (unsigned char) (0xFF >> (8 - bstr))));
8328 emitcode ("orl", "a,b");
8329 if (p_type == GPOINTER)
8330 emitcode ("pop", "b");
8337 emitcode ("mov", "@%s,a", rname);
8341 emitcode ("movx", "@dptr,a");
8345 emitcode ("lcall", "__gptrput");
8350 if (SPEC_BLEN (etype) <= 8)
8353 emitcode ("inc", "%s", rname);
8354 rLen = SPEC_BLEN (etype);
8356 /* now generate for lengths greater than one byte */
8360 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8372 emitcode ("mov", "@%s,a", rname);
8375 emitcode ("mov", "@%s,%s", rname, l);
8380 emitcode ("movx", "@dptr,a");
8385 emitcode ("lcall", "__gptrput");
8388 emitcode ("inc", "%s", rname);
8393 /* last last was not complete */
8396 /* save the byte & read byte */
8400 emitcode ("mov", "b,a");
8401 emitcode ("mov", "a,@%s", rname);
8405 emitcode ("mov", "b,a");
8406 emitcode ("movx", "a,@dptr");
8410 emitcode ("push", "b");
8411 emitcode ("push", "acc");
8412 emitcode ("lcall", "__gptrget");
8413 emitcode ("pop", "b");
8417 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8418 emitcode ("orl", "a,b");
8421 if (p_type == GPOINTER)
8422 emitcode ("pop", "b");
8428 emitcode ("mov", "@%s,a", rname);
8432 emitcode ("movx", "@dptr,a");
8436 emitcode ("lcall", "__gptrput");
8440 /*-----------------------------------------------------------------*/
8441 /* genDataPointerSet - remat pointer to data space */
8442 /*-----------------------------------------------------------------*/
8444 genDataPointerSet (operand * right,
8448 int size, offset = 0;
8449 char *l, buffer[256];
8451 aopOp (right, ic, FALSE, FALSE);
8453 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8454 size = AOP_SIZE (right);
8458 sprintf (buffer, "(%s + %d)", l + 1, offset);
8460 sprintf (buffer, "%s", l + 1);
8461 emitcode ("mov", "%s,%s", buffer,
8462 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8465 freeAsmop (right, NULL, ic, TRUE);
8466 freeAsmop (result, NULL, ic, TRUE);
8469 /*-----------------------------------------------------------------*/
8470 /* genNearPointerSet - emitcode for near pointer put */
8471 /*-----------------------------------------------------------------*/
8473 genNearPointerSet (operand * right,
8480 sym_link *retype, *letype;
8481 sym_link *ptype = operandType (result);
8483 retype = getSpec (operandType (right));
8484 letype = getSpec (ptype);
8486 aopOp (result, ic, FALSE, FALSE);
8488 /* if the result is rematerializable &
8489 in data space & not a bit variable */
8490 if (AOP_TYPE (result) == AOP_IMMD &&
8491 DCL_TYPE (ptype) == POINTER &&
8492 !IS_BITVAR (retype) &&
8493 !IS_BITVAR (letype))
8495 genDataPointerSet (right, result, ic);
8499 /* if the value is already in a pointer register
8500 then don't need anything more */
8501 if (!AOP_INPREG (AOP (result)))
8503 /* otherwise get a free pointer register */
8505 preg = getFreePtr (ic, &aop, FALSE);
8506 emitcode ("mov", "%s,%s",
8508 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8512 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8514 freeAsmop (result, NULL, ic, TRUE);
8515 aopOp (right, ic, FALSE, FALSE);
8517 /* if bitfield then unpack the bits */
8518 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8519 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8522 /* we have can just get the values */
8523 int size = AOP_SIZE (right);
8528 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8532 emitcode ("mov", "@%s,a", rname);
8535 emitcode ("mov", "@%s,%s", rname, l);
8537 emitcode ("inc", "%s", rname);
8542 /* now some housekeeping stuff */
8545 /* we had to allocate for this iCode */
8546 freeAsmop (NULL, aop, ic, TRUE);
8550 /* we did not allocate which means left
8551 already in a pointer register, then
8552 if size > 0 && this could be used again
8553 we have to point it back to where it
8555 if (AOP_SIZE (right) > 1 &&
8556 !OP_SYMBOL (result)->remat &&
8557 (OP_SYMBOL (result)->liveTo > ic->seq ||
8560 int size = AOP_SIZE (right) - 1;
8562 emitcode ("dec", "%s", rname);
8567 freeAsmop (right, NULL, ic, TRUE);
8572 /*-----------------------------------------------------------------*/
8573 /* genPagedPointerSet - emitcode for Paged pointer put */
8574 /*-----------------------------------------------------------------*/
8576 genPagedPointerSet (operand * right,
8583 sym_link *retype, *letype;
8585 retype = getSpec (operandType (right));
8586 letype = getSpec (operandType (result));
8588 aopOp (result, ic, FALSE, FALSE);
8590 /* if the value is already in a pointer register
8591 then don't need anything more */
8592 if (!AOP_INPREG (AOP (result)))
8594 /* otherwise get a free pointer register */
8596 preg = getFreePtr (ic, &aop, FALSE);
8597 emitcode ("mov", "%s,%s",
8599 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8603 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8605 freeAsmop (result, NULL, ic, TRUE);
8606 aopOp (right, ic, FALSE, FALSE);
8608 /* if bitfield then unpack the bits */
8609 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8610 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8613 /* we have can just get the values */
8614 int size = AOP_SIZE (right);
8619 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8622 emitcode ("movx", "@%s,a", rname);
8625 emitcode ("inc", "%s", rname);
8631 /* now some housekeeping stuff */
8634 /* we had to allocate for this iCode */
8635 freeAsmop (NULL, aop, ic, TRUE);
8639 /* we did not allocate which means left
8640 already in a pointer register, then
8641 if size > 0 && this could be used again
8642 we have to point it back to where it
8644 if (AOP_SIZE (right) > 1 &&
8645 !OP_SYMBOL (result)->remat &&
8646 (OP_SYMBOL (result)->liveTo > ic->seq ||
8649 int size = AOP_SIZE (right) - 1;
8651 emitcode ("dec", "%s", rname);
8656 freeAsmop (right, NULL, ic, TRUE);
8661 /*-----------------------------------------------------------------*/
8662 /* genFarPointerSet - set value from far space */
8663 /*-----------------------------------------------------------------*/
8665 genFarPointerSet (operand * right,
8666 operand * result, iCode * ic)
8669 sym_link *retype = getSpec (operandType (right));
8670 sym_link *letype = getSpec (operandType (result));
8672 aopOp (result, ic, FALSE, FALSE);
8674 /* if the operand is already in dptr
8675 then we do nothing else we move the value to dptr */
8676 if (AOP_TYPE (result) != AOP_STR)
8678 /* if this is remateriazable */
8679 if (AOP_TYPE (result) == AOP_IMMD)
8680 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8683 /* we need to get it byte by byte */
8684 _startLazyDPSEvaluation ();
8685 if (AOP_TYPE (result) != AOP_DPTR)
8687 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8688 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8689 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8693 /* We need to generate a load to DPTR indirect through DPTR. */
8694 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8696 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8697 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8698 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8699 emitcode ("pop", "dph");
8700 emitcode ("pop", "dpl");
8702 _endLazyDPSEvaluation ();
8705 /* so dptr know contains the address */
8706 freeAsmop (result, NULL, ic, TRUE);
8707 aopOp (right, ic, FALSE, TRUE);
8709 /* if bit then unpack */
8710 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8711 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8714 size = AOP_SIZE (right);
8717 _startLazyDPSEvaluation ();
8720 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8726 emitcode ("movx", "@dptr,a");
8728 emitcode ("inc", "dptr");
8730 _endLazyDPSEvaluation ();
8733 freeAsmop (right, NULL, ic, TRUE);
8736 /*-----------------------------------------------------------------*/
8737 /* genGenPointerSet - set value from generic pointer space */
8738 /*-----------------------------------------------------------------*/
8740 genGenPointerSet (operand * right,
8741 operand * result, iCode * ic)
8744 sym_link *retype = getSpec (operandType (right));
8745 sym_link *letype = getSpec (operandType (result));
8747 aopOp (result, ic, FALSE, TRUE);
8749 /* if the operand is already in dptr
8750 then we do nothing else we move the value to dptr */
8751 if (AOP_TYPE (result) != AOP_STR)
8753 _startLazyDPSEvaluation ();
8754 /* if this is remateriazable */
8755 if (AOP_TYPE (result) == AOP_IMMD)
8757 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8758 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8761 { /* we need to get it byte by byte */
8762 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8763 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8764 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8765 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8767 _endLazyDPSEvaluation ();
8769 /* so dptr know contains the address */
8770 freeAsmop (result, NULL, ic, TRUE);
8771 aopOp (right, ic, FALSE, TRUE);
8773 /* if bit then unpack */
8774 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8775 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8778 size = AOP_SIZE (right);
8781 _startLazyDPSEvaluation ();
8784 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8790 emitcode ("lcall", "__gptrput");
8792 emitcode ("inc", "dptr");
8794 _endLazyDPSEvaluation ();
8797 freeAsmop (right, NULL, ic, TRUE);
8800 /*-----------------------------------------------------------------*/
8801 /* genPointerSet - stores the value into a pointer location */
8802 /*-----------------------------------------------------------------*/
8804 genPointerSet (iCode * ic)
8806 operand *right, *result;
8807 sym_link *type, *etype;
8810 D (emitcode (";", "genPointerSet ");
8813 right = IC_RIGHT (ic);
8814 result = IC_RESULT (ic);
8816 /* depending on the type of pointer we need to
8817 move it to the correct pointer register */
8818 type = operandType (result);
8819 etype = getSpec (type);
8820 /* if left is of type of pointer then it is simple */
8821 if (IS_PTR (type) && !IS_FUNC (type->next))
8823 p_type = DCL_TYPE (type);
8827 /* we have to go by the storage class */
8828 p_type = PTR_TYPE (SPEC_OCLS (etype));
8831 /* now that we have the pointer type we assign
8832 the pointer values */
8838 genNearPointerSet (right, result, ic);
8842 genPagedPointerSet (right, result, ic);
8846 genFarPointerSet (right, result, ic);
8850 genGenPointerSet (right, result, ic);
8856 /*-----------------------------------------------------------------*/
8857 /* genIfx - generate code for Ifx statement */
8858 /*-----------------------------------------------------------------*/
8860 genIfx (iCode * ic, iCode * popIc)
8862 operand *cond = IC_COND (ic);
8865 D (emitcode (";", "genIfx "););
8867 aopOp (cond, ic, FALSE, FALSE);
8869 /* get the value into acc */
8870 if (AOP_TYPE (cond) != AOP_CRY)
8874 /* the result is now in the accumulator */
8875 freeAsmop (cond, NULL, ic, TRUE);
8877 /* if there was something to be popped then do it */
8881 /* if the condition is a bit variable */
8882 if (isbit && IS_ITEMP (cond) &&
8884 genIfxJump (ic, SPIL_LOC (cond)->rname);
8885 else if (isbit && !IS_ITEMP (cond))
8886 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8888 genIfxJump (ic, "a");
8893 /*-----------------------------------------------------------------*/
8894 /* genAddrOf - generates code for address of */
8895 /*-----------------------------------------------------------------*/
8897 genAddrOf (iCode * ic)
8899 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8902 D (emitcode (";", "genAddrOf ");
8905 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8907 /* if the operand is on the stack then we
8908 need to get the stack offset of this
8912 /* if it has an offset then we need to compute
8916 emitcode ("mov", "a,_bp");
8917 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8918 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8922 /* we can just move _bp */
8923 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8925 /* fill the result with zero */
8926 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8929 if (options.stack10bit && size < (FPTRSIZE - 1))
8932 "*** warning: pointer to stack var truncated.\n");
8939 if (options.stack10bit && offset == 2)
8941 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8945 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8952 /* object not on stack then we need the name */
8953 size = AOP_SIZE (IC_RESULT (ic));
8958 char s[SDCC_NAME_MAX];
8960 sprintf (s, "#(%s >> %d)",
8964 sprintf (s, "#%s", sym->rname);
8965 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8969 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8973 /*-----------------------------------------------------------------*/
8974 /* genFarFarAssign - assignment when both are in far space */
8975 /*-----------------------------------------------------------------*/
8977 genFarFarAssign (operand * result, operand * right, iCode * ic)
8979 int size = AOP_SIZE (right);
8981 symbol *rSym = NULL;
8985 /* quick & easy case. */
8986 D(emitcode(";","genFarFarAssign (1 byte case)"););
8987 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
8988 freeAsmop (right, NULL, ic, FALSE);
8989 /* now assign DPTR to result */
8991 aopOp(result, ic, FALSE, FALSE);
8993 aopPut(AOP(result), "a", 0);
8994 freeAsmop(result, NULL, ic, FALSE);
8998 /* See if we've got an underlying symbol to abuse. */
8999 if (IS_SYMOP(result) && OP_SYMBOL(result))
9001 if (IS_TRUE_SYMOP(result))
9003 rSym = OP_SYMBOL(result);
9005 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9007 rSym = OP_SYMBOL(result)->usl.spillLoc;
9011 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9013 /* We can use the '390 auto-toggle feature to good effect here. */
9015 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9016 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9017 emitcode ("mov", "dptr,#%s", rSym->rname);
9018 /* DP2 = result, DP1 = right, DP1 is current. */
9021 emitcode("movx", "a,@dptr");
9022 emitcode("movx", "@dptr,a");
9025 emitcode("inc", "dptr");
9026 emitcode("inc", "dptr");
9029 emitcode("mov", "dps, #0");
9030 freeAsmop (right, NULL, ic, FALSE);
9034 D (emitcode (";", "genFarFarAssign"););
9035 aopOp (result, ic, TRUE, TRUE);
9037 _startLazyDPSEvaluation ();
9041 aopPut (AOP (result),
9042 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9045 _endLazyDPSEvaluation ();
9046 freeAsmop (result, NULL, ic, FALSE);
9047 freeAsmop (right, NULL, ic, FALSE);
9051 /*-----------------------------------------------------------------*/
9052 /* genAssign - generate code for assignment */
9053 /*-----------------------------------------------------------------*/
9055 genAssign (iCode * ic)
9057 operand *result, *right;
9059 unsigned long lit = 0L;
9061 D (emitcode (";", "genAssign ");
9064 result = IC_RESULT (ic);
9065 right = IC_RIGHT (ic);
9067 /* if they are the same */
9068 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9071 aopOp (right, ic, FALSE, FALSE);
9073 emitcode (";", "genAssign: resultIsFar = %s",
9074 isOperandInFarSpace (result) ?
9077 /* special case both in far space */
9078 if ((AOP_TYPE (right) == AOP_DPTR ||
9079 AOP_TYPE (right) == AOP_DPTR2) &&
9080 /* IS_TRUE_SYMOP(result) && */
9081 isOperandInFarSpace (result))
9083 genFarFarAssign (result, right, ic);
9087 aopOp (result, ic, TRUE, FALSE);
9089 /* if they are the same registers */
9090 if (sameRegs (AOP (right), AOP (result)))
9093 /* if the result is a bit */
9094 if (AOP_TYPE (result) == AOP_CRY)
9097 /* if the right size is a literal then
9098 we know what the value is */
9099 if (AOP_TYPE (right) == AOP_LIT)
9101 if (((int) operandLitValue (right)))
9102 aopPut (AOP (result), one, 0);
9104 aopPut (AOP (result), zero, 0);
9108 /* the right is also a bit variable */
9109 if (AOP_TYPE (right) == AOP_CRY)
9111 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9112 aopPut (AOP (result), "c", 0);
9118 aopPut (AOP (result), "a", 0);
9122 /* bit variables done */
9124 size = AOP_SIZE (result);
9126 if (AOP_TYPE (right) == AOP_LIT)
9127 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9130 (AOP_TYPE (result) != AOP_REG) &&
9131 (AOP_TYPE (right) == AOP_LIT) &&
9132 !IS_FLOAT (operandType (right)))
9134 _startLazyDPSEvaluation ();
9135 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9137 aopPut (AOP (result),
9138 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9143 /* And now fill the rest with zeros. */
9146 emitcode ("clr", "a");
9150 aopPut (AOP (result), "a", offset++);
9152 _endLazyDPSEvaluation ();
9156 _startLazyDPSEvaluation ();
9159 aopPut (AOP (result),
9160 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9164 _endLazyDPSEvaluation ();
9168 freeAsmop (right, NULL, ic, FALSE);
9169 freeAsmop (result, NULL, ic, TRUE);
9172 /*-----------------------------------------------------------------*/
9173 /* genJumpTab - generates code for jump table */
9174 /*-----------------------------------------------------------------*/
9176 genJumpTab (iCode * ic)
9181 D (emitcode (";", "genJumpTab ");
9184 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9185 /* get the condition into accumulator */
9186 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9188 /* multiply by four! */
9189 emitcode ("add", "a,acc");
9190 emitcode ("add", "a,acc");
9191 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9193 jtab = newiTempLabel (NULL);
9194 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9195 emitcode ("jmp", "@a+dptr");
9196 emitcode ("", "%05d$:", jtab->key + 100);
9197 /* now generate the jump labels */
9198 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9199 jtab = setNextItem (IC_JTLABELS (ic)))
9200 emitcode ("ljmp", "%05d$", jtab->key + 100);
9204 /*-----------------------------------------------------------------*/
9205 /* genCast - gen code for casting */
9206 /*-----------------------------------------------------------------*/
9208 genCast (iCode * ic)
9210 operand *result = IC_RESULT (ic);
9211 sym_link *ctype = operandType (IC_LEFT (ic));
9212 sym_link *rtype = operandType (IC_RIGHT (ic));
9213 operand *right = IC_RIGHT (ic);
9216 D (emitcode (";", "genCast ");
9219 /* if they are equivalent then do nothing */
9220 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9223 aopOp (right, ic, FALSE, FALSE);
9224 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9226 /* if the result is a bit */
9227 if (AOP_TYPE (result) == AOP_CRY)
9229 /* if the right size is a literal then
9230 we know what the value is */
9231 if (AOP_TYPE (right) == AOP_LIT)
9233 if (((int) operandLitValue (right)))
9234 aopPut (AOP (result), one, 0);
9236 aopPut (AOP (result), zero, 0);
9241 /* the right is also a bit variable */
9242 if (AOP_TYPE (right) == AOP_CRY)
9244 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9245 aopPut (AOP (result), "c", 0);
9251 aopPut (AOP (result), "a", 0);
9255 /* if they are the same size : or less */
9256 if (AOP_SIZE (result) <= AOP_SIZE (right))
9259 /* if they are in the same place */
9260 if (sameRegs (AOP (right), AOP (result)))
9263 /* if they in different places then copy */
9264 size = AOP_SIZE (result);
9266 _startLazyDPSEvaluation ();
9269 aopPut (AOP (result),
9270 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9274 _endLazyDPSEvaluation ();
9279 /* if the result is of type pointer */
9284 sym_link *type = operandType (right);
9286 /* pointer to generic pointer */
9287 if (IS_GENPTR (ctype))
9293 p_type = DCL_TYPE (type);
9297 #if OLD_CAST_BEHAVIOR
9298 /* KV: we are converting a non-pointer type to
9299 * a generic pointer. This (ifdef'd out) code
9300 * says that the resulting generic pointer
9301 * should have the same class as the storage
9302 * location of the non-pointer variable.
9304 * For example, converting an int (which happens
9305 * to be stored in DATA space) to a pointer results
9306 * in a DATA generic pointer; if the original int
9307 * in XDATA space, so will be the resulting pointer.
9309 * I don't like that behavior, and thus this change:
9310 * all such conversions will be forced to XDATA and
9311 * throw a warning. If you want some non-XDATA
9312 * type, or you want to suppress the warning, you
9313 * must go through an intermediate cast, like so:
9315 * char _generic *gp = (char _xdata *)(intVar);
9317 sym_link *etype = getSpec (type);
9319 /* we have to go by the storage class */
9320 if (SPEC_OCLS (etype) != generic)
9322 p_type = PTR_TYPE (SPEC_OCLS (etype));
9327 /* Converting unknown class (i.e. register variable)
9328 * to generic pointer. This is not good, but
9329 * we'll make a guess (and throw a warning).
9332 werror (W_INT_TO_GEN_PTR_CAST);
9336 /* the first two bytes are known */
9337 size = GPTRSIZE - 1;
9339 _startLazyDPSEvaluation ();
9342 aopPut (AOP (result),
9343 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9347 _endLazyDPSEvaluation ();
9349 /* the last byte depending on type */
9367 /* this should never happen */
9368 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9369 "got unknown pointer type");
9372 aopPut (AOP (result), l, GPTRSIZE - 1);
9376 /* just copy the pointers */
9377 size = AOP_SIZE (result);
9379 _startLazyDPSEvaluation ();
9382 aopPut (AOP (result),
9383 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9387 _endLazyDPSEvaluation ();
9391 /* so we now know that the size of destination is greater
9392 than the size of the source */
9393 /* we move to result for the size of source */
9394 size = AOP_SIZE (right);
9396 _startLazyDPSEvaluation ();
9399 aopPut (AOP (result),
9400 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9404 _endLazyDPSEvaluation ();
9406 /* now depending on the sign of the source && destination */
9407 size = AOP_SIZE (result) - AOP_SIZE (right);
9408 /* if unsigned or not an integral type */
9409 /* also, if the source is a bit, we don't need to sign extend, because
9410 * it can't possibly have set the sign bit.
9412 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9416 aopPut (AOP (result), zero, offset++);
9421 /* we need to extend the sign :{ */
9422 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9423 FALSE, FALSE, TRUE);
9425 emitcode ("rlc", "a");
9426 emitcode ("subb", "a,acc");
9428 aopPut (AOP (result), "a", offset++);
9431 /* we are done hurray !!!! */
9434 freeAsmop (right, NULL, ic, TRUE);
9435 freeAsmop (result, NULL, ic, TRUE);
9439 /*-----------------------------------------------------------------*/
9440 /* genDjnz - generate decrement & jump if not zero instrucion */
9441 /*-----------------------------------------------------------------*/
9443 genDjnz (iCode * ic, iCode * ifx)
9449 /* if the if condition has a false label
9450 then we cannot save */
9454 /* if the minus is not of the form
9456 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9457 !IS_OP_LITERAL (IC_RIGHT (ic)))
9460 if (operandLitValue (IC_RIGHT (ic)) != 1)
9463 /* if the size of this greater than one then no
9465 if (getSize (operandType (IC_RESULT (ic))) > 1)
9468 /* otherwise we can save BIG */
9469 D(emitcode(";", "genDjnz"););
9471 lbl = newiTempLabel (NULL);
9472 lbl1 = newiTempLabel (NULL);
9474 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9476 if (AOP_NEEDSACC(IC_RESULT(ic)))
9478 /* If the result is accessed indirectly via
9479 * the accumulator, we must explicitly write
9480 * it back after the decrement.
9482 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9484 if (strcmp(rByte, "a"))
9486 /* Something is hopelessly wrong */
9487 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9488 __FILE__, __LINE__);
9489 /* We can just give up; the generated code will be inefficient,
9492 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9495 emitcode ("dec", "%s", rByte);
9496 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9497 emitcode ("jnz", "%05d$", lbl->key + 100);
9499 else if (IS_AOP_PREG (IC_RESULT (ic)))
9501 emitcode ("dec", "%s",
9502 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9503 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9504 emitcode ("jnz", "%05d$", lbl->key + 100);
9508 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9511 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9512 emitcode ("", "%05d$:", lbl->key + 100);
9513 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9514 emitcode ("", "%05d$:", lbl1->key + 100);
9516 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9521 /*-----------------------------------------------------------------*/
9522 /* genReceive - generate code for a receive iCode */
9523 /*-----------------------------------------------------------------*/
9525 genReceive (iCode * ic)
9528 D (emitcode (";", "genReceive ");
9531 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9532 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9533 IS_TRUE_SYMOP (IC_RESULT (ic))))
9535 int size = getSize (operandType (IC_RESULT (ic)));
9536 int offset = fReturnSizeDS390 - size;
9539 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9540 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9543 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9544 size = AOP_SIZE (IC_RESULT (ic));
9548 emitcode ("pop", "acc");
9549 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9556 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9558 assignResultValue (IC_RESULT (ic));
9561 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9564 /*-----------------------------------------------------------------*/
9565 /* gen390Code - generate code for Dallas 390 based controllers */
9566 /*-----------------------------------------------------------------*/
9568 gen390Code (iCode * lic)
9573 lineHead = lineCurr = NULL;
9577 /* print the allocation information */
9579 printAllocInfo (currFunc, codeOutFile);
9581 /* if debug information required */
9582 if (options.debug && currFunc)
9584 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9586 if (IS_STATIC (currFunc->etype))
9587 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9589 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9592 /* stack pointer name */
9593 if (options.useXstack)
9599 for (ic = lic; ic; ic = ic->next)
9602 if (cln != ic->lineno)
9607 emitcode ("", "C$%s$%d$%d$%d ==.",
9608 FileBaseName (ic->filename), ic->lineno,
9609 ic->level, ic->block);
9612 emitcode (";", "%s %d", ic->filename, ic->lineno);
9615 /* if the result is marked as
9616 spilt and rematerializable or code for
9617 this has already been generated then
9619 if (resultRemat (ic) || ic->generated)
9622 /* depending on the operation */
9642 /* IPOP happens only when trying to restore a
9643 spilt live range, if there is an ifx statement
9644 following this pop then the if statement might
9645 be using some of the registers being popped which
9646 would destory the contents of the register so
9647 we need to check for this condition and handle it */
9649 ic->next->op == IFX &&
9650 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9651 genIfx (ic->next, ic);
9669 genEndFunction (ic);
9689 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9706 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9710 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9717 /* note these two are xlated by algebraic equivalence
9718 during parsing SDCC.y */
9719 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9720 "got '>=' or '<=' shouldn't have come here");
9724 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9736 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9740 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9744 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9771 case GET_VALUE_AT_ADDRESS:
9776 if (POINTER_SET (ic))
9803 addSet (&_G.sendSet, ic);
9812 /* now we are ready to call the
9813 peep hole optimizer */
9814 if (!options.nopeep)
9815 peepHole (&lineHead);
9817 /* now do the actual printing */
9818 printLine (lineHead, codeOutFile);