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 ");
2158 /* if send set is not empty the assign */
2163 for (sic = setFirstItem (_G.sendSet); sic;
2164 sic = setNextItem (_G.sendSet))
2166 int size, offset = 0;
2168 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2169 size = AOP_SIZE (IC_LEFT (sic));
2171 _startLazyDPSEvaluation ();
2174 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2175 FALSE, FALSE, TRUE);
2176 if (strcmp (l, fReturn[offset])) {
2179 emitcode ("mov", "%s,%s",
2185 _endLazyDPSEvaluation ();
2186 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2191 /* if we are calling a function that is not using
2192 the same register bank then we need to save the
2193 destination registers on the stack */
2194 detype = getSpec (operandType (IC_LEFT (ic)));
2196 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2197 IS_ISR (currFunc->etype) &&
2199 saveRBank (SPEC_BANK (detype), ic, TRUE);
2200 } else /* no need to save if we just saved the whole bank */ {
2201 /* if caller saves & we have not saved then */
2207 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2208 OP_SYMBOL (IC_LEFT (ic))->rname :
2209 OP_SYMBOL (IC_LEFT (ic))->name));
2211 /* if we need assign a result value */
2212 if ((IS_ITEMP (IC_RESULT (ic)) &&
2213 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2214 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2215 IS_TRUE_SYMOP (IC_RESULT (ic)))
2217 if (isOperandInFarSpace (IC_RESULT (ic))
2218 && getSize (operandType (IC_RESULT (ic))) <= 2)
2220 int size = getSize (operandType (IC_RESULT (ic)));
2222 /* Special case for 1 or 2 byte return in far space. */
2226 emitcode ("mov", "b,%s", fReturn[1]);
2229 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2230 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2234 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2236 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2241 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2244 assignResultValue (IC_RESULT (ic));
2246 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2250 /* adjust the stack for parameters if
2255 if (ic->parmBytes > 3)
2257 emitcode ("mov", "a,%s", spname);
2258 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2259 emitcode ("mov", "%s,a", spname);
2262 for (i = 0; i < ic->parmBytes; i++)
2263 emitcode ("dec", "%s", spname);
2267 /* if register bank was saved then pop them */
2269 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2271 /* if we hade saved some registers then unsave them */
2272 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2273 unsaveRegisters (ic);
2278 /*-----------------------------------------------------------------*/
2279 /* genPcall - generates a call by pointer statement */
2280 /*-----------------------------------------------------------------*/
2282 genPcall (iCode * ic)
2285 symbol *rlbl = newiTempLabel (NULL);
2287 D (emitcode (";", "genPcall ");
2291 /* if caller saves & we have not saved then */
2295 /* if we are calling a function that is not using
2296 the same register bank then we need to save the
2297 destination registers on the stack */
2298 detype = getSpec (operandType (IC_LEFT (ic)));
2300 IS_ISR (currFunc->etype) &&
2301 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2302 saveRBank (SPEC_BANK (detype), ic, TRUE);
2305 /* push the return address on to the stack */
2306 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2307 emitcode ("push", "acc");
2308 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2309 emitcode ("push", "acc");
2311 if (options.model == MODEL_FLAT24)
2313 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2314 emitcode ("push", "acc");
2317 /* now push the calling address */
2318 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2320 pushSide (IC_LEFT (ic), FPTRSIZE);
2322 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2324 /* if send set is not empty the assign */
2329 for (sic = setFirstItem (_G.sendSet); sic;
2330 sic = setNextItem (_G.sendSet))
2332 int size, offset = 0;
2334 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2335 size = AOP_SIZE (IC_LEFT (sic));
2336 _startLazyDPSEvaluation ();
2339 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2340 FALSE, FALSE, TRUE);
2341 if (strcmp (l, fReturn[offset]))
2343 emitcode ("mov", "%s,%s",
2349 _endLazyDPSEvaluation ();
2350 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2355 emitcode ("ret", "");
2356 emitcode ("", "%05d$:", (rlbl->key + 100));
2359 /* if we need assign a result value */
2360 if ((IS_ITEMP (IC_RESULT (ic)) &&
2361 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2362 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2363 IS_TRUE_SYMOP (IC_RESULT (ic)))
2367 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2370 assignResultValue (IC_RESULT (ic));
2372 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2375 /* adjust the stack for parameters if
2380 if (ic->parmBytes > 3)
2382 emitcode ("mov", "a,%s", spname);
2383 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2384 emitcode ("mov", "%s,a", spname);
2387 for (i = 0; i < ic->parmBytes; i++)
2388 emitcode ("dec", "%s", spname);
2392 /* if register bank was saved then unsave them */
2394 (SPEC_BANK (currFunc->etype) !=
2395 SPEC_BANK (detype)))
2396 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2398 /* if we hade saved some registers then
2401 unsaveRegisters (ic);
2405 /*-----------------------------------------------------------------*/
2406 /* resultRemat - result is rematerializable */
2407 /*-----------------------------------------------------------------*/
2409 resultRemat (iCode * ic)
2411 if (SKIP_IC (ic) || ic->op == IFX)
2414 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2416 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2417 if (sym->remat && !POINTER_SET (ic))
2424 #if defined(__BORLANDC__) || defined(_MSC_VER)
2425 #define STRCASECMP stricmp
2427 #define STRCASECMP strcasecmp
2430 /*-----------------------------------------------------------------*/
2431 /* inExcludeList - return 1 if the string is in exclude Reg list */
2432 /*-----------------------------------------------------------------*/
2434 inExcludeList (char *s)
2438 if (options.excludeRegs[i] &&
2439 STRCASECMP (options.excludeRegs[i], "none") == 0)
2442 for (i = 0; options.excludeRegs[i]; i++)
2444 if (options.excludeRegs[i] &&
2445 STRCASECMP (s, options.excludeRegs[i]) == 0)
2451 /*-----------------------------------------------------------------*/
2452 /* genFunction - generated code for function entry */
2453 /*-----------------------------------------------------------------*/
2455 genFunction (iCode * ic)
2460 D (emitcode (";", "genFunction ");
2464 /* create the function header */
2465 emitcode (";", "-----------------------------------------");
2466 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2467 emitcode (";", "-----------------------------------------");
2469 emitcode ("", "%s:", sym->rname);
2470 fetype = getSpec (operandType (IC_LEFT (ic)));
2472 /* if critical function then turn interrupts off */
2473 if (SPEC_CRTCL (fetype))
2474 emitcode ("clr", "ea");
2476 /* here we need to generate the equates for the
2477 register bank if required */
2478 if (SPEC_BANK (fetype) != rbank)
2482 rbank = SPEC_BANK (fetype);
2483 for (i = 0; i < ds390_nRegs; i++)
2485 if (strcmp (regs390[i].base, "0") == 0)
2486 emitcode ("", "%s = 0x%02x",
2488 8 * rbank + regs390[i].offset);
2490 emitcode ("", "%s = %s + 0x%02x",
2493 8 * rbank + regs390[i].offset);
2497 /* if this is an interrupt service routine then
2498 save acc, b, dpl, dph */
2499 if (IS_ISR (sym->etype))
2502 if (!inExcludeList ("acc"))
2503 emitcode ("push", "acc");
2504 if (!inExcludeList ("b"))
2505 emitcode ("push", "b");
2506 if (!inExcludeList ("dpl"))
2507 emitcode ("push", "dpl");
2508 if (!inExcludeList ("dph"))
2509 emitcode ("push", "dph");
2510 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2512 emitcode ("push", "dpx");
2513 /* Make sure we're using standard DPTR */
2514 emitcode ("push", "dps");
2515 emitcode ("mov", "dps, #0x00");
2516 if (options.stack10bit)
2518 /* This ISR could conceivably use DPTR2. Better save it. */
2519 emitcode ("push", "dpl1");
2520 emitcode ("push", "dph1");
2521 emitcode ("push", "dpx1");
2522 emitcode ("push", DP2_RESULT_REG);
2525 /* if this isr has no bank i.e. is going to
2526 run with bank 0 , then we need to save more
2528 if (!SPEC_BANK (sym->etype))
2531 /* if this function does not call any other
2532 function then we can be economical and
2533 save only those registers that are used */
2538 /* if any registers used */
2541 /* save the registers used */
2542 for (i = 0; i < sym->regsUsed->size; i++)
2544 if (bitVectBitValue (sym->regsUsed, i) ||
2545 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2546 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2553 /* this function has a function call cannot
2554 determines register usage so we will have to push the
2556 saveRBank (0, ic, FALSE);
2562 /* if callee-save to be used for this function
2563 then save the registers being used in this function */
2564 if (sym->calleeSave)
2568 /* if any registers used */
2571 /* save the registers used */
2572 for (i = 0; i < sym->regsUsed->size; i++)
2574 if (bitVectBitValue (sym->regsUsed, i) ||
2575 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2577 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2585 /* set the register bank to the desired value */
2586 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2588 emitcode ("push", "psw");
2589 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2592 if (IS_RENT (sym->etype) || options.stackAuto)
2595 if (options.useXstack)
2597 emitcode ("mov", "r0,%s", spname);
2598 emitcode ("mov", "a,_bp");
2599 emitcode ("movx", "@r0,a");
2600 emitcode ("inc", "%s", spname);
2604 /* set up the stack */
2605 emitcode ("push", "_bp"); /* save the callers stack */
2607 emitcode ("mov", "_bp,%s", spname);
2610 /* adjust the stack for the function */
2616 werror (W_STACK_OVERFLOW, sym->name);
2618 if (i > 3 && sym->recvSize < 4)
2621 emitcode ("mov", "a,sp");
2622 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2623 emitcode ("mov", "sp,a");
2628 emitcode ("inc", "sp");
2634 emitcode ("mov", "a,_spx");
2635 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2636 emitcode ("mov", "_spx,a");
2641 /*-----------------------------------------------------------------*/
2642 /* genEndFunction - generates epilogue for functions */
2643 /*-----------------------------------------------------------------*/
2645 genEndFunction (iCode * ic)
2647 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2649 D (emitcode (";", "genEndFunction ");
2652 if (IS_RENT (sym->etype) || options.stackAuto)
2654 emitcode ("mov", "%s,_bp", spname);
2657 /* if use external stack but some variables were
2658 added to the local stack then decrement the
2660 if (options.useXstack && sym->stack)
2662 emitcode ("mov", "a,sp");
2663 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2664 emitcode ("mov", "sp,a");
2668 if ((IS_RENT (sym->etype) || options.stackAuto))
2670 if (options.useXstack)
2672 emitcode ("mov", "r0,%s", spname);
2673 emitcode ("movx", "a,@r0");
2674 emitcode ("mov", "_bp,a");
2675 emitcode ("dec", "%s", spname);
2679 emitcode ("pop", "_bp");
2683 /* restore the register bank */
2684 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2685 emitcode ("pop", "psw");
2687 if (IS_ISR (sym->etype))
2690 /* now we need to restore the registers */
2691 /* if this isr has no bank i.e. is going to
2692 run with bank 0 , then we need to save more
2694 if (!SPEC_BANK (sym->etype))
2697 /* if this function does not call any other
2698 function then we can be economical and
2699 save only those registers that are used */
2704 /* if any registers used */
2707 /* save the registers used */
2708 for (i = sym->regsUsed->size; i >= 0; i--)
2710 if (bitVectBitValue (sym->regsUsed, i) ||
2711 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2712 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2719 /* this function has a function call cannot
2720 determines register usage so we will have to pop the
2722 unsaveRBank (0, ic, FALSE);
2726 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2728 if (options.stack10bit)
2730 emitcode ("pop", DP2_RESULT_REG);
2731 emitcode ("pop", "dpx1");
2732 emitcode ("pop", "dph1");
2733 emitcode ("pop", "dpl1");
2735 emitcode ("pop", "dps");
2736 emitcode ("pop", "dpx");
2738 if (!inExcludeList ("dph"))
2739 emitcode ("pop", "dph");
2740 if (!inExcludeList ("dpl"))
2741 emitcode ("pop", "dpl");
2742 if (!inExcludeList ("b"))
2743 emitcode ("pop", "b");
2744 if (!inExcludeList ("acc"))
2745 emitcode ("pop", "acc");
2747 if (SPEC_CRTCL (sym->etype))
2748 emitcode ("setb", "ea");
2750 /* if debug then send end of function */
2751 /* if (options.debug && currFunc) { */
2755 emitcode ("", "C$%s$%d$%d$%d ==.",
2756 FileBaseName (ic->filename), currFunc->lastLine,
2757 ic->level, ic->block);
2758 if (IS_STATIC (currFunc->etype))
2759 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2761 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2765 emitcode ("reti", "");
2769 if (SPEC_CRTCL (sym->etype))
2770 emitcode ("setb", "ea");
2772 if (sym->calleeSave)
2776 /* if any registers used */
2779 /* save the registers used */
2780 for (i = sym->regsUsed->size; i >= 0; i--)
2782 if (bitVectBitValue (sym->regsUsed, i) ||
2783 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2784 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2790 /* if debug then send end of function */
2794 emitcode ("", "C$%s$%d$%d$%d ==.",
2795 FileBaseName (ic->filename), currFunc->lastLine,
2796 ic->level, ic->block);
2797 if (IS_STATIC (currFunc->etype))
2798 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2800 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2804 emitcode ("ret", "");
2809 /*-----------------------------------------------------------------*/
2810 /* genRet - generate code for return statement */
2811 /*-----------------------------------------------------------------*/
2815 int size, offset = 0, pushed = 0;
2817 D (emitcode (";", "genRet ");
2820 /* if we have no return value then
2821 just generate the "ret" */
2825 /* we have something to return then
2826 move the return value into place */
2827 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2828 size = AOP_SIZE (IC_LEFT (ic));
2830 _startLazyDPSEvaluation ();
2834 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2836 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2837 FALSE, TRUE, FALSE);
2838 emitcode ("push", "%s", l);
2843 /* Since A is the last element of fReturn,
2844 * is is OK to clobber it in the aopGet.
2846 l = aopGet (AOP (IC_LEFT (ic)), offset,
2847 FALSE, FALSE, TRUE);
2848 if (strcmp (fReturn[offset], l))
2849 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2852 _endLazyDPSEvaluation ();
2859 if (strcmp (fReturn[pushed], "a"))
2860 emitcode ("pop", fReturn[pushed]);
2862 emitcode ("pop", "acc");
2865 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2868 /* generate a jump to the return label
2869 if the next is not the return statement */
2870 if (!(ic->next && ic->next->op == LABEL &&
2871 IC_LABEL (ic->next) == returnLabel))
2873 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2877 /*-----------------------------------------------------------------*/
2878 /* genLabel - generates a label */
2879 /*-----------------------------------------------------------------*/
2881 genLabel (iCode * ic)
2883 /* special case never generate */
2884 if (IC_LABEL (ic) == entryLabel)
2887 D (emitcode (";", "genLabel ");
2890 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2893 /*-----------------------------------------------------------------*/
2894 /* genGoto - generates a ljmp */
2895 /*-----------------------------------------------------------------*/
2897 genGoto (iCode * ic)
2899 D (emitcode (";", "genGoto ");
2901 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2904 /*-----------------------------------------------------------------*/
2905 /* findLabelBackwards: walks back through the iCode chain looking */
2906 /* for the given label. Returns number of iCode instructions */
2907 /* between that label and given ic. */
2908 /* Returns zero if label not found. */
2909 /*-----------------------------------------------------------------*/
2911 findLabelBackwards (iCode * ic, int key)
2920 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2922 /* printf("findLabelBackwards = %d\n", count); */
2930 /*-----------------------------------------------------------------*/
2931 /* genPlusIncr :- does addition with increment if possible */
2932 /*-----------------------------------------------------------------*/
2934 genPlusIncr (iCode * ic)
2936 unsigned int icount;
2937 unsigned int size = getDataSize (IC_RESULT (ic));
2939 /* will try to generate an increment */
2940 /* if the right side is not a literal
2942 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2945 /* if the literal value of the right hand side
2946 is greater than 4 then it is not worth it */
2947 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2950 /* if increment 16 bits in register */
2952 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2953 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2954 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2962 /* If the next instruction is a goto and the goto target
2963 * is <= 5 instructions previous to this, we can generate
2964 * jumps straight to that target.
2966 if (ic->next && ic->next->op == GOTO
2967 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2970 emitcode (";", "tail increment optimized (range %d)", labelRange);
2971 tlbl = IC_LABEL (ic->next);
2976 tlbl = newiTempLabel (NULL);
2979 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2980 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2981 IS_AOP_PREG (IC_RESULT (ic)))
2982 emitcode ("cjne", "%s,#0x00,%05d$"
2983 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2987 emitcode ("clr", "a");
2988 emitcode ("cjne", "a,%s,%05d$"
2989 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2993 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2996 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2997 IS_AOP_PREG (IC_RESULT (ic)))
2998 emitcode ("cjne", "%s,#0x00,%05d$"
2999 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3002 emitcode ("cjne", "a,%s,%05d$"
3003 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3006 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3010 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3011 IS_AOP_PREG (IC_RESULT (ic)))
3012 emitcode ("cjne", "%s,#0x00,%05d$"
3013 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3017 emitcode ("cjne", "a,%s,%05d$"
3018 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3021 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3026 emitcode ("", "%05d$:", tlbl->key + 100);
3031 /* if the sizes are greater than 1 then we cannot */
3032 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3033 AOP_SIZE (IC_LEFT (ic)) > 1)
3036 /* we can if the aops of the left & result match or
3037 if they are in registers and the registers are the
3040 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3041 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3042 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3047 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3048 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3049 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3054 _startLazyDPSEvaluation ();
3057 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3059 _endLazyDPSEvaluation ();
3068 /*-----------------------------------------------------------------*/
3069 /* outBitAcc - output a bit in acc */
3070 /*-----------------------------------------------------------------*/
3072 outBitAcc (operand * result)
3074 symbol *tlbl = newiTempLabel (NULL);
3075 /* if the result is a bit */
3076 if (AOP_TYPE (result) == AOP_CRY)
3078 aopPut (AOP (result), "a", 0);
3082 emitcode ("jz", "%05d$", tlbl->key + 100);
3083 emitcode ("mov", "a,%s", one);
3084 emitcode ("", "%05d$:", tlbl->key + 100);
3089 /*-----------------------------------------------------------------*/
3090 /* genPlusBits - generates code for addition of two bits */
3091 /*-----------------------------------------------------------------*/
3093 genPlusBits (iCode * ic)
3095 D (emitcode (";", "genPlusBits ");
3097 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3099 symbol *lbl = newiTempLabel (NULL);
3100 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3101 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3102 emitcode ("cpl", "c");
3103 emitcode ("", "%05d$:", (lbl->key + 100));
3104 outBitC (IC_RESULT (ic));
3108 emitcode ("clr", "a");
3109 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3110 emitcode ("rlc", "a");
3111 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3112 emitcode ("addc", "a,#0x00");
3113 outAcc (IC_RESULT (ic));
3118 adjustArithmeticResult (iCode * ic)
3120 if (opIsGptr (IC_RESULT (ic)) &&
3121 opIsGptr (IC_LEFT (ic)) &&
3122 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3124 aopPut (AOP (IC_RESULT (ic)),
3125 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3129 if (opIsGptr (IC_RESULT (ic)) &&
3130 opIsGptr (IC_RIGHT (ic)) &&
3131 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3133 aopPut (AOP (IC_RESULT (ic)),
3134 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3138 if (opIsGptr (IC_RESULT (ic)) &&
3139 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3140 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3141 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3142 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3145 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3146 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3150 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3151 // (because all three operands are in far space).
3152 #define AOP_OP_3(ic) \
3153 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3154 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3155 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3156 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3157 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3158 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3160 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3162 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3165 // Macro to aopOp all three operands of an ic. If this cannot be done,
3166 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3167 // will be set TRUE. The caller must then handle the case specially, noting
3168 // that the IC_RESULT operand is not aopOp'd.
3169 #define AOP_OP_3_NOFATAL(ic, rc) \
3170 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3171 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3172 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3173 isOperandInFarSpace(IC_RESULT(ic))) \
3175 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3180 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3181 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3183 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3184 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3186 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3188 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3192 // aopOp the left & right operands of an ic.
3193 #define AOP_OP_2(ic) \
3194 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3195 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3197 // convienience macro.
3198 #define AOP_SET_LOCALS(ic) \
3199 left = IC_LEFT(ic); \
3200 right = IC_RIGHT(ic); \
3201 result = IC_RESULT(ic);
3204 // Given an integer value of pushedSize bytes on the stack,
3205 // adjust it to be resultSize bytes, either by discarding
3206 // the most significant bytes or by zero-padding.
3208 // On exit from this macro, pushedSize will have been adjusted to
3209 // equal resultSize, and ACC may be trashed.
3210 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3211 /* If the pushed data is bigger than the result, \
3212 * simply discard unused bytes. Icky, but works. \
3214 while (pushedSize > resultSize) \
3216 D (emitcode (";", "discarding unused result byte."););\
3217 emitcode ("pop", "acc"); \
3220 if (pushedSize < resultSize) \
3222 emitcode ("clr", "a"); \
3223 /* Conversly, we haven't pushed enough here. \
3224 * just zero-pad, and all is well. \
3226 while (pushedSize < resultSize) \
3228 emitcode("push", "acc"); \
3232 assert(pushedSize == resultSize);
3234 /*-----------------------------------------------------------------*/
3235 /* genPlus - generates code for addition */
3236 /*-----------------------------------------------------------------*/
3238 genPlus (iCode * ic)
3240 int size, offset = 0;
3241 bool pushResult = FALSE;
3244 D (emitcode (";", "genPlus "););
3246 /* special cases :- */
3248 AOP_OP_3_NOFATAL (ic, pushResult);
3251 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3256 /* if literal, literal on the right or
3257 if left requires ACC or right is already
3259 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3260 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3261 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3263 operand *t = IC_RIGHT (ic);
3264 IC_RIGHT (ic) = IC_LEFT (ic);
3266 emitcode (";", "Swapped plus args.");
3269 /* if both left & right are in bit
3271 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3272 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3278 /* if left in bit space & right literal */
3279 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3280 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3282 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3283 /* if result in bit space */
3284 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3286 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3287 emitcode ("cpl", "c");
3288 outBitC (IC_RESULT (ic));
3292 size = getDataSize (IC_RESULT (ic));
3293 _startLazyDPSEvaluation ();
3296 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3297 emitcode ("addc", "a,#00");
3298 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3300 _endLazyDPSEvaluation ();
3305 /* if I can do an increment instead
3306 of add then GOOD for ME */
3307 if (genPlusIncr (ic) == TRUE)
3309 emitcode (";", "did genPlusIncr");
3314 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3316 _startLazyDPSEvaluation ();
3319 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3321 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3323 emitcode ("add", "a,%s",
3324 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3326 emitcode ("addc", "a,%s",
3327 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3331 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3333 emitcode ("add", "a,%s",
3334 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3336 emitcode ("addc", "a,%s",
3337 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3341 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3345 emitcode ("push", "acc");
3349 _endLazyDPSEvaluation ();
3353 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3355 size = getDataSize (IC_LEFT (ic));
3356 rSize = getDataSize (IC_RESULT (ic));
3358 ADJUST_PUSHED_RESULT(size, rSize);
3360 _startLazyDPSEvaluation ();
3363 emitcode ("pop", "acc");
3364 aopPut (AOP (IC_RESULT (ic)), "a", size);
3366 _endLazyDPSEvaluation ();
3369 adjustArithmeticResult (ic);
3372 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3373 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3374 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3377 /*-----------------------------------------------------------------*/
3378 /* genMinusDec :- does subtraction with deccrement if possible */
3379 /*-----------------------------------------------------------------*/
3381 genMinusDec (iCode * ic)
3383 unsigned int icount;
3384 unsigned int size = getDataSize (IC_RESULT (ic));
3386 /* will try to generate an increment */
3387 /* if the right side is not a literal
3389 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3392 /* if the literal value of the right hand side
3393 is greater than 4 then it is not worth it */
3394 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3397 /* if decrement 16 bits in register */
3398 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3399 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3400 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3408 /* If the next instruction is a goto and the goto target
3409 * is <= 5 instructions previous to this, we can generate
3410 * jumps straight to that target.
3412 if (ic->next && ic->next->op == GOTO
3413 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3416 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3417 tlbl = IC_LABEL (ic->next);
3422 tlbl = newiTempLabel (NULL);
3426 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3427 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3428 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3429 IS_AOP_PREG (IC_RESULT (ic)))
3430 emitcode ("cjne", "%s,#0xff,%05d$"
3431 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3435 emitcode ("mov", "a,#0xff");
3436 emitcode ("cjne", "a,%s,%05d$"
3437 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3440 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3443 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3444 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3445 IS_AOP_PREG (IC_RESULT (ic)))
3446 emitcode ("cjne", "%s,#0xff,%05d$"
3447 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3451 emitcode ("cjne", "a,%s,%05d$"
3452 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3455 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3459 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3460 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3461 IS_AOP_PREG (IC_RESULT (ic)))
3462 emitcode ("cjne", "%s,#0xff,%05d$"
3463 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3467 emitcode ("cjne", "a,%s,%05d$"
3468 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3471 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3475 emitcode ("", "%05d$:", tlbl->key + 100);
3480 /* if the sizes are greater than 1 then we cannot */
3481 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3482 AOP_SIZE (IC_LEFT (ic)) > 1)
3485 /* we can if the aops of the left & result match or
3486 if they are in registers and the registers are the
3489 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3490 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3491 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3494 _startLazyDPSEvaluation ();
3497 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3499 _endLazyDPSEvaluation ();
3507 /*-----------------------------------------------------------------*/
3508 /* addSign - complete with sign */
3509 /*-----------------------------------------------------------------*/
3511 addSign (operand * result, int offset, int sign)
3513 int size = (getDataSize (result) - offset);
3516 _startLazyDPSEvaluation();
3519 emitcode ("rlc", "a");
3520 emitcode ("subb", "a,acc");
3523 aopPut (AOP (result), "a", offset++);
3530 aopPut (AOP (result), zero, offset++);
3533 _endLazyDPSEvaluation();
3537 /*-----------------------------------------------------------------*/
3538 /* genMinusBits - generates code for subtraction of two bits */
3539 /*-----------------------------------------------------------------*/
3541 genMinusBits (iCode * ic)
3543 symbol *lbl = newiTempLabel (NULL);
3545 D (emitcode (";", "genMinusBits "););
3547 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3549 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3550 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3551 emitcode ("cpl", "c");
3552 emitcode ("", "%05d$:", (lbl->key + 100));
3553 outBitC (IC_RESULT (ic));
3557 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3558 emitcode ("subb", "a,acc");
3559 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3560 emitcode ("inc", "a");
3561 emitcode ("", "%05d$:", (lbl->key + 100));
3562 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3563 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3567 /*-----------------------------------------------------------------*/
3568 /* genMinus - generates code for subtraction */
3569 /*-----------------------------------------------------------------*/
3571 genMinus (iCode * ic)
3573 int size, offset = 0;
3575 unsigned long lit = 0L;
3576 bool pushResult = FALSE;
3578 D (emitcode (";", "genMinus "););
3580 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3581 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3582 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3583 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3589 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3591 /* special cases :- */
3592 /* if both left & right are in bit space */
3593 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3594 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3600 /* if I can do an decrement instead
3601 of subtract then GOOD for ME */
3602 if (genMinusDec (ic) == TRUE)
3607 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3609 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3615 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3620 /* if literal, add a,#-lit, else normal subb */
3621 _startLazyDPSEvaluation ();
3624 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3625 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3626 emitcode ("subb", "a,%s",
3627 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3630 /* first add without previous c */
3632 emitcode ("add", "a,#0x%02x",
3633 (unsigned int) (lit & 0x0FFL));
3635 emitcode ("addc", "a,#0x%02x",
3636 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3641 emitcode ("push", "acc");
3645 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3649 _endLazyDPSEvaluation ();
3653 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3655 size = getDataSize (IC_LEFT (ic));
3656 rSize = getDataSize (IC_RESULT (ic));
3658 ADJUST_PUSHED_RESULT(size, rSize);
3660 _startLazyDPSEvaluation ();
3663 emitcode ("pop", "acc");
3664 aopPut (AOP (IC_RESULT (ic)), "a", size);
3666 _endLazyDPSEvaluation ();
3669 adjustArithmeticResult (ic);
3672 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3673 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3674 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3678 /*-----------------------------------------------------------------*/
3679 /* genMultbits :- multiplication of bits */
3680 /*-----------------------------------------------------------------*/
3682 genMultbits (operand * left,
3686 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3687 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3692 /*-----------------------------------------------------------------*/
3693 /* genMultOneByte : 8*8=8/16 bit multiplication */
3694 /*-----------------------------------------------------------------*/
3696 genMultOneByte (operand * left,
3700 sym_link *opetype = operandType (result);
3702 int size=AOP_SIZE(result);
3704 if (size<1 || size>2) {
3705 // this should never happen
3706 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3707 AOP_SIZE(result), __FILE__, lineno);
3711 /* (if two literals: the value is computed before) */
3712 /* if one literal, literal on the right */
3713 if (AOP_TYPE (left) == AOP_LIT)
3718 emitcode (";", "swapped left and right");
3721 if (SPEC_USIGN(opetype)
3722 // ignore the sign of left and right, what else can we do?
3723 || (SPEC_USIGN(operandType(left)) &&
3724 SPEC_USIGN(operandType(right)))) {
3725 // just an unsigned 8*8=8/16 multiply
3726 //emitcode (";","unsigned");
3727 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3728 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3729 emitcode ("mul", "ab");
3730 aopPut (AOP (result), "a", 0);
3732 aopPut (AOP (result), "b", 1);
3737 // we have to do a signed multiply
3739 emitcode (";", "signed");
3740 emitcode ("clr", "F0"); // reset sign flag
3741 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3742 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3744 lbl=newiTempLabel(NULL);
3745 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3746 // left side is negative, 8-bit two's complement, this fails for -128
3747 emitcode ("setb", "F0"); // set sign flag
3748 emitcode ("cpl", "a");
3749 emitcode ("inc", "a");
3751 emitcode ("", "%05d$:", lbl->key+100);
3752 emitcode ("xch", "a,b");
3755 if (AOP_TYPE(right)==AOP_LIT) {
3756 /* AND literal negative */
3757 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3758 // two's complement for literal<0
3759 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3760 emitcode ("cpl", "a");
3761 emitcode ("inc", "a");
3764 lbl=newiTempLabel(NULL);
3765 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3766 // right side is negative, 8-bit two's complement
3767 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3768 emitcode ("cpl", "a");
3769 emitcode ("inc", "a");
3770 emitcode ("", "%05d$:", lbl->key+100);
3772 emitcode ("mul", "ab");
3774 lbl=newiTempLabel(NULL);
3775 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3776 // only ONE op was negative, we have to do a 8/16-bit two's complement
3777 emitcode ("cpl", "a"); // lsb
3779 emitcode ("inc", "a");
3781 emitcode ("add", "a,#1");
3782 emitcode ("xch", "a,b");
3783 emitcode ("cpl", "a"); // msb
3784 emitcode ("addc", "a,#0");
3785 emitcode ("xch", "a,b");
3788 emitcode ("", "%05d$:", lbl->key+100);
3789 aopPut (AOP (result), "a", 0);
3791 aopPut (AOP (result), "b", 1);
3795 /*-----------------------------------------------------------------*/
3796 /* genMult - generates code for multiplication */
3797 /*-----------------------------------------------------------------*/
3799 genMult (iCode * ic)
3801 operand *left = IC_LEFT (ic);
3802 operand *right = IC_RIGHT (ic);
3803 operand *result = IC_RESULT (ic);
3805 D (emitcode (";", "genMult "););
3807 /* assign the amsops */
3810 /* special cases first */
3812 if (AOP_TYPE (left) == AOP_CRY &&
3813 AOP_TYPE (right) == AOP_CRY)
3815 genMultbits (left, right, result);
3819 /* if both are of size == 1 */
3820 if (AOP_SIZE (left) == 1 &&
3821 AOP_SIZE (right) == 1)
3823 genMultOneByte (left, right, result);
3827 /* should have been converted to function call */
3831 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3832 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3833 freeAsmop (result, NULL, ic, TRUE);
3836 /*-----------------------------------------------------------------*/
3837 /* genDivbits :- division of bits */
3838 /*-----------------------------------------------------------------*/
3840 genDivbits (operand * left,
3847 /* the result must be bit */
3848 LOAD_AB_FOR_DIV (left, right, l);
3849 emitcode ("div", "ab");
3850 emitcode ("rrc", "a");
3851 aopPut (AOP (result), "c", 0);
3854 /*-----------------------------------------------------------------*/
3855 /* genDivOneByte : 8 bit division */
3856 /*-----------------------------------------------------------------*/
3858 genDivOneByte (operand * left,
3862 sym_link *opetype = operandType (result);
3867 size = AOP_SIZE (result) - 1;
3869 /* signed or unsigned */
3870 if (SPEC_USIGN (opetype))
3872 /* unsigned is easy */
3873 LOAD_AB_FOR_DIV (left, right, l);
3874 emitcode ("div", "ab");
3875 aopPut (AOP (result), "a", 0);
3877 aopPut (AOP (result), zero, offset++);
3881 /* signed is a little bit more difficult */
3883 /* save the signs of the operands */
3884 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3886 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3887 emitcode ("push", "acc"); /* save it on the stack */
3889 /* now sign adjust for both left & right */
3890 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3892 lbl = newiTempLabel (NULL);
3893 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3894 emitcode ("cpl", "a");
3895 emitcode ("inc", "a");
3896 emitcode ("", "%05d$:", (lbl->key + 100));
3897 emitcode ("mov", "b,a");
3899 /* sign adjust left side */
3900 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3903 lbl = newiTempLabel (NULL);
3904 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3905 emitcode ("cpl", "a");
3906 emitcode ("inc", "a");
3907 emitcode ("", "%05d$:", (lbl->key + 100));
3909 /* now the division */
3910 emitcode ("nop", "; workaround for DS80C390 div bug.");
3911 emitcode ("div", "ab");
3912 /* we are interested in the lower order
3914 emitcode ("mov", "b,a");
3915 lbl = newiTempLabel (NULL);
3916 emitcode ("pop", "acc");
3917 /* if there was an over flow we don't
3918 adjust the sign of the result */
3919 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3920 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3922 emitcode ("clr", "a");
3923 emitcode ("subb", "a,b");
3924 emitcode ("mov", "b,a");
3925 emitcode ("", "%05d$:", (lbl->key + 100));
3927 /* now we are done */
3928 aopPut (AOP (result), "b", 0);
3931 emitcode ("mov", "c,b.7");
3932 emitcode ("subb", "a,acc");
3935 aopPut (AOP (result), "a", offset++);
3939 /*-----------------------------------------------------------------*/
3940 /* genDiv - generates code for division */
3941 /*-----------------------------------------------------------------*/
3945 operand *left = IC_LEFT (ic);
3946 operand *right = IC_RIGHT (ic);
3947 operand *result = IC_RESULT (ic);
3949 D (emitcode (";", "genDiv ");
3952 /* assign the amsops */
3955 /* special cases first */
3957 if (AOP_TYPE (left) == AOP_CRY &&
3958 AOP_TYPE (right) == AOP_CRY)
3960 genDivbits (left, right, result);
3964 /* if both are of size == 1 */
3965 if (AOP_SIZE (left) == 1 &&
3966 AOP_SIZE (right) == 1)
3968 genDivOneByte (left, right, result);
3972 /* should have been converted to function call */
3975 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3976 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3977 freeAsmop (result, NULL, ic, TRUE);
3980 /*-----------------------------------------------------------------*/
3981 /* genModbits :- modulus of bits */
3982 /*-----------------------------------------------------------------*/
3984 genModbits (operand * left,
3991 /* the result must be bit */
3992 LOAD_AB_FOR_DIV (left, right, l);
3993 emitcode ("div", "ab");
3994 emitcode ("mov", "a,b");
3995 emitcode ("rrc", "a");
3996 aopPut (AOP (result), "c", 0);
3999 /*-----------------------------------------------------------------*/
4000 /* genModOneByte : 8 bit modulus */
4001 /*-----------------------------------------------------------------*/
4003 genModOneByte (operand * left,
4007 sym_link *opetype = operandType (result);
4011 /* signed or unsigned */
4012 if (SPEC_USIGN (opetype))
4014 /* unsigned is easy */
4015 LOAD_AB_FOR_DIV (left, right, l);
4016 emitcode ("div", "ab");
4017 aopPut (AOP (result), "b", 0);
4021 /* signed is a little bit more difficult */
4023 /* save the signs of the operands */
4024 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4027 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4028 emitcode ("push", "acc"); /* save it on the stack */
4030 /* now sign adjust for both left & right */
4031 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4034 lbl = newiTempLabel (NULL);
4035 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4036 emitcode ("cpl", "a");
4037 emitcode ("inc", "a");
4038 emitcode ("", "%05d$:", (lbl->key + 100));
4039 emitcode ("mov", "b,a");
4041 /* sign adjust left side */
4042 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4045 lbl = newiTempLabel (NULL);
4046 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4047 emitcode ("cpl", "a");
4048 emitcode ("inc", "a");
4049 emitcode ("", "%05d$:", (lbl->key + 100));
4051 /* now the multiplication */
4052 emitcode ("nop", "; workaround for DS80C390 div bug.");
4053 emitcode ("div", "ab");
4054 /* we are interested in the lower order
4056 lbl = newiTempLabel (NULL);
4057 emitcode ("pop", "acc");
4058 /* if there was an over flow we don't
4059 adjust the sign of the result */
4060 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4061 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4063 emitcode ("clr", "a");
4064 emitcode ("subb", "a,b");
4065 emitcode ("mov", "b,a");
4066 emitcode ("", "%05d$:", (lbl->key + 100));
4068 /* now we are done */
4069 aopPut (AOP (result), "b", 0);
4073 /*-----------------------------------------------------------------*/
4074 /* genMod - generates code for division */
4075 /*-----------------------------------------------------------------*/
4079 operand *left = IC_LEFT (ic);
4080 operand *right = IC_RIGHT (ic);
4081 operand *result = IC_RESULT (ic);
4083 D (emitcode (";", "genMod ");
4086 /* assign the amsops */
4089 /* special cases first */
4091 if (AOP_TYPE (left) == AOP_CRY &&
4092 AOP_TYPE (right) == AOP_CRY)
4094 genModbits (left, right, result);
4098 /* if both are of size == 1 */
4099 if (AOP_SIZE (left) == 1 &&
4100 AOP_SIZE (right) == 1)
4102 genModOneByte (left, right, result);
4106 /* should have been converted to function call */
4110 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4111 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4112 freeAsmop (result, NULL, ic, TRUE);
4115 /*-----------------------------------------------------------------*/
4116 /* genIfxJump :- will create a jump depending on the ifx */
4117 /*-----------------------------------------------------------------*/
4119 genIfxJump (iCode * ic, char *jval)
4122 symbol *tlbl = newiTempLabel (NULL);
4125 D (emitcode (";", "genIfxJump ");
4128 /* if true label then we jump if condition
4132 jlbl = IC_TRUE (ic);
4133 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4134 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4138 /* false label is present */
4139 jlbl = IC_FALSE (ic);
4140 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4141 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4143 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4144 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4146 emitcode (inst, "%05d$", tlbl->key + 100);
4147 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4148 emitcode ("", "%05d$:", tlbl->key + 100);
4150 /* mark the icode as generated */
4154 /*-----------------------------------------------------------------*/
4155 /* genCmp :- greater or less than comparison */
4156 /*-----------------------------------------------------------------*/
4158 genCmp (operand * left, operand * right,
4159 iCode * ic, iCode * ifx, int sign)
4161 int size, offset = 0;
4162 unsigned long lit = 0L;
4165 D (emitcode (";", "genCmp");
4168 result = IC_RESULT (ic);
4170 /* if left & right are bit variables */
4171 if (AOP_TYPE (left) == AOP_CRY &&
4172 AOP_TYPE (right) == AOP_CRY)
4174 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4175 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4179 /* subtract right from left if at the
4180 end the carry flag is set then we know that
4181 left is greater than right */
4182 size = max (AOP_SIZE (left), AOP_SIZE (right));
4184 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4185 if ((size == 1) && !sign &&
4186 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4188 symbol *lbl = newiTempLabel (NULL);
4189 emitcode ("cjne", "%s,%s,%05d$",
4190 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4191 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4193 emitcode ("", "%05d$:", lbl->key + 100);
4197 if (AOP_TYPE (right) == AOP_LIT)
4199 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4200 /* optimize if(x < 0) or if(x >= 0) */
4209 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4211 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4212 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4214 aopOp (result, ic, FALSE, FALSE);
4216 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4218 freeAsmop (result, NULL, ic, TRUE);
4219 genIfxJump (ifx, "acc.7");
4224 emitcode ("rlc", "a");
4226 goto release_freedLR;
4234 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4235 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4236 emitcode (";", "genCmp #2");
4237 if (sign && (size == 0))
4239 emitcode (";", "genCmp #3");
4240 emitcode ("xrl", "a,#0x80");
4241 if (AOP_TYPE (right) == AOP_LIT)
4243 unsigned long lit = (unsigned long)
4244 floatFromVal (AOP (right)->aopu.aop_lit);
4245 emitcode (";", "genCmp #3.1");
4246 emitcode ("subb", "a,#0x%02x",
4247 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4251 emitcode (";", "genCmp #3.2");
4252 if (AOP_NEEDSACC (right))
4254 emitcode ("push", "acc");
4256 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4257 FALSE, FALSE, FALSE));
4258 emitcode ("xrl", "b,#0x80");
4259 if (AOP_NEEDSACC (right))
4261 emitcode ("pop", "acc");
4263 emitcode ("subb", "a,b");
4270 emitcode (";", "genCmp #4");
4271 if (AOP_NEEDSACC (right))
4274 emitcode (";", "genCmp #4.1");
4275 emitcode ("xch", "a, b");
4276 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4277 emitcode ("xch", "a, b");
4282 emitcode (";", "genCmp #4.2");
4283 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4286 emitcode ("subb", "a,%s", s);
4293 /* Don't need the left & right operands any more; do need the result. */
4294 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4295 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4297 aopOp (result, ic, FALSE, FALSE);
4301 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4307 /* if the result is used in the next
4308 ifx conditional branch then generate
4309 code a little differently */
4312 genIfxJump (ifx, "c");
4318 /* leave the result in acc */
4320 freeAsmop (result, NULL, ic, TRUE);
4323 /*-----------------------------------------------------------------*/
4324 /* genCmpGt :- greater than comparison */
4325 /*-----------------------------------------------------------------*/
4327 genCmpGt (iCode * ic, iCode * ifx)
4329 operand *left, *right;
4330 sym_link *letype, *retype;
4333 D (emitcode (";", "genCmpGt ");
4336 left = IC_LEFT (ic);
4337 right = IC_RIGHT (ic);
4339 letype = getSpec (operandType (left));
4340 retype = getSpec (operandType (right));
4341 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4343 /* assign the left & right amsops */
4346 genCmp (right, left, ic, ifx, sign);
4349 /*-----------------------------------------------------------------*/
4350 /* genCmpLt - less than comparisons */
4351 /*-----------------------------------------------------------------*/
4353 genCmpLt (iCode * ic, iCode * ifx)
4355 operand *left, *right;
4356 sym_link *letype, *retype;
4359 D (emitcode (";", "genCmpLt "););
4361 left = IC_LEFT (ic);
4362 right = IC_RIGHT (ic);
4364 letype = getSpec (operandType (left));
4365 retype = getSpec (operandType (right));
4366 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4368 /* assign the left & right amsops */
4371 genCmp (left, right, ic, ifx, sign);
4374 /*-----------------------------------------------------------------*/
4375 /* gencjneshort - compare and jump if not equal */
4376 /*-----------------------------------------------------------------*/
4378 gencjneshort (operand * left, operand * right, symbol * lbl)
4380 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4382 unsigned long lit = 0L;
4384 D (emitcode (";", "gencjneshort");
4387 /* if the left side is a literal or
4388 if the right is in a pointer register and left
4390 if ((AOP_TYPE (left) == AOP_LIT) ||
4391 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4398 if (AOP_TYPE (right) == AOP_LIT)
4399 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4401 if (opIsGptr (left) || opIsGptr (right))
4403 /* We are comparing a generic pointer to something.
4404 * Exclude the generic type byte from the comparison.
4407 D (emitcode (";", "cjneshort: generic ptr special case.");
4412 /* if the right side is a literal then anything goes */
4413 if (AOP_TYPE (right) == AOP_LIT &&
4414 AOP_TYPE (left) != AOP_DIR)
4418 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4420 emitcode ("cjne", "a,%s,%05d$",
4421 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4427 /* if the right side is in a register or in direct space or
4428 if the left is a pointer register & right is not */
4429 else if (AOP_TYPE (right) == AOP_REG ||
4430 AOP_TYPE (right) == AOP_DIR ||
4431 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4432 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4436 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4437 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4438 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4439 emitcode ("jnz", "%05d$", lbl->key + 100);
4441 emitcode ("cjne", "a,%s,%05d$",
4442 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4449 /* right is a pointer reg need both a & b */
4452 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4453 if (strcmp (l, "b"))
4454 emitcode ("mov", "b,%s", l);
4455 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4456 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4462 /*-----------------------------------------------------------------*/
4463 /* gencjne - compare and jump if not equal */
4464 /*-----------------------------------------------------------------*/
4466 gencjne (operand * left, operand * right, symbol * lbl)
4468 symbol *tlbl = newiTempLabel (NULL);
4470 D (emitcode (";", "gencjne");
4473 gencjneshort (left, right, lbl);
4475 emitcode ("mov", "a,%s", one);
4476 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4477 emitcode ("", "%05d$:", lbl->key + 100);
4478 emitcode ("clr", "a");
4479 emitcode ("", "%05d$:", tlbl->key + 100);
4482 /*-----------------------------------------------------------------*/
4483 /* genCmpEq - generates code for equal to */
4484 /*-----------------------------------------------------------------*/
4486 genCmpEq (iCode * ic, iCode * ifx)
4488 operand *left, *right, *result;
4490 D (emitcode (";", "genCmpEq ");
4494 AOP_SET_LOCALS (ic);
4496 /* if literal, literal on the right or
4497 if the right is in a pointer register and left
4499 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4500 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4502 operand *t = IC_RIGHT (ic);
4503 IC_RIGHT (ic) = IC_LEFT (ic);
4507 if (ifx && /* !AOP_SIZE(result) */
4508 OP_SYMBOL (result) &&
4509 OP_SYMBOL (result)->regType == REG_CND)
4512 /* if they are both bit variables */
4513 if (AOP_TYPE (left) == AOP_CRY &&
4514 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4516 if (AOP_TYPE (right) == AOP_LIT)
4518 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4521 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4522 emitcode ("cpl", "c");
4526 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4530 emitcode ("clr", "c");
4532 /* AOP_TYPE(right) == AOP_CRY */
4536 symbol *lbl = newiTempLabel (NULL);
4537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4538 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4539 emitcode ("cpl", "c");
4540 emitcode ("", "%05d$:", (lbl->key + 100));
4542 /* if true label then we jump if condition
4544 tlbl = newiTempLabel (NULL);
4547 emitcode ("jnc", "%05d$", tlbl->key + 100);
4548 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4552 emitcode ("jc", "%05d$", tlbl->key + 100);
4553 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4555 emitcode ("", "%05d$:", tlbl->key + 100);
4559 tlbl = newiTempLabel (NULL);
4560 gencjneshort (left, right, tlbl);
4563 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4564 emitcode ("", "%05d$:", tlbl->key + 100);
4568 symbol *lbl = newiTempLabel (NULL);
4569 emitcode ("sjmp", "%05d$", lbl->key + 100);
4570 emitcode ("", "%05d$:", tlbl->key + 100);
4571 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4572 emitcode ("", "%05d$:", lbl->key + 100);
4575 /* mark the icode as generated */
4578 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4579 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4583 /* if they are both bit variables */
4584 if (AOP_TYPE (left) == AOP_CRY &&
4585 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4587 if (AOP_TYPE (right) == AOP_LIT)
4589 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4592 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4593 emitcode ("cpl", "c");
4597 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4601 emitcode ("clr", "c");
4603 /* AOP_TYPE(right) == AOP_CRY */
4607 symbol *lbl = newiTempLabel (NULL);
4608 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4609 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4610 emitcode ("cpl", "c");
4611 emitcode ("", "%05d$:", (lbl->key + 100));
4614 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4615 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617 aopOp (result, ic, TRUE, FALSE);
4620 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4627 genIfxJump (ifx, "c");
4630 /* if the result is used in an arithmetic operation
4631 then put the result in place */
4636 gencjne (left, right, newiTempLabel (NULL));
4638 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4639 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4641 aopOp (result, ic, TRUE, FALSE);
4643 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4645 aopPut (AOP (result), "a", 0);
4650 genIfxJump (ifx, "a");
4653 /* if the result is used in an arithmetic operation
4654 then put the result in place */
4655 if (AOP_TYPE (result) != AOP_CRY)
4657 /* leave the result in acc */
4661 freeAsmop (result, NULL, ic, TRUE);
4664 /*-----------------------------------------------------------------*/
4665 /* ifxForOp - returns the icode containing the ifx for operand */
4666 /*-----------------------------------------------------------------*/
4668 ifxForOp (operand * op, iCode * ic)
4670 /* if true symbol then needs to be assigned */
4671 if (IS_TRUE_SYMOP (op))
4674 /* if this has register type condition and
4675 the next instruction is ifx with the same operand
4676 and live to of the operand is upto the ifx only then */
4678 ic->next->op == IFX &&
4679 IC_COND (ic->next)->key == op->key &&
4680 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4685 /*-----------------------------------------------------------------*/
4686 /* genAndOp - for && operation */
4687 /*-----------------------------------------------------------------*/
4689 genAndOp (iCode * ic)
4691 operand *left, *right, *result;
4694 D (emitcode (";", "genAndOp "););
4696 /* note here that && operations that are in an
4697 if statement are taken away by backPatchLabels
4698 only those used in arthmetic operations remain */
4700 AOP_SET_LOCALS (ic);
4702 /* if both are bit variables */
4703 if (AOP_TYPE (left) == AOP_CRY &&
4704 AOP_TYPE (right) == AOP_CRY)
4706 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4707 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4708 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4709 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4711 aopOp (result,ic,FALSE, FALSE);
4716 tlbl = newiTempLabel (NULL);
4718 emitcode ("jz", "%05d$", tlbl->key + 100);
4720 emitcode ("", "%05d$:", tlbl->key + 100);
4721 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4722 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4724 aopOp (result,ic,FALSE, FALSE);
4727 freeAsmop (result, NULL, ic, TRUE);
4731 /*-----------------------------------------------------------------*/
4732 /* genOrOp - for || operation */
4733 /*-----------------------------------------------------------------*/
4735 genOrOp (iCode * ic)
4737 operand *left, *right, *result;
4740 D (emitcode (";", "genOrOp "););
4742 /* note here that || operations that are in an
4743 if statement are taken away by backPatchLabels
4744 only those used in arthmetic operations remain */
4746 AOP_SET_LOCALS (ic);
4748 /* if both are bit variables */
4749 if (AOP_TYPE (left) == AOP_CRY &&
4750 AOP_TYPE (right) == AOP_CRY)
4752 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4753 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4754 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4755 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4757 aopOp (result,ic,FALSE, FALSE);
4763 tlbl = newiTempLabel (NULL);
4765 emitcode ("jnz", "%05d$", tlbl->key + 100);
4767 emitcode ("", "%05d$:", tlbl->key + 100);
4768 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4769 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771 aopOp (result,ic,FALSE, FALSE);
4776 freeAsmop (result, NULL, ic, TRUE);
4779 /*-----------------------------------------------------------------*/
4780 /* isLiteralBit - test if lit == 2^n */
4781 /*-----------------------------------------------------------------*/
4783 isLiteralBit (unsigned long lit)
4785 unsigned long pw[32] =
4786 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4787 0x100L, 0x200L, 0x400L, 0x800L,
4788 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4789 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4790 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4791 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4792 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4795 for (idx = 0; idx < 32; idx++)
4801 /*-----------------------------------------------------------------*/
4802 /* continueIfTrue - */
4803 /*-----------------------------------------------------------------*/
4805 continueIfTrue (iCode * ic)
4808 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4812 /*-----------------------------------------------------------------*/
4814 /*-----------------------------------------------------------------*/
4816 jumpIfTrue (iCode * ic)
4819 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4823 /*-----------------------------------------------------------------*/
4824 /* jmpTrueOrFalse - */
4825 /*-----------------------------------------------------------------*/
4827 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4829 // ugly but optimized by peephole
4832 symbol *nlbl = newiTempLabel (NULL);
4833 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4834 emitcode ("", "%05d$:", tlbl->key + 100);
4835 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4836 emitcode ("", "%05d$:", nlbl->key + 100);
4840 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4841 emitcode ("", "%05d$:", tlbl->key + 100);
4846 // Generate code to perform a bit-wise logic operation
4847 // on two operands in far space (assumed to already have been
4848 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4849 // in far space. This requires pushing the result on the stack
4850 // then popping it into the result.
4852 genFarFarLogicOp(iCode *ic, char *logicOp)
4854 int size, resultSize, compSize;
4857 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4858 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4859 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4861 _startLazyDPSEvaluation();
4862 for (size = compSize; (size--); offset++)
4864 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4865 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4866 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4868 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4869 emitcode ("push", "acc");
4871 _endLazyDPSEvaluation();
4873 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4874 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4875 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4877 resultSize = AOP_SIZE(IC_RESULT(ic));
4879 ADJUST_PUSHED_RESULT(compSize, resultSize);
4881 _startLazyDPSEvaluation();
4884 emitcode ("pop", "acc");
4885 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4887 _endLazyDPSEvaluation();
4888 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4892 /*-----------------------------------------------------------------*/
4893 /* genAnd - code for and */
4894 /*-----------------------------------------------------------------*/
4896 genAnd (iCode * ic, iCode * ifx)
4898 operand *left, *right, *result;
4899 int size, offset = 0;
4900 unsigned long lit = 0L;
4905 D (emitcode (";", "genAnd "););
4907 AOP_OP_3_NOFATAL (ic, pushResult);
4908 AOP_SET_LOCALS (ic);
4912 genFarFarLogicOp(ic, "anl");
4917 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4919 AOP_TYPE (left), AOP_TYPE (right));
4920 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4922 AOP_SIZE (left), AOP_SIZE (right));
4925 /* if left is a literal & right is not then exchange them */
4926 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4927 AOP_NEEDSACC (left))
4929 operand *tmp = right;
4934 /* if result = right then exchange them */
4935 if (sameRegs (AOP (result), AOP (right)))
4937 operand *tmp = right;
4942 /* if right is bit then exchange them */
4943 if (AOP_TYPE (right) == AOP_CRY &&
4944 AOP_TYPE (left) != AOP_CRY)
4946 operand *tmp = right;
4950 if (AOP_TYPE (right) == AOP_LIT)
4951 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4953 size = AOP_SIZE (result);
4956 // result = bit & yy;
4957 if (AOP_TYPE (left) == AOP_CRY)
4959 // c = bit & literal;
4960 if (AOP_TYPE (right) == AOP_LIT)
4964 if (size && sameRegs (AOP (result), AOP (left)))
4967 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4972 if (size && (AOP_TYPE (result) == AOP_CRY))
4974 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4977 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4982 emitcode ("clr", "c");
4987 if (AOP_TYPE (right) == AOP_CRY)
4990 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4991 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4996 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4998 emitcode ("rrc", "a");
4999 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5007 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5008 genIfxJump (ifx, "c");
5012 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5013 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5014 if ((AOP_TYPE (right) == AOP_LIT) &&
5015 (AOP_TYPE (result) == AOP_CRY) &&
5016 (AOP_TYPE (left) != AOP_CRY))
5018 int posbit = isLiteralBit (lit);
5023 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5026 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5032 sprintf (buffer, "acc.%d", posbit & 0x07);
5033 genIfxJump (ifx, buffer);
5040 symbol *tlbl = newiTempLabel (NULL);
5041 int sizel = AOP_SIZE (left);
5043 emitcode ("setb", "c");
5046 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5048 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5050 if ((posbit = isLiteralBit (bytelit)) != 0)
5051 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5054 if (bytelit != 0x0FFL)
5055 emitcode ("anl", "a,%s",
5056 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5057 emitcode ("jnz", "%05d$", tlbl->key + 100);
5062 // bit = left & literal
5065 emitcode ("clr", "c");
5066 emitcode ("", "%05d$:", tlbl->key + 100);
5068 // if(left & literal)
5072 jmpTrueOrFalse (ifx, tlbl);
5080 /* if left is same as result */
5081 if (sameRegs (AOP (result), AOP (left)))
5083 for (; size--; offset++)
5085 if (AOP_TYPE (right) == AOP_LIT)
5087 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5089 else if (bytelit == 0)
5090 aopPut (AOP (result), zero, offset);
5091 else if (IS_AOP_PREG (result))
5093 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5094 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5095 aopPut (AOP (result), "a", offset);
5098 emitcode ("anl", "%s,%s",
5099 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5100 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5104 if (AOP_TYPE (left) == AOP_ACC)
5105 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5108 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5109 if (IS_AOP_PREG (result))
5111 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5112 aopPut (AOP (result), "a", offset);
5116 emitcode ("anl", "%s,a",
5117 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5124 // left & result in different registers
5125 if (AOP_TYPE (result) == AOP_CRY)
5128 // if(size), result in bit
5129 // if(!size && ifx), conditional oper: if(left & right)
5130 symbol *tlbl = newiTempLabel (NULL);
5131 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5133 emitcode ("setb", "c");
5136 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5137 emitcode ("anl", "a,%s",
5138 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5139 emitcode ("jnz", "%05d$", tlbl->key + 100);
5145 emitcode ("", "%05d$:", tlbl->key + 100);
5149 jmpTrueOrFalse (ifx, tlbl);
5153 for (; (size--); offset++)
5156 // result = left & right
5157 if (AOP_TYPE (right) == AOP_LIT)
5159 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5161 aopPut (AOP (result),
5162 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5166 else if (bytelit == 0)
5168 aopPut (AOP (result), zero, offset);
5171 D (emitcode (";", "better literal AND.");
5173 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5174 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5175 FALSE, FALSE, FALSE));
5180 // faster than result <- left, anl result,right
5181 // and better if result is SFR
5182 if (AOP_TYPE (left) == AOP_ACC)
5184 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5185 FALSE, FALSE, FALSE));
5189 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5190 emitcode ("anl", "a,%s",
5191 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5194 aopPut (AOP (result), "a", offset);
5200 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5201 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5202 freeAsmop (result, NULL, ic, TRUE);
5206 /*-----------------------------------------------------------------*/
5207 /* genOr - code for or */
5208 /*-----------------------------------------------------------------*/
5210 genOr (iCode * ic, iCode * ifx)
5212 operand *left, *right, *result;
5213 int size, offset = 0;
5214 unsigned long lit = 0L;
5217 D (emitcode (";", "genOr "););
5219 AOP_OP_3_NOFATAL (ic, pushResult);
5220 AOP_SET_LOCALS (ic);
5224 genFarFarLogicOp(ic, "orl");
5230 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5232 AOP_TYPE (left), AOP_TYPE (right));
5233 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5235 AOP_SIZE (left), AOP_SIZE (right));
5238 /* if left is a literal & right is not then exchange them */
5239 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5240 AOP_NEEDSACC (left))
5242 operand *tmp = right;
5247 /* if result = right then exchange them */
5248 if (sameRegs (AOP (result), AOP (right)))
5250 operand *tmp = right;
5255 /* if right is bit then exchange them */
5256 if (AOP_TYPE (right) == AOP_CRY &&
5257 AOP_TYPE (left) != AOP_CRY)
5259 operand *tmp = right;
5263 if (AOP_TYPE (right) == AOP_LIT)
5264 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5266 size = AOP_SIZE (result);
5270 if (AOP_TYPE (left) == AOP_CRY)
5272 if (AOP_TYPE (right) == AOP_LIT)
5274 // c = bit & literal;
5277 // lit != 0 => result = 1
5278 if (AOP_TYPE (result) == AOP_CRY)
5281 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5283 continueIfTrue (ifx);
5286 emitcode ("setb", "c");
5290 // lit == 0 => result = left
5291 if (size && sameRegs (AOP (result), AOP (left)))
5293 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5298 if (AOP_TYPE (right) == AOP_CRY)
5301 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5302 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5307 symbol *tlbl = newiTempLabel (NULL);
5308 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5309 emitcode ("setb", "c");
5310 emitcode ("jb", "%s,%05d$",
5311 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5313 emitcode ("jnz", "%05d$", tlbl->key + 100);
5314 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5316 jmpTrueOrFalse (ifx, tlbl);
5322 emitcode ("", "%05d$:", tlbl->key + 100);
5331 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5332 genIfxJump (ifx, "c");
5336 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5337 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5338 if ((AOP_TYPE (right) == AOP_LIT) &&
5339 (AOP_TYPE (result) == AOP_CRY) &&
5340 (AOP_TYPE (left) != AOP_CRY))
5346 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5348 continueIfTrue (ifx);
5353 // lit = 0, result = boolean(left)
5355 emitcode ("setb", "c");
5359 symbol *tlbl = newiTempLabel (NULL);
5360 emitcode ("jnz", "%05d$", tlbl->key + 100);
5362 emitcode ("", "%05d$:", tlbl->key + 100);
5366 genIfxJump (ifx, "a");
5374 /* if left is same as result */
5375 if (sameRegs (AOP (result), AOP (left)))
5377 for (; size--; offset++)
5379 if (AOP_TYPE (right) == AOP_LIT)
5381 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5387 if (IS_AOP_PREG (left))
5389 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5390 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5391 aopPut (AOP (result), "a", offset);
5395 emitcode ("orl", "%s,%s",
5396 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5397 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5403 if (AOP_TYPE (left) == AOP_ACC)
5405 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5409 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5410 if (IS_AOP_PREG (left))
5412 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5413 aopPut (AOP (result), "a", offset);
5417 emitcode ("orl", "%s,a",
5418 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5426 // left & result in different registers
5427 if (AOP_TYPE (result) == AOP_CRY)
5430 // if(size), result in bit
5431 // if(!size && ifx), conditional oper: if(left | right)
5432 symbol *tlbl = newiTempLabel (NULL);
5433 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5435 emitcode ("setb", "c");
5438 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5439 emitcode ("orl", "a,%s",
5440 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5441 emitcode ("jnz", "%05d$", tlbl->key + 100);
5447 emitcode ("", "%05d$:", tlbl->key + 100);
5451 jmpTrueOrFalse (ifx, tlbl);
5455 for (; (size--); offset++)
5458 // result = left & right
5459 if (AOP_TYPE (right) == AOP_LIT)
5461 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5463 aopPut (AOP (result),
5464 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5468 D (emitcode (";", "better literal OR.");
5470 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5471 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5472 FALSE, FALSE, FALSE));
5477 // faster than result <- left, anl result,right
5478 // and better if result is SFR
5479 if (AOP_TYPE (left) == AOP_ACC)
5481 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5482 FALSE, FALSE, FALSE));
5486 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5487 emitcode ("orl", "a,%s",
5488 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5491 aopPut (AOP (result), "a", offset);
5497 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5498 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5499 freeAsmop (result, NULL, ic, TRUE);
5502 /*-----------------------------------------------------------------*/
5503 /* genXor - code for xclusive or */
5504 /*-----------------------------------------------------------------*/
5506 genXor (iCode * ic, iCode * ifx)
5508 operand *left, *right, *result;
5509 int size, offset = 0;
5510 unsigned long lit = 0L;
5513 D (emitcode (";", "genXor "););
5515 AOP_OP_3_NOFATAL (ic, pushResult);
5516 AOP_SET_LOCALS (ic);
5520 genFarFarLogicOp(ic, "xrl");
5525 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5527 AOP_TYPE (left), AOP_TYPE (right));
5528 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5530 AOP_SIZE (left), AOP_SIZE (right));
5533 /* if left is a literal & right is not ||
5534 if left needs acc & right does not */
5535 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5536 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5538 operand *tmp = right;
5543 /* if result = right then exchange them */
5544 if (sameRegs (AOP (result), AOP (right)))
5546 operand *tmp = right;
5551 /* if right is bit then exchange them */
5552 if (AOP_TYPE (right) == AOP_CRY &&
5553 AOP_TYPE (left) != AOP_CRY)
5555 operand *tmp = right;
5559 if (AOP_TYPE (right) == AOP_LIT)
5560 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5562 size = AOP_SIZE (result);
5566 if (AOP_TYPE (left) == AOP_CRY)
5568 if (AOP_TYPE (right) == AOP_LIT)
5570 // c = bit & literal;
5573 // lit>>1 != 0 => result = 1
5574 if (AOP_TYPE (result) == AOP_CRY)
5577 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5579 continueIfTrue (ifx);
5582 emitcode ("setb", "c");
5589 // lit == 0, result = left
5590 if (size && sameRegs (AOP (result), AOP (left)))
5592 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5596 // lit == 1, result = not(left)
5597 if (size && sameRegs (AOP (result), AOP (left)))
5599 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5604 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5605 emitcode ("cpl", "c");
5614 symbol *tlbl = newiTempLabel (NULL);
5615 if (AOP_TYPE (right) == AOP_CRY)
5618 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5622 int sizer = AOP_SIZE (right);
5624 // if val>>1 != 0, result = 1
5625 emitcode ("setb", "c");
5628 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5630 // test the msb of the lsb
5631 emitcode ("anl", "a,#0xfe");
5632 emitcode ("jnz", "%05d$", tlbl->key + 100);
5636 emitcode ("rrc", "a");
5638 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5639 emitcode ("cpl", "c");
5640 emitcode ("", "%05d$:", (tlbl->key + 100));
5647 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5648 genIfxJump (ifx, "c");
5652 if (sameRegs (AOP (result), AOP (left)))
5654 /* if left is same as result */
5655 for (; size--; offset++)
5657 if (AOP_TYPE (right) == AOP_LIT)
5659 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5661 else if (IS_AOP_PREG (left))
5663 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5664 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5665 aopPut (AOP (result), "a", offset);
5668 emitcode ("xrl", "%s,%s",
5669 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5670 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5674 if (AOP_TYPE (left) == AOP_ACC)
5675 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5678 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5679 if (IS_AOP_PREG (left))
5681 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5682 aopPut (AOP (result), "a", offset);
5685 emitcode ("xrl", "%s,a",
5686 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5693 // left & result in different registers
5694 if (AOP_TYPE (result) == AOP_CRY)
5697 // if(size), result in bit
5698 // if(!size && ifx), conditional oper: if(left ^ right)
5699 symbol *tlbl = newiTempLabel (NULL);
5700 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5702 emitcode ("setb", "c");
5705 if ((AOP_TYPE (right) == AOP_LIT) &&
5706 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5708 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5712 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5713 emitcode ("xrl", "a,%s",
5714 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5716 emitcode ("jnz", "%05d$", tlbl->key + 100);
5722 emitcode ("", "%05d$:", tlbl->key + 100);
5726 jmpTrueOrFalse (ifx, tlbl);
5729 for (; (size--); offset++)
5732 // result = left & right
5733 if (AOP_TYPE (right) == AOP_LIT)
5735 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5737 aopPut (AOP (result),
5738 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5742 D (emitcode (";", "better literal XOR.");
5744 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5745 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5746 FALSE, FALSE, FALSE));
5750 // faster than result <- left, anl result,right
5751 // and better if result is SFR
5752 if (AOP_TYPE (left) == AOP_ACC)
5754 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5755 FALSE, FALSE, FALSE));
5759 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5760 emitcode ("xrl", "a,%s",
5761 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5764 aopPut (AOP (result), "a", offset);
5769 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5770 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5771 freeAsmop (result, NULL, ic, TRUE);
5774 /*-----------------------------------------------------------------*/
5775 /* genInline - write the inline code out */
5776 /*-----------------------------------------------------------------*/
5778 genInline (iCode * ic)
5780 char *buffer, *bp, *bp1;
5782 D (emitcode (";", "genInline ");
5785 _G.inLine += (!options.asmpeep);
5787 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5788 strcpy (buffer, IC_INLINE (ic));
5790 /* emit each line as a code */
5815 /* emitcode("",buffer); */
5816 _G.inLine -= (!options.asmpeep);
5819 /*-----------------------------------------------------------------*/
5820 /* genRRC - rotate right with carry */
5821 /*-----------------------------------------------------------------*/
5825 operand *left, *result;
5826 int size, offset = 0;
5829 D (emitcode (";", "genRRC ");
5832 /* rotate right with carry */
5833 left = IC_LEFT (ic);
5834 result = IC_RESULT (ic);
5835 aopOp (left, ic, FALSE, FALSE);
5836 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5838 /* move it to the result */
5839 size = AOP_SIZE (result);
5843 _startLazyDPSEvaluation ();
5846 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5848 emitcode ("rrc", "a");
5849 if (AOP_SIZE (result) > 1)
5850 aopPut (AOP (result), "a", offset--);
5852 _endLazyDPSEvaluation ();
5854 /* now we need to put the carry into the
5855 highest order byte of the result */
5856 if (AOP_SIZE (result) > 1)
5858 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5861 emitcode ("mov", "acc.7,c");
5862 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5863 freeAsmop (left, NULL, ic, TRUE);
5864 freeAsmop (result, NULL, ic, TRUE);
5867 /*-----------------------------------------------------------------*/
5868 /* genRLC - generate code for rotate left with carry */
5869 /*-----------------------------------------------------------------*/
5873 operand *left, *result;
5874 int size, offset = 0;
5877 D (emitcode (";", "genRLC ");
5880 /* rotate right with carry */
5881 left = IC_LEFT (ic);
5882 result = IC_RESULT (ic);
5883 aopOp (left, ic, FALSE, FALSE);
5884 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5886 /* move it to the result */
5887 size = AOP_SIZE (result);
5891 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5893 emitcode ("add", "a,acc");
5894 if (AOP_SIZE (result) > 1)
5896 aopPut (AOP (result), "a", offset++);
5899 _startLazyDPSEvaluation ();
5902 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5904 emitcode ("rlc", "a");
5905 if (AOP_SIZE (result) > 1)
5906 aopPut (AOP (result), "a", offset++);
5908 _endLazyDPSEvaluation ();
5910 /* now we need to put the carry into the
5911 highest order byte of the result */
5912 if (AOP_SIZE (result) > 1)
5914 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5917 emitcode ("mov", "acc.0,c");
5918 aopPut (AOP (result), "a", 0);
5919 freeAsmop (left, NULL, ic, TRUE);
5920 freeAsmop (result, NULL, ic, TRUE);
5923 /*-----------------------------------------------------------------*/
5924 /* genGetHbit - generates code get highest order bit */
5925 /*-----------------------------------------------------------------*/
5927 genGetHbit (iCode * ic)
5929 operand *left, *result;
5930 left = IC_LEFT (ic);
5931 result = IC_RESULT (ic);
5932 aopOp (left, ic, FALSE, FALSE);
5933 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5935 D (emitcode (";", "genGetHbit ");
5938 /* get the highest order byte into a */
5939 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5940 if (AOP_TYPE (result) == AOP_CRY)
5942 emitcode ("rlc", "a");
5947 emitcode ("rl", "a");
5948 emitcode ("anl", "a,#0x01");
5953 freeAsmop (left, NULL, ic, TRUE);
5954 freeAsmop (result, NULL, ic, TRUE);
5957 /*-----------------------------------------------------------------*/
5958 /* AccRol - rotate left accumulator by known count */
5959 /*-----------------------------------------------------------------*/
5961 AccRol (int shCount)
5963 shCount &= 0x0007; // shCount : 0..7
5970 emitcode ("rl", "a");
5973 emitcode ("rl", "a");
5974 emitcode ("rl", "a");
5977 emitcode ("swap", "a");
5978 emitcode ("rr", "a");
5981 emitcode ("swap", "a");
5984 emitcode ("swap", "a");
5985 emitcode ("rl", "a");
5988 emitcode ("rr", "a");
5989 emitcode ("rr", "a");
5992 emitcode ("rr", "a");
5997 /*-----------------------------------------------------------------*/
5998 /* AccLsh - left shift accumulator by known count */
5999 /*-----------------------------------------------------------------*/
6001 AccLsh (int shCount)
6006 emitcode ("add", "a,acc");
6007 else if (shCount == 2)
6009 emitcode ("add", "a,acc");
6010 emitcode ("add", "a,acc");
6014 /* rotate left accumulator */
6016 /* and kill the lower order bits */
6017 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6022 /*-----------------------------------------------------------------*/
6023 /* AccRsh - right shift accumulator by known count */
6024 /*-----------------------------------------------------------------*/
6026 AccRsh (int shCount)
6033 emitcode ("rrc", "a");
6037 /* rotate right accumulator */
6038 AccRol (8 - shCount);
6039 /* and kill the higher order bits */
6040 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6045 #ifdef BETTER_LITERAL_SHIFT
6046 /*-----------------------------------------------------------------*/
6047 /* AccSRsh - signed right shift accumulator by known count */
6048 /*-----------------------------------------------------------------*/
6050 AccSRsh (int shCount)
6057 emitcode ("mov", "c,acc.7");
6058 emitcode ("rrc", "a");
6060 else if (shCount == 2)
6062 emitcode ("mov", "c,acc.7");
6063 emitcode ("rrc", "a");
6064 emitcode ("mov", "c,acc.7");
6065 emitcode ("rrc", "a");
6069 tlbl = newiTempLabel (NULL);
6070 /* rotate right accumulator */
6071 AccRol (8 - shCount);
6072 /* and kill the higher order bits */
6073 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6074 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6075 emitcode ("orl", "a,#0x%02x",
6076 (unsigned char) ~SRMask[shCount]);
6077 emitcode ("", "%05d$:", tlbl->key + 100);
6083 #ifdef BETTER_LITERAL_SHIFT
6084 /*-----------------------------------------------------------------*/
6085 /* shiftR1Left2Result - shift right one byte from left to result */
6086 /*-----------------------------------------------------------------*/
6088 shiftR1Left2Result (operand * left, int offl,
6089 operand * result, int offr,
6090 int shCount, int sign)
6092 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6093 /* shift right accumulator */
6098 aopPut (AOP (result), "a", offr);
6102 #ifdef BETTER_LITERAL_SHIFT
6103 /*-----------------------------------------------------------------*/
6104 /* shiftL1Left2Result - shift left one byte from left to result */
6105 /*-----------------------------------------------------------------*/
6107 shiftL1Left2Result (operand * left, int offl,
6108 operand * result, int offr, int shCount)
6110 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6111 /* shift left accumulator */
6113 aopPut (AOP (result), "a", offr);
6117 #ifdef BETTER_LITERAL_SHIFT
6118 /*-----------------------------------------------------------------*/
6119 /* movLeft2Result - move byte from left to result */
6120 /*-----------------------------------------------------------------*/
6122 movLeft2Result (operand * left, int offl,
6123 operand * result, int offr, int sign)
6126 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6128 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6130 if (*l == '@' && (IS_AOP_PREG (result)))
6132 emitcode ("mov", "a,%s", l);
6133 aopPut (AOP (result), "a", offr);
6139 aopPut (AOP (result), l, offr);
6143 /* MSB sign in acc.7 ! */
6144 if (getDataSize (left) == offl + 1)
6146 emitcode ("mov", "a,%s", l);
6147 aopPut (AOP (result), "a", offr);
6155 #ifdef BETTER_LITERAL_SHIFT
6156 /*-----------------------------------------------------------------*/
6157 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6158 /*-----------------------------------------------------------------*/
6162 emitcode ("rrc", "a");
6163 emitcode ("xch", "a,%s", x);
6164 emitcode ("rrc", "a");
6165 emitcode ("xch", "a,%s", x);
6169 #ifdef BETTER_LITERAL_SHIFT
6171 /*-----------------------------------------------------------------*/
6172 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6173 /*-----------------------------------------------------------------*/
6177 emitcode ("xch", "a,%s", x);
6178 emitcode ("rlc", "a");
6179 emitcode ("xch", "a,%s", x);
6180 emitcode ("rlc", "a");
6184 #ifdef BETTER_LITERAL_SHIFT
6185 /*-----------------------------------------------------------------*/
6186 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6187 /*-----------------------------------------------------------------*/
6191 emitcode ("xch", "a,%s", x);
6192 emitcode ("add", "a,acc");
6193 emitcode ("xch", "a,%s", x);
6194 emitcode ("rlc", "a");
6198 #ifdef BETTER_LITERAL_SHIFT
6199 /*-----------------------------------------------------------------*/
6200 /* AccAXLsh - left shift a:x by known count (0..7) */
6201 /*-----------------------------------------------------------------*/
6203 AccAXLsh (char *x, int shCount)
6218 case 5: // AAAAABBB:CCCCCDDD
6220 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6222 emitcode ("anl", "a,#0x%02x",
6223 SLMask[shCount]); // BBB00000:CCCCCDDD
6225 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6227 AccRol (shCount); // DDDCCCCC:BBB00000
6229 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6231 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6233 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6235 emitcode ("anl", "a,#0x%02x",
6236 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6238 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6240 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6243 case 6: // AAAAAABB:CCCCCCDD
6244 emitcode ("anl", "a,#0x%02x",
6245 SRMask[shCount]); // 000000BB:CCCCCCDD
6246 emitcode ("mov", "c,acc.0"); // c = B
6247 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6249 AccAXRrl1 (x); // BCCCCCCD:D000000B
6250 AccAXRrl1 (x); // BBCCCCCC:DD000000
6252 emitcode("rrc","a");
6253 emitcode("xch","a,%s", x);
6254 emitcode("rrc","a");
6255 emitcode("mov","c,acc.0"); //<< get correct bit
6256 emitcode("xch","a,%s", x);
6258 emitcode("rrc","a");
6259 emitcode("xch","a,%s", x);
6260 emitcode("rrc","a");
6261 emitcode("xch","a,%s", x);
6264 case 7: // a:x <<= 7
6266 emitcode ("anl", "a,#0x%02x",
6267 SRMask[shCount]); // 0000000B:CCCCCCCD
6269 emitcode ("mov", "c,acc.0"); // c = B
6271 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6273 AccAXRrl1 (x); // BCCCCCCC:D0000000
6282 #ifdef BETTER_LITERAL_SHIFT
6284 /*-----------------------------------------------------------------*/
6285 /* AccAXRsh - right shift a:x known count (0..7) */
6286 /*-----------------------------------------------------------------*/
6288 AccAXRsh (char *x, int shCount)
6296 AccAXRrl1 (x); // 0->a:x
6301 AccAXRrl1 (x); // 0->a:x
6304 AccAXRrl1 (x); // 0->a:x
6309 case 5: // AAAAABBB:CCCCCDDD = a:x
6311 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6313 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6315 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6317 emitcode ("anl", "a,#0x%02x",
6318 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6320 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6322 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6324 emitcode ("anl", "a,#0x%02x",
6325 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6327 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6329 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6331 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6334 case 6: // AABBBBBB:CCDDDDDD
6336 emitcode ("mov", "c,acc.7");
6337 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6339 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6341 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6343 emitcode ("anl", "a,#0x%02x",
6344 SRMask[shCount]); // 000000AA:BBBBBBCC
6347 case 7: // ABBBBBBB:CDDDDDDD
6349 emitcode ("mov", "c,acc.7"); // c = A
6351 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6353 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6355 emitcode ("anl", "a,#0x%02x",
6356 SRMask[shCount]); // 0000000A:BBBBBBBC
6365 #ifdef BETTER_LITERAL_SHIFT
6367 /*-----------------------------------------------------------------*/
6368 /* AccAXRshS - right shift signed a:x known count (0..7) */
6369 /*-----------------------------------------------------------------*/
6371 AccAXRshS (char *x, int shCount)
6379 emitcode ("mov", "c,acc.7");
6380 AccAXRrl1 (x); // s->a:x
6384 emitcode ("mov", "c,acc.7");
6385 AccAXRrl1 (x); // s->a:x
6387 emitcode ("mov", "c,acc.7");
6388 AccAXRrl1 (x); // s->a:x
6393 case 5: // AAAAABBB:CCCCCDDD = a:x
6395 tlbl = newiTempLabel (NULL);
6396 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6398 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6400 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6402 emitcode ("anl", "a,#0x%02x",
6403 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6405 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6407 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6409 emitcode ("anl", "a,#0x%02x",
6410 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6412 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6414 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6416 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6418 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6419 emitcode ("orl", "a,#0x%02x",
6420 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6422 emitcode ("", "%05d$:", tlbl->key + 100);
6423 break; // SSSSAAAA:BBBCCCCC
6425 case 6: // AABBBBBB:CCDDDDDD
6427 tlbl = newiTempLabel (NULL);
6428 emitcode ("mov", "c,acc.7");
6429 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6431 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6433 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6435 emitcode ("anl", "a,#0x%02x",
6436 SRMask[shCount]); // 000000AA:BBBBBBCC
6438 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6439 emitcode ("orl", "a,#0x%02x",
6440 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6442 emitcode ("", "%05d$:", tlbl->key + 100);
6444 case 7: // ABBBBBBB:CDDDDDDD
6446 tlbl = newiTempLabel (NULL);
6447 emitcode ("mov", "c,acc.7"); // c = A
6449 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6451 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6453 emitcode ("anl", "a,#0x%02x",
6454 SRMask[shCount]); // 0000000A:BBBBBBBC
6456 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6457 emitcode ("orl", "a,#0x%02x",
6458 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6460 emitcode ("", "%05d$:", tlbl->key + 100);
6468 #ifdef BETTER_LITERAL_SHIFT
6470 _loadLeftIntoAx(char **lsb,
6476 // Get the initial value from left into a pair of registers.
6477 // MSB must be in A, LSB can be any register.
6479 // If the result is held in registers, it is an optimization
6480 // if the LSB can be held in the register which will hold the,
6481 // result LSB since this saves us from having to copy it into
6482 // the result following AccAXLsh.
6484 // If the result is addressed indirectly, this is not a gain.
6485 if (AOP_NEEDSACC(result))
6489 _startLazyDPSEvaluation();
6490 if (AOP_TYPE(left) == AOP_DPTR2)
6493 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6494 // get LSB in DP2_RESULT_REG.
6495 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6496 assert(!strcmp(leftByte, DP2_RESULT_REG));
6500 // get LSB into DP2_RESULT_REG
6501 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6502 if (strcmp(leftByte, DP2_RESULT_REG))
6504 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6507 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6508 assert(strcmp(leftByte, DP2_RESULT_REG));
6511 _endLazyDPSEvaluation();
6512 *lsb = DP2_RESULT_REG;
6516 if (sameRegs (AOP (result), AOP (left)) &&
6517 ((offl + MSB16) == offr))
6519 /* don't crash result[offr] */
6520 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6521 emitcode ("xch", "a,%s",
6522 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6526 movLeft2Result (left, offl, result, offr, 0);
6527 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6529 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6530 assert(strcmp(*lsb,"a"));
6535 _storeAxResults(char *lsb,
6539 _startLazyDPSEvaluation();
6540 if (AOP_NEEDSACC(result))
6542 /* We have to explicitly update the result LSB.
6544 emitcode("xch","a,%s", lsb);
6545 aopPut(AOP(result), "a", offr);
6546 emitcode("mov","a,%s", lsb);
6548 if (getDataSize (result) > 1)
6550 aopPut (AOP (result), "a", offr + MSB16);
6552 _endLazyDPSEvaluation();
6555 /*-----------------------------------------------------------------*/
6556 /* shiftL2Left2Result - shift left two bytes from left to result */
6557 /*-----------------------------------------------------------------*/
6559 shiftL2Left2Result (operand * left, int offl,
6560 operand * result, int offr, int shCount)
6564 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6566 AccAXLsh (lsb, shCount);
6568 _storeAxResults(lsb, result, offr);
6572 #ifdef BETTER_LITERAL_SHIFT
6573 /*-----------------------------------------------------------------*/
6574 /* shiftR2Left2Result - shift right two bytes from left to result */
6575 /*-----------------------------------------------------------------*/
6577 shiftR2Left2Result (operand * left, int offl,
6578 operand * result, int offr,
6579 int shCount, int sign)
6583 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6585 /* a:x >> shCount (x = lsb(result)) */
6588 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6592 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6595 _storeAxResults(lsb, result, offr);
6601 /*-----------------------------------------------------------------*/
6602 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6603 /*-----------------------------------------------------------------*/
6605 shiftLLeftOrResult (operand * left, int offl,
6606 operand * result, int offr, int shCount)
6608 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6609 /* shift left accumulator */
6611 /* or with result */
6612 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6613 /* back to result */
6614 aopPut (AOP (result), "a", offr);
6620 /*-----------------------------------------------------------------*/
6621 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6622 /*-----------------------------------------------------------------*/
6624 shiftRLeftOrResult (operand * left, int offl,
6625 operand * result, int offr, int shCount)
6627 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6628 /* shift right accumulator */
6630 /* or with result */
6631 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6632 /* back to result */
6633 aopPut (AOP (result), "a", offr);
6637 #ifdef BETTER_LITERAL_SHIFT
6638 /*-----------------------------------------------------------------*/
6639 /* genlshOne - left shift a one byte quantity by known count */
6640 /*-----------------------------------------------------------------*/
6642 genlshOne (operand * result, operand * left, int shCount)
6644 D (emitcode (";", "genlshOne "););
6645 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6649 #ifdef BETTER_LITERAL_SHIFT
6650 /*-----------------------------------------------------------------*/
6651 /* genlshTwo - left shift two bytes by known amount != 0 */
6652 /*-----------------------------------------------------------------*/
6654 genlshTwo (operand * result, operand * left, int shCount)
6658 D (emitcode (";", "genlshTwo "););
6660 size = getDataSize (result);
6662 /* if shCount >= 8 */
6667 _startLazyDPSEvaluation();
6673 _endLazyDPSEvaluation();
6674 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6675 aopPut (AOP (result), zero, LSB);
6679 movLeft2Result (left, LSB, result, MSB16, 0);
6680 aopPut (AOP (result), zero, LSB);
6681 _endLazyDPSEvaluation();
6686 aopPut (AOP (result), zero, LSB);
6687 _endLazyDPSEvaluation();
6691 /* 1 <= shCount <= 7 */
6696 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6700 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6708 /*-----------------------------------------------------------------*/
6709 /* shiftLLong - shift left one long from left to result */
6710 /* offl = LSB or MSB16 */
6711 /*-----------------------------------------------------------------*/
6713 shiftLLong (operand * left, operand * result, int offr)
6716 int size = AOP_SIZE (result);
6718 if (size >= LSB + offr)
6720 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6722 emitcode ("add", "a,acc");
6723 if (sameRegs (AOP (left), AOP (result)) &&
6724 size >= MSB16 + offr && offr != LSB)
6725 emitcode ("xch", "a,%s",
6726 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6728 aopPut (AOP (result), "a", LSB + offr);
6731 if (size >= MSB16 + offr)
6733 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6735 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6738 emitcode ("rlc", "a");
6739 if (sameRegs (AOP (left), AOP (result)) &&
6740 size >= MSB24 + offr && offr != LSB)
6741 emitcode ("xch", "a,%s",
6742 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6744 aopPut (AOP (result), "a", MSB16 + offr);
6747 if (size >= MSB24 + offr)
6749 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6751 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6754 emitcode ("rlc", "a");
6755 if (sameRegs (AOP (left), AOP (result)) &&
6756 size >= MSB32 + offr && offr != LSB)
6757 emitcode ("xch", "a,%s",
6758 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6760 aopPut (AOP (result), "a", MSB24 + offr);
6763 if (size > MSB32 + offr)
6765 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6767 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6770 emitcode ("rlc", "a");
6771 aopPut (AOP (result), "a", MSB32 + offr);
6774 aopPut (AOP (result), zero, LSB);
6780 /*-----------------------------------------------------------------*/
6781 /* genlshFour - shift four byte by a known amount != 0 */
6782 /*-----------------------------------------------------------------*/
6784 genlshFour (operand * result, operand * left, int shCount)
6788 D (emitcode (";", "genlshFour ");
6791 size = AOP_SIZE (result);
6793 /* if shifting more that 3 bytes */
6798 /* lowest order of left goes to the highest
6799 order of the destination */
6800 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6802 movLeft2Result (left, LSB, result, MSB32, 0);
6803 aopPut (AOP (result), zero, LSB);
6804 aopPut (AOP (result), zero, MSB16);
6805 aopPut (AOP (result), zero, MSB24);
6809 /* more than two bytes */
6810 else if (shCount >= 16)
6812 /* lower order two bytes goes to higher order two bytes */
6814 /* if some more remaining */
6816 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6819 movLeft2Result (left, MSB16, result, MSB32, 0);
6820 movLeft2Result (left, LSB, result, MSB24, 0);
6822 aopPut (AOP (result), zero, MSB16);
6823 aopPut (AOP (result), zero, LSB);
6827 /* if more than 1 byte */
6828 else if (shCount >= 8)
6830 /* lower order three bytes goes to higher order three bytes */
6835 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6837 movLeft2Result (left, LSB, result, MSB16, 0);
6843 movLeft2Result (left, MSB24, result, MSB32, 0);
6844 movLeft2Result (left, MSB16, result, MSB24, 0);
6845 movLeft2Result (left, LSB, result, MSB16, 0);
6846 aopPut (AOP (result), zero, LSB);
6848 else if (shCount == 1)
6849 shiftLLong (left, result, MSB16);
6852 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6853 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6854 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6855 aopPut (AOP (result), zero, LSB);
6860 /* 1 <= shCount <= 7 */
6861 else if (shCount <= 2)
6863 shiftLLong (left, result, LSB);
6865 shiftLLong (result, result, LSB);
6867 /* 3 <= shCount <= 7, optimize */
6870 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6871 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6872 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6877 #ifdef BETTER_LITERAL_SHIFT
6878 /*-----------------------------------------------------------------*/
6879 /* genLeftShiftLiteral - left shifting by known count */
6880 /*-----------------------------------------------------------------*/
6882 genLeftShiftLiteral (operand * left,
6887 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6890 size = getSize (operandType (result));
6892 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6894 /* We only handle certain easy cases so far. */
6896 && (shCount < (size * 8))
6900 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6904 freeAsmop (right, NULL, ic, TRUE);
6906 aopOp(left, ic, FALSE, FALSE);
6907 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6910 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6912 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6913 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6915 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6918 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6920 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6921 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6923 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6929 emitcode ("; shift left ", "result %d, left %d", size,
6933 /* I suppose that the left size >= result size */
6936 _startLazyDPSEvaluation();
6939 movLeft2Result (left, size, result, size, 0);
6941 _endLazyDPSEvaluation();
6943 else if (shCount >= (size * 8))
6945 _startLazyDPSEvaluation();
6948 aopPut (AOP (result), zero, size);
6950 _endLazyDPSEvaluation();
6957 genlshOne (result, left, shCount);
6961 genlshTwo (result, left, shCount);
6965 genlshFour (result, left, shCount);
6969 fprintf(stderr, "*** ack! mystery literal shift!\n");
6973 freeAsmop (left, NULL, ic, TRUE);
6974 freeAsmop (result, NULL, ic, TRUE);
6979 /*-----------------------------------------------------------------*/
6980 /* genLeftShift - generates code for left shifting */
6981 /*-----------------------------------------------------------------*/
6983 genLeftShift (iCode * ic)
6985 operand *left, *right, *result;
6988 symbol *tlbl, *tlbl1;
6990 D (emitcode (";", "genLeftShift "););
6992 right = IC_RIGHT (ic);
6993 left = IC_LEFT (ic);
6994 result = IC_RESULT (ic);
6996 aopOp (right, ic, FALSE, FALSE);
6999 #ifdef BETTER_LITERAL_SHIFT
7000 /* if the shift count is known then do it
7001 as efficiently as possible */
7002 if (AOP_TYPE (right) == AOP_LIT)
7004 if (genLeftShiftLiteral (left, right, result, ic))
7011 /* shift count is unknown then we have to form
7012 a loop get the loop count in B : Note: we take
7013 only the lower order byte since shifting
7014 more that 32 bits make no sense anyway, ( the
7015 largest size of an object can be only 32 bits ) */
7017 if (AOP_TYPE (right) == AOP_LIT)
7019 /* Really should be handled by genLeftShiftLiteral,
7020 * but since I'm too lazy to fix that today, at least we can make
7021 * some small improvement.
7023 emitcode("mov", "b,#0x%02x",
7024 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7028 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7029 emitcode ("inc", "b");
7031 freeAsmop (right, NULL, ic, TRUE);
7032 aopOp (left, ic, FALSE, FALSE);
7033 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7035 /* now move the left to the result if they are not the
7037 if (!sameRegs (AOP (left), AOP (result)) &&
7038 AOP_SIZE (result) > 1)
7041 size = AOP_SIZE (result);
7043 _startLazyDPSEvaluation ();
7046 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7047 if (*l == '@' && (IS_AOP_PREG (result)))
7050 emitcode ("mov", "a,%s", l);
7051 aopPut (AOP (result), "a", offset);
7054 aopPut (AOP (result), l, offset);
7057 _endLazyDPSEvaluation ();
7060 tlbl = newiTempLabel (NULL);
7061 size = AOP_SIZE (result);
7063 tlbl1 = newiTempLabel (NULL);
7065 /* if it is only one byte then */
7068 symbol *tlbl1 = newiTempLabel (NULL);
7070 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7072 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7073 emitcode ("", "%05d$:", tlbl->key + 100);
7074 emitcode ("add", "a,acc");
7075 emitcode ("", "%05d$:", tlbl1->key + 100);
7076 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7077 aopPut (AOP (result), "a", 0);
7081 reAdjustPreg (AOP (result));
7083 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7084 emitcode ("", "%05d$:", tlbl->key + 100);
7085 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7087 emitcode ("add", "a,acc");
7088 aopPut (AOP (result), "a", offset++);
7089 _startLazyDPSEvaluation ();
7092 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7094 emitcode ("rlc", "a");
7095 aopPut (AOP (result), "a", offset++);
7097 _endLazyDPSEvaluation ();
7098 reAdjustPreg (AOP (result));
7100 emitcode ("", "%05d$:", tlbl1->key + 100);
7101 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7103 freeAsmop (left, NULL, ic, TRUE);
7104 freeAsmop (result, NULL, ic, TRUE);
7107 #ifdef BETTER_LITERAL_SHIFT
7108 /*-----------------------------------------------------------------*/
7109 /* genrshOne - right shift a one byte quantity by known count */
7110 /*-----------------------------------------------------------------*/
7112 genrshOne (operand * result, operand * left,
7113 int shCount, int sign)
7115 D (emitcode (";", "genrshOne"););
7116 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7120 #ifdef BETTER_LITERAL_SHIFT
7121 /*-----------------------------------------------------------------*/
7122 /* genrshTwo - right shift two bytes by known amount != 0 */
7123 /*-----------------------------------------------------------------*/
7125 genrshTwo (operand * result, operand * left,
7126 int shCount, int sign)
7128 D (emitcode (";", "genrshTwo"););
7130 /* if shCount >= 8 */
7134 _startLazyDPSEvaluation();
7137 shiftR1Left2Result (left, MSB16, result, LSB,
7142 movLeft2Result (left, MSB16, result, LSB, sign);
7144 addSign (result, MSB16, sign);
7145 _endLazyDPSEvaluation();
7148 /* 1 <= shCount <= 7 */
7151 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7158 /*-----------------------------------------------------------------*/
7159 /* shiftRLong - shift right one long from left to result */
7160 /* offl = LSB or MSB16 */
7161 /*-----------------------------------------------------------------*/
7163 shiftRLong (operand * left, int offl,
7164 operand * result, int sign)
7167 emitcode ("clr", "c");
7168 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7170 emitcode ("mov", "c,acc.7");
7171 emitcode ("rrc", "a");
7172 aopPut (AOP (result), "a", MSB32 - offl);
7174 /* add sign of "a" */
7175 addSign (result, MSB32, sign);
7177 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7178 emitcode ("rrc", "a");
7179 aopPut (AOP (result), "a", MSB24 - offl);
7181 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7182 emitcode ("rrc", "a");
7183 aopPut (AOP (result), "a", MSB16 - offl);
7187 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7188 emitcode ("rrc", "a");
7189 aopPut (AOP (result), "a", LSB);
7196 /*-----------------------------------------------------------------*/
7197 /* genrshFour - shift four byte by a known amount != 0 */
7198 /*-----------------------------------------------------------------*/
7200 genrshFour (operand * result, operand * left,
7201 int shCount, int sign)
7203 D (emitcode (";", "genrshFour");
7206 /* if shifting more that 3 bytes */
7211 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7213 movLeft2Result (left, MSB32, result, LSB, sign);
7214 addSign (result, MSB16, sign);
7216 else if (shCount >= 16)
7220 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7223 movLeft2Result (left, MSB24, result, LSB, 0);
7224 movLeft2Result (left, MSB32, result, MSB16, sign);
7226 addSign (result, MSB24, sign);
7228 else if (shCount >= 8)
7232 shiftRLong (left, MSB16, result, sign);
7233 else if (shCount == 0)
7235 movLeft2Result (left, MSB16, result, LSB, 0);
7236 movLeft2Result (left, MSB24, result, MSB16, 0);
7237 movLeft2Result (left, MSB32, result, MSB24, sign);
7238 addSign (result, MSB32, sign);
7242 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7243 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7244 /* the last shift is signed */
7245 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7246 addSign (result, MSB32, sign);
7250 { /* 1 <= shCount <= 7 */
7253 shiftRLong (left, LSB, result, sign);
7255 shiftRLong (result, LSB, result, sign);
7259 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7260 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7261 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7267 #ifdef BETTER_LITERAL_SHIFT
7268 /*-----------------------------------------------------------------*/
7269 /* genRightShiftLiteral - right shifting by known count */
7270 /*-----------------------------------------------------------------*/
7272 genRightShiftLiteral (operand * left,
7278 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7281 size = getSize (operandType (result));
7283 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7285 /* We only handle certain easy cases so far. */
7287 && (shCount < (size * 8))
7291 D(emitcode (";", "genRightShiftLiteral wimping out"););
7295 freeAsmop (right, NULL, ic, TRUE);
7297 aopOp (left, ic, FALSE, FALSE);
7298 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7301 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7305 /* test the LEFT size !!! */
7307 /* I suppose that the left size >= result size */
7310 size = getDataSize (result);
7311 _startLazyDPSEvaluation();
7314 movLeft2Result (left, size, result, size, 0);
7316 _endLazyDPSEvaluation();
7318 else if (shCount >= (size * 8))
7322 /* get sign in acc.7 */
7323 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7325 addSign (result, LSB, sign);
7332 genrshOne (result, left, shCount, sign);
7336 genrshTwo (result, left, shCount, sign);
7340 genrshFour (result, left, shCount, sign);
7347 freeAsmop (left, NULL, ic, TRUE);
7348 freeAsmop (result, NULL, ic, TRUE);
7354 /*-----------------------------------------------------------------*/
7355 /* genSignedRightShift - right shift of signed number */
7356 /*-----------------------------------------------------------------*/
7358 genSignedRightShift (iCode * ic)
7360 operand *right, *left, *result;
7363 symbol *tlbl, *tlbl1;
7365 D (emitcode (";", "genSignedRightShift "););
7367 /* we do it the hard way put the shift count in b
7368 and loop thru preserving the sign */
7370 right = IC_RIGHT (ic);
7371 left = IC_LEFT (ic);
7372 result = IC_RESULT (ic);
7374 aopOp (right, ic, FALSE, FALSE);
7376 #ifdef BETTER_LITERAL_SHIFT
7377 if (AOP_TYPE (right) == AOP_LIT)
7379 if (genRightShiftLiteral (left, right, result, ic, 1))
7385 /* shift count is unknown then we have to form
7386 a loop get the loop count in B : Note: we take
7387 only the lower order byte since shifting
7388 more that 32 bits make no sense anyway, ( the
7389 largest size of an object can be only 32 bits ) */
7391 if (AOP_TYPE (right) == AOP_LIT)
7393 /* Really should be handled by genRightShiftLiteral,
7394 * but since I'm too lazy to fix that today, at least we can make
7395 * some small improvement.
7397 emitcode("mov", "b,#0x%02x",
7398 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7402 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7403 emitcode ("inc", "b");
7405 freeAsmop (right, NULL, ic, TRUE);
7406 aopOp (left, ic, FALSE, FALSE);
7407 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7409 /* now move the left to the result if they are not the
7411 if (!sameRegs (AOP (left), AOP (result)) &&
7412 AOP_SIZE (result) > 1)
7415 size = AOP_SIZE (result);
7417 _startLazyDPSEvaluation ();
7420 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7421 if (*l == '@' && IS_AOP_PREG (result))
7424 emitcode ("mov", "a,%s", l);
7425 aopPut (AOP (result), "a", offset);
7428 aopPut (AOP (result), l, offset);
7431 _endLazyDPSEvaluation ();
7434 /* mov the highest order bit to OVR */
7435 tlbl = newiTempLabel (NULL);
7436 tlbl1 = newiTempLabel (NULL);
7438 size = AOP_SIZE (result);
7440 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7441 emitcode ("rlc", "a");
7442 emitcode ("mov", "ov,c");
7443 /* if it is only one byte then */
7446 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7448 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7449 emitcode ("", "%05d$:", tlbl->key + 100);
7450 emitcode ("mov", "c,ov");
7451 emitcode ("rrc", "a");
7452 emitcode ("", "%05d$:", tlbl1->key + 100);
7453 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7454 aopPut (AOP (result), "a", 0);
7458 reAdjustPreg (AOP (result));
7459 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7460 emitcode ("", "%05d$:", tlbl->key + 100);
7461 emitcode ("mov", "c,ov");
7462 _startLazyDPSEvaluation ();
7465 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7467 emitcode ("rrc", "a");
7468 aopPut (AOP (result), "a", offset--);
7470 _endLazyDPSEvaluation ();
7471 reAdjustPreg (AOP (result));
7472 emitcode ("", "%05d$:", tlbl1->key + 100);
7473 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7476 freeAsmop (left, NULL, ic, TRUE);
7477 freeAsmop (result, NULL, ic, TRUE);
7480 /*-----------------------------------------------------------------*/
7481 /* genRightShift - generate code for right shifting */
7482 /*-----------------------------------------------------------------*/
7484 genRightShift (iCode * ic)
7486 operand *right, *left, *result;
7490 symbol *tlbl, *tlbl1;
7492 D (emitcode (";", "genRightShift "););
7494 /* if signed then we do it the hard way preserve the
7495 sign bit moving it inwards */
7496 retype = getSpec (operandType (IC_RESULT (ic)));
7498 if (!SPEC_USIGN (retype))
7500 genSignedRightShift (ic);
7504 /* signed & unsigned types are treated the same : i.e. the
7505 signed is NOT propagated inwards : quoting from the
7506 ANSI - standard : "for E1 >> E2, is equivalent to division
7507 by 2**E2 if unsigned or if it has a non-negative value,
7508 otherwise the result is implementation defined ", MY definition
7509 is that the sign does not get propagated */
7511 right = IC_RIGHT (ic);
7512 left = IC_LEFT (ic);
7513 result = IC_RESULT (ic);
7515 aopOp (right, ic, FALSE, FALSE);
7517 #ifdef BETTER_LITERAL_SHIFT
7518 /* if the shift count is known then do it
7519 as efficiently as possible */
7520 if (AOP_TYPE (right) == AOP_LIT)
7522 if (genRightShiftLiteral (left, right, result, ic, 0))
7529 /* shift count is unknown then we have to form
7530 a loop get the loop count in B : Note: we take
7531 only the lower order byte since shifting
7532 more that 32 bits make no sense anyway, ( the
7533 largest size of an object can be only 32 bits ) */
7535 if (AOP_TYPE (right) == AOP_LIT)
7537 /* Really should be handled by genRightShiftLiteral,
7538 * but since I'm too lazy to fix that today, at least we can make
7539 * some small improvement.
7541 emitcode("mov", "b,#0x%02x",
7542 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7546 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7547 emitcode ("inc", "b");
7549 freeAsmop (right, NULL, ic, TRUE);
7550 aopOp (left, ic, FALSE, FALSE);
7551 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7553 /* now move the left to the result if they are not the
7555 if (!sameRegs (AOP (left), AOP (result)) &&
7556 AOP_SIZE (result) > 1)
7559 size = AOP_SIZE (result);
7561 _startLazyDPSEvaluation ();
7564 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7565 if (*l == '@' && IS_AOP_PREG (result))
7568 emitcode ("mov", "a,%s", l);
7569 aopPut (AOP (result), "a", offset);
7572 aopPut (AOP (result), l, offset);
7575 _endLazyDPSEvaluation ();
7578 tlbl = newiTempLabel (NULL);
7579 tlbl1 = newiTempLabel (NULL);
7580 size = AOP_SIZE (result);
7583 /* if it is only one byte then */
7586 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7588 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7589 emitcode ("", "%05d$:", tlbl->key + 100);
7591 emitcode ("rrc", "a");
7592 emitcode ("", "%05d$:", tlbl1->key + 100);
7593 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7594 aopPut (AOP (result), "a", 0);
7598 reAdjustPreg (AOP (result));
7599 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7600 emitcode ("", "%05d$:", tlbl->key + 100);
7602 _startLazyDPSEvaluation ();
7605 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7607 emitcode ("rrc", "a");
7608 aopPut (AOP (result), "a", offset--);
7610 _endLazyDPSEvaluation ();
7611 reAdjustPreg (AOP (result));
7613 emitcode ("", "%05d$:", tlbl1->key + 100);
7614 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7617 freeAsmop (left, NULL, ic, TRUE);
7618 freeAsmop (result, NULL, ic, TRUE);
7621 /*-----------------------------------------------------------------*/
7622 /* genUnpackBits - generates code for unpacking bits */
7623 /*-----------------------------------------------------------------*/
7625 genUnpackBits (operand * result, char *rname, int ptype)
7632 D (emitcode (";", "genUnpackBits ");
7635 etype = getSpec (operandType (result));
7637 /* read the first byte */
7643 emitcode ("mov", "a,@%s", rname);
7647 emitcode ("movx", "a,@%s", rname);
7651 emitcode ("movx", "a,@dptr");
7655 emitcode ("clr", "a");
7656 emitcode ("movc", "a", "@a+dptr");
7660 emitcode ("lcall", "__gptrget");
7664 /* if we have bitdisplacement then it fits */
7665 /* into this byte completely or if length is */
7666 /* less than a byte */
7667 if ((shCnt = SPEC_BSTR (etype)) ||
7668 (SPEC_BLEN (etype) <= 8))
7671 /* shift right acc */
7674 emitcode ("anl", "a,#0x%02x",
7675 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7676 aopPut (AOP (result), "a", offset);
7680 /* bit field did not fit in a byte */
7681 rlen = SPEC_BLEN (etype) - 8;
7682 aopPut (AOP (result), "a", offset++);
7691 emitcode ("inc", "%s", rname);
7692 emitcode ("mov", "a,@%s", rname);
7696 emitcode ("inc", "%s", rname);
7697 emitcode ("movx", "a,@%s", rname);
7701 emitcode ("inc", "dptr");
7702 emitcode ("movx", "a,@dptr");
7706 emitcode ("clr", "a");
7707 emitcode ("inc", "dptr");
7708 emitcode ("movc", "a", "@a+dptr");
7712 emitcode ("inc", "dptr");
7713 emitcode ("lcall", "__gptrget");
7718 /* if we are done */
7722 aopPut (AOP (result), "a", offset++);
7728 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7729 aopPut (AOP (result), "a", offset);
7736 /*-----------------------------------------------------------------*/
7737 /* genDataPointerGet - generates code when ptr offset is known */
7738 /*-----------------------------------------------------------------*/
7740 genDataPointerGet (operand * left,
7746 int size, offset = 0;
7747 aopOp (result, ic, TRUE, FALSE);
7749 /* get the string representation of the name */
7750 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7751 size = AOP_SIZE (result);
7752 _startLazyDPSEvaluation ();
7756 sprintf (buffer, "(%s + %d)", l + 1, offset);
7758 sprintf (buffer, "%s", l + 1);
7759 aopPut (AOP (result), buffer, offset++);
7761 _endLazyDPSEvaluation ();
7763 freeAsmop (left, NULL, ic, TRUE);
7764 freeAsmop (result, NULL, ic, TRUE);
7767 /*-----------------------------------------------------------------*/
7768 /* genNearPointerGet - emitcode for near pointer fetch */
7769 /*-----------------------------------------------------------------*/
7771 genNearPointerGet (operand * left,
7778 sym_link *rtype, *retype, *letype;
7779 sym_link *ltype = operandType (left);
7782 rtype = operandType (result);
7783 retype = getSpec (rtype);
7784 letype = getSpec (ltype);
7786 aopOp (left, ic, FALSE, FALSE);
7788 /* if left is rematerialisable and
7789 result is not bit variable type and
7790 the left is pointer to data space i.e
7791 lower 128 bytes of space */
7792 if (AOP_TYPE (left) == AOP_IMMD &&
7793 !IS_BITVAR (retype) &&
7794 !IS_BITVAR (letype) &&
7795 DCL_TYPE (ltype) == POINTER)
7797 genDataPointerGet (left, result, ic);
7801 /* if the value is already in a pointer register
7802 then don't need anything more */
7803 if (!AOP_INPREG (AOP (left)))
7805 /* otherwise get a free pointer register */
7807 preg = getFreePtr (ic, &aop, FALSE);
7808 emitcode ("mov", "%s,%s",
7810 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7814 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7816 freeAsmop (left, NULL, ic, TRUE);
7817 aopOp (result, ic, FALSE, FALSE);
7819 /* if bitfield then unpack the bits */
7820 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7821 genUnpackBits (result, rname, POINTER);
7824 /* we have can just get the values */
7825 int size = AOP_SIZE (result);
7830 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7833 emitcode ("mov", "a,@%s", rname);
7834 aopPut (AOP (result), "a", offset);
7838 sprintf (buffer, "@%s", rname);
7839 aopPut (AOP (result), buffer, offset);
7843 emitcode ("inc", "%s", rname);
7847 /* now some housekeeping stuff */
7850 /* we had to allocate for this iCode */
7851 freeAsmop (NULL, aop, ic, TRUE);
7855 /* we did not allocate which means left
7856 already in a pointer register, then
7857 if size > 0 && this could be used again
7858 we have to point it back to where it
7860 if (AOP_SIZE (result) > 1 &&
7861 !OP_SYMBOL (left)->remat &&
7862 (OP_SYMBOL (left)->liveTo > ic->seq ||
7865 int size = AOP_SIZE (result) - 1;
7867 emitcode ("dec", "%s", rname);
7872 freeAsmop (result, NULL, ic, TRUE);
7876 /*-----------------------------------------------------------------*/
7877 /* genPagedPointerGet - emitcode for paged pointer fetch */
7878 /*-----------------------------------------------------------------*/
7880 genPagedPointerGet (operand * left,
7887 sym_link *rtype, *retype, *letype;
7889 rtype = operandType (result);
7890 retype = getSpec (rtype);
7891 letype = getSpec (operandType (left));
7892 aopOp (left, ic, FALSE, FALSE);
7894 /* if the value is already in a pointer register
7895 then don't need anything more */
7896 if (!AOP_INPREG (AOP (left)))
7898 /* otherwise get a free pointer register */
7900 preg = getFreePtr (ic, &aop, FALSE);
7901 emitcode ("mov", "%s,%s",
7903 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7907 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7909 freeAsmop (left, NULL, ic, TRUE);
7910 aopOp (result, ic, FALSE, FALSE);
7912 /* if bitfield then unpack the bits */
7913 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7914 genUnpackBits (result, rname, PPOINTER);
7917 /* we have can just get the values */
7918 int size = AOP_SIZE (result);
7924 emitcode ("movx", "a,@%s", rname);
7925 aopPut (AOP (result), "a", offset);
7930 emitcode ("inc", "%s", rname);
7934 /* now some housekeeping stuff */
7937 /* we had to allocate for this iCode */
7938 freeAsmop (NULL, aop, ic, TRUE);
7942 /* we did not allocate which means left
7943 already in a pointer register, then
7944 if size > 0 && this could be used again
7945 we have to point it back to where it
7947 if (AOP_SIZE (result) > 1 &&
7948 !OP_SYMBOL (left)->remat &&
7949 (OP_SYMBOL (left)->liveTo > ic->seq ||
7952 int size = AOP_SIZE (result) - 1;
7954 emitcode ("dec", "%s", rname);
7959 freeAsmop (result, NULL, ic, TRUE);
7964 /*-----------------------------------------------------------------*/
7965 /* genFarPointerGet - gget value from far space */
7966 /*-----------------------------------------------------------------*/
7968 genFarPointerGet (operand * left,
7969 operand * result, iCode * ic)
7972 sym_link *retype = getSpec (operandType (result));
7973 sym_link *letype = getSpec (operandType (left));
7974 D (emitcode (";", "genFarPointerGet");
7977 aopOp (left, ic, FALSE, FALSE);
7979 /* if the operand is already in dptr
7980 then we do nothing else we move the value to dptr */
7981 if (AOP_TYPE (left) != AOP_STR)
7983 /* if this is remateriazable */
7984 if (AOP_TYPE (left) == AOP_IMMD)
7986 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7990 /* we need to get it byte by byte */
7991 _startLazyDPSEvaluation ();
7992 if (AOP_TYPE (left) != AOP_DPTR)
7994 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7995 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7996 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8000 /* We need to generate a load to DPTR indirect through DPTR. */
8001 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8003 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8004 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8005 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8006 emitcode ("pop", "dph");
8007 emitcode ("pop", "dpl");
8009 _endLazyDPSEvaluation ();
8012 /* so dptr know contains the address */
8013 freeAsmop (left, NULL, ic, TRUE);
8014 aopOp (result, ic, FALSE, TRUE);
8016 /* if bit then unpack */
8017 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8018 genUnpackBits (result, "dptr", FPOINTER);
8021 size = AOP_SIZE (result);
8024 _startLazyDPSEvaluation ();
8031 emitcode ("movx", "a,@dptr");
8033 emitcode ("inc", "dptr");
8035 aopPut (AOP (result), "a", offset++);
8037 _endLazyDPSEvaluation ();
8040 freeAsmop (result, NULL, ic, TRUE);
8043 /*-----------------------------------------------------------------*/
8044 /* emitcodePointerGet - gget value from code space */
8045 /*-----------------------------------------------------------------*/
8047 emitcodePointerGet (operand * left,
8048 operand * result, iCode * ic)
8051 sym_link *retype = getSpec (operandType (result));
8053 aopOp (left, ic, FALSE, FALSE);
8055 /* if the operand is already in dptr
8056 then we do nothing else we move the value to dptr */
8057 if (AOP_TYPE (left) != AOP_STR)
8059 /* if this is remateriazable */
8060 if (AOP_TYPE (left) == AOP_IMMD)
8062 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8065 { /* we need to get it byte by byte */
8066 _startLazyDPSEvaluation ();
8067 if (AOP_TYPE (left) != AOP_DPTR)
8069 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8070 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8071 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8075 /* We need to generate a load to DPTR indirect through DPTR. */
8076 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8078 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8079 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8080 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8081 emitcode ("pop", "dph");
8082 emitcode ("pop", "dpl");
8084 _endLazyDPSEvaluation ();
8087 /* so dptr know contains the address */
8088 freeAsmop (left, NULL, ic, TRUE);
8089 aopOp (result, ic, FALSE, TRUE);
8091 /* if bit then unpack */
8092 if (IS_BITVAR (retype))
8093 genUnpackBits (result, "dptr", CPOINTER);
8096 size = AOP_SIZE (result);
8099 _startLazyDPSEvaluation ();
8105 emitcode ("clr", "a");
8106 emitcode ("movc", "a,@a+dptr");
8108 emitcode ("inc", "dptr");
8109 aopPut (AOP (result), "a", offset++);
8111 _endLazyDPSEvaluation ();
8114 freeAsmop (result, NULL, ic, TRUE);
8117 /*-----------------------------------------------------------------*/
8118 /* genGenPointerGet - gget value from generic pointer space */
8119 /*-----------------------------------------------------------------*/
8121 genGenPointerGet (operand * left,
8122 operand * result, iCode * ic)
8125 sym_link *retype = getSpec (operandType (result));
8126 sym_link *letype = getSpec (operandType (left));
8128 D (emitcode (";", "genGenPointerGet "); );
8130 aopOp (left, ic, FALSE, TRUE);
8132 /* if the operand is already in dptr
8133 then we do nothing else we move the value to dptr */
8134 if (AOP_TYPE (left) != AOP_STR)
8136 /* if this is remateriazable */
8137 if (AOP_TYPE (left) == AOP_IMMD)
8139 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8140 emitcode ("mov", "b,#%d", pointerCode (retype));
8143 { /* we need to get it byte by byte */
8144 _startLazyDPSEvaluation ();
8145 if (AOP(left)->type==AOP_DPTR2) {
8147 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8150 emitcode ("mov", "dpl,%s", l);
8151 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8154 emitcode ("mov", "dph,%s", l);
8155 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8158 emitcode ("mov", "dpx,%s", l);
8159 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8161 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8162 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8163 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8164 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8166 _endLazyDPSEvaluation ();
8169 /* so dptr know contains the address */
8170 freeAsmop (left, NULL, ic, TRUE);
8171 aopOp (result, ic, FALSE, TRUE);
8173 /* if bit then unpack */
8174 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8175 genUnpackBits (result, "dptr", GPOINTER);
8178 size = AOP_SIZE (result);
8183 emitcode ("lcall", "__gptrget");
8184 aopPut (AOP (result), "a", offset++);
8186 emitcode ("inc", "dptr");
8190 freeAsmop (result, NULL, ic, TRUE);
8193 /*-----------------------------------------------------------------*/
8194 /* genPointerGet - generate code for pointer get */
8195 /*-----------------------------------------------------------------*/
8197 genPointerGet (iCode * ic)
8199 operand *left, *result;
8200 sym_link *type, *etype;
8203 D (emitcode (";", "genPointerGet ");
8206 left = IC_LEFT (ic);
8207 result = IC_RESULT (ic);
8209 /* depending on the type of pointer we need to
8210 move it to the correct pointer register */
8211 type = operandType (left);
8212 etype = getSpec (type);
8213 /* if left is of type of pointer then it is simple */
8214 if (IS_PTR (type) && !IS_FUNC (type->next))
8215 p_type = DCL_TYPE (type);
8218 /* we have to go by the storage class */
8219 p_type = PTR_TYPE (SPEC_OCLS (etype));
8222 /* now that we have the pointer type we assign
8223 the pointer values */
8229 genNearPointerGet (left, result, ic);
8233 genPagedPointerGet (left, result, ic);
8237 genFarPointerGet (left, result, ic);
8241 emitcodePointerGet (left, result, ic);
8245 genGenPointerGet (left, result, ic);
8251 /*-----------------------------------------------------------------*/
8252 /* genPackBits - generates code for packed bit storage */
8253 /*-----------------------------------------------------------------*/
8255 genPackBits (sym_link * etype,
8257 char *rname, int p_type)
8265 blen = SPEC_BLEN (etype);
8266 bstr = SPEC_BSTR (etype);
8268 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8271 /* if the bit lenth is less than or */
8272 /* it exactly fits a byte then */
8273 if (SPEC_BLEN (etype) <= 8)
8275 shCount = SPEC_BSTR (etype);
8277 /* shift left acc */
8280 if (SPEC_BLEN (etype) < 8)
8281 { /* if smaller than a byte */
8287 emitcode ("mov", "b,a");
8288 emitcode ("mov", "a,@%s", rname);
8292 emitcode ("mov", "b,a");
8293 emitcode ("movx", "a,@dptr");
8297 emitcode ("push", "b");
8298 emitcode ("push", "acc");
8299 emitcode ("lcall", "__gptrget");
8300 emitcode ("pop", "b");
8304 emitcode ("anl", "a,#0x%02x", (unsigned char)
8305 ((unsigned char) (0xFF << (blen + bstr)) |
8306 (unsigned char) (0xFF >> (8 - bstr))));
8307 emitcode ("orl", "a,b");
8308 if (p_type == GPOINTER)
8309 emitcode ("pop", "b");
8316 emitcode ("mov", "@%s,a", rname);
8320 emitcode ("movx", "@dptr,a");
8324 emitcode ("lcall", "__gptrput");
8329 if (SPEC_BLEN (etype) <= 8)
8332 emitcode ("inc", "%s", rname);
8333 rLen = SPEC_BLEN (etype);
8335 /* now generate for lengths greater than one byte */
8339 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8351 emitcode ("mov", "@%s,a", rname);
8354 emitcode ("mov", "@%s,%s", rname, l);
8359 emitcode ("movx", "@dptr,a");
8364 emitcode ("lcall", "__gptrput");
8367 emitcode ("inc", "%s", rname);
8372 /* last last was not complete */
8375 /* save the byte & read byte */
8379 emitcode ("mov", "b,a");
8380 emitcode ("mov", "a,@%s", rname);
8384 emitcode ("mov", "b,a");
8385 emitcode ("movx", "a,@dptr");
8389 emitcode ("push", "b");
8390 emitcode ("push", "acc");
8391 emitcode ("lcall", "__gptrget");
8392 emitcode ("pop", "b");
8396 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8397 emitcode ("orl", "a,b");
8400 if (p_type == GPOINTER)
8401 emitcode ("pop", "b");
8407 emitcode ("mov", "@%s,a", rname);
8411 emitcode ("movx", "@dptr,a");
8415 emitcode ("lcall", "__gptrput");
8419 /*-----------------------------------------------------------------*/
8420 /* genDataPointerSet - remat pointer to data space */
8421 /*-----------------------------------------------------------------*/
8423 genDataPointerSet (operand * right,
8427 int size, offset = 0;
8428 char *l, buffer[256];
8430 aopOp (right, ic, FALSE, FALSE);
8432 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8433 size = AOP_SIZE (right);
8437 sprintf (buffer, "(%s + %d)", l + 1, offset);
8439 sprintf (buffer, "%s", l + 1);
8440 emitcode ("mov", "%s,%s", buffer,
8441 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8444 freeAsmop (right, NULL, ic, TRUE);
8445 freeAsmop (result, NULL, ic, TRUE);
8448 /*-----------------------------------------------------------------*/
8449 /* genNearPointerSet - emitcode for near pointer put */
8450 /*-----------------------------------------------------------------*/
8452 genNearPointerSet (operand * right,
8459 sym_link *retype, *letype;
8460 sym_link *ptype = operandType (result);
8462 retype = getSpec (operandType (right));
8463 letype = getSpec (ptype);
8465 aopOp (result, ic, FALSE, FALSE);
8467 /* if the result is rematerializable &
8468 in data space & not a bit variable */
8469 if (AOP_TYPE (result) == AOP_IMMD &&
8470 DCL_TYPE (ptype) == POINTER &&
8471 !IS_BITVAR (retype) &&
8472 !IS_BITVAR (letype))
8474 genDataPointerSet (right, result, ic);
8478 /* if the value is already in a pointer register
8479 then don't need anything more */
8480 if (!AOP_INPREG (AOP (result)))
8482 /* otherwise get a free pointer register */
8484 preg = getFreePtr (ic, &aop, FALSE);
8485 emitcode ("mov", "%s,%s",
8487 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8491 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8493 freeAsmop (result, NULL, ic, TRUE);
8494 aopOp (right, ic, FALSE, FALSE);
8496 /* if bitfield then unpack the bits */
8497 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8498 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8501 /* we have can just get the values */
8502 int size = AOP_SIZE (right);
8507 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8511 emitcode ("mov", "@%s,a", rname);
8514 emitcode ("mov", "@%s,%s", rname, l);
8516 emitcode ("inc", "%s", rname);
8521 /* now some housekeeping stuff */
8524 /* we had to allocate for this iCode */
8525 freeAsmop (NULL, aop, ic, TRUE);
8529 /* we did not allocate which means left
8530 already in a pointer register, then
8531 if size > 0 && this could be used again
8532 we have to point it back to where it
8534 if (AOP_SIZE (right) > 1 &&
8535 !OP_SYMBOL (result)->remat &&
8536 (OP_SYMBOL (result)->liveTo > ic->seq ||
8539 int size = AOP_SIZE (right) - 1;
8541 emitcode ("dec", "%s", rname);
8546 freeAsmop (right, NULL, ic, TRUE);
8551 /*-----------------------------------------------------------------*/
8552 /* genPagedPointerSet - emitcode for Paged pointer put */
8553 /*-----------------------------------------------------------------*/
8555 genPagedPointerSet (operand * right,
8562 sym_link *retype, *letype;
8564 retype = getSpec (operandType (right));
8565 letype = getSpec (operandType (result));
8567 aopOp (result, ic, FALSE, FALSE);
8569 /* if the value is already in a pointer register
8570 then don't need anything more */
8571 if (!AOP_INPREG (AOP (result)))
8573 /* otherwise get a free pointer register */
8575 preg = getFreePtr (ic, &aop, FALSE);
8576 emitcode ("mov", "%s,%s",
8578 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8582 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8584 freeAsmop (result, NULL, ic, TRUE);
8585 aopOp (right, ic, FALSE, FALSE);
8587 /* if bitfield then unpack the bits */
8588 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8589 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8592 /* we have can just get the values */
8593 int size = AOP_SIZE (right);
8598 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8601 emitcode ("movx", "@%s,a", rname);
8604 emitcode ("inc", "%s", rname);
8610 /* now some housekeeping stuff */
8613 /* we had to allocate for this iCode */
8614 freeAsmop (NULL, aop, ic, TRUE);
8618 /* we did not allocate which means left
8619 already in a pointer register, then
8620 if size > 0 && this could be used again
8621 we have to point it back to where it
8623 if (AOP_SIZE (right) > 1 &&
8624 !OP_SYMBOL (result)->remat &&
8625 (OP_SYMBOL (result)->liveTo > ic->seq ||
8628 int size = AOP_SIZE (right) - 1;
8630 emitcode ("dec", "%s", rname);
8635 freeAsmop (right, NULL, ic, TRUE);
8640 /*-----------------------------------------------------------------*/
8641 /* genFarPointerSet - set value from far space */
8642 /*-----------------------------------------------------------------*/
8644 genFarPointerSet (operand * right,
8645 operand * result, iCode * ic)
8648 sym_link *retype = getSpec (operandType (right));
8649 sym_link *letype = getSpec (operandType (result));
8651 aopOp (result, ic, FALSE, FALSE);
8653 /* if the operand is already in dptr
8654 then we do nothing else we move the value to dptr */
8655 if (AOP_TYPE (result) != AOP_STR)
8657 /* if this is remateriazable */
8658 if (AOP_TYPE (result) == AOP_IMMD)
8659 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8662 /* we need to get it byte by byte */
8663 _startLazyDPSEvaluation ();
8664 if (AOP_TYPE (result) != AOP_DPTR)
8666 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8667 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8668 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8672 /* We need to generate a load to DPTR indirect through DPTR. */
8673 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8675 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8676 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8677 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8678 emitcode ("pop", "dph");
8679 emitcode ("pop", "dpl");
8681 _endLazyDPSEvaluation ();
8684 /* so dptr know contains the address */
8685 freeAsmop (result, NULL, ic, TRUE);
8686 aopOp (right, ic, FALSE, TRUE);
8688 /* if bit then unpack */
8689 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8690 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8693 size = AOP_SIZE (right);
8696 _startLazyDPSEvaluation ();
8699 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8705 emitcode ("movx", "@dptr,a");
8707 emitcode ("inc", "dptr");
8709 _endLazyDPSEvaluation ();
8712 freeAsmop (right, NULL, ic, TRUE);
8715 /*-----------------------------------------------------------------*/
8716 /* genGenPointerSet - set value from generic pointer space */
8717 /*-----------------------------------------------------------------*/
8719 genGenPointerSet (operand * right,
8720 operand * result, iCode * ic)
8723 sym_link *retype = getSpec (operandType (right));
8724 sym_link *letype = getSpec (operandType (result));
8726 aopOp (result, ic, FALSE, TRUE);
8728 /* if the operand is already in dptr
8729 then we do nothing else we move the value to dptr */
8730 if (AOP_TYPE (result) != AOP_STR)
8732 _startLazyDPSEvaluation ();
8733 /* if this is remateriazable */
8734 if (AOP_TYPE (result) == AOP_IMMD)
8736 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8737 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8740 { /* we need to get it byte by byte */
8741 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8742 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8743 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8744 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8746 _endLazyDPSEvaluation ();
8748 /* so dptr know contains the address */
8749 freeAsmop (result, NULL, ic, TRUE);
8750 aopOp (right, ic, FALSE, TRUE);
8752 /* if bit then unpack */
8753 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8754 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8757 size = AOP_SIZE (right);
8760 _startLazyDPSEvaluation ();
8763 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8769 emitcode ("lcall", "__gptrput");
8771 emitcode ("inc", "dptr");
8773 _endLazyDPSEvaluation ();
8776 freeAsmop (right, NULL, ic, TRUE);
8779 /*-----------------------------------------------------------------*/
8780 /* genPointerSet - stores the value into a pointer location */
8781 /*-----------------------------------------------------------------*/
8783 genPointerSet (iCode * ic)
8785 operand *right, *result;
8786 sym_link *type, *etype;
8789 D (emitcode (";", "genPointerSet ");
8792 right = IC_RIGHT (ic);
8793 result = IC_RESULT (ic);
8795 /* depending on the type of pointer we need to
8796 move it to the correct pointer register */
8797 type = operandType (result);
8798 etype = getSpec (type);
8799 /* if left is of type of pointer then it is simple */
8800 if (IS_PTR (type) && !IS_FUNC (type->next))
8802 p_type = DCL_TYPE (type);
8806 /* we have to go by the storage class */
8807 p_type = PTR_TYPE (SPEC_OCLS (etype));
8810 /* now that we have the pointer type we assign
8811 the pointer values */
8817 genNearPointerSet (right, result, ic);
8821 genPagedPointerSet (right, result, ic);
8825 genFarPointerSet (right, result, ic);
8829 genGenPointerSet (right, result, ic);
8835 /*-----------------------------------------------------------------*/
8836 /* genIfx - generate code for Ifx statement */
8837 /*-----------------------------------------------------------------*/
8839 genIfx (iCode * ic, iCode * popIc)
8841 operand *cond = IC_COND (ic);
8844 D (emitcode (";", "genIfx "););
8846 aopOp (cond, ic, FALSE, FALSE);
8848 /* get the value into acc */
8849 if (AOP_TYPE (cond) != AOP_CRY)
8853 /* the result is now in the accumulator */
8854 freeAsmop (cond, NULL, ic, TRUE);
8856 /* if there was something to be popped then do it */
8860 /* if the condition is a bit variable */
8861 if (isbit && IS_ITEMP (cond) &&
8863 genIfxJump (ic, SPIL_LOC (cond)->rname);
8864 else if (isbit && !IS_ITEMP (cond))
8865 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8867 genIfxJump (ic, "a");
8872 /*-----------------------------------------------------------------*/
8873 /* genAddrOf - generates code for address of */
8874 /*-----------------------------------------------------------------*/
8876 genAddrOf (iCode * ic)
8878 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8881 D (emitcode (";", "genAddrOf ");
8884 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8886 /* if the operand is on the stack then we
8887 need to get the stack offset of this
8891 /* if it has an offset then we need to compute
8895 emitcode ("mov", "a,_bp");
8896 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8897 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8901 /* we can just move _bp */
8902 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8904 /* fill the result with zero */
8905 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8908 if (options.stack10bit && size < (FPTRSIZE - 1))
8911 "*** warning: pointer to stack var truncated.\n");
8918 if (options.stack10bit && offset == 2)
8920 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8924 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8931 /* object not on stack then we need the name */
8932 size = AOP_SIZE (IC_RESULT (ic));
8937 char s[SDCC_NAME_MAX];
8939 sprintf (s, "#(%s >> %d)",
8943 sprintf (s, "#%s", sym->rname);
8944 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8948 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8952 /*-----------------------------------------------------------------*/
8953 /* genFarFarAssign - assignment when both are in far space */
8954 /*-----------------------------------------------------------------*/
8956 genFarFarAssign (operand * result, operand * right, iCode * ic)
8958 int size = AOP_SIZE (right);
8960 symbol *rSym = NULL;
8964 /* quick & easy case. */
8965 D(emitcode(";","genFarFarAssign (1 byte case)"););
8966 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
8967 freeAsmop (right, NULL, ic, FALSE);
8968 /* now assign DPTR to result */
8970 aopOp(result, ic, FALSE, FALSE);
8972 aopPut(AOP(result), "a", 0);
8973 freeAsmop(result, NULL, ic, FALSE);
8977 /* See if we've got an underlying symbol to abuse. */
8978 if (IS_SYMOP(result) && OP_SYMBOL(result))
8980 if (IS_TRUE_SYMOP(result))
8982 rSym = OP_SYMBOL(result);
8984 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
8986 rSym = OP_SYMBOL(result)->usl.spillLoc;
8990 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
8992 /* We can use the '390 auto-toggle feature to good effect here. */
8994 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
8995 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
8996 emitcode ("mov", "dptr,#%s", rSym->rname);
8997 /* DP2 = result, DP1 = right, DP1 is current. */
9000 emitcode("movx", "a,@dptr");
9001 emitcode("movx", "@dptr,a");
9004 emitcode("inc", "dptr");
9005 emitcode("inc", "dptr");
9008 emitcode("mov", "dps, #0");
9009 freeAsmop (right, NULL, ic, FALSE);
9013 D (emitcode (";", "genFarFarAssign"););
9014 aopOp (result, ic, TRUE, TRUE);
9016 _startLazyDPSEvaluation ();
9020 aopPut (AOP (result),
9021 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9024 _endLazyDPSEvaluation ();
9025 freeAsmop (result, NULL, ic, FALSE);
9026 freeAsmop (right, NULL, ic, FALSE);
9030 /*-----------------------------------------------------------------*/
9031 /* genAssign - generate code for assignment */
9032 /*-----------------------------------------------------------------*/
9034 genAssign (iCode * ic)
9036 operand *result, *right;
9038 unsigned long lit = 0L;
9040 D (emitcode (";", "genAssign ");
9043 result = IC_RESULT (ic);
9044 right = IC_RIGHT (ic);
9046 /* if they are the same */
9047 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9050 aopOp (right, ic, FALSE, FALSE);
9052 emitcode (";", "genAssign: resultIsFar = %s",
9053 isOperandInFarSpace (result) ?
9056 /* special case both in far space */
9057 if ((AOP_TYPE (right) == AOP_DPTR ||
9058 AOP_TYPE (right) == AOP_DPTR2) &&
9059 /* IS_TRUE_SYMOP(result) && */
9060 isOperandInFarSpace (result))
9062 genFarFarAssign (result, right, ic);
9066 aopOp (result, ic, TRUE, FALSE);
9068 /* if they are the same registers */
9069 if (sameRegs (AOP (right), AOP (result)))
9072 /* if the result is a bit */
9073 if (AOP_TYPE (result) == AOP_CRY)
9076 /* if the right size is a literal then
9077 we know what the value is */
9078 if (AOP_TYPE (right) == AOP_LIT)
9080 if (((int) operandLitValue (right)))
9081 aopPut (AOP (result), one, 0);
9083 aopPut (AOP (result), zero, 0);
9087 /* the right is also a bit variable */
9088 if (AOP_TYPE (right) == AOP_CRY)
9090 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9091 aopPut (AOP (result), "c", 0);
9097 aopPut (AOP (result), "a", 0);
9101 /* bit variables done */
9103 size = AOP_SIZE (result);
9105 if (AOP_TYPE (right) == AOP_LIT)
9106 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9109 (AOP_TYPE (result) != AOP_REG) &&
9110 (AOP_TYPE (right) == AOP_LIT) &&
9111 !IS_FLOAT (operandType (right)))
9113 _startLazyDPSEvaluation ();
9114 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9116 aopPut (AOP (result),
9117 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9122 /* And now fill the rest with zeros. */
9125 emitcode ("clr", "a");
9129 aopPut (AOP (result), "a", offset++);
9131 _endLazyDPSEvaluation ();
9135 _startLazyDPSEvaluation ();
9138 aopPut (AOP (result),
9139 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9143 _endLazyDPSEvaluation ();
9147 freeAsmop (right, NULL, ic, FALSE);
9148 freeAsmop (result, NULL, ic, TRUE);
9151 /*-----------------------------------------------------------------*/
9152 /* genJumpTab - generates code for jump table */
9153 /*-----------------------------------------------------------------*/
9155 genJumpTab (iCode * ic)
9160 D (emitcode (";", "genJumpTab ");
9163 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9164 /* get the condition into accumulator */
9165 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9167 /* multiply by four! */
9168 emitcode ("add", "a,acc");
9169 emitcode ("add", "a,acc");
9170 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9172 jtab = newiTempLabel (NULL);
9173 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9174 emitcode ("jmp", "@a+dptr");
9175 emitcode ("", "%05d$:", jtab->key + 100);
9176 /* now generate the jump labels */
9177 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9178 jtab = setNextItem (IC_JTLABELS (ic)))
9179 emitcode ("ljmp", "%05d$", jtab->key + 100);
9183 /*-----------------------------------------------------------------*/
9184 /* genCast - gen code for casting */
9185 /*-----------------------------------------------------------------*/
9187 genCast (iCode * ic)
9189 operand *result = IC_RESULT (ic);
9190 sym_link *ctype = operandType (IC_LEFT (ic));
9191 sym_link *rtype = operandType (IC_RIGHT (ic));
9192 operand *right = IC_RIGHT (ic);
9195 D (emitcode (";", "genCast ");
9198 /* if they are equivalent then do nothing */
9199 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9202 aopOp (right, ic, FALSE, FALSE);
9203 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9205 /* if the result is a bit */
9206 if (AOP_TYPE (result) == AOP_CRY)
9208 /* if the right size is a literal then
9209 we know what the value is */
9210 if (AOP_TYPE (right) == AOP_LIT)
9212 if (((int) operandLitValue (right)))
9213 aopPut (AOP (result), one, 0);
9215 aopPut (AOP (result), zero, 0);
9220 /* the right is also a bit variable */
9221 if (AOP_TYPE (right) == AOP_CRY)
9223 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9224 aopPut (AOP (result), "c", 0);
9230 aopPut (AOP (result), "a", 0);
9234 /* if they are the same size : or less */
9235 if (AOP_SIZE (result) <= AOP_SIZE (right))
9238 /* if they are in the same place */
9239 if (sameRegs (AOP (right), AOP (result)))
9242 /* if they in different places then copy */
9243 size = AOP_SIZE (result);
9245 _startLazyDPSEvaluation ();
9248 aopPut (AOP (result),
9249 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9253 _endLazyDPSEvaluation ();
9258 /* if the result is of type pointer */
9263 sym_link *type = operandType (right);
9265 /* pointer to generic pointer */
9266 if (IS_GENPTR (ctype))
9272 p_type = DCL_TYPE (type);
9276 #if OLD_CAST_BEHAVIOR
9277 /* KV: we are converting a non-pointer type to
9278 * a generic pointer. This (ifdef'd out) code
9279 * says that the resulting generic pointer
9280 * should have the same class as the storage
9281 * location of the non-pointer variable.
9283 * For example, converting an int (which happens
9284 * to be stored in DATA space) to a pointer results
9285 * in a DATA generic pointer; if the original int
9286 * in XDATA space, so will be the resulting pointer.
9288 * I don't like that behavior, and thus this change:
9289 * all such conversions will be forced to XDATA and
9290 * throw a warning. If you want some non-XDATA
9291 * type, or you want to suppress the warning, you
9292 * must go through an intermediate cast, like so:
9294 * char _generic *gp = (char _xdata *)(intVar);
9296 sym_link *etype = getSpec (type);
9298 /* we have to go by the storage class */
9299 if (SPEC_OCLS (etype) != generic)
9301 p_type = PTR_TYPE (SPEC_OCLS (etype));
9306 /* Converting unknown class (i.e. register variable)
9307 * to generic pointer. This is not good, but
9308 * we'll make a guess (and throw a warning).
9311 werror (W_INT_TO_GEN_PTR_CAST);
9315 /* the first two bytes are known */
9316 size = GPTRSIZE - 1;
9318 _startLazyDPSEvaluation ();
9321 aopPut (AOP (result),
9322 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9326 _endLazyDPSEvaluation ();
9328 /* the last byte depending on type */
9346 /* this should never happen */
9347 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9348 "got unknown pointer type");
9351 aopPut (AOP (result), l, GPTRSIZE - 1);
9355 /* just copy the pointers */
9356 size = AOP_SIZE (result);
9358 _startLazyDPSEvaluation ();
9361 aopPut (AOP (result),
9362 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9366 _endLazyDPSEvaluation ();
9370 /* so we now know that the size of destination is greater
9371 than the size of the source */
9372 /* we move to result for the size of source */
9373 size = AOP_SIZE (right);
9375 _startLazyDPSEvaluation ();
9378 aopPut (AOP (result),
9379 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9383 _endLazyDPSEvaluation ();
9385 /* now depending on the sign of the source && destination */
9386 size = AOP_SIZE (result) - AOP_SIZE (right);
9387 /* if unsigned or not an integral type */
9388 /* also, if the source is a bit, we don't need to sign extend, because
9389 * it can't possibly have set the sign bit.
9391 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9395 aopPut (AOP (result), zero, offset++);
9400 /* we need to extend the sign :{ */
9401 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9402 FALSE, FALSE, TRUE);
9404 emitcode ("rlc", "a");
9405 emitcode ("subb", "a,acc");
9407 aopPut (AOP (result), "a", offset++);
9410 /* we are done hurray !!!! */
9413 freeAsmop (right, NULL, ic, TRUE);
9414 freeAsmop (result, NULL, ic, TRUE);
9418 /*-----------------------------------------------------------------*/
9419 /* genDjnz - generate decrement & jump if not zero instrucion */
9420 /*-----------------------------------------------------------------*/
9422 genDjnz (iCode * ic, iCode * ifx)
9428 /* if the if condition has a false label
9429 then we cannot save */
9433 /* if the minus is not of the form
9435 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9436 !IS_OP_LITERAL (IC_RIGHT (ic)))
9439 if (operandLitValue (IC_RIGHT (ic)) != 1)
9442 /* if the size of this greater than one then no
9444 if (getSize (operandType (IC_RESULT (ic))) > 1)
9447 /* otherwise we can save BIG */
9448 D(emitcode(";", "genDjnz"););
9450 lbl = newiTempLabel (NULL);
9451 lbl1 = newiTempLabel (NULL);
9453 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9455 if (AOP_NEEDSACC(IC_RESULT(ic)))
9457 /* If the result is accessed indirectly via
9458 * the accumulator, we must explicitly write
9459 * it back after the decrement.
9461 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9463 if (strcmp(rByte, "a"))
9465 /* Something is hopelessly wrong */
9466 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9467 __FILE__, __LINE__);
9468 /* We can just give up; the generated code will be inefficient,
9471 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9474 emitcode ("dec", "%s", rByte);
9475 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9476 emitcode ("jnz", "%05d$", lbl->key + 100);
9478 else if (IS_AOP_PREG (IC_RESULT (ic)))
9480 emitcode ("dec", "%s",
9481 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9482 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9483 emitcode ("jnz", "%05d$", lbl->key + 100);
9487 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9490 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9491 emitcode ("", "%05d$:", lbl->key + 100);
9492 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9493 emitcode ("", "%05d$:", lbl1->key + 100);
9495 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9500 /*-----------------------------------------------------------------*/
9501 /* genReceive - generate code for a receive iCode */
9502 /*-----------------------------------------------------------------*/
9504 genReceive (iCode * ic)
9507 D (emitcode (";", "genReceive ");
9510 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9511 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9512 IS_TRUE_SYMOP (IC_RESULT (ic))))
9514 int size = getSize (operandType (IC_RESULT (ic)));
9515 int offset = fReturnSizeDS390 - size;
9518 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9519 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9522 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9523 size = AOP_SIZE (IC_RESULT (ic));
9527 emitcode ("pop", "acc");
9528 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9535 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9537 assignResultValue (IC_RESULT (ic));
9540 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9543 /*-----------------------------------------------------------------*/
9544 /* gen390Code - generate code for Dallas 390 based controllers */
9545 /*-----------------------------------------------------------------*/
9547 gen390Code (iCode * lic)
9552 lineHead = lineCurr = NULL;
9556 /* print the allocation information */
9558 printAllocInfo (currFunc, codeOutFile);
9560 /* if debug information required */
9561 if (options.debug && currFunc)
9563 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9565 if (IS_STATIC (currFunc->etype))
9566 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9568 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9571 /* stack pointer name */
9572 if (options.useXstack)
9578 for (ic = lic; ic; ic = ic->next)
9581 if (cln != ic->lineno)
9586 emitcode ("", "C$%s$%d$%d$%d ==.",
9587 FileBaseName (ic->filename), ic->lineno,
9588 ic->level, ic->block);
9591 emitcode (";", "%s %d", ic->filename, ic->lineno);
9594 /* if the result is marked as
9595 spilt and rematerializable or code for
9596 this has already been generated then
9598 if (resultRemat (ic) || ic->generated)
9601 /* depending on the operation */
9621 /* IPOP happens only when trying to restore a
9622 spilt live range, if there is an ifx statement
9623 following this pop then the if statement might
9624 be using some of the registers being popped which
9625 would destory the contents of the register so
9626 we need to check for this condition and handle it */
9628 ic->next->op == IFX &&
9629 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9630 genIfx (ic->next, ic);
9648 genEndFunction (ic);
9668 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9685 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9689 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9696 /* note these two are xlated by algebraic equivalence
9697 during parsing SDCC.y */
9698 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9699 "got '>=' or '<=' shouldn't have come here");
9703 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9715 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9719 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9723 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9750 case GET_VALUE_AT_ADDRESS:
9755 if (POINTER_SET (ic))
9782 addSet (&_G.sendSet, ic);
9791 /* now we are ready to call the
9792 peep hole optimizer */
9793 if (!options.nopeep)
9794 peepHole (&lineHead);
9796 /* now do the actual printing */
9797 printLine (lineHead, codeOutFile);