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 /* Since A is the last element of fReturn,
2847 * it is OK to clobber it in the aopGet.
2849 l = aopGet (AOP (IC_LEFT (ic)), offset,
2850 FALSE, FALSE, TRUE);
2851 if (strcmp (fReturn[offset], l))
2853 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2857 _endLazyDPSEvaluation ();
2864 if (strcmp (fReturn[pushed], "a"))
2865 emitcode ("pop", fReturn[pushed]);
2867 emitcode ("pop", "acc");
2870 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2873 /* generate a jump to the return label
2874 if the next is not the return statement */
2875 if (!(ic->next && ic->next->op == LABEL &&
2876 IC_LABEL (ic->next) == returnLabel))
2878 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2882 /*-----------------------------------------------------------------*/
2883 /* genLabel - generates a label */
2884 /*-----------------------------------------------------------------*/
2886 genLabel (iCode * ic)
2888 /* special case never generate */
2889 if (IC_LABEL (ic) == entryLabel)
2892 D (emitcode (";", "genLabel ");
2895 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2898 /*-----------------------------------------------------------------*/
2899 /* genGoto - generates a ljmp */
2900 /*-----------------------------------------------------------------*/
2902 genGoto (iCode * ic)
2904 D (emitcode (";", "genGoto ");
2906 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2909 /*-----------------------------------------------------------------*/
2910 /* findLabelBackwards: walks back through the iCode chain looking */
2911 /* for the given label. Returns number of iCode instructions */
2912 /* between that label and given ic. */
2913 /* Returns zero if label not found. */
2914 /*-----------------------------------------------------------------*/
2916 findLabelBackwards (iCode * ic, int key)
2925 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2927 /* printf("findLabelBackwards = %d\n", count); */
2935 /*-----------------------------------------------------------------*/
2936 /* genPlusIncr :- does addition with increment if possible */
2937 /*-----------------------------------------------------------------*/
2939 genPlusIncr (iCode * ic)
2941 unsigned int icount;
2942 unsigned int size = getDataSize (IC_RESULT (ic));
2944 /* will try to generate an increment */
2945 /* if the right side is not a literal
2947 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2950 /* if the literal value of the right hand side
2951 is greater than 4 then it is not worth it */
2952 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2955 /* if increment 16 bits in register */
2957 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2958 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2959 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2967 /* If the next instruction is a goto and the goto target
2968 * is <= 5 instructions previous to this, we can generate
2969 * jumps straight to that target.
2971 if (ic->next && ic->next->op == GOTO
2972 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2975 emitcode (";", "tail increment optimized (range %d)", labelRange);
2976 tlbl = IC_LABEL (ic->next);
2981 tlbl = newiTempLabel (NULL);
2984 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2985 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2986 IS_AOP_PREG (IC_RESULT (ic)))
2987 emitcode ("cjne", "%s,#0x00,%05d$"
2988 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2992 emitcode ("clr", "a");
2993 emitcode ("cjne", "a,%s,%05d$"
2994 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2998 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3001 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3002 IS_AOP_PREG (IC_RESULT (ic)))
3003 emitcode ("cjne", "%s,#0x00,%05d$"
3004 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3007 emitcode ("cjne", "a,%s,%05d$"
3008 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3011 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3015 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3016 IS_AOP_PREG (IC_RESULT (ic)))
3017 emitcode ("cjne", "%s,#0x00,%05d$"
3018 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3022 emitcode ("cjne", "a,%s,%05d$"
3023 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3026 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3031 emitcode ("", "%05d$:", tlbl->key + 100);
3036 /* if the sizes are greater than 1 then we cannot */
3037 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3038 AOP_SIZE (IC_LEFT (ic)) > 1)
3041 /* we can if the aops of the left & result match or
3042 if they are in registers and the registers are the
3045 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3046 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3047 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3052 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3053 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3054 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3059 _startLazyDPSEvaluation ();
3062 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3064 _endLazyDPSEvaluation ();
3073 /*-----------------------------------------------------------------*/
3074 /* outBitAcc - output a bit in acc */
3075 /*-----------------------------------------------------------------*/
3077 outBitAcc (operand * result)
3079 symbol *tlbl = newiTempLabel (NULL);
3080 /* if the result is a bit */
3081 if (AOP_TYPE (result) == AOP_CRY)
3083 aopPut (AOP (result), "a", 0);
3087 emitcode ("jz", "%05d$", tlbl->key + 100);
3088 emitcode ("mov", "a,%s", one);
3089 emitcode ("", "%05d$:", tlbl->key + 100);
3094 /*-----------------------------------------------------------------*/
3095 /* genPlusBits - generates code for addition of two bits */
3096 /*-----------------------------------------------------------------*/
3098 genPlusBits (iCode * ic)
3100 D (emitcode (";", "genPlusBits ");
3102 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3104 symbol *lbl = newiTempLabel (NULL);
3105 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3106 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3107 emitcode ("cpl", "c");
3108 emitcode ("", "%05d$:", (lbl->key + 100));
3109 outBitC (IC_RESULT (ic));
3113 emitcode ("clr", "a");
3114 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3115 emitcode ("rlc", "a");
3116 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3117 emitcode ("addc", "a,#0x00");
3118 outAcc (IC_RESULT (ic));
3123 adjustArithmeticResult (iCode * ic)
3125 if (opIsGptr (IC_RESULT (ic)) &&
3126 opIsGptr (IC_LEFT (ic)) &&
3127 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3129 aopPut (AOP (IC_RESULT (ic)),
3130 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3134 if (opIsGptr (IC_RESULT (ic)) &&
3135 opIsGptr (IC_RIGHT (ic)) &&
3136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3138 aopPut (AOP (IC_RESULT (ic)),
3139 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3143 if (opIsGptr (IC_RESULT (ic)) &&
3144 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3145 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3146 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3147 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3150 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3151 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3155 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3156 // (because all three operands are in far space).
3157 #define AOP_OP_3(ic) \
3158 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3159 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3160 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3161 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3162 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3163 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3165 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3167 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3170 // Macro to aopOp all three operands of an ic. If this cannot be done,
3171 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3172 // will be set TRUE. The caller must then handle the case specially, noting
3173 // that the IC_RESULT operand is not aopOp'd.
3174 #define AOP_OP_3_NOFATAL(ic, rc) \
3175 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3176 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3177 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3178 isOperandInFarSpace(IC_RESULT(ic))) \
3180 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3185 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3186 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3188 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3189 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3191 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3193 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3197 // aopOp the left & right operands of an ic.
3198 #define AOP_OP_2(ic) \
3199 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3200 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3202 // convienience macro.
3203 #define AOP_SET_LOCALS(ic) \
3204 left = IC_LEFT(ic); \
3205 right = IC_RIGHT(ic); \
3206 result = IC_RESULT(ic);
3209 // Given an integer value of pushedSize bytes on the stack,
3210 // adjust it to be resultSize bytes, either by discarding
3211 // the most significant bytes or by zero-padding.
3213 // On exit from this macro, pushedSize will have been adjusted to
3214 // equal resultSize, and ACC may be trashed.
3215 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3216 /* If the pushed data is bigger than the result, \
3217 * simply discard unused bytes. Icky, but works. \
3219 while (pushedSize > resultSize) \
3221 D (emitcode (";", "discarding unused result byte."););\
3222 emitcode ("pop", "acc"); \
3225 if (pushedSize < resultSize) \
3227 emitcode ("clr", "a"); \
3228 /* Conversly, we haven't pushed enough here. \
3229 * just zero-pad, and all is well. \
3231 while (pushedSize < resultSize) \
3233 emitcode("push", "acc"); \
3237 assert(pushedSize == resultSize);
3239 /*-----------------------------------------------------------------*/
3240 /* genPlus - generates code for addition */
3241 /*-----------------------------------------------------------------*/
3243 genPlus (iCode * ic)
3245 int size, offset = 0;
3246 bool pushResult = FALSE;
3249 D (emitcode (";", "genPlus "););
3251 /* special cases :- */
3253 AOP_OP_3_NOFATAL (ic, pushResult);
3256 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3261 /* if literal, literal on the right or
3262 if left requires ACC or right is already
3264 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3265 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3266 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3268 operand *t = IC_RIGHT (ic);
3269 IC_RIGHT (ic) = IC_LEFT (ic);
3271 emitcode (";", "Swapped plus args.");
3274 /* if both left & right are in bit
3276 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3277 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3283 /* if left in bit space & right literal */
3284 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3285 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3287 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3288 /* if result in bit space */
3289 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3291 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3292 emitcode ("cpl", "c");
3293 outBitC (IC_RESULT (ic));
3297 size = getDataSize (IC_RESULT (ic));
3298 _startLazyDPSEvaluation ();
3301 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3302 emitcode ("addc", "a,#00");
3303 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3305 _endLazyDPSEvaluation ();
3310 /* if I can do an increment instead
3311 of add then GOOD for ME */
3312 if (genPlusIncr (ic) == TRUE)
3314 emitcode (";", "did genPlusIncr");
3319 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3321 _startLazyDPSEvaluation ();
3324 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3326 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3328 emitcode ("add", "a,%s",
3329 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3331 emitcode ("addc", "a,%s",
3332 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3336 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3338 emitcode ("add", "a,%s",
3339 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3341 emitcode ("addc", "a,%s",
3342 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3346 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3350 emitcode ("push", "acc");
3354 _endLazyDPSEvaluation ();
3358 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3360 size = getDataSize (IC_LEFT (ic));
3361 rSize = getDataSize (IC_RESULT (ic));
3363 ADJUST_PUSHED_RESULT(size, rSize);
3365 _startLazyDPSEvaluation ();
3368 emitcode ("pop", "acc");
3369 aopPut (AOP (IC_RESULT (ic)), "a", size);
3371 _endLazyDPSEvaluation ();
3374 adjustArithmeticResult (ic);
3377 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3378 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3379 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3382 /*-----------------------------------------------------------------*/
3383 /* genMinusDec :- does subtraction with deccrement if possible */
3384 /*-----------------------------------------------------------------*/
3386 genMinusDec (iCode * ic)
3388 unsigned int icount;
3389 unsigned int size = getDataSize (IC_RESULT (ic));
3391 /* will try to generate an increment */
3392 /* if the right side is not a literal
3394 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3397 /* if the literal value of the right hand side
3398 is greater than 4 then it is not worth it */
3399 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3402 /* if decrement 16 bits in register */
3403 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3404 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3405 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3413 /* If the next instruction is a goto and the goto target
3414 * is <= 5 instructions previous to this, we can generate
3415 * jumps straight to that target.
3417 if (ic->next && ic->next->op == GOTO
3418 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3421 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3422 tlbl = IC_LABEL (ic->next);
3427 tlbl = newiTempLabel (NULL);
3431 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3432 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3433 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3434 IS_AOP_PREG (IC_RESULT (ic)))
3435 emitcode ("cjne", "%s,#0xff,%05d$"
3436 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3440 emitcode ("mov", "a,#0xff");
3441 emitcode ("cjne", "a,%s,%05d$"
3442 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3445 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3448 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3449 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3450 IS_AOP_PREG (IC_RESULT (ic)))
3451 emitcode ("cjne", "%s,#0xff,%05d$"
3452 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3456 emitcode ("cjne", "a,%s,%05d$"
3457 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3460 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3464 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3465 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3466 IS_AOP_PREG (IC_RESULT (ic)))
3467 emitcode ("cjne", "%s,#0xff,%05d$"
3468 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3472 emitcode ("cjne", "a,%s,%05d$"
3473 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3476 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3480 emitcode ("", "%05d$:", tlbl->key + 100);
3485 /* if the sizes are greater than 1 then we cannot */
3486 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3487 AOP_SIZE (IC_LEFT (ic)) > 1)
3490 /* we can if the aops of the left & result match or
3491 if they are in registers and the registers are the
3494 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3495 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3496 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3499 _startLazyDPSEvaluation ();
3502 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3504 _endLazyDPSEvaluation ();
3512 /*-----------------------------------------------------------------*/
3513 /* addSign - complete with sign */
3514 /*-----------------------------------------------------------------*/
3516 addSign (operand * result, int offset, int sign)
3518 int size = (getDataSize (result) - offset);
3521 _startLazyDPSEvaluation();
3524 emitcode ("rlc", "a");
3525 emitcode ("subb", "a,acc");
3528 aopPut (AOP (result), "a", offset++);
3535 aopPut (AOP (result), zero, offset++);
3538 _endLazyDPSEvaluation();
3542 /*-----------------------------------------------------------------*/
3543 /* genMinusBits - generates code for subtraction of two bits */
3544 /*-----------------------------------------------------------------*/
3546 genMinusBits (iCode * ic)
3548 symbol *lbl = newiTempLabel (NULL);
3550 D (emitcode (";", "genMinusBits "););
3552 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3554 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3555 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3556 emitcode ("cpl", "c");
3557 emitcode ("", "%05d$:", (lbl->key + 100));
3558 outBitC (IC_RESULT (ic));
3562 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3563 emitcode ("subb", "a,acc");
3564 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3565 emitcode ("inc", "a");
3566 emitcode ("", "%05d$:", (lbl->key + 100));
3567 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3568 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3572 /*-----------------------------------------------------------------*/
3573 /* genMinus - generates code for subtraction */
3574 /*-----------------------------------------------------------------*/
3576 genMinus (iCode * ic)
3578 int size, offset = 0;
3580 unsigned long lit = 0L;
3581 bool pushResult = FALSE;
3583 D (emitcode (";", "genMinus "););
3585 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3586 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3587 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3588 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3594 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3596 /* special cases :- */
3597 /* if both left & right are in bit space */
3598 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3599 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3605 /* if I can do an decrement instead
3606 of subtract then GOOD for ME */
3607 if (genMinusDec (ic) == TRUE)
3612 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3614 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3620 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3625 /* if literal, add a,#-lit, else normal subb */
3626 _startLazyDPSEvaluation ();
3629 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3630 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3631 emitcode ("subb", "a,%s",
3632 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3635 /* first add without previous c */
3637 emitcode ("add", "a,#0x%02x",
3638 (unsigned int) (lit & 0x0FFL));
3640 emitcode ("addc", "a,#0x%02x",
3641 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3646 emitcode ("push", "acc");
3650 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3654 _endLazyDPSEvaluation ();
3658 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3660 size = getDataSize (IC_LEFT (ic));
3661 rSize = getDataSize (IC_RESULT (ic));
3663 ADJUST_PUSHED_RESULT(size, rSize);
3665 _startLazyDPSEvaluation ();
3668 emitcode ("pop", "acc");
3669 aopPut (AOP (IC_RESULT (ic)), "a", size);
3671 _endLazyDPSEvaluation ();
3674 adjustArithmeticResult (ic);
3677 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3678 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3679 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3683 /*-----------------------------------------------------------------*/
3684 /* genMultbits :- multiplication of bits */
3685 /*-----------------------------------------------------------------*/
3687 genMultbits (operand * left,
3691 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3692 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3697 /*-----------------------------------------------------------------*/
3698 /* genMultOneByte : 8*8=8/16 bit multiplication */
3699 /*-----------------------------------------------------------------*/
3701 genMultOneByte (operand * left,
3705 sym_link *opetype = operandType (result);
3707 int size=AOP_SIZE(result);
3709 emitcode (";",__FUNCTION__);
3710 if (size<1 || size>2) {
3711 // this should never happen
3712 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3713 AOP_SIZE(result), __FUNCTION__, lineno);
3717 /* (if two literals: the value is computed before) */
3718 /* if one literal, literal on the right */
3719 if (AOP_TYPE (left) == AOP_LIT)
3724 emitcode (";", "swapped left and right");
3727 if (SPEC_USIGN(opetype)
3728 // ignore the sign of left and right, what else can we do?
3729 || (SPEC_USIGN(operandType(left)) &&
3730 SPEC_USIGN(operandType(right)))) {
3731 // just an unsigned 8*8=8/16 multiply
3732 //emitcode (";","unsigned");
3733 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3734 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3735 emitcode ("mul", "ab");
3736 aopPut (AOP (result), "a", 0);
3738 aopPut (AOP (result), "b", 1);
3743 // we have to do a signed multiply
3745 emitcode (";", "signed");
3746 emitcode ("clr", "F0"); // reset sign flag
3747 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3748 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3750 lbl=newiTempLabel(NULL);
3751 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3752 // left side is negative, 8-bit two's complement, this fails for -128
3753 emitcode ("setb", "F0"); // set sign flag
3754 emitcode ("cpl", "a");
3755 emitcode ("inc", "a");
3757 emitcode ("", "%05d$:", lbl->key+100);
3758 emitcode ("xch", "a,b");
3761 if (AOP_TYPE(right)==AOP_LIT) {
3762 /* AND literal negative */
3763 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3764 // two's complement for literal<0
3765 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3766 emitcode ("cpl", "a");
3767 emitcode ("inc", "a");
3770 lbl=newiTempLabel(NULL);
3771 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3772 // right side is negative, 8-bit two's complement
3773 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3774 emitcode ("cpl", "a");
3775 emitcode ("inc", "a");
3776 emitcode ("", "%05d$:", lbl->key+100);
3778 emitcode ("mul", "ab");
3780 lbl=newiTempLabel(NULL);
3781 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3782 // only ONE op was negative, we have to do a 8/16-bit two's complement
3783 emitcode ("cpl", "a"); // lsb
3785 emitcode ("inc", "a");
3787 emitcode ("add", "a,#1");
3788 emitcode ("xch", "a,b");
3789 emitcode ("cpl", "a"); // msb
3790 emitcode ("addc", "a,#0");
3791 emitcode ("xch", "a,b");
3794 emitcode ("", "%05d$:", lbl->key+100);
3795 aopPut (AOP (result), "a", 0);
3797 aopPut (AOP (result), "b", 1);
3801 /*-----------------------------------------------------------------*/
3802 /* genMult - generates code for multiplication */
3803 /*-----------------------------------------------------------------*/
3805 genMult (iCode * ic)
3807 operand *left = IC_LEFT (ic);
3808 operand *right = IC_RIGHT (ic);
3809 operand *result = IC_RESULT (ic);
3811 D (emitcode (";", "genMult "););
3813 /* assign the amsops */
3816 /* special cases first */
3818 if (AOP_TYPE (left) == AOP_CRY &&
3819 AOP_TYPE (right) == AOP_CRY)
3821 genMultbits (left, right, result);
3825 /* if both are of size == 1 */
3826 if (AOP_SIZE (left) == 1 &&
3827 AOP_SIZE (right) == 1)
3829 genMultOneByte (left, right, result);
3833 /* should have been converted to function call */
3837 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3838 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3839 freeAsmop (result, NULL, ic, TRUE);
3842 /*-----------------------------------------------------------------*/
3843 /* genDivbits :- division of bits */
3844 /*-----------------------------------------------------------------*/
3846 genDivbits (operand * left,
3853 /* the result must be bit */
3854 LOAD_AB_FOR_DIV (left, right, l);
3855 emitcode ("div", "ab");
3856 emitcode ("rrc", "a");
3857 aopPut (AOP (result), "c", 0);
3860 /*-----------------------------------------------------------------*/
3861 /* genDivOneByte : 8 bit division */
3862 /*-----------------------------------------------------------------*/
3864 genDivOneByte (operand * left,
3868 sym_link *opetype = operandType (result);
3873 size = AOP_SIZE (result) - 1;
3875 /* signed or unsigned */
3876 if (SPEC_USIGN (opetype))
3878 /* unsigned is easy */
3879 LOAD_AB_FOR_DIV (left, right, l);
3880 emitcode ("div", "ab");
3881 aopPut (AOP (result), "a", 0);
3883 aopPut (AOP (result), zero, offset++);
3887 /* signed is a little bit more difficult */
3889 /* save the signs of the operands */
3890 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3892 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3893 emitcode ("push", "acc"); /* save it on the stack */
3895 /* now sign adjust for both left & right */
3896 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3898 lbl = newiTempLabel (NULL);
3899 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3900 emitcode ("cpl", "a");
3901 emitcode ("inc", "a");
3902 emitcode ("", "%05d$:", (lbl->key + 100));
3903 emitcode ("mov", "b,a");
3905 /* sign adjust left side */
3906 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3909 lbl = newiTempLabel (NULL);
3910 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3911 emitcode ("cpl", "a");
3912 emitcode ("inc", "a");
3913 emitcode ("", "%05d$:", (lbl->key + 100));
3915 /* now the division */
3916 emitcode ("nop", "; workaround for DS80C390 div bug.");
3917 emitcode ("div", "ab");
3918 /* we are interested in the lower order
3920 emitcode ("mov", "b,a");
3921 lbl = newiTempLabel (NULL);
3922 emitcode ("pop", "acc");
3923 /* if there was an over flow we don't
3924 adjust the sign of the result */
3925 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3926 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3928 emitcode ("clr", "a");
3929 emitcode ("subb", "a,b");
3930 emitcode ("mov", "b,a");
3931 emitcode ("", "%05d$:", (lbl->key + 100));
3933 /* now we are done */
3934 aopPut (AOP (result), "b", 0);
3937 emitcode ("mov", "c,b.7");
3938 emitcode ("subb", "a,acc");
3941 aopPut (AOP (result), "a", offset++);
3945 /*-----------------------------------------------------------------*/
3946 /* genDiv - generates code for division */
3947 /*-----------------------------------------------------------------*/
3951 operand *left = IC_LEFT (ic);
3952 operand *right = IC_RIGHT (ic);
3953 operand *result = IC_RESULT (ic);
3955 D (emitcode (";", "genDiv ");
3958 /* assign the amsops */
3961 /* special cases first */
3963 if (AOP_TYPE (left) == AOP_CRY &&
3964 AOP_TYPE (right) == AOP_CRY)
3966 genDivbits (left, right, result);
3970 /* if both are of size == 1 */
3971 if (AOP_SIZE (left) == 1 &&
3972 AOP_SIZE (right) == 1)
3974 genDivOneByte (left, right, result);
3978 /* should have been converted to function call */
3981 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3982 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3983 freeAsmop (result, NULL, ic, TRUE);
3986 /*-----------------------------------------------------------------*/
3987 /* genModbits :- modulus of bits */
3988 /*-----------------------------------------------------------------*/
3990 genModbits (operand * left,
3997 /* the result must be bit */
3998 LOAD_AB_FOR_DIV (left, right, l);
3999 emitcode ("div", "ab");
4000 emitcode ("mov", "a,b");
4001 emitcode ("rrc", "a");
4002 aopPut (AOP (result), "c", 0);
4005 /*-----------------------------------------------------------------*/
4006 /* genModOneByte : 8 bit modulus */
4007 /*-----------------------------------------------------------------*/
4009 genModOneByte (operand * left,
4013 sym_link *opetype = operandType (result);
4017 /* signed or unsigned */
4018 if (SPEC_USIGN (opetype))
4020 /* unsigned is easy */
4021 LOAD_AB_FOR_DIV (left, right, l);
4022 emitcode ("div", "ab");
4023 aopPut (AOP (result), "b", 0);
4027 /* signed is a little bit more difficult */
4029 /* save the signs of the operands */
4030 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4033 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4034 emitcode ("push", "acc"); /* save it on the stack */
4036 /* now sign adjust for both left & right */
4037 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4040 lbl = newiTempLabel (NULL);
4041 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4042 emitcode ("cpl", "a");
4043 emitcode ("inc", "a");
4044 emitcode ("", "%05d$:", (lbl->key + 100));
4045 emitcode ("mov", "b,a");
4047 /* sign adjust left side */
4048 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4051 lbl = newiTempLabel (NULL);
4052 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4053 emitcode ("cpl", "a");
4054 emitcode ("inc", "a");
4055 emitcode ("", "%05d$:", (lbl->key + 100));
4057 /* now the multiplication */
4058 emitcode ("nop", "; workaround for DS80C390 div bug.");
4059 emitcode ("div", "ab");
4060 /* we are interested in the lower order
4062 lbl = newiTempLabel (NULL);
4063 emitcode ("pop", "acc");
4064 /* if there was an over flow we don't
4065 adjust the sign of the result */
4066 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4067 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4069 emitcode ("clr", "a");
4070 emitcode ("subb", "a,b");
4071 emitcode ("mov", "b,a");
4072 emitcode ("", "%05d$:", (lbl->key + 100));
4074 /* now we are done */
4075 aopPut (AOP (result), "b", 0);
4079 /*-----------------------------------------------------------------*/
4080 /* genMod - generates code for division */
4081 /*-----------------------------------------------------------------*/
4085 operand *left = IC_LEFT (ic);
4086 operand *right = IC_RIGHT (ic);
4087 operand *result = IC_RESULT (ic);
4089 D (emitcode (";", "genMod ");
4092 /* assign the amsops */
4095 /* special cases first */
4097 if (AOP_TYPE (left) == AOP_CRY &&
4098 AOP_TYPE (right) == AOP_CRY)
4100 genModbits (left, right, result);
4104 /* if both are of size == 1 */
4105 if (AOP_SIZE (left) == 1 &&
4106 AOP_SIZE (right) == 1)
4108 genModOneByte (left, right, result);
4112 /* should have been converted to function call */
4116 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4117 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4118 freeAsmop (result, NULL, ic, TRUE);
4121 /*-----------------------------------------------------------------*/
4122 /* genIfxJump :- will create a jump depending on the ifx */
4123 /*-----------------------------------------------------------------*/
4125 genIfxJump (iCode * ic, char *jval)
4128 symbol *tlbl = newiTempLabel (NULL);
4131 D (emitcode (";", "genIfxJump ");
4134 /* if true label then we jump if condition
4138 jlbl = IC_TRUE (ic);
4139 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4140 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4144 /* false label is present */
4145 jlbl = IC_FALSE (ic);
4146 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4147 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4149 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4150 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4152 emitcode (inst, "%05d$", tlbl->key + 100);
4153 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4154 emitcode ("", "%05d$:", tlbl->key + 100);
4156 /* mark the icode as generated */
4160 /*-----------------------------------------------------------------*/
4161 /* genCmp :- greater or less than comparison */
4162 /*-----------------------------------------------------------------*/
4164 genCmp (operand * left, operand * right,
4165 iCode * ic, iCode * ifx, int sign)
4167 int size, offset = 0;
4168 unsigned long lit = 0L;
4171 D (emitcode (";", "genCmp");
4174 result = IC_RESULT (ic);
4176 /* if left & right are bit variables */
4177 if (AOP_TYPE (left) == AOP_CRY &&
4178 AOP_TYPE (right) == AOP_CRY)
4180 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4181 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4185 /* subtract right from left if at the
4186 end the carry flag is set then we know that
4187 left is greater than right */
4188 size = max (AOP_SIZE (left), AOP_SIZE (right));
4190 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4191 if ((size == 1) && !sign &&
4192 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4194 symbol *lbl = newiTempLabel (NULL);
4195 emitcode ("cjne", "%s,%s,%05d$",
4196 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4197 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4199 emitcode ("", "%05d$:", lbl->key + 100);
4203 if (AOP_TYPE (right) == AOP_LIT)
4205 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4206 /* optimize if(x < 0) or if(x >= 0) */
4215 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4217 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4218 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4220 aopOp (result, ic, FALSE, FALSE);
4222 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4224 freeAsmop (result, NULL, ic, TRUE);
4225 genIfxJump (ifx, "acc.7");
4230 emitcode ("rlc", "a");
4232 goto release_freedLR;
4240 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4241 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4242 emitcode (";", "genCmp #2");
4243 if (sign && (size == 0))
4245 emitcode (";", "genCmp #3");
4246 emitcode ("xrl", "a,#0x80");
4247 if (AOP_TYPE (right) == AOP_LIT)
4249 unsigned long lit = (unsigned long)
4250 floatFromVal (AOP (right)->aopu.aop_lit);
4251 emitcode (";", "genCmp #3.1");
4252 emitcode ("subb", "a,#0x%02x",
4253 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4257 emitcode (";", "genCmp #3.2");
4258 if (AOP_NEEDSACC (right))
4260 emitcode ("push", "acc");
4262 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4263 FALSE, FALSE, FALSE));
4264 emitcode ("xrl", "b,#0x80");
4265 if (AOP_NEEDSACC (right))
4267 emitcode ("pop", "acc");
4269 emitcode ("subb", "a,b");
4276 emitcode (";", "genCmp #4");
4277 if (AOP_NEEDSACC (right))
4280 emitcode (";", "genCmp #4.1");
4281 emitcode ("xch", "a, b");
4282 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4283 emitcode ("xch", "a, b");
4288 emitcode (";", "genCmp #4.2");
4289 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4292 emitcode ("subb", "a,%s", s);
4299 /* Don't need the left & right operands any more; do need the result. */
4300 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4301 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4303 aopOp (result, ic, FALSE, FALSE);
4307 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4313 /* if the result is used in the next
4314 ifx conditional branch then generate
4315 code a little differently */
4318 genIfxJump (ifx, "c");
4324 /* leave the result in acc */
4326 freeAsmop (result, NULL, ic, TRUE);
4329 /*-----------------------------------------------------------------*/
4330 /* genCmpGt :- greater than comparison */
4331 /*-----------------------------------------------------------------*/
4333 genCmpGt (iCode * ic, iCode * ifx)
4335 operand *left, *right;
4336 sym_link *letype, *retype;
4339 D (emitcode (";", "genCmpGt ");
4342 left = IC_LEFT (ic);
4343 right = IC_RIGHT (ic);
4345 letype = getSpec (operandType (left));
4346 retype = getSpec (operandType (right));
4347 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4349 /* assign the left & right amsops */
4352 genCmp (right, left, ic, ifx, sign);
4355 /*-----------------------------------------------------------------*/
4356 /* genCmpLt - less than comparisons */
4357 /*-----------------------------------------------------------------*/
4359 genCmpLt (iCode * ic, iCode * ifx)
4361 operand *left, *right;
4362 sym_link *letype, *retype;
4365 D (emitcode (";", "genCmpLt "););
4367 left = IC_LEFT (ic);
4368 right = IC_RIGHT (ic);
4370 letype = getSpec (operandType (left));
4371 retype = getSpec (operandType (right));
4372 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4374 /* assign the left & right amsops */
4377 genCmp (left, right, ic, ifx, sign);
4380 /*-----------------------------------------------------------------*/
4381 /* gencjneshort - compare and jump if not equal */
4382 /*-----------------------------------------------------------------*/
4384 gencjneshort (operand * left, operand * right, symbol * lbl)
4386 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4388 unsigned long lit = 0L;
4390 D (emitcode (";", "gencjneshort");
4393 /* if the left side is a literal or
4394 if the right is in a pointer register and left
4396 if ((AOP_TYPE (left) == AOP_LIT) ||
4397 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4404 if (AOP_TYPE (right) == AOP_LIT)
4405 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4407 if (opIsGptr (left) || opIsGptr (right))
4409 /* We are comparing a generic pointer to something.
4410 * Exclude the generic type byte from the comparison.
4413 D (emitcode (";", "cjneshort: generic ptr special case.");
4418 /* if the right side is a literal then anything goes */
4419 if (AOP_TYPE (right) == AOP_LIT &&
4420 AOP_TYPE (left) != AOP_DIR)
4424 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4426 emitcode ("cjne", "a,%s,%05d$",
4427 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4433 /* if the right side is in a register or in direct space or
4434 if the left is a pointer register & right is not */
4435 else if (AOP_TYPE (right) == AOP_REG ||
4436 AOP_TYPE (right) == AOP_DIR ||
4437 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4438 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4442 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4443 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4444 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4445 emitcode ("jnz", "%05d$", lbl->key + 100);
4447 emitcode ("cjne", "a,%s,%05d$",
4448 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4455 /* right is a pointer reg need both a & b */
4458 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4459 if (strcmp (l, "b"))
4460 emitcode ("mov", "b,%s", l);
4461 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4462 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4468 /*-----------------------------------------------------------------*/
4469 /* gencjne - compare and jump if not equal */
4470 /*-----------------------------------------------------------------*/
4472 gencjne (operand * left, operand * right, symbol * lbl)
4474 symbol *tlbl = newiTempLabel (NULL);
4476 D (emitcode (";", "gencjne");
4479 gencjneshort (left, right, lbl);
4481 emitcode ("mov", "a,%s", one);
4482 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4483 emitcode ("", "%05d$:", lbl->key + 100);
4484 emitcode ("clr", "a");
4485 emitcode ("", "%05d$:", tlbl->key + 100);
4488 /*-----------------------------------------------------------------*/
4489 /* genCmpEq - generates code for equal to */
4490 /*-----------------------------------------------------------------*/
4492 genCmpEq (iCode * ic, iCode * ifx)
4494 operand *left, *right, *result;
4496 D (emitcode (";", "genCmpEq ");
4500 AOP_SET_LOCALS (ic);
4502 /* if literal, literal on the right or
4503 if the right is in a pointer register and left
4505 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4506 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4508 operand *t = IC_RIGHT (ic);
4509 IC_RIGHT (ic) = IC_LEFT (ic);
4513 if (ifx && /* !AOP_SIZE(result) */
4514 OP_SYMBOL (result) &&
4515 OP_SYMBOL (result)->regType == REG_CND)
4518 /* if they are both bit variables */
4519 if (AOP_TYPE (left) == AOP_CRY &&
4520 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4522 if (AOP_TYPE (right) == AOP_LIT)
4524 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4527 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4528 emitcode ("cpl", "c");
4532 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4536 emitcode ("clr", "c");
4538 /* AOP_TYPE(right) == AOP_CRY */
4542 symbol *lbl = newiTempLabel (NULL);
4543 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4544 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4545 emitcode ("cpl", "c");
4546 emitcode ("", "%05d$:", (lbl->key + 100));
4548 /* if true label then we jump if condition
4550 tlbl = newiTempLabel (NULL);
4553 emitcode ("jnc", "%05d$", tlbl->key + 100);
4554 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4558 emitcode ("jc", "%05d$", tlbl->key + 100);
4559 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4561 emitcode ("", "%05d$:", tlbl->key + 100);
4565 tlbl = newiTempLabel (NULL);
4566 gencjneshort (left, right, tlbl);
4569 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4570 emitcode ("", "%05d$:", tlbl->key + 100);
4574 symbol *lbl = newiTempLabel (NULL);
4575 emitcode ("sjmp", "%05d$", lbl->key + 100);
4576 emitcode ("", "%05d$:", tlbl->key + 100);
4577 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4578 emitcode ("", "%05d$:", lbl->key + 100);
4581 /* mark the icode as generated */
4584 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4585 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4589 /* if they are both bit variables */
4590 if (AOP_TYPE (left) == AOP_CRY &&
4591 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4593 if (AOP_TYPE (right) == AOP_LIT)
4595 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4598 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4599 emitcode ("cpl", "c");
4603 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4607 emitcode ("clr", "c");
4609 /* AOP_TYPE(right) == AOP_CRY */
4613 symbol *lbl = newiTempLabel (NULL);
4614 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4615 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4616 emitcode ("cpl", "c");
4617 emitcode ("", "%05d$:", (lbl->key + 100));
4620 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4621 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4623 aopOp (result, ic, TRUE, FALSE);
4626 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4633 genIfxJump (ifx, "c");
4636 /* if the result is used in an arithmetic operation
4637 then put the result in place */
4642 gencjne (left, right, newiTempLabel (NULL));
4644 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4645 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4647 aopOp (result, ic, TRUE, FALSE);
4649 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4651 aopPut (AOP (result), "a", 0);
4656 genIfxJump (ifx, "a");
4659 /* if the result is used in an arithmetic operation
4660 then put the result in place */
4661 if (AOP_TYPE (result) != AOP_CRY)
4663 /* leave the result in acc */
4667 freeAsmop (result, NULL, ic, TRUE);
4670 /*-----------------------------------------------------------------*/
4671 /* ifxForOp - returns the icode containing the ifx for operand */
4672 /*-----------------------------------------------------------------*/
4674 ifxForOp (operand * op, iCode * ic)
4676 /* if true symbol then needs to be assigned */
4677 if (IS_TRUE_SYMOP (op))
4680 /* if this has register type condition and
4681 the next instruction is ifx with the same operand
4682 and live to of the operand is upto the ifx only then */
4684 ic->next->op == IFX &&
4685 IC_COND (ic->next)->key == op->key &&
4686 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4691 /*-----------------------------------------------------------------*/
4692 /* genAndOp - for && operation */
4693 /*-----------------------------------------------------------------*/
4695 genAndOp (iCode * ic)
4697 operand *left, *right, *result;
4700 D (emitcode (";", "genAndOp "););
4702 /* note here that && operations that are in an
4703 if statement are taken away by backPatchLabels
4704 only those used in arthmetic operations remain */
4706 AOP_SET_LOCALS (ic);
4708 /* if both are bit variables */
4709 if (AOP_TYPE (left) == AOP_CRY &&
4710 AOP_TYPE (right) == AOP_CRY)
4712 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4713 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4714 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4715 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4717 aopOp (result,ic,FALSE, FALSE);
4722 tlbl = newiTempLabel (NULL);
4724 emitcode ("jz", "%05d$", tlbl->key + 100);
4726 emitcode ("", "%05d$:", tlbl->key + 100);
4727 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4728 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4730 aopOp (result,ic,FALSE, FALSE);
4733 freeAsmop (result, NULL, ic, TRUE);
4737 /*-----------------------------------------------------------------*/
4738 /* genOrOp - for || operation */
4739 /*-----------------------------------------------------------------*/
4741 genOrOp (iCode * ic)
4743 operand *left, *right, *result;
4746 D (emitcode (";", "genOrOp "););
4748 /* note here that || operations that are in an
4749 if statement are taken away by backPatchLabels
4750 only those used in arthmetic operations remain */
4752 AOP_SET_LOCALS (ic);
4754 /* if both are bit variables */
4755 if (AOP_TYPE (left) == AOP_CRY &&
4756 AOP_TYPE (right) == AOP_CRY)
4758 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4759 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4760 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4761 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4763 aopOp (result,ic,FALSE, FALSE);
4769 tlbl = newiTempLabel (NULL);
4771 emitcode ("jnz", "%05d$", tlbl->key + 100);
4773 emitcode ("", "%05d$:", tlbl->key + 100);
4774 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4775 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4777 aopOp (result,ic,FALSE, FALSE);
4782 freeAsmop (result, NULL, ic, TRUE);
4785 /*-----------------------------------------------------------------*/
4786 /* isLiteralBit - test if lit == 2^n */
4787 /*-----------------------------------------------------------------*/
4789 isLiteralBit (unsigned long lit)
4791 unsigned long pw[32] =
4792 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4793 0x100L, 0x200L, 0x400L, 0x800L,
4794 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4795 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4796 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4797 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4798 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4801 for (idx = 0; idx < 32; idx++)
4807 /*-----------------------------------------------------------------*/
4808 /* continueIfTrue - */
4809 /*-----------------------------------------------------------------*/
4811 continueIfTrue (iCode * ic)
4814 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4818 /*-----------------------------------------------------------------*/
4820 /*-----------------------------------------------------------------*/
4822 jumpIfTrue (iCode * ic)
4825 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4829 /*-----------------------------------------------------------------*/
4830 /* jmpTrueOrFalse - */
4831 /*-----------------------------------------------------------------*/
4833 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4835 // ugly but optimized by peephole
4838 symbol *nlbl = newiTempLabel (NULL);
4839 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4840 emitcode ("", "%05d$:", tlbl->key + 100);
4841 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4842 emitcode ("", "%05d$:", nlbl->key + 100);
4846 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4847 emitcode ("", "%05d$:", tlbl->key + 100);
4852 // Generate code to perform a bit-wise logic operation
4853 // on two operands in far space (assumed to already have been
4854 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4855 // in far space. This requires pushing the result on the stack
4856 // then popping it into the result.
4858 genFarFarLogicOp(iCode *ic, char *logicOp)
4860 int size, resultSize, compSize;
4863 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4864 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4865 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4867 _startLazyDPSEvaluation();
4868 for (size = compSize; (size--); offset++)
4870 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4871 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4872 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4874 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4875 emitcode ("push", "acc");
4877 _endLazyDPSEvaluation();
4879 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4880 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4881 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4883 resultSize = AOP_SIZE(IC_RESULT(ic));
4885 ADJUST_PUSHED_RESULT(compSize, resultSize);
4887 _startLazyDPSEvaluation();
4890 emitcode ("pop", "acc");
4891 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4893 _endLazyDPSEvaluation();
4894 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4898 /*-----------------------------------------------------------------*/
4899 /* genAnd - code for and */
4900 /*-----------------------------------------------------------------*/
4902 genAnd (iCode * ic, iCode * ifx)
4904 operand *left, *right, *result;
4905 int size, offset = 0;
4906 unsigned long lit = 0L;
4911 D (emitcode (";", "genAnd "););
4913 AOP_OP_3_NOFATAL (ic, pushResult);
4914 AOP_SET_LOCALS (ic);
4918 genFarFarLogicOp(ic, "anl");
4923 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4925 AOP_TYPE (left), AOP_TYPE (right));
4926 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4928 AOP_SIZE (left), AOP_SIZE (right));
4931 /* if left is a literal & right is not then exchange them */
4932 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4933 AOP_NEEDSACC (left))
4935 operand *tmp = right;
4940 /* if result = right then exchange them */
4941 if (sameRegs (AOP (result), AOP (right)))
4943 operand *tmp = right;
4948 /* if right is bit then exchange them */
4949 if (AOP_TYPE (right) == AOP_CRY &&
4950 AOP_TYPE (left) != AOP_CRY)
4952 operand *tmp = right;
4956 if (AOP_TYPE (right) == AOP_LIT)
4957 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4959 size = AOP_SIZE (result);
4962 // result = bit & yy;
4963 if (AOP_TYPE (left) == AOP_CRY)
4965 // c = bit & literal;
4966 if (AOP_TYPE (right) == AOP_LIT)
4970 if (size && sameRegs (AOP (result), AOP (left)))
4973 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4978 if (size && (AOP_TYPE (result) == AOP_CRY))
4980 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4983 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4988 emitcode ("clr", "c");
4993 if (AOP_TYPE (right) == AOP_CRY)
4996 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4997 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5002 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5004 emitcode ("rrc", "a");
5005 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5013 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5014 genIfxJump (ifx, "c");
5018 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5019 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5020 if ((AOP_TYPE (right) == AOP_LIT) &&
5021 (AOP_TYPE (result) == AOP_CRY) &&
5022 (AOP_TYPE (left) != AOP_CRY))
5024 int posbit = isLiteralBit (lit);
5029 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5032 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5038 sprintf (buffer, "acc.%d", posbit & 0x07);
5039 genIfxJump (ifx, buffer);
5046 symbol *tlbl = newiTempLabel (NULL);
5047 int sizel = AOP_SIZE (left);
5049 emitcode ("setb", "c");
5052 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5054 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5056 if ((posbit = isLiteralBit (bytelit)) != 0)
5057 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5060 if (bytelit != 0x0FFL)
5061 emitcode ("anl", "a,%s",
5062 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5063 emitcode ("jnz", "%05d$", tlbl->key + 100);
5068 // bit = left & literal
5071 emitcode ("clr", "c");
5072 emitcode ("", "%05d$:", tlbl->key + 100);
5074 // if(left & literal)
5078 jmpTrueOrFalse (ifx, tlbl);
5086 /* if left is same as result */
5087 if (sameRegs (AOP (result), AOP (left)))
5089 for (; size--; offset++)
5091 if (AOP_TYPE (right) == AOP_LIT)
5093 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5095 else if (bytelit == 0)
5096 aopPut (AOP (result), zero, offset);
5097 else if (IS_AOP_PREG (result))
5099 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5100 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5101 aopPut (AOP (result), "a", offset);
5104 emitcode ("anl", "%s,%s",
5105 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5106 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5110 if (AOP_TYPE (left) == AOP_ACC)
5111 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5114 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5115 if (IS_AOP_PREG (result))
5117 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5118 aopPut (AOP (result), "a", offset);
5122 emitcode ("anl", "%s,a",
5123 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5130 // left & result in different registers
5131 if (AOP_TYPE (result) == AOP_CRY)
5134 // if(size), result in bit
5135 // if(!size && ifx), conditional oper: if(left & right)
5136 symbol *tlbl = newiTempLabel (NULL);
5137 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5139 emitcode ("setb", "c");
5142 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5143 emitcode ("anl", "a,%s",
5144 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5145 emitcode ("jnz", "%05d$", tlbl->key + 100);
5151 emitcode ("", "%05d$:", tlbl->key + 100);
5155 jmpTrueOrFalse (ifx, tlbl);
5159 for (; (size--); offset++)
5162 // result = left & right
5163 if (AOP_TYPE (right) == AOP_LIT)
5165 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5167 aopPut (AOP (result),
5168 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5172 else if (bytelit == 0)
5174 aopPut (AOP (result), zero, offset);
5177 D (emitcode (";", "better literal AND.");
5179 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5180 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5181 FALSE, FALSE, FALSE));
5186 // faster than result <- left, anl result,right
5187 // and better if result is SFR
5188 if (AOP_TYPE (left) == AOP_ACC)
5190 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5191 FALSE, FALSE, FALSE));
5195 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5196 emitcode ("anl", "a,%s",
5197 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5200 aopPut (AOP (result), "a", offset);
5206 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5207 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5208 freeAsmop (result, NULL, ic, TRUE);
5212 /*-----------------------------------------------------------------*/
5213 /* genOr - code for or */
5214 /*-----------------------------------------------------------------*/
5216 genOr (iCode * ic, iCode * ifx)
5218 operand *left, *right, *result;
5219 int size, offset = 0;
5220 unsigned long lit = 0L;
5223 D (emitcode (";", "genOr "););
5225 AOP_OP_3_NOFATAL (ic, pushResult);
5226 AOP_SET_LOCALS (ic);
5230 genFarFarLogicOp(ic, "orl");
5236 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5238 AOP_TYPE (left), AOP_TYPE (right));
5239 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5241 AOP_SIZE (left), AOP_SIZE (right));
5244 /* if left is a literal & right is not then exchange them */
5245 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5246 AOP_NEEDSACC (left))
5248 operand *tmp = right;
5253 /* if result = right then exchange them */
5254 if (sameRegs (AOP (result), AOP (right)))
5256 operand *tmp = right;
5261 /* if right is bit then exchange them */
5262 if (AOP_TYPE (right) == AOP_CRY &&
5263 AOP_TYPE (left) != AOP_CRY)
5265 operand *tmp = right;
5269 if (AOP_TYPE (right) == AOP_LIT)
5270 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5272 size = AOP_SIZE (result);
5276 if (AOP_TYPE (left) == AOP_CRY)
5278 if (AOP_TYPE (right) == AOP_LIT)
5280 // c = bit & literal;
5283 // lit != 0 => result = 1
5284 if (AOP_TYPE (result) == AOP_CRY)
5287 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5289 continueIfTrue (ifx);
5292 emitcode ("setb", "c");
5296 // lit == 0 => result = left
5297 if (size && sameRegs (AOP (result), AOP (left)))
5299 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5304 if (AOP_TYPE (right) == AOP_CRY)
5307 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5308 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5313 symbol *tlbl = newiTempLabel (NULL);
5314 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5315 emitcode ("setb", "c");
5316 emitcode ("jb", "%s,%05d$",
5317 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5319 emitcode ("jnz", "%05d$", tlbl->key + 100);
5320 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5322 jmpTrueOrFalse (ifx, tlbl);
5328 emitcode ("", "%05d$:", tlbl->key + 100);
5337 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5338 genIfxJump (ifx, "c");
5342 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5343 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5344 if ((AOP_TYPE (right) == AOP_LIT) &&
5345 (AOP_TYPE (result) == AOP_CRY) &&
5346 (AOP_TYPE (left) != AOP_CRY))
5352 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5354 continueIfTrue (ifx);
5359 // lit = 0, result = boolean(left)
5361 emitcode ("setb", "c");
5365 symbol *tlbl = newiTempLabel (NULL);
5366 emitcode ("jnz", "%05d$", tlbl->key + 100);
5368 emitcode ("", "%05d$:", tlbl->key + 100);
5372 genIfxJump (ifx, "a");
5380 /* if left is same as result */
5381 if (sameRegs (AOP (result), AOP (left)))
5383 for (; size--; offset++)
5385 if (AOP_TYPE (right) == AOP_LIT)
5387 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5393 if (IS_AOP_PREG (left))
5395 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5396 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5397 aopPut (AOP (result), "a", offset);
5401 emitcode ("orl", "%s,%s",
5402 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5403 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5409 if (AOP_TYPE (left) == AOP_ACC)
5411 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5415 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5416 if (IS_AOP_PREG (left))
5418 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5419 aopPut (AOP (result), "a", offset);
5423 emitcode ("orl", "%s,a",
5424 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5432 // left & result in different registers
5433 if (AOP_TYPE (result) == AOP_CRY)
5436 // if(size), result in bit
5437 // if(!size && ifx), conditional oper: if(left | right)
5438 symbol *tlbl = newiTempLabel (NULL);
5439 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5441 emitcode ("setb", "c");
5444 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5445 emitcode ("orl", "a,%s",
5446 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5447 emitcode ("jnz", "%05d$", tlbl->key + 100);
5453 emitcode ("", "%05d$:", tlbl->key + 100);
5457 jmpTrueOrFalse (ifx, tlbl);
5461 for (; (size--); offset++)
5464 // result = left & right
5465 if (AOP_TYPE (right) == AOP_LIT)
5467 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5469 aopPut (AOP (result),
5470 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5474 D (emitcode (";", "better literal OR.");
5476 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5477 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5478 FALSE, FALSE, FALSE));
5483 // faster than result <- left, anl result,right
5484 // and better if result is SFR
5485 if (AOP_TYPE (left) == AOP_ACC)
5487 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5488 FALSE, FALSE, FALSE));
5492 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5493 emitcode ("orl", "a,%s",
5494 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5497 aopPut (AOP (result), "a", offset);
5503 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5504 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5505 freeAsmop (result, NULL, ic, TRUE);
5508 /*-----------------------------------------------------------------*/
5509 /* genXor - code for xclusive or */
5510 /*-----------------------------------------------------------------*/
5512 genXor (iCode * ic, iCode * ifx)
5514 operand *left, *right, *result;
5515 int size, offset = 0;
5516 unsigned long lit = 0L;
5519 D (emitcode (";", "genXor "););
5521 AOP_OP_3_NOFATAL (ic, pushResult);
5522 AOP_SET_LOCALS (ic);
5526 genFarFarLogicOp(ic, "xrl");
5531 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5533 AOP_TYPE (left), AOP_TYPE (right));
5534 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5536 AOP_SIZE (left), AOP_SIZE (right));
5539 /* if left is a literal & right is not ||
5540 if left needs acc & right does not */
5541 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5542 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5544 operand *tmp = right;
5549 /* if result = right then exchange them */
5550 if (sameRegs (AOP (result), AOP (right)))
5552 operand *tmp = right;
5557 /* if right is bit then exchange them */
5558 if (AOP_TYPE (right) == AOP_CRY &&
5559 AOP_TYPE (left) != AOP_CRY)
5561 operand *tmp = right;
5565 if (AOP_TYPE (right) == AOP_LIT)
5566 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5568 size = AOP_SIZE (result);
5572 if (AOP_TYPE (left) == AOP_CRY)
5574 if (AOP_TYPE (right) == AOP_LIT)
5576 // c = bit & literal;
5579 // lit>>1 != 0 => result = 1
5580 if (AOP_TYPE (result) == AOP_CRY)
5583 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5585 continueIfTrue (ifx);
5588 emitcode ("setb", "c");
5595 // lit == 0, result = left
5596 if (size && sameRegs (AOP (result), AOP (left)))
5598 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5602 // lit == 1, result = not(left)
5603 if (size && sameRegs (AOP (result), AOP (left)))
5605 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5610 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5611 emitcode ("cpl", "c");
5620 symbol *tlbl = newiTempLabel (NULL);
5621 if (AOP_TYPE (right) == AOP_CRY)
5624 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5628 int sizer = AOP_SIZE (right);
5630 // if val>>1 != 0, result = 1
5631 emitcode ("setb", "c");
5634 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5636 // test the msb of the lsb
5637 emitcode ("anl", "a,#0xfe");
5638 emitcode ("jnz", "%05d$", tlbl->key + 100);
5642 emitcode ("rrc", "a");
5644 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5645 emitcode ("cpl", "c");
5646 emitcode ("", "%05d$:", (tlbl->key + 100));
5653 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5654 genIfxJump (ifx, "c");
5658 if (sameRegs (AOP (result), AOP (left)))
5660 /* if left is same as result */
5661 for (; size--; offset++)
5663 if (AOP_TYPE (right) == AOP_LIT)
5665 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5667 else if (IS_AOP_PREG (left))
5669 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5670 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5671 aopPut (AOP (result), "a", offset);
5674 emitcode ("xrl", "%s,%s",
5675 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5676 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5680 if (AOP_TYPE (left) == AOP_ACC)
5681 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5684 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5685 if (IS_AOP_PREG (left))
5687 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5688 aopPut (AOP (result), "a", offset);
5691 emitcode ("xrl", "%s,a",
5692 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5699 // left & result in different registers
5700 if (AOP_TYPE (result) == AOP_CRY)
5703 // if(size), result in bit
5704 // if(!size && ifx), conditional oper: if(left ^ right)
5705 symbol *tlbl = newiTempLabel (NULL);
5706 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5708 emitcode ("setb", "c");
5711 if ((AOP_TYPE (right) == AOP_LIT) &&
5712 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5714 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5718 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5719 emitcode ("xrl", "a,%s",
5720 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5722 emitcode ("jnz", "%05d$", tlbl->key + 100);
5728 emitcode ("", "%05d$:", tlbl->key + 100);
5732 jmpTrueOrFalse (ifx, tlbl);
5735 for (; (size--); offset++)
5738 // result = left & right
5739 if (AOP_TYPE (right) == AOP_LIT)
5741 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5743 aopPut (AOP (result),
5744 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5748 D (emitcode (";", "better literal XOR.");
5750 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5751 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5752 FALSE, FALSE, FALSE));
5756 // faster than result <- left, anl result,right
5757 // and better if result is SFR
5758 if (AOP_TYPE (left) == AOP_ACC)
5760 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5761 FALSE, FALSE, FALSE));
5765 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5766 emitcode ("xrl", "a,%s",
5767 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5770 aopPut (AOP (result), "a", offset);
5775 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5776 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5777 freeAsmop (result, NULL, ic, TRUE);
5780 /*-----------------------------------------------------------------*/
5781 /* genInline - write the inline code out */
5782 /*-----------------------------------------------------------------*/
5784 genInline (iCode * ic)
5786 char buffer[MAX_INLINEASM];
5790 D (emitcode (";", "genInline ");
5793 _G.inLine += (!options.asmpeep);
5794 strcpy (buffer, IC_INLINE (ic));
5796 /* emit each line as a code */
5821 /* emitcode("",buffer); */
5822 _G.inLine -= (!options.asmpeep);
5825 /*-----------------------------------------------------------------*/
5826 /* genRRC - rotate right with carry */
5827 /*-----------------------------------------------------------------*/
5831 operand *left, *result;
5832 int size, offset = 0;
5835 D (emitcode (";", "genRRC ");
5838 /* rotate right with carry */
5839 left = IC_LEFT (ic);
5840 result = IC_RESULT (ic);
5841 aopOp (left, ic, FALSE, FALSE);
5842 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5844 /* move it to the result */
5845 size = AOP_SIZE (result);
5849 _startLazyDPSEvaluation ();
5852 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5854 emitcode ("rrc", "a");
5855 if (AOP_SIZE (result) > 1)
5856 aopPut (AOP (result), "a", offset--);
5858 _endLazyDPSEvaluation ();
5860 /* now we need to put the carry into the
5861 highest order byte of the result */
5862 if (AOP_SIZE (result) > 1)
5864 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5867 emitcode ("mov", "acc.7,c");
5868 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5869 freeAsmop (left, NULL, ic, TRUE);
5870 freeAsmop (result, NULL, ic, TRUE);
5873 /*-----------------------------------------------------------------*/
5874 /* genRLC - generate code for rotate left with carry */
5875 /*-----------------------------------------------------------------*/
5879 operand *left, *result;
5880 int size, offset = 0;
5883 D (emitcode (";", "genRLC ");
5886 /* rotate right with carry */
5887 left = IC_LEFT (ic);
5888 result = IC_RESULT (ic);
5889 aopOp (left, ic, FALSE, FALSE);
5890 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5892 /* move it to the result */
5893 size = AOP_SIZE (result);
5897 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5899 emitcode ("add", "a,acc");
5900 if (AOP_SIZE (result) > 1)
5902 aopPut (AOP (result), "a", offset++);
5905 _startLazyDPSEvaluation ();
5908 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5910 emitcode ("rlc", "a");
5911 if (AOP_SIZE (result) > 1)
5912 aopPut (AOP (result), "a", offset++);
5914 _endLazyDPSEvaluation ();
5916 /* now we need to put the carry into the
5917 highest order byte of the result */
5918 if (AOP_SIZE (result) > 1)
5920 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5923 emitcode ("mov", "acc.0,c");
5924 aopPut (AOP (result), "a", 0);
5925 freeAsmop (left, NULL, ic, TRUE);
5926 freeAsmop (result, NULL, ic, TRUE);
5929 /*-----------------------------------------------------------------*/
5930 /* genGetHbit - generates code get highest order bit */
5931 /*-----------------------------------------------------------------*/
5933 genGetHbit (iCode * ic)
5935 operand *left, *result;
5936 left = IC_LEFT (ic);
5937 result = IC_RESULT (ic);
5938 aopOp (left, ic, FALSE, FALSE);
5939 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5941 D (emitcode (";", "genGetHbit ");
5944 /* get the highest order byte into a */
5945 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5946 if (AOP_TYPE (result) == AOP_CRY)
5948 emitcode ("rlc", "a");
5953 emitcode ("rl", "a");
5954 emitcode ("anl", "a,#0x01");
5959 freeAsmop (left, NULL, ic, TRUE);
5960 freeAsmop (result, NULL, ic, TRUE);
5963 /*-----------------------------------------------------------------*/
5964 /* AccRol - rotate left accumulator by known count */
5965 /*-----------------------------------------------------------------*/
5967 AccRol (int shCount)
5969 shCount &= 0x0007; // shCount : 0..7
5976 emitcode ("rl", "a");
5979 emitcode ("rl", "a");
5980 emitcode ("rl", "a");
5983 emitcode ("swap", "a");
5984 emitcode ("rr", "a");
5987 emitcode ("swap", "a");
5990 emitcode ("swap", "a");
5991 emitcode ("rl", "a");
5994 emitcode ("rr", "a");
5995 emitcode ("rr", "a");
5998 emitcode ("rr", "a");
6003 /*-----------------------------------------------------------------*/
6004 /* AccLsh - left shift accumulator by known count */
6005 /*-----------------------------------------------------------------*/
6007 AccLsh (int shCount)
6012 emitcode ("add", "a,acc");
6013 else if (shCount == 2)
6015 emitcode ("add", "a,acc");
6016 emitcode ("add", "a,acc");
6020 /* rotate left accumulator */
6022 /* and kill the lower order bits */
6023 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6028 /*-----------------------------------------------------------------*/
6029 /* AccRsh - right shift accumulator by known count */
6030 /*-----------------------------------------------------------------*/
6032 AccRsh (int shCount)
6039 emitcode ("rrc", "a");
6043 /* rotate right accumulator */
6044 AccRol (8 - shCount);
6045 /* and kill the higher order bits */
6046 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6051 #ifdef BETTER_LITERAL_SHIFT
6052 /*-----------------------------------------------------------------*/
6053 /* AccSRsh - signed right shift accumulator by known count */
6054 /*-----------------------------------------------------------------*/
6056 AccSRsh (int shCount)
6063 emitcode ("mov", "c,acc.7");
6064 emitcode ("rrc", "a");
6066 else if (shCount == 2)
6068 emitcode ("mov", "c,acc.7");
6069 emitcode ("rrc", "a");
6070 emitcode ("mov", "c,acc.7");
6071 emitcode ("rrc", "a");
6075 tlbl = newiTempLabel (NULL);
6076 /* rotate right accumulator */
6077 AccRol (8 - shCount);
6078 /* and kill the higher order bits */
6079 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6080 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6081 emitcode ("orl", "a,#0x%02x",
6082 (unsigned char) ~SRMask[shCount]);
6083 emitcode ("", "%05d$:", tlbl->key + 100);
6089 #ifdef BETTER_LITERAL_SHIFT
6090 /*-----------------------------------------------------------------*/
6091 /* shiftR1Left2Result - shift right one byte from left to result */
6092 /*-----------------------------------------------------------------*/
6094 shiftR1Left2Result (operand * left, int offl,
6095 operand * result, int offr,
6096 int shCount, int sign)
6098 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6099 /* shift right accumulator */
6104 aopPut (AOP (result), "a", offr);
6108 #ifdef BETTER_LITERAL_SHIFT
6109 /*-----------------------------------------------------------------*/
6110 /* shiftL1Left2Result - shift left one byte from left to result */
6111 /*-----------------------------------------------------------------*/
6113 shiftL1Left2Result (operand * left, int offl,
6114 operand * result, int offr, int shCount)
6116 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6117 /* shift left accumulator */
6119 aopPut (AOP (result), "a", offr);
6123 #ifdef BETTER_LITERAL_SHIFT
6124 /*-----------------------------------------------------------------*/
6125 /* movLeft2Result - move byte from left to result */
6126 /*-----------------------------------------------------------------*/
6128 movLeft2Result (operand * left, int offl,
6129 operand * result, int offr, int sign)
6132 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6134 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6136 if (*l == '@' && (IS_AOP_PREG (result)))
6138 emitcode ("mov", "a,%s", l);
6139 aopPut (AOP (result), "a", offr);
6145 aopPut (AOP (result), l, offr);
6149 /* MSB sign in acc.7 ! */
6150 if (getDataSize (left) == offl + 1)
6152 emitcode ("mov", "a,%s", l);
6153 aopPut (AOP (result), "a", offr);
6161 #ifdef BETTER_LITERAL_SHIFT
6162 /*-----------------------------------------------------------------*/
6163 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6164 /*-----------------------------------------------------------------*/
6168 emitcode ("rrc", "a");
6169 emitcode ("xch", "a,%s", x);
6170 emitcode ("rrc", "a");
6171 emitcode ("xch", "a,%s", x);
6175 #ifdef BETTER_LITERAL_SHIFT
6177 /*-----------------------------------------------------------------*/
6178 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6179 /*-----------------------------------------------------------------*/
6183 emitcode ("xch", "a,%s", x);
6184 emitcode ("rlc", "a");
6185 emitcode ("xch", "a,%s", x);
6186 emitcode ("rlc", "a");
6190 #ifdef BETTER_LITERAL_SHIFT
6191 /*-----------------------------------------------------------------*/
6192 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6193 /*-----------------------------------------------------------------*/
6197 emitcode ("xch", "a,%s", x);
6198 emitcode ("add", "a,acc");
6199 emitcode ("xch", "a,%s", x);
6200 emitcode ("rlc", "a");
6204 #ifdef BETTER_LITERAL_SHIFT
6205 /*-----------------------------------------------------------------*/
6206 /* AccAXLsh - left shift a:x by known count (0..7) */
6207 /*-----------------------------------------------------------------*/
6209 AccAXLsh (char *x, int shCount)
6224 case 5: // AAAAABBB:CCCCCDDD
6226 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6228 emitcode ("anl", "a,#0x%02x",
6229 SLMask[shCount]); // BBB00000:CCCCCDDD
6231 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6233 AccRol (shCount); // DDDCCCCC:BBB00000
6235 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6237 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6239 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6241 emitcode ("anl", "a,#0x%02x",
6242 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6244 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6246 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6249 case 6: // AAAAAABB:CCCCCCDD
6250 emitcode ("anl", "a,#0x%02x",
6251 SRMask[shCount]); // 000000BB:CCCCCCDD
6252 emitcode ("mov", "c,acc.0"); // c = B
6253 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6255 AccAXRrl1 (x); // BCCCCCCD:D000000B
6256 AccAXRrl1 (x); // BBCCCCCC:DD000000
6258 emitcode("rrc","a");
6259 emitcode("xch","a,%s", x);
6260 emitcode("rrc","a");
6261 emitcode("mov","c,acc.0"); //<< get correct bit
6262 emitcode("xch","a,%s", x);
6264 emitcode("rrc","a");
6265 emitcode("xch","a,%s", x);
6266 emitcode("rrc","a");
6267 emitcode("xch","a,%s", x);
6270 case 7: // a:x <<= 7
6272 emitcode ("anl", "a,#0x%02x",
6273 SRMask[shCount]); // 0000000B:CCCCCCCD
6275 emitcode ("mov", "c,acc.0"); // c = B
6277 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6279 AccAXRrl1 (x); // BCCCCCCC:D0000000
6288 #ifdef BETTER_LITERAL_SHIFT
6290 /*-----------------------------------------------------------------*/
6291 /* AccAXRsh - right shift a:x known count (0..7) */
6292 /*-----------------------------------------------------------------*/
6294 AccAXRsh (char *x, int shCount)
6302 AccAXRrl1 (x); // 0->a:x
6307 AccAXRrl1 (x); // 0->a:x
6310 AccAXRrl1 (x); // 0->a:x
6315 case 5: // AAAAABBB:CCCCCDDD = a:x
6317 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6319 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6321 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6323 emitcode ("anl", "a,#0x%02x",
6324 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6326 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6328 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6330 emitcode ("anl", "a,#0x%02x",
6331 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6333 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6335 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6337 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6340 case 6: // AABBBBBB:CCDDDDDD
6342 emitcode ("mov", "c,acc.7");
6343 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6345 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6347 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6349 emitcode ("anl", "a,#0x%02x",
6350 SRMask[shCount]); // 000000AA:BBBBBBCC
6353 case 7: // ABBBBBBB:CDDDDDDD
6355 emitcode ("mov", "c,acc.7"); // c = A
6357 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6359 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6361 emitcode ("anl", "a,#0x%02x",
6362 SRMask[shCount]); // 0000000A:BBBBBBBC
6371 #ifdef BETTER_LITERAL_SHIFT
6373 /*-----------------------------------------------------------------*/
6374 /* AccAXRshS - right shift signed a:x known count (0..7) */
6375 /*-----------------------------------------------------------------*/
6377 AccAXRshS (char *x, int shCount)
6385 emitcode ("mov", "c,acc.7");
6386 AccAXRrl1 (x); // s->a:x
6390 emitcode ("mov", "c,acc.7");
6391 AccAXRrl1 (x); // s->a:x
6393 emitcode ("mov", "c,acc.7");
6394 AccAXRrl1 (x); // s->a:x
6399 case 5: // AAAAABBB:CCCCCDDD = a:x
6401 tlbl = newiTempLabel (NULL);
6402 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6404 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6406 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6408 emitcode ("anl", "a,#0x%02x",
6409 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6411 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6413 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6415 emitcode ("anl", "a,#0x%02x",
6416 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6418 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6420 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6422 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6424 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6425 emitcode ("orl", "a,#0x%02x",
6426 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6428 emitcode ("", "%05d$:", tlbl->key + 100);
6429 break; // SSSSAAAA:BBBCCCCC
6431 case 6: // AABBBBBB:CCDDDDDD
6433 tlbl = newiTempLabel (NULL);
6434 emitcode ("mov", "c,acc.7");
6435 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6437 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6439 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6441 emitcode ("anl", "a,#0x%02x",
6442 SRMask[shCount]); // 000000AA:BBBBBBCC
6444 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6445 emitcode ("orl", "a,#0x%02x",
6446 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6448 emitcode ("", "%05d$:", tlbl->key + 100);
6450 case 7: // ABBBBBBB:CDDDDDDD
6452 tlbl = newiTempLabel (NULL);
6453 emitcode ("mov", "c,acc.7"); // c = A
6455 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6457 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6459 emitcode ("anl", "a,#0x%02x",
6460 SRMask[shCount]); // 0000000A:BBBBBBBC
6462 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6463 emitcode ("orl", "a,#0x%02x",
6464 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6466 emitcode ("", "%05d$:", tlbl->key + 100);
6474 #ifdef BETTER_LITERAL_SHIFT
6476 _loadLeftIntoAx(char **lsb,
6482 // Get the initial value from left into a pair of registers.
6483 // MSB must be in A, LSB can be any register.
6485 // If the result is held in registers, it is an optimization
6486 // if the LSB can be held in the register which will hold the,
6487 // result LSB since this saves us from having to copy it into
6488 // the result following AccAXLsh.
6490 // If the result is addressed indirectly, this is not a gain.
6491 if (AOP_NEEDSACC(result))
6495 _startLazyDPSEvaluation();
6496 if (AOP_TYPE(left) == AOP_DPTR2)
6499 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6500 // get LSB in DP2_RESULT_REG.
6501 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6502 assert(!strcmp(leftByte, DP2_RESULT_REG));
6506 // get LSB into DP2_RESULT_REG
6507 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6508 if (strcmp(leftByte, DP2_RESULT_REG))
6510 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6513 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6514 assert(strcmp(leftByte, DP2_RESULT_REG));
6517 _endLazyDPSEvaluation();
6518 *lsb = DP2_RESULT_REG;
6522 if (sameRegs (AOP (result), AOP (left)) &&
6523 ((offl + MSB16) == offr))
6525 /* don't crash result[offr] */
6526 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6527 emitcode ("xch", "a,%s",
6528 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6532 movLeft2Result (left, offl, result, offr, 0);
6533 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6535 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6536 assert(strcmp(*lsb,"a"));
6541 _storeAxResults(char *lsb,
6545 _startLazyDPSEvaluation();
6546 if (AOP_NEEDSACC(result))
6548 /* We have to explicitly update the result LSB.
6550 emitcode("xch","a,%s", lsb);
6551 aopPut(AOP(result), "a", offr);
6552 emitcode("mov","a,%s", lsb);
6554 if (getDataSize (result) > 1)
6556 aopPut (AOP (result), "a", offr + MSB16);
6558 _endLazyDPSEvaluation();
6561 /*-----------------------------------------------------------------*/
6562 /* shiftL2Left2Result - shift left two bytes from left to result */
6563 /*-----------------------------------------------------------------*/
6565 shiftL2Left2Result (operand * left, int offl,
6566 operand * result, int offr, int shCount)
6570 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6572 AccAXLsh (lsb, shCount);
6574 _storeAxResults(lsb, result, offr);
6578 #ifdef BETTER_LITERAL_SHIFT
6579 /*-----------------------------------------------------------------*/
6580 /* shiftR2Left2Result - shift right two bytes from left to result */
6581 /*-----------------------------------------------------------------*/
6583 shiftR2Left2Result (operand * left, int offl,
6584 operand * result, int offr,
6585 int shCount, int sign)
6589 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6591 /* a:x >> shCount (x = lsb(result)) */
6594 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6598 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6601 _storeAxResults(lsb, result, offr);
6607 /*-----------------------------------------------------------------*/
6608 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6609 /*-----------------------------------------------------------------*/
6611 shiftLLeftOrResult (operand * left, int offl,
6612 operand * result, int offr, int shCount)
6614 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6615 /* shift left accumulator */
6617 /* or with result */
6618 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6619 /* back to result */
6620 aopPut (AOP (result), "a", offr);
6626 /*-----------------------------------------------------------------*/
6627 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6628 /*-----------------------------------------------------------------*/
6630 shiftRLeftOrResult (operand * left, int offl,
6631 operand * result, int offr, int shCount)
6633 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6634 /* shift right accumulator */
6636 /* or with result */
6637 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6638 /* back to result */
6639 aopPut (AOP (result), "a", offr);
6643 #ifdef BETTER_LITERAL_SHIFT
6644 /*-----------------------------------------------------------------*/
6645 /* genlshOne - left shift a one byte quantity by known count */
6646 /*-----------------------------------------------------------------*/
6648 genlshOne (operand * result, operand * left, int shCount)
6650 D (emitcode (";", "genlshOne "););
6651 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6655 #ifdef BETTER_LITERAL_SHIFT
6656 /*-----------------------------------------------------------------*/
6657 /* genlshTwo - left shift two bytes by known amount != 0 */
6658 /*-----------------------------------------------------------------*/
6660 genlshTwo (operand * result, operand * left, int shCount)
6664 D (emitcode (";", "genlshTwo "););
6666 size = getDataSize (result);
6668 /* if shCount >= 8 */
6673 _startLazyDPSEvaluation();
6679 _endLazyDPSEvaluation();
6680 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6681 aopPut (AOP (result), zero, LSB);
6685 movLeft2Result (left, LSB, result, MSB16, 0);
6686 aopPut (AOP (result), zero, LSB);
6687 _endLazyDPSEvaluation();
6692 aopPut (AOP (result), zero, LSB);
6693 _endLazyDPSEvaluation();
6697 /* 1 <= shCount <= 7 */
6702 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6706 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6714 /*-----------------------------------------------------------------*/
6715 /* shiftLLong - shift left one long from left to result */
6716 /* offl = LSB or MSB16 */
6717 /*-----------------------------------------------------------------*/
6719 shiftLLong (operand * left, operand * result, int offr)
6722 int size = AOP_SIZE (result);
6724 if (size >= LSB + offr)
6726 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6728 emitcode ("add", "a,acc");
6729 if (sameRegs (AOP (left), AOP (result)) &&
6730 size >= MSB16 + offr && offr != LSB)
6731 emitcode ("xch", "a,%s",
6732 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6734 aopPut (AOP (result), "a", LSB + offr);
6737 if (size >= MSB16 + offr)
6739 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6741 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6744 emitcode ("rlc", "a");
6745 if (sameRegs (AOP (left), AOP (result)) &&
6746 size >= MSB24 + offr && offr != LSB)
6747 emitcode ("xch", "a,%s",
6748 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6750 aopPut (AOP (result), "a", MSB16 + offr);
6753 if (size >= MSB24 + offr)
6755 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6757 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6760 emitcode ("rlc", "a");
6761 if (sameRegs (AOP (left), AOP (result)) &&
6762 size >= MSB32 + offr && offr != LSB)
6763 emitcode ("xch", "a,%s",
6764 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6766 aopPut (AOP (result), "a", MSB24 + offr);
6769 if (size > MSB32 + offr)
6771 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6773 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6776 emitcode ("rlc", "a");
6777 aopPut (AOP (result), "a", MSB32 + offr);
6780 aopPut (AOP (result), zero, LSB);
6786 /*-----------------------------------------------------------------*/
6787 /* genlshFour - shift four byte by a known amount != 0 */
6788 /*-----------------------------------------------------------------*/
6790 genlshFour (operand * result, operand * left, int shCount)
6794 D (emitcode (";", "genlshFour ");
6797 size = AOP_SIZE (result);
6799 /* if shifting more that 3 bytes */
6804 /* lowest order of left goes to the highest
6805 order of the destination */
6806 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6808 movLeft2Result (left, LSB, result, MSB32, 0);
6809 aopPut (AOP (result), zero, LSB);
6810 aopPut (AOP (result), zero, MSB16);
6811 aopPut (AOP (result), zero, MSB24);
6815 /* more than two bytes */
6816 else if (shCount >= 16)
6818 /* lower order two bytes goes to higher order two bytes */
6820 /* if some more remaining */
6822 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6825 movLeft2Result (left, MSB16, result, MSB32, 0);
6826 movLeft2Result (left, LSB, result, MSB24, 0);
6828 aopPut (AOP (result), zero, MSB16);
6829 aopPut (AOP (result), zero, LSB);
6833 /* if more than 1 byte */
6834 else if (shCount >= 8)
6836 /* lower order three bytes goes to higher order three bytes */
6841 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6843 movLeft2Result (left, LSB, result, MSB16, 0);
6849 movLeft2Result (left, MSB24, result, MSB32, 0);
6850 movLeft2Result (left, MSB16, result, MSB24, 0);
6851 movLeft2Result (left, LSB, result, MSB16, 0);
6852 aopPut (AOP (result), zero, LSB);
6854 else if (shCount == 1)
6855 shiftLLong (left, result, MSB16);
6858 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6859 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6860 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6861 aopPut (AOP (result), zero, LSB);
6866 /* 1 <= shCount <= 7 */
6867 else if (shCount <= 2)
6869 shiftLLong (left, result, LSB);
6871 shiftLLong (result, result, LSB);
6873 /* 3 <= shCount <= 7, optimize */
6876 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6877 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6878 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6883 #ifdef BETTER_LITERAL_SHIFT
6884 /*-----------------------------------------------------------------*/
6885 /* genLeftShiftLiteral - left shifting by known count */
6886 /*-----------------------------------------------------------------*/
6888 genLeftShiftLiteral (operand * left,
6893 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6896 size = getSize (operandType (result));
6898 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6900 /* We only handle certain easy cases so far. */
6902 && (shCount < (size * 8))
6906 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6910 freeAsmop (right, NULL, ic, TRUE);
6912 aopOp(left, ic, FALSE, FALSE);
6913 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6916 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6918 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6919 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6921 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6924 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6926 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6927 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6929 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6935 emitcode ("; shift left ", "result %d, left %d", size,
6939 /* I suppose that the left size >= result size */
6942 _startLazyDPSEvaluation();
6945 movLeft2Result (left, size, result, size, 0);
6947 _endLazyDPSEvaluation();
6949 else if (shCount >= (size * 8))
6951 _startLazyDPSEvaluation();
6954 aopPut (AOP (result), zero, size);
6956 _endLazyDPSEvaluation();
6963 genlshOne (result, left, shCount);
6967 genlshTwo (result, left, shCount);
6971 genlshFour (result, left, shCount);
6975 fprintf(stderr, "*** ack! mystery literal shift!\n");
6979 freeAsmop (left, NULL, ic, TRUE);
6980 freeAsmop (result, NULL, ic, TRUE);
6985 /*-----------------------------------------------------------------*/
6986 /* genLeftShift - generates code for left shifting */
6987 /*-----------------------------------------------------------------*/
6989 genLeftShift (iCode * ic)
6991 operand *left, *right, *result;
6994 symbol *tlbl, *tlbl1;
6996 D (emitcode (";", "genLeftShift "););
6998 right = IC_RIGHT (ic);
6999 left = IC_LEFT (ic);
7000 result = IC_RESULT (ic);
7002 aopOp (right, ic, FALSE, FALSE);
7005 #ifdef BETTER_LITERAL_SHIFT
7006 /* if the shift count is known then do it
7007 as efficiently as possible */
7008 if (AOP_TYPE (right) == AOP_LIT)
7010 if (genLeftShiftLiteral (left, right, result, ic))
7017 /* shift count is unknown then we have to form
7018 a loop get the loop count in B : Note: we take
7019 only the lower order byte since shifting
7020 more that 32 bits make no sense anyway, ( the
7021 largest size of an object can be only 32 bits ) */
7023 if (AOP_TYPE (right) == AOP_LIT)
7025 /* Really should be handled by genLeftShiftLiteral,
7026 * but since I'm too lazy to fix that today, at least we can make
7027 * some small improvement.
7029 emitcode("mov", "b,#0x%02x",
7030 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7034 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7035 emitcode ("inc", "b");
7037 freeAsmop (right, NULL, ic, TRUE);
7038 aopOp (left, ic, FALSE, FALSE);
7039 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7041 /* now move the left to the result if they are not the
7043 if (!sameRegs (AOP (left), AOP (result)) &&
7044 AOP_SIZE (result) > 1)
7047 size = AOP_SIZE (result);
7049 _startLazyDPSEvaluation ();
7052 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7053 if (*l == '@' && (IS_AOP_PREG (result)))
7056 emitcode ("mov", "a,%s", l);
7057 aopPut (AOP (result), "a", offset);
7060 aopPut (AOP (result), l, offset);
7063 _endLazyDPSEvaluation ();
7066 tlbl = newiTempLabel (NULL);
7067 size = AOP_SIZE (result);
7069 tlbl1 = newiTempLabel (NULL);
7071 /* if it is only one byte then */
7074 symbol *tlbl1 = newiTempLabel (NULL);
7076 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7078 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7079 emitcode ("", "%05d$:", tlbl->key + 100);
7080 emitcode ("add", "a,acc");
7081 emitcode ("", "%05d$:", tlbl1->key + 100);
7082 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7083 aopPut (AOP (result), "a", 0);
7087 reAdjustPreg (AOP (result));
7089 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7090 emitcode ("", "%05d$:", tlbl->key + 100);
7091 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7093 emitcode ("add", "a,acc");
7094 aopPut (AOP (result), "a", offset++);
7095 _startLazyDPSEvaluation ();
7098 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7100 emitcode ("rlc", "a");
7101 aopPut (AOP (result), "a", offset++);
7103 _endLazyDPSEvaluation ();
7104 reAdjustPreg (AOP (result));
7106 emitcode ("", "%05d$:", tlbl1->key + 100);
7107 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7109 freeAsmop (left, NULL, ic, TRUE);
7110 freeAsmop (result, NULL, ic, TRUE);
7113 #ifdef BETTER_LITERAL_SHIFT
7114 /*-----------------------------------------------------------------*/
7115 /* genrshOne - right shift a one byte quantity by known count */
7116 /*-----------------------------------------------------------------*/
7118 genrshOne (operand * result, operand * left,
7119 int shCount, int sign)
7121 D (emitcode (";", "genrshOne"););
7122 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7126 #ifdef BETTER_LITERAL_SHIFT
7127 /*-----------------------------------------------------------------*/
7128 /* genrshTwo - right shift two bytes by known amount != 0 */
7129 /*-----------------------------------------------------------------*/
7131 genrshTwo (operand * result, operand * left,
7132 int shCount, int sign)
7134 D (emitcode (";", "genrshTwo"););
7136 /* if shCount >= 8 */
7140 _startLazyDPSEvaluation();
7143 shiftR1Left2Result (left, MSB16, result, LSB,
7148 movLeft2Result (left, MSB16, result, LSB, sign);
7150 addSign (result, MSB16, sign);
7151 _endLazyDPSEvaluation();
7154 /* 1 <= shCount <= 7 */
7157 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7164 /*-----------------------------------------------------------------*/
7165 /* shiftRLong - shift right one long from left to result */
7166 /* offl = LSB or MSB16 */
7167 /*-----------------------------------------------------------------*/
7169 shiftRLong (operand * left, int offl,
7170 operand * result, int sign)
7173 emitcode ("clr", "c");
7174 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7176 emitcode ("mov", "c,acc.7");
7177 emitcode ("rrc", "a");
7178 aopPut (AOP (result), "a", MSB32 - offl);
7180 /* add sign of "a" */
7181 addSign (result, MSB32, sign);
7183 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7184 emitcode ("rrc", "a");
7185 aopPut (AOP (result), "a", MSB24 - offl);
7187 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7188 emitcode ("rrc", "a");
7189 aopPut (AOP (result), "a", MSB16 - offl);
7193 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7194 emitcode ("rrc", "a");
7195 aopPut (AOP (result), "a", LSB);
7202 /*-----------------------------------------------------------------*/
7203 /* genrshFour - shift four byte by a known amount != 0 */
7204 /*-----------------------------------------------------------------*/
7206 genrshFour (operand * result, operand * left,
7207 int shCount, int sign)
7209 D (emitcode (";", "genrshFour");
7212 /* if shifting more that 3 bytes */
7217 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7219 movLeft2Result (left, MSB32, result, LSB, sign);
7220 addSign (result, MSB16, sign);
7222 else if (shCount >= 16)
7226 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7229 movLeft2Result (left, MSB24, result, LSB, 0);
7230 movLeft2Result (left, MSB32, result, MSB16, sign);
7232 addSign (result, MSB24, sign);
7234 else if (shCount >= 8)
7238 shiftRLong (left, MSB16, result, sign);
7239 else if (shCount == 0)
7241 movLeft2Result (left, MSB16, result, LSB, 0);
7242 movLeft2Result (left, MSB24, result, MSB16, 0);
7243 movLeft2Result (left, MSB32, result, MSB24, sign);
7244 addSign (result, MSB32, sign);
7248 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7249 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7250 /* the last shift is signed */
7251 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7252 addSign (result, MSB32, sign);
7256 { /* 1 <= shCount <= 7 */
7259 shiftRLong (left, LSB, result, sign);
7261 shiftRLong (result, LSB, result, sign);
7265 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7266 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7267 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7273 #ifdef BETTER_LITERAL_SHIFT
7274 /*-----------------------------------------------------------------*/
7275 /* genRightShiftLiteral - right shifting by known count */
7276 /*-----------------------------------------------------------------*/
7278 genRightShiftLiteral (operand * left,
7284 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7287 size = getSize (operandType (result));
7289 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7291 /* We only handle certain easy cases so far. */
7293 && (shCount < (size * 8))
7297 D(emitcode (";", "genRightShiftLiteral wimping out"););
7301 freeAsmop (right, NULL, ic, TRUE);
7303 aopOp (left, ic, FALSE, FALSE);
7304 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7307 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7311 /* test the LEFT size !!! */
7313 /* I suppose that the left size >= result size */
7316 size = getDataSize (result);
7317 _startLazyDPSEvaluation();
7320 movLeft2Result (left, size, result, size, 0);
7322 _endLazyDPSEvaluation();
7324 else if (shCount >= (size * 8))
7328 /* get sign in acc.7 */
7329 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7331 addSign (result, LSB, sign);
7338 genrshOne (result, left, shCount, sign);
7342 genrshTwo (result, left, shCount, sign);
7346 genrshFour (result, left, shCount, sign);
7353 freeAsmop (left, NULL, ic, TRUE);
7354 freeAsmop (result, NULL, ic, TRUE);
7360 /*-----------------------------------------------------------------*/
7361 /* genSignedRightShift - right shift of signed number */
7362 /*-----------------------------------------------------------------*/
7364 genSignedRightShift (iCode * ic)
7366 operand *right, *left, *result;
7369 symbol *tlbl, *tlbl1;
7371 D (emitcode (";", "genSignedRightShift "););
7373 /* we do it the hard way put the shift count in b
7374 and loop thru preserving the sign */
7376 right = IC_RIGHT (ic);
7377 left = IC_LEFT (ic);
7378 result = IC_RESULT (ic);
7380 aopOp (right, ic, FALSE, FALSE);
7382 #ifdef BETTER_LITERAL_SHIFT
7383 if (AOP_TYPE (right) == AOP_LIT)
7385 if (genRightShiftLiteral (left, right, result, ic, 1))
7391 /* shift count is unknown then we have to form
7392 a loop get the loop count in B : Note: we take
7393 only the lower order byte since shifting
7394 more that 32 bits make no sense anyway, ( the
7395 largest size of an object can be only 32 bits ) */
7397 if (AOP_TYPE (right) == AOP_LIT)
7399 /* Really should be handled by genRightShiftLiteral,
7400 * but since I'm too lazy to fix that today, at least we can make
7401 * some small improvement.
7403 emitcode("mov", "b,#0x%02x",
7404 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7408 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7409 emitcode ("inc", "b");
7411 freeAsmop (right, NULL, ic, TRUE);
7412 aopOp (left, ic, FALSE, FALSE);
7413 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7415 /* now move the left to the result if they are not the
7417 if (!sameRegs (AOP (left), AOP (result)) &&
7418 AOP_SIZE (result) > 1)
7421 size = AOP_SIZE (result);
7423 _startLazyDPSEvaluation ();
7426 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7427 if (*l == '@' && IS_AOP_PREG (result))
7430 emitcode ("mov", "a,%s", l);
7431 aopPut (AOP (result), "a", offset);
7434 aopPut (AOP (result), l, offset);
7437 _endLazyDPSEvaluation ();
7440 /* mov the highest order bit to OVR */
7441 tlbl = newiTempLabel (NULL);
7442 tlbl1 = newiTempLabel (NULL);
7444 size = AOP_SIZE (result);
7446 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7447 emitcode ("rlc", "a");
7448 emitcode ("mov", "ov,c");
7449 /* if it is only one byte then */
7452 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7454 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7455 emitcode ("", "%05d$:", tlbl->key + 100);
7456 emitcode ("mov", "c,ov");
7457 emitcode ("rrc", "a");
7458 emitcode ("", "%05d$:", tlbl1->key + 100);
7459 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7460 aopPut (AOP (result), "a", 0);
7464 reAdjustPreg (AOP (result));
7465 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7466 emitcode ("", "%05d$:", tlbl->key + 100);
7467 emitcode ("mov", "c,ov");
7468 _startLazyDPSEvaluation ();
7471 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7473 emitcode ("rrc", "a");
7474 aopPut (AOP (result), "a", offset--);
7476 _endLazyDPSEvaluation ();
7477 reAdjustPreg (AOP (result));
7478 emitcode ("", "%05d$:", tlbl1->key + 100);
7479 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7482 freeAsmop (left, NULL, ic, TRUE);
7483 freeAsmop (result, NULL, ic, TRUE);
7486 /*-----------------------------------------------------------------*/
7487 /* genRightShift - generate code for right shifting */
7488 /*-----------------------------------------------------------------*/
7490 genRightShift (iCode * ic)
7492 operand *right, *left, *result;
7496 symbol *tlbl, *tlbl1;
7498 D (emitcode (";", "genRightShift "););
7500 /* if signed then we do it the hard way preserve the
7501 sign bit moving it inwards */
7502 retype = getSpec (operandType (IC_RESULT (ic)));
7504 if (!SPEC_USIGN (retype))
7506 genSignedRightShift (ic);
7510 /* signed & unsigned types are treated the same : i.e. the
7511 signed is NOT propagated inwards : quoting from the
7512 ANSI - standard : "for E1 >> E2, is equivalent to division
7513 by 2**E2 if unsigned or if it has a non-negative value,
7514 otherwise the result is implementation defined ", MY definition
7515 is that the sign does not get propagated */
7517 right = IC_RIGHT (ic);
7518 left = IC_LEFT (ic);
7519 result = IC_RESULT (ic);
7521 aopOp (right, ic, FALSE, FALSE);
7523 #ifdef BETTER_LITERAL_SHIFT
7524 /* if the shift count is known then do it
7525 as efficiently as possible */
7526 if (AOP_TYPE (right) == AOP_LIT)
7528 if (genRightShiftLiteral (left, right, result, ic, 0))
7535 /* shift count is unknown then we have to form
7536 a loop get the loop count in B : Note: we take
7537 only the lower order byte since shifting
7538 more that 32 bits make no sense anyway, ( the
7539 largest size of an object can be only 32 bits ) */
7541 if (AOP_TYPE (right) == AOP_LIT)
7543 /* Really should be handled by genRightShiftLiteral,
7544 * but since I'm too lazy to fix that today, at least we can make
7545 * some small improvement.
7547 emitcode("mov", "b,#0x%02x",
7548 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7552 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7553 emitcode ("inc", "b");
7555 freeAsmop (right, NULL, ic, TRUE);
7556 aopOp (left, ic, FALSE, FALSE);
7557 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7559 /* now move the left to the result if they are not the
7561 if (!sameRegs (AOP (left), AOP (result)) &&
7562 AOP_SIZE (result) > 1)
7565 size = AOP_SIZE (result);
7567 _startLazyDPSEvaluation ();
7570 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7571 if (*l == '@' && IS_AOP_PREG (result))
7574 emitcode ("mov", "a,%s", l);
7575 aopPut (AOP (result), "a", offset);
7578 aopPut (AOP (result), l, offset);
7581 _endLazyDPSEvaluation ();
7584 tlbl = newiTempLabel (NULL);
7585 tlbl1 = newiTempLabel (NULL);
7586 size = AOP_SIZE (result);
7589 /* if it is only one byte then */
7592 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7594 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7595 emitcode ("", "%05d$:", tlbl->key + 100);
7597 emitcode ("rrc", "a");
7598 emitcode ("", "%05d$:", tlbl1->key + 100);
7599 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7600 aopPut (AOP (result), "a", 0);
7604 reAdjustPreg (AOP (result));
7605 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7606 emitcode ("", "%05d$:", tlbl->key + 100);
7608 _startLazyDPSEvaluation ();
7611 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7613 emitcode ("rrc", "a");
7614 aopPut (AOP (result), "a", offset--);
7616 _endLazyDPSEvaluation ();
7617 reAdjustPreg (AOP (result));
7619 emitcode ("", "%05d$:", tlbl1->key + 100);
7620 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7623 freeAsmop (left, NULL, ic, TRUE);
7624 freeAsmop (result, NULL, ic, TRUE);
7627 /*-----------------------------------------------------------------*/
7628 /* genUnpackBits - generates code for unpacking bits */
7629 /*-----------------------------------------------------------------*/
7631 genUnpackBits (operand * result, char *rname, int ptype)
7638 D (emitcode (";", "genUnpackBits ");
7641 etype = getSpec (operandType (result));
7643 /* read the first byte */
7649 emitcode ("mov", "a,@%s", rname);
7653 emitcode ("movx", "a,@%s", rname);
7657 emitcode ("movx", "a,@dptr");
7661 emitcode ("clr", "a");
7662 emitcode ("movc", "a", "@a+dptr");
7666 emitcode ("lcall", "__gptrget");
7670 /* if we have bitdisplacement then it fits */
7671 /* into this byte completely or if length is */
7672 /* less than a byte */
7673 if ((shCnt = SPEC_BSTR (etype)) ||
7674 (SPEC_BLEN (etype) <= 8))
7677 /* shift right acc */
7680 emitcode ("anl", "a,#0x%02x",
7681 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7682 aopPut (AOP (result), "a", offset);
7686 /* bit field did not fit in a byte */
7687 rlen = SPEC_BLEN (etype) - 8;
7688 aopPut (AOP (result), "a", offset++);
7697 emitcode ("inc", "%s", rname);
7698 emitcode ("mov", "a,@%s", rname);
7702 emitcode ("inc", "%s", rname);
7703 emitcode ("movx", "a,@%s", rname);
7707 emitcode ("inc", "dptr");
7708 emitcode ("movx", "a,@dptr");
7712 emitcode ("clr", "a");
7713 emitcode ("inc", "dptr");
7714 emitcode ("movc", "a", "@a+dptr");
7718 emitcode ("inc", "dptr");
7719 emitcode ("lcall", "__gptrget");
7724 /* if we are done */
7728 aopPut (AOP (result), "a", offset++);
7734 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7735 aopPut (AOP (result), "a", offset);
7742 /*-----------------------------------------------------------------*/
7743 /* genDataPointerGet - generates code when ptr offset is known */
7744 /*-----------------------------------------------------------------*/
7746 genDataPointerGet (operand * left,
7752 int size, offset = 0;
7753 aopOp (result, ic, TRUE, FALSE);
7755 /* get the string representation of the name */
7756 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7757 size = AOP_SIZE (result);
7758 _startLazyDPSEvaluation ();
7762 sprintf (buffer, "(%s + %d)", l + 1, offset);
7764 sprintf (buffer, "%s", l + 1);
7765 aopPut (AOP (result), buffer, offset++);
7767 _endLazyDPSEvaluation ();
7769 freeAsmop (left, NULL, ic, TRUE);
7770 freeAsmop (result, NULL, ic, TRUE);
7773 /*-----------------------------------------------------------------*/
7774 /* genNearPointerGet - emitcode for near pointer fetch */
7775 /*-----------------------------------------------------------------*/
7777 genNearPointerGet (operand * left,
7784 sym_link *rtype, *retype, *letype;
7785 sym_link *ltype = operandType (left);
7788 rtype = operandType (result);
7789 retype = getSpec (rtype);
7790 letype = getSpec (ltype);
7792 aopOp (left, ic, FALSE, FALSE);
7794 /* if left is rematerialisable and
7795 result is not bit variable type and
7796 the left is pointer to data space i.e
7797 lower 128 bytes of space */
7798 if (AOP_TYPE (left) == AOP_IMMD &&
7799 !IS_BITVAR (retype) &&
7800 !IS_BITVAR (letype) &&
7801 DCL_TYPE (ltype) == POINTER)
7803 genDataPointerGet (left, result, ic);
7807 /* if the value is already in a pointer register
7808 then don't need anything more */
7809 if (!AOP_INPREG (AOP (left)))
7811 /* otherwise get a free pointer register */
7813 preg = getFreePtr (ic, &aop, FALSE);
7814 emitcode ("mov", "%s,%s",
7816 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7820 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7822 freeAsmop (left, NULL, ic, TRUE);
7823 aopOp (result, ic, FALSE, FALSE);
7825 /* if bitfield then unpack the bits */
7826 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7827 genUnpackBits (result, rname, POINTER);
7830 /* we have can just get the values */
7831 int size = AOP_SIZE (result);
7836 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7839 emitcode ("mov", "a,@%s", rname);
7840 aopPut (AOP (result), "a", offset);
7844 sprintf (buffer, "@%s", rname);
7845 aopPut (AOP (result), buffer, offset);
7849 emitcode ("inc", "%s", rname);
7853 /* now some housekeeping stuff */
7856 /* we had to allocate for this iCode */
7857 freeAsmop (NULL, aop, ic, TRUE);
7861 /* we did not allocate which means left
7862 already in a pointer register, then
7863 if size > 0 && this could be used again
7864 we have to point it back to where it
7866 if (AOP_SIZE (result) > 1 &&
7867 !OP_SYMBOL (left)->remat &&
7868 (OP_SYMBOL (left)->liveTo > ic->seq ||
7871 int size = AOP_SIZE (result) - 1;
7873 emitcode ("dec", "%s", rname);
7878 freeAsmop (result, NULL, ic, TRUE);
7882 /*-----------------------------------------------------------------*/
7883 /* genPagedPointerGet - emitcode for paged pointer fetch */
7884 /*-----------------------------------------------------------------*/
7886 genPagedPointerGet (operand * left,
7893 sym_link *rtype, *retype, *letype;
7895 rtype = operandType (result);
7896 retype = getSpec (rtype);
7897 letype = getSpec (operandType (left));
7898 aopOp (left, ic, FALSE, FALSE);
7900 /* if the value is already in a pointer register
7901 then don't need anything more */
7902 if (!AOP_INPREG (AOP (left)))
7904 /* otherwise get a free pointer register */
7906 preg = getFreePtr (ic, &aop, FALSE);
7907 emitcode ("mov", "%s,%s",
7909 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7913 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7915 freeAsmop (left, NULL, ic, TRUE);
7916 aopOp (result, ic, FALSE, FALSE);
7918 /* if bitfield then unpack the bits */
7919 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7920 genUnpackBits (result, rname, PPOINTER);
7923 /* we have can just get the values */
7924 int size = AOP_SIZE (result);
7930 emitcode ("movx", "a,@%s", rname);
7931 aopPut (AOP (result), "a", offset);
7936 emitcode ("inc", "%s", rname);
7940 /* now some housekeeping stuff */
7943 /* we had to allocate for this iCode */
7944 freeAsmop (NULL, aop, ic, TRUE);
7948 /* we did not allocate which means left
7949 already in a pointer register, then
7950 if size > 0 && this could be used again
7951 we have to point it back to where it
7953 if (AOP_SIZE (result) > 1 &&
7954 !OP_SYMBOL (left)->remat &&
7955 (OP_SYMBOL (left)->liveTo > ic->seq ||
7958 int size = AOP_SIZE (result) - 1;
7960 emitcode ("dec", "%s", rname);
7965 freeAsmop (result, NULL, ic, TRUE);
7970 /*-----------------------------------------------------------------*/
7971 /* genFarPointerGet - gget value from far space */
7972 /*-----------------------------------------------------------------*/
7974 genFarPointerGet (operand * left,
7975 operand * result, iCode * ic)
7978 sym_link *retype = getSpec (operandType (result));
7979 sym_link *letype = getSpec (operandType (left));
7980 D (emitcode (";", "genFarPointerGet");
7983 aopOp (left, ic, FALSE, FALSE);
7985 /* if the operand is already in dptr
7986 then we do nothing else we move the value to dptr */
7987 if (AOP_TYPE (left) != AOP_STR)
7989 /* if this is remateriazable */
7990 if (AOP_TYPE (left) == AOP_IMMD)
7992 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7996 /* we need to get it byte by byte */
7997 _startLazyDPSEvaluation ();
7998 if (AOP_TYPE (left) != AOP_DPTR)
8000 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8001 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8002 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8006 /* We need to generate a load to DPTR indirect through DPTR. */
8007 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8009 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8010 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8011 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8012 emitcode ("pop", "dph");
8013 emitcode ("pop", "dpl");
8015 _endLazyDPSEvaluation ();
8018 /* so dptr know contains the address */
8019 freeAsmop (left, NULL, ic, TRUE);
8020 aopOp (result, ic, FALSE, TRUE);
8022 /* if bit then unpack */
8023 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8024 genUnpackBits (result, "dptr", FPOINTER);
8027 size = AOP_SIZE (result);
8030 _startLazyDPSEvaluation ();
8037 emitcode ("movx", "a,@dptr");
8039 emitcode ("inc", "dptr");
8041 aopPut (AOP (result), "a", offset++);
8043 _endLazyDPSEvaluation ();
8046 freeAsmop (result, NULL, ic, TRUE);
8049 /*-----------------------------------------------------------------*/
8050 /* emitcodePointerGet - gget value from code space */
8051 /*-----------------------------------------------------------------*/
8053 emitcodePointerGet (operand * left,
8054 operand * result, iCode * ic)
8057 sym_link *retype = getSpec (operandType (result));
8059 aopOp (left, ic, FALSE, FALSE);
8061 /* if the operand is already in dptr
8062 then we do nothing else we move the value to dptr */
8063 if (AOP_TYPE (left) != AOP_STR)
8065 /* if this is remateriazable */
8066 if (AOP_TYPE (left) == AOP_IMMD)
8068 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8071 { /* we need to get it byte by byte */
8072 _startLazyDPSEvaluation ();
8073 if (AOP_TYPE (left) != AOP_DPTR)
8075 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8076 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8077 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8081 /* We need to generate a load to DPTR indirect through DPTR. */
8082 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8084 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8085 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8086 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8087 emitcode ("pop", "dph");
8088 emitcode ("pop", "dpl");
8090 _endLazyDPSEvaluation ();
8093 /* so dptr know contains the address */
8094 freeAsmop (left, NULL, ic, TRUE);
8095 aopOp (result, ic, FALSE, TRUE);
8097 /* if bit then unpack */
8098 if (IS_BITVAR (retype))
8099 genUnpackBits (result, "dptr", CPOINTER);
8102 size = AOP_SIZE (result);
8105 _startLazyDPSEvaluation ();
8111 emitcode ("clr", "a");
8112 emitcode ("movc", "a,@a+dptr");
8114 emitcode ("inc", "dptr");
8115 aopPut (AOP (result), "a", offset++);
8117 _endLazyDPSEvaluation ();
8120 freeAsmop (result, NULL, ic, TRUE);
8123 /*-----------------------------------------------------------------*/
8124 /* genGenPointerGet - gget value from generic pointer space */
8125 /*-----------------------------------------------------------------*/
8127 genGenPointerGet (operand * left,
8128 operand * result, iCode * ic)
8131 sym_link *retype = getSpec (operandType (result));
8132 sym_link *letype = getSpec (operandType (left));
8134 D (emitcode (";", "genGenPointerGet "); );
8136 aopOp (left, ic, FALSE, TRUE);
8138 /* if the operand is already in dptr
8139 then we do nothing else we move the value to dptr */
8140 if (AOP_TYPE (left) != AOP_STR)
8142 /* if this is remateriazable */
8143 if (AOP_TYPE (left) == AOP_IMMD)
8145 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8146 emitcode ("mov", "b,#%d", pointerCode (retype));
8149 { /* we need to get it byte by byte */
8150 _startLazyDPSEvaluation ();
8151 if (AOP(left)->type==AOP_DPTR2) {
8153 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8156 emitcode ("mov", "dpl,%s", l);
8157 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8160 emitcode ("mov", "dph,%s", l);
8161 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8164 emitcode ("mov", "dpx,%s", l);
8165 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8167 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8168 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8169 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8170 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8172 _endLazyDPSEvaluation ();
8175 /* so dptr know contains the address */
8176 freeAsmop (left, NULL, ic, TRUE);
8177 aopOp (result, ic, FALSE, TRUE);
8179 /* if bit then unpack */
8180 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8181 genUnpackBits (result, "dptr", GPOINTER);
8184 size = AOP_SIZE (result);
8189 emitcode ("lcall", "__gptrget");
8190 aopPut (AOP (result), "a", offset++);
8192 emitcode ("inc", "dptr");
8196 freeAsmop (result, NULL, ic, TRUE);
8199 /*-----------------------------------------------------------------*/
8200 /* genPointerGet - generate code for pointer get */
8201 /*-----------------------------------------------------------------*/
8203 genPointerGet (iCode * ic)
8205 operand *left, *result;
8206 sym_link *type, *etype;
8209 D (emitcode (";", "genPointerGet ");
8212 left = IC_LEFT (ic);
8213 result = IC_RESULT (ic);
8215 /* depending on the type of pointer we need to
8216 move it to the correct pointer register */
8217 type = operandType (left);
8218 etype = getSpec (type);
8219 /* if left is of type of pointer then it is simple */
8220 if (IS_PTR (type) && !IS_FUNC (type->next))
8221 p_type = DCL_TYPE (type);
8224 /* we have to go by the storage class */
8225 p_type = PTR_TYPE (SPEC_OCLS (etype));
8228 /* now that we have the pointer type we assign
8229 the pointer values */
8235 genNearPointerGet (left, result, ic);
8239 genPagedPointerGet (left, result, ic);
8243 genFarPointerGet (left, result, ic);
8247 emitcodePointerGet (left, result, ic);
8251 genGenPointerGet (left, result, ic);
8257 /*-----------------------------------------------------------------*/
8258 /* genPackBits - generates code for packed bit storage */
8259 /*-----------------------------------------------------------------*/
8261 genPackBits (sym_link * etype,
8263 char *rname, int p_type)
8271 blen = SPEC_BLEN (etype);
8272 bstr = SPEC_BSTR (etype);
8274 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8277 /* if the bit lenth is less than or */
8278 /* it exactly fits a byte then */
8279 if (SPEC_BLEN (etype) <= 8)
8281 shCount = SPEC_BSTR (etype);
8283 /* shift left acc */
8286 if (SPEC_BLEN (etype) < 8)
8287 { /* if smaller than a byte */
8293 emitcode ("mov", "b,a");
8294 emitcode ("mov", "a,@%s", rname);
8298 emitcode ("mov", "b,a");
8299 emitcode ("movx", "a,@dptr");
8303 emitcode ("push", "b");
8304 emitcode ("push", "acc");
8305 emitcode ("lcall", "__gptrget");
8306 emitcode ("pop", "b");
8310 emitcode ("anl", "a,#0x%02x", (unsigned char)
8311 ((unsigned char) (0xFF << (blen + bstr)) |
8312 (unsigned char) (0xFF >> (8 - bstr))));
8313 emitcode ("orl", "a,b");
8314 if (p_type == GPOINTER)
8315 emitcode ("pop", "b");
8322 emitcode ("mov", "@%s,a", rname);
8326 emitcode ("movx", "@dptr,a");
8330 emitcode ("lcall", "__gptrput");
8335 if (SPEC_BLEN (etype) <= 8)
8338 emitcode ("inc", "%s", rname);
8339 rLen = SPEC_BLEN (etype);
8341 /* now generate for lengths greater than one byte */
8345 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8357 emitcode ("mov", "@%s,a", rname);
8360 emitcode ("mov", "@%s,%s", rname, l);
8365 emitcode ("movx", "@dptr,a");
8370 emitcode ("lcall", "__gptrput");
8373 emitcode ("inc", "%s", rname);
8378 /* last last was not complete */
8381 /* save the byte & read byte */
8385 emitcode ("mov", "b,a");
8386 emitcode ("mov", "a,@%s", rname);
8390 emitcode ("mov", "b,a");
8391 emitcode ("movx", "a,@dptr");
8395 emitcode ("push", "b");
8396 emitcode ("push", "acc");
8397 emitcode ("lcall", "__gptrget");
8398 emitcode ("pop", "b");
8402 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8403 emitcode ("orl", "a,b");
8406 if (p_type == GPOINTER)
8407 emitcode ("pop", "b");
8413 emitcode ("mov", "@%s,a", rname);
8417 emitcode ("movx", "@dptr,a");
8421 emitcode ("lcall", "__gptrput");
8425 /*-----------------------------------------------------------------*/
8426 /* genDataPointerSet - remat pointer to data space */
8427 /*-----------------------------------------------------------------*/
8429 genDataPointerSet (operand * right,
8433 int size, offset = 0;
8434 char *l, buffer[256];
8436 aopOp (right, ic, FALSE, FALSE);
8438 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8439 size = AOP_SIZE (right);
8443 sprintf (buffer, "(%s + %d)", l + 1, offset);
8445 sprintf (buffer, "%s", l + 1);
8446 emitcode ("mov", "%s,%s", buffer,
8447 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8450 freeAsmop (right, NULL, ic, TRUE);
8451 freeAsmop (result, NULL, ic, TRUE);
8454 /*-----------------------------------------------------------------*/
8455 /* genNearPointerSet - emitcode for near pointer put */
8456 /*-----------------------------------------------------------------*/
8458 genNearPointerSet (operand * right,
8465 sym_link *retype, *letype;
8466 sym_link *ptype = operandType (result);
8468 retype = getSpec (operandType (right));
8469 letype = getSpec (ptype);
8471 aopOp (result, ic, FALSE, FALSE);
8473 /* if the result is rematerializable &
8474 in data space & not a bit variable */
8475 if (AOP_TYPE (result) == AOP_IMMD &&
8476 DCL_TYPE (ptype) == POINTER &&
8477 !IS_BITVAR (retype) &&
8478 !IS_BITVAR (letype))
8480 genDataPointerSet (right, result, ic);
8484 /* if the value is already in a pointer register
8485 then don't need anything more */
8486 if (!AOP_INPREG (AOP (result)))
8488 /* otherwise get a free pointer register */
8490 preg = getFreePtr (ic, &aop, FALSE);
8491 emitcode ("mov", "%s,%s",
8493 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8497 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8499 freeAsmop (result, NULL, ic, TRUE);
8500 aopOp (right, ic, FALSE, FALSE);
8502 /* if bitfield then unpack the bits */
8503 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8504 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8507 /* we have can just get the values */
8508 int size = AOP_SIZE (right);
8513 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8517 emitcode ("mov", "@%s,a", rname);
8520 emitcode ("mov", "@%s,%s", rname, l);
8522 emitcode ("inc", "%s", rname);
8527 /* now some housekeeping stuff */
8530 /* we had to allocate for this iCode */
8531 freeAsmop (NULL, aop, ic, TRUE);
8535 /* we did not allocate which means left
8536 already in a pointer register, then
8537 if size > 0 && this could be used again
8538 we have to point it back to where it
8540 if (AOP_SIZE (right) > 1 &&
8541 !OP_SYMBOL (result)->remat &&
8542 (OP_SYMBOL (result)->liveTo > ic->seq ||
8545 int size = AOP_SIZE (right) - 1;
8547 emitcode ("dec", "%s", rname);
8552 freeAsmop (right, NULL, ic, TRUE);
8557 /*-----------------------------------------------------------------*/
8558 /* genPagedPointerSet - emitcode for Paged pointer put */
8559 /*-----------------------------------------------------------------*/
8561 genPagedPointerSet (operand * right,
8568 sym_link *retype, *letype;
8570 retype = getSpec (operandType (right));
8571 letype = getSpec (operandType (result));
8573 aopOp (result, ic, FALSE, FALSE);
8575 /* if the value is already in a pointer register
8576 then don't need anything more */
8577 if (!AOP_INPREG (AOP (result)))
8579 /* otherwise get a free pointer register */
8581 preg = getFreePtr (ic, &aop, FALSE);
8582 emitcode ("mov", "%s,%s",
8584 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8588 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8590 freeAsmop (result, NULL, ic, TRUE);
8591 aopOp (right, ic, FALSE, FALSE);
8593 /* if bitfield then unpack the bits */
8594 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8595 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8598 /* we have can just get the values */
8599 int size = AOP_SIZE (right);
8604 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8607 emitcode ("movx", "@%s,a", rname);
8610 emitcode ("inc", "%s", rname);
8616 /* now some housekeeping stuff */
8619 /* we had to allocate for this iCode */
8620 freeAsmop (NULL, aop, ic, TRUE);
8624 /* we did not allocate which means left
8625 already in a pointer register, then
8626 if size > 0 && this could be used again
8627 we have to point it back to where it
8629 if (AOP_SIZE (right) > 1 &&
8630 !OP_SYMBOL (result)->remat &&
8631 (OP_SYMBOL (result)->liveTo > ic->seq ||
8634 int size = AOP_SIZE (right) - 1;
8636 emitcode ("dec", "%s", rname);
8641 freeAsmop (right, NULL, ic, TRUE);
8646 /*-----------------------------------------------------------------*/
8647 /* genFarPointerSet - set value from far space */
8648 /*-----------------------------------------------------------------*/
8650 genFarPointerSet (operand * right,
8651 operand * result, iCode * ic)
8654 sym_link *retype = getSpec (operandType (right));
8655 sym_link *letype = getSpec (operandType (result));
8657 aopOp (result, ic, FALSE, FALSE);
8659 /* if the operand is already in dptr
8660 then we do nothing else we move the value to dptr */
8661 if (AOP_TYPE (result) != AOP_STR)
8663 /* if this is remateriazable */
8664 if (AOP_TYPE (result) == AOP_IMMD)
8665 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8668 /* we need to get it byte by byte */
8669 _startLazyDPSEvaluation ();
8670 if (AOP_TYPE (result) != AOP_DPTR)
8672 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8673 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8674 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8678 /* We need to generate a load to DPTR indirect through DPTR. */
8679 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8681 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8682 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8683 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8684 emitcode ("pop", "dph");
8685 emitcode ("pop", "dpl");
8687 _endLazyDPSEvaluation ();
8690 /* so dptr know contains the address */
8691 freeAsmop (result, NULL, ic, TRUE);
8692 aopOp (right, ic, FALSE, TRUE);
8694 /* if bit then unpack */
8695 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8696 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8699 size = AOP_SIZE (right);
8702 _startLazyDPSEvaluation ();
8705 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8711 emitcode ("movx", "@dptr,a");
8713 emitcode ("inc", "dptr");
8715 _endLazyDPSEvaluation ();
8718 freeAsmop (right, NULL, ic, TRUE);
8721 /*-----------------------------------------------------------------*/
8722 /* genGenPointerSet - set value from generic pointer space */
8723 /*-----------------------------------------------------------------*/
8725 genGenPointerSet (operand * right,
8726 operand * result, iCode * ic)
8729 sym_link *retype = getSpec (operandType (right));
8730 sym_link *letype = getSpec (operandType (result));
8732 aopOp (result, ic, FALSE, TRUE);
8734 /* if the operand is already in dptr
8735 then we do nothing else we move the value to dptr */
8736 if (AOP_TYPE (result) != AOP_STR)
8738 _startLazyDPSEvaluation ();
8739 /* if this is remateriazable */
8740 if (AOP_TYPE (result) == AOP_IMMD)
8742 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8743 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8746 { /* we need to get it byte by byte */
8747 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8748 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8749 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8750 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8752 _endLazyDPSEvaluation ();
8754 /* so dptr know contains the address */
8755 freeAsmop (result, NULL, ic, TRUE);
8756 aopOp (right, ic, FALSE, TRUE);
8758 /* if bit then unpack */
8759 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8760 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8763 size = AOP_SIZE (right);
8766 _startLazyDPSEvaluation ();
8769 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8775 emitcode ("lcall", "__gptrput");
8777 emitcode ("inc", "dptr");
8779 _endLazyDPSEvaluation ();
8782 freeAsmop (right, NULL, ic, TRUE);
8785 /*-----------------------------------------------------------------*/
8786 /* genPointerSet - stores the value into a pointer location */
8787 /*-----------------------------------------------------------------*/
8789 genPointerSet (iCode * ic)
8791 operand *right, *result;
8792 sym_link *type, *etype;
8795 D (emitcode (";", "genPointerSet ");
8798 right = IC_RIGHT (ic);
8799 result = IC_RESULT (ic);
8801 /* depending on the type of pointer we need to
8802 move it to the correct pointer register */
8803 type = operandType (result);
8804 etype = getSpec (type);
8805 /* if left is of type of pointer then it is simple */
8806 if (IS_PTR (type) && !IS_FUNC (type->next))
8808 p_type = DCL_TYPE (type);
8812 /* we have to go by the storage class */
8813 p_type = PTR_TYPE (SPEC_OCLS (etype));
8816 /* now that we have the pointer type we assign
8817 the pointer values */
8823 genNearPointerSet (right, result, ic);
8827 genPagedPointerSet (right, result, ic);
8831 genFarPointerSet (right, result, ic);
8835 genGenPointerSet (right, result, ic);
8841 /*-----------------------------------------------------------------*/
8842 /* genIfx - generate code for Ifx statement */
8843 /*-----------------------------------------------------------------*/
8845 genIfx (iCode * ic, iCode * popIc)
8847 operand *cond = IC_COND (ic);
8850 D (emitcode (";", "genIfx "););
8852 aopOp (cond, ic, FALSE, FALSE);
8854 /* get the value into acc */
8855 if (AOP_TYPE (cond) != AOP_CRY)
8859 /* the result is now in the accumulator */
8860 freeAsmop (cond, NULL, ic, TRUE);
8862 /* if there was something to be popped then do it */
8866 /* if the condition is a bit variable */
8867 if (isbit && IS_ITEMP (cond) &&
8869 genIfxJump (ic, SPIL_LOC (cond)->rname);
8870 else if (isbit && !IS_ITEMP (cond))
8871 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8873 genIfxJump (ic, "a");
8878 /*-----------------------------------------------------------------*/
8879 /* genAddrOf - generates code for address of */
8880 /*-----------------------------------------------------------------*/
8882 genAddrOf (iCode * ic)
8884 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8887 D (emitcode (";", "genAddrOf ");
8890 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8892 /* if the operand is on the stack then we
8893 need to get the stack offset of this
8897 /* if it has an offset then we need to compute
8901 emitcode ("mov", "a,_bp");
8902 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8903 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8907 /* we can just move _bp */
8908 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8910 /* fill the result with zero */
8911 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8914 if (options.stack10bit && size < (FPTRSIZE - 1))
8917 "*** warning: pointer to stack var truncated.\n");
8924 if (options.stack10bit && offset == 2)
8926 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8930 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8937 /* object not on stack then we need the name */
8938 size = AOP_SIZE (IC_RESULT (ic));
8943 char s[SDCC_NAME_MAX];
8945 sprintf (s, "#(%s >> %d)",
8949 sprintf (s, "#%s", sym->rname);
8950 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8954 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8958 /*-----------------------------------------------------------------*/
8959 /* genFarFarAssign - assignment when both are in far space */
8960 /*-----------------------------------------------------------------*/
8962 genFarFarAssign (operand * result, operand * right, iCode * ic)
8964 int size = AOP_SIZE (right);
8966 symbol *rSym = NULL;
8970 /* quick & easy case. */
8971 D(emitcode(";","genFarFarAssign (1 byte case)"););
8972 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
8973 freeAsmop (right, NULL, ic, FALSE);
8974 /* now assign DPTR to result */
8976 aopOp(result, ic, FALSE, FALSE);
8978 aopPut(AOP(result), "a", 0);
8979 freeAsmop(result, NULL, ic, FALSE);
8983 /* See if we've got an underlying symbol to abuse. */
8984 if (IS_SYMOP(result) && OP_SYMBOL(result))
8986 if (IS_TRUE_SYMOP(result))
8988 rSym = OP_SYMBOL(result);
8990 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
8992 rSym = OP_SYMBOL(result)->usl.spillLoc;
8996 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
8998 /* We can use the '390 auto-toggle feature to good effect here. */
9000 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9001 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9002 emitcode ("mov", "dptr,#%s", rSym->rname);
9003 /* DP2 = result, DP1 = right, DP1 is current. */
9006 emitcode("movx", "a,@dptr");
9007 emitcode("movx", "@dptr,a");
9010 emitcode("inc", "dptr");
9011 emitcode("inc", "dptr");
9014 emitcode("mov", "dps, #0");
9015 freeAsmop (right, NULL, ic, FALSE);
9019 D (emitcode (";", "genFarFarAssign"););
9020 aopOp (result, ic, TRUE, TRUE);
9022 _startLazyDPSEvaluation ();
9026 aopPut (AOP (result),
9027 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9030 _endLazyDPSEvaluation ();
9031 freeAsmop (result, NULL, ic, FALSE);
9032 freeAsmop (right, NULL, ic, FALSE);
9036 /*-----------------------------------------------------------------*/
9037 /* genAssign - generate code for assignment */
9038 /*-----------------------------------------------------------------*/
9040 genAssign (iCode * ic)
9042 operand *result, *right;
9044 unsigned long lit = 0L;
9046 D (emitcode (";", "genAssign ");
9049 result = IC_RESULT (ic);
9050 right = IC_RIGHT (ic);
9052 /* if they are the same */
9053 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9056 aopOp (right, ic, FALSE, FALSE);
9058 emitcode (";", "genAssign: resultIsFar = %s",
9059 isOperandInFarSpace (result) ?
9062 /* special case both in far space */
9063 if ((AOP_TYPE (right) == AOP_DPTR ||
9064 AOP_TYPE (right) == AOP_DPTR2) &&
9065 /* IS_TRUE_SYMOP(result) && */
9066 isOperandInFarSpace (result))
9068 genFarFarAssign (result, right, ic);
9072 aopOp (result, ic, TRUE, FALSE);
9074 /* if they are the same registers */
9075 if (sameRegs (AOP (right), AOP (result)))
9078 /* if the result is a bit */
9079 if (AOP_TYPE (result) == AOP_CRY)
9082 /* if the right size is a literal then
9083 we know what the value is */
9084 if (AOP_TYPE (right) == AOP_LIT)
9086 if (((int) operandLitValue (right)))
9087 aopPut (AOP (result), one, 0);
9089 aopPut (AOP (result), zero, 0);
9093 /* the right is also a bit variable */
9094 if (AOP_TYPE (right) == AOP_CRY)
9096 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9097 aopPut (AOP (result), "c", 0);
9103 aopPut (AOP (result), "a", 0);
9107 /* bit variables done */
9109 size = AOP_SIZE (result);
9111 if (AOP_TYPE (right) == AOP_LIT)
9112 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9115 (AOP_TYPE (result) != AOP_REG) &&
9116 (AOP_TYPE (right) == AOP_LIT) &&
9117 !IS_FLOAT (operandType (right)))
9119 _startLazyDPSEvaluation ();
9120 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9122 aopPut (AOP (result),
9123 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9128 /* And now fill the rest with zeros. */
9131 emitcode ("clr", "a");
9135 aopPut (AOP (result), "a", offset++);
9137 _endLazyDPSEvaluation ();
9141 _startLazyDPSEvaluation ();
9144 aopPut (AOP (result),
9145 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9149 _endLazyDPSEvaluation ();
9153 freeAsmop (right, NULL, ic, FALSE);
9154 freeAsmop (result, NULL, ic, TRUE);
9157 /*-----------------------------------------------------------------*/
9158 /* genJumpTab - generates code for jump table */
9159 /*-----------------------------------------------------------------*/
9161 genJumpTab (iCode * ic)
9166 D (emitcode (";", "genJumpTab ");
9169 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9170 /* get the condition into accumulator */
9171 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9173 /* multiply by four! */
9174 emitcode ("add", "a,acc");
9175 emitcode ("add", "a,acc");
9176 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9178 jtab = newiTempLabel (NULL);
9179 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9180 emitcode ("jmp", "@a+dptr");
9181 emitcode ("", "%05d$:", jtab->key + 100);
9182 /* now generate the jump labels */
9183 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9184 jtab = setNextItem (IC_JTLABELS (ic)))
9185 emitcode ("ljmp", "%05d$", jtab->key + 100);
9189 /*-----------------------------------------------------------------*/
9190 /* genCast - gen code for casting */
9191 /*-----------------------------------------------------------------*/
9193 genCast (iCode * ic)
9195 operand *result = IC_RESULT (ic);
9196 sym_link *ctype = operandType (IC_LEFT (ic));
9197 sym_link *rtype = operandType (IC_RIGHT (ic));
9198 operand *right = IC_RIGHT (ic);
9201 D (emitcode (";", "genCast ");
9204 /* if they are equivalent then do nothing */
9205 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9208 aopOp (right, ic, FALSE, FALSE);
9209 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9211 /* if the result is a bit */
9212 if (AOP_TYPE (result) == AOP_CRY)
9214 /* if the right size is a literal then
9215 we know what the value is */
9216 if (AOP_TYPE (right) == AOP_LIT)
9218 if (((int) operandLitValue (right)))
9219 aopPut (AOP (result), one, 0);
9221 aopPut (AOP (result), zero, 0);
9226 /* the right is also a bit variable */
9227 if (AOP_TYPE (right) == AOP_CRY)
9229 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9230 aopPut (AOP (result), "c", 0);
9236 aopPut (AOP (result), "a", 0);
9240 /* if they are the same size : or less */
9241 if (AOP_SIZE (result) <= AOP_SIZE (right))
9244 /* if they are in the same place */
9245 if (sameRegs (AOP (right), AOP (result)))
9248 /* if they in different places then copy */
9249 size = AOP_SIZE (result);
9251 _startLazyDPSEvaluation ();
9254 aopPut (AOP (result),
9255 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9259 _endLazyDPSEvaluation ();
9264 /* if the result is of type pointer */
9269 sym_link *type = operandType (right);
9271 /* pointer to generic pointer */
9272 if (IS_GENPTR (ctype))
9278 p_type = DCL_TYPE (type);
9282 #if OLD_CAST_BEHAVIOR
9283 /* KV: we are converting a non-pointer type to
9284 * a generic pointer. This (ifdef'd out) code
9285 * says that the resulting generic pointer
9286 * should have the same class as the storage
9287 * location of the non-pointer variable.
9289 * For example, converting an int (which happens
9290 * to be stored in DATA space) to a pointer results
9291 * in a DATA generic pointer; if the original int
9292 * in XDATA space, so will be the resulting pointer.
9294 * I don't like that behavior, and thus this change:
9295 * all such conversions will be forced to XDATA and
9296 * throw a warning. If you want some non-XDATA
9297 * type, or you want to suppress the warning, you
9298 * must go through an intermediate cast, like so:
9300 * char _generic *gp = (char _xdata *)(intVar);
9302 sym_link *etype = getSpec (type);
9304 /* we have to go by the storage class */
9305 if (SPEC_OCLS (etype) != generic)
9307 p_type = PTR_TYPE (SPEC_OCLS (etype));
9312 /* Converting unknown class (i.e. register variable)
9313 * to generic pointer. This is not good, but
9314 * we'll make a guess (and throw a warning).
9317 werror (W_INT_TO_GEN_PTR_CAST);
9321 /* the first two bytes are known */
9322 size = GPTRSIZE - 1;
9324 _startLazyDPSEvaluation ();
9327 aopPut (AOP (result),
9328 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9332 _endLazyDPSEvaluation ();
9334 /* the last byte depending on type */
9352 /* this should never happen */
9353 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9354 "got unknown pointer type");
9357 aopPut (AOP (result), l, GPTRSIZE - 1);
9361 /* just copy the pointers */
9362 size = AOP_SIZE (result);
9364 _startLazyDPSEvaluation ();
9367 aopPut (AOP (result),
9368 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9372 _endLazyDPSEvaluation ();
9376 /* so we now know that the size of destination is greater
9377 than the size of the source */
9378 /* we move to result for the size of source */
9379 size = AOP_SIZE (right);
9381 _startLazyDPSEvaluation ();
9384 aopPut (AOP (result),
9385 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9389 _endLazyDPSEvaluation ();
9391 /* now depending on the sign of the source && destination */
9392 size = AOP_SIZE (result) - AOP_SIZE (right);
9393 /* if unsigned or not an integral type */
9394 /* also, if the source is a bit, we don't need to sign extend, because
9395 * it can't possibly have set the sign bit.
9397 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9401 aopPut (AOP (result), zero, offset++);
9406 /* we need to extend the sign :{ */
9407 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9408 FALSE, FALSE, TRUE);
9410 emitcode ("rlc", "a");
9411 emitcode ("subb", "a,acc");
9413 aopPut (AOP (result), "a", offset++);
9416 /* we are done hurray !!!! */
9419 freeAsmop (right, NULL, ic, TRUE);
9420 freeAsmop (result, NULL, ic, TRUE);
9424 /*-----------------------------------------------------------------*/
9425 /* genDjnz - generate decrement & jump if not zero instrucion */
9426 /*-----------------------------------------------------------------*/
9428 genDjnz (iCode * ic, iCode * ifx)
9434 /* if the if condition has a false label
9435 then we cannot save */
9439 /* if the minus is not of the form
9441 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9442 !IS_OP_LITERAL (IC_RIGHT (ic)))
9445 if (operandLitValue (IC_RIGHT (ic)) != 1)
9448 /* if the size of this greater than one then no
9450 if (getSize (operandType (IC_RESULT (ic))) > 1)
9453 /* otherwise we can save BIG */
9454 D(emitcode(";", "genDjnz"););
9456 lbl = newiTempLabel (NULL);
9457 lbl1 = newiTempLabel (NULL);
9459 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9461 if (AOP_NEEDSACC(IC_RESULT(ic)))
9463 /* If the result is accessed indirectly via
9464 * the accumulator, we must explicitly write
9465 * it back after the decrement.
9467 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9469 if (strcmp(rByte, "a"))
9471 /* Something is hopelessly wrong */
9472 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9473 __FILE__, __LINE__);
9474 /* We can just give up; the generated code will be inefficient,
9477 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9480 emitcode ("dec", "%s", rByte);
9481 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9482 emitcode ("jnz", "%05d$", lbl->key + 100);
9484 else if (IS_AOP_PREG (IC_RESULT (ic)))
9486 emitcode ("dec", "%s",
9487 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9488 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9489 emitcode ("jnz", "%05d$", lbl->key + 100);
9493 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9496 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9497 emitcode ("", "%05d$:", lbl->key + 100);
9498 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9499 emitcode ("", "%05d$:", lbl1->key + 100);
9501 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9506 /*-----------------------------------------------------------------*/
9507 /* genReceive - generate code for a receive iCode */
9508 /*-----------------------------------------------------------------*/
9510 genReceive (iCode * ic)
9513 D (emitcode (";", "genReceive ");
9516 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9517 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9518 IS_TRUE_SYMOP (IC_RESULT (ic))))
9520 int size = getSize (operandType (IC_RESULT (ic)));
9521 int offset = fReturnSizeDS390 - size;
9524 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9525 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9528 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9529 size = AOP_SIZE (IC_RESULT (ic));
9533 emitcode ("pop", "acc");
9534 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9541 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9543 assignResultValue (IC_RESULT (ic));
9546 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9549 /*-----------------------------------------------------------------*/
9550 /* gen390Code - generate code for Dallas 390 based controllers */
9551 /*-----------------------------------------------------------------*/
9553 gen390Code (iCode * lic)
9558 lineHead = lineCurr = NULL;
9562 /* print the allocation information */
9564 printAllocInfo (currFunc, codeOutFile);
9566 /* if debug information required */
9567 if (options.debug && currFunc)
9569 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9571 if (IS_STATIC (currFunc->etype))
9572 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9574 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9577 /* stack pointer name */
9578 if (options.useXstack)
9584 for (ic = lic; ic; ic = ic->next)
9587 if (cln != ic->lineno)
9592 emitcode ("", "C$%s$%d$%d$%d ==.",
9593 FileBaseName (ic->filename), ic->lineno,
9594 ic->level, ic->block);
9597 emitcode (";", "%s %d", ic->filename, ic->lineno);
9600 /* if the result is marked as
9601 spilt and rematerializable or code for
9602 this has already been generated then
9604 if (resultRemat (ic) || ic->generated)
9607 /* depending on the operation */
9627 /* IPOP happens only when trying to restore a
9628 spilt live range, if there is an ifx statement
9629 following this pop then the if statement might
9630 be using some of the registers being popped which
9631 would destory the contents of the register so
9632 we need to check for this condition and handle it */
9634 ic->next->op == IFX &&
9635 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9636 genIfx (ic->next, ic);
9654 genEndFunction (ic);
9674 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9691 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9695 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9702 /* note these two are xlated by algebraic equivalence
9703 during parsing SDCC.y */
9704 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9705 "got '>=' or '<=' shouldn't have come here");
9709 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9721 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9725 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9729 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9756 case GET_VALUE_AT_ADDRESS:
9761 if (POINTER_SET (ic))
9788 addSet (&_G.sendSet, ic);
9797 /* now we are ready to call the
9798 peep hole optimizer */
9799 if (!options.nopeep)
9800 peepHole (&lineHead);
9802 /* now do the actual printing */
9803 printLine (lineHead, codeOutFile);