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 ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1798 detype = getSpec (operandType (IC_LEFT (ic)));
1800 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1801 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 ;jwk unsaveRegisters", 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 ;jwk genIpush: !parm", 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 ;jwk genIpush", 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 ;jwk genIpop", 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)
2153 D (emitcode (";", "genCall ");
2156 /* if caller saves & we have not saved then */
2160 /* if we are calling a function that is not using
2161 the same register bank then we need to save the
2162 destination registers on the stack */
2163 detype = getSpec (operandType (IC_LEFT (ic)));
2165 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2166 IS_ISR (currFunc->etype) &&
2169 saverbank (SPEC_BANK (detype), ic, TRUE);
2171 /* if send set is not empty the assign */
2176 for (sic = setFirstItem (_G.sendSet); sic;
2177 sic = setNextItem (_G.sendSet))
2179 int size, offset = 0;
2181 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2182 size = AOP_SIZE (IC_LEFT (sic));
2184 _startLazyDPSEvaluation ();
2187 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2188 FALSE, FALSE, TRUE);
2189 if (strcmp (l, fReturn[offset])) {
2192 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2198 _endLazyDPSEvaluation ();
2199 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2204 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2205 OP_SYMBOL (IC_LEFT (ic))->rname :
2206 OP_SYMBOL (IC_LEFT (ic))->name));
2208 /* if we need assign a result value */
2209 if ((IS_ITEMP (IC_RESULT (ic)) &&
2210 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2211 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2212 IS_TRUE_SYMOP (IC_RESULT (ic)))
2214 if (isOperandInFarSpace (IC_RESULT (ic))
2215 && getSize (operandType (IC_RESULT (ic))) <= 2)
2217 int size = getSize (operandType (IC_RESULT (ic)));
2219 /* Special case for 1 or 2 byte return in far space. */
2223 emitcode ("mov", "b,%s", fReturn[1]);
2226 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2227 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2231 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2233 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2238 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2241 assignResultValue (IC_RESULT (ic));
2243 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2247 /* adjust the stack for parameters if
2252 if (ic->parmBytes > 3)
2254 emitcode ("mov", "a,%s", spname);
2255 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2256 emitcode ("mov", "%s,a", spname);
2259 for (i = 0; i < ic->parmBytes; i++)
2260 emitcode ("dec", "%s", spname);
2264 /* if register bank was saved then pop them */
2266 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2268 /* if we hade saved some registers then unsave them */
2269 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2270 unsaveRegisters (ic);
2275 /*-----------------------------------------------------------------*/
2276 /* genPcall - generates a call by pointer statement */
2277 /*-----------------------------------------------------------------*/
2279 genPcall (iCode * ic)
2282 symbol *rlbl = newiTempLabel (NULL);
2284 D (emitcode (";", "genPcall ");
2288 /* if caller saves & we have not saved then */
2292 /* if we are calling a function that is not using
2293 the same register bank then we need to save the
2294 destination registers on the stack */
2295 detype = getSpec (operandType (IC_LEFT (ic)));
2297 IS_ISR (currFunc->etype) &&
2298 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2299 saverbank (SPEC_BANK (detype), ic, TRUE);
2302 /* push the return address on to the stack */
2303 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2304 emitcode ("push", "acc");
2305 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2306 emitcode ("push", "acc");
2308 if (options.model == MODEL_FLAT24)
2310 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2311 emitcode ("push", "acc");
2314 /* now push the calling address */
2315 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2317 pushSide (IC_LEFT (ic), FPTRSIZE);
2319 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2321 /* if send set is not empty the assign */
2326 for (sic = setFirstItem (_G.sendSet); sic;
2327 sic = setNextItem (_G.sendSet))
2329 int size, offset = 0;
2331 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2332 size = AOP_SIZE (IC_LEFT (sic));
2333 _startLazyDPSEvaluation ();
2336 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2337 FALSE, FALSE, TRUE);
2338 if (strcmp (l, fReturn[offset]))
2340 emitcode ("mov", "%s,%s",
2346 _endLazyDPSEvaluation ();
2347 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2352 emitcode ("ret", "");
2353 emitcode ("", "%05d$:", (rlbl->key + 100));
2356 /* if we need assign a result value */
2357 if ((IS_ITEMP (IC_RESULT (ic)) &&
2358 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2359 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2360 IS_TRUE_SYMOP (IC_RESULT (ic)))
2364 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2367 assignResultValue (IC_RESULT (ic));
2369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2372 /* adjust the stack for parameters if
2377 if (ic->parmBytes > 3)
2379 emitcode ("mov", "a,%s", spname);
2380 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2381 emitcode ("mov", "%s,a", spname);
2384 for (i = 0; i < ic->parmBytes; i++)
2385 emitcode ("dec", "%s", spname);
2389 /* if register bank was saved then unsave them */
2391 (SPEC_BANK (currFunc->etype) !=
2392 SPEC_BANK (detype)))
2393 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2395 /* if we hade saved some registers then
2398 unsaveRegisters (ic);
2402 /*-----------------------------------------------------------------*/
2403 /* resultRemat - result is rematerializable */
2404 /*-----------------------------------------------------------------*/
2406 resultRemat (iCode * ic)
2408 if (SKIP_IC (ic) || ic->op == IFX)
2411 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2413 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2414 if (sym->remat && !POINTER_SET (ic))
2421 #if defined(__BORLANDC__) || defined(_MSC_VER)
2422 #define STRCASECMP stricmp
2424 #define STRCASECMP strcasecmp
2427 /*-----------------------------------------------------------------*/
2428 /* inExcludeList - return 1 if the string is in exclude Reg list */
2429 /*-----------------------------------------------------------------*/
2431 inExcludeList (char *s)
2435 if (options.excludeRegs[i] &&
2436 STRCASECMP (options.excludeRegs[i], "none") == 0)
2439 for (i = 0; options.excludeRegs[i]; i++)
2441 if (options.excludeRegs[i] &&
2442 STRCASECMP (s, options.excludeRegs[i]) == 0)
2448 /*-----------------------------------------------------------------*/
2449 /* genFunction - generated code for function entry */
2450 /*-----------------------------------------------------------------*/
2452 genFunction (iCode * ic)
2457 D (emitcode (";", "genFunction ");
2461 /* create the function header */
2462 emitcode (";", "-----------------------------------------");
2463 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2464 emitcode (";", "-----------------------------------------");
2466 emitcode ("", "%s:", sym->rname);
2467 fetype = getSpec (operandType (IC_LEFT (ic)));
2469 /* if critical function then turn interrupts off */
2470 if (SPEC_CRTCL (fetype))
2471 emitcode ("clr", "ea");
2473 /* here we need to generate the equates for the
2474 register bank if required */
2475 if (SPEC_BANK (fetype) != rbank)
2479 rbank = SPEC_BANK (fetype);
2480 for (i = 0; i < ds390_nRegs; i++)
2482 if (strcmp (regs390[i].base, "0") == 0)
2483 emitcode ("", "%s = 0x%02x",
2485 8 * rbank + regs390[i].offset);
2487 emitcode ("", "%s = %s + 0x%02x",
2490 8 * rbank + regs390[i].offset);
2494 /* if this is an interrupt service routine then
2495 save acc, b, dpl, dph */
2496 if (IS_ISR (sym->etype))
2499 if (!inExcludeList ("acc"))
2500 emitcode ("push", "acc");
2501 if (!inExcludeList ("b"))
2502 emitcode ("push", "b");
2503 if (!inExcludeList ("dpl"))
2504 emitcode ("push", "dpl");
2505 if (!inExcludeList ("dph"))
2506 emitcode ("push", "dph");
2507 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2509 emitcode ("push", "dpx");
2510 /* Make sure we're using standard DPTR */
2511 emitcode ("push", "dps");
2512 emitcode ("mov", "dps, #0x00");
2513 if (options.stack10bit)
2515 /* This ISR could conceivably use DPTR2. Better save it. */
2516 emitcode ("push", "dpl1");
2517 emitcode ("push", "dph1");
2518 emitcode ("push", "dpx1");
2519 emitcode ("push", DP2_RESULT_REG);
2522 /* if this isr has no bank i.e. is going to
2523 run with bank 0 , then we need to save more
2525 if (!SPEC_BANK (sym->etype))
2528 /* if this function does not call any other
2529 function then we can be economical and
2530 save only those registers that are used */
2535 /* if any registers used */
2538 /* save the registers used */
2539 for (i = 0; i < sym->regsUsed->size; i++)
2541 if (bitVectBitValue (sym->regsUsed, i) ||
2542 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2543 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2550 /* this function has a function call cannot
2551 determines register usage so we will have the
2553 saverbank (0, ic, FALSE);
2559 /* if callee-save to be used for this function
2560 then save the registers being used in this function */
2561 if (sym->calleeSave)
2565 /* if any registers used */
2568 /* save the registers used */
2569 for (i = 0; i < sym->regsUsed->size; i++)
2571 if (bitVectBitValue (sym->regsUsed, i) ||
2572 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2574 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2582 /* set the register bank to the desired value */
2583 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2585 emitcode ("push", "psw");
2586 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2589 if (IS_RENT (sym->etype) || options.stackAuto)
2592 if (options.useXstack)
2594 emitcode ("mov", "r0,%s", spname);
2595 emitcode ("mov", "a,_bp");
2596 emitcode ("movx", "@r0,a");
2597 emitcode ("inc", "%s", spname);
2601 /* set up the stack */
2602 emitcode ("push", "_bp"); /* save the callers stack */
2604 emitcode ("mov", "_bp,%s", spname);
2607 /* adjust the stack for the function */
2613 werror (W_STACK_OVERFLOW, sym->name);
2615 if (i > 3 && sym->recvSize < 4)
2618 emitcode ("mov", "a,sp");
2619 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2620 emitcode ("mov", "sp,a");
2625 emitcode ("inc", "sp");
2631 emitcode ("mov", "a,_spx");
2632 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2633 emitcode ("mov", "_spx,a");
2638 /*-----------------------------------------------------------------*/
2639 /* genEndFunction - generates epilogue for functions */
2640 /*-----------------------------------------------------------------*/
2642 genEndFunction (iCode * ic)
2644 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2646 D (emitcode (";", "genEndFunction ");
2649 if (IS_RENT (sym->etype) || options.stackAuto)
2651 emitcode ("mov", "%s,_bp", spname);
2654 /* if use external stack but some variables were
2655 added to the local stack then decrement the
2657 if (options.useXstack && sym->stack)
2659 emitcode ("mov", "a,sp");
2660 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2661 emitcode ("mov", "sp,a");
2665 if ((IS_RENT (sym->etype) || options.stackAuto))
2667 if (options.useXstack)
2669 emitcode ("mov", "r0,%s", spname);
2670 emitcode ("movx", "a,@r0");
2671 emitcode ("mov", "_bp,a");
2672 emitcode ("dec", "%s", spname);
2676 emitcode ("pop", "_bp");
2680 /* restore the register bank */
2681 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2682 emitcode ("pop", "psw");
2684 if (IS_ISR (sym->etype))
2687 /* now we need to restore the registers */
2688 /* if this isr has no bank i.e. is going to
2689 run with bank 0 , then we need to save more
2691 if (!SPEC_BANK (sym->etype))
2694 /* if this function does not call any other
2695 function then we can be economical and
2696 save only those registers that are used */
2701 /* if any registers used */
2704 /* save the registers used */
2705 for (i = sym->regsUsed->size; i >= 0; i--)
2707 if (bitVectBitValue (sym->regsUsed, i) ||
2708 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2709 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2716 /* this function has a function call cannot
2717 determines register usage so we will have the
2719 unsaverbank (0, ic, FALSE);
2723 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2725 if (options.stack10bit)
2727 emitcode ("pop", DP2_RESULT_REG);
2728 emitcode ("pop", "dpx1");
2729 emitcode ("pop", "dph1");
2730 emitcode ("pop", "dpl1");
2732 emitcode ("pop", "dps");
2733 emitcode ("pop", "dpx");
2735 if (!inExcludeList ("dph"))
2736 emitcode ("pop", "dph");
2737 if (!inExcludeList ("dpl"))
2738 emitcode ("pop", "dpl");
2739 if (!inExcludeList ("b"))
2740 emitcode ("pop", "b");
2741 if (!inExcludeList ("acc"))
2742 emitcode ("pop", "acc");
2744 if (SPEC_CRTCL (sym->etype))
2745 emitcode ("setb", "ea");
2747 /* if debug then send end of function */
2748 /* if (options.debug && currFunc) { */
2752 emitcode ("", "C$%s$%d$%d$%d ==.",
2753 FileBaseName (ic->filename), currFunc->lastLine,
2754 ic->level, ic->block);
2755 if (IS_STATIC (currFunc->etype))
2756 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2758 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2762 emitcode ("reti", "");
2766 if (SPEC_CRTCL (sym->etype))
2767 emitcode ("setb", "ea");
2769 if (sym->calleeSave)
2773 /* if any registers used */
2776 /* save the registers used */
2777 for (i = sym->regsUsed->size; i >= 0; i--)
2779 if (bitVectBitValue (sym->regsUsed, i) ||
2780 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2781 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2787 /* if debug then send end of function */
2791 emitcode ("", "C$%s$%d$%d$%d ==.",
2792 FileBaseName (ic->filename), currFunc->lastLine,
2793 ic->level, ic->block);
2794 if (IS_STATIC (currFunc->etype))
2795 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2797 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2801 emitcode ("ret", "");
2806 /*-----------------------------------------------------------------*/
2807 /* genRet - generate code for return statement */
2808 /*-----------------------------------------------------------------*/
2812 int size, offset = 0, pushed = 0;
2814 D (emitcode (";", "genRet ");
2817 /* if we have no return value then
2818 just generate the "ret" */
2822 /* we have something to return then
2823 move the return value into place */
2824 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2825 size = AOP_SIZE (IC_LEFT (ic));
2827 _startLazyDPSEvaluation ();
2831 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2833 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2834 FALSE, TRUE, FALSE);
2835 emitcode ("push", "%s", l);
2840 l = aopGet (AOP (IC_LEFT (ic)), offset,
2841 FALSE, FALSE, FALSE);
2842 if (strcmp (fReturn[offset], l))
2843 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2846 _endLazyDPSEvaluation ();
2853 if (strcmp (fReturn[pushed], "a"))
2854 emitcode ("pop", fReturn[pushed]);
2856 emitcode ("pop", "acc");
2859 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2862 /* generate a jump to the return label
2863 if the next is not the return statement */
2864 if (!(ic->next && ic->next->op == LABEL &&
2865 IC_LABEL (ic->next) == returnLabel))
2867 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2871 /*-----------------------------------------------------------------*/
2872 /* genLabel - generates a label */
2873 /*-----------------------------------------------------------------*/
2875 genLabel (iCode * ic)
2877 /* special case never generate */
2878 if (IC_LABEL (ic) == entryLabel)
2881 D (emitcode (";", "genLabel ");
2884 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2887 /*-----------------------------------------------------------------*/
2888 /* genGoto - generates a ljmp */
2889 /*-----------------------------------------------------------------*/
2891 genGoto (iCode * ic)
2893 D (emitcode (";", "genGoto ");
2895 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2898 /*-----------------------------------------------------------------*/
2899 /* findLabelBackwards: walks back through the iCode chain looking */
2900 /* for the given label. Returns number of iCode instructions */
2901 /* between that label and given ic. */
2902 /* Returns zero if label not found. */
2903 /*-----------------------------------------------------------------*/
2905 findLabelBackwards (iCode * ic, int key)
2914 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2916 /* printf("findLabelBackwards = %d\n", count); */
2924 /*-----------------------------------------------------------------*/
2925 /* genPlusIncr :- does addition with increment if possible */
2926 /*-----------------------------------------------------------------*/
2928 genPlusIncr (iCode * ic)
2930 unsigned int icount;
2931 unsigned int size = getDataSize (IC_RESULT (ic));
2933 /* will try to generate an increment */
2934 /* if the right side is not a literal
2936 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2939 /* if the literal value of the right hand side
2940 is greater than 4 then it is not worth it */
2941 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2944 /* if increment 16 bits in register */
2946 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2947 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2948 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2956 /* If the next instruction is a goto and the goto target
2957 * is <= 5 instructions previous to this, we can generate
2958 * jumps straight to that target.
2960 if (ic->next && ic->next->op == GOTO
2961 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2964 emitcode (";", "tail increment optimized (range %d)", labelRange);
2965 tlbl = IC_LABEL (ic->next);
2970 tlbl = newiTempLabel (NULL);
2973 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2974 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2975 IS_AOP_PREG (IC_RESULT (ic)))
2976 emitcode ("cjne", "%s,#0x00,%05d$"
2977 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2981 emitcode ("clr", "a");
2982 emitcode ("cjne", "a,%s,%05d$"
2983 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2987 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2990 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2991 IS_AOP_PREG (IC_RESULT (ic)))
2992 emitcode ("cjne", "%s,#0x00,%05d$"
2993 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2996 emitcode ("cjne", "a,%s,%05d$"
2997 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3000 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3004 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3005 IS_AOP_PREG (IC_RESULT (ic)))
3006 emitcode ("cjne", "%s,#0x00,%05d$"
3007 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3011 emitcode ("cjne", "a,%s,%05d$"
3012 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3015 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3020 emitcode ("", "%05d$:", tlbl->key + 100);
3025 /* if the sizes are greater than 1 then we cannot */
3026 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3027 AOP_SIZE (IC_LEFT (ic)) > 1)
3030 /* we can if the aops of the left & result match or
3031 if they are in registers and the registers are the
3034 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3035 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3036 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3041 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3042 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3043 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3048 _startLazyDPSEvaluation ();
3051 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3053 _endLazyDPSEvaluation ();
3062 /*-----------------------------------------------------------------*/
3063 /* outBitAcc - output a bit in acc */
3064 /*-----------------------------------------------------------------*/
3066 outBitAcc (operand * result)
3068 symbol *tlbl = newiTempLabel (NULL);
3069 /* if the result is a bit */
3070 if (AOP_TYPE (result) == AOP_CRY)
3072 aopPut (AOP (result), "a", 0);
3076 emitcode ("jz", "%05d$", tlbl->key + 100);
3077 emitcode ("mov", "a,%s", one);
3078 emitcode ("", "%05d$:", tlbl->key + 100);
3083 /*-----------------------------------------------------------------*/
3084 /* genPlusBits - generates code for addition of two bits */
3085 /*-----------------------------------------------------------------*/
3087 genPlusBits (iCode * ic)
3089 D (emitcode (";", "genPlusBits ");
3091 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3093 symbol *lbl = newiTempLabel (NULL);
3094 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3096 emitcode ("cpl", "c");
3097 emitcode ("", "%05d$:", (lbl->key + 100));
3098 outBitC (IC_RESULT (ic));
3102 emitcode ("clr", "a");
3103 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3104 emitcode ("rlc", "a");
3105 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3106 emitcode ("addc", "a,#0x00");
3107 outAcc (IC_RESULT (ic));
3112 adjustArithmeticResult (iCode * ic)
3114 if (opIsGptr (IC_RESULT (ic)) &&
3115 opIsGptr (IC_LEFT (ic)) &&
3116 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3118 aopPut (AOP (IC_RESULT (ic)),
3119 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3123 if (opIsGptr (IC_RESULT (ic)) &&
3124 opIsGptr (IC_RIGHT (ic)) &&
3125 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3127 aopPut (AOP (IC_RESULT (ic)),
3128 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3132 if (opIsGptr (IC_RESULT (ic)) &&
3133 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3134 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3135 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3139 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3140 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3144 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3145 // (because all three operands are in far space).
3146 #define AOP_OP_3(ic) \
3147 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3148 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3149 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3150 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3151 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3152 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3154 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3156 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3159 // Macro to aopOp all three operands of an ic. If this cannot be done,
3160 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3161 // will be set TRUE. The caller must then handle the case specially, noting
3162 // that the IC_RESULT operand is not aopOp'd.
3163 #define AOP_OP_3_NOFATAL(ic, rc) \
3164 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3165 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3166 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3167 isOperandInFarSpace(IC_RESULT(ic))) \
3169 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3174 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3175 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3177 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3178 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3180 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3182 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3186 // aopOp the left & right operands of an ic.
3187 #define AOP_OP_2(ic) \
3188 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3189 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3191 // convienience macro.
3192 #define AOP_SET_LOCALS(ic) \
3193 left = IC_LEFT(ic); \
3194 right = IC_RIGHT(ic); \
3195 result = IC_RESULT(ic);
3198 // Given an integer value of pushedSize bytes on the stack,
3199 // adjust it to be resultSize bytes, either by discarding
3200 // the most significant bytes or by zero-padding.
3202 // On exit from this macro, pushedSize will have been adjusted to
3203 // equal resultSize, and ACC may be trashed.
3204 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3205 /* If the pushed data is bigger than the result, \
3206 * simply discard unused bytes. Icky, but works. \
3208 while (pushedSize > resultSize) \
3210 D (emitcode (";", "discarding unused result byte."););\
3211 emitcode ("pop", "acc"); \
3214 if (pushedSize < resultSize) \
3216 emitcode ("clr", "a"); \
3217 /* Conversly, we haven't pushed enough here. \
3218 * just zero-pad, and all is well. \
3220 while (pushedSize < resultSize) \
3222 emitcode("push", "acc"); \
3226 assert(pushedSize == resultSize);
3228 /*-----------------------------------------------------------------*/
3229 /* genPlus - generates code for addition */
3230 /*-----------------------------------------------------------------*/
3232 genPlus (iCode * ic)
3234 int size, offset = 0;
3235 bool pushResult = FALSE;
3238 D (emitcode (";", "genPlus "););
3240 /* special cases :- */
3242 AOP_OP_3_NOFATAL (ic, pushResult);
3245 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3250 /* if literal, literal on the right or
3251 if left requires ACC or right is already
3253 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3254 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3255 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3257 operand *t = IC_RIGHT (ic);
3258 IC_RIGHT (ic) = IC_LEFT (ic);
3260 emitcode (";", "Swapped plus args.");
3263 /* if both left & right are in bit
3265 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3266 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3272 /* if left in bit space & right literal */
3273 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3274 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3276 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3277 /* if result in bit space */
3278 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3280 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3281 emitcode ("cpl", "c");
3282 outBitC (IC_RESULT (ic));
3286 size = getDataSize (IC_RESULT (ic));
3287 _startLazyDPSEvaluation ();
3290 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3291 emitcode ("addc", "a,#00");
3292 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3294 _endLazyDPSEvaluation ();
3299 /* if I can do an increment instead
3300 of add then GOOD for ME */
3301 if (genPlusIncr (ic) == TRUE)
3303 emitcode (";", "did genPlusIncr");
3308 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3310 _startLazyDPSEvaluation ();
3313 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3315 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3317 emitcode ("add", "a,%s",
3318 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3320 emitcode ("addc", "a,%s",
3321 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3325 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3327 emitcode ("add", "a,%s",
3328 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3330 emitcode ("addc", "a,%s",
3331 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3335 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3339 emitcode ("push", "acc");
3343 _endLazyDPSEvaluation ();
3347 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3349 size = getDataSize (IC_LEFT (ic));
3350 rSize = getDataSize (IC_RESULT (ic));
3352 ADJUST_PUSHED_RESULT(size, rSize);
3354 _startLazyDPSEvaluation ();
3357 emitcode ("pop", "acc");
3358 aopPut (AOP (IC_RESULT (ic)), "a", size);
3360 _endLazyDPSEvaluation ();
3363 adjustArithmeticResult (ic);
3366 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3367 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3368 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3371 /*-----------------------------------------------------------------*/
3372 /* genMinusDec :- does subtraction with deccrement if possible */
3373 /*-----------------------------------------------------------------*/
3375 genMinusDec (iCode * ic)
3377 unsigned int icount;
3378 unsigned int size = getDataSize (IC_RESULT (ic));
3380 /* will try to generate an increment */
3381 /* if the right side is not a literal
3383 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3386 /* if the literal value of the right hand side
3387 is greater than 4 then it is not worth it */
3388 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3391 /* if decrement 16 bits in register */
3392 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3393 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3394 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3402 /* If the next instruction is a goto and the goto target
3403 * is <= 5 instructions previous to this, we can generate
3404 * jumps straight to that target.
3406 if (ic->next && ic->next->op == GOTO
3407 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3410 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3411 tlbl = IC_LABEL (ic->next);
3416 tlbl = newiTempLabel (NULL);
3420 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3421 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3422 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3423 IS_AOP_PREG (IC_RESULT (ic)))
3424 emitcode ("cjne", "%s,#0xff,%05d$"
3425 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3429 emitcode ("mov", "a,#0xff");
3430 emitcode ("cjne", "a,%s,%05d$"
3431 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3434 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3437 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3438 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3439 IS_AOP_PREG (IC_RESULT (ic)))
3440 emitcode ("cjne", "%s,#0xff,%05d$"
3441 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3445 emitcode ("cjne", "a,%s,%05d$"
3446 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3449 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3453 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3454 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3455 IS_AOP_PREG (IC_RESULT (ic)))
3456 emitcode ("cjne", "%s,#0xff,%05d$"
3457 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3461 emitcode ("cjne", "a,%s,%05d$"
3462 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3465 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3469 emitcode ("", "%05d$:", tlbl->key + 100);
3474 /* if the sizes are greater than 1 then we cannot */
3475 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3476 AOP_SIZE (IC_LEFT (ic)) > 1)
3479 /* we can if the aops of the left & result match or
3480 if they are in registers and the registers are the
3483 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3484 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3485 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3488 _startLazyDPSEvaluation ();
3491 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3493 _endLazyDPSEvaluation ();
3501 /*-----------------------------------------------------------------*/
3502 /* addSign - complete with sign */
3503 /*-----------------------------------------------------------------*/
3505 addSign (operand * result, int offset, int sign)
3507 int size = (getDataSize (result) - offset);
3510 _startLazyDPSEvaluation();
3513 emitcode ("rlc", "a");
3514 emitcode ("subb", "a,acc");
3517 aopPut (AOP (result), "a", offset++);
3524 aopPut (AOP (result), zero, offset++);
3527 _endLazyDPSEvaluation();
3531 /*-----------------------------------------------------------------*/
3532 /* genMinusBits - generates code for subtraction of two bits */
3533 /*-----------------------------------------------------------------*/
3535 genMinusBits (iCode * ic)
3537 symbol *lbl = newiTempLabel (NULL);
3539 D (emitcode (";", "genMinusBits "););
3541 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3543 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3544 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3545 emitcode ("cpl", "c");
3546 emitcode ("", "%05d$:", (lbl->key + 100));
3547 outBitC (IC_RESULT (ic));
3551 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3552 emitcode ("subb", "a,acc");
3553 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3554 emitcode ("inc", "a");
3555 emitcode ("", "%05d$:", (lbl->key + 100));
3556 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3557 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3561 /*-----------------------------------------------------------------*/
3562 /* genMinus - generates code for subtraction */
3563 /*-----------------------------------------------------------------*/
3565 genMinus (iCode * ic)
3567 int size, offset = 0;
3569 unsigned long lit = 0L;
3570 bool pushResult = FALSE;
3572 D (emitcode (";", "genMinus "););
3574 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3575 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3576 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3577 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3583 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3585 /* special cases :- */
3586 /* if both left & right are in bit space */
3587 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3588 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3594 /* if I can do an decrement instead
3595 of subtract then GOOD for ME */
3596 if (genMinusDec (ic) == TRUE)
3601 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3603 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3609 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3614 /* if literal, add a,#-lit, else normal subb */
3615 _startLazyDPSEvaluation ();
3618 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3619 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3620 emitcode ("subb", "a,%s",
3621 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3624 /* first add without previous c */
3626 emitcode ("add", "a,#0x%02x",
3627 (unsigned int) (lit & 0x0FFL));
3629 emitcode ("addc", "a,#0x%02x",
3630 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3635 emitcode ("push", "acc");
3639 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3643 _endLazyDPSEvaluation ();
3647 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3649 size = getDataSize (IC_LEFT (ic));
3650 rSize = getDataSize (IC_RESULT (ic));
3652 ADJUST_PUSHED_RESULT(size, rSize);
3654 _startLazyDPSEvaluation ();
3657 emitcode ("pop", "acc");
3658 aopPut (AOP (IC_RESULT (ic)), "a", size);
3660 _endLazyDPSEvaluation ();
3663 adjustArithmeticResult (ic);
3666 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3667 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3668 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3672 /*-----------------------------------------------------------------*/
3673 /* genMultbits :- multiplication of bits */
3674 /*-----------------------------------------------------------------*/
3676 genMultbits (operand * left,
3680 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3681 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3686 /*-----------------------------------------------------------------*/
3687 /* genMultOneByte : 8*8=8/16 bit multiplication */
3688 /*-----------------------------------------------------------------*/
3690 genMultOneByte (operand * left,
3694 sym_link *opetype = operandType (result);
3696 int size=AOP_SIZE(result);
3698 emitcode (";",__FUNCTION__);
3699 if (size<1 || size>2) {
3700 // this should never happen
3701 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3702 AOP_SIZE(result), __FUNCTION__, lineno);
3706 /* (if two literals: the value is computed before) */
3707 /* if one literal, literal on the right */
3708 if (AOP_TYPE (left) == AOP_LIT)
3713 emitcode (";", "swapped left and right");
3716 if (SPEC_USIGN(opetype)
3717 // ignore the sign of left and right, what else can we do?
3718 || (SPEC_USIGN(operandType(left)) &&
3719 SPEC_USIGN(operandType(right)))) {
3720 // just an unsigned 8*8=8/16 multiply
3721 //emitcode (";","unsigned");
3722 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3723 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3724 emitcode ("mul", "ab");
3725 aopPut (AOP (result), "a", 0);
3727 aopPut (AOP (result), "b", 1);
3732 // we have to do a signed multiply
3734 emitcode (";", "signed");
3735 emitcode ("clr", "F0"); // reset sign flag
3736 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3737 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3739 lbl=newiTempLabel(NULL);
3740 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3741 // left side is negative, 8-bit two's complement, this fails for -128
3742 emitcode ("setb", "F0"); // set sign flag
3743 emitcode ("cpl", "a");
3744 emitcode ("inc", "a");
3746 emitcode ("", "%05d$:", lbl->key+100);
3747 emitcode ("xch", "a,b");
3750 if (AOP_TYPE(right)==AOP_LIT) {
3751 /* AND literal negative */
3752 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3753 // two's complement for literal<0
3754 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3755 emitcode ("cpl", "a");
3756 emitcode ("inc", "a");
3759 lbl=newiTempLabel(NULL);
3760 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3761 // right side is negative, 8-bit two's complement
3762 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3763 emitcode ("cpl", "a");
3764 emitcode ("inc", "a");
3765 emitcode ("", "%05d$:", lbl->key+100);
3767 emitcode ("mul", "ab");
3769 lbl=newiTempLabel(NULL);
3770 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3771 // only ONE op was negative, we have to do a 8/16-bit two's complement
3772 emitcode ("cpl", "a"); // lsb
3774 emitcode ("inc", "a");
3776 emitcode ("add", "a,#1");
3777 emitcode ("xch", "a,b");
3778 emitcode ("cpl", "a"); // msb
3779 emitcode ("addc", "a,#0");
3780 emitcode ("xch", "a,b");
3783 emitcode ("", "%05d$:", lbl->key+100);
3784 aopPut (AOP (result), "a", 0);
3786 aopPut (AOP (result), "b", 1);
3790 /*-----------------------------------------------------------------*/
3791 /* genMult - generates code for multiplication */
3792 /*-----------------------------------------------------------------*/
3794 genMult (iCode * ic)
3796 operand *left = IC_LEFT (ic);
3797 operand *right = IC_RIGHT (ic);
3798 operand *result = IC_RESULT (ic);
3800 D (emitcode (";", "genMult "););
3802 /* assign the amsops */
3805 /* special cases first */
3807 if (AOP_TYPE (left) == AOP_CRY &&
3808 AOP_TYPE (right) == AOP_CRY)
3810 genMultbits (left, right, result);
3814 /* if both are of size == 1 */
3815 if (AOP_SIZE (left) == 1 &&
3816 AOP_SIZE (right) == 1)
3818 genMultOneByte (left, right, result);
3822 /* should have been converted to function call */
3826 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3827 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3828 freeAsmop (result, NULL, ic, TRUE);
3831 /*-----------------------------------------------------------------*/
3832 /* genDivbits :- division of bits */
3833 /*-----------------------------------------------------------------*/
3835 genDivbits (operand * left,
3842 /* the result must be bit */
3843 LOAD_AB_FOR_DIV (left, right, l);
3844 emitcode ("div", "ab");
3845 emitcode ("rrc", "a");
3846 aopPut (AOP (result), "c", 0);
3849 /*-----------------------------------------------------------------*/
3850 /* genDivOneByte : 8 bit division */
3851 /*-----------------------------------------------------------------*/
3853 genDivOneByte (operand * left,
3857 sym_link *opetype = operandType (result);
3862 size = AOP_SIZE (result) - 1;
3864 /* signed or unsigned */
3865 if (SPEC_USIGN (opetype))
3867 /* unsigned is easy */
3868 LOAD_AB_FOR_DIV (left, right, l);
3869 emitcode ("div", "ab");
3870 aopPut (AOP (result), "a", 0);
3872 aopPut (AOP (result), zero, offset++);
3876 /* signed is a little bit more difficult */
3878 /* save the signs of the operands */
3879 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3881 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3882 emitcode ("push", "acc"); /* save it on the stack */
3884 /* now sign adjust for both left & right */
3885 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3887 lbl = newiTempLabel (NULL);
3888 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3889 emitcode ("cpl", "a");
3890 emitcode ("inc", "a");
3891 emitcode ("", "%05d$:", (lbl->key + 100));
3892 emitcode ("mov", "b,a");
3894 /* sign adjust left side */
3895 l = aopGet (AOP (left), 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));
3904 /* now the division */
3905 emitcode ("nop", "; workaround for DS80C390 div bug.");
3906 emitcode ("div", "ab");
3907 /* we are interested in the lower order
3909 emitcode ("mov", "b,a");
3910 lbl = newiTempLabel (NULL);
3911 emitcode ("pop", "acc");
3912 /* if there was an over flow we don't
3913 adjust the sign of the result */
3914 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3915 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3917 emitcode ("clr", "a");
3918 emitcode ("subb", "a,b");
3919 emitcode ("mov", "b,a");
3920 emitcode ("", "%05d$:", (lbl->key + 100));
3922 /* now we are done */
3923 aopPut (AOP (result), "b", 0);
3926 emitcode ("mov", "c,b.7");
3927 emitcode ("subb", "a,acc");
3930 aopPut (AOP (result), "a", offset++);
3934 /*-----------------------------------------------------------------*/
3935 /* genDiv - generates code for division */
3936 /*-----------------------------------------------------------------*/
3940 operand *left = IC_LEFT (ic);
3941 operand *right = IC_RIGHT (ic);
3942 operand *result = IC_RESULT (ic);
3944 D (emitcode (";", "genDiv ");
3947 /* assign the amsops */
3950 /* special cases first */
3952 if (AOP_TYPE (left) == AOP_CRY &&
3953 AOP_TYPE (right) == AOP_CRY)
3955 genDivbits (left, right, result);
3959 /* if both are of size == 1 */
3960 if (AOP_SIZE (left) == 1 &&
3961 AOP_SIZE (right) == 1)
3963 genDivOneByte (left, right, result);
3967 /* should have been converted to function call */
3970 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3971 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3972 freeAsmop (result, NULL, ic, TRUE);
3975 /*-----------------------------------------------------------------*/
3976 /* genModbits :- modulus of bits */
3977 /*-----------------------------------------------------------------*/
3979 genModbits (operand * left,
3986 /* the result must be bit */
3987 LOAD_AB_FOR_DIV (left, right, l);
3988 emitcode ("div", "ab");
3989 emitcode ("mov", "a,b");
3990 emitcode ("rrc", "a");
3991 aopPut (AOP (result), "c", 0);
3994 /*-----------------------------------------------------------------*/
3995 /* genModOneByte : 8 bit modulus */
3996 /*-----------------------------------------------------------------*/
3998 genModOneByte (operand * left,
4002 sym_link *opetype = operandType (result);
4006 /* signed or unsigned */
4007 if (SPEC_USIGN (opetype))
4009 /* unsigned is easy */
4010 LOAD_AB_FOR_DIV (left, right, l);
4011 emitcode ("div", "ab");
4012 aopPut (AOP (result), "b", 0);
4016 /* signed is a little bit more difficult */
4018 /* save the signs of the operands */
4019 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4022 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4023 emitcode ("push", "acc"); /* save it on the stack */
4025 /* now sign adjust for both left & right */
4026 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4029 lbl = newiTempLabel (NULL);
4030 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4031 emitcode ("cpl", "a");
4032 emitcode ("inc", "a");
4033 emitcode ("", "%05d$:", (lbl->key + 100));
4034 emitcode ("mov", "b,a");
4036 /* sign adjust left side */
4037 l = aopGet (AOP (left), 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));
4046 /* now the multiplication */
4047 emitcode ("nop", "; workaround for DS80C390 div bug.");
4048 emitcode ("div", "ab");
4049 /* we are interested in the lower order
4051 lbl = newiTempLabel (NULL);
4052 emitcode ("pop", "acc");
4053 /* if there was an over flow we don't
4054 adjust the sign of the result */
4055 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4056 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4058 emitcode ("clr", "a");
4059 emitcode ("subb", "a,b");
4060 emitcode ("mov", "b,a");
4061 emitcode ("", "%05d$:", (lbl->key + 100));
4063 /* now we are done */
4064 aopPut (AOP (result), "b", 0);
4068 /*-----------------------------------------------------------------*/
4069 /* genMod - generates code for division */
4070 /*-----------------------------------------------------------------*/
4074 operand *left = IC_LEFT (ic);
4075 operand *right = IC_RIGHT (ic);
4076 operand *result = IC_RESULT (ic);
4078 D (emitcode (";", "genMod ");
4081 /* assign the amsops */
4084 /* special cases first */
4086 if (AOP_TYPE (left) == AOP_CRY &&
4087 AOP_TYPE (right) == AOP_CRY)
4089 genModbits (left, right, result);
4093 /* if both are of size == 1 */
4094 if (AOP_SIZE (left) == 1 &&
4095 AOP_SIZE (right) == 1)
4097 genModOneByte (left, right, result);
4101 /* should have been converted to function call */
4105 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4106 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4107 freeAsmop (result, NULL, ic, TRUE);
4110 /*-----------------------------------------------------------------*/
4111 /* genIfxJump :- will create a jump depending on the ifx */
4112 /*-----------------------------------------------------------------*/
4114 genIfxJump (iCode * ic, char *jval)
4117 symbol *tlbl = newiTempLabel (NULL);
4120 D (emitcode (";", "genIfxJump ");
4123 /* if true label then we jump if condition
4127 jlbl = IC_TRUE (ic);
4128 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4129 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4133 /* false label is present */
4134 jlbl = IC_FALSE (ic);
4135 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4136 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4138 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4139 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4141 emitcode (inst, "%05d$", tlbl->key + 100);
4142 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4143 emitcode ("", "%05d$:", tlbl->key + 100);
4145 /* mark the icode as generated */
4149 /*-----------------------------------------------------------------*/
4150 /* genCmp :- greater or less than comparison */
4151 /*-----------------------------------------------------------------*/
4153 genCmp (operand * left, operand * right,
4154 iCode * ic, iCode * ifx, int sign)
4156 int size, offset = 0;
4157 unsigned long lit = 0L;
4160 D (emitcode (";", "genCmp");
4163 result = IC_RESULT (ic);
4165 /* if left & right are bit variables */
4166 if (AOP_TYPE (left) == AOP_CRY &&
4167 AOP_TYPE (right) == AOP_CRY)
4169 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4170 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4174 /* subtract right from left if at the
4175 end the carry flag is set then we know that
4176 left is greater than right */
4177 size = max (AOP_SIZE (left), AOP_SIZE (right));
4179 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4180 if ((size == 1) && !sign &&
4181 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4183 symbol *lbl = newiTempLabel (NULL);
4184 emitcode ("cjne", "%s,%s,%05d$",
4185 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4186 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4188 emitcode ("", "%05d$:", lbl->key + 100);
4192 if (AOP_TYPE (right) == AOP_LIT)
4194 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4195 /* optimize if(x < 0) or if(x >= 0) */
4204 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4206 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4207 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4209 aopOp (result, ic, FALSE, FALSE);
4211 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4213 freeAsmop (result, NULL, ic, TRUE);
4214 genIfxJump (ifx, "acc.7");
4219 emitcode ("rlc", "a");
4221 goto release_freedLR;
4229 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4230 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4231 emitcode (";", "genCmp #2");
4232 if (sign && (size == 0))
4234 emitcode (";", "genCmp #3");
4235 emitcode ("xrl", "a,#0x80");
4236 if (AOP_TYPE (right) == AOP_LIT)
4238 unsigned long lit = (unsigned long)
4239 floatFromVal (AOP (right)->aopu.aop_lit);
4240 emitcode (";", "genCmp #3.1");
4241 emitcode ("subb", "a,#0x%02x",
4242 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4246 emitcode (";", "genCmp #3.2");
4247 if (AOP_NEEDSACC (right))
4249 emitcode ("push", "acc");
4251 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4252 FALSE, FALSE, FALSE));
4253 emitcode ("xrl", "b,#0x80");
4254 if (AOP_NEEDSACC (right))
4256 emitcode ("pop", "acc");
4258 emitcode ("subb", "a,b");
4265 emitcode (";", "genCmp #4");
4266 if (AOP_NEEDSACC (right))
4269 emitcode (";", "genCmp #4.1");
4270 emitcode ("xch", "a, b");
4271 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4272 emitcode ("xch", "a, b");
4277 emitcode (";", "genCmp #4.2");
4278 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4281 emitcode ("subb", "a,%s", s);
4288 /* Don't need the left & right operands any more; do need the result. */
4289 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4290 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4292 aopOp (result, ic, FALSE, FALSE);
4296 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4302 /* if the result is used in the next
4303 ifx conditional branch then generate
4304 code a little differently */
4307 genIfxJump (ifx, "c");
4313 /* leave the result in acc */
4315 freeAsmop (result, NULL, ic, TRUE);
4318 /*-----------------------------------------------------------------*/
4319 /* genCmpGt :- greater than comparison */
4320 /*-----------------------------------------------------------------*/
4322 genCmpGt (iCode * ic, iCode * ifx)
4324 operand *left, *right;
4325 sym_link *letype, *retype;
4328 D (emitcode (";", "genCmpGt ");
4331 left = IC_LEFT (ic);
4332 right = IC_RIGHT (ic);
4334 letype = getSpec (operandType (left));
4335 retype = getSpec (operandType (right));
4336 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4338 /* assign the left & right amsops */
4341 genCmp (right, left, ic, ifx, sign);
4344 /*-----------------------------------------------------------------*/
4345 /* genCmpLt - less than comparisons */
4346 /*-----------------------------------------------------------------*/
4348 genCmpLt (iCode * ic, iCode * ifx)
4350 operand *left, *right;
4351 sym_link *letype, *retype;
4354 D (emitcode (";", "genCmpLt "););
4356 left = IC_LEFT (ic);
4357 right = IC_RIGHT (ic);
4359 letype = getSpec (operandType (left));
4360 retype = getSpec (operandType (right));
4361 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4363 /* assign the left & right amsops */
4366 genCmp (left, right, ic, ifx, sign);
4369 /*-----------------------------------------------------------------*/
4370 /* gencjneshort - compare and jump if not equal */
4371 /*-----------------------------------------------------------------*/
4373 gencjneshort (operand * left, operand * right, symbol * lbl)
4375 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4377 unsigned long lit = 0L;
4379 D (emitcode (";", "gencjneshort");
4382 /* if the left side is a literal or
4383 if the right is in a pointer register and left
4385 if ((AOP_TYPE (left) == AOP_LIT) ||
4386 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4393 if (AOP_TYPE (right) == AOP_LIT)
4394 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4396 if (opIsGptr (left) || opIsGptr (right))
4398 /* We are comparing a generic pointer to something.
4399 * Exclude the generic type byte from the comparison.
4402 D (emitcode (";", "cjneshort: generic ptr special case.");
4407 /* if the right side is a literal then anything goes */
4408 if (AOP_TYPE (right) == AOP_LIT &&
4409 AOP_TYPE (left) != AOP_DIR)
4413 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4415 emitcode ("cjne", "a,%s,%05d$",
4416 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4422 /* if the right side is in a register or in direct space or
4423 if the left is a pointer register & right is not */
4424 else if (AOP_TYPE (right) == AOP_REG ||
4425 AOP_TYPE (right) == AOP_DIR ||
4426 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4427 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4431 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4432 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4433 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4434 emitcode ("jnz", "%05d$", lbl->key + 100);
4436 emitcode ("cjne", "a,%s,%05d$",
4437 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4444 /* right is a pointer reg need both a & b */
4447 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4448 if (strcmp (l, "b"))
4449 emitcode ("mov", "b,%s", l);
4450 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4451 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4457 /*-----------------------------------------------------------------*/
4458 /* gencjne - compare and jump if not equal */
4459 /*-----------------------------------------------------------------*/
4461 gencjne (operand * left, operand * right, symbol * lbl)
4463 symbol *tlbl = newiTempLabel (NULL);
4465 D (emitcode (";", "gencjne");
4468 gencjneshort (left, right, lbl);
4470 emitcode ("mov", "a,%s", one);
4471 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4472 emitcode ("", "%05d$:", lbl->key + 100);
4473 emitcode ("clr", "a");
4474 emitcode ("", "%05d$:", tlbl->key + 100);
4477 /*-----------------------------------------------------------------*/
4478 /* genCmpEq - generates code for equal to */
4479 /*-----------------------------------------------------------------*/
4481 genCmpEq (iCode * ic, iCode * ifx)
4483 operand *left, *right, *result;
4485 D (emitcode (";", "genCmpEq ");
4489 AOP_SET_LOCALS (ic);
4491 /* if literal, literal on the right or
4492 if the right is in a pointer register and left
4494 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4495 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4497 operand *t = IC_RIGHT (ic);
4498 IC_RIGHT (ic) = IC_LEFT (ic);
4502 if (ifx && /* !AOP_SIZE(result) */
4503 OP_SYMBOL (result) &&
4504 OP_SYMBOL (result)->regType == REG_CND)
4507 /* if they are both bit variables */
4508 if (AOP_TYPE (left) == AOP_CRY &&
4509 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4511 if (AOP_TYPE (right) == AOP_LIT)
4513 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4516 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4517 emitcode ("cpl", "c");
4521 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4525 emitcode ("clr", "c");
4527 /* AOP_TYPE(right) == AOP_CRY */
4531 symbol *lbl = newiTempLabel (NULL);
4532 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4533 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4534 emitcode ("cpl", "c");
4535 emitcode ("", "%05d$:", (lbl->key + 100));
4537 /* if true label then we jump if condition
4539 tlbl = newiTempLabel (NULL);
4542 emitcode ("jnc", "%05d$", tlbl->key + 100);
4543 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4547 emitcode ("jc", "%05d$", tlbl->key + 100);
4548 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4550 emitcode ("", "%05d$:", tlbl->key + 100);
4554 tlbl = newiTempLabel (NULL);
4555 gencjneshort (left, right, tlbl);
4558 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4559 emitcode ("", "%05d$:", tlbl->key + 100);
4563 symbol *lbl = newiTempLabel (NULL);
4564 emitcode ("sjmp", "%05d$", lbl->key + 100);
4565 emitcode ("", "%05d$:", tlbl->key + 100);
4566 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4567 emitcode ("", "%05d$:", lbl->key + 100);
4570 /* mark the icode as generated */
4573 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4574 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 /* if they are both bit variables */
4579 if (AOP_TYPE (left) == AOP_CRY &&
4580 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4582 if (AOP_TYPE (right) == AOP_LIT)
4584 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4588 emitcode ("cpl", "c");
4592 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4596 emitcode ("clr", "c");
4598 /* AOP_TYPE(right) == AOP_CRY */
4602 symbol *lbl = newiTempLabel (NULL);
4603 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4604 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4605 emitcode ("cpl", "c");
4606 emitcode ("", "%05d$:", (lbl->key + 100));
4609 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4612 aopOp (result, ic, TRUE, FALSE);
4615 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4622 genIfxJump (ifx, "c");
4625 /* if the result is used in an arithmetic operation
4626 then put the result in place */
4631 gencjne (left, right, newiTempLabel (NULL));
4633 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4634 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636 aopOp (result, ic, TRUE, FALSE);
4638 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4640 aopPut (AOP (result), "a", 0);
4645 genIfxJump (ifx, "a");
4648 /* if the result is used in an arithmetic operation
4649 then put the result in place */
4650 if (AOP_TYPE (result) != AOP_CRY)
4652 /* leave the result in acc */
4656 freeAsmop (result, NULL, ic, TRUE);
4659 /*-----------------------------------------------------------------*/
4660 /* ifxForOp - returns the icode containing the ifx for operand */
4661 /*-----------------------------------------------------------------*/
4663 ifxForOp (operand * op, iCode * ic)
4665 /* if true symbol then needs to be assigned */
4666 if (IS_TRUE_SYMOP (op))
4669 /* if this has register type condition and
4670 the next instruction is ifx with the same operand
4671 and live to of the operand is upto the ifx only then */
4673 ic->next->op == IFX &&
4674 IC_COND (ic->next)->key == op->key &&
4675 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4680 /*-----------------------------------------------------------------*/
4681 /* genAndOp - for && operation */
4682 /*-----------------------------------------------------------------*/
4684 genAndOp (iCode * ic)
4686 operand *left, *right, *result;
4689 D (emitcode (";", "genAndOp "););
4691 /* note here that && operations that are in an
4692 if statement are taken away by backPatchLabels
4693 only those used in arthmetic operations remain */
4695 AOP_SET_LOCALS (ic);
4697 /* if both are bit variables */
4698 if (AOP_TYPE (left) == AOP_CRY &&
4699 AOP_TYPE (right) == AOP_CRY)
4701 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4702 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4703 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4704 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4706 aopOp (result,ic,FALSE, FALSE);
4711 tlbl = newiTempLabel (NULL);
4713 emitcode ("jz", "%05d$", tlbl->key + 100);
4715 emitcode ("", "%05d$:", tlbl->key + 100);
4716 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4717 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4719 aopOp (result,ic,FALSE, FALSE);
4722 freeAsmop (result, NULL, ic, TRUE);
4726 /*-----------------------------------------------------------------*/
4727 /* genOrOp - for || operation */
4728 /*-----------------------------------------------------------------*/
4730 genOrOp (iCode * ic)
4732 operand *left, *right, *result;
4735 D (emitcode (";", "genOrOp "););
4737 /* note here that || operations that are in an
4738 if statement are taken away by backPatchLabels
4739 only those used in arthmetic operations remain */
4741 AOP_SET_LOCALS (ic);
4743 /* if both are bit variables */
4744 if (AOP_TYPE (left) == AOP_CRY &&
4745 AOP_TYPE (right) == AOP_CRY)
4747 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4748 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4749 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4752 aopOp (result,ic,FALSE, FALSE);
4758 tlbl = newiTempLabel (NULL);
4760 emitcode ("jnz", "%05d$", tlbl->key + 100);
4762 emitcode ("", "%05d$:", tlbl->key + 100);
4763 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4764 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4766 aopOp (result,ic,FALSE, FALSE);
4771 freeAsmop (result, NULL, ic, TRUE);
4774 /*-----------------------------------------------------------------*/
4775 /* isLiteralBit - test if lit == 2^n */
4776 /*-----------------------------------------------------------------*/
4778 isLiteralBit (unsigned long lit)
4780 unsigned long pw[32] =
4781 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4782 0x100L, 0x200L, 0x400L, 0x800L,
4783 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4784 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4785 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4786 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4787 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4790 for (idx = 0; idx < 32; idx++)
4796 /*-----------------------------------------------------------------*/
4797 /* continueIfTrue - */
4798 /*-----------------------------------------------------------------*/
4800 continueIfTrue (iCode * ic)
4803 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4807 /*-----------------------------------------------------------------*/
4809 /*-----------------------------------------------------------------*/
4811 jumpIfTrue (iCode * ic)
4814 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4818 /*-----------------------------------------------------------------*/
4819 /* jmpTrueOrFalse - */
4820 /*-----------------------------------------------------------------*/
4822 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4824 // ugly but optimized by peephole
4827 symbol *nlbl = newiTempLabel (NULL);
4828 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4829 emitcode ("", "%05d$:", tlbl->key + 100);
4830 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4831 emitcode ("", "%05d$:", nlbl->key + 100);
4835 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4836 emitcode ("", "%05d$:", tlbl->key + 100);
4841 // Generate code to perform a bit-wise logic operation
4842 // on two operands in far space (assumed to already have been
4843 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4844 // in far space. This requires pushing the result on the stack
4845 // then popping it into the result.
4847 genFarFarLogicOp(iCode *ic, char *logicOp)
4849 int size, resultSize, compSize;
4852 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4853 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4854 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4856 _startLazyDPSEvaluation();
4857 for (size = compSize; (size--); offset++)
4859 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4860 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4861 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4863 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4864 emitcode ("push", "acc");
4866 _endLazyDPSEvaluation();
4868 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4869 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4870 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4872 resultSize = AOP_SIZE(IC_RESULT(ic));
4874 ADJUST_PUSHED_RESULT(compSize, resultSize);
4876 _startLazyDPSEvaluation();
4879 emitcode ("pop", "acc");
4880 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4882 _endLazyDPSEvaluation();
4883 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4887 /*-----------------------------------------------------------------*/
4888 /* genAnd - code for and */
4889 /*-----------------------------------------------------------------*/
4891 genAnd (iCode * ic, iCode * ifx)
4893 operand *left, *right, *result;
4894 int size, offset = 0;
4895 unsigned long lit = 0L;
4900 D (emitcode (";", "genAnd "););
4902 AOP_OP_3_NOFATAL (ic, pushResult);
4903 AOP_SET_LOCALS (ic);
4907 genFarFarLogicOp(ic, "anl");
4912 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4914 AOP_TYPE (left), AOP_TYPE (right));
4915 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4917 AOP_SIZE (left), AOP_SIZE (right));
4920 /* if left is a literal & right is not then exchange them */
4921 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4922 AOP_NEEDSACC (left))
4924 operand *tmp = right;
4929 /* if result = right then exchange them */
4930 if (sameRegs (AOP (result), AOP (right)))
4932 operand *tmp = right;
4937 /* if right is bit then exchange them */
4938 if (AOP_TYPE (right) == AOP_CRY &&
4939 AOP_TYPE (left) != AOP_CRY)
4941 operand *tmp = right;
4945 if (AOP_TYPE (right) == AOP_LIT)
4946 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4948 size = AOP_SIZE (result);
4951 // result = bit & yy;
4952 if (AOP_TYPE (left) == AOP_CRY)
4954 // c = bit & literal;
4955 if (AOP_TYPE (right) == AOP_LIT)
4959 if (size && sameRegs (AOP (result), AOP (left)))
4962 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4967 if (size && (AOP_TYPE (result) == AOP_CRY))
4969 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4972 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4977 emitcode ("clr", "c");
4982 if (AOP_TYPE (right) == AOP_CRY)
4985 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4986 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4991 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4993 emitcode ("rrc", "a");
4994 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5002 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5003 genIfxJump (ifx, "c");
5007 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5008 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5009 if ((AOP_TYPE (right) == AOP_LIT) &&
5010 (AOP_TYPE (result) == AOP_CRY) &&
5011 (AOP_TYPE (left) != AOP_CRY))
5013 int posbit = isLiteralBit (lit);
5018 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5021 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5027 sprintf (buffer, "acc.%d", posbit & 0x07);
5028 genIfxJump (ifx, buffer);
5035 symbol *tlbl = newiTempLabel (NULL);
5036 int sizel = AOP_SIZE (left);
5038 emitcode ("setb", "c");
5041 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5043 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5045 if ((posbit = isLiteralBit (bytelit)) != 0)
5046 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5049 if (bytelit != 0x0FFL)
5050 emitcode ("anl", "a,%s",
5051 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5052 emitcode ("jnz", "%05d$", tlbl->key + 100);
5057 // bit = left & literal
5060 emitcode ("clr", "c");
5061 emitcode ("", "%05d$:", tlbl->key + 100);
5063 // if(left & literal)
5067 jmpTrueOrFalse (ifx, tlbl);
5075 /* if left is same as result */
5076 if (sameRegs (AOP (result), AOP (left)))
5078 for (; size--; offset++)
5080 if (AOP_TYPE (right) == AOP_LIT)
5082 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5084 else if (bytelit == 0)
5085 aopPut (AOP (result), zero, offset);
5086 else if (IS_AOP_PREG (result))
5088 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5089 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5090 aopPut (AOP (result), "a", offset);
5093 emitcode ("anl", "%s,%s",
5094 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5095 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5099 if (AOP_TYPE (left) == AOP_ACC)
5100 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5103 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5104 if (IS_AOP_PREG (result))
5106 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5107 aopPut (AOP (result), "a", offset);
5111 emitcode ("anl", "%s,a",
5112 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5119 // left & result in different registers
5120 if (AOP_TYPE (result) == AOP_CRY)
5123 // if(size), result in bit
5124 // if(!size && ifx), conditional oper: if(left & right)
5125 symbol *tlbl = newiTempLabel (NULL);
5126 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5128 emitcode ("setb", "c");
5131 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5132 emitcode ("anl", "a,%s",
5133 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5134 emitcode ("jnz", "%05d$", tlbl->key + 100);
5140 emitcode ("", "%05d$:", tlbl->key + 100);
5144 jmpTrueOrFalse (ifx, tlbl);
5148 for (; (size--); offset++)
5151 // result = left & right
5152 if (AOP_TYPE (right) == AOP_LIT)
5154 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5156 aopPut (AOP (result),
5157 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5161 else if (bytelit == 0)
5163 aopPut (AOP (result), zero, offset);
5166 D (emitcode (";", "better literal AND.");
5168 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5169 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5170 FALSE, FALSE, FALSE));
5175 // faster than result <- left, anl result,right
5176 // and better if result is SFR
5177 if (AOP_TYPE (left) == AOP_ACC)
5179 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5180 FALSE, FALSE, FALSE));
5184 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5185 emitcode ("anl", "a,%s",
5186 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5189 aopPut (AOP (result), "a", offset);
5195 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5196 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5197 freeAsmop (result, NULL, ic, TRUE);
5201 /*-----------------------------------------------------------------*/
5202 /* genOr - code for or */
5203 /*-----------------------------------------------------------------*/
5205 genOr (iCode * ic, iCode * ifx)
5207 operand *left, *right, *result;
5208 int size, offset = 0;
5209 unsigned long lit = 0L;
5212 D (emitcode (";", "genOr "););
5214 AOP_OP_3_NOFATAL (ic, pushResult);
5215 AOP_SET_LOCALS (ic);
5219 genFarFarLogicOp(ic, "orl");
5225 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5227 AOP_TYPE (left), AOP_TYPE (right));
5228 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5230 AOP_SIZE (left), AOP_SIZE (right));
5233 /* if left is a literal & right is not then exchange them */
5234 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5235 AOP_NEEDSACC (left))
5237 operand *tmp = right;
5242 /* if result = right then exchange them */
5243 if (sameRegs (AOP (result), AOP (right)))
5245 operand *tmp = right;
5250 /* if right is bit then exchange them */
5251 if (AOP_TYPE (right) == AOP_CRY &&
5252 AOP_TYPE (left) != AOP_CRY)
5254 operand *tmp = right;
5258 if (AOP_TYPE (right) == AOP_LIT)
5259 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5261 size = AOP_SIZE (result);
5265 if (AOP_TYPE (left) == AOP_CRY)
5267 if (AOP_TYPE (right) == AOP_LIT)
5269 // c = bit & literal;
5272 // lit != 0 => result = 1
5273 if (AOP_TYPE (result) == AOP_CRY)
5276 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5278 continueIfTrue (ifx);
5281 emitcode ("setb", "c");
5285 // lit == 0 => result = left
5286 if (size && sameRegs (AOP (result), AOP (left)))
5288 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5293 if (AOP_TYPE (right) == AOP_CRY)
5296 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5297 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5302 symbol *tlbl = newiTempLabel (NULL);
5303 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5304 emitcode ("setb", "c");
5305 emitcode ("jb", "%s,%05d$",
5306 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5308 emitcode ("jnz", "%05d$", tlbl->key + 100);
5309 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5311 jmpTrueOrFalse (ifx, tlbl);
5317 emitcode ("", "%05d$:", tlbl->key + 100);
5326 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5327 genIfxJump (ifx, "c");
5331 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5332 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5333 if ((AOP_TYPE (right) == AOP_LIT) &&
5334 (AOP_TYPE (result) == AOP_CRY) &&
5335 (AOP_TYPE (left) != AOP_CRY))
5341 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5343 continueIfTrue (ifx);
5348 // lit = 0, result = boolean(left)
5350 emitcode ("setb", "c");
5354 symbol *tlbl = newiTempLabel (NULL);
5355 emitcode ("jnz", "%05d$", tlbl->key + 100);
5357 emitcode ("", "%05d$:", tlbl->key + 100);
5361 genIfxJump (ifx, "a");
5369 /* if left is same as result */
5370 if (sameRegs (AOP (result), AOP (left)))
5372 for (; size--; offset++)
5374 if (AOP_TYPE (right) == AOP_LIT)
5376 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5382 if (IS_AOP_PREG (left))
5384 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5385 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5386 aopPut (AOP (result), "a", offset);
5390 emitcode ("orl", "%s,%s",
5391 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5392 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5398 if (AOP_TYPE (left) == AOP_ACC)
5400 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5404 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5405 if (IS_AOP_PREG (left))
5407 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5408 aopPut (AOP (result), "a", offset);
5412 emitcode ("orl", "%s,a",
5413 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5421 // left & result in different registers
5422 if (AOP_TYPE (result) == AOP_CRY)
5425 // if(size), result in bit
5426 // if(!size && ifx), conditional oper: if(left | right)
5427 symbol *tlbl = newiTempLabel (NULL);
5428 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5430 emitcode ("setb", "c");
5433 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5434 emitcode ("orl", "a,%s",
5435 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5436 emitcode ("jnz", "%05d$", tlbl->key + 100);
5442 emitcode ("", "%05d$:", tlbl->key + 100);
5446 jmpTrueOrFalse (ifx, tlbl);
5450 for (; (size--); offset++)
5453 // result = left & right
5454 if (AOP_TYPE (right) == AOP_LIT)
5456 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5458 aopPut (AOP (result),
5459 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5463 D (emitcode (";", "better literal OR.");
5465 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5466 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5467 FALSE, FALSE, FALSE));
5472 // faster than result <- left, anl result,right
5473 // and better if result is SFR
5474 if (AOP_TYPE (left) == AOP_ACC)
5476 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5477 FALSE, FALSE, FALSE));
5481 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5482 emitcode ("orl", "a,%s",
5483 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5486 aopPut (AOP (result), "a", offset);
5492 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5494 freeAsmop (result, NULL, ic, TRUE);
5497 /*-----------------------------------------------------------------*/
5498 /* genXor - code for xclusive or */
5499 /*-----------------------------------------------------------------*/
5501 genXor (iCode * ic, iCode * ifx)
5503 operand *left, *right, *result;
5504 int size, offset = 0;
5505 unsigned long lit = 0L;
5508 D (emitcode (";", "genXor "););
5510 AOP_OP_3_NOFATAL (ic, pushResult);
5511 AOP_SET_LOCALS (ic);
5515 genFarFarLogicOp(ic, "xrl");
5520 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5522 AOP_TYPE (left), AOP_TYPE (right));
5523 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5525 AOP_SIZE (left), AOP_SIZE (right));
5528 /* if left is a literal & right is not ||
5529 if left needs acc & right does not */
5530 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5531 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5533 operand *tmp = right;
5538 /* if result = right then exchange them */
5539 if (sameRegs (AOP (result), AOP (right)))
5541 operand *tmp = right;
5546 /* if right is bit then exchange them */
5547 if (AOP_TYPE (right) == AOP_CRY &&
5548 AOP_TYPE (left) != AOP_CRY)
5550 operand *tmp = right;
5554 if (AOP_TYPE (right) == AOP_LIT)
5555 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5557 size = AOP_SIZE (result);
5561 if (AOP_TYPE (left) == AOP_CRY)
5563 if (AOP_TYPE (right) == AOP_LIT)
5565 // c = bit & literal;
5568 // lit>>1 != 0 => result = 1
5569 if (AOP_TYPE (result) == AOP_CRY)
5572 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5574 continueIfTrue (ifx);
5577 emitcode ("setb", "c");
5584 // lit == 0, result = left
5585 if (size && sameRegs (AOP (result), AOP (left)))
5587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5591 // lit == 1, result = not(left)
5592 if (size && sameRegs (AOP (result), AOP (left)))
5594 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5599 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5600 emitcode ("cpl", "c");
5609 symbol *tlbl = newiTempLabel (NULL);
5610 if (AOP_TYPE (right) == AOP_CRY)
5613 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5617 int sizer = AOP_SIZE (right);
5619 // if val>>1 != 0, result = 1
5620 emitcode ("setb", "c");
5623 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5625 // test the msb of the lsb
5626 emitcode ("anl", "a,#0xfe");
5627 emitcode ("jnz", "%05d$", tlbl->key + 100);
5631 emitcode ("rrc", "a");
5633 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5634 emitcode ("cpl", "c");
5635 emitcode ("", "%05d$:", (tlbl->key + 100));
5642 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5643 genIfxJump (ifx, "c");
5647 if (sameRegs (AOP (result), AOP (left)))
5649 /* if left is same as result */
5650 for (; size--; offset++)
5652 if (AOP_TYPE (right) == AOP_LIT)
5654 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5656 else if (IS_AOP_PREG (left))
5658 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5659 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5660 aopPut (AOP (result), "a", offset);
5663 emitcode ("xrl", "%s,%s",
5664 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5665 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5669 if (AOP_TYPE (left) == AOP_ACC)
5670 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5673 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5674 if (IS_AOP_PREG (left))
5676 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5677 aopPut (AOP (result), "a", offset);
5680 emitcode ("xrl", "%s,a",
5681 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5688 // left & result in different registers
5689 if (AOP_TYPE (result) == AOP_CRY)
5692 // if(size), result in bit
5693 // if(!size && ifx), conditional oper: if(left ^ right)
5694 symbol *tlbl = newiTempLabel (NULL);
5695 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5697 emitcode ("setb", "c");
5700 if ((AOP_TYPE (right) == AOP_LIT) &&
5701 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5703 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5707 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5708 emitcode ("xrl", "a,%s",
5709 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5711 emitcode ("jnz", "%05d$", tlbl->key + 100);
5717 emitcode ("", "%05d$:", tlbl->key + 100);
5721 jmpTrueOrFalse (ifx, tlbl);
5724 for (; (size--); offset++)
5727 // result = left & right
5728 if (AOP_TYPE (right) == AOP_LIT)
5730 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5732 aopPut (AOP (result),
5733 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5737 D (emitcode (";", "better literal XOR.");
5739 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5740 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5741 FALSE, FALSE, FALSE));
5745 // faster than result <- left, anl result,right
5746 // and better if result is SFR
5747 if (AOP_TYPE (left) == AOP_ACC)
5749 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5750 FALSE, FALSE, FALSE));
5754 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5755 emitcode ("xrl", "a,%s",
5756 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5759 aopPut (AOP (result), "a", offset);
5764 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5765 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5766 freeAsmop (result, NULL, ic, TRUE);
5769 /*-----------------------------------------------------------------*/
5770 /* genInline - write the inline code out */
5771 /*-----------------------------------------------------------------*/
5773 genInline (iCode * ic)
5775 char buffer[MAX_INLINEASM];
5779 D (emitcode (";", "genInline ");
5782 _G.inLine += (!options.asmpeep);
5783 strcpy (buffer, IC_INLINE (ic));
5785 /* emit each line as a code */
5810 /* emitcode("",buffer); */
5811 _G.inLine -= (!options.asmpeep);
5814 /*-----------------------------------------------------------------*/
5815 /* genRRC - rotate right with carry */
5816 /*-----------------------------------------------------------------*/
5820 operand *left, *result;
5821 int size, offset = 0;
5824 D (emitcode (";", "genRRC ");
5827 /* rotate right with carry */
5828 left = IC_LEFT (ic);
5829 result = IC_RESULT (ic);
5830 aopOp (left, ic, FALSE, FALSE);
5831 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5833 /* move it to the result */
5834 size = AOP_SIZE (result);
5838 _startLazyDPSEvaluation ();
5841 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5843 emitcode ("rrc", "a");
5844 if (AOP_SIZE (result) > 1)
5845 aopPut (AOP (result), "a", offset--);
5847 _endLazyDPSEvaluation ();
5849 /* now we need to put the carry into the
5850 highest order byte of the result */
5851 if (AOP_SIZE (result) > 1)
5853 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5856 emitcode ("mov", "acc.7,c");
5857 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5858 freeAsmop (left, NULL, ic, TRUE);
5859 freeAsmop (result, NULL, ic, TRUE);
5862 /*-----------------------------------------------------------------*/
5863 /* genRLC - generate code for rotate left with carry */
5864 /*-----------------------------------------------------------------*/
5868 operand *left, *result;
5869 int size, offset = 0;
5872 D (emitcode (";", "genRLC ");
5875 /* rotate right with carry */
5876 left = IC_LEFT (ic);
5877 result = IC_RESULT (ic);
5878 aopOp (left, ic, FALSE, FALSE);
5879 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5881 /* move it to the result */
5882 size = AOP_SIZE (result);
5886 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5888 emitcode ("add", "a,acc");
5889 if (AOP_SIZE (result) > 1)
5891 aopPut (AOP (result), "a", offset++);
5894 _startLazyDPSEvaluation ();
5897 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5899 emitcode ("rlc", "a");
5900 if (AOP_SIZE (result) > 1)
5901 aopPut (AOP (result), "a", offset++);
5903 _endLazyDPSEvaluation ();
5905 /* now we need to put the carry into the
5906 highest order byte of the result */
5907 if (AOP_SIZE (result) > 1)
5909 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5912 emitcode ("mov", "acc.0,c");
5913 aopPut (AOP (result), "a", 0);
5914 freeAsmop (left, NULL, ic, TRUE);
5915 freeAsmop (result, NULL, ic, TRUE);
5918 /*-----------------------------------------------------------------*/
5919 /* genGetHbit - generates code get highest order bit */
5920 /*-----------------------------------------------------------------*/
5922 genGetHbit (iCode * ic)
5924 operand *left, *result;
5925 left = IC_LEFT (ic);
5926 result = IC_RESULT (ic);
5927 aopOp (left, ic, FALSE, FALSE);
5928 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5930 D (emitcode (";", "genGetHbit ");
5933 /* get the highest order byte into a */
5934 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5935 if (AOP_TYPE (result) == AOP_CRY)
5937 emitcode ("rlc", "a");
5942 emitcode ("rl", "a");
5943 emitcode ("anl", "a,#0x01");
5948 freeAsmop (left, NULL, ic, TRUE);
5949 freeAsmop (result, NULL, ic, TRUE);
5952 /*-----------------------------------------------------------------*/
5953 /* AccRol - rotate left accumulator by known count */
5954 /*-----------------------------------------------------------------*/
5956 AccRol (int shCount)
5958 shCount &= 0x0007; // shCount : 0..7
5965 emitcode ("rl", "a");
5968 emitcode ("rl", "a");
5969 emitcode ("rl", "a");
5972 emitcode ("swap", "a");
5973 emitcode ("rr", "a");
5976 emitcode ("swap", "a");
5979 emitcode ("swap", "a");
5980 emitcode ("rl", "a");
5983 emitcode ("rr", "a");
5984 emitcode ("rr", "a");
5987 emitcode ("rr", "a");
5992 /*-----------------------------------------------------------------*/
5993 /* AccLsh - left shift accumulator by known count */
5994 /*-----------------------------------------------------------------*/
5996 AccLsh (int shCount)
6001 emitcode ("add", "a,acc");
6002 else if (shCount == 2)
6004 emitcode ("add", "a,acc");
6005 emitcode ("add", "a,acc");
6009 /* rotate left accumulator */
6011 /* and kill the lower order bits */
6012 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6017 /*-----------------------------------------------------------------*/
6018 /* AccRsh - right shift accumulator by known count */
6019 /*-----------------------------------------------------------------*/
6021 AccRsh (int shCount)
6028 emitcode ("rrc", "a");
6032 /* rotate right accumulator */
6033 AccRol (8 - shCount);
6034 /* and kill the higher order bits */
6035 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6040 #ifdef BETTER_LITERAL_SHIFT
6041 /*-----------------------------------------------------------------*/
6042 /* AccSRsh - signed right shift accumulator by known count */
6043 /*-----------------------------------------------------------------*/
6045 AccSRsh (int shCount)
6052 emitcode ("mov", "c,acc.7");
6053 emitcode ("rrc", "a");
6055 else if (shCount == 2)
6057 emitcode ("mov", "c,acc.7");
6058 emitcode ("rrc", "a");
6059 emitcode ("mov", "c,acc.7");
6060 emitcode ("rrc", "a");
6064 tlbl = newiTempLabel (NULL);
6065 /* rotate right accumulator */
6066 AccRol (8 - shCount);
6067 /* and kill the higher order bits */
6068 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6069 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6070 emitcode ("orl", "a,#0x%02x",
6071 (unsigned char) ~SRMask[shCount]);
6072 emitcode ("", "%05d$:", tlbl->key + 100);
6078 #ifdef BETTER_LITERAL_SHIFT
6079 /*-----------------------------------------------------------------*/
6080 /* shiftR1Left2Result - shift right one byte from left to result */
6081 /*-----------------------------------------------------------------*/
6083 shiftR1Left2Result (operand * left, int offl,
6084 operand * result, int offr,
6085 int shCount, int sign)
6087 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6088 /* shift right accumulator */
6093 aopPut (AOP (result), "a", offr);
6097 #ifdef BETTER_LITERAL_SHIFT
6098 /*-----------------------------------------------------------------*/
6099 /* shiftL1Left2Result - shift left one byte from left to result */
6100 /*-----------------------------------------------------------------*/
6102 shiftL1Left2Result (operand * left, int offl,
6103 operand * result, int offr, int shCount)
6105 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6106 /* shift left accumulator */
6108 aopPut (AOP (result), "a", offr);
6112 #ifdef BETTER_LITERAL_SHIFT
6113 /*-----------------------------------------------------------------*/
6114 /* movLeft2Result - move byte from left to result */
6115 /*-----------------------------------------------------------------*/
6117 movLeft2Result (operand * left, int offl,
6118 operand * result, int offr, int sign)
6121 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6123 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6125 if (*l == '@' && (IS_AOP_PREG (result)))
6127 emitcode ("mov", "a,%s", l);
6128 aopPut (AOP (result), "a", offr);
6134 aopPut (AOP (result), l, offr);
6138 /* MSB sign in acc.7 ! */
6139 if (getDataSize (left) == offl + 1)
6141 emitcode ("mov", "a,%s", l);
6142 aopPut (AOP (result), "a", offr);
6150 #ifdef BETTER_LITERAL_SHIFT
6151 /*-----------------------------------------------------------------*/
6152 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6153 /*-----------------------------------------------------------------*/
6157 emitcode ("rrc", "a");
6158 emitcode ("xch", "a,%s", x);
6159 emitcode ("rrc", "a");
6160 emitcode ("xch", "a,%s", x);
6164 #ifdef BETTER_LITERAL_SHIFT
6166 /*-----------------------------------------------------------------*/
6167 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6168 /*-----------------------------------------------------------------*/
6172 emitcode ("xch", "a,%s", x);
6173 emitcode ("rlc", "a");
6174 emitcode ("xch", "a,%s", x);
6175 emitcode ("rlc", "a");
6179 #ifdef BETTER_LITERAL_SHIFT
6180 /*-----------------------------------------------------------------*/
6181 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6182 /*-----------------------------------------------------------------*/
6186 emitcode ("xch", "a,%s", x);
6187 emitcode ("add", "a,acc");
6188 emitcode ("xch", "a,%s", x);
6189 emitcode ("rlc", "a");
6193 #ifdef BETTER_LITERAL_SHIFT
6194 /*-----------------------------------------------------------------*/
6195 /* AccAXLsh - left shift a:x by known count (0..7) */
6196 /*-----------------------------------------------------------------*/
6198 AccAXLsh (char *x, int shCount)
6213 case 5: // AAAAABBB:CCCCCDDD
6215 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6217 emitcode ("anl", "a,#0x%02x",
6218 SLMask[shCount]); // BBB00000:CCCCCDDD
6220 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6222 AccRol (shCount); // DDDCCCCC:BBB00000
6224 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6226 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6228 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6230 emitcode ("anl", "a,#0x%02x",
6231 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6233 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6235 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6238 case 6: // AAAAAABB:CCCCCCDD
6239 emitcode ("anl", "a,#0x%02x",
6240 SRMask[shCount]); // 000000BB:CCCCCCDD
6241 emitcode ("mov", "c,acc.0"); // c = B
6242 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6244 AccAXRrl1 (x); // BCCCCCCD:D000000B
6245 AccAXRrl1 (x); // BBCCCCCC:DD000000
6247 emitcode("rrc","a");
6248 emitcode("xch","a,%s", x);
6249 emitcode("rrc","a");
6250 emitcode("mov","c,acc.0"); //<< get correct bit
6251 emitcode("xch","a,%s", x);
6253 emitcode("rrc","a");
6254 emitcode("xch","a,%s", x);
6255 emitcode("rrc","a");
6256 emitcode("xch","a,%s", x);
6259 case 7: // a:x <<= 7
6261 emitcode ("anl", "a,#0x%02x",
6262 SRMask[shCount]); // 0000000B:CCCCCCCD
6264 emitcode ("mov", "c,acc.0"); // c = B
6266 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6268 AccAXRrl1 (x); // BCCCCCCC:D0000000
6277 #ifdef BETTER_LITERAL_SHIFT
6279 /*-----------------------------------------------------------------*/
6280 /* AccAXRsh - right shift a:x known count (0..7) */
6281 /*-----------------------------------------------------------------*/
6283 AccAXRsh (char *x, int shCount)
6291 AccAXRrl1 (x); // 0->a:x
6296 AccAXRrl1 (x); // 0->a:x
6299 AccAXRrl1 (x); // 0->a:x
6304 case 5: // AAAAABBB:CCCCCDDD = a:x
6306 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6308 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6310 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6312 emitcode ("anl", "a,#0x%02x",
6313 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6315 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6317 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6319 emitcode ("anl", "a,#0x%02x",
6320 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6322 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6324 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6326 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6329 case 6: // AABBBBBB:CCDDDDDD
6331 emitcode ("mov", "c,acc.7");
6332 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6334 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6336 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6338 emitcode ("anl", "a,#0x%02x",
6339 SRMask[shCount]); // 000000AA:BBBBBBCC
6342 case 7: // ABBBBBBB:CDDDDDDD
6344 emitcode ("mov", "c,acc.7"); // c = A
6346 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6348 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6350 emitcode ("anl", "a,#0x%02x",
6351 SRMask[shCount]); // 0000000A:BBBBBBBC
6360 #ifdef BETTER_LITERAL_SHIFT
6362 /*-----------------------------------------------------------------*/
6363 /* AccAXRshS - right shift signed a:x known count (0..7) */
6364 /*-----------------------------------------------------------------*/
6366 AccAXRshS (char *x, int shCount)
6374 emitcode ("mov", "c,acc.7");
6375 AccAXRrl1 (x); // s->a:x
6379 emitcode ("mov", "c,acc.7");
6380 AccAXRrl1 (x); // s->a:x
6382 emitcode ("mov", "c,acc.7");
6383 AccAXRrl1 (x); // s->a:x
6388 case 5: // AAAAABBB:CCCCCDDD = a:x
6390 tlbl = newiTempLabel (NULL);
6391 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6393 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6395 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6397 emitcode ("anl", "a,#0x%02x",
6398 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6400 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6402 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6404 emitcode ("anl", "a,#0x%02x",
6405 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6407 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6409 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6411 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6413 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6414 emitcode ("orl", "a,#0x%02x",
6415 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6417 emitcode ("", "%05d$:", tlbl->key + 100);
6418 break; // SSSSAAAA:BBBCCCCC
6420 case 6: // AABBBBBB:CCDDDDDD
6422 tlbl = newiTempLabel (NULL);
6423 emitcode ("mov", "c,acc.7");
6424 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6426 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6428 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6430 emitcode ("anl", "a,#0x%02x",
6431 SRMask[shCount]); // 000000AA:BBBBBBCC
6433 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6434 emitcode ("orl", "a,#0x%02x",
6435 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6437 emitcode ("", "%05d$:", tlbl->key + 100);
6439 case 7: // ABBBBBBB:CDDDDDDD
6441 tlbl = newiTempLabel (NULL);
6442 emitcode ("mov", "c,acc.7"); // c = A
6444 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6446 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6448 emitcode ("anl", "a,#0x%02x",
6449 SRMask[shCount]); // 0000000A:BBBBBBBC
6451 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6452 emitcode ("orl", "a,#0x%02x",
6453 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6455 emitcode ("", "%05d$:", tlbl->key + 100);
6463 #ifdef BETTER_LITERAL_SHIFT
6465 _loadLeftIntoAx(char **lsb,
6471 // Get the initial value from left into a pair of registers.
6472 // MSB must be in A, LSB can be any register.
6474 // If the result is held in registers, it is an optimization
6475 // if the LSB can be held in the register which will hold the,
6476 // result LSB since this saves us from having to copy it into
6477 // the result following AccAXLsh.
6479 // If the result is addressed indirectly, this is not a gain.
6480 if (AOP_NEEDSACC(result))
6484 _startLazyDPSEvaluation();
6485 if (AOP_TYPE(left) == AOP_DPTR2)
6488 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6489 // get LSB in DP2_RESULT_REG.
6490 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6491 assert(!strcmp(leftByte, DP2_RESULT_REG));
6495 // get LSB into DP2_RESULT_REG
6496 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6497 if (strcmp(leftByte, DP2_RESULT_REG))
6499 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6502 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6503 assert(strcmp(leftByte, DP2_RESULT_REG));
6506 _endLazyDPSEvaluation();
6507 *lsb = DP2_RESULT_REG;
6511 if (sameRegs (AOP (result), AOP (left)) &&
6512 ((offl + MSB16) == offr))
6514 /* don't crash result[offr] */
6515 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6516 emitcode ("xch", "a,%s",
6517 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6521 movLeft2Result (left, offl, result, offr, 0);
6522 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6524 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6525 assert(strcmp(*lsb,"a"));
6530 _storeAxResults(char *lsb,
6534 _startLazyDPSEvaluation();
6535 if (AOP_NEEDSACC(result))
6537 /* We have to explicitly update the result LSB.
6539 emitcode("xch","a,%s", lsb);
6540 aopPut(AOP(result), "a", offr);
6541 emitcode("mov","a,%s", lsb);
6543 if (getDataSize (result) > 1)
6545 aopPut (AOP (result), "a", offr + MSB16);
6547 _endLazyDPSEvaluation();
6550 /*-----------------------------------------------------------------*/
6551 /* shiftL2Left2Result - shift left two bytes from left to result */
6552 /*-----------------------------------------------------------------*/
6554 shiftL2Left2Result (operand * left, int offl,
6555 operand * result, int offr, int shCount)
6559 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6561 AccAXLsh (lsb, shCount);
6563 _storeAxResults(lsb, result, offr);
6567 #ifdef BETTER_LITERAL_SHIFT
6568 /*-----------------------------------------------------------------*/
6569 /* shiftR2Left2Result - shift right two bytes from left to result */
6570 /*-----------------------------------------------------------------*/
6572 shiftR2Left2Result (operand * left, int offl,
6573 operand * result, int offr,
6574 int shCount, int sign)
6578 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6580 /* a:x >> shCount (x = lsb(result)) */
6583 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6587 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6590 _storeAxResults(lsb, result, offr);
6596 /*-----------------------------------------------------------------*/
6597 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6598 /*-----------------------------------------------------------------*/
6600 shiftLLeftOrResult (operand * left, int offl,
6601 operand * result, int offr, int shCount)
6603 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6604 /* shift left accumulator */
6606 /* or with result */
6607 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6608 /* back to result */
6609 aopPut (AOP (result), "a", offr);
6615 /*-----------------------------------------------------------------*/
6616 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6617 /*-----------------------------------------------------------------*/
6619 shiftRLeftOrResult (operand * left, int offl,
6620 operand * result, int offr, int shCount)
6622 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6623 /* shift right accumulator */
6625 /* or with result */
6626 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6627 /* back to result */
6628 aopPut (AOP (result), "a", offr);
6632 #ifdef BETTER_LITERAL_SHIFT
6633 /*-----------------------------------------------------------------*/
6634 /* genlshOne - left shift a one byte quantity by known count */
6635 /*-----------------------------------------------------------------*/
6637 genlshOne (operand * result, operand * left, int shCount)
6639 D (emitcode (";", "genlshOne "););
6640 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6644 #ifdef BETTER_LITERAL_SHIFT
6645 /*-----------------------------------------------------------------*/
6646 /* genlshTwo - left shift two bytes by known amount != 0 */
6647 /*-----------------------------------------------------------------*/
6649 genlshTwo (operand * result, operand * left, int shCount)
6653 D (emitcode (";", "genlshTwo "););
6655 size = getDataSize (result);
6657 /* if shCount >= 8 */
6662 _startLazyDPSEvaluation();
6668 _endLazyDPSEvaluation();
6669 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6670 aopPut (AOP (result), zero, LSB);
6674 movLeft2Result (left, LSB, result, MSB16, 0);
6675 aopPut (AOP (result), zero, LSB);
6676 _endLazyDPSEvaluation();
6681 aopPut (AOP (result), zero, LSB);
6682 _endLazyDPSEvaluation();
6686 /* 1 <= shCount <= 7 */
6691 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6695 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6703 /*-----------------------------------------------------------------*/
6704 /* shiftLLong - shift left one long from left to result */
6705 /* offl = LSB or MSB16 */
6706 /*-----------------------------------------------------------------*/
6708 shiftLLong (operand * left, operand * result, int offr)
6711 int size = AOP_SIZE (result);
6713 if (size >= LSB + offr)
6715 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6717 emitcode ("add", "a,acc");
6718 if (sameRegs (AOP (left), AOP (result)) &&
6719 size >= MSB16 + offr && offr != LSB)
6720 emitcode ("xch", "a,%s",
6721 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6723 aopPut (AOP (result), "a", LSB + offr);
6726 if (size >= MSB16 + offr)
6728 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6730 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6733 emitcode ("rlc", "a");
6734 if (sameRegs (AOP (left), AOP (result)) &&
6735 size >= MSB24 + offr && offr != LSB)
6736 emitcode ("xch", "a,%s",
6737 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6739 aopPut (AOP (result), "a", MSB16 + offr);
6742 if (size >= MSB24 + offr)
6744 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6746 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6749 emitcode ("rlc", "a");
6750 if (sameRegs (AOP (left), AOP (result)) &&
6751 size >= MSB32 + offr && offr != LSB)
6752 emitcode ("xch", "a,%s",
6753 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6755 aopPut (AOP (result), "a", MSB24 + offr);
6758 if (size > MSB32 + offr)
6760 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6762 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6765 emitcode ("rlc", "a");
6766 aopPut (AOP (result), "a", MSB32 + offr);
6769 aopPut (AOP (result), zero, LSB);
6775 /*-----------------------------------------------------------------*/
6776 /* genlshFour - shift four byte by a known amount != 0 */
6777 /*-----------------------------------------------------------------*/
6779 genlshFour (operand * result, operand * left, int shCount)
6783 D (emitcode (";", "genlshFour ");
6786 size = AOP_SIZE (result);
6788 /* if shifting more that 3 bytes */
6793 /* lowest order of left goes to the highest
6794 order of the destination */
6795 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6797 movLeft2Result (left, LSB, result, MSB32, 0);
6798 aopPut (AOP (result), zero, LSB);
6799 aopPut (AOP (result), zero, MSB16);
6800 aopPut (AOP (result), zero, MSB24);
6804 /* more than two bytes */
6805 else if (shCount >= 16)
6807 /* lower order two bytes goes to higher order two bytes */
6809 /* if some more remaining */
6811 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6814 movLeft2Result (left, MSB16, result, MSB32, 0);
6815 movLeft2Result (left, LSB, result, MSB24, 0);
6817 aopPut (AOP (result), zero, MSB16);
6818 aopPut (AOP (result), zero, LSB);
6822 /* if more than 1 byte */
6823 else if (shCount >= 8)
6825 /* lower order three bytes goes to higher order three bytes */
6830 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6832 movLeft2Result (left, LSB, result, MSB16, 0);
6838 movLeft2Result (left, MSB24, result, MSB32, 0);
6839 movLeft2Result (left, MSB16, result, MSB24, 0);
6840 movLeft2Result (left, LSB, result, MSB16, 0);
6841 aopPut (AOP (result), zero, LSB);
6843 else if (shCount == 1)
6844 shiftLLong (left, result, MSB16);
6847 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6848 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6849 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6850 aopPut (AOP (result), zero, LSB);
6855 /* 1 <= shCount <= 7 */
6856 else if (shCount <= 2)
6858 shiftLLong (left, result, LSB);
6860 shiftLLong (result, result, LSB);
6862 /* 3 <= shCount <= 7, optimize */
6865 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6866 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6867 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6872 #ifdef BETTER_LITERAL_SHIFT
6873 /*-----------------------------------------------------------------*/
6874 /* genLeftShiftLiteral - left shifting by known count */
6875 /*-----------------------------------------------------------------*/
6877 genLeftShiftLiteral (operand * left,
6882 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6885 size = getSize (operandType (result));
6887 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6889 /* We only handle certain easy cases so far. */
6891 && (shCount < (size * 8))
6895 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6899 freeAsmop (right, NULL, ic, TRUE);
6901 aopOp(left, ic, FALSE, FALSE);
6902 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6905 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6907 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6908 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6910 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6913 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6915 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6916 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6918 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6924 emitcode ("; shift left ", "result %d, left %d", size,
6928 /* I suppose that the left size >= result size */
6931 _startLazyDPSEvaluation();
6934 movLeft2Result (left, size, result, size, 0);
6936 _endLazyDPSEvaluation();
6938 else if (shCount >= (size * 8))
6940 _startLazyDPSEvaluation();
6943 aopPut (AOP (result), zero, size);
6945 _endLazyDPSEvaluation();
6952 genlshOne (result, left, shCount);
6956 genlshTwo (result, left, shCount);
6960 genlshFour (result, left, shCount);
6964 fprintf(stderr, "*** ack! mystery literal shift!\n");
6968 freeAsmop (left, NULL, ic, TRUE);
6969 freeAsmop (result, NULL, ic, TRUE);
6974 /*-----------------------------------------------------------------*/
6975 /* genLeftShift - generates code for left shifting */
6976 /*-----------------------------------------------------------------*/
6978 genLeftShift (iCode * ic)
6980 operand *left, *right, *result;
6983 symbol *tlbl, *tlbl1;
6985 D (emitcode (";", "genLeftShift "););
6987 right = IC_RIGHT (ic);
6988 left = IC_LEFT (ic);
6989 result = IC_RESULT (ic);
6991 aopOp (right, ic, FALSE, FALSE);
6994 #ifdef BETTER_LITERAL_SHIFT
6995 /* if the shift count is known then do it
6996 as efficiently as possible */
6997 if (AOP_TYPE (right) == AOP_LIT)
6999 if (genLeftShiftLiteral (left, right, result, ic))
7006 /* shift count is unknown then we have to form
7007 a loop get the loop count in B : Note: we take
7008 only the lower order byte since shifting
7009 more that 32 bits make no sense anyway, ( the
7010 largest size of an object can be only 32 bits ) */
7012 if (AOP_TYPE (right) == AOP_LIT)
7014 /* Really should be handled by genLeftShiftLiteral,
7015 * but since I'm too lazy to fix that today, at least we can make
7016 * some small improvement.
7018 emitcode("mov", "b,#0x%02x",
7019 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7023 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7024 emitcode ("inc", "b");
7026 freeAsmop (right, NULL, ic, TRUE);
7027 aopOp (left, ic, FALSE, FALSE);
7028 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7030 /* now move the left to the result if they are not the
7032 if (!sameRegs (AOP (left), AOP (result)) &&
7033 AOP_SIZE (result) > 1)
7036 size = AOP_SIZE (result);
7038 _startLazyDPSEvaluation ();
7041 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7042 if (*l == '@' && (IS_AOP_PREG (result)))
7045 emitcode ("mov", "a,%s", l);
7046 aopPut (AOP (result), "a", offset);
7049 aopPut (AOP (result), l, offset);
7052 _endLazyDPSEvaluation ();
7055 tlbl = newiTempLabel (NULL);
7056 size = AOP_SIZE (result);
7058 tlbl1 = newiTempLabel (NULL);
7060 /* if it is only one byte then */
7063 symbol *tlbl1 = newiTempLabel (NULL);
7065 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7067 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7068 emitcode ("", "%05d$:", tlbl->key + 100);
7069 emitcode ("add", "a,acc");
7070 emitcode ("", "%05d$:", tlbl1->key + 100);
7071 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7072 aopPut (AOP (result), "a", 0);
7076 reAdjustPreg (AOP (result));
7078 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7079 emitcode ("", "%05d$:", tlbl->key + 100);
7080 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7082 emitcode ("add", "a,acc");
7083 aopPut (AOP (result), "a", offset++);
7084 _startLazyDPSEvaluation ();
7087 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7089 emitcode ("rlc", "a");
7090 aopPut (AOP (result), "a", offset++);
7092 _endLazyDPSEvaluation ();
7093 reAdjustPreg (AOP (result));
7095 emitcode ("", "%05d$:", tlbl1->key + 100);
7096 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7098 freeAsmop (left, NULL, ic, TRUE);
7099 freeAsmop (result, NULL, ic, TRUE);
7102 #ifdef BETTER_LITERAL_SHIFT
7103 /*-----------------------------------------------------------------*/
7104 /* genrshOne - right shift a one byte quantity by known count */
7105 /*-----------------------------------------------------------------*/
7107 genrshOne (operand * result, operand * left,
7108 int shCount, int sign)
7110 D (emitcode (";", "genrshOne"););
7111 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7115 #ifdef BETTER_LITERAL_SHIFT
7116 /*-----------------------------------------------------------------*/
7117 /* genrshTwo - right shift two bytes by known amount != 0 */
7118 /*-----------------------------------------------------------------*/
7120 genrshTwo (operand * result, operand * left,
7121 int shCount, int sign)
7123 D (emitcode (";", "genrshTwo"););
7125 /* if shCount >= 8 */
7129 _startLazyDPSEvaluation();
7132 shiftR1Left2Result (left, MSB16, result, LSB,
7137 movLeft2Result (left, MSB16, result, LSB, sign);
7139 addSign (result, MSB16, sign);
7140 _endLazyDPSEvaluation();
7143 /* 1 <= shCount <= 7 */
7146 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7153 /*-----------------------------------------------------------------*/
7154 /* shiftRLong - shift right one long from left to result */
7155 /* offl = LSB or MSB16 */
7156 /*-----------------------------------------------------------------*/
7158 shiftRLong (operand * left, int offl,
7159 operand * result, int sign)
7162 emitcode ("clr", "c");
7163 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7165 emitcode ("mov", "c,acc.7");
7166 emitcode ("rrc", "a");
7167 aopPut (AOP (result), "a", MSB32 - offl);
7169 /* add sign of "a" */
7170 addSign (result, MSB32, sign);
7172 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7173 emitcode ("rrc", "a");
7174 aopPut (AOP (result), "a", MSB24 - offl);
7176 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7177 emitcode ("rrc", "a");
7178 aopPut (AOP (result), "a", MSB16 - offl);
7182 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7183 emitcode ("rrc", "a");
7184 aopPut (AOP (result), "a", LSB);
7191 /*-----------------------------------------------------------------*/
7192 /* genrshFour - shift four byte by a known amount != 0 */
7193 /*-----------------------------------------------------------------*/
7195 genrshFour (operand * result, operand * left,
7196 int shCount, int sign)
7198 D (emitcode (";", "genrshFour");
7201 /* if shifting more that 3 bytes */
7206 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7208 movLeft2Result (left, MSB32, result, LSB, sign);
7209 addSign (result, MSB16, sign);
7211 else if (shCount >= 16)
7215 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7218 movLeft2Result (left, MSB24, result, LSB, 0);
7219 movLeft2Result (left, MSB32, result, MSB16, sign);
7221 addSign (result, MSB24, sign);
7223 else if (shCount >= 8)
7227 shiftRLong (left, MSB16, result, sign);
7228 else if (shCount == 0)
7230 movLeft2Result (left, MSB16, result, LSB, 0);
7231 movLeft2Result (left, MSB24, result, MSB16, 0);
7232 movLeft2Result (left, MSB32, result, MSB24, sign);
7233 addSign (result, MSB32, sign);
7237 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7238 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7239 /* the last shift is signed */
7240 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7241 addSign (result, MSB32, sign);
7245 { /* 1 <= shCount <= 7 */
7248 shiftRLong (left, LSB, result, sign);
7250 shiftRLong (result, LSB, result, sign);
7254 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7255 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7256 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7262 #ifdef BETTER_LITERAL_SHIFT
7263 /*-----------------------------------------------------------------*/
7264 /* genRightShiftLiteral - right shifting by known count */
7265 /*-----------------------------------------------------------------*/
7267 genRightShiftLiteral (operand * left,
7273 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7276 size = getSize (operandType (result));
7278 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7280 /* We only handle certain easy cases so far. */
7282 && (shCount < (size * 8))
7286 D(emitcode (";", "genRightShiftLiteral wimping out"););
7290 freeAsmop (right, NULL, ic, TRUE);
7292 aopOp (left, ic, FALSE, FALSE);
7293 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7296 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7300 /* test the LEFT size !!! */
7302 /* I suppose that the left size >= result size */
7305 size = getDataSize (result);
7306 _startLazyDPSEvaluation();
7309 movLeft2Result (left, size, result, size, 0);
7311 _endLazyDPSEvaluation();
7313 else if (shCount >= (size * 8))
7317 /* get sign in acc.7 */
7318 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7320 addSign (result, LSB, sign);
7327 genrshOne (result, left, shCount, sign);
7331 genrshTwo (result, left, shCount, sign);
7335 genrshFour (result, left, shCount, sign);
7342 freeAsmop (left, NULL, ic, TRUE);
7343 freeAsmop (result, NULL, ic, TRUE);
7349 /*-----------------------------------------------------------------*/
7350 /* genSignedRightShift - right shift of signed number */
7351 /*-----------------------------------------------------------------*/
7353 genSignedRightShift (iCode * ic)
7355 operand *right, *left, *result;
7358 symbol *tlbl, *tlbl1;
7360 D (emitcode (";", "genSignedRightShift "););
7362 /* we do it the hard way put the shift count in b
7363 and loop thru preserving the sign */
7365 right = IC_RIGHT (ic);
7366 left = IC_LEFT (ic);
7367 result = IC_RESULT (ic);
7369 aopOp (right, ic, FALSE, FALSE);
7371 #ifdef BETTER_LITERAL_SHIFT
7372 if (AOP_TYPE (right) == AOP_LIT)
7374 if (genRightShiftLiteral (left, right, result, ic, 1))
7380 /* shift count is unknown then we have to form
7381 a loop get the loop count in B : Note: we take
7382 only the lower order byte since shifting
7383 more that 32 bits make no sense anyway, ( the
7384 largest size of an object can be only 32 bits ) */
7386 if (AOP_TYPE (right) == AOP_LIT)
7388 /* Really should be handled by genRightShiftLiteral,
7389 * but since I'm too lazy to fix that today, at least we can make
7390 * some small improvement.
7392 emitcode("mov", "b,#0x%02x",
7393 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7397 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7398 emitcode ("inc", "b");
7400 freeAsmop (right, NULL, ic, TRUE);
7401 aopOp (left, ic, FALSE, FALSE);
7402 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7404 /* now move the left to the result if they are not the
7406 if (!sameRegs (AOP (left), AOP (result)) &&
7407 AOP_SIZE (result) > 1)
7410 size = AOP_SIZE (result);
7412 _startLazyDPSEvaluation ();
7415 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7416 if (*l == '@' && IS_AOP_PREG (result))
7419 emitcode ("mov", "a,%s", l);
7420 aopPut (AOP (result), "a", offset);
7423 aopPut (AOP (result), l, offset);
7426 _endLazyDPSEvaluation ();
7429 /* mov the highest order bit to OVR */
7430 tlbl = newiTempLabel (NULL);
7431 tlbl1 = newiTempLabel (NULL);
7433 size = AOP_SIZE (result);
7435 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7436 emitcode ("rlc", "a");
7437 emitcode ("mov", "ov,c");
7438 /* if it is only one byte then */
7441 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7443 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7444 emitcode ("", "%05d$:", tlbl->key + 100);
7445 emitcode ("mov", "c,ov");
7446 emitcode ("rrc", "a");
7447 emitcode ("", "%05d$:", tlbl1->key + 100);
7448 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7449 aopPut (AOP (result), "a", 0);
7453 reAdjustPreg (AOP (result));
7454 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7455 emitcode ("", "%05d$:", tlbl->key + 100);
7456 emitcode ("mov", "c,ov");
7457 _startLazyDPSEvaluation ();
7460 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7462 emitcode ("rrc", "a");
7463 aopPut (AOP (result), "a", offset--);
7465 _endLazyDPSEvaluation ();
7466 reAdjustPreg (AOP (result));
7467 emitcode ("", "%05d$:", tlbl1->key + 100);
7468 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7471 freeAsmop (left, NULL, ic, TRUE);
7472 freeAsmop (result, NULL, ic, TRUE);
7475 /*-----------------------------------------------------------------*/
7476 /* genRightShift - generate code for right shifting */
7477 /*-----------------------------------------------------------------*/
7479 genRightShift (iCode * ic)
7481 operand *right, *left, *result;
7485 symbol *tlbl, *tlbl1;
7487 D (emitcode (";", "genRightShift "););
7489 /* if signed then we do it the hard way preserve the
7490 sign bit moving it inwards */
7491 retype = getSpec (operandType (IC_RESULT (ic)));
7493 if (!SPEC_USIGN (retype))
7495 genSignedRightShift (ic);
7499 /* signed & unsigned types are treated the same : i.e. the
7500 signed is NOT propagated inwards : quoting from the
7501 ANSI - standard : "for E1 >> E2, is equivalent to division
7502 by 2**E2 if unsigned or if it has a non-negative value,
7503 otherwise the result is implementation defined ", MY definition
7504 is that the sign does not get propagated */
7506 right = IC_RIGHT (ic);
7507 left = IC_LEFT (ic);
7508 result = IC_RESULT (ic);
7510 aopOp (right, ic, FALSE, FALSE);
7512 #ifdef BETTER_LITERAL_SHIFT
7513 /* if the shift count is known then do it
7514 as efficiently as possible */
7515 if (AOP_TYPE (right) == AOP_LIT)
7517 if (genRightShiftLiteral (left, right, result, ic, 0))
7524 /* shift count is unknown then we have to form
7525 a loop get the loop count in B : Note: we take
7526 only the lower order byte since shifting
7527 more that 32 bits make no sense anyway, ( the
7528 largest size of an object can be only 32 bits ) */
7530 if (AOP_TYPE (right) == AOP_LIT)
7532 /* Really should be handled by genRightShiftLiteral,
7533 * but since I'm too lazy to fix that today, at least we can make
7534 * some small improvement.
7536 emitcode("mov", "b,#0x%02x",
7537 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7541 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7542 emitcode ("inc", "b");
7544 freeAsmop (right, NULL, ic, TRUE);
7545 aopOp (left, ic, FALSE, FALSE);
7546 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7548 /* now move the left to the result if they are not the
7550 if (!sameRegs (AOP (left), AOP (result)) &&
7551 AOP_SIZE (result) > 1)
7554 size = AOP_SIZE (result);
7556 _startLazyDPSEvaluation ();
7559 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7560 if (*l == '@' && IS_AOP_PREG (result))
7563 emitcode ("mov", "a,%s", l);
7564 aopPut (AOP (result), "a", offset);
7567 aopPut (AOP (result), l, offset);
7570 _endLazyDPSEvaluation ();
7573 tlbl = newiTempLabel (NULL);
7574 tlbl1 = newiTempLabel (NULL);
7575 size = AOP_SIZE (result);
7578 /* if it is only one byte then */
7581 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7583 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7584 emitcode ("", "%05d$:", tlbl->key + 100);
7586 emitcode ("rrc", "a");
7587 emitcode ("", "%05d$:", tlbl1->key + 100);
7588 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7589 aopPut (AOP (result), "a", 0);
7593 reAdjustPreg (AOP (result));
7594 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7595 emitcode ("", "%05d$:", tlbl->key + 100);
7597 _startLazyDPSEvaluation ();
7600 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7602 emitcode ("rrc", "a");
7603 aopPut (AOP (result), "a", offset--);
7605 _endLazyDPSEvaluation ();
7606 reAdjustPreg (AOP (result));
7608 emitcode ("", "%05d$:", tlbl1->key + 100);
7609 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7612 freeAsmop (left, NULL, ic, TRUE);
7613 freeAsmop (result, NULL, ic, TRUE);
7616 /*-----------------------------------------------------------------*/
7617 /* genUnpackBits - generates code for unpacking bits */
7618 /*-----------------------------------------------------------------*/
7620 genUnpackBits (operand * result, char *rname, int ptype)
7627 D (emitcode (";", "genUnpackBits ");
7630 etype = getSpec (operandType (result));
7632 /* read the first byte */
7638 emitcode ("mov", "a,@%s", rname);
7642 emitcode ("movx", "a,@%s", rname);
7646 emitcode ("movx", "a,@dptr");
7650 emitcode ("clr", "a");
7651 emitcode ("movc", "a", "@a+dptr");
7655 emitcode ("lcall", "__gptrget");
7659 /* if we have bitdisplacement then it fits */
7660 /* into this byte completely or if length is */
7661 /* less than a byte */
7662 if ((shCnt = SPEC_BSTR (etype)) ||
7663 (SPEC_BLEN (etype) <= 8))
7666 /* shift right acc */
7669 emitcode ("anl", "a,#0x%02x",
7670 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7671 aopPut (AOP (result), "a", offset);
7675 /* bit field did not fit in a byte */
7676 rlen = SPEC_BLEN (etype) - 8;
7677 aopPut (AOP (result), "a", offset++);
7686 emitcode ("inc", "%s", rname);
7687 emitcode ("mov", "a,@%s", rname);
7691 emitcode ("inc", "%s", rname);
7692 emitcode ("movx", "a,@%s", rname);
7696 emitcode ("inc", "dptr");
7697 emitcode ("movx", "a,@dptr");
7701 emitcode ("clr", "a");
7702 emitcode ("inc", "dptr");
7703 emitcode ("movc", "a", "@a+dptr");
7707 emitcode ("inc", "dptr");
7708 emitcode ("lcall", "__gptrget");
7713 /* if we are done */
7717 aopPut (AOP (result), "a", offset++);
7723 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7724 aopPut (AOP (result), "a", offset);
7731 /*-----------------------------------------------------------------*/
7732 /* genDataPointerGet - generates code when ptr offset is known */
7733 /*-----------------------------------------------------------------*/
7735 genDataPointerGet (operand * left,
7741 int size, offset = 0;
7742 aopOp (result, ic, TRUE, FALSE);
7744 /* get the string representation of the name */
7745 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7746 size = AOP_SIZE (result);
7747 _startLazyDPSEvaluation ();
7751 sprintf (buffer, "(%s + %d)", l + 1, offset);
7753 sprintf (buffer, "%s", l + 1);
7754 aopPut (AOP (result), buffer, offset++);
7756 _endLazyDPSEvaluation ();
7758 freeAsmop (left, NULL, ic, TRUE);
7759 freeAsmop (result, NULL, ic, TRUE);
7762 /*-----------------------------------------------------------------*/
7763 /* genNearPointerGet - emitcode for near pointer fetch */
7764 /*-----------------------------------------------------------------*/
7766 genNearPointerGet (operand * left,
7773 sym_link *rtype, *retype, *letype;
7774 sym_link *ltype = operandType (left);
7777 rtype = operandType (result);
7778 retype = getSpec (rtype);
7779 letype = getSpec (ltype);
7781 aopOp (left, ic, FALSE, FALSE);
7783 /* if left is rematerialisable and
7784 result is not bit variable type and
7785 the left is pointer to data space i.e
7786 lower 128 bytes of space */
7787 if (AOP_TYPE (left) == AOP_IMMD &&
7788 !IS_BITVAR (retype) &&
7789 !IS_BITVAR (letype) &&
7790 DCL_TYPE (ltype) == POINTER)
7792 genDataPointerGet (left, result, ic);
7796 /* if the value is already in a pointer register
7797 then don't need anything more */
7798 if (!AOP_INPREG (AOP (left)))
7800 /* otherwise get a free pointer register */
7802 preg = getFreePtr (ic, &aop, FALSE);
7803 emitcode ("mov", "%s,%s",
7805 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7809 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7811 freeAsmop (left, NULL, ic, TRUE);
7812 aopOp (result, ic, FALSE, FALSE);
7814 /* if bitfield then unpack the bits */
7815 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7816 genUnpackBits (result, rname, POINTER);
7819 /* we have can just get the values */
7820 int size = AOP_SIZE (result);
7825 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7828 emitcode ("mov", "a,@%s", rname);
7829 aopPut (AOP (result), "a", offset);
7833 sprintf (buffer, "@%s", rname);
7834 aopPut (AOP (result), buffer, offset);
7838 emitcode ("inc", "%s", rname);
7842 /* now some housekeeping stuff */
7845 /* we had to allocate for this iCode */
7846 freeAsmop (NULL, aop, ic, TRUE);
7850 /* we did not allocate which means left
7851 already in a pointer register, then
7852 if size > 0 && this could be used again
7853 we have to point it back to where it
7855 if (AOP_SIZE (result) > 1 &&
7856 !OP_SYMBOL (left)->remat &&
7857 (OP_SYMBOL (left)->liveTo > ic->seq ||
7860 int size = AOP_SIZE (result) - 1;
7862 emitcode ("dec", "%s", rname);
7867 freeAsmop (result, NULL, ic, TRUE);
7871 /*-----------------------------------------------------------------*/
7872 /* genPagedPointerGet - emitcode for paged pointer fetch */
7873 /*-----------------------------------------------------------------*/
7875 genPagedPointerGet (operand * left,
7882 sym_link *rtype, *retype, *letype;
7884 rtype = operandType (result);
7885 retype = getSpec (rtype);
7886 letype = getSpec (operandType (left));
7887 aopOp (left, ic, FALSE, FALSE);
7889 /* if the value is already in a pointer register
7890 then don't need anything more */
7891 if (!AOP_INPREG (AOP (left)))
7893 /* otherwise get a free pointer register */
7895 preg = getFreePtr (ic, &aop, FALSE);
7896 emitcode ("mov", "%s,%s",
7898 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7902 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7904 freeAsmop (left, NULL, ic, TRUE);
7905 aopOp (result, ic, FALSE, FALSE);
7907 /* if bitfield then unpack the bits */
7908 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7909 genUnpackBits (result, rname, PPOINTER);
7912 /* we have can just get the values */
7913 int size = AOP_SIZE (result);
7919 emitcode ("movx", "a,@%s", rname);
7920 aopPut (AOP (result), "a", offset);
7925 emitcode ("inc", "%s", rname);
7929 /* now some housekeeping stuff */
7932 /* we had to allocate for this iCode */
7933 freeAsmop (NULL, aop, ic, TRUE);
7937 /* we did not allocate which means left
7938 already in a pointer register, then
7939 if size > 0 && this could be used again
7940 we have to point it back to where it
7942 if (AOP_SIZE (result) > 1 &&
7943 !OP_SYMBOL (left)->remat &&
7944 (OP_SYMBOL (left)->liveTo > ic->seq ||
7947 int size = AOP_SIZE (result) - 1;
7949 emitcode ("dec", "%s", rname);
7954 freeAsmop (result, NULL, ic, TRUE);
7959 /*-----------------------------------------------------------------*/
7960 /* genFarPointerGet - gget value from far space */
7961 /*-----------------------------------------------------------------*/
7963 genFarPointerGet (operand * left,
7964 operand * result, iCode * ic)
7967 sym_link *retype = getSpec (operandType (result));
7968 sym_link *letype = getSpec (operandType (left));
7969 D (emitcode (";", "genFarPointerGet");
7972 aopOp (left, ic, FALSE, FALSE);
7974 /* if the operand is already in dptr
7975 then we do nothing else we move the value to dptr */
7976 if (AOP_TYPE (left) != AOP_STR)
7978 /* if this is remateriazable */
7979 if (AOP_TYPE (left) == AOP_IMMD)
7981 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7985 /* we need to get it byte by byte */
7986 _startLazyDPSEvaluation ();
7987 if (AOP_TYPE (left) != AOP_DPTR)
7989 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7990 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7991 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7995 /* We need to generate a load to DPTR indirect through DPTR. */
7996 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7998 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7999 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8000 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8001 emitcode ("pop", "dph");
8002 emitcode ("pop", "dpl");
8004 _endLazyDPSEvaluation ();
8007 /* so dptr know contains the address */
8008 freeAsmop (left, NULL, ic, TRUE);
8009 aopOp (result, ic, FALSE, TRUE);
8011 /* if bit then unpack */
8012 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8013 genUnpackBits (result, "dptr", FPOINTER);
8016 size = AOP_SIZE (result);
8019 _startLazyDPSEvaluation ();
8026 emitcode ("movx", "a,@dptr");
8028 emitcode ("inc", "dptr");
8030 aopPut (AOP (result), "a", offset++);
8032 _endLazyDPSEvaluation ();
8035 freeAsmop (result, NULL, ic, TRUE);
8038 /*-----------------------------------------------------------------*/
8039 /* emitcodePointerGet - gget value from code space */
8040 /*-----------------------------------------------------------------*/
8042 emitcodePointerGet (operand * left,
8043 operand * result, iCode * ic)
8046 sym_link *retype = getSpec (operandType (result));
8048 aopOp (left, ic, FALSE, FALSE);
8050 /* if the operand is already in dptr
8051 then we do nothing else we move the value to dptr */
8052 if (AOP_TYPE (left) != AOP_STR)
8054 /* if this is remateriazable */
8055 if (AOP_TYPE (left) == AOP_IMMD)
8057 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8060 { /* we need to get it byte by byte */
8061 _startLazyDPSEvaluation ();
8062 if (AOP_TYPE (left) != AOP_DPTR)
8064 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8065 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8066 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8070 /* We need to generate a load to DPTR indirect through DPTR. */
8071 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8073 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8074 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8075 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8076 emitcode ("pop", "dph");
8077 emitcode ("pop", "dpl");
8079 _endLazyDPSEvaluation ();
8082 /* so dptr know contains the address */
8083 freeAsmop (left, NULL, ic, TRUE);
8084 aopOp (result, ic, FALSE, TRUE);
8086 /* if bit then unpack */
8087 if (IS_BITVAR (retype))
8088 genUnpackBits (result, "dptr", CPOINTER);
8091 size = AOP_SIZE (result);
8094 _startLazyDPSEvaluation ();
8100 emitcode ("clr", "a");
8101 emitcode ("movc", "a,@a+dptr");
8103 emitcode ("inc", "dptr");
8104 aopPut (AOP (result), "a", offset++);
8106 _endLazyDPSEvaluation ();
8109 freeAsmop (result, NULL, ic, TRUE);
8112 /*-----------------------------------------------------------------*/
8113 /* genGenPointerGet - gget value from generic pointer space */
8114 /*-----------------------------------------------------------------*/
8116 genGenPointerGet (operand * left,
8117 operand * result, iCode * ic)
8120 sym_link *retype = getSpec (operandType (result));
8121 sym_link *letype = getSpec (operandType (left));
8123 D (emitcode (";", "genGenPointerGet "); );
8125 aopOp (left, ic, FALSE, TRUE);
8127 /* if the operand is already in dptr
8128 then we do nothing else we move the value to dptr */
8129 if (AOP_TYPE (left) != AOP_STR)
8131 /* if this is remateriazable */
8132 if (AOP_TYPE (left) == AOP_IMMD)
8134 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8135 emitcode ("mov", "b,#%d", pointerCode (retype));
8138 { /* we need to get it byte by byte */
8139 _startLazyDPSEvaluation ();
8140 if (AOP(left)->type==AOP_DPTR2) {
8142 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8145 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
8146 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8149 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
8150 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8153 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
8154 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8156 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8157 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8158 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8159 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8161 _endLazyDPSEvaluation ();
8164 /* so dptr know contains the address */
8165 freeAsmop (left, NULL, ic, TRUE);
8166 aopOp (result, ic, FALSE, TRUE);
8168 /* if bit then unpack */
8169 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8170 genUnpackBits (result, "dptr", GPOINTER);
8173 size = AOP_SIZE (result);
8178 emitcode ("lcall", "__gptrget");
8179 aopPut (AOP (result), "a", offset++);
8181 emitcode ("inc", "dptr");
8185 freeAsmop (result, NULL, ic, TRUE);
8188 /*-----------------------------------------------------------------*/
8189 /* genPointerGet - generate code for pointer get */
8190 /*-----------------------------------------------------------------*/
8192 genPointerGet (iCode * ic)
8194 operand *left, *result;
8195 sym_link *type, *etype;
8198 D (emitcode (";", "genPointerGet ");
8201 left = IC_LEFT (ic);
8202 result = IC_RESULT (ic);
8204 /* depending on the type of pointer we need to
8205 move it to the correct pointer register */
8206 type = operandType (left);
8207 etype = getSpec (type);
8208 /* if left is of type of pointer then it is simple */
8209 if (IS_PTR (type) && !IS_FUNC (type->next))
8210 p_type = DCL_TYPE (type);
8213 /* we have to go by the storage class */
8214 p_type = PTR_TYPE (SPEC_OCLS (etype));
8217 /* now that we have the pointer type we assign
8218 the pointer values */
8224 genNearPointerGet (left, result, ic);
8228 genPagedPointerGet (left, result, ic);
8232 genFarPointerGet (left, result, ic);
8236 emitcodePointerGet (left, result, ic);
8240 genGenPointerGet (left, result, ic);
8246 /*-----------------------------------------------------------------*/
8247 /* genPackBits - generates code for packed bit storage */
8248 /*-----------------------------------------------------------------*/
8250 genPackBits (sym_link * etype,
8252 char *rname, int p_type)
8260 blen = SPEC_BLEN (etype);
8261 bstr = SPEC_BSTR (etype);
8263 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8266 /* if the bit lenth is less than or */
8267 /* it exactly fits a byte then */
8268 if (SPEC_BLEN (etype) <= 8)
8270 shCount = SPEC_BSTR (etype);
8272 /* shift left acc */
8275 if (SPEC_BLEN (etype) < 8)
8276 { /* if smaller than a byte */
8282 emitcode ("mov", "b,a");
8283 emitcode ("mov", "a,@%s", rname);
8287 emitcode ("mov", "b,a");
8288 emitcode ("movx", "a,@dptr");
8292 emitcode ("push", "b");
8293 emitcode ("push", "acc");
8294 emitcode ("lcall", "__gptrget");
8295 emitcode ("pop", "b");
8299 emitcode ("anl", "a,#0x%02x", (unsigned char)
8300 ((unsigned char) (0xFF << (blen + bstr)) |
8301 (unsigned char) (0xFF >> (8 - bstr))));
8302 emitcode ("orl", "a,b");
8303 if (p_type == GPOINTER)
8304 emitcode ("pop", "b");
8311 emitcode ("mov", "@%s,a", rname);
8315 emitcode ("movx", "@dptr,a");
8319 emitcode ("lcall", "__gptrput");
8324 if (SPEC_BLEN (etype) <= 8)
8327 emitcode ("inc", "%s", rname);
8328 rLen = SPEC_BLEN (etype);
8330 /* now generate for lengths greater than one byte */
8334 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8346 emitcode ("mov", "@%s,a", rname);
8349 emitcode ("mov", "@%s,%s", rname, l);
8354 emitcode ("movx", "@dptr,a");
8359 emitcode ("lcall", "__gptrput");
8362 emitcode ("inc", "%s", rname);
8367 /* last last was not complete */
8370 /* save the byte & read byte */
8374 emitcode ("mov", "b,a");
8375 emitcode ("mov", "a,@%s", rname);
8379 emitcode ("mov", "b,a");
8380 emitcode ("movx", "a,@dptr");
8384 emitcode ("push", "b");
8385 emitcode ("push", "acc");
8386 emitcode ("lcall", "__gptrget");
8387 emitcode ("pop", "b");
8391 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8392 emitcode ("orl", "a,b");
8395 if (p_type == GPOINTER)
8396 emitcode ("pop", "b");
8402 emitcode ("mov", "@%s,a", rname);
8406 emitcode ("movx", "@dptr,a");
8410 emitcode ("lcall", "__gptrput");
8414 /*-----------------------------------------------------------------*/
8415 /* genDataPointerSet - remat pointer to data space */
8416 /*-----------------------------------------------------------------*/
8418 genDataPointerSet (operand * right,
8422 int size, offset = 0;
8423 char *l, buffer[256];
8425 aopOp (right, ic, FALSE, FALSE);
8427 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8428 size = AOP_SIZE (right);
8432 sprintf (buffer, "(%s + %d)", l + 1, offset);
8434 sprintf (buffer, "%s", l + 1);
8435 emitcode ("mov", "%s,%s", buffer,
8436 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8439 freeAsmop (right, NULL, ic, TRUE);
8440 freeAsmop (result, NULL, ic, TRUE);
8443 /*-----------------------------------------------------------------*/
8444 /* genNearPointerSet - emitcode for near pointer put */
8445 /*-----------------------------------------------------------------*/
8447 genNearPointerSet (operand * right,
8454 sym_link *retype, *letype;
8455 sym_link *ptype = operandType (result);
8457 retype = getSpec (operandType (right));
8458 letype = getSpec (ptype);
8460 aopOp (result, ic, FALSE, FALSE);
8462 /* if the result is rematerializable &
8463 in data space & not a bit variable */
8464 if (AOP_TYPE (result) == AOP_IMMD &&
8465 DCL_TYPE (ptype) == POINTER &&
8466 !IS_BITVAR (retype) &&
8467 !IS_BITVAR (letype))
8469 genDataPointerSet (right, result, ic);
8473 /* if the value is already in a pointer register
8474 then don't need anything more */
8475 if (!AOP_INPREG (AOP (result)))
8477 /* otherwise get a free pointer register */
8479 preg = getFreePtr (ic, &aop, FALSE);
8480 emitcode ("mov", "%s,%s",
8482 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8486 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8488 freeAsmop (result, NULL, ic, TRUE);
8489 aopOp (right, ic, FALSE, FALSE);
8491 /* if bitfield then unpack the bits */
8492 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8493 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8496 /* we have can just get the values */
8497 int size = AOP_SIZE (right);
8502 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8506 emitcode ("mov", "@%s,a", rname);
8509 emitcode ("mov", "@%s,%s", rname, l);
8511 emitcode ("inc", "%s", rname);
8516 /* now some housekeeping stuff */
8519 /* we had to allocate for this iCode */
8520 freeAsmop (NULL, aop, ic, TRUE);
8524 /* we did not allocate which means left
8525 already in a pointer register, then
8526 if size > 0 && this could be used again
8527 we have to point it back to where it
8529 if (AOP_SIZE (right) > 1 &&
8530 !OP_SYMBOL (result)->remat &&
8531 (OP_SYMBOL (result)->liveTo > ic->seq ||
8534 int size = AOP_SIZE (right) - 1;
8536 emitcode ("dec", "%s", rname);
8541 freeAsmop (right, NULL, ic, TRUE);
8546 /*-----------------------------------------------------------------*/
8547 /* genPagedPointerSet - emitcode for Paged pointer put */
8548 /*-----------------------------------------------------------------*/
8550 genPagedPointerSet (operand * right,
8557 sym_link *retype, *letype;
8559 retype = getSpec (operandType (right));
8560 letype = getSpec (operandType (result));
8562 aopOp (result, ic, FALSE, FALSE);
8564 /* if the value is already in a pointer register
8565 then don't need anything more */
8566 if (!AOP_INPREG (AOP (result)))
8568 /* otherwise get a free pointer register */
8570 preg = getFreePtr (ic, &aop, FALSE);
8571 emitcode ("mov", "%s,%s",
8573 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8577 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8579 freeAsmop (result, NULL, ic, TRUE);
8580 aopOp (right, ic, FALSE, FALSE);
8582 /* if bitfield then unpack the bits */
8583 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8584 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8587 /* we have can just get the values */
8588 int size = AOP_SIZE (right);
8593 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8596 emitcode ("movx", "@%s,a", rname);
8599 emitcode ("inc", "%s", rname);
8605 /* now some housekeeping stuff */
8608 /* we had to allocate for this iCode */
8609 freeAsmop (NULL, aop, ic, TRUE);
8613 /* we did not allocate which means left
8614 already in a pointer register, then
8615 if size > 0 && this could be used again
8616 we have to point it back to where it
8618 if (AOP_SIZE (right) > 1 &&
8619 !OP_SYMBOL (result)->remat &&
8620 (OP_SYMBOL (result)->liveTo > ic->seq ||
8623 int size = AOP_SIZE (right) - 1;
8625 emitcode ("dec", "%s", rname);
8630 freeAsmop (right, NULL, ic, TRUE);
8635 /*-----------------------------------------------------------------*/
8636 /* genFarPointerSet - set value from far space */
8637 /*-----------------------------------------------------------------*/
8639 genFarPointerSet (operand * right,
8640 operand * result, iCode * ic)
8643 sym_link *retype = getSpec (operandType (right));
8644 sym_link *letype = getSpec (operandType (result));
8646 aopOp (result, ic, FALSE, FALSE);
8648 /* if the operand is already in dptr
8649 then we do nothing else we move the value to dptr */
8650 if (AOP_TYPE (result) != AOP_STR)
8652 /* if this is remateriazable */
8653 if (AOP_TYPE (result) == AOP_IMMD)
8654 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8657 /* we need to get it byte by byte */
8658 _startLazyDPSEvaluation ();
8659 if (AOP_TYPE (result) != AOP_DPTR)
8661 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8662 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8663 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8667 /* We need to generate a load to DPTR indirect through DPTR. */
8668 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8670 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8671 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8672 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8673 emitcode ("pop", "dph");
8674 emitcode ("pop", "dpl");
8676 _endLazyDPSEvaluation ();
8679 /* so dptr know contains the address */
8680 freeAsmop (result, NULL, ic, TRUE);
8681 aopOp (right, ic, FALSE, TRUE);
8683 /* if bit then unpack */
8684 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8685 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8688 size = AOP_SIZE (right);
8691 _startLazyDPSEvaluation ();
8694 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8700 emitcode ("movx", "@dptr,a");
8702 emitcode ("inc", "dptr");
8704 _endLazyDPSEvaluation ();
8707 freeAsmop (right, NULL, ic, TRUE);
8710 /*-----------------------------------------------------------------*/
8711 /* genGenPointerSet - set value from generic pointer space */
8712 /*-----------------------------------------------------------------*/
8714 genGenPointerSet (operand * right,
8715 operand * result, iCode * ic)
8718 sym_link *retype = getSpec (operandType (right));
8719 sym_link *letype = getSpec (operandType (result));
8721 aopOp (result, ic, FALSE, TRUE);
8723 /* if the operand is already in dptr
8724 then we do nothing else we move the value to dptr */
8725 if (AOP_TYPE (result) != AOP_STR)
8727 _startLazyDPSEvaluation ();
8728 /* if this is remateriazable */
8729 if (AOP_TYPE (result) == AOP_IMMD)
8731 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8732 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8735 { /* we need to get it byte by byte */
8736 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8737 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8738 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8739 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8741 _endLazyDPSEvaluation ();
8743 /* so dptr know contains the address */
8744 freeAsmop (result, NULL, ic, TRUE);
8745 aopOp (right, ic, FALSE, TRUE);
8747 /* if bit then unpack */
8748 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8749 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8752 size = AOP_SIZE (right);
8755 _startLazyDPSEvaluation ();
8758 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8764 emitcode ("lcall", "__gptrput");
8766 emitcode ("inc", "dptr");
8768 _endLazyDPSEvaluation ();
8771 freeAsmop (right, NULL, ic, TRUE);
8774 /*-----------------------------------------------------------------*/
8775 /* genPointerSet - stores the value into a pointer location */
8776 /*-----------------------------------------------------------------*/
8778 genPointerSet (iCode * ic)
8780 operand *right, *result;
8781 sym_link *type, *etype;
8784 D (emitcode (";", "genPointerSet ");
8787 right = IC_RIGHT (ic);
8788 result = IC_RESULT (ic);
8790 /* depending on the type of pointer we need to
8791 move it to the correct pointer register */
8792 type = operandType (result);
8793 etype = getSpec (type);
8794 /* if left is of type of pointer then it is simple */
8795 if (IS_PTR (type) && !IS_FUNC (type->next))
8797 p_type = DCL_TYPE (type);
8801 /* we have to go by the storage class */
8802 p_type = PTR_TYPE (SPEC_OCLS (etype));
8805 /* now that we have the pointer type we assign
8806 the pointer values */
8812 genNearPointerSet (right, result, ic);
8816 genPagedPointerSet (right, result, ic);
8820 genFarPointerSet (right, result, ic);
8824 genGenPointerSet (right, result, ic);
8830 /*-----------------------------------------------------------------*/
8831 /* genIfx - generate code for Ifx statement */
8832 /*-----------------------------------------------------------------*/
8834 genIfx (iCode * ic, iCode * popIc)
8836 operand *cond = IC_COND (ic);
8839 D (emitcode (";", "genIfx "););
8841 aopOp (cond, ic, FALSE, FALSE);
8843 /* get the value into acc */
8844 if (AOP_TYPE (cond) != AOP_CRY)
8848 /* the result is now in the accumulator */
8849 freeAsmop (cond, NULL, ic, TRUE);
8851 /* if there was something to be popped then do it */
8855 /* if the condition is a bit variable */
8856 if (isbit && IS_ITEMP (cond) &&
8858 genIfxJump (ic, SPIL_LOC (cond)->rname);
8859 else if (isbit && !IS_ITEMP (cond))
8860 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8862 genIfxJump (ic, "a");
8867 /*-----------------------------------------------------------------*/
8868 /* genAddrOf - generates code for address of */
8869 /*-----------------------------------------------------------------*/
8871 genAddrOf (iCode * ic)
8873 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8876 D (emitcode (";", "genAddrOf ");
8879 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8881 /* if the operand is on the stack then we
8882 need to get the stack offset of this
8886 /* if it has an offset then we need to compute
8890 emitcode ("mov", "a,_bp");
8891 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8892 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8896 /* we can just move _bp */
8897 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8899 /* fill the result with zero */
8900 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8903 if (options.stack10bit && size < (FPTRSIZE - 1))
8906 "*** warning: pointer to stack var truncated.\n");
8913 if (options.stack10bit && offset == 2)
8915 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8919 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8926 /* object not on stack then we need the name */
8927 size = AOP_SIZE (IC_RESULT (ic));
8932 char s[SDCC_NAME_MAX];
8934 sprintf (s, "#(%s >> %d)",
8938 sprintf (s, "#%s", sym->rname);
8939 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8943 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8947 /*-----------------------------------------------------------------*/
8948 /* genFarFarAssign - assignment when both are in far space */
8949 /*-----------------------------------------------------------------*/
8951 genFarFarAssign (operand * result, operand * right, iCode * ic)
8953 int size = AOP_SIZE (right);
8955 symbol *rSym = NULL;
8959 /* quick & easy case. */
8960 D(emitcode(";","genFarFarAssign (1 byte case)"););
8961 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
8962 freeAsmop (right, NULL, ic, FALSE);
8963 /* now assign DPTR to result */
8965 aopOp(result, ic, FALSE, FALSE);
8967 aopPut(AOP(result), "a", 0);
8968 freeAsmop(result, NULL, ic, FALSE);
8972 /* See if we've got an underlying symbol to abuse. */
8973 if (IS_SYMOP(result) && OP_SYMBOL(result))
8975 if (IS_TRUE_SYMOP(result))
8977 rSym = OP_SYMBOL(result);
8979 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
8981 rSym = OP_SYMBOL(result)->usl.spillLoc;
8985 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
8987 /* We can use the '390 auto-toggle feature to good effect here. */
8989 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
8990 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
8991 emitcode ("mov", "dptr,#%s", rSym->rname);
8992 /* DP2 = result, DP1 = right, DP1 is current. */
8995 emitcode("movx", "a,@dptr");
8996 emitcode("movx", "@dptr,a");
8999 emitcode("inc", "dptr");
9000 emitcode("inc", "dptr");
9003 emitcode("mov", "dps, #0");
9004 freeAsmop (right, NULL, ic, FALSE);
9008 D (emitcode (";", "genFarFarAssign"););
9009 aopOp (result, ic, TRUE, TRUE);
9011 _startLazyDPSEvaluation ();
9015 aopPut (AOP (result),
9016 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9019 _endLazyDPSEvaluation ();
9020 freeAsmop (result, NULL, ic, FALSE);
9021 freeAsmop (right, NULL, ic, FALSE);
9025 /*-----------------------------------------------------------------*/
9026 /* genAssign - generate code for assignment */
9027 /*-----------------------------------------------------------------*/
9029 genAssign (iCode * ic)
9031 operand *result, *right;
9033 unsigned long lit = 0L;
9035 D (emitcode (";", "genAssign ");
9038 result = IC_RESULT (ic);
9039 right = IC_RIGHT (ic);
9041 /* if they are the same */
9042 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9045 aopOp (right, ic, FALSE, FALSE);
9047 emitcode (";", "genAssign: resultIsFar = %s",
9048 isOperandInFarSpace (result) ?
9051 /* special case both in far space */
9052 if ((AOP_TYPE (right) == AOP_DPTR ||
9053 AOP_TYPE (right) == AOP_DPTR2) &&
9054 /* IS_TRUE_SYMOP(result) && */
9055 isOperandInFarSpace (result))
9057 genFarFarAssign (result, right, ic);
9061 aopOp (result, ic, TRUE, FALSE);
9063 /* if they are the same registers */
9064 if (sameRegs (AOP (right), AOP (result)))
9067 /* if the result is a bit */
9068 if (AOP_TYPE (result) == AOP_CRY)
9071 /* if the right size is a literal then
9072 we know what the value is */
9073 if (AOP_TYPE (right) == AOP_LIT)
9075 if (((int) operandLitValue (right)))
9076 aopPut (AOP (result), one, 0);
9078 aopPut (AOP (result), zero, 0);
9082 /* the right is also a bit variable */
9083 if (AOP_TYPE (right) == AOP_CRY)
9085 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9086 aopPut (AOP (result), "c", 0);
9092 aopPut (AOP (result), "a", 0);
9096 /* bit variables done */
9098 size = AOP_SIZE (result);
9100 if (AOP_TYPE (right) == AOP_LIT)
9101 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9104 (AOP_TYPE (result) != AOP_REG) &&
9105 (AOP_TYPE (right) == AOP_LIT) &&
9106 !IS_FLOAT (operandType (right)))
9108 _startLazyDPSEvaluation ();
9109 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9111 aopPut (AOP (result),
9112 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9117 /* And now fill the rest with zeros. */
9120 emitcode ("clr", "a");
9124 aopPut (AOP (result), "a", offset++);
9126 _endLazyDPSEvaluation ();
9130 _startLazyDPSEvaluation ();
9133 aopPut (AOP (result),
9134 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9138 _endLazyDPSEvaluation ();
9142 freeAsmop (right, NULL, ic, FALSE);
9143 freeAsmop (result, NULL, ic, TRUE);
9146 /*-----------------------------------------------------------------*/
9147 /* genJumpTab - generates code for jump table */
9148 /*-----------------------------------------------------------------*/
9150 genJumpTab (iCode * ic)
9155 D (emitcode (";", "genJumpTab ");
9158 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9159 /* get the condition into accumulator */
9160 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9162 /* multiply by four! */
9163 emitcode ("add", "a,acc");
9164 emitcode ("add", "a,acc");
9165 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9167 jtab = newiTempLabel (NULL);
9168 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9169 emitcode ("jmp", "@a+dptr");
9170 emitcode ("", "%05d$:", jtab->key + 100);
9171 /* now generate the jump labels */
9172 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9173 jtab = setNextItem (IC_JTLABELS (ic)))
9174 emitcode ("ljmp", "%05d$", jtab->key + 100);
9178 /*-----------------------------------------------------------------*/
9179 /* genCast - gen code for casting */
9180 /*-----------------------------------------------------------------*/
9182 genCast (iCode * ic)
9184 operand *result = IC_RESULT (ic);
9185 sym_link *ctype = operandType (IC_LEFT (ic));
9186 sym_link *rtype = operandType (IC_RIGHT (ic));
9187 operand *right = IC_RIGHT (ic);
9190 D (emitcode (";", "genCast ");
9193 /* if they are equivalent then do nothing */
9194 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9197 aopOp (right, ic, FALSE, FALSE);
9198 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9200 /* if the result is a bit */
9201 if (AOP_TYPE (result) == AOP_CRY)
9203 /* if the right size is a literal then
9204 we know what the value is */
9205 if (AOP_TYPE (right) == AOP_LIT)
9207 if (((int) operandLitValue (right)))
9208 aopPut (AOP (result), one, 0);
9210 aopPut (AOP (result), zero, 0);
9215 /* the right is also a bit variable */
9216 if (AOP_TYPE (right) == AOP_CRY)
9218 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9219 aopPut (AOP (result), "c", 0);
9225 aopPut (AOP (result), "a", 0);
9229 /* if they are the same size : or less */
9230 if (AOP_SIZE (result) <= AOP_SIZE (right))
9233 /* if they are in the same place */
9234 if (sameRegs (AOP (right), AOP (result)))
9237 /* if they in different places then copy */
9238 size = AOP_SIZE (result);
9240 _startLazyDPSEvaluation ();
9243 aopPut (AOP (result),
9244 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9248 _endLazyDPSEvaluation ();
9253 /* if the result is of type pointer */
9258 sym_link *type = operandType (right);
9260 /* pointer to generic pointer */
9261 if (IS_GENPTR (ctype))
9267 p_type = DCL_TYPE (type);
9271 #if OLD_CAST_BEHAVIOR
9272 /* KV: we are converting a non-pointer type to
9273 * a generic pointer. This (ifdef'd out) code
9274 * says that the resulting generic pointer
9275 * should have the same class as the storage
9276 * location of the non-pointer variable.
9278 * For example, converting an int (which happens
9279 * to be stored in DATA space) to a pointer results
9280 * in a DATA generic pointer; if the original int
9281 * in XDATA space, so will be the resulting pointer.
9283 * I don't like that behavior, and thus this change:
9284 * all such conversions will be forced to XDATA and
9285 * throw a warning. If you want some non-XDATA
9286 * type, or you want to suppress the warning, you
9287 * must go through an intermediate cast, like so:
9289 * char _generic *gp = (char _xdata *)(intVar);
9291 sym_link *etype = getSpec (type);
9293 /* we have to go by the storage class */
9294 if (SPEC_OCLS (etype) != generic)
9296 p_type = PTR_TYPE (SPEC_OCLS (etype));
9301 /* Converting unknown class (i.e. register variable)
9302 * to generic pointer. This is not good, but
9303 * we'll make a guess (and throw a warning).
9306 werror (W_INT_TO_GEN_PTR_CAST);
9310 /* the first two bytes are known */
9311 size = GPTRSIZE - 1;
9313 _startLazyDPSEvaluation ();
9316 aopPut (AOP (result),
9317 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9321 _endLazyDPSEvaluation ();
9323 /* the last byte depending on type */
9341 /* this should never happen */
9342 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9343 "got unknown pointer type");
9346 aopPut (AOP (result), l, GPTRSIZE - 1);
9350 /* just copy the pointers */
9351 size = AOP_SIZE (result);
9353 _startLazyDPSEvaluation ();
9356 aopPut (AOP (result),
9357 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9361 _endLazyDPSEvaluation ();
9365 /* so we now know that the size of destination is greater
9366 than the size of the source */
9367 /* we move to result for the size of source */
9368 size = AOP_SIZE (right);
9370 _startLazyDPSEvaluation ();
9373 aopPut (AOP (result),
9374 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9378 _endLazyDPSEvaluation ();
9380 /* now depending on the sign of the source && destination */
9381 size = AOP_SIZE (result) - AOP_SIZE (right);
9382 /* if unsigned or not an integral type */
9383 /* also, if the source is a bit, we don't need to sign extend, because
9384 * it can't possibly have set the sign bit.
9386 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9390 aopPut (AOP (result), zero, offset++);
9395 /* we need to extend the sign :{ */
9396 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9397 FALSE, FALSE, TRUE);
9399 emitcode ("rlc", "a");
9400 emitcode ("subb", "a,acc");
9402 aopPut (AOP (result), "a", offset++);
9405 /* we are done hurray !!!! */
9408 freeAsmop (right, NULL, ic, TRUE);
9409 freeAsmop (result, NULL, ic, TRUE);
9413 /*-----------------------------------------------------------------*/
9414 /* genDjnz - generate decrement & jump if not zero instrucion */
9415 /*-----------------------------------------------------------------*/
9417 genDjnz (iCode * ic, iCode * ifx)
9423 /* if the if condition has a false label
9424 then we cannot save */
9428 /* if the minus is not of the form
9430 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9431 !IS_OP_LITERAL (IC_RIGHT (ic)))
9434 if (operandLitValue (IC_RIGHT (ic)) != 1)
9437 /* if the size of this greater than one then no
9439 if (getSize (operandType (IC_RESULT (ic))) > 1)
9442 /* otherwise we can save BIG */
9443 D(emitcode(";", "genDjnz"););
9445 lbl = newiTempLabel (NULL);
9446 lbl1 = newiTempLabel (NULL);
9448 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9450 if (AOP_NEEDSACC(IC_RESULT(ic)))
9452 /* If the result is accessed indirectly via
9453 * the accumulator, we must explicitly write
9454 * it back after the decrement.
9456 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9458 if (strcmp(rByte, "a"))
9460 /* Something is hopelessly wrong */
9461 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9462 __FILE__, __LINE__);
9463 /* We can just give up; the generated code will be inefficient,
9466 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9469 emitcode ("dec", "%s", rByte);
9470 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9471 emitcode ("jnz", "%05d$", lbl->key + 100);
9473 else if (IS_AOP_PREG (IC_RESULT (ic)))
9475 emitcode ("dec", "%s",
9476 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9477 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9478 emitcode ("jnz", "%05d$", lbl->key + 100);
9482 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9485 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9486 emitcode ("", "%05d$:", lbl->key + 100);
9487 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9488 emitcode ("", "%05d$:", lbl1->key + 100);
9490 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9495 /*-----------------------------------------------------------------*/
9496 /* genReceive - generate code for a receive iCode */
9497 /*-----------------------------------------------------------------*/
9499 genReceive (iCode * ic)
9502 D (emitcode (";", "genReceive ");
9505 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9506 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9507 IS_TRUE_SYMOP (IC_RESULT (ic))))
9509 int size = getSize (operandType (IC_RESULT (ic)));
9510 int offset = fReturnSizeDS390 - size;
9513 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9514 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9517 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9518 size = AOP_SIZE (IC_RESULT (ic));
9522 emitcode ("pop", "acc");
9523 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9530 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9532 assignResultValue (IC_RESULT (ic));
9535 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9538 /*-----------------------------------------------------------------*/
9539 /* gen390Code - generate code for Dallas 390 based controllers */
9540 /*-----------------------------------------------------------------*/
9542 gen390Code (iCode * lic)
9547 lineHead = lineCurr = NULL;
9551 /* print the allocation information */
9553 printAllocInfo (currFunc, codeOutFile);
9555 /* if debug information required */
9556 if (options.debug && currFunc)
9558 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9560 if (IS_STATIC (currFunc->etype))
9561 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9563 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9566 /* stack pointer name */
9567 if (options.useXstack)
9573 for (ic = lic; ic; ic = ic->next)
9576 if (cln != ic->lineno)
9581 emitcode ("", "C$%s$%d$%d$%d ==.",
9582 FileBaseName (ic->filename), ic->lineno,
9583 ic->level, ic->block);
9586 emitcode (";", "%s %d", ic->filename, ic->lineno);
9589 /* if the result is marked as
9590 spilt and rematerializable or code for
9591 this has already been generated then
9593 if (resultRemat (ic) || ic->generated)
9596 /* depending on the operation */
9616 /* IPOP happens only when trying to restore a
9617 spilt live range, if there is an ifx statement
9618 following this pop then the if statement might
9619 be using some of the registers being popped which
9620 would destory the contents of the register so
9621 we need to check for this condition and handle it */
9623 ic->next->op == IFX &&
9624 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9625 genIfx (ic->next, ic);
9643 genEndFunction (ic);
9663 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9680 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9684 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9691 /* note these two are xlated by algebraic equivalence
9692 during parsing SDCC.y */
9693 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9694 "got '>=' or '<=' shouldn't have come here");
9698 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9710 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9714 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9718 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9745 case GET_VALUE_AT_ADDRESS:
9750 if (POINTER_SET (ic))
9777 addSet (&_G.sendSet, ic);
9786 /* now we are ready to call the
9787 peep hole optimizer */
9788 if (!options.nopeep)
9789 peepHole (&lineHead);
9791 /* now do the actual printing */
9792 printLine (lineHead, codeOutFile);