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[MAX_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)));
1799 if (/* why would we do this?: jwk20010511 */ 0 &&
1801 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1802 IS_ISR (currFunc->etype) &&
1804 saverbank (SPEC_BANK (detype), ic, TRUE);
1807 /*-----------------------------------------------------------------*/
1808 /* unsaveRegisters - pop the pushed registers */
1809 /*-----------------------------------------------------------------*/
1811 unsaveRegisters (iCode * ic)
1815 /* find the registers in use at this time
1816 and push them away to safety */
1817 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1820 if (options.useXstack)
1822 emitcode ("mov", "r0,%s", spname);
1823 for (i = ds390_nRegs; i >= 0; i--)
1825 if (bitVectBitValue (rsave, i))
1827 emitcode ("dec", "r0");
1828 emitcode ("movx", "a,@r0");
1830 emitcode ("mov", "b,a");
1832 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1836 emitcode ("mov", "%s,r0", spname);
1837 if (bitVectBitValue (rsave, R0_IDX))
1838 emitcode ("mov", "r0,b");
1841 for (i = ds390_nRegs; i >= 0; i--)
1843 if (bitVectBitValue (rsave, i))
1844 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1850 /*-----------------------------------------------------------------*/
1852 /*-----------------------------------------------------------------*/
1854 pushSide (operand * oper, int size)
1857 _startLazyDPSEvaluation ();
1860 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1861 if (AOP_TYPE (oper) != AOP_REG &&
1862 AOP_TYPE (oper) != AOP_DIR &&
1865 emitcode ("mov", "a,%s", l);
1866 emitcode ("push", "acc");
1869 emitcode ("push", "%s", l);
1871 _endLazyDPSEvaluation ();
1874 /*-----------------------------------------------------------------*/
1875 /* assignResultValue - */
1876 /*-----------------------------------------------------------------*/
1878 assignResultValue (operand * oper)
1881 int size = AOP_SIZE (oper);
1883 _startLazyDPSEvaluation ();
1886 aopPut (AOP (oper), fReturn[offset], offset);
1889 _endLazyDPSEvaluation ();
1893 /*-----------------------------------------------------------------*/
1894 /* genXpush - pushes onto the external stack */
1895 /*-----------------------------------------------------------------*/
1897 genXpush (iCode * ic)
1899 asmop *aop = newAsmop (0);
1901 int size, offset = 0;
1903 D (emitcode (";", "genXpush ");
1906 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1907 r = getFreePtr (ic, &aop, FALSE);
1910 emitcode ("mov", "%s,_spx", r->name);
1912 size = AOP_SIZE (IC_LEFT (ic));
1913 _startLazyDPSEvaluation ();
1917 char *l = aopGet (AOP (IC_LEFT (ic)),
1918 offset++, FALSE, FALSE, TRUE);
1920 emitcode ("movx", "@%s,a", r->name);
1921 emitcode ("inc", "%s", r->name);
1924 _endLazyDPSEvaluation ();
1927 emitcode ("mov", "_spx,%s", r->name);
1929 freeAsmop (NULL, aop, ic, TRUE);
1930 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1933 /*-----------------------------------------------------------------*/
1934 /* genIpush - genrate code for pushing this gets a little complex */
1935 /*-----------------------------------------------------------------*/
1937 genIpush (iCode * ic)
1939 int size, offset = 0;
1942 D (emitcode (";", "genIpush ");
1945 /* if this is not a parm push : ie. it is spill push
1946 and spill push is always done on the local stack */
1950 /* and the item is spilt then do nothing */
1951 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1954 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1955 size = AOP_SIZE (IC_LEFT (ic));
1956 /* push it on the stack */
1957 _startLazyDPSEvaluation ();
1960 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1966 emitcode ("push", "%s", l);
1968 _endLazyDPSEvaluation ();
1972 /* this is a paramter push: in this case we call
1973 the routine to find the call and save those
1974 registers that need to be saved */
1977 /* if use external stack then call the external
1978 stack pushing routine */
1979 if (options.useXstack)
1985 /* then do the push */
1986 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1988 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1989 size = AOP_SIZE (IC_LEFT (ic));
1991 _startLazyDPSEvaluation ();
1994 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1995 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1996 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1999 emitcode ("mov", "a,%s", l);
2000 emitcode ("push", "acc");
2003 emitcode ("push", "%s", l);
2005 _endLazyDPSEvaluation ();
2007 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2010 /*-----------------------------------------------------------------*/
2011 /* genIpop - recover the registers: can happen only for spilling */
2012 /*-----------------------------------------------------------------*/
2014 genIpop (iCode * ic)
2018 D (emitcode (";", "genIpop ");
2022 /* if the temp was not pushed then */
2023 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2026 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2027 size = AOP_SIZE (IC_LEFT (ic));
2028 offset = (size - 1);
2029 _startLazyDPSEvaluation ();
2032 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2033 FALSE, TRUE, TRUE));
2035 _endLazyDPSEvaluation ();
2037 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2040 /*-----------------------------------------------------------------*/
2041 /* unsaverbank - restores the resgister bank from stack */
2042 /*-----------------------------------------------------------------*/
2044 unsaverbank (int bank, iCode * ic, bool popPsw)
2052 if (options.useXstack)
2055 r = getFreePtr (ic, &aop, FALSE);
2058 emitcode ("mov", "%s,_spx", r->name);
2059 emitcode ("movx", "a,@%s", r->name);
2060 emitcode ("mov", "psw,a");
2061 emitcode ("dec", "%s", r->name);
2065 emitcode ("pop", "psw");
2068 for (i = (ds390_nRegs - 1); i >= 0; i--)
2070 if (options.useXstack)
2072 emitcode ("movx", "a,@%s", r->name);
2073 emitcode ("mov", "(%s+%d),a",
2074 regs390[i].base, 8 * bank + regs390[i].offset);
2075 emitcode ("dec", "%s", r->name);
2079 emitcode ("pop", "(%s+%d)",
2080 regs390[i].base, 8 * bank + regs390[i].offset);
2083 if (options.useXstack)
2086 emitcode ("mov", "_spx,%s", r->name);
2087 freeAsmop (NULL, aop, ic, TRUE);
2092 /*-----------------------------------------------------------------*/
2093 /* saverbank - saves an entire register bank on the stack */
2094 /*-----------------------------------------------------------------*/
2096 saverbank (int bank, iCode * ic, bool pushPsw)
2102 if (options.useXstack)
2106 r = getFreePtr (ic, &aop, FALSE);
2107 emitcode ("mov", "%s,_spx", r->name);
2111 for (i = 0; i < ds390_nRegs; i++)
2113 if (options.useXstack)
2115 emitcode ("inc", "%s", r->name);
2116 emitcode ("mov", "a,(%s+%d)",
2117 regs390[i].base, 8 * bank + regs390[i].offset);
2118 emitcode ("movx", "@%s,a", r->name);
2121 emitcode ("push", "(%s+%d)",
2122 regs390[i].base, 8 * bank + regs390[i].offset);
2127 if (options.useXstack)
2129 emitcode ("mov", "a,psw");
2130 emitcode ("movx", "@%s,a", r->name);
2131 emitcode ("inc", "%s", r->name);
2132 emitcode ("mov", "_spx,%s", r->name);
2133 freeAsmop (NULL, aop, ic, TRUE);
2137 emitcode ("push", "psw");
2139 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2145 /*-----------------------------------------------------------------*/
2146 /* genCall - generates a call statement */
2147 /*-----------------------------------------------------------------*/
2149 genCall (iCode * ic)
2154 D (emitcode (";", "genCall "););
2156 /* if we are calling a function that is not using
2157 the same register bank then we need to save the
2158 destination registers on the stack */
2159 detype = getSpec (operandType (IC_LEFT (ic)));
2161 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2162 IS_ISR (currFunc->etype) &&
2167 /* if caller saves & we have not saved then */
2168 if (!ic->regsSaved) {
2170 // no need to save if we switch banks
2176 /* if send set is not empty the assign */
2181 for (sic = setFirstItem (_G.sendSet); sic;
2182 sic = setNextItem (_G.sendSet))
2184 int size, offset = 0;
2186 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2187 size = AOP_SIZE (IC_LEFT (sic));
2189 _startLazyDPSEvaluation ();
2192 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2193 FALSE, FALSE, TRUE);
2194 if (strcmp (l, fReturn[offset])) {
2197 emitcode ("mov", "%s,%s",
2203 _endLazyDPSEvaluation ();
2204 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2210 saverbank(SPEC_BANK(detype), ic, TRUE);
2214 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2215 OP_SYMBOL (IC_LEFT (ic))->rname :
2216 OP_SYMBOL (IC_LEFT (ic))->name));
2218 /* if we need assign a result value */
2219 if ((IS_ITEMP (IC_RESULT (ic)) &&
2220 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2221 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2222 IS_TRUE_SYMOP (IC_RESULT (ic)))
2224 if (isOperandInFarSpace (IC_RESULT (ic))
2225 && getSize (operandType (IC_RESULT (ic))) <= 2)
2227 int size = getSize (operandType (IC_RESULT (ic)));
2229 /* Special case for 1 or 2 byte return in far space. */
2233 emitcode ("mov", "b,%s", fReturn[1]);
2236 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2237 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2241 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2243 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2248 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2251 assignResultValue (IC_RESULT (ic));
2253 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2257 /* adjust the stack for parameters if
2262 if (ic->parmBytes > 3)
2264 emitcode ("mov", "a,%s", spname);
2265 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2266 emitcode ("mov", "%s,a", spname);
2269 for (i = 0; i < ic->parmBytes; i++)
2270 emitcode ("dec", "%s", spname);
2273 /* if register bank was saved then pop them */
2275 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2277 /* if we have saved some registers then unsave them */
2278 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2279 unsaveRegisters (ic);
2283 /*-----------------------------------------------------------------*/
2284 /* genPcall - generates a call by pointer statement */
2285 /*-----------------------------------------------------------------*/
2287 genPcall (iCode * ic)
2290 symbol *rlbl = newiTempLabel (NULL);
2292 D (emitcode (";", "genPcall ");
2295 /* if caller saves & we have not saved then */
2299 /* if we are calling a function that is not using
2300 the same register bank then we need to save the
2301 destination registers on the stack */
2302 detype = getSpec (operandType (IC_LEFT (ic)));
2304 IS_ISR (currFunc->etype) &&
2305 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2306 saverbank (SPEC_BANK (detype), ic, TRUE);
2308 /* push the return address on to the stack */
2309 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2310 emitcode ("push", "acc");
2311 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2312 emitcode ("push", "acc");
2314 if (options.model == MODEL_FLAT24)
2316 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2317 emitcode ("push", "acc");
2320 /* now push the calling address */
2321 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2323 pushSide (IC_LEFT (ic), FPTRSIZE);
2325 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2327 /* if send set is not empty the assign */
2332 for (sic = setFirstItem (_G.sendSet); sic;
2333 sic = setNextItem (_G.sendSet))
2335 int size, offset = 0;
2337 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2338 size = AOP_SIZE (IC_LEFT (sic));
2339 _startLazyDPSEvaluation ();
2342 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2343 FALSE, FALSE, TRUE);
2344 if (strcmp (l, fReturn[offset]))
2346 emitcode ("mov", "%s,%s",
2352 _endLazyDPSEvaluation ();
2353 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2358 emitcode ("ret", "");
2359 emitcode ("", "%05d$:", (rlbl->key + 100));
2362 /* if we need assign a result value */
2363 if ((IS_ITEMP (IC_RESULT (ic)) &&
2364 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2365 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2366 IS_TRUE_SYMOP (IC_RESULT (ic)))
2370 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2373 assignResultValue (IC_RESULT (ic));
2375 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2378 /* adjust the stack for parameters if
2383 if (ic->parmBytes > 3)
2385 emitcode ("mov", "a,%s", spname);
2386 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2387 emitcode ("mov", "%s,a", spname);
2390 for (i = 0; i < ic->parmBytes; i++)
2391 emitcode ("dec", "%s", spname);
2395 /* if register bank was saved then unsave them */
2397 (SPEC_BANK (currFunc->etype) !=
2398 SPEC_BANK (detype)))
2399 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2401 /* if we hade saved some registers then
2404 unsaveRegisters (ic);
2408 /*-----------------------------------------------------------------*/
2409 /* resultRemat - result is rematerializable */
2410 /*-----------------------------------------------------------------*/
2412 resultRemat (iCode * ic)
2414 if (SKIP_IC (ic) || ic->op == IFX)
2417 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2419 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2420 if (sym->remat && !POINTER_SET (ic))
2427 #if defined(__BORLANDC__) || defined(_MSC_VER)
2428 #define STRCASECMP stricmp
2430 #define STRCASECMP strcasecmp
2433 /*-----------------------------------------------------------------*/
2434 /* inExcludeList - return 1 if the string is in exclude Reg list */
2435 /*-----------------------------------------------------------------*/
2437 inExcludeList (char *s)
2441 if (options.excludeRegs[i] &&
2442 STRCASECMP (options.excludeRegs[i], "none") == 0)
2445 for (i = 0; options.excludeRegs[i]; i++)
2447 if (options.excludeRegs[i] &&
2448 STRCASECMP (s, options.excludeRegs[i]) == 0)
2454 /*-----------------------------------------------------------------*/
2455 /* genFunction - generated code for function entry */
2456 /*-----------------------------------------------------------------*/
2458 genFunction (iCode * ic)
2463 D (emitcode (";", "genFunction ");
2467 /* create the function header */
2468 emitcode (";", "-----------------------------------------");
2469 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2470 emitcode (";", "-----------------------------------------");
2472 emitcode ("", "%s:", sym->rname);
2473 fetype = getSpec (operandType (IC_LEFT (ic)));
2475 /* if critical function then turn interrupts off */
2476 if (SPEC_CRTCL (fetype))
2477 emitcode ("clr", "ea");
2479 /* here we need to generate the equates for the
2480 register bank if required */
2481 if (SPEC_BANK (fetype) != rbank)
2485 rbank = SPEC_BANK (fetype);
2486 for (i = 0; i < ds390_nRegs; i++)
2488 if (strcmp (regs390[i].base, "0") == 0)
2489 emitcode ("", "%s = 0x%02x",
2491 8 * rbank + regs390[i].offset);
2493 emitcode ("", "%s = %s + 0x%02x",
2496 8 * rbank + regs390[i].offset);
2500 /* if this is an interrupt service routine then
2501 save acc, b, dpl, dph */
2502 if (IS_ISR (sym->etype))
2505 if (!inExcludeList ("acc"))
2506 emitcode ("push", "acc");
2507 if (!inExcludeList ("b"))
2508 emitcode ("push", "b");
2509 if (!inExcludeList ("dpl"))
2510 emitcode ("push", "dpl");
2511 if (!inExcludeList ("dph"))
2512 emitcode ("push", "dph");
2513 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2515 emitcode ("push", "dpx");
2516 /* Make sure we're using standard DPTR */
2517 emitcode ("push", "dps");
2518 emitcode ("mov", "dps, #0x00");
2519 if (options.stack10bit)
2521 /* This ISR could conceivably use DPTR2. Better save it. */
2522 emitcode ("push", "dpl1");
2523 emitcode ("push", "dph1");
2524 emitcode ("push", "dpx1");
2525 emitcode ("push", DP2_RESULT_REG);
2528 /* if this isr has no bank i.e. is going to
2529 run with bank 0 , then we need to save more
2531 if (!SPEC_BANK (sym->etype))
2534 /* if this function does not call any other
2535 function then we can be economical and
2536 save only those registers that are used */
2541 /* if any registers used */
2544 /* save the registers used */
2545 for (i = 0; i < sym->regsUsed->size; i++)
2547 if (bitVectBitValue (sym->regsUsed, i) ||
2548 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2549 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2556 /* this function has a function call cannot
2557 determines register usage so we will have the
2559 saverbank (0, ic, FALSE);
2565 /* if callee-save to be used for this function
2566 then save the registers being used in this function */
2567 if (sym->calleeSave)
2571 /* if any registers used */
2574 /* save the registers used */
2575 for (i = 0; i < sym->regsUsed->size; i++)
2577 if (bitVectBitValue (sym->regsUsed, i) ||
2578 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2580 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2588 /* set the register bank to the desired value */
2589 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2591 emitcode ("push", "psw");
2592 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2595 if (IS_RENT (sym->etype) || options.stackAuto)
2598 if (options.useXstack)
2600 emitcode ("mov", "r0,%s", spname);
2601 emitcode ("mov", "a,_bp");
2602 emitcode ("movx", "@r0,a");
2603 emitcode ("inc", "%s", spname);
2607 /* set up the stack */
2608 emitcode ("push", "_bp"); /* save the callers stack */
2610 emitcode ("mov", "_bp,%s", spname);
2613 /* adjust the stack for the function */
2619 werror (W_STACK_OVERFLOW, sym->name);
2621 if (i > 3 && sym->recvSize < 4)
2624 emitcode ("mov", "a,sp");
2625 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2626 emitcode ("mov", "sp,a");
2631 emitcode ("inc", "sp");
2637 emitcode ("mov", "a,_spx");
2638 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2639 emitcode ("mov", "_spx,a");
2644 /*-----------------------------------------------------------------*/
2645 /* genEndFunction - generates epilogue for functions */
2646 /*-----------------------------------------------------------------*/
2648 genEndFunction (iCode * ic)
2650 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2652 D (emitcode (";", "genEndFunction ");
2655 if (IS_RENT (sym->etype) || options.stackAuto)
2657 emitcode ("mov", "%s,_bp", spname);
2660 /* if use external stack but some variables were
2661 added to the local stack then decrement the
2663 if (options.useXstack && sym->stack)
2665 emitcode ("mov", "a,sp");
2666 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2667 emitcode ("mov", "sp,a");
2671 if ((IS_RENT (sym->etype) || options.stackAuto))
2673 if (options.useXstack)
2675 emitcode ("mov", "r0,%s", spname);
2676 emitcode ("movx", "a,@r0");
2677 emitcode ("mov", "_bp,a");
2678 emitcode ("dec", "%s", spname);
2682 emitcode ("pop", "_bp");
2686 /* restore the register bank */
2687 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2688 emitcode ("pop", "psw");
2690 if (IS_ISR (sym->etype))
2693 /* now we need to restore the registers */
2694 /* if this isr has no bank i.e. is going to
2695 run with bank 0 , then we need to save more
2697 if (!SPEC_BANK (sym->etype))
2700 /* if this function does not call any other
2701 function then we can be economical and
2702 save only those registers that are used */
2707 /* if any registers used */
2710 /* save the registers used */
2711 for (i = sym->regsUsed->size; i >= 0; i--)
2713 if (bitVectBitValue (sym->regsUsed, i) ||
2714 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2715 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2722 /* this function has a function call cannot
2723 determines register usage so we will have the
2725 unsaverbank (0, ic, FALSE);
2729 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2731 if (options.stack10bit)
2733 emitcode ("pop", DP2_RESULT_REG);
2734 emitcode ("pop", "dpx1");
2735 emitcode ("pop", "dph1");
2736 emitcode ("pop", "dpl1");
2738 emitcode ("pop", "dps");
2739 emitcode ("pop", "dpx");
2741 if (!inExcludeList ("dph"))
2742 emitcode ("pop", "dph");
2743 if (!inExcludeList ("dpl"))
2744 emitcode ("pop", "dpl");
2745 if (!inExcludeList ("b"))
2746 emitcode ("pop", "b");
2747 if (!inExcludeList ("acc"))
2748 emitcode ("pop", "acc");
2750 if (SPEC_CRTCL (sym->etype))
2751 emitcode ("setb", "ea");
2753 /* if debug then send end of function */
2754 /* if (options.debug && currFunc) { */
2758 emitcode ("", "C$%s$%d$%d$%d ==.",
2759 FileBaseName (ic->filename), currFunc->lastLine,
2760 ic->level, ic->block);
2761 if (IS_STATIC (currFunc->etype))
2762 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2764 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2768 emitcode ("reti", "");
2772 if (SPEC_CRTCL (sym->etype))
2773 emitcode ("setb", "ea");
2775 if (sym->calleeSave)
2779 /* if any registers used */
2782 /* save the registers used */
2783 for (i = sym->regsUsed->size; i >= 0; i--)
2785 if (bitVectBitValue (sym->regsUsed, i) ||
2786 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2787 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2793 /* if debug then send end of function */
2797 emitcode ("", "C$%s$%d$%d$%d ==.",
2798 FileBaseName (ic->filename), currFunc->lastLine,
2799 ic->level, ic->block);
2800 if (IS_STATIC (currFunc->etype))
2801 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2803 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2807 emitcode ("ret", "");
2812 /*-----------------------------------------------------------------*/
2813 /* genRet - generate code for return statement */
2814 /*-----------------------------------------------------------------*/
2818 int size, offset = 0, pushed = 0;
2820 D (emitcode (";", "genRet ");
2823 /* if we have no return value then
2824 just generate the "ret" */
2828 /* we have something to return then
2829 move the return value into place */
2830 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2831 size = AOP_SIZE (IC_LEFT (ic));
2833 _startLazyDPSEvaluation ();
2837 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2839 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2840 FALSE, TRUE, FALSE);
2841 emitcode ("push", "%s", l);
2846 l = aopGet (AOP (IC_LEFT (ic)), offset,
2847 FALSE, FALSE, FALSE);
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 emitcode (";",__FUNCTION__);
3705 if (size<1 || size>2) {
3706 // this should never happen
3707 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3708 AOP_SIZE(result), __FUNCTION__, lineno);
3712 /* (if two literals: the value is computed before) */
3713 /* if one literal, literal on the right */
3714 if (AOP_TYPE (left) == AOP_LIT)
3719 emitcode (";", "swapped left and right");
3722 if (SPEC_USIGN(opetype)
3723 // ignore the sign of left and right, what else can we do?
3724 || (SPEC_USIGN(operandType(left)) &&
3725 SPEC_USIGN(operandType(right)))) {
3726 // just an unsigned 8*8=8/16 multiply
3727 //emitcode (";","unsigned");
3728 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3729 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3730 emitcode ("mul", "ab");
3731 aopPut (AOP (result), "a", 0);
3733 aopPut (AOP (result), "b", 1);
3738 // we have to do a signed multiply
3740 emitcode (";", "signed");
3741 emitcode ("clr", "F0"); // reset sign flag
3742 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3743 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3745 lbl=newiTempLabel(NULL);
3746 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3747 // left side is negative, 8-bit two's complement, this fails for -128
3748 emitcode ("setb", "F0"); // set sign flag
3749 emitcode ("cpl", "a");
3750 emitcode ("inc", "a");
3752 emitcode ("", "%05d$:", lbl->key+100);
3753 emitcode ("xch", "a,b");
3756 if (AOP_TYPE(right)==AOP_LIT) {
3757 /* AND literal negative */
3758 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3759 // two's complement for literal<0
3760 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3761 emitcode ("cpl", "a");
3762 emitcode ("inc", "a");
3765 lbl=newiTempLabel(NULL);
3766 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3767 // right side is negative, 8-bit two's complement
3768 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3769 emitcode ("cpl", "a");
3770 emitcode ("inc", "a");
3771 emitcode ("", "%05d$:", lbl->key+100);
3773 emitcode ("mul", "ab");
3775 lbl=newiTempLabel(NULL);
3776 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3777 // only ONE op was negative, we have to do a 8/16-bit two's complement
3778 emitcode ("cpl", "a"); // lsb
3780 emitcode ("inc", "a");
3782 emitcode ("add", "a,#1");
3783 emitcode ("xch", "a,b");
3784 emitcode ("cpl", "a"); // msb
3785 emitcode ("addc", "a,#0");
3786 emitcode ("xch", "a,b");
3789 emitcode ("", "%05d$:", lbl->key+100);
3790 aopPut (AOP (result), "a", 0);
3792 aopPut (AOP (result), "b", 1);
3796 /*-----------------------------------------------------------------*/
3797 /* genMult - generates code for multiplication */
3798 /*-----------------------------------------------------------------*/
3800 genMult (iCode * ic)
3802 operand *left = IC_LEFT (ic);
3803 operand *right = IC_RIGHT (ic);
3804 operand *result = IC_RESULT (ic);
3806 D (emitcode (";", "genMult "););
3808 /* assign the amsops */
3811 /* special cases first */
3813 if (AOP_TYPE (left) == AOP_CRY &&
3814 AOP_TYPE (right) == AOP_CRY)
3816 genMultbits (left, right, result);
3820 /* if both are of size == 1 */
3821 if (AOP_SIZE (left) == 1 &&
3822 AOP_SIZE (right) == 1)
3824 genMultOneByte (left, right, result);
3828 /* should have been converted to function call */
3832 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3833 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3834 freeAsmop (result, NULL, ic, TRUE);
3837 /*-----------------------------------------------------------------*/
3838 /* genDivbits :- division of bits */
3839 /*-----------------------------------------------------------------*/
3841 genDivbits (operand * left,
3848 /* the result must be bit */
3849 LOAD_AB_FOR_DIV (left, right, l);
3850 emitcode ("div", "ab");
3851 emitcode ("rrc", "a");
3852 aopPut (AOP (result), "c", 0);
3855 /*-----------------------------------------------------------------*/
3856 /* genDivOneByte : 8 bit division */
3857 /*-----------------------------------------------------------------*/
3859 genDivOneByte (operand * left,
3863 sym_link *opetype = operandType (result);
3868 size = AOP_SIZE (result) - 1;
3870 /* signed or unsigned */
3871 if (SPEC_USIGN (opetype))
3873 /* unsigned is easy */
3874 LOAD_AB_FOR_DIV (left, right, l);
3875 emitcode ("div", "ab");
3876 aopPut (AOP (result), "a", 0);
3878 aopPut (AOP (result), zero, offset++);
3882 /* signed is a little bit more difficult */
3884 /* save the signs of the operands */
3885 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3887 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3888 emitcode ("push", "acc"); /* save it on the stack */
3890 /* now sign adjust for both left & right */
3891 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3893 lbl = newiTempLabel (NULL);
3894 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3895 emitcode ("cpl", "a");
3896 emitcode ("inc", "a");
3897 emitcode ("", "%05d$:", (lbl->key + 100));
3898 emitcode ("mov", "b,a");
3900 /* sign adjust left side */
3901 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3904 lbl = newiTempLabel (NULL);
3905 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3906 emitcode ("cpl", "a");
3907 emitcode ("inc", "a");
3908 emitcode ("", "%05d$:", (lbl->key + 100));
3910 /* now the division */
3911 emitcode ("nop", "; workaround for DS80C390 div bug.");
3912 emitcode ("div", "ab");
3913 /* we are interested in the lower order
3915 emitcode ("mov", "b,a");
3916 lbl = newiTempLabel (NULL);
3917 emitcode ("pop", "acc");
3918 /* if there was an over flow we don't
3919 adjust the sign of the result */
3920 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3921 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3923 emitcode ("clr", "a");
3924 emitcode ("subb", "a,b");
3925 emitcode ("mov", "b,a");
3926 emitcode ("", "%05d$:", (lbl->key + 100));
3928 /* now we are done */
3929 aopPut (AOP (result), "b", 0);
3932 emitcode ("mov", "c,b.7");
3933 emitcode ("subb", "a,acc");
3936 aopPut (AOP (result), "a", offset++);
3940 /*-----------------------------------------------------------------*/
3941 /* genDiv - generates code for division */
3942 /*-----------------------------------------------------------------*/
3946 operand *left = IC_LEFT (ic);
3947 operand *right = IC_RIGHT (ic);
3948 operand *result = IC_RESULT (ic);
3950 D (emitcode (";", "genDiv ");
3953 /* assign the amsops */
3956 /* special cases first */
3958 if (AOP_TYPE (left) == AOP_CRY &&
3959 AOP_TYPE (right) == AOP_CRY)
3961 genDivbits (left, right, result);
3965 /* if both are of size == 1 */
3966 if (AOP_SIZE (left) == 1 &&
3967 AOP_SIZE (right) == 1)
3969 genDivOneByte (left, right, result);
3973 /* should have been converted to function call */
3976 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3977 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3978 freeAsmop (result, NULL, ic, TRUE);
3981 /*-----------------------------------------------------------------*/
3982 /* genModbits :- modulus of bits */
3983 /*-----------------------------------------------------------------*/
3985 genModbits (operand * left,
3992 /* the result must be bit */
3993 LOAD_AB_FOR_DIV (left, right, l);
3994 emitcode ("div", "ab");
3995 emitcode ("mov", "a,b");
3996 emitcode ("rrc", "a");
3997 aopPut (AOP (result), "c", 0);
4000 /*-----------------------------------------------------------------*/
4001 /* genModOneByte : 8 bit modulus */
4002 /*-----------------------------------------------------------------*/
4004 genModOneByte (operand * left,
4008 sym_link *opetype = operandType (result);
4012 /* signed or unsigned */
4013 if (SPEC_USIGN (opetype))
4015 /* unsigned is easy */
4016 LOAD_AB_FOR_DIV (left, right, l);
4017 emitcode ("div", "ab");
4018 aopPut (AOP (result), "b", 0);
4022 /* signed is a little bit more difficult */
4024 /* save the signs of the operands */
4025 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4028 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4029 emitcode ("push", "acc"); /* save it on the stack */
4031 /* now sign adjust for both left & right */
4032 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4035 lbl = newiTempLabel (NULL);
4036 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4037 emitcode ("cpl", "a");
4038 emitcode ("inc", "a");
4039 emitcode ("", "%05d$:", (lbl->key + 100));
4040 emitcode ("mov", "b,a");
4042 /* sign adjust left side */
4043 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4046 lbl = newiTempLabel (NULL);
4047 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4048 emitcode ("cpl", "a");
4049 emitcode ("inc", "a");
4050 emitcode ("", "%05d$:", (lbl->key + 100));
4052 /* now the multiplication */
4053 emitcode ("nop", "; workaround for DS80C390 div bug.");
4054 emitcode ("div", "ab");
4055 /* we are interested in the lower order
4057 lbl = newiTempLabel (NULL);
4058 emitcode ("pop", "acc");
4059 /* if there was an over flow we don't
4060 adjust the sign of the result */
4061 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4062 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4064 emitcode ("clr", "a");
4065 emitcode ("subb", "a,b");
4066 emitcode ("mov", "b,a");
4067 emitcode ("", "%05d$:", (lbl->key + 100));
4069 /* now we are done */
4070 aopPut (AOP (result), "b", 0);
4074 /*-----------------------------------------------------------------*/
4075 /* genMod - generates code for division */
4076 /*-----------------------------------------------------------------*/
4080 operand *left = IC_LEFT (ic);
4081 operand *right = IC_RIGHT (ic);
4082 operand *result = IC_RESULT (ic);
4084 D (emitcode (";", "genMod ");
4087 /* assign the amsops */
4090 /* special cases first */
4092 if (AOP_TYPE (left) == AOP_CRY &&
4093 AOP_TYPE (right) == AOP_CRY)
4095 genModbits (left, right, result);
4099 /* if both are of size == 1 */
4100 if (AOP_SIZE (left) == 1 &&
4101 AOP_SIZE (right) == 1)
4103 genModOneByte (left, right, result);
4107 /* should have been converted to function call */
4111 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4112 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4113 freeAsmop (result, NULL, ic, TRUE);
4116 /*-----------------------------------------------------------------*/
4117 /* genIfxJump :- will create a jump depending on the ifx */
4118 /*-----------------------------------------------------------------*/
4120 genIfxJump (iCode * ic, char *jval)
4123 symbol *tlbl = newiTempLabel (NULL);
4126 D (emitcode (";", "genIfxJump ");
4129 /* if true label then we jump if condition
4133 jlbl = IC_TRUE (ic);
4134 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4135 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4139 /* false label is present */
4140 jlbl = IC_FALSE (ic);
4141 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4142 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4144 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4145 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4147 emitcode (inst, "%05d$", tlbl->key + 100);
4148 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4149 emitcode ("", "%05d$:", tlbl->key + 100);
4151 /* mark the icode as generated */
4155 /*-----------------------------------------------------------------*/
4156 /* genCmp :- greater or less than comparison */
4157 /*-----------------------------------------------------------------*/
4159 genCmp (operand * left, operand * right,
4160 iCode * ic, iCode * ifx, int sign)
4162 int size, offset = 0;
4163 unsigned long lit = 0L;
4166 D (emitcode (";", "genCmp");
4169 result = IC_RESULT (ic);
4171 /* if left & right are bit variables */
4172 if (AOP_TYPE (left) == AOP_CRY &&
4173 AOP_TYPE (right) == AOP_CRY)
4175 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4176 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4180 /* subtract right from left if at the
4181 end the carry flag is set then we know that
4182 left is greater than right */
4183 size = max (AOP_SIZE (left), AOP_SIZE (right));
4185 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4186 if ((size == 1) && !sign &&
4187 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4189 symbol *lbl = newiTempLabel (NULL);
4190 emitcode ("cjne", "%s,%s,%05d$",
4191 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4192 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4194 emitcode ("", "%05d$:", lbl->key + 100);
4198 if (AOP_TYPE (right) == AOP_LIT)
4200 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4201 /* optimize if(x < 0) or if(x >= 0) */
4210 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4212 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215 aopOp (result, ic, FALSE, FALSE);
4217 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4219 freeAsmop (result, NULL, ic, TRUE);
4220 genIfxJump (ifx, "acc.7");
4225 emitcode ("rlc", "a");
4227 goto release_freedLR;
4235 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4236 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4237 emitcode (";", "genCmp #2");
4238 if (sign && (size == 0))
4240 emitcode (";", "genCmp #3");
4241 emitcode ("xrl", "a,#0x80");
4242 if (AOP_TYPE (right) == AOP_LIT)
4244 unsigned long lit = (unsigned long)
4245 floatFromVal (AOP (right)->aopu.aop_lit);
4246 emitcode (";", "genCmp #3.1");
4247 emitcode ("subb", "a,#0x%02x",
4248 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4252 emitcode (";", "genCmp #3.2");
4253 if (AOP_NEEDSACC (right))
4255 emitcode ("push", "acc");
4257 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4258 FALSE, FALSE, FALSE));
4259 emitcode ("xrl", "b,#0x80");
4260 if (AOP_NEEDSACC (right))
4262 emitcode ("pop", "acc");
4264 emitcode ("subb", "a,b");
4271 emitcode (";", "genCmp #4");
4272 if (AOP_NEEDSACC (right))
4275 emitcode (";", "genCmp #4.1");
4276 emitcode ("xch", "a, b");
4277 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4278 emitcode ("xch", "a, b");
4283 emitcode (";", "genCmp #4.2");
4284 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4287 emitcode ("subb", "a,%s", s);
4294 /* Don't need the left & right operands any more; do need the result. */
4295 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4296 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4298 aopOp (result, ic, FALSE, FALSE);
4302 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4308 /* if the result is used in the next
4309 ifx conditional branch then generate
4310 code a little differently */
4313 genIfxJump (ifx, "c");
4319 /* leave the result in acc */
4321 freeAsmop (result, NULL, ic, TRUE);
4324 /*-----------------------------------------------------------------*/
4325 /* genCmpGt :- greater than comparison */
4326 /*-----------------------------------------------------------------*/
4328 genCmpGt (iCode * ic, iCode * ifx)
4330 operand *left, *right;
4331 sym_link *letype, *retype;
4334 D (emitcode (";", "genCmpGt ");
4337 left = IC_LEFT (ic);
4338 right = IC_RIGHT (ic);
4340 letype = getSpec (operandType (left));
4341 retype = getSpec (operandType (right));
4342 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4344 /* assign the left & right amsops */
4347 genCmp (right, left, ic, ifx, sign);
4350 /*-----------------------------------------------------------------*/
4351 /* genCmpLt - less than comparisons */
4352 /*-----------------------------------------------------------------*/
4354 genCmpLt (iCode * ic, iCode * ifx)
4356 operand *left, *right;
4357 sym_link *letype, *retype;
4360 D (emitcode (";", "genCmpLt "););
4362 left = IC_LEFT (ic);
4363 right = IC_RIGHT (ic);
4365 letype = getSpec (operandType (left));
4366 retype = getSpec (operandType (right));
4367 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4369 /* assign the left & right amsops */
4372 genCmp (left, right, ic, ifx, sign);
4375 /*-----------------------------------------------------------------*/
4376 /* gencjneshort - compare and jump if not equal */
4377 /*-----------------------------------------------------------------*/
4379 gencjneshort (operand * left, operand * right, symbol * lbl)
4381 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4383 unsigned long lit = 0L;
4385 D (emitcode (";", "gencjneshort");
4388 /* if the left side is a literal or
4389 if the right is in a pointer register and left
4391 if ((AOP_TYPE (left) == AOP_LIT) ||
4392 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4399 if (AOP_TYPE (right) == AOP_LIT)
4400 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4402 if (opIsGptr (left) || opIsGptr (right))
4404 /* We are comparing a generic pointer to something.
4405 * Exclude the generic type byte from the comparison.
4408 D (emitcode (";", "cjneshort: generic ptr special case.");
4413 /* if the right side is a literal then anything goes */
4414 if (AOP_TYPE (right) == AOP_LIT &&
4415 AOP_TYPE (left) != AOP_DIR)
4419 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4421 emitcode ("cjne", "a,%s,%05d$",
4422 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4428 /* if the right side is in a register or in direct space or
4429 if the left is a pointer register & right is not */
4430 else if (AOP_TYPE (right) == AOP_REG ||
4431 AOP_TYPE (right) == AOP_DIR ||
4432 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4433 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4437 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4438 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4439 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4440 emitcode ("jnz", "%05d$", lbl->key + 100);
4442 emitcode ("cjne", "a,%s,%05d$",
4443 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4450 /* right is a pointer reg need both a & b */
4453 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4454 if (strcmp (l, "b"))
4455 emitcode ("mov", "b,%s", l);
4456 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4457 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4463 /*-----------------------------------------------------------------*/
4464 /* gencjne - compare and jump if not equal */
4465 /*-----------------------------------------------------------------*/
4467 gencjne (operand * left, operand * right, symbol * lbl)
4469 symbol *tlbl = newiTempLabel (NULL);
4471 D (emitcode (";", "gencjne");
4474 gencjneshort (left, right, lbl);
4476 emitcode ("mov", "a,%s", one);
4477 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4478 emitcode ("", "%05d$:", lbl->key + 100);
4479 emitcode ("clr", "a");
4480 emitcode ("", "%05d$:", tlbl->key + 100);
4483 /*-----------------------------------------------------------------*/
4484 /* genCmpEq - generates code for equal to */
4485 /*-----------------------------------------------------------------*/
4487 genCmpEq (iCode * ic, iCode * ifx)
4489 operand *left, *right, *result;
4491 D (emitcode (";", "genCmpEq ");
4495 AOP_SET_LOCALS (ic);
4497 /* if literal, literal on the right or
4498 if the right is in a pointer register and left
4500 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4501 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4503 operand *t = IC_RIGHT (ic);
4504 IC_RIGHT (ic) = IC_LEFT (ic);
4508 if (ifx && /* !AOP_SIZE(result) */
4509 OP_SYMBOL (result) &&
4510 OP_SYMBOL (result)->regType == REG_CND)
4513 /* if they are both bit variables */
4514 if (AOP_TYPE (left) == AOP_CRY &&
4515 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4517 if (AOP_TYPE (right) == AOP_LIT)
4519 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4522 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4523 emitcode ("cpl", "c");
4527 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4531 emitcode ("clr", "c");
4533 /* AOP_TYPE(right) == AOP_CRY */
4537 symbol *lbl = newiTempLabel (NULL);
4538 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4539 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4540 emitcode ("cpl", "c");
4541 emitcode ("", "%05d$:", (lbl->key + 100));
4543 /* if true label then we jump if condition
4545 tlbl = newiTempLabel (NULL);
4548 emitcode ("jnc", "%05d$", tlbl->key + 100);
4549 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4553 emitcode ("jc", "%05d$", tlbl->key + 100);
4554 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4556 emitcode ("", "%05d$:", tlbl->key + 100);
4560 tlbl = newiTempLabel (NULL);
4561 gencjneshort (left, right, tlbl);
4564 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4565 emitcode ("", "%05d$:", tlbl->key + 100);
4569 symbol *lbl = newiTempLabel (NULL);
4570 emitcode ("sjmp", "%05d$", lbl->key + 100);
4571 emitcode ("", "%05d$:", tlbl->key + 100);
4572 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4573 emitcode ("", "%05d$:", lbl->key + 100);
4576 /* mark the icode as generated */
4579 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4580 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4584 /* if they are both bit variables */
4585 if (AOP_TYPE (left) == AOP_CRY &&
4586 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4588 if (AOP_TYPE (right) == AOP_LIT)
4590 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4593 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4594 emitcode ("cpl", "c");
4598 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4602 emitcode ("clr", "c");
4604 /* AOP_TYPE(right) == AOP_CRY */
4608 symbol *lbl = newiTempLabel (NULL);
4609 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4610 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4611 emitcode ("cpl", "c");
4612 emitcode ("", "%05d$:", (lbl->key + 100));
4615 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618 aopOp (result, ic, TRUE, FALSE);
4621 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4628 genIfxJump (ifx, "c");
4631 /* if the result is used in an arithmetic operation
4632 then put the result in place */
4637 gencjne (left, right, newiTempLabel (NULL));
4639 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4640 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4642 aopOp (result, ic, TRUE, FALSE);
4644 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4646 aopPut (AOP (result), "a", 0);
4651 genIfxJump (ifx, "a");
4654 /* if the result is used in an arithmetic operation
4655 then put the result in place */
4656 if (AOP_TYPE (result) != AOP_CRY)
4658 /* leave the result in acc */
4662 freeAsmop (result, NULL, ic, TRUE);
4665 /*-----------------------------------------------------------------*/
4666 /* ifxForOp - returns the icode containing the ifx for operand */
4667 /*-----------------------------------------------------------------*/
4669 ifxForOp (operand * op, iCode * ic)
4671 /* if true symbol then needs to be assigned */
4672 if (IS_TRUE_SYMOP (op))
4675 /* if this has register type condition and
4676 the next instruction is ifx with the same operand
4677 and live to of the operand is upto the ifx only then */
4679 ic->next->op == IFX &&
4680 IC_COND (ic->next)->key == op->key &&
4681 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4686 /*-----------------------------------------------------------------*/
4687 /* genAndOp - for && operation */
4688 /*-----------------------------------------------------------------*/
4690 genAndOp (iCode * ic)
4692 operand *left, *right, *result;
4695 D (emitcode (";", "genAndOp "););
4697 /* note here that && operations that are in an
4698 if statement are taken away by backPatchLabels
4699 only those used in arthmetic operations remain */
4701 AOP_SET_LOCALS (ic);
4703 /* if both are bit variables */
4704 if (AOP_TYPE (left) == AOP_CRY &&
4705 AOP_TYPE (right) == AOP_CRY)
4707 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4708 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4709 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4710 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4712 aopOp (result,ic,FALSE, FALSE);
4717 tlbl = newiTempLabel (NULL);
4719 emitcode ("jz", "%05d$", tlbl->key + 100);
4721 emitcode ("", "%05d$:", tlbl->key + 100);
4722 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4723 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4725 aopOp (result,ic,FALSE, FALSE);
4728 freeAsmop (result, NULL, ic, TRUE);
4732 /*-----------------------------------------------------------------*/
4733 /* genOrOp - for || operation */
4734 /*-----------------------------------------------------------------*/
4736 genOrOp (iCode * ic)
4738 operand *left, *right, *result;
4741 D (emitcode (";", "genOrOp "););
4743 /* note here that || operations that are in an
4744 if statement are taken away by backPatchLabels
4745 only those used in arthmetic operations remain */
4747 AOP_SET_LOCALS (ic);
4749 /* if both are bit variables */
4750 if (AOP_TYPE (left) == AOP_CRY &&
4751 AOP_TYPE (right) == AOP_CRY)
4753 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4754 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4755 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4756 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4758 aopOp (result,ic,FALSE, FALSE);
4764 tlbl = newiTempLabel (NULL);
4766 emitcode ("jnz", "%05d$", tlbl->key + 100);
4768 emitcode ("", "%05d$:", tlbl->key + 100);
4769 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4770 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4772 aopOp (result,ic,FALSE, FALSE);
4777 freeAsmop (result, NULL, ic, TRUE);
4780 /*-----------------------------------------------------------------*/
4781 /* isLiteralBit - test if lit == 2^n */
4782 /*-----------------------------------------------------------------*/
4784 isLiteralBit (unsigned long lit)
4786 unsigned long pw[32] =
4787 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4788 0x100L, 0x200L, 0x400L, 0x800L,
4789 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4790 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4791 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4792 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4793 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4796 for (idx = 0; idx < 32; idx++)
4802 /*-----------------------------------------------------------------*/
4803 /* continueIfTrue - */
4804 /*-----------------------------------------------------------------*/
4806 continueIfTrue (iCode * ic)
4809 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4813 /*-----------------------------------------------------------------*/
4815 /*-----------------------------------------------------------------*/
4817 jumpIfTrue (iCode * ic)
4820 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4824 /*-----------------------------------------------------------------*/
4825 /* jmpTrueOrFalse - */
4826 /*-----------------------------------------------------------------*/
4828 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4830 // ugly but optimized by peephole
4833 symbol *nlbl = newiTempLabel (NULL);
4834 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4835 emitcode ("", "%05d$:", tlbl->key + 100);
4836 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4837 emitcode ("", "%05d$:", nlbl->key + 100);
4841 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4842 emitcode ("", "%05d$:", tlbl->key + 100);
4847 // Generate code to perform a bit-wise logic operation
4848 // on two operands in far space (assumed to already have been
4849 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4850 // in far space. This requires pushing the result on the stack
4851 // then popping it into the result.
4853 genFarFarLogicOp(iCode *ic, char *logicOp)
4855 int size, resultSize, compSize;
4858 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4859 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4860 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4862 _startLazyDPSEvaluation();
4863 for (size = compSize; (size--); offset++)
4865 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4866 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4867 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4869 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4870 emitcode ("push", "acc");
4872 _endLazyDPSEvaluation();
4874 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4875 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4876 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4878 resultSize = AOP_SIZE(IC_RESULT(ic));
4880 ADJUST_PUSHED_RESULT(compSize, resultSize);
4882 _startLazyDPSEvaluation();
4885 emitcode ("pop", "acc");
4886 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4888 _endLazyDPSEvaluation();
4889 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4893 /*-----------------------------------------------------------------*/
4894 /* genAnd - code for and */
4895 /*-----------------------------------------------------------------*/
4897 genAnd (iCode * ic, iCode * ifx)
4899 operand *left, *right, *result;
4900 int size, offset = 0;
4901 unsigned long lit = 0L;
4906 D (emitcode (";", "genAnd "););
4908 AOP_OP_3_NOFATAL (ic, pushResult);
4909 AOP_SET_LOCALS (ic);
4913 genFarFarLogicOp(ic, "anl");
4918 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4920 AOP_TYPE (left), AOP_TYPE (right));
4921 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4923 AOP_SIZE (left), AOP_SIZE (right));
4926 /* if left is a literal & right is not then exchange them */
4927 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4928 AOP_NEEDSACC (left))
4930 operand *tmp = right;
4935 /* if result = right then exchange them */
4936 if (sameRegs (AOP (result), AOP (right)))
4938 operand *tmp = right;
4943 /* if right is bit then exchange them */
4944 if (AOP_TYPE (right) == AOP_CRY &&
4945 AOP_TYPE (left) != AOP_CRY)
4947 operand *tmp = right;
4951 if (AOP_TYPE (right) == AOP_LIT)
4952 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4954 size = AOP_SIZE (result);
4957 // result = bit & yy;
4958 if (AOP_TYPE (left) == AOP_CRY)
4960 // c = bit & literal;
4961 if (AOP_TYPE (right) == AOP_LIT)
4965 if (size && sameRegs (AOP (result), AOP (left)))
4968 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4973 if (size && (AOP_TYPE (result) == AOP_CRY))
4975 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4978 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4983 emitcode ("clr", "c");
4988 if (AOP_TYPE (right) == AOP_CRY)
4991 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4992 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4997 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4999 emitcode ("rrc", "a");
5000 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5008 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5009 genIfxJump (ifx, "c");
5013 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5014 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5015 if ((AOP_TYPE (right) == AOP_LIT) &&
5016 (AOP_TYPE (result) == AOP_CRY) &&
5017 (AOP_TYPE (left) != AOP_CRY))
5019 int posbit = isLiteralBit (lit);
5024 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5027 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5033 sprintf (buffer, "acc.%d", posbit & 0x07);
5034 genIfxJump (ifx, buffer);
5041 symbol *tlbl = newiTempLabel (NULL);
5042 int sizel = AOP_SIZE (left);
5044 emitcode ("setb", "c");
5047 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5049 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5051 if ((posbit = isLiteralBit (bytelit)) != 0)
5052 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5055 if (bytelit != 0x0FFL)
5056 emitcode ("anl", "a,%s",
5057 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5058 emitcode ("jnz", "%05d$", tlbl->key + 100);
5063 // bit = left & literal
5066 emitcode ("clr", "c");
5067 emitcode ("", "%05d$:", tlbl->key + 100);
5069 // if(left & literal)
5073 jmpTrueOrFalse (ifx, tlbl);
5081 /* if left is same as result */
5082 if (sameRegs (AOP (result), AOP (left)))
5084 for (; size--; offset++)
5086 if (AOP_TYPE (right) == AOP_LIT)
5088 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5090 else if (bytelit == 0)
5091 aopPut (AOP (result), zero, offset);
5092 else if (IS_AOP_PREG (result))
5094 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5095 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5096 aopPut (AOP (result), "a", offset);
5099 emitcode ("anl", "%s,%s",
5100 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5101 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5105 if (AOP_TYPE (left) == AOP_ACC)
5106 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5109 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5110 if (IS_AOP_PREG (result))
5112 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5113 aopPut (AOP (result), "a", offset);
5117 emitcode ("anl", "%s,a",
5118 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5125 // left & result in different registers
5126 if (AOP_TYPE (result) == AOP_CRY)
5129 // if(size), result in bit
5130 // if(!size && ifx), conditional oper: if(left & right)
5131 symbol *tlbl = newiTempLabel (NULL);
5132 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5134 emitcode ("setb", "c");
5137 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5138 emitcode ("anl", "a,%s",
5139 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5140 emitcode ("jnz", "%05d$", tlbl->key + 100);
5146 emitcode ("", "%05d$:", tlbl->key + 100);
5150 jmpTrueOrFalse (ifx, tlbl);
5154 for (; (size--); offset++)
5157 // result = left & right
5158 if (AOP_TYPE (right) == AOP_LIT)
5160 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5162 aopPut (AOP (result),
5163 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5167 else if (bytelit == 0)
5169 aopPut (AOP (result), zero, offset);
5172 D (emitcode (";", "better literal AND.");
5174 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5175 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5176 FALSE, FALSE, FALSE));
5181 // faster than result <- left, anl result,right
5182 // and better if result is SFR
5183 if (AOP_TYPE (left) == AOP_ACC)
5185 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5186 FALSE, FALSE, FALSE));
5190 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5191 emitcode ("anl", "a,%s",
5192 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5195 aopPut (AOP (result), "a", offset);
5201 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5202 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5203 freeAsmop (result, NULL, ic, TRUE);
5207 /*-----------------------------------------------------------------*/
5208 /* genOr - code for or */
5209 /*-----------------------------------------------------------------*/
5211 genOr (iCode * ic, iCode * ifx)
5213 operand *left, *right, *result;
5214 int size, offset = 0;
5215 unsigned long lit = 0L;
5218 D (emitcode (";", "genOr "););
5220 AOP_OP_3_NOFATAL (ic, pushResult);
5221 AOP_SET_LOCALS (ic);
5225 genFarFarLogicOp(ic, "orl");
5231 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5233 AOP_TYPE (left), AOP_TYPE (right));
5234 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5236 AOP_SIZE (left), AOP_SIZE (right));
5239 /* if left is a literal & right is not then exchange them */
5240 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5241 AOP_NEEDSACC (left))
5243 operand *tmp = right;
5248 /* if result = right then exchange them */
5249 if (sameRegs (AOP (result), AOP (right)))
5251 operand *tmp = right;
5256 /* if right is bit then exchange them */
5257 if (AOP_TYPE (right) == AOP_CRY &&
5258 AOP_TYPE (left) != AOP_CRY)
5260 operand *tmp = right;
5264 if (AOP_TYPE (right) == AOP_LIT)
5265 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5267 size = AOP_SIZE (result);
5271 if (AOP_TYPE (left) == AOP_CRY)
5273 if (AOP_TYPE (right) == AOP_LIT)
5275 // c = bit & literal;
5278 // lit != 0 => result = 1
5279 if (AOP_TYPE (result) == AOP_CRY)
5282 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5284 continueIfTrue (ifx);
5287 emitcode ("setb", "c");
5291 // lit == 0 => result = left
5292 if (size && sameRegs (AOP (result), AOP (left)))
5294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5299 if (AOP_TYPE (right) == AOP_CRY)
5302 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5303 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5308 symbol *tlbl = newiTempLabel (NULL);
5309 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5310 emitcode ("setb", "c");
5311 emitcode ("jb", "%s,%05d$",
5312 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5314 emitcode ("jnz", "%05d$", tlbl->key + 100);
5315 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5317 jmpTrueOrFalse (ifx, tlbl);
5323 emitcode ("", "%05d$:", tlbl->key + 100);
5332 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5333 genIfxJump (ifx, "c");
5337 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5338 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5339 if ((AOP_TYPE (right) == AOP_LIT) &&
5340 (AOP_TYPE (result) == AOP_CRY) &&
5341 (AOP_TYPE (left) != AOP_CRY))
5347 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5349 continueIfTrue (ifx);
5354 // lit = 0, result = boolean(left)
5356 emitcode ("setb", "c");
5360 symbol *tlbl = newiTempLabel (NULL);
5361 emitcode ("jnz", "%05d$", tlbl->key + 100);
5363 emitcode ("", "%05d$:", tlbl->key + 100);
5367 genIfxJump (ifx, "a");
5375 /* if left is same as result */
5376 if (sameRegs (AOP (result), AOP (left)))
5378 for (; size--; offset++)
5380 if (AOP_TYPE (right) == AOP_LIT)
5382 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5388 if (IS_AOP_PREG (left))
5390 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5391 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5392 aopPut (AOP (result), "a", offset);
5396 emitcode ("orl", "%s,%s",
5397 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5398 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5404 if (AOP_TYPE (left) == AOP_ACC)
5406 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5410 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5411 if (IS_AOP_PREG (left))
5413 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5414 aopPut (AOP (result), "a", offset);
5418 emitcode ("orl", "%s,a",
5419 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5427 // left & result in different registers
5428 if (AOP_TYPE (result) == AOP_CRY)
5431 // if(size), result in bit
5432 // if(!size && ifx), conditional oper: if(left | right)
5433 symbol *tlbl = newiTempLabel (NULL);
5434 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5436 emitcode ("setb", "c");
5439 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5440 emitcode ("orl", "a,%s",
5441 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5442 emitcode ("jnz", "%05d$", tlbl->key + 100);
5448 emitcode ("", "%05d$:", tlbl->key + 100);
5452 jmpTrueOrFalse (ifx, tlbl);
5456 for (; (size--); offset++)
5459 // result = left & right
5460 if (AOP_TYPE (right) == AOP_LIT)
5462 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5464 aopPut (AOP (result),
5465 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5469 D (emitcode (";", "better literal OR.");
5471 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5472 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5473 FALSE, FALSE, FALSE));
5478 // faster than result <- left, anl result,right
5479 // and better if result is SFR
5480 if (AOP_TYPE (left) == AOP_ACC)
5482 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5483 FALSE, FALSE, FALSE));
5487 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5488 emitcode ("orl", "a,%s",
5489 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5492 aopPut (AOP (result), "a", offset);
5498 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5499 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5500 freeAsmop (result, NULL, ic, TRUE);
5503 /*-----------------------------------------------------------------*/
5504 /* genXor - code for xclusive or */
5505 /*-----------------------------------------------------------------*/
5507 genXor (iCode * ic, iCode * ifx)
5509 operand *left, *right, *result;
5510 int size, offset = 0;
5511 unsigned long lit = 0L;
5514 D (emitcode (";", "genXor "););
5516 AOP_OP_3_NOFATAL (ic, pushResult);
5517 AOP_SET_LOCALS (ic);
5521 genFarFarLogicOp(ic, "xrl");
5526 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5528 AOP_TYPE (left), AOP_TYPE (right));
5529 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5531 AOP_SIZE (left), AOP_SIZE (right));
5534 /* if left is a literal & right is not ||
5535 if left needs acc & right does not */
5536 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5537 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5539 operand *tmp = right;
5544 /* if result = right then exchange them */
5545 if (sameRegs (AOP (result), AOP (right)))
5547 operand *tmp = right;
5552 /* if right is bit then exchange them */
5553 if (AOP_TYPE (right) == AOP_CRY &&
5554 AOP_TYPE (left) != AOP_CRY)
5556 operand *tmp = right;
5560 if (AOP_TYPE (right) == AOP_LIT)
5561 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5563 size = AOP_SIZE (result);
5567 if (AOP_TYPE (left) == AOP_CRY)
5569 if (AOP_TYPE (right) == AOP_LIT)
5571 // c = bit & literal;
5574 // lit>>1 != 0 => result = 1
5575 if (AOP_TYPE (result) == AOP_CRY)
5578 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5580 continueIfTrue (ifx);
5583 emitcode ("setb", "c");
5590 // lit == 0, result = left
5591 if (size && sameRegs (AOP (result), AOP (left)))
5593 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5597 // lit == 1, result = not(left)
5598 if (size && sameRegs (AOP (result), AOP (left)))
5600 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5605 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5606 emitcode ("cpl", "c");
5615 symbol *tlbl = newiTempLabel (NULL);
5616 if (AOP_TYPE (right) == AOP_CRY)
5619 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5623 int sizer = AOP_SIZE (right);
5625 // if val>>1 != 0, result = 1
5626 emitcode ("setb", "c");
5629 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5631 // test the msb of the lsb
5632 emitcode ("anl", "a,#0xfe");
5633 emitcode ("jnz", "%05d$", tlbl->key + 100);
5637 emitcode ("rrc", "a");
5639 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5640 emitcode ("cpl", "c");
5641 emitcode ("", "%05d$:", (tlbl->key + 100));
5648 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5649 genIfxJump (ifx, "c");
5653 if (sameRegs (AOP (result), AOP (left)))
5655 /* if left is same as result */
5656 for (; size--; offset++)
5658 if (AOP_TYPE (right) == AOP_LIT)
5660 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5662 else if (IS_AOP_PREG (left))
5664 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5665 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5666 aopPut (AOP (result), "a", offset);
5669 emitcode ("xrl", "%s,%s",
5670 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5671 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5675 if (AOP_TYPE (left) == AOP_ACC)
5676 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5679 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5680 if (IS_AOP_PREG (left))
5682 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5683 aopPut (AOP (result), "a", offset);
5686 emitcode ("xrl", "%s,a",
5687 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5694 // left & result in different registers
5695 if (AOP_TYPE (result) == AOP_CRY)
5698 // if(size), result in bit
5699 // if(!size && ifx), conditional oper: if(left ^ right)
5700 symbol *tlbl = newiTempLabel (NULL);
5701 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5703 emitcode ("setb", "c");
5706 if ((AOP_TYPE (right) == AOP_LIT) &&
5707 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5709 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5713 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5714 emitcode ("xrl", "a,%s",
5715 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5717 emitcode ("jnz", "%05d$", tlbl->key + 100);
5723 emitcode ("", "%05d$:", tlbl->key + 100);
5727 jmpTrueOrFalse (ifx, tlbl);
5730 for (; (size--); offset++)
5733 // result = left & right
5734 if (AOP_TYPE (right) == AOP_LIT)
5736 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5738 aopPut (AOP (result),
5739 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5743 D (emitcode (";", "better literal XOR.");
5745 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5746 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5747 FALSE, FALSE, FALSE));
5751 // faster than result <- left, anl result,right
5752 // and better if result is SFR
5753 if (AOP_TYPE (left) == AOP_ACC)
5755 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5756 FALSE, FALSE, FALSE));
5760 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5761 emitcode ("xrl", "a,%s",
5762 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5765 aopPut (AOP (result), "a", offset);
5770 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5771 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5772 freeAsmop (result, NULL, ic, TRUE);
5775 /*-----------------------------------------------------------------*/
5776 /* genInline - write the inline code out */
5777 /*-----------------------------------------------------------------*/
5779 genInline (iCode * ic)
5781 char buffer[MAX_INLINEASM];
5785 D (emitcode (";", "genInline ");
5788 _G.inLine += (!options.asmpeep);
5789 strcpy (buffer, IC_INLINE (ic));
5791 /* emit each line as a code */
5816 /* emitcode("",buffer); */
5817 _G.inLine -= (!options.asmpeep);
5820 /*-----------------------------------------------------------------*/
5821 /* genRRC - rotate right with carry */
5822 /*-----------------------------------------------------------------*/
5826 operand *left, *result;
5827 int size, offset = 0;
5830 D (emitcode (";", "genRRC ");
5833 /* rotate right with carry */
5834 left = IC_LEFT (ic);
5835 result = IC_RESULT (ic);
5836 aopOp (left, ic, FALSE, FALSE);
5837 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5839 /* move it to the result */
5840 size = AOP_SIZE (result);
5844 _startLazyDPSEvaluation ();
5847 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5849 emitcode ("rrc", "a");
5850 if (AOP_SIZE (result) > 1)
5851 aopPut (AOP (result), "a", offset--);
5853 _endLazyDPSEvaluation ();
5855 /* now we need to put the carry into the
5856 highest order byte of the result */
5857 if (AOP_SIZE (result) > 1)
5859 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5862 emitcode ("mov", "acc.7,c");
5863 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5864 freeAsmop (left, NULL, ic, TRUE);
5865 freeAsmop (result, NULL, ic, TRUE);
5868 /*-----------------------------------------------------------------*/
5869 /* genRLC - generate code for rotate left with carry */
5870 /*-----------------------------------------------------------------*/
5874 operand *left, *result;
5875 int size, offset = 0;
5878 D (emitcode (";", "genRLC ");
5881 /* rotate right with carry */
5882 left = IC_LEFT (ic);
5883 result = IC_RESULT (ic);
5884 aopOp (left, ic, FALSE, FALSE);
5885 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5887 /* move it to the result */
5888 size = AOP_SIZE (result);
5892 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5894 emitcode ("add", "a,acc");
5895 if (AOP_SIZE (result) > 1)
5897 aopPut (AOP (result), "a", offset++);
5900 _startLazyDPSEvaluation ();
5903 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5905 emitcode ("rlc", "a");
5906 if (AOP_SIZE (result) > 1)
5907 aopPut (AOP (result), "a", offset++);
5909 _endLazyDPSEvaluation ();
5911 /* now we need to put the carry into the
5912 highest order byte of the result */
5913 if (AOP_SIZE (result) > 1)
5915 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5918 emitcode ("mov", "acc.0,c");
5919 aopPut (AOP (result), "a", 0);
5920 freeAsmop (left, NULL, ic, TRUE);
5921 freeAsmop (result, NULL, ic, TRUE);
5924 /*-----------------------------------------------------------------*/
5925 /* genGetHbit - generates code get highest order bit */
5926 /*-----------------------------------------------------------------*/
5928 genGetHbit (iCode * ic)
5930 operand *left, *result;
5931 left = IC_LEFT (ic);
5932 result = IC_RESULT (ic);
5933 aopOp (left, ic, FALSE, FALSE);
5934 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5936 D (emitcode (";", "genGetHbit ");
5939 /* get the highest order byte into a */
5940 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5941 if (AOP_TYPE (result) == AOP_CRY)
5943 emitcode ("rlc", "a");
5948 emitcode ("rl", "a");
5949 emitcode ("anl", "a,#0x01");
5954 freeAsmop (left, NULL, ic, TRUE);
5955 freeAsmop (result, NULL, ic, TRUE);
5958 /*-----------------------------------------------------------------*/
5959 /* AccRol - rotate left accumulator by known count */
5960 /*-----------------------------------------------------------------*/
5962 AccRol (int shCount)
5964 shCount &= 0x0007; // shCount : 0..7
5971 emitcode ("rl", "a");
5974 emitcode ("rl", "a");
5975 emitcode ("rl", "a");
5978 emitcode ("swap", "a");
5979 emitcode ("rr", "a");
5982 emitcode ("swap", "a");
5985 emitcode ("swap", "a");
5986 emitcode ("rl", "a");
5989 emitcode ("rr", "a");
5990 emitcode ("rr", "a");
5993 emitcode ("rr", "a");
5998 /*-----------------------------------------------------------------*/
5999 /* AccLsh - left shift accumulator by known count */
6000 /*-----------------------------------------------------------------*/
6002 AccLsh (int shCount)
6007 emitcode ("add", "a,acc");
6008 else if (shCount == 2)
6010 emitcode ("add", "a,acc");
6011 emitcode ("add", "a,acc");
6015 /* rotate left accumulator */
6017 /* and kill the lower order bits */
6018 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6023 /*-----------------------------------------------------------------*/
6024 /* AccRsh - right shift accumulator by known count */
6025 /*-----------------------------------------------------------------*/
6027 AccRsh (int shCount)
6034 emitcode ("rrc", "a");
6038 /* rotate right accumulator */
6039 AccRol (8 - shCount);
6040 /* and kill the higher order bits */
6041 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6046 #ifdef BETTER_LITERAL_SHIFT
6047 /*-----------------------------------------------------------------*/
6048 /* AccSRsh - signed right shift accumulator by known count */
6049 /*-----------------------------------------------------------------*/
6051 AccSRsh (int shCount)
6058 emitcode ("mov", "c,acc.7");
6059 emitcode ("rrc", "a");
6061 else if (shCount == 2)
6063 emitcode ("mov", "c,acc.7");
6064 emitcode ("rrc", "a");
6065 emitcode ("mov", "c,acc.7");
6066 emitcode ("rrc", "a");
6070 tlbl = newiTempLabel (NULL);
6071 /* rotate right accumulator */
6072 AccRol (8 - shCount);
6073 /* and kill the higher order bits */
6074 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6075 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6076 emitcode ("orl", "a,#0x%02x",
6077 (unsigned char) ~SRMask[shCount]);
6078 emitcode ("", "%05d$:", tlbl->key + 100);
6084 #ifdef BETTER_LITERAL_SHIFT
6085 /*-----------------------------------------------------------------*/
6086 /* shiftR1Left2Result - shift right one byte from left to result */
6087 /*-----------------------------------------------------------------*/
6089 shiftR1Left2Result (operand * left, int offl,
6090 operand * result, int offr,
6091 int shCount, int sign)
6093 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6094 /* shift right accumulator */
6099 aopPut (AOP (result), "a", offr);
6103 #ifdef BETTER_LITERAL_SHIFT
6104 /*-----------------------------------------------------------------*/
6105 /* shiftL1Left2Result - shift left one byte from left to result */
6106 /*-----------------------------------------------------------------*/
6108 shiftL1Left2Result (operand * left, int offl,
6109 operand * result, int offr, int shCount)
6111 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6112 /* shift left accumulator */
6114 aopPut (AOP (result), "a", offr);
6118 #ifdef BETTER_LITERAL_SHIFT
6119 /*-----------------------------------------------------------------*/
6120 /* movLeft2Result - move byte from left to result */
6121 /*-----------------------------------------------------------------*/
6123 movLeft2Result (operand * left, int offl,
6124 operand * result, int offr, int sign)
6127 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6129 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6131 if (*l == '@' && (IS_AOP_PREG (result)))
6133 emitcode ("mov", "a,%s", l);
6134 aopPut (AOP (result), "a", offr);
6140 aopPut (AOP (result), l, offr);
6144 /* MSB sign in acc.7 ! */
6145 if (getDataSize (left) == offl + 1)
6147 emitcode ("mov", "a,%s", l);
6148 aopPut (AOP (result), "a", offr);
6156 #ifdef BETTER_LITERAL_SHIFT
6157 /*-----------------------------------------------------------------*/
6158 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6159 /*-----------------------------------------------------------------*/
6163 emitcode ("rrc", "a");
6164 emitcode ("xch", "a,%s", x);
6165 emitcode ("rrc", "a");
6166 emitcode ("xch", "a,%s", x);
6170 #ifdef BETTER_LITERAL_SHIFT
6172 /*-----------------------------------------------------------------*/
6173 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6174 /*-----------------------------------------------------------------*/
6178 emitcode ("xch", "a,%s", x);
6179 emitcode ("rlc", "a");
6180 emitcode ("xch", "a,%s", x);
6181 emitcode ("rlc", "a");
6185 #ifdef BETTER_LITERAL_SHIFT
6186 /*-----------------------------------------------------------------*/
6187 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6188 /*-----------------------------------------------------------------*/
6192 emitcode ("xch", "a,%s", x);
6193 emitcode ("add", "a,acc");
6194 emitcode ("xch", "a,%s", x);
6195 emitcode ("rlc", "a");
6199 #ifdef BETTER_LITERAL_SHIFT
6200 /*-----------------------------------------------------------------*/
6201 /* AccAXLsh - left shift a:x by known count (0..7) */
6202 /*-----------------------------------------------------------------*/
6204 AccAXLsh (char *x, int shCount)
6219 case 5: // AAAAABBB:CCCCCDDD
6221 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6223 emitcode ("anl", "a,#0x%02x",
6224 SLMask[shCount]); // BBB00000:CCCCCDDD
6226 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6228 AccRol (shCount); // DDDCCCCC:BBB00000
6230 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6232 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6234 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6236 emitcode ("anl", "a,#0x%02x",
6237 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6239 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6241 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6244 case 6: // AAAAAABB:CCCCCCDD
6245 emitcode ("anl", "a,#0x%02x",
6246 SRMask[shCount]); // 000000BB:CCCCCCDD
6247 emitcode ("mov", "c,acc.0"); // c = B
6248 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6250 AccAXRrl1 (x); // BCCCCCCD:D000000B
6251 AccAXRrl1 (x); // BBCCCCCC:DD000000
6253 emitcode("rrc","a");
6254 emitcode("xch","a,%s", x);
6255 emitcode("rrc","a");
6256 emitcode("mov","c,acc.0"); //<< get correct bit
6257 emitcode("xch","a,%s", x);
6259 emitcode("rrc","a");
6260 emitcode("xch","a,%s", x);
6261 emitcode("rrc","a");
6262 emitcode("xch","a,%s", x);
6265 case 7: // a:x <<= 7
6267 emitcode ("anl", "a,#0x%02x",
6268 SRMask[shCount]); // 0000000B:CCCCCCCD
6270 emitcode ("mov", "c,acc.0"); // c = B
6272 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6274 AccAXRrl1 (x); // BCCCCCCC:D0000000
6283 #ifdef BETTER_LITERAL_SHIFT
6285 /*-----------------------------------------------------------------*/
6286 /* AccAXRsh - right shift a:x known count (0..7) */
6287 /*-----------------------------------------------------------------*/
6289 AccAXRsh (char *x, int shCount)
6297 AccAXRrl1 (x); // 0->a:x
6302 AccAXRrl1 (x); // 0->a:x
6305 AccAXRrl1 (x); // 0->a:x
6310 case 5: // AAAAABBB:CCCCCDDD = a:x
6312 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6314 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6316 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6318 emitcode ("anl", "a,#0x%02x",
6319 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6321 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6323 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6325 emitcode ("anl", "a,#0x%02x",
6326 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6328 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6330 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6332 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6335 case 6: // AABBBBBB:CCDDDDDD
6337 emitcode ("mov", "c,acc.7");
6338 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6340 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6342 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6344 emitcode ("anl", "a,#0x%02x",
6345 SRMask[shCount]); // 000000AA:BBBBBBCC
6348 case 7: // ABBBBBBB:CDDDDDDD
6350 emitcode ("mov", "c,acc.7"); // c = A
6352 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6354 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6356 emitcode ("anl", "a,#0x%02x",
6357 SRMask[shCount]); // 0000000A:BBBBBBBC
6366 #ifdef BETTER_LITERAL_SHIFT
6368 /*-----------------------------------------------------------------*/
6369 /* AccAXRshS - right shift signed a:x known count (0..7) */
6370 /*-----------------------------------------------------------------*/
6372 AccAXRshS (char *x, int shCount)
6380 emitcode ("mov", "c,acc.7");
6381 AccAXRrl1 (x); // s->a:x
6385 emitcode ("mov", "c,acc.7");
6386 AccAXRrl1 (x); // s->a:x
6388 emitcode ("mov", "c,acc.7");
6389 AccAXRrl1 (x); // s->a:x
6394 case 5: // AAAAABBB:CCCCCDDD = a:x
6396 tlbl = newiTempLabel (NULL);
6397 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6399 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6401 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6403 emitcode ("anl", "a,#0x%02x",
6404 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6406 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6408 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6410 emitcode ("anl", "a,#0x%02x",
6411 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6413 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6415 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6417 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6419 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6420 emitcode ("orl", "a,#0x%02x",
6421 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6423 emitcode ("", "%05d$:", tlbl->key + 100);
6424 break; // SSSSAAAA:BBBCCCCC
6426 case 6: // AABBBBBB:CCDDDDDD
6428 tlbl = newiTempLabel (NULL);
6429 emitcode ("mov", "c,acc.7");
6430 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6432 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6434 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6436 emitcode ("anl", "a,#0x%02x",
6437 SRMask[shCount]); // 000000AA:BBBBBBCC
6439 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6440 emitcode ("orl", "a,#0x%02x",
6441 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6443 emitcode ("", "%05d$:", tlbl->key + 100);
6445 case 7: // ABBBBBBB:CDDDDDDD
6447 tlbl = newiTempLabel (NULL);
6448 emitcode ("mov", "c,acc.7"); // c = A
6450 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6452 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6454 emitcode ("anl", "a,#0x%02x",
6455 SRMask[shCount]); // 0000000A:BBBBBBBC
6457 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6458 emitcode ("orl", "a,#0x%02x",
6459 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6461 emitcode ("", "%05d$:", tlbl->key + 100);
6469 #ifdef BETTER_LITERAL_SHIFT
6471 _loadLeftIntoAx(char **lsb,
6477 // Get the initial value from left into a pair of registers.
6478 // MSB must be in A, LSB can be any register.
6480 // If the result is held in registers, it is an optimization
6481 // if the LSB can be held in the register which will hold the,
6482 // result LSB since this saves us from having to copy it into
6483 // the result following AccAXLsh.
6485 // If the result is addressed indirectly, this is not a gain.
6486 if (AOP_NEEDSACC(result))
6490 _startLazyDPSEvaluation();
6491 if (AOP_TYPE(left) == AOP_DPTR2)
6494 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6495 // get LSB in DP2_RESULT_REG.
6496 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6497 assert(!strcmp(leftByte, DP2_RESULT_REG));
6501 // get LSB into DP2_RESULT_REG
6502 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6503 if (strcmp(leftByte, DP2_RESULT_REG))
6505 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6508 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6509 assert(strcmp(leftByte, DP2_RESULT_REG));
6512 _endLazyDPSEvaluation();
6513 *lsb = DP2_RESULT_REG;
6517 if (sameRegs (AOP (result), AOP (left)) &&
6518 ((offl + MSB16) == offr))
6520 /* don't crash result[offr] */
6521 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6522 emitcode ("xch", "a,%s",
6523 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6527 movLeft2Result (left, offl, result, offr, 0);
6528 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6530 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6531 assert(strcmp(*lsb,"a"));
6536 _storeAxResults(char *lsb,
6540 _startLazyDPSEvaluation();
6541 if (AOP_NEEDSACC(result))
6543 /* We have to explicitly update the result LSB.
6545 emitcode("xch","a,%s", lsb);
6546 aopPut(AOP(result), "a", offr);
6547 emitcode("mov","a,%s", lsb);
6549 if (getDataSize (result) > 1)
6551 aopPut (AOP (result), "a", offr + MSB16);
6553 _endLazyDPSEvaluation();
6556 /*-----------------------------------------------------------------*/
6557 /* shiftL2Left2Result - shift left two bytes from left to result */
6558 /*-----------------------------------------------------------------*/
6560 shiftL2Left2Result (operand * left, int offl,
6561 operand * result, int offr, int shCount)
6565 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6567 AccAXLsh (lsb, shCount);
6569 _storeAxResults(lsb, result, offr);
6573 #ifdef BETTER_LITERAL_SHIFT
6574 /*-----------------------------------------------------------------*/
6575 /* shiftR2Left2Result - shift right two bytes from left to result */
6576 /*-----------------------------------------------------------------*/
6578 shiftR2Left2Result (operand * left, int offl,
6579 operand * result, int offr,
6580 int shCount, int sign)
6584 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6586 /* a:x >> shCount (x = lsb(result)) */
6589 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6593 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6596 _storeAxResults(lsb, result, offr);
6602 /*-----------------------------------------------------------------*/
6603 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6604 /*-----------------------------------------------------------------*/
6606 shiftLLeftOrResult (operand * left, int offl,
6607 operand * result, int offr, int shCount)
6609 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6610 /* shift left accumulator */
6612 /* or with result */
6613 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6614 /* back to result */
6615 aopPut (AOP (result), "a", offr);
6621 /*-----------------------------------------------------------------*/
6622 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6623 /*-----------------------------------------------------------------*/
6625 shiftRLeftOrResult (operand * left, int offl,
6626 operand * result, int offr, int shCount)
6628 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6629 /* shift right accumulator */
6631 /* or with result */
6632 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6633 /* back to result */
6634 aopPut (AOP (result), "a", offr);
6638 #ifdef BETTER_LITERAL_SHIFT
6639 /*-----------------------------------------------------------------*/
6640 /* genlshOne - left shift a one byte quantity by known count */
6641 /*-----------------------------------------------------------------*/
6643 genlshOne (operand * result, operand * left, int shCount)
6645 D (emitcode (";", "genlshOne "););
6646 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6650 #ifdef BETTER_LITERAL_SHIFT
6651 /*-----------------------------------------------------------------*/
6652 /* genlshTwo - left shift two bytes by known amount != 0 */
6653 /*-----------------------------------------------------------------*/
6655 genlshTwo (operand * result, operand * left, int shCount)
6659 D (emitcode (";", "genlshTwo "););
6661 size = getDataSize (result);
6663 /* if shCount >= 8 */
6668 _startLazyDPSEvaluation();
6674 _endLazyDPSEvaluation();
6675 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6676 aopPut (AOP (result), zero, LSB);
6680 movLeft2Result (left, LSB, result, MSB16, 0);
6681 aopPut (AOP (result), zero, LSB);
6682 _endLazyDPSEvaluation();
6687 aopPut (AOP (result), zero, LSB);
6688 _endLazyDPSEvaluation();
6692 /* 1 <= shCount <= 7 */
6697 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6701 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6709 /*-----------------------------------------------------------------*/
6710 /* shiftLLong - shift left one long from left to result */
6711 /* offl = LSB or MSB16 */
6712 /*-----------------------------------------------------------------*/
6714 shiftLLong (operand * left, operand * result, int offr)
6717 int size = AOP_SIZE (result);
6719 if (size >= LSB + offr)
6721 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6723 emitcode ("add", "a,acc");
6724 if (sameRegs (AOP (left), AOP (result)) &&
6725 size >= MSB16 + offr && offr != LSB)
6726 emitcode ("xch", "a,%s",
6727 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6729 aopPut (AOP (result), "a", LSB + offr);
6732 if (size >= MSB16 + offr)
6734 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6736 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6739 emitcode ("rlc", "a");
6740 if (sameRegs (AOP (left), AOP (result)) &&
6741 size >= MSB24 + offr && offr != LSB)
6742 emitcode ("xch", "a,%s",
6743 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6745 aopPut (AOP (result), "a", MSB16 + offr);
6748 if (size >= MSB24 + offr)
6750 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6752 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6755 emitcode ("rlc", "a");
6756 if (sameRegs (AOP (left), AOP (result)) &&
6757 size >= MSB32 + offr && offr != LSB)
6758 emitcode ("xch", "a,%s",
6759 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6761 aopPut (AOP (result), "a", MSB24 + offr);
6764 if (size > MSB32 + offr)
6766 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6768 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6771 emitcode ("rlc", "a");
6772 aopPut (AOP (result), "a", MSB32 + offr);
6775 aopPut (AOP (result), zero, LSB);
6781 /*-----------------------------------------------------------------*/
6782 /* genlshFour - shift four byte by a known amount != 0 */
6783 /*-----------------------------------------------------------------*/
6785 genlshFour (operand * result, operand * left, int shCount)
6789 D (emitcode (";", "genlshFour ");
6792 size = AOP_SIZE (result);
6794 /* if shifting more that 3 bytes */
6799 /* lowest order of left goes to the highest
6800 order of the destination */
6801 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6803 movLeft2Result (left, LSB, result, MSB32, 0);
6804 aopPut (AOP (result), zero, LSB);
6805 aopPut (AOP (result), zero, MSB16);
6806 aopPut (AOP (result), zero, MSB24);
6810 /* more than two bytes */
6811 else if (shCount >= 16)
6813 /* lower order two bytes goes to higher order two bytes */
6815 /* if some more remaining */
6817 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6820 movLeft2Result (left, MSB16, result, MSB32, 0);
6821 movLeft2Result (left, LSB, result, MSB24, 0);
6823 aopPut (AOP (result), zero, MSB16);
6824 aopPut (AOP (result), zero, LSB);
6828 /* if more than 1 byte */
6829 else if (shCount >= 8)
6831 /* lower order three bytes goes to higher order three bytes */
6836 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6838 movLeft2Result (left, LSB, result, MSB16, 0);
6844 movLeft2Result (left, MSB24, result, MSB32, 0);
6845 movLeft2Result (left, MSB16, result, MSB24, 0);
6846 movLeft2Result (left, LSB, result, MSB16, 0);
6847 aopPut (AOP (result), zero, LSB);
6849 else if (shCount == 1)
6850 shiftLLong (left, result, MSB16);
6853 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6854 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6855 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6856 aopPut (AOP (result), zero, LSB);
6861 /* 1 <= shCount <= 7 */
6862 else if (shCount <= 2)
6864 shiftLLong (left, result, LSB);
6866 shiftLLong (result, result, LSB);
6868 /* 3 <= shCount <= 7, optimize */
6871 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6872 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6873 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6878 #ifdef BETTER_LITERAL_SHIFT
6879 /*-----------------------------------------------------------------*/
6880 /* genLeftShiftLiteral - left shifting by known count */
6881 /*-----------------------------------------------------------------*/
6883 genLeftShiftLiteral (operand * left,
6888 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6891 size = getSize (operandType (result));
6893 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6895 /* We only handle certain easy cases so far. */
6897 && (shCount < (size * 8))
6901 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6905 freeAsmop (right, NULL, ic, TRUE);
6907 aopOp(left, ic, FALSE, FALSE);
6908 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6911 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6913 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6914 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6916 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6919 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6921 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6922 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6924 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6930 emitcode ("; shift left ", "result %d, left %d", size,
6934 /* I suppose that the left size >= result size */
6937 _startLazyDPSEvaluation();
6940 movLeft2Result (left, size, result, size, 0);
6942 _endLazyDPSEvaluation();
6944 else if (shCount >= (size * 8))
6946 _startLazyDPSEvaluation();
6949 aopPut (AOP (result), zero, size);
6951 _endLazyDPSEvaluation();
6958 genlshOne (result, left, shCount);
6962 genlshTwo (result, left, shCount);
6966 genlshFour (result, left, shCount);
6970 fprintf(stderr, "*** ack! mystery literal shift!\n");
6974 freeAsmop (left, NULL, ic, TRUE);
6975 freeAsmop (result, NULL, ic, TRUE);
6980 /*-----------------------------------------------------------------*/
6981 /* genLeftShift - generates code for left shifting */
6982 /*-----------------------------------------------------------------*/
6984 genLeftShift (iCode * ic)
6986 operand *left, *right, *result;
6989 symbol *tlbl, *tlbl1;
6991 D (emitcode (";", "genLeftShift "););
6993 right = IC_RIGHT (ic);
6994 left = IC_LEFT (ic);
6995 result = IC_RESULT (ic);
6997 aopOp (right, ic, FALSE, FALSE);
7000 #ifdef BETTER_LITERAL_SHIFT
7001 /* if the shift count is known then do it
7002 as efficiently as possible */
7003 if (AOP_TYPE (right) == AOP_LIT)
7005 if (genLeftShiftLiteral (left, right, result, ic))
7012 /* shift count is unknown then we have to form
7013 a loop get the loop count in B : Note: we take
7014 only the lower order byte since shifting
7015 more that 32 bits make no sense anyway, ( the
7016 largest size of an object can be only 32 bits ) */
7018 if (AOP_TYPE (right) == AOP_LIT)
7020 /* Really should be handled by genLeftShiftLiteral,
7021 * but since I'm too lazy to fix that today, at least we can make
7022 * some small improvement.
7024 emitcode("mov", "b,#0x%02x",
7025 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7029 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7030 emitcode ("inc", "b");
7032 freeAsmop (right, NULL, ic, TRUE);
7033 aopOp (left, ic, FALSE, FALSE);
7034 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7036 /* now move the left to the result if they are not the
7038 if (!sameRegs (AOP (left), AOP (result)) &&
7039 AOP_SIZE (result) > 1)
7042 size = AOP_SIZE (result);
7044 _startLazyDPSEvaluation ();
7047 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7048 if (*l == '@' && (IS_AOP_PREG (result)))
7051 emitcode ("mov", "a,%s", l);
7052 aopPut (AOP (result), "a", offset);
7055 aopPut (AOP (result), l, offset);
7058 _endLazyDPSEvaluation ();
7061 tlbl = newiTempLabel (NULL);
7062 size = AOP_SIZE (result);
7064 tlbl1 = newiTempLabel (NULL);
7066 /* if it is only one byte then */
7069 symbol *tlbl1 = newiTempLabel (NULL);
7071 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7073 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7074 emitcode ("", "%05d$:", tlbl->key + 100);
7075 emitcode ("add", "a,acc");
7076 emitcode ("", "%05d$:", tlbl1->key + 100);
7077 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7078 aopPut (AOP (result), "a", 0);
7082 reAdjustPreg (AOP (result));
7084 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7085 emitcode ("", "%05d$:", tlbl->key + 100);
7086 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7088 emitcode ("add", "a,acc");
7089 aopPut (AOP (result), "a", offset++);
7090 _startLazyDPSEvaluation ();
7093 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7095 emitcode ("rlc", "a");
7096 aopPut (AOP (result), "a", offset++);
7098 _endLazyDPSEvaluation ();
7099 reAdjustPreg (AOP (result));
7101 emitcode ("", "%05d$:", tlbl1->key + 100);
7102 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7104 freeAsmop (left, NULL, ic, TRUE);
7105 freeAsmop (result, NULL, ic, TRUE);
7108 #ifdef BETTER_LITERAL_SHIFT
7109 /*-----------------------------------------------------------------*/
7110 /* genrshOne - right shift a one byte quantity by known count */
7111 /*-----------------------------------------------------------------*/
7113 genrshOne (operand * result, operand * left,
7114 int shCount, int sign)
7116 D (emitcode (";", "genrshOne"););
7117 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7121 #ifdef BETTER_LITERAL_SHIFT
7122 /*-----------------------------------------------------------------*/
7123 /* genrshTwo - right shift two bytes by known amount != 0 */
7124 /*-----------------------------------------------------------------*/
7126 genrshTwo (operand * result, operand * left,
7127 int shCount, int sign)
7129 D (emitcode (";", "genrshTwo"););
7131 /* if shCount >= 8 */
7135 _startLazyDPSEvaluation();
7138 shiftR1Left2Result (left, MSB16, result, LSB,
7143 movLeft2Result (left, MSB16, result, LSB, sign);
7145 addSign (result, MSB16, sign);
7146 _endLazyDPSEvaluation();
7149 /* 1 <= shCount <= 7 */
7152 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7159 /*-----------------------------------------------------------------*/
7160 /* shiftRLong - shift right one long from left to result */
7161 /* offl = LSB or MSB16 */
7162 /*-----------------------------------------------------------------*/
7164 shiftRLong (operand * left, int offl,
7165 operand * result, int sign)
7168 emitcode ("clr", "c");
7169 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7171 emitcode ("mov", "c,acc.7");
7172 emitcode ("rrc", "a");
7173 aopPut (AOP (result), "a", MSB32 - offl);
7175 /* add sign of "a" */
7176 addSign (result, MSB32, sign);
7178 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7179 emitcode ("rrc", "a");
7180 aopPut (AOP (result), "a", MSB24 - offl);
7182 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7183 emitcode ("rrc", "a");
7184 aopPut (AOP (result), "a", MSB16 - offl);
7188 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7189 emitcode ("rrc", "a");
7190 aopPut (AOP (result), "a", LSB);
7197 /*-----------------------------------------------------------------*/
7198 /* genrshFour - shift four byte by a known amount != 0 */
7199 /*-----------------------------------------------------------------*/
7201 genrshFour (operand * result, operand * left,
7202 int shCount, int sign)
7204 D (emitcode (";", "genrshFour");
7207 /* if shifting more that 3 bytes */
7212 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7214 movLeft2Result (left, MSB32, result, LSB, sign);
7215 addSign (result, MSB16, sign);
7217 else if (shCount >= 16)
7221 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7224 movLeft2Result (left, MSB24, result, LSB, 0);
7225 movLeft2Result (left, MSB32, result, MSB16, sign);
7227 addSign (result, MSB24, sign);
7229 else if (shCount >= 8)
7233 shiftRLong (left, MSB16, result, sign);
7234 else if (shCount == 0)
7236 movLeft2Result (left, MSB16, result, LSB, 0);
7237 movLeft2Result (left, MSB24, result, MSB16, 0);
7238 movLeft2Result (left, MSB32, result, MSB24, sign);
7239 addSign (result, MSB32, sign);
7243 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7244 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7245 /* the last shift is signed */
7246 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7247 addSign (result, MSB32, sign);
7251 { /* 1 <= shCount <= 7 */
7254 shiftRLong (left, LSB, result, sign);
7256 shiftRLong (result, LSB, result, sign);
7260 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7261 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7262 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7268 #ifdef BETTER_LITERAL_SHIFT
7269 /*-----------------------------------------------------------------*/
7270 /* genRightShiftLiteral - right shifting by known count */
7271 /*-----------------------------------------------------------------*/
7273 genRightShiftLiteral (operand * left,
7279 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7282 size = getSize (operandType (result));
7284 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7286 /* We only handle certain easy cases so far. */
7288 && (shCount < (size * 8))
7292 D(emitcode (";", "genRightShiftLiteral wimping out"););
7296 freeAsmop (right, NULL, ic, TRUE);
7298 aopOp (left, ic, FALSE, FALSE);
7299 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7302 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7306 /* test the LEFT size !!! */
7308 /* I suppose that the left size >= result size */
7311 size = getDataSize (result);
7312 _startLazyDPSEvaluation();
7315 movLeft2Result (left, size, result, size, 0);
7317 _endLazyDPSEvaluation();
7319 else if (shCount >= (size * 8))
7323 /* get sign in acc.7 */
7324 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7326 addSign (result, LSB, sign);
7333 genrshOne (result, left, shCount, sign);
7337 genrshTwo (result, left, shCount, sign);
7341 genrshFour (result, left, shCount, sign);
7348 freeAsmop (left, NULL, ic, TRUE);
7349 freeAsmop (result, NULL, ic, TRUE);
7355 /*-----------------------------------------------------------------*/
7356 /* genSignedRightShift - right shift of signed number */
7357 /*-----------------------------------------------------------------*/
7359 genSignedRightShift (iCode * ic)
7361 operand *right, *left, *result;
7364 symbol *tlbl, *tlbl1;
7366 D (emitcode (";", "genSignedRightShift "););
7368 /* we do it the hard way put the shift count in b
7369 and loop thru preserving the sign */
7371 right = IC_RIGHT (ic);
7372 left = IC_LEFT (ic);
7373 result = IC_RESULT (ic);
7375 aopOp (right, ic, FALSE, FALSE);
7377 #ifdef BETTER_LITERAL_SHIFT
7378 if (AOP_TYPE (right) == AOP_LIT)
7380 if (genRightShiftLiteral (left, right, result, ic, 1))
7386 /* shift count is unknown then we have to form
7387 a loop get the loop count in B : Note: we take
7388 only the lower order byte since shifting
7389 more that 32 bits make no sense anyway, ( the
7390 largest size of an object can be only 32 bits ) */
7392 if (AOP_TYPE (right) == AOP_LIT)
7394 /* Really should be handled by genRightShiftLiteral,
7395 * but since I'm too lazy to fix that today, at least we can make
7396 * some small improvement.
7398 emitcode("mov", "b,#0x%02x",
7399 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7403 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7404 emitcode ("inc", "b");
7406 freeAsmop (right, NULL, ic, TRUE);
7407 aopOp (left, ic, FALSE, FALSE);
7408 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7410 /* now move the left to the result if they are not the
7412 if (!sameRegs (AOP (left), AOP (result)) &&
7413 AOP_SIZE (result) > 1)
7416 size = AOP_SIZE (result);
7418 _startLazyDPSEvaluation ();
7421 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7422 if (*l == '@' && IS_AOP_PREG (result))
7425 emitcode ("mov", "a,%s", l);
7426 aopPut (AOP (result), "a", offset);
7429 aopPut (AOP (result), l, offset);
7432 _endLazyDPSEvaluation ();
7435 /* mov the highest order bit to OVR */
7436 tlbl = newiTempLabel (NULL);
7437 tlbl1 = newiTempLabel (NULL);
7439 size = AOP_SIZE (result);
7441 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7442 emitcode ("rlc", "a");
7443 emitcode ("mov", "ov,c");
7444 /* if it is only one byte then */
7447 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7449 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7450 emitcode ("", "%05d$:", tlbl->key + 100);
7451 emitcode ("mov", "c,ov");
7452 emitcode ("rrc", "a");
7453 emitcode ("", "%05d$:", tlbl1->key + 100);
7454 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7455 aopPut (AOP (result), "a", 0);
7459 reAdjustPreg (AOP (result));
7460 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7461 emitcode ("", "%05d$:", tlbl->key + 100);
7462 emitcode ("mov", "c,ov");
7463 _startLazyDPSEvaluation ();
7466 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7468 emitcode ("rrc", "a");
7469 aopPut (AOP (result), "a", offset--);
7471 _endLazyDPSEvaluation ();
7472 reAdjustPreg (AOP (result));
7473 emitcode ("", "%05d$:", tlbl1->key + 100);
7474 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7477 freeAsmop (left, NULL, ic, TRUE);
7478 freeAsmop (result, NULL, ic, TRUE);
7481 /*-----------------------------------------------------------------*/
7482 /* genRightShift - generate code for right shifting */
7483 /*-----------------------------------------------------------------*/
7485 genRightShift (iCode * ic)
7487 operand *right, *left, *result;
7491 symbol *tlbl, *tlbl1;
7493 D (emitcode (";", "genRightShift "););
7495 /* if signed then we do it the hard way preserve the
7496 sign bit moving it inwards */
7497 retype = getSpec (operandType (IC_RESULT (ic)));
7499 if (!SPEC_USIGN (retype))
7501 genSignedRightShift (ic);
7505 /* signed & unsigned types are treated the same : i.e. the
7506 signed is NOT propagated inwards : quoting from the
7507 ANSI - standard : "for E1 >> E2, is equivalent to division
7508 by 2**E2 if unsigned or if it has a non-negative value,
7509 otherwise the result is implementation defined ", MY definition
7510 is that the sign does not get propagated */
7512 right = IC_RIGHT (ic);
7513 left = IC_LEFT (ic);
7514 result = IC_RESULT (ic);
7516 aopOp (right, ic, FALSE, FALSE);
7518 #ifdef BETTER_LITERAL_SHIFT
7519 /* if the shift count is known then do it
7520 as efficiently as possible */
7521 if (AOP_TYPE (right) == AOP_LIT)
7523 if (genRightShiftLiteral (left, right, result, ic, 0))
7530 /* shift count is unknown then we have to form
7531 a loop get the loop count in B : Note: we take
7532 only the lower order byte since shifting
7533 more that 32 bits make no sense anyway, ( the
7534 largest size of an object can be only 32 bits ) */
7536 if (AOP_TYPE (right) == AOP_LIT)
7538 /* Really should be handled by genRightShiftLiteral,
7539 * but since I'm too lazy to fix that today, at least we can make
7540 * some small improvement.
7542 emitcode("mov", "b,#0x%02x",
7543 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7547 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7548 emitcode ("inc", "b");
7550 freeAsmop (right, NULL, ic, TRUE);
7551 aopOp (left, ic, FALSE, FALSE);
7552 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7554 /* now move the left to the result if they are not the
7556 if (!sameRegs (AOP (left), AOP (result)) &&
7557 AOP_SIZE (result) > 1)
7560 size = AOP_SIZE (result);
7562 _startLazyDPSEvaluation ();
7565 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7566 if (*l == '@' && IS_AOP_PREG (result))
7569 emitcode ("mov", "a,%s", l);
7570 aopPut (AOP (result), "a", offset);
7573 aopPut (AOP (result), l, offset);
7576 _endLazyDPSEvaluation ();
7579 tlbl = newiTempLabel (NULL);
7580 tlbl1 = newiTempLabel (NULL);
7581 size = AOP_SIZE (result);
7584 /* if it is only one byte then */
7587 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7589 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7590 emitcode ("", "%05d$:", tlbl->key + 100);
7592 emitcode ("rrc", "a");
7593 emitcode ("", "%05d$:", tlbl1->key + 100);
7594 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7595 aopPut (AOP (result), "a", 0);
7599 reAdjustPreg (AOP (result));
7600 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7601 emitcode ("", "%05d$:", tlbl->key + 100);
7603 _startLazyDPSEvaluation ();
7606 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7608 emitcode ("rrc", "a");
7609 aopPut (AOP (result), "a", offset--);
7611 _endLazyDPSEvaluation ();
7612 reAdjustPreg (AOP (result));
7614 emitcode ("", "%05d$:", tlbl1->key + 100);
7615 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7618 freeAsmop (left, NULL, ic, TRUE);
7619 freeAsmop (result, NULL, ic, TRUE);
7622 /*-----------------------------------------------------------------*/
7623 /* genUnpackBits - generates code for unpacking bits */
7624 /*-----------------------------------------------------------------*/
7626 genUnpackBits (operand * result, char *rname, int ptype)
7633 D (emitcode (";", "genUnpackBits ");
7636 etype = getSpec (operandType (result));
7638 /* read the first byte */
7644 emitcode ("mov", "a,@%s", rname);
7648 emitcode ("movx", "a,@%s", rname);
7652 emitcode ("movx", "a,@dptr");
7656 emitcode ("clr", "a");
7657 emitcode ("movc", "a", "@a+dptr");
7661 emitcode ("lcall", "__gptrget");
7665 /* if we have bitdisplacement then it fits */
7666 /* into this byte completely or if length is */
7667 /* less than a byte */
7668 if ((shCnt = SPEC_BSTR (etype)) ||
7669 (SPEC_BLEN (etype) <= 8))
7672 /* shift right acc */
7675 emitcode ("anl", "a,#0x%02x",
7676 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7677 aopPut (AOP (result), "a", offset);
7681 /* bit field did not fit in a byte */
7682 rlen = SPEC_BLEN (etype) - 8;
7683 aopPut (AOP (result), "a", offset++);
7692 emitcode ("inc", "%s", rname);
7693 emitcode ("mov", "a,@%s", rname);
7697 emitcode ("inc", "%s", rname);
7698 emitcode ("movx", "a,@%s", rname);
7702 emitcode ("inc", "dptr");
7703 emitcode ("movx", "a,@dptr");
7707 emitcode ("clr", "a");
7708 emitcode ("inc", "dptr");
7709 emitcode ("movc", "a", "@a+dptr");
7713 emitcode ("inc", "dptr");
7714 emitcode ("lcall", "__gptrget");
7719 /* if we are done */
7723 aopPut (AOP (result), "a", offset++);
7729 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7730 aopPut (AOP (result), "a", offset);
7737 /*-----------------------------------------------------------------*/
7738 /* genDataPointerGet - generates code when ptr offset is known */
7739 /*-----------------------------------------------------------------*/
7741 genDataPointerGet (operand * left,
7747 int size, offset = 0;
7748 aopOp (result, ic, TRUE, FALSE);
7750 /* get the string representation of the name */
7751 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7752 size = AOP_SIZE (result);
7753 _startLazyDPSEvaluation ();
7757 sprintf (buffer, "(%s + %d)", l + 1, offset);
7759 sprintf (buffer, "%s", l + 1);
7760 aopPut (AOP (result), buffer, offset++);
7762 _endLazyDPSEvaluation ();
7764 freeAsmop (left, NULL, ic, TRUE);
7765 freeAsmop (result, NULL, ic, TRUE);
7768 /*-----------------------------------------------------------------*/
7769 /* genNearPointerGet - emitcode for near pointer fetch */
7770 /*-----------------------------------------------------------------*/
7772 genNearPointerGet (operand * left,
7779 sym_link *rtype, *retype, *letype;
7780 sym_link *ltype = operandType (left);
7783 rtype = operandType (result);
7784 retype = getSpec (rtype);
7785 letype = getSpec (ltype);
7787 aopOp (left, ic, FALSE, FALSE);
7789 /* if left is rematerialisable and
7790 result is not bit variable type and
7791 the left is pointer to data space i.e
7792 lower 128 bytes of space */
7793 if (AOP_TYPE (left) == AOP_IMMD &&
7794 !IS_BITVAR (retype) &&
7795 !IS_BITVAR (letype) &&
7796 DCL_TYPE (ltype) == POINTER)
7798 genDataPointerGet (left, result, ic);
7802 /* if the value is already in a pointer register
7803 then don't need anything more */
7804 if (!AOP_INPREG (AOP (left)))
7806 /* otherwise get a free pointer register */
7808 preg = getFreePtr (ic, &aop, FALSE);
7809 emitcode ("mov", "%s,%s",
7811 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7815 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7817 freeAsmop (left, NULL, ic, TRUE);
7818 aopOp (result, ic, FALSE, FALSE);
7820 /* if bitfield then unpack the bits */
7821 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7822 genUnpackBits (result, rname, POINTER);
7825 /* we have can just get the values */
7826 int size = AOP_SIZE (result);
7831 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7834 emitcode ("mov", "a,@%s", rname);
7835 aopPut (AOP (result), "a", offset);
7839 sprintf (buffer, "@%s", rname);
7840 aopPut (AOP (result), buffer, offset);
7844 emitcode ("inc", "%s", rname);
7848 /* now some housekeeping stuff */
7851 /* we had to allocate for this iCode */
7852 freeAsmop (NULL, aop, ic, TRUE);
7856 /* we did not allocate which means left
7857 already in a pointer register, then
7858 if size > 0 && this could be used again
7859 we have to point it back to where it
7861 if (AOP_SIZE (result) > 1 &&
7862 !OP_SYMBOL (left)->remat &&
7863 (OP_SYMBOL (left)->liveTo > ic->seq ||
7866 int size = AOP_SIZE (result) - 1;
7868 emitcode ("dec", "%s", rname);
7873 freeAsmop (result, NULL, ic, TRUE);
7877 /*-----------------------------------------------------------------*/
7878 /* genPagedPointerGet - emitcode for paged pointer fetch */
7879 /*-----------------------------------------------------------------*/
7881 genPagedPointerGet (operand * left,
7888 sym_link *rtype, *retype, *letype;
7890 rtype = operandType (result);
7891 retype = getSpec (rtype);
7892 letype = getSpec (operandType (left));
7893 aopOp (left, ic, FALSE, FALSE);
7895 /* if the value is already in a pointer register
7896 then don't need anything more */
7897 if (!AOP_INPREG (AOP (left)))
7899 /* otherwise get a free pointer register */
7901 preg = getFreePtr (ic, &aop, FALSE);
7902 emitcode ("mov", "%s,%s",
7904 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7908 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7910 freeAsmop (left, NULL, ic, TRUE);
7911 aopOp (result, ic, FALSE, FALSE);
7913 /* if bitfield then unpack the bits */
7914 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7915 genUnpackBits (result, rname, PPOINTER);
7918 /* we have can just get the values */
7919 int size = AOP_SIZE (result);
7925 emitcode ("movx", "a,@%s", rname);
7926 aopPut (AOP (result), "a", offset);
7931 emitcode ("inc", "%s", rname);
7935 /* now some housekeeping stuff */
7938 /* we had to allocate for this iCode */
7939 freeAsmop (NULL, aop, ic, TRUE);
7943 /* we did not allocate which means left
7944 already in a pointer register, then
7945 if size > 0 && this could be used again
7946 we have to point it back to where it
7948 if (AOP_SIZE (result) > 1 &&
7949 !OP_SYMBOL (left)->remat &&
7950 (OP_SYMBOL (left)->liveTo > ic->seq ||
7953 int size = AOP_SIZE (result) - 1;
7955 emitcode ("dec", "%s", rname);
7960 freeAsmop (result, NULL, ic, TRUE);
7965 /*-----------------------------------------------------------------*/
7966 /* genFarPointerGet - gget value from far space */
7967 /*-----------------------------------------------------------------*/
7969 genFarPointerGet (operand * left,
7970 operand * result, iCode * ic)
7973 sym_link *retype = getSpec (operandType (result));
7974 sym_link *letype = getSpec (operandType (left));
7975 D (emitcode (";", "genFarPointerGet");
7978 aopOp (left, ic, FALSE, FALSE);
7980 /* if the operand is already in dptr
7981 then we do nothing else we move the value to dptr */
7982 if (AOP_TYPE (left) != AOP_STR)
7984 /* if this is remateriazable */
7985 if (AOP_TYPE (left) == AOP_IMMD)
7987 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7991 /* we need to get it byte by byte */
7992 _startLazyDPSEvaluation ();
7993 if (AOP_TYPE (left) != AOP_DPTR)
7995 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7996 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7997 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8001 /* We need to generate a load to DPTR indirect through DPTR. */
8002 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8004 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8005 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8006 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8007 emitcode ("pop", "dph");
8008 emitcode ("pop", "dpl");
8010 _endLazyDPSEvaluation ();
8013 /* so dptr know contains the address */
8014 freeAsmop (left, NULL, ic, TRUE);
8015 aopOp (result, ic, FALSE, TRUE);
8017 /* if bit then unpack */
8018 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8019 genUnpackBits (result, "dptr", FPOINTER);
8022 size = AOP_SIZE (result);
8025 _startLazyDPSEvaluation ();
8032 emitcode ("movx", "a,@dptr");
8034 emitcode ("inc", "dptr");
8036 aopPut (AOP (result), "a", offset++);
8038 _endLazyDPSEvaluation ();
8041 freeAsmop (result, NULL, ic, TRUE);
8044 /*-----------------------------------------------------------------*/
8045 /* emitcodePointerGet - gget value from code space */
8046 /*-----------------------------------------------------------------*/
8048 emitcodePointerGet (operand * left,
8049 operand * result, iCode * ic)
8052 sym_link *retype = getSpec (operandType (result));
8054 aopOp (left, ic, FALSE, FALSE);
8056 /* if the operand is already in dptr
8057 then we do nothing else we move the value to dptr */
8058 if (AOP_TYPE (left) != AOP_STR)
8060 /* if this is remateriazable */
8061 if (AOP_TYPE (left) == AOP_IMMD)
8063 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8066 { /* we need to get it byte by byte */
8067 _startLazyDPSEvaluation ();
8068 if (AOP_TYPE (left) != AOP_DPTR)
8070 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8071 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8072 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8076 /* We need to generate a load to DPTR indirect through DPTR. */
8077 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8079 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8080 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8081 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8082 emitcode ("pop", "dph");
8083 emitcode ("pop", "dpl");
8085 _endLazyDPSEvaluation ();
8088 /* so dptr know contains the address */
8089 freeAsmop (left, NULL, ic, TRUE);
8090 aopOp (result, ic, FALSE, TRUE);
8092 /* if bit then unpack */
8093 if (IS_BITVAR (retype))
8094 genUnpackBits (result, "dptr", CPOINTER);
8097 size = AOP_SIZE (result);
8100 _startLazyDPSEvaluation ();
8106 emitcode ("clr", "a");
8107 emitcode ("movc", "a,@a+dptr");
8109 emitcode ("inc", "dptr");
8110 aopPut (AOP (result), "a", offset++);
8112 _endLazyDPSEvaluation ();
8115 freeAsmop (result, NULL, ic, TRUE);
8118 /*-----------------------------------------------------------------*/
8119 /* genGenPointerGet - gget value from generic pointer space */
8120 /*-----------------------------------------------------------------*/
8122 genGenPointerGet (operand * left,
8123 operand * result, iCode * ic)
8126 sym_link *retype = getSpec (operandType (result));
8127 sym_link *letype = getSpec (operandType (left));
8129 D (emitcode (";", "genGenPointerGet "); );
8131 aopOp (left, ic, FALSE, TRUE);
8133 /* if the operand is already in dptr
8134 then we do nothing else we move the value to dptr */
8135 if (AOP_TYPE (left) != AOP_STR)
8137 /* if this is remateriazable */
8138 if (AOP_TYPE (left) == AOP_IMMD)
8140 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8141 emitcode ("mov", "b,#%d", pointerCode (retype));
8144 { /* we need to get it byte by byte */
8145 _startLazyDPSEvaluation ();
8146 if (AOP(left)->type==AOP_DPTR2) {
8148 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8151 emitcode ("mov", "dpl,%s", l);
8152 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8155 emitcode ("mov", "dph,%s", l);
8156 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8159 emitcode ("mov", "dpx,%s", l);
8160 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8162 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8163 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8164 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8165 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8167 _endLazyDPSEvaluation ();
8170 /* so dptr know contains the address */
8171 freeAsmop (left, NULL, ic, TRUE);
8172 aopOp (result, ic, FALSE, TRUE);
8174 /* if bit then unpack */
8175 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8176 genUnpackBits (result, "dptr", GPOINTER);
8179 size = AOP_SIZE (result);
8184 emitcode ("lcall", "__gptrget");
8185 aopPut (AOP (result), "a", offset++);
8187 emitcode ("inc", "dptr");
8191 freeAsmop (result, NULL, ic, TRUE);
8194 /*-----------------------------------------------------------------*/
8195 /* genPointerGet - generate code for pointer get */
8196 /*-----------------------------------------------------------------*/
8198 genPointerGet (iCode * ic)
8200 operand *left, *result;
8201 sym_link *type, *etype;
8204 D (emitcode (";", "genPointerGet ");
8207 left = IC_LEFT (ic);
8208 result = IC_RESULT (ic);
8210 /* depending on the type of pointer we need to
8211 move it to the correct pointer register */
8212 type = operandType (left);
8213 etype = getSpec (type);
8214 /* if left is of type of pointer then it is simple */
8215 if (IS_PTR (type) && !IS_FUNC (type->next))
8216 p_type = DCL_TYPE (type);
8219 /* we have to go by the storage class */
8220 p_type = PTR_TYPE (SPEC_OCLS (etype));
8223 /* now that we have the pointer type we assign
8224 the pointer values */
8230 genNearPointerGet (left, result, ic);
8234 genPagedPointerGet (left, result, ic);
8238 genFarPointerGet (left, result, ic);
8242 emitcodePointerGet (left, result, ic);
8246 genGenPointerGet (left, result, ic);
8252 /*-----------------------------------------------------------------*/
8253 /* genPackBits - generates code for packed bit storage */
8254 /*-----------------------------------------------------------------*/
8256 genPackBits (sym_link * etype,
8258 char *rname, int p_type)
8266 blen = SPEC_BLEN (etype);
8267 bstr = SPEC_BSTR (etype);
8269 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8272 /* if the bit lenth is less than or */
8273 /* it exactly fits a byte then */
8274 if (SPEC_BLEN (etype) <= 8)
8276 shCount = SPEC_BSTR (etype);
8278 /* shift left acc */
8281 if (SPEC_BLEN (etype) < 8)
8282 { /* if smaller than a byte */
8288 emitcode ("mov", "b,a");
8289 emitcode ("mov", "a,@%s", rname);
8293 emitcode ("mov", "b,a");
8294 emitcode ("movx", "a,@dptr");
8298 emitcode ("push", "b");
8299 emitcode ("push", "acc");
8300 emitcode ("lcall", "__gptrget");
8301 emitcode ("pop", "b");
8305 emitcode ("anl", "a,#0x%02x", (unsigned char)
8306 ((unsigned char) (0xFF << (blen + bstr)) |
8307 (unsigned char) (0xFF >> (8 - bstr))));
8308 emitcode ("orl", "a,b");
8309 if (p_type == GPOINTER)
8310 emitcode ("pop", "b");
8317 emitcode ("mov", "@%s,a", rname);
8321 emitcode ("movx", "@dptr,a");
8325 emitcode ("lcall", "__gptrput");
8330 if (SPEC_BLEN (etype) <= 8)
8333 emitcode ("inc", "%s", rname);
8334 rLen = SPEC_BLEN (etype);
8336 /* now generate for lengths greater than one byte */
8340 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8352 emitcode ("mov", "@%s,a", rname);
8355 emitcode ("mov", "@%s,%s", rname, l);
8360 emitcode ("movx", "@dptr,a");
8365 emitcode ("lcall", "__gptrput");
8368 emitcode ("inc", "%s", rname);
8373 /* last last was not complete */
8376 /* save the byte & read byte */
8380 emitcode ("mov", "b,a");
8381 emitcode ("mov", "a,@%s", rname);
8385 emitcode ("mov", "b,a");
8386 emitcode ("movx", "a,@dptr");
8390 emitcode ("push", "b");
8391 emitcode ("push", "acc");
8392 emitcode ("lcall", "__gptrget");
8393 emitcode ("pop", "b");
8397 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8398 emitcode ("orl", "a,b");
8401 if (p_type == GPOINTER)
8402 emitcode ("pop", "b");
8408 emitcode ("mov", "@%s,a", rname);
8412 emitcode ("movx", "@dptr,a");
8416 emitcode ("lcall", "__gptrput");
8420 /*-----------------------------------------------------------------*/
8421 /* genDataPointerSet - remat pointer to data space */
8422 /*-----------------------------------------------------------------*/
8424 genDataPointerSet (operand * right,
8428 int size, offset = 0;
8429 char *l, buffer[256];
8431 aopOp (right, ic, FALSE, FALSE);
8433 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8434 size = AOP_SIZE (right);
8438 sprintf (buffer, "(%s + %d)", l + 1, offset);
8440 sprintf (buffer, "%s", l + 1);
8441 emitcode ("mov", "%s,%s", buffer,
8442 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8445 freeAsmop (right, NULL, ic, TRUE);
8446 freeAsmop (result, NULL, ic, TRUE);
8449 /*-----------------------------------------------------------------*/
8450 /* genNearPointerSet - emitcode for near pointer put */
8451 /*-----------------------------------------------------------------*/
8453 genNearPointerSet (operand * right,
8460 sym_link *retype, *letype;
8461 sym_link *ptype = operandType (result);
8463 retype = getSpec (operandType (right));
8464 letype = getSpec (ptype);
8466 aopOp (result, ic, FALSE, FALSE);
8468 /* if the result is rematerializable &
8469 in data space & not a bit variable */
8470 if (AOP_TYPE (result) == AOP_IMMD &&
8471 DCL_TYPE (ptype) == POINTER &&
8472 !IS_BITVAR (retype) &&
8473 !IS_BITVAR (letype))
8475 genDataPointerSet (right, result, ic);
8479 /* if the value is already in a pointer register
8480 then don't need anything more */
8481 if (!AOP_INPREG (AOP (result)))
8483 /* otherwise get a free pointer register */
8485 preg = getFreePtr (ic, &aop, FALSE);
8486 emitcode ("mov", "%s,%s",
8488 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8492 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8494 freeAsmop (result, NULL, ic, TRUE);
8495 aopOp (right, ic, FALSE, FALSE);
8497 /* if bitfield then unpack the bits */
8498 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8499 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8502 /* we have can just get the values */
8503 int size = AOP_SIZE (right);
8508 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8512 emitcode ("mov", "@%s,a", rname);
8515 emitcode ("mov", "@%s,%s", rname, l);
8517 emitcode ("inc", "%s", rname);
8522 /* now some housekeeping stuff */
8525 /* we had to allocate for this iCode */
8526 freeAsmop (NULL, aop, ic, TRUE);
8530 /* we did not allocate which means left
8531 already in a pointer register, then
8532 if size > 0 && this could be used again
8533 we have to point it back to where it
8535 if (AOP_SIZE (right) > 1 &&
8536 !OP_SYMBOL (result)->remat &&
8537 (OP_SYMBOL (result)->liveTo > ic->seq ||
8540 int size = AOP_SIZE (right) - 1;
8542 emitcode ("dec", "%s", rname);
8547 freeAsmop (right, NULL, ic, TRUE);
8552 /*-----------------------------------------------------------------*/
8553 /* genPagedPointerSet - emitcode for Paged pointer put */
8554 /*-----------------------------------------------------------------*/
8556 genPagedPointerSet (operand * right,
8563 sym_link *retype, *letype;
8565 retype = getSpec (operandType (right));
8566 letype = getSpec (operandType (result));
8568 aopOp (result, ic, FALSE, FALSE);
8570 /* if the value is already in a pointer register
8571 then don't need anything more */
8572 if (!AOP_INPREG (AOP (result)))
8574 /* otherwise get a free pointer register */
8576 preg = getFreePtr (ic, &aop, FALSE);
8577 emitcode ("mov", "%s,%s",
8579 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8583 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8585 freeAsmop (result, NULL, ic, TRUE);
8586 aopOp (right, ic, FALSE, FALSE);
8588 /* if bitfield then unpack the bits */
8589 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8590 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8593 /* we have can just get the values */
8594 int size = AOP_SIZE (right);
8599 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8602 emitcode ("movx", "@%s,a", rname);
8605 emitcode ("inc", "%s", rname);
8611 /* now some housekeeping stuff */
8614 /* we had to allocate for this iCode */
8615 freeAsmop (NULL, aop, ic, TRUE);
8619 /* we did not allocate which means left
8620 already in a pointer register, then
8621 if size > 0 && this could be used again
8622 we have to point it back to where it
8624 if (AOP_SIZE (right) > 1 &&
8625 !OP_SYMBOL (result)->remat &&
8626 (OP_SYMBOL (result)->liveTo > ic->seq ||
8629 int size = AOP_SIZE (right) - 1;
8631 emitcode ("dec", "%s", rname);
8636 freeAsmop (right, NULL, ic, TRUE);
8641 /*-----------------------------------------------------------------*/
8642 /* genFarPointerSet - set value from far space */
8643 /*-----------------------------------------------------------------*/
8645 genFarPointerSet (operand * right,
8646 operand * result, iCode * ic)
8649 sym_link *retype = getSpec (operandType (right));
8650 sym_link *letype = getSpec (operandType (result));
8652 aopOp (result, ic, FALSE, FALSE);
8654 /* if the operand is already in dptr
8655 then we do nothing else we move the value to dptr */
8656 if (AOP_TYPE (result) != AOP_STR)
8658 /* if this is remateriazable */
8659 if (AOP_TYPE (result) == AOP_IMMD)
8660 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8663 /* we need to get it byte by byte */
8664 _startLazyDPSEvaluation ();
8665 if (AOP_TYPE (result) != AOP_DPTR)
8667 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8668 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8669 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8673 /* We need to generate a load to DPTR indirect through DPTR. */
8674 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8676 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8677 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8678 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8679 emitcode ("pop", "dph");
8680 emitcode ("pop", "dpl");
8682 _endLazyDPSEvaluation ();
8685 /* so dptr know contains the address */
8686 freeAsmop (result, NULL, ic, TRUE);
8687 aopOp (right, ic, FALSE, TRUE);
8689 /* if bit then unpack */
8690 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8691 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8694 size = AOP_SIZE (right);
8697 _startLazyDPSEvaluation ();
8700 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8706 emitcode ("movx", "@dptr,a");
8708 emitcode ("inc", "dptr");
8710 _endLazyDPSEvaluation ();
8713 freeAsmop (right, NULL, ic, TRUE);
8716 /*-----------------------------------------------------------------*/
8717 /* genGenPointerSet - set value from generic pointer space */
8718 /*-----------------------------------------------------------------*/
8720 genGenPointerSet (operand * right,
8721 operand * result, iCode * ic)
8724 sym_link *retype = getSpec (operandType (right));
8725 sym_link *letype = getSpec (operandType (result));
8727 aopOp (result, ic, FALSE, TRUE);
8729 /* if the operand is already in dptr
8730 then we do nothing else we move the value to dptr */
8731 if (AOP_TYPE (result) != AOP_STR)
8733 _startLazyDPSEvaluation ();
8734 /* if this is remateriazable */
8735 if (AOP_TYPE (result) == AOP_IMMD)
8737 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8738 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8741 { /* we need to get it byte by byte */
8742 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8743 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8744 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8745 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8747 _endLazyDPSEvaluation ();
8749 /* so dptr know contains the address */
8750 freeAsmop (result, NULL, ic, TRUE);
8751 aopOp (right, ic, FALSE, TRUE);
8753 /* if bit then unpack */
8754 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8755 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8758 size = AOP_SIZE (right);
8761 _startLazyDPSEvaluation ();
8764 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8770 emitcode ("lcall", "__gptrput");
8772 emitcode ("inc", "dptr");
8774 _endLazyDPSEvaluation ();
8777 freeAsmop (right, NULL, ic, TRUE);
8780 /*-----------------------------------------------------------------*/
8781 /* genPointerSet - stores the value into a pointer location */
8782 /*-----------------------------------------------------------------*/
8784 genPointerSet (iCode * ic)
8786 operand *right, *result;
8787 sym_link *type, *etype;
8790 D (emitcode (";", "genPointerSet ");
8793 right = IC_RIGHT (ic);
8794 result = IC_RESULT (ic);
8796 /* depending on the type of pointer we need to
8797 move it to the correct pointer register */
8798 type = operandType (result);
8799 etype = getSpec (type);
8800 /* if left is of type of pointer then it is simple */
8801 if (IS_PTR (type) && !IS_FUNC (type->next))
8803 p_type = DCL_TYPE (type);
8807 /* we have to go by the storage class */
8808 p_type = PTR_TYPE (SPEC_OCLS (etype));
8811 /* now that we have the pointer type we assign
8812 the pointer values */
8818 genNearPointerSet (right, result, ic);
8822 genPagedPointerSet (right, result, ic);
8826 genFarPointerSet (right, result, ic);
8830 genGenPointerSet (right, result, ic);
8836 /*-----------------------------------------------------------------*/
8837 /* genIfx - generate code for Ifx statement */
8838 /*-----------------------------------------------------------------*/
8840 genIfx (iCode * ic, iCode * popIc)
8842 operand *cond = IC_COND (ic);
8845 D (emitcode (";", "genIfx "););
8847 aopOp (cond, ic, FALSE, FALSE);
8849 /* get the value into acc */
8850 if (AOP_TYPE (cond) != AOP_CRY)
8854 /* the result is now in the accumulator */
8855 freeAsmop (cond, NULL, ic, TRUE);
8857 /* if there was something to be popped then do it */
8861 /* if the condition is a bit variable */
8862 if (isbit && IS_ITEMP (cond) &&
8864 genIfxJump (ic, SPIL_LOC (cond)->rname);
8865 else if (isbit && !IS_ITEMP (cond))
8866 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8868 genIfxJump (ic, "a");
8873 /*-----------------------------------------------------------------*/
8874 /* genAddrOf - generates code for address of */
8875 /*-----------------------------------------------------------------*/
8877 genAddrOf (iCode * ic)
8879 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8882 D (emitcode (";", "genAddrOf ");
8885 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8887 /* if the operand is on the stack then we
8888 need to get the stack offset of this
8892 /* if it has an offset then we need to compute
8896 emitcode ("mov", "a,_bp");
8897 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8898 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8902 /* we can just move _bp */
8903 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8905 /* fill the result with zero */
8906 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8909 if (options.stack10bit && size < (FPTRSIZE - 1))
8912 "*** warning: pointer to stack var truncated.\n");
8919 if (options.stack10bit && offset == 2)
8921 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8925 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8932 /* object not on stack then we need the name */
8933 size = AOP_SIZE (IC_RESULT (ic));
8938 char s[SDCC_NAME_MAX];
8940 sprintf (s, "#(%s >> %d)",
8944 sprintf (s, "#%s", sym->rname);
8945 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8949 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8953 /*-----------------------------------------------------------------*/
8954 /* genFarFarAssign - assignment when both are in far space */
8955 /*-----------------------------------------------------------------*/
8957 genFarFarAssign (operand * result, operand * right, iCode * ic)
8959 int size = AOP_SIZE (right);
8961 symbol *rSym = NULL;
8965 /* quick & easy case. */
8966 D(emitcode(";","genFarFarAssign (1 byte case)"););
8967 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
8968 freeAsmop (right, NULL, ic, FALSE);
8969 /* now assign DPTR to result */
8971 aopOp(result, ic, FALSE, FALSE);
8973 aopPut(AOP(result), "a", 0);
8974 freeAsmop(result, NULL, ic, FALSE);
8978 /* See if we've got an underlying symbol to abuse. */
8979 if (IS_SYMOP(result) && OP_SYMBOL(result))
8981 if (IS_TRUE_SYMOP(result))
8983 rSym = OP_SYMBOL(result);
8985 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
8987 rSym = OP_SYMBOL(result)->usl.spillLoc;
8991 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
8993 /* We can use the '390 auto-toggle feature to good effect here. */
8995 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
8996 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
8997 emitcode ("mov", "dptr,#%s", rSym->rname);
8998 /* DP2 = result, DP1 = right, DP1 is current. */
9001 emitcode("movx", "a,@dptr");
9002 emitcode("movx", "@dptr,a");
9005 emitcode("inc", "dptr");
9006 emitcode("inc", "dptr");
9009 emitcode("mov", "dps, #0");
9010 freeAsmop (right, NULL, ic, FALSE);
9014 D (emitcode (";", "genFarFarAssign"););
9015 aopOp (result, ic, TRUE, TRUE);
9017 _startLazyDPSEvaluation ();
9021 aopPut (AOP (result),
9022 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9025 _endLazyDPSEvaluation ();
9026 freeAsmop (result, NULL, ic, FALSE);
9027 freeAsmop (right, NULL, ic, FALSE);
9031 /*-----------------------------------------------------------------*/
9032 /* genAssign - generate code for assignment */
9033 /*-----------------------------------------------------------------*/
9035 genAssign (iCode * ic)
9037 operand *result, *right;
9039 unsigned long lit = 0L;
9041 D (emitcode (";", "genAssign ");
9044 result = IC_RESULT (ic);
9045 right = IC_RIGHT (ic);
9047 /* if they are the same */
9048 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9051 aopOp (right, ic, FALSE, FALSE);
9053 emitcode (";", "genAssign: resultIsFar = %s",
9054 isOperandInFarSpace (result) ?
9057 /* special case both in far space */
9058 if ((AOP_TYPE (right) == AOP_DPTR ||
9059 AOP_TYPE (right) == AOP_DPTR2) &&
9060 /* IS_TRUE_SYMOP(result) && */
9061 isOperandInFarSpace (result))
9063 genFarFarAssign (result, right, ic);
9067 aopOp (result, ic, TRUE, FALSE);
9069 /* if they are the same registers */
9070 if (sameRegs (AOP (right), AOP (result)))
9073 /* if the result is a bit */
9074 if (AOP_TYPE (result) == AOP_CRY)
9077 /* if the right size is a literal then
9078 we know what the value is */
9079 if (AOP_TYPE (right) == AOP_LIT)
9081 if (((int) operandLitValue (right)))
9082 aopPut (AOP (result), one, 0);
9084 aopPut (AOP (result), zero, 0);
9088 /* the right is also a bit variable */
9089 if (AOP_TYPE (right) == AOP_CRY)
9091 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9092 aopPut (AOP (result), "c", 0);
9098 aopPut (AOP (result), "a", 0);
9102 /* bit variables done */
9104 size = AOP_SIZE (result);
9106 if (AOP_TYPE (right) == AOP_LIT)
9107 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9110 (AOP_TYPE (result) != AOP_REG) &&
9111 (AOP_TYPE (right) == AOP_LIT) &&
9112 !IS_FLOAT (operandType (right)))
9114 _startLazyDPSEvaluation ();
9115 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9117 aopPut (AOP (result),
9118 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9123 /* And now fill the rest with zeros. */
9126 emitcode ("clr", "a");
9130 aopPut (AOP (result), "a", offset++);
9132 _endLazyDPSEvaluation ();
9136 _startLazyDPSEvaluation ();
9139 aopPut (AOP (result),
9140 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9144 _endLazyDPSEvaluation ();
9148 freeAsmop (right, NULL, ic, FALSE);
9149 freeAsmop (result, NULL, ic, TRUE);
9152 /*-----------------------------------------------------------------*/
9153 /* genJumpTab - generates code for jump table */
9154 /*-----------------------------------------------------------------*/
9156 genJumpTab (iCode * ic)
9161 D (emitcode (";", "genJumpTab ");
9164 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9165 /* get the condition into accumulator */
9166 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9168 /* multiply by four! */
9169 emitcode ("add", "a,acc");
9170 emitcode ("add", "a,acc");
9171 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9173 jtab = newiTempLabel (NULL);
9174 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9175 emitcode ("jmp", "@a+dptr");
9176 emitcode ("", "%05d$:", jtab->key + 100);
9177 /* now generate the jump labels */
9178 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9179 jtab = setNextItem (IC_JTLABELS (ic)))
9180 emitcode ("ljmp", "%05d$", jtab->key + 100);
9184 /*-----------------------------------------------------------------*/
9185 /* genCast - gen code for casting */
9186 /*-----------------------------------------------------------------*/
9188 genCast (iCode * ic)
9190 operand *result = IC_RESULT (ic);
9191 sym_link *ctype = operandType (IC_LEFT (ic));
9192 sym_link *rtype = operandType (IC_RIGHT (ic));
9193 operand *right = IC_RIGHT (ic);
9196 D (emitcode (";", "genCast ");
9199 /* if they are equivalent then do nothing */
9200 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9203 aopOp (right, ic, FALSE, FALSE);
9204 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9206 /* if the result is a bit */
9207 if (AOP_TYPE (result) == AOP_CRY)
9209 /* if the right size is a literal then
9210 we know what the value is */
9211 if (AOP_TYPE (right) == AOP_LIT)
9213 if (((int) operandLitValue (right)))
9214 aopPut (AOP (result), one, 0);
9216 aopPut (AOP (result), zero, 0);
9221 /* the right is also a bit variable */
9222 if (AOP_TYPE (right) == AOP_CRY)
9224 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9225 aopPut (AOP (result), "c", 0);
9231 aopPut (AOP (result), "a", 0);
9235 /* if they are the same size : or less */
9236 if (AOP_SIZE (result) <= AOP_SIZE (right))
9239 /* if they are in the same place */
9240 if (sameRegs (AOP (right), AOP (result)))
9243 /* if they in different places then copy */
9244 size = AOP_SIZE (result);
9246 _startLazyDPSEvaluation ();
9249 aopPut (AOP (result),
9250 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9254 _endLazyDPSEvaluation ();
9259 /* if the result is of type pointer */
9264 sym_link *type = operandType (right);
9266 /* pointer to generic pointer */
9267 if (IS_GENPTR (ctype))
9273 p_type = DCL_TYPE (type);
9277 #if OLD_CAST_BEHAVIOR
9278 /* KV: we are converting a non-pointer type to
9279 * a generic pointer. This (ifdef'd out) code
9280 * says that the resulting generic pointer
9281 * should have the same class as the storage
9282 * location of the non-pointer variable.
9284 * For example, converting an int (which happens
9285 * to be stored in DATA space) to a pointer results
9286 * in a DATA generic pointer; if the original int
9287 * in XDATA space, so will be the resulting pointer.
9289 * I don't like that behavior, and thus this change:
9290 * all such conversions will be forced to XDATA and
9291 * throw a warning. If you want some non-XDATA
9292 * type, or you want to suppress the warning, you
9293 * must go through an intermediate cast, like so:
9295 * char _generic *gp = (char _xdata *)(intVar);
9297 sym_link *etype = getSpec (type);
9299 /* we have to go by the storage class */
9300 if (SPEC_OCLS (etype) != generic)
9302 p_type = PTR_TYPE (SPEC_OCLS (etype));
9307 /* Converting unknown class (i.e. register variable)
9308 * to generic pointer. This is not good, but
9309 * we'll make a guess (and throw a warning).
9312 werror (W_INT_TO_GEN_PTR_CAST);
9316 /* the first two bytes are known */
9317 size = GPTRSIZE - 1;
9319 _startLazyDPSEvaluation ();
9322 aopPut (AOP (result),
9323 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9327 _endLazyDPSEvaluation ();
9329 /* the last byte depending on type */
9347 /* this should never happen */
9348 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9349 "got unknown pointer type");
9352 aopPut (AOP (result), l, GPTRSIZE - 1);
9356 /* just copy the pointers */
9357 size = AOP_SIZE (result);
9359 _startLazyDPSEvaluation ();
9362 aopPut (AOP (result),
9363 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9367 _endLazyDPSEvaluation ();
9371 /* so we now know that the size of destination is greater
9372 than the size of the source */
9373 /* we move to result for the size of source */
9374 size = AOP_SIZE (right);
9376 _startLazyDPSEvaluation ();
9379 aopPut (AOP (result),
9380 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9384 _endLazyDPSEvaluation ();
9386 /* now depending on the sign of the source && destination */
9387 size = AOP_SIZE (result) - AOP_SIZE (right);
9388 /* if unsigned or not an integral type */
9389 /* also, if the source is a bit, we don't need to sign extend, because
9390 * it can't possibly have set the sign bit.
9392 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9396 aopPut (AOP (result), zero, offset++);
9401 /* we need to extend the sign :{ */
9402 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9403 FALSE, FALSE, TRUE);
9405 emitcode ("rlc", "a");
9406 emitcode ("subb", "a,acc");
9408 aopPut (AOP (result), "a", offset++);
9411 /* we are done hurray !!!! */
9414 freeAsmop (right, NULL, ic, TRUE);
9415 freeAsmop (result, NULL, ic, TRUE);
9419 /*-----------------------------------------------------------------*/
9420 /* genDjnz - generate decrement & jump if not zero instrucion */
9421 /*-----------------------------------------------------------------*/
9423 genDjnz (iCode * ic, iCode * ifx)
9429 /* if the if condition has a false label
9430 then we cannot save */
9434 /* if the minus is not of the form
9436 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9437 !IS_OP_LITERAL (IC_RIGHT (ic)))
9440 if (operandLitValue (IC_RIGHT (ic)) != 1)
9443 /* if the size of this greater than one then no
9445 if (getSize (operandType (IC_RESULT (ic))) > 1)
9448 /* otherwise we can save BIG */
9449 D(emitcode(";", "genDjnz"););
9451 lbl = newiTempLabel (NULL);
9452 lbl1 = newiTempLabel (NULL);
9454 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9456 if (AOP_NEEDSACC(IC_RESULT(ic)))
9458 /* If the result is accessed indirectly via
9459 * the accumulator, we must explicitly write
9460 * it back after the decrement.
9462 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9464 if (strcmp(rByte, "a"))
9466 /* Something is hopelessly wrong */
9467 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9468 __FILE__, __LINE__);
9469 /* We can just give up; the generated code will be inefficient,
9472 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9475 emitcode ("dec", "%s", rByte);
9476 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9477 emitcode ("jnz", "%05d$", lbl->key + 100);
9479 else if (IS_AOP_PREG (IC_RESULT (ic)))
9481 emitcode ("dec", "%s",
9482 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9483 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9484 emitcode ("jnz", "%05d$", lbl->key + 100);
9488 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9491 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9492 emitcode ("", "%05d$:", lbl->key + 100);
9493 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9494 emitcode ("", "%05d$:", lbl1->key + 100);
9496 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9501 /*-----------------------------------------------------------------*/
9502 /* genReceive - generate code for a receive iCode */
9503 /*-----------------------------------------------------------------*/
9505 genReceive (iCode * ic)
9508 D (emitcode (";", "genReceive ");
9511 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9512 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9513 IS_TRUE_SYMOP (IC_RESULT (ic))))
9515 int size = getSize (operandType (IC_RESULT (ic)));
9516 int offset = fReturnSizeDS390 - size;
9519 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9520 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9523 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9524 size = AOP_SIZE (IC_RESULT (ic));
9528 emitcode ("pop", "acc");
9529 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9536 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9538 assignResultValue (IC_RESULT (ic));
9541 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9544 /*-----------------------------------------------------------------*/
9545 /* gen390Code - generate code for Dallas 390 based controllers */
9546 /*-----------------------------------------------------------------*/
9548 gen390Code (iCode * lic)
9553 lineHead = lineCurr = NULL;
9557 /* print the allocation information */
9559 printAllocInfo (currFunc, codeOutFile);
9561 /* if debug information required */
9562 if (options.debug && currFunc)
9564 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9566 if (IS_STATIC (currFunc->etype))
9567 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9569 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9572 /* stack pointer name */
9573 if (options.useXstack)
9579 for (ic = lic; ic; ic = ic->next)
9582 if (cln != ic->lineno)
9587 emitcode ("", "C$%s$%d$%d$%d ==.",
9588 FileBaseName (ic->filename), ic->lineno,
9589 ic->level, ic->block);
9592 emitcode (";", "%s %d", ic->filename, ic->lineno);
9595 /* if the result is marked as
9596 spilt and rematerializable or code for
9597 this has already been generated then
9599 if (resultRemat (ic) || ic->generated)
9602 /* depending on the operation */
9622 /* IPOP happens only when trying to restore a
9623 spilt live range, if there is an ifx statement
9624 following this pop then the if statement might
9625 be using some of the registers being popped which
9626 would destory the contents of the register so
9627 we need to check for this condition and handle it */
9629 ic->next->op == IFX &&
9630 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9631 genIfx (ic->next, ic);
9649 genEndFunction (ic);
9669 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9686 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9690 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9697 /* note these two are xlated by algebraic equivalence
9698 during parsing SDCC.y */
9699 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9700 "got '>=' or '<=' shouldn't have come here");
9704 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9716 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9720 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9724 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9751 case GET_VALUE_AT_ADDRESS:
9756 if (POINTER_SET (ic))
9783 addSet (&_G.sendSet, ic);
9792 /* now we are ready to call the
9793 peep hole optimizer */
9794 if (!options.nopeep)
9795 peepHole (&lineHead);
9797 /* now do the actual printing */
9798 printLine (lineHead, codeOutFile);