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>
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 #define BETTER_LITERAL_SHIFT
57 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
70 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
71 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
74 static char *fReturn24[] =
75 {"dpl", "dph", "dpx", "b", "a"};
76 static char *fReturn16[] =
77 {"dpl", "dph", "b", "a"};
78 static char **fReturn = fReturn24;
79 static char *accUse[] =
82 static short rbank = -1;
96 static void saveRBank (int, iCode *, bool);
98 #define RESULTONSTACK(x) \
99 (IC_RESULT(x) && IC_RESULT(x)->aop && \
100 IC_RESULT(x)->aop->type == AOP_STK )
102 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
103 #define MOVA(x) { char *_mova_tmp = strdup(x); \
104 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106 emitcode("mov","a,%s",_mova_tmp); \
110 #define CLRC emitcode("clr","c")
111 #define SETC emitcode("setb","c")
113 // A scratch register which will be used to hold
114 // result bytes from operands in far space via DPTR2.
115 #define DP2_RESULT_REG "ap"
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
120 static unsigned char SLMask[] =
121 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
125 0x07, 0x03, 0x01, 0x00};
132 /*-----------------------------------------------------------------*/
133 /* emitcode - writes the code into a file : for now it is simple */
134 /*-----------------------------------------------------------------*/
136 emitcode (char *inst, char *fmt,...)
139 char lb[INITIAL_INLINEASM];
147 sprintf (lb, "%s\t", inst);
149 sprintf (lb, "%s", inst);
150 vsprintf (lb + (strlen (lb)), fmt, ap);
153 vsprintf (lb, fmt, ap);
155 while (isspace (*lbp))
159 lineCurr = (lineCurr ?
160 connectLine (lineCurr, newLineNode (lb)) :
161 (lineHead = newLineNode (lb)));
162 lineCurr->isInline = _G.inLine;
163 lineCurr->isDebug = _G.debugLine;
167 /*-----------------------------------------------------------------*/
168 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
169 /*-----------------------------------------------------------------*/
171 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 bool r0iu = FALSE, r1iu = FALSE;
174 bool r0ou = FALSE, r1ou = FALSE;
176 /* the logic: if r0 & r1 used in the instruction
177 then we are in trouble otherwise */
179 /* first check if r0 & r1 are used by this
180 instruction, in which case we are in trouble */
181 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
182 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
187 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
188 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190 /* if no usage of r0 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
194 (*aopp)->type = AOP_R0;
196 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
199 /* if no usage of r1 then return it */
202 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
203 (*aopp)->type = AOP_R1;
205 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
208 /* now we know they both have usage */
209 /* if r0 not used in this instruction */
212 /* push it if not already pushed */
215 emitcode ("push", "%s",
216 ds390_regWithIdx (R0_IDX)->dname);
220 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
221 (*aopp)->type = AOP_R0;
223 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
226 /* if r1 not used then */
230 /* push it if not already pushed */
233 emitcode ("push", "%s",
234 ds390_regWithIdx (R1_IDX)->dname);
238 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
239 (*aopp)->type = AOP_R1;
240 return ds390_regWithIdx (R1_IDX);
244 /* I said end of world but not quite end of world yet */
245 /* if this is a result then we can push it on the stack */
248 (*aopp)->type = AOP_STK;
252 /* other wise this is true end of the world */
253 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
254 "getFreePtr should never reach here");
258 /*-----------------------------------------------------------------*/
259 /* newAsmop - creates a new asmOp */
260 /*-----------------------------------------------------------------*/
262 newAsmop (short type)
266 aop = Safe_calloc (1, sizeof (asmop));
271 static int _currentDPS; /* Current processor DPS. */
272 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
273 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
275 /*-----------------------------------------------------------------*/
276 /* genSetDPTR: generate code to select which DPTR is in use (zero */
277 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
278 /* alternate DPTR (DPL1/DPH1/DPX1). */
279 /*-----------------------------------------------------------------*/
284 /* If we are doing lazy evaluation, simply note the desired
285 * change, but don't emit any code yet.
295 emitcode ("mov", "dps, #0x00");
300 emitcode ("mov", "dps, #0x01");
304 /*-----------------------------------------------------------------*/
305 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /* Any code that operates on DPTR (NB: not on the individual */
308 /* components, like DPH) *must* call _flushLazyDPS() before using */
309 /* DPTR within a lazy DPS evaluation block. */
311 /* Note that aopPut and aopGet already contain the proper calls to */
312 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
313 /* DPS evaluation block. */
315 /* Also, _flushLazyDPS must be called before any flow control */
316 /* operations that could potentially branch out of the block. */
318 /* Lazy DPS evaluation is simply an optimization (though an */
319 /* important one), so if in doubt, leave it out. */
320 /*-----------------------------------------------------------------*/
322 _startLazyDPSEvaluation (void)
326 #ifdef BETTER_LITERAL_SHIFT
333 /*-----------------------------------------------------------------*/
334 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
335 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /*-----------------------------------------------------------------*/
347 if (_desiredDPS != _currentDPS)
351 emitcode ("inc", "dps");
355 emitcode ("dec", "dps");
357 _currentDPS = _desiredDPS;
361 /*-----------------------------------------------------------------*/
362 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
364 /* Forces us back to the safe state (standard DPTR selected). */
365 /*-----------------------------------------------------------------*/
367 _endLazyDPSEvaluation (void)
369 #ifdef BETTER_LITERAL_SHIFT
388 /*-----------------------------------------------------------------*/
389 /* pointerCode - returns the code for a pointer type */
390 /*-----------------------------------------------------------------*/
392 pointerCode (sym_link * etype)
395 return PTR_TYPE (SPEC_OCLS (etype));
399 /*-----------------------------------------------------------------*/
400 /* aopForSym - for a true symbol */
401 /*-----------------------------------------------------------------*/
403 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
406 memmap *space = SPEC_OCLS (sym->etype);
408 /* if already has one */
412 /* assign depending on the storage class */
413 /* if it is on the stack or indirectly addressable */
414 /* space we need to assign either r0 or r1 to it */
415 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417 sym->aop = aop = newAsmop (0);
418 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
419 aop->size = getSize (sym->type);
421 /* now assign the address of the variable to
422 the pointer register */
423 if (aop->type != AOP_STK)
429 emitcode ("push", "acc");
431 emitcode ("mov", "a,_bp");
432 emitcode ("add", "a,#0x%02x",
434 ((char) (sym->stack - _G.nRegsSaved)) :
435 ((char) sym->stack)) & 0xff);
436 emitcode ("mov", "%s,a",
437 aop->aopu.aop_ptr->name);
440 emitcode ("pop", "acc");
443 emitcode ("mov", "%s,#%s",
444 aop->aopu.aop_ptr->name,
446 aop->paged = space->paged;
449 aop->aopu.aop_stk = sym->stack;
453 if (sym->onStack && options.stack10bit)
455 /* It's on the 10 bit stack, which is located in
460 emitcode ("push", "acc");
462 emitcode ("mov", "a,_bp");
463 emitcode ("add", "a,#0x%02x",
465 ((char) (sym->stack - _G.nRegsSaved)) :
466 ((char) sym->stack)) & 0xff);
470 if (options.model == MODEL_FLAT24)
471 emitcode ("mov", "dpx1,#0x40");
473 emitcode ("mov", "dph1,#0x00");
474 emitcode ("mov", "dpl1, a");
478 if (options.model == MODEL_FLAT24)
479 emitcode ("mov", "dpx,#0x40");
480 emitcode ("mov", "dph,#0x00");
481 emitcode ("mov", "dpl, a");
485 emitcode ("pop", "acc");
487 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
488 aop->size = getSize (sym->type);
492 /* if in bit space */
493 if (IN_BITSPACE (space))
495 sym->aop = aop = newAsmop (AOP_CRY);
496 aop->aopu.aop_dir = sym->rname;
497 aop->size = getSize (sym->type);
500 /* if it is in direct space */
501 if (IN_DIRSPACE (space))
503 sym->aop = aop = newAsmop (AOP_DIR);
504 aop->aopu.aop_dir = sym->rname;
505 aop->size = getSize (sym->type);
509 /* special case for a function */
510 if (IS_FUNC (sym->type))
512 sym->aop = aop = newAsmop (AOP_IMMD);
513 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
514 strcpy (aop->aopu.aop_immd, sym->rname);
515 aop->size = FPTRSIZE;
519 /* only remaining is far space */
520 /* in which case DPTR gets the address */
521 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
526 emitcode ("mov", "dptr,#%s", sym->rname);
531 emitcode ("mov", "dptr,#%s", sym->rname);
533 aop->size = getSize (sym->type);
535 /* if it is in code space */
536 if (IN_CODESPACE (space))
542 /*-----------------------------------------------------------------*/
543 /* aopForRemat - rematerialzes an object */
544 /*-----------------------------------------------------------------*/
546 aopForRemat (symbol * sym)
548 iCode *ic = sym->rematiCode;
549 asmop *aop = newAsmop (AOP_IMMD);
556 val += (int) operandLitValue (IC_RIGHT (ic));
557 else if (ic->op == '-')
558 val -= (int) operandLitValue (IC_RIGHT (ic));
562 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
566 sprintf (buffer, "(%s %c 0x%04x)",
567 OP_SYMBOL (IC_LEFT (ic))->rname,
568 val >= 0 ? '+' : '-',
571 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
573 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
574 strcpy (aop->aopu.aop_immd, buffer);
578 /*-----------------------------------------------------------------*/
579 /* regsInCommon - two operands have some registers in common */
580 /*-----------------------------------------------------------------*/
582 regsInCommon (operand * op1, operand * op2)
587 /* if they have registers in common */
588 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
591 sym1 = OP_SYMBOL (op1);
592 sym2 = OP_SYMBOL (op2);
594 if (sym1->nRegs == 0 || sym2->nRegs == 0)
597 for (i = 0; i < sym1->nRegs; i++)
603 for (j = 0; j < sym2->nRegs; j++)
608 if (sym2->regs[j] == sym1->regs[i])
616 /*-----------------------------------------------------------------*/
617 /* operandsEqu - equivalent */
618 /*-----------------------------------------------------------------*/
620 operandsEqu (operand * op1, operand * op2)
624 /* if they not symbols */
625 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
628 sym1 = OP_SYMBOL (op1);
629 sym2 = OP_SYMBOL (op2);
631 /* if both are itemps & one is spilt
632 and the other is not then false */
633 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
634 sym1->isspilt != sym2->isspilt)
637 /* if they are the same */
641 if (strcmp (sym1->rname, sym2->rname) == 0)
645 /* if left is a tmp & right is not */
646 if (IS_ITEMP (op1) &&
649 (sym1->usl.spillLoc == sym2))
652 if (IS_ITEMP (op2) &&
656 (sym2->usl.spillLoc == sym1))
662 /*-----------------------------------------------------------------*/
663 /* sameRegs - two asmops have the same registers */
664 /*-----------------------------------------------------------------*/
666 sameRegs (asmop * aop1, asmop * aop2)
672 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
679 if (aop1->type != AOP_REG ||
680 aop2->type != AOP_REG)
683 if (aop1->size != aop2->size)
686 for (i = 0; i < aop1->size; i++)
687 if (aop1->aopu.aop_reg[i] !=
688 aop2->aopu.aop_reg[i])
694 /*-----------------------------------------------------------------*/
695 /* aopOp - allocates an asmop for an operand : */
696 /*-----------------------------------------------------------------*/
698 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
707 /* if this a literal */
708 if (IS_OP_LITERAL (op))
710 op->aop = aop = newAsmop (AOP_LIT);
711 aop->aopu.aop_lit = op->operand.valOperand;
712 aop->size = getSize (operandType (op));
716 /* if already has a asmop then continue */
720 /* if the underlying symbol has a aop */
721 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
723 op->aop = OP_SYMBOL (op)->aop;
727 /* if this is a true symbol */
728 if (IS_TRUE_SYMOP (op))
730 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
734 /* this is a temporary : this has
740 e) can be a return use only */
742 sym = OP_SYMBOL (op);
745 /* if the type is a conditional */
746 if (sym->regType == REG_CND)
748 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
753 /* if it is spilt then two situations
755 b) has a spill location */
756 if (sym->isspilt || sym->nRegs == 0)
759 /* rematerialize it NOW */
762 sym->aop = op->aop = aop =
764 aop->size = getSize (sym->type);
771 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
772 aop->size = getSize (sym->type);
773 for (i = 0; i < 2; i++)
774 aop->aopu.aop_str[i] = accUse[i];
784 /* a AOP_STR uses DPTR, but DPTR is already in use;
787 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
790 aop = op->aop = sym->aop = newAsmop (AOP_STR);
791 aop->size = getSize (sym->type);
792 for (i = 0; i < (int) fReturnSizeDS390; i++)
793 aop->aopu.aop_str[i] = fReturn[i];
797 /* else spill location */
798 sym->aop = op->aop = aop =
799 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
800 aop->size = getSize (sym->type);
804 /* must be in a register */
805 sym->aop = op->aop = aop = newAsmop (AOP_REG);
806 aop->size = sym->nRegs;
807 for (i = 0; i < sym->nRegs; i++)
808 aop->aopu.aop_reg[i] = sym->regs[i];
811 /*-----------------------------------------------------------------*/
812 /* freeAsmop - free up the asmop given to an operand */
813 /*----------------------------------------------------------------*/
815 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
832 /* depending on the asmop type only three cases need work AOP_RO
833 , AOP_R1 && AOP_STK */
841 emitcode ("pop", "ar0");
845 bitVectUnSetBit (ic->rUsed, R0_IDX);
853 emitcode ("pop", "ar1");
857 bitVectUnSetBit (ic->rUsed, R1_IDX);
863 int stk = aop->aopu.aop_stk + aop->size;
864 bitVectUnSetBit (ic->rUsed, R0_IDX);
865 bitVectUnSetBit (ic->rUsed, R1_IDX);
867 getFreePtr (ic, &aop, FALSE);
869 if (options.stack10bit)
871 /* I'm not sure what to do here yet... */
874 "*** Warning: probably generating bad code for "
875 "10 bit stack mode.\n");
880 emitcode ("mov", "a,_bp");
881 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
882 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
886 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
891 emitcode ("pop", "acc");
892 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
895 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
898 freeAsmop (op, NULL, ic, TRUE);
901 emitcode ("pop", "ar0");
907 emitcode ("pop", "ar1");
914 /* all other cases just dealloc */
920 OP_SYMBOL (op)->aop = NULL;
921 /* if the symbol has a spill */
923 SPIL_LOC (op)->aop = NULL;
928 /*------------------------------------------------------------------*/
929 /* aopGet - for fetching value of the aop */
931 /* Set canClobberACC if you are sure it is OK to clobber the value */
932 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
933 /* just less efficient. */
934 /*------------------------------------------------------------------*/
946 /* offset is greater than
948 if (offset > (aop->size - 1) &&
949 aop->type != AOP_LIT)
952 /* depending on type */
958 /* if we need to increment it */
959 while (offset > aop->coff)
961 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
965 while (offset < aop->coff)
967 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
974 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
975 return (dname ? "acc" : "a");
977 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
978 rs = Safe_calloc (1, strlen (s) + 1);
985 if (aop->type == AOP_DPTR2)
991 emitcode ("xch", "a, %s", DP2_RESULT_REG);
997 while (offset > aop->coff)
999 emitcode ("inc", "dptr");
1003 while (offset < aop->coff)
1005 emitcode ("lcall", "__decdptr");
1012 emitcode ("clr", "a");
1013 emitcode ("movc", "a,@a+dptr");
1017 emitcode ("movx", "a,@dptr");
1020 if (aop->type == AOP_DPTR2)
1026 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1027 return DP2_RESULT_REG;
1030 return (dname ? "acc" : "a");
1034 sprintf (s, "#%s", aop->aopu.aop_immd);
1036 sprintf (s, "#(%s >> %d)",
1041 aop->aopu.aop_immd);
1042 rs = Safe_calloc (1, strlen (s) + 1);
1048 sprintf (s, "(%s + %d)",
1052 sprintf (s, "%s", aop->aopu.aop_dir);
1053 rs = Safe_calloc (1, strlen (s) + 1);
1059 return aop->aopu.aop_reg[offset]->dname;
1061 return aop->aopu.aop_reg[offset]->name;
1064 emitcode ("clr", "a");
1065 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1066 emitcode ("rlc", "a");
1067 return (dname ? "acc" : "a");
1070 if (!offset && dname)
1072 return aop->aopu.aop_str[offset];
1075 return aopLiteral (aop->aopu.aop_lit, offset);
1079 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1083 return aop->aopu.aop_str[offset];
1087 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1088 "aopget got unsupported aop->type");
1091 /*-----------------------------------------------------------------*/
1092 /* aopPut - puts a string for a aop */
1093 /*-----------------------------------------------------------------*/
1095 aopPut (asmop * aop, char *s, int offset)
1099 if (aop->size && offset > (aop->size - 1))
1101 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1102 "aopPut got offset > aop->size");
1106 /* will assign value to value */
1107 /* depending on where it is ofcourse */
1112 sprintf (d, "(%s + %d)",
1113 aop->aopu.aop_dir, offset);
1115 sprintf (d, "%s", aop->aopu.aop_dir);
1118 emitcode ("mov", "%s,%s", d, s);
1123 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1124 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1127 strcmp (s, "r0") == 0 ||
1128 strcmp (s, "r1") == 0 ||
1129 strcmp (s, "r2") == 0 ||
1130 strcmp (s, "r3") == 0 ||
1131 strcmp (s, "r4") == 0 ||
1132 strcmp (s, "r5") == 0 ||
1133 strcmp (s, "r6") == 0 ||
1134 strcmp (s, "r7") == 0)
1135 emitcode ("mov", "%s,%s",
1136 aop->aopu.aop_reg[offset]->dname, s);
1138 emitcode ("mov", "%s,%s",
1139 aop->aopu.aop_reg[offset]->name, s);
1146 if (aop->type == AOP_DPTR2)
1154 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1155 "aopPut writting to code space");
1159 while (offset > aop->coff)
1162 emitcode ("inc", "dptr");
1165 while (offset < aop->coff)
1168 emitcode ("lcall", "__decdptr");
1173 /* if not in accumulater */
1176 emitcode ("movx", "@dptr,a");
1178 if (aop->type == AOP_DPTR2)
1186 while (offset > aop->coff)
1189 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1191 while (offset < aop->coff)
1194 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1201 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1207 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1209 else if (strcmp (s, "r0") == 0 ||
1210 strcmp (s, "r1") == 0 ||
1211 strcmp (s, "r2") == 0 ||
1212 strcmp (s, "r3") == 0 ||
1213 strcmp (s, "r4") == 0 ||
1214 strcmp (s, "r5") == 0 ||
1215 strcmp (s, "r6") == 0 ||
1216 strcmp (s, "r7") == 0)
1219 sprintf (buffer, "a%s", s);
1220 emitcode ("mov", "@%s,%s",
1221 aop->aopu.aop_ptr->name, buffer);
1224 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1229 if (strcmp (s, "a") == 0)
1230 emitcode ("push", "acc");
1232 emitcode ("push", "%s", s);
1237 /* if bit variable */
1238 if (!aop->aopu.aop_dir)
1240 emitcode ("clr", "a");
1241 emitcode ("rlc", "a");
1246 emitcode ("clr", "%s", aop->aopu.aop_dir);
1248 emitcode ("setb", "%s", aop->aopu.aop_dir);
1249 else if (!strcmp (s, "c"))
1250 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1253 if (strcmp (s, "a"))
1258 symbol *lbl = newiTempLabel (NULL);
1259 emitcode ("clr", "c");
1260 emitcode ("jz", "%05d$", lbl->key + 100);
1261 emitcode ("cpl", "c");
1262 emitcode ("", "%05d$:", lbl->key + 100);
1263 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1271 if (strcmp (aop->aopu.aop_str[offset], s))
1272 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1277 if (!offset && (strcmp (s, "acc") == 0))
1280 if (strcmp (aop->aopu.aop_str[offset], s))
1281 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286 "aopPut got unsupported aop->type");
1293 /*--------------------------------------------------------------------*/
1294 /* reAdjustPreg - points a register back to where it should (coff==0) */
1295 /*--------------------------------------------------------------------*/
1297 reAdjustPreg (asmop * aop)
1299 if ((aop->coff==0) || (aop->size <= 1)) {
1308 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1312 if (aop->type == AOP_DPTR2)
1319 emitcode ("lcall", "__decdptr");
1322 if (aop->type == AOP_DPTR2)
1332 #define AOP(op) op->aop
1333 #define AOP_TYPE(op) AOP(op)->type
1334 #define AOP_SIZE(op) AOP(op)->size
1335 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1336 AOP_TYPE(x) == AOP_R0))
1338 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1339 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1342 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1343 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1344 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1346 /* Workaround for DS80C390 bug: div ab may return bogus results
1347 * if A is accessed in instruction immediately before the div.
1349 * Will be fixed in B4 rev of processor, Dallas claims.
1352 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1353 if (!AOP_NEEDSACC(RIGHT)) \
1355 /* We can load A first, then B, since \
1356 * B (the RIGHT operand) won't clobber A, \
1357 * thus avoiding touching A right before the div. \
1359 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1360 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1362 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1366 /* Just stuff in a nop after loading A. */ \
1367 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1368 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1370 emitcode("nop", "; workaround for DS80C390 div bug."); \
1373 /*-----------------------------------------------------------------*/
1374 /* genNotFloat - generates not for float operations */
1375 /*-----------------------------------------------------------------*/
1377 genNotFloat (operand * op, operand * res)
1383 D (emitcode (";", "genNotFloat ");
1386 /* we will put 127 in the first byte of
1388 aopPut (AOP (res), "#127", 0);
1389 size = AOP_SIZE (op) - 1;
1392 _startLazyDPSEvaluation ();
1393 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1398 emitcode ("orl", "a,%s",
1400 offset++, FALSE, FALSE, FALSE));
1402 _endLazyDPSEvaluation ();
1404 tlbl = newiTempLabel (NULL);
1405 aopPut (res->aop, one, 1);
1406 emitcode ("jz", "%05d$", (tlbl->key + 100));
1407 aopPut (res->aop, zero, 1);
1408 emitcode ("", "%05d$:", (tlbl->key + 100));
1410 size = res->aop->size - 2;
1412 /* put zeros in the rest */
1414 aopPut (res->aop, zero, offset++);
1417 /*-----------------------------------------------------------------*/
1418 /* opIsGptr: returns non-zero if the passed operand is */
1419 /* a generic pointer type. */
1420 /*-----------------------------------------------------------------*/
1422 opIsGptr (operand * op)
1424 sym_link *type = operandType (op);
1426 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1433 /*-----------------------------------------------------------------*/
1434 /* getDataSize - get the operand data size */
1435 /*-----------------------------------------------------------------*/
1437 getDataSize (operand * op)
1440 size = AOP_SIZE (op);
1441 if (size == GPTRSIZE)
1443 sym_link *type = operandType (op);
1444 if (IS_GENPTR (type))
1446 /* generic pointer; arithmetic operations
1447 * should ignore the high byte (pointer type).
1455 /*-----------------------------------------------------------------*/
1456 /* outAcc - output Acc */
1457 /*-----------------------------------------------------------------*/
1459 outAcc (operand * result)
1462 size = getDataSize (result);
1465 aopPut (AOP (result), "a", 0);
1468 /* unsigned or positive */
1471 aopPut (AOP (result), zero, offset++);
1476 /*-----------------------------------------------------------------*/
1477 /* outBitC - output a bit C */
1478 /*-----------------------------------------------------------------*/
1480 outBitC (operand * result)
1482 /* if the result is bit */
1483 if (AOP_TYPE (result) == AOP_CRY)
1485 aopPut (AOP (result), "c", 0);
1489 emitcode ("clr", "a");
1490 emitcode ("rlc", "a");
1495 /*-----------------------------------------------------------------*/
1496 /* toBoolean - emit code for orl a,operator(sizeop) */
1497 /*-----------------------------------------------------------------*/
1499 toBoolean (operand * oper)
1501 int size = AOP_SIZE (oper) - 1;
1505 /* The generic part of a generic pointer should
1506 * not participate in it's truth value.
1508 * i.e. 0x10000000 is zero.
1510 if (opIsGptr (oper))
1512 D (emitcode (";", "toBoolean: generic ptr special case.");
1517 _startLazyDPSEvaluation ();
1518 if (AOP_NEEDSACC (oper) && size)
1521 emitcode ("push", "b");
1522 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1526 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1532 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1536 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1539 _endLazyDPSEvaluation ();
1543 emitcode ("mov", "a,b");
1544 emitcode ("pop", "b");
1549 /*-----------------------------------------------------------------*/
1550 /* genNot - generate code for ! operation */
1551 /*-----------------------------------------------------------------*/
1556 sym_link *optype = operandType (IC_LEFT (ic));
1558 D (emitcode (";", "genNot ");
1561 /* assign asmOps to operand & result */
1562 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1563 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1565 /* if in bit space then a special case */
1566 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1568 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1569 emitcode ("cpl", "c");
1570 outBitC (IC_RESULT (ic));
1574 /* if type float then do float */
1575 if (IS_FLOAT (optype))
1577 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1581 toBoolean (IC_LEFT (ic));
1583 tlbl = newiTempLabel (NULL);
1584 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1585 emitcode ("", "%05d$:", tlbl->key + 100);
1586 outBitC (IC_RESULT (ic));
1589 /* release the aops */
1590 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1591 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1595 /*-----------------------------------------------------------------*/
1596 /* genCpl - generate code for complement */
1597 /*-----------------------------------------------------------------*/
1604 D (emitcode (";", "genCpl ");
1608 /* assign asmOps to operand & result */
1609 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1610 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1612 /* if both are in bit space then
1614 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1615 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1618 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1619 emitcode ("cpl", "c");
1620 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1624 size = AOP_SIZE (IC_RESULT (ic));
1625 _startLazyDPSEvaluation ();
1628 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1630 emitcode ("cpl", "a");
1631 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1633 _endLazyDPSEvaluation ();
1637 /* release the aops */
1638 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1639 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1642 /*-----------------------------------------------------------------*/
1643 /* genUminusFloat - unary minus for floating points */
1644 /*-----------------------------------------------------------------*/
1646 genUminusFloat (operand * op, operand * result)
1648 int size, offset = 0;
1650 /* for this we just need to flip the
1651 first it then copy the rest in place */
1652 D (emitcode (";", "genUminusFloat");
1655 _startLazyDPSEvaluation ();
1656 size = AOP_SIZE (op) - 1;
1657 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1660 emitcode ("cpl", "acc.7");
1661 aopPut (AOP (result), "a", 3);
1665 aopPut (AOP (result),
1666 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1670 _endLazyDPSEvaluation ();
1673 /*-----------------------------------------------------------------*/
1674 /* genUminus - unary minus code generation */
1675 /*-----------------------------------------------------------------*/
1677 genUminus (iCode * ic)
1680 sym_link *optype, *rtype;
1682 D (emitcode (";", "genUminus ");
1687 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1688 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1690 /* if both in bit space then special
1692 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1693 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1696 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1697 emitcode ("cpl", "c");
1698 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1702 optype = operandType (IC_LEFT (ic));
1703 rtype = operandType (IC_RESULT (ic));
1705 /* if float then do float stuff */
1706 if (IS_FLOAT (optype))
1708 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1712 /* otherwise subtract from zero */
1713 size = AOP_SIZE (IC_LEFT (ic));
1715 _startLazyDPSEvaluation ();
1718 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1719 if (!strcmp (l, "a"))
1723 emitcode ("cpl", "a");
1724 emitcode ("addc", "a,#0");
1730 emitcode ("clr", "a");
1731 emitcode ("subb", "a,%s", l);
1733 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1735 _endLazyDPSEvaluation ();
1737 /* if any remaining bytes in the result */
1738 /* we just need to propagate the sign */
1739 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1741 emitcode ("rlc", "a");
1742 emitcode ("subb", "a,acc");
1744 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1748 /* release the aops */
1749 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1750 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1753 /*-----------------------------------------------------------------*/
1754 /* saveRegisters - will look for a call and save the registers */
1755 /*-----------------------------------------------------------------*/
1757 saveRegisters (iCode * lic)
1765 for (ic = lic; ic; ic = ic->next)
1766 if (ic->op == CALL || ic->op == PCALL)
1771 fprintf (stderr, "found parameter push with no function call\n");
1775 /* if the registers have been saved already then
1777 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1778 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
1781 /* find the registers in use at this time
1782 and push them away to safety */
1783 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1787 if (options.useXstack)
1789 if (bitVectBitValue (rsave, R0_IDX))
1790 emitcode ("mov", "b,r0");
1791 emitcode ("mov", "r0,%s", spname);
1792 for (i = 0; i < ds390_nRegs; i++)
1794 if (bitVectBitValue (rsave, i))
1797 emitcode ("mov", "a,b");
1799 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1800 emitcode ("movx", "@r0,a");
1801 emitcode ("inc", "r0");
1804 emitcode ("mov", "%s,r0", spname);
1805 if (bitVectBitValue (rsave, R0_IDX))
1806 emitcode ("mov", "r0,b");
1809 for (i = 0; i < ds390_nRegs; i++)
1811 if (bitVectBitValue (rsave, i))
1812 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1815 detype = getSpec (operandType (IC_LEFT (ic)));
1818 /*-----------------------------------------------------------------*/
1819 /* unsaveRegisters - pop the pushed registers */
1820 /*-----------------------------------------------------------------*/
1822 unsaveRegisters (iCode * ic)
1826 /* find the registers in use at this time
1827 and push them away to safety */
1828 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1831 if (options.useXstack)
1833 emitcode ("mov", "r0,%s", spname);
1834 for (i = ds390_nRegs; i >= 0; i--)
1836 if (bitVectBitValue (rsave, i))
1838 emitcode ("dec", "r0");
1839 emitcode ("movx", "a,@r0");
1841 emitcode ("mov", "b,a");
1843 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1847 emitcode ("mov", "%s,r0", spname);
1848 if (bitVectBitValue (rsave, R0_IDX))
1849 emitcode ("mov", "r0,b");
1852 for (i = ds390_nRegs; i >= 0; i--)
1854 if (bitVectBitValue (rsave, i))
1855 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1861 /*-----------------------------------------------------------------*/
1863 /*-----------------------------------------------------------------*/
1865 pushSide (operand * oper, int size)
1868 _startLazyDPSEvaluation ();
1871 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1872 if (AOP_TYPE (oper) != AOP_REG &&
1873 AOP_TYPE (oper) != AOP_DIR &&
1876 emitcode ("mov", "a,%s", l);
1877 emitcode ("push", "acc");
1880 emitcode ("push", "%s", l);
1882 _endLazyDPSEvaluation ();
1885 /*-----------------------------------------------------------------*/
1886 /* assignResultValue - */
1887 /*-----------------------------------------------------------------*/
1889 assignResultValue (operand * oper)
1892 int size = AOP_SIZE (oper);
1894 _startLazyDPSEvaluation ();
1897 aopPut (AOP (oper), fReturn[offset], offset);
1900 _endLazyDPSEvaluation ();
1904 /*-----------------------------------------------------------------*/
1905 /* genXpush - pushes onto the external stack */
1906 /*-----------------------------------------------------------------*/
1908 genXpush (iCode * ic)
1910 asmop *aop = newAsmop (0);
1912 int size, offset = 0;
1914 D (emitcode (";", "genXpush ");
1917 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1918 r = getFreePtr (ic, &aop, FALSE);
1921 emitcode ("mov", "%s,_spx", r->name);
1923 size = AOP_SIZE (IC_LEFT (ic));
1924 _startLazyDPSEvaluation ();
1928 char *l = aopGet (AOP (IC_LEFT (ic)),
1929 offset++, FALSE, FALSE, TRUE);
1931 emitcode ("movx", "@%s,a", r->name);
1932 emitcode ("inc", "%s", r->name);
1935 _endLazyDPSEvaluation ();
1938 emitcode ("mov", "_spx,%s", r->name);
1940 freeAsmop (NULL, aop, ic, TRUE);
1941 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1944 /*-----------------------------------------------------------------*/
1945 /* genIpush - genrate code for pushing this gets a little complex */
1946 /*-----------------------------------------------------------------*/
1948 genIpush (iCode * ic)
1950 int size, offset = 0;
1953 D (emitcode (";", "genIpush ");
1956 /* if this is not a parm push : ie. it is spill push
1957 and spill push is always done on the local stack */
1961 /* and the item is spilt then do nothing */
1962 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1965 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1966 size = AOP_SIZE (IC_LEFT (ic));
1967 /* push it on the stack */
1968 _startLazyDPSEvaluation ();
1971 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1977 emitcode ("push", "%s", l);
1979 _endLazyDPSEvaluation ();
1983 /* this is a paramter push: in this case we call
1984 the routine to find the call and save those
1985 registers that need to be saved */
1988 /* if use external stack then call the external
1989 stack pushing routine */
1990 if (options.useXstack)
1996 /* then do the push */
1997 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1999 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2000 size = AOP_SIZE (IC_LEFT (ic));
2002 _startLazyDPSEvaluation ();
2005 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2006 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2007 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2010 emitcode ("mov", "a,%s", l);
2011 emitcode ("push", "acc");
2014 emitcode ("push", "%s", l);
2016 _endLazyDPSEvaluation ();
2018 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2021 /*-----------------------------------------------------------------*/
2022 /* genIpop - recover the registers: can happen only for spilling */
2023 /*-----------------------------------------------------------------*/
2025 genIpop (iCode * ic)
2029 D (emitcode (";", "genIpop ");
2033 /* if the temp was not pushed then */
2034 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2037 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2038 size = AOP_SIZE (IC_LEFT (ic));
2039 offset = (size - 1);
2040 _startLazyDPSEvaluation ();
2043 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2044 FALSE, TRUE, TRUE));
2046 _endLazyDPSEvaluation ();
2048 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2051 /*-----------------------------------------------------------------*/
2052 /* unsaveRBank - restores the resgister bank from stack */
2053 /*-----------------------------------------------------------------*/
2055 unsaveRBank (int bank, iCode * ic, bool popPsw)
2061 if (options.useXstack)
2065 /* Assume r0 is available for use. */
2066 r = ds390_regWithIdx (R0_IDX);;
2071 r = getFreePtr (ic, &aop, FALSE);
2073 emitcode ("mov", "%s,_spx", r->name);
2078 if (options.useXstack)
2080 emitcode ("movx", "a,@%s", r->name);
2081 emitcode ("mov", "psw,a");
2082 emitcode ("dec", "%s", r->name);
2086 emitcode ("pop", "psw");
2090 for (i = (ds390_nRegs - 1); i >= 0; i--)
2092 if (options.useXstack)
2094 emitcode ("movx", "a,@%s", r->name);
2095 emitcode ("mov", "(%s+%d),a",
2096 regs390[i].base, 8 * bank + regs390[i].offset);
2097 emitcode ("dec", "%s", r->name);
2101 emitcode ("pop", "(%s+%d)",
2102 regs390[i].base, 8 * bank + regs390[i].offset);
2105 if (options.useXstack)
2107 emitcode ("mov", "_spx,%s", r->name);
2112 freeAsmop (NULL, aop, ic, TRUE);
2116 /*-----------------------------------------------------------------*/
2117 /* saveRBank - saves an entire register bank on the stack */
2118 /*-----------------------------------------------------------------*/
2120 saveRBank (int bank, iCode * ic, bool pushPsw)
2126 if (options.useXstack)
2130 /* Assume r0 is available for use. */
2131 r = ds390_regWithIdx (R0_IDX);;
2136 r = getFreePtr (ic, &aop, FALSE);
2138 emitcode ("mov", "%s,_spx", r->name);
2141 for (i = 0; i < ds390_nRegs; i++)
2143 if (options.useXstack)
2145 emitcode ("inc", "%s", r->name);
2146 emitcode ("mov", "a,(%s+%d)",
2147 regs390[i].base, 8 * bank + regs390[i].offset);
2148 emitcode ("movx", "@%s,a", r->name);
2151 emitcode ("push", "(%s+%d)",
2152 regs390[i].base, 8 * bank + regs390[i].offset);
2157 if (options.useXstack)
2159 emitcode ("mov", "a,psw");
2160 emitcode ("movx", "@%s,a", r->name);
2161 emitcode ("inc", "%s", r->name);
2162 emitcode ("mov", "_spx,%s", r->name);
2166 emitcode ("push", "psw");
2169 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2174 freeAsmop (NULL, aop, ic, TRUE);
2183 /*-----------------------------------------------------------------*/
2184 /* genCall - generates a call statement */
2185 /*-----------------------------------------------------------------*/
2187 genCall (iCode * ic)
2190 bool restoreBank = FALSE;
2191 bool swapBanks = FALSE;
2193 D (emitcode (";", "genCall "););
2195 /* if we are calling a not _naked function that is not using
2196 the same register bank then we need to save the
2197 destination registers on the stack */
2198 detype = getSpec (operandType (IC_LEFT (ic)));
2199 if (detype && !SPEC_NAKED(detype) &&
2200 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2201 IS_ISR (currFunc->etype))
2205 /* This is unexpected; the bank should have been saved in
2208 saveRBank (SPEC_BANK (detype), ic, FALSE);
2214 /* if caller saves & we have not saved then */
2218 /* if send set is not empty the assign */
2219 /* We've saved all the registers we care about;
2220 * therefore, we may clobber any register not used
2221 * in the calling convention (i.e. anything not in
2228 for (sic = setFirstItem (_G.sendSet); sic;
2229 sic = setNextItem (_G.sendSet))
2231 int size, offset = 0;
2233 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2234 size = AOP_SIZE (IC_LEFT (sic));
2236 _startLazyDPSEvaluation ();
2239 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2240 FALSE, FALSE, TRUE);
2241 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2243 emitcode("mov", "%s,%s", regs390[offset].name, l);
2245 else if (strcmp (l, fReturn[offset]))
2247 emitcode ("mov", "%s,%s",
2253 _endLazyDPSEvaluation ();
2254 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2256 size = AOP_SIZE (IC_LEFT (sic));
2264 emitcode("mov", "%s,%s",
2265 fReturn[size], regs390[size].name);
2268 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2275 emitcode ("mov", "psw,#0x%02x",
2276 ((SPEC_BANK(detype)) << 3) & 0xff);
2280 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2281 OP_SYMBOL (IC_LEFT (ic))->rname :
2282 OP_SYMBOL (IC_LEFT (ic))->name));
2286 emitcode ("mov", "psw,#0x%02x",
2287 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
2290 /* if we need assign a result value */
2291 if ((IS_ITEMP (IC_RESULT (ic)) &&
2292 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2293 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2294 IS_TRUE_SYMOP (IC_RESULT (ic)))
2296 if (isOperandInFarSpace (IC_RESULT (ic))
2297 && getSize (operandType (IC_RESULT (ic))) <= 2)
2299 int size = getSize (operandType (IC_RESULT (ic)));
2301 /* Special case for 1 or 2 byte return in far space. */
2305 emitcode ("mov", "b,%s", fReturn[1]);
2308 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2309 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2313 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2315 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2320 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2323 assignResultValue (IC_RESULT (ic));
2325 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2329 /* adjust the stack for parameters if
2334 if (ic->parmBytes > 3)
2336 emitcode ("mov", "a,%s", spname);
2337 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2338 emitcode ("mov", "%s,a", spname);
2341 for (i = 0; i < ic->parmBytes; i++)
2342 emitcode ("dec", "%s", spname);
2345 /* if we hade saved some registers then unsave them */
2346 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2347 unsaveRegisters (ic);
2349 /* if register bank was saved then pop them */
2351 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
2354 /*-----------------------------------------------------------------*/
2355 /* genPcall - generates a call by pointer statement */
2356 /*-----------------------------------------------------------------*/
2358 genPcall (iCode * ic)
2361 symbol *rlbl = newiTempLabel (NULL);
2363 D (emitcode (";", "genPcall ");
2367 /* if caller saves & we have not saved then */
2371 /* if we are calling a function that is not using
2372 the same register bank then we need to save the
2373 destination registers on the stack */
2374 detype = getSpec (operandType (IC_LEFT (ic)));
2376 IS_ISR (currFunc->etype) &&
2377 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2378 saveRBank (SPEC_BANK (detype), ic, TRUE);
2381 /* push the return address on to the stack */
2382 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2383 emitcode ("push", "acc");
2384 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2385 emitcode ("push", "acc");
2387 if (options.model == MODEL_FLAT24)
2389 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2390 emitcode ("push", "acc");
2393 /* now push the calling address */
2394 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2396 pushSide (IC_LEFT (ic), FPTRSIZE);
2398 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2400 /* if send set is not empty the assign */
2405 for (sic = setFirstItem (_G.sendSet); sic;
2406 sic = setNextItem (_G.sendSet))
2408 int size, offset = 0;
2410 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2411 size = AOP_SIZE (IC_LEFT (sic));
2412 _startLazyDPSEvaluation ();
2415 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2416 FALSE, FALSE, TRUE);
2417 if (strcmp (l, fReturn[offset]))
2419 emitcode ("mov", "%s,%s",
2425 _endLazyDPSEvaluation ();
2426 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2431 emitcode ("ret", "");
2432 emitcode ("", "%05d$:", (rlbl->key + 100));
2435 /* if we need assign a result value */
2436 if ((IS_ITEMP (IC_RESULT (ic)) &&
2437 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2438 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2439 IS_TRUE_SYMOP (IC_RESULT (ic)))
2443 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2446 assignResultValue (IC_RESULT (ic));
2448 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2451 /* adjust the stack for parameters if
2456 if (ic->parmBytes > 3)
2458 emitcode ("mov", "a,%s", spname);
2459 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2460 emitcode ("mov", "%s,a", spname);
2463 for (i = 0; i < ic->parmBytes; i++)
2464 emitcode ("dec", "%s", spname);
2468 /* if register bank was saved then unsave them */
2470 (SPEC_BANK (currFunc->etype) !=
2471 SPEC_BANK (detype)))
2472 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2474 /* if we hade saved some registers then
2477 unsaveRegisters (ic);
2481 /*-----------------------------------------------------------------*/
2482 /* resultRemat - result is rematerializable */
2483 /*-----------------------------------------------------------------*/
2485 resultRemat (iCode * ic)
2487 if (SKIP_IC (ic) || ic->op == IFX)
2490 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2492 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2493 if (sym->remat && !POINTER_SET (ic))
2500 #if defined(__BORLANDC__) || defined(_MSC_VER)
2501 #define STRCASECMP stricmp
2503 #define STRCASECMP strcasecmp
2506 /*-----------------------------------------------------------------*/
2507 /* inExcludeList - return 1 if the string is in exclude Reg list */
2508 /*-----------------------------------------------------------------*/
2510 inExcludeList (char *s)
2514 if (options.excludeRegs[i] &&
2515 STRCASECMP (options.excludeRegs[i], "none") == 0)
2518 for (i = 0; options.excludeRegs[i]; i++)
2520 if (options.excludeRegs[i] &&
2521 STRCASECMP (s, options.excludeRegs[i]) == 0)
2527 /*-----------------------------------------------------------------*/
2528 /* genFunction - generated code for function entry */
2529 /*-----------------------------------------------------------------*/
2531 genFunction (iCode * ic)
2535 bool switchedPSW = FALSE;
2537 D (emitcode (";", "genFunction "););
2540 /* create the function header */
2541 emitcode (";", "-----------------------------------------");
2542 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2543 emitcode (";", "-----------------------------------------");
2545 emitcode ("", "%s:", sym->rname);
2546 fetype = getSpec (operandType (IC_LEFT (ic)));
2548 if (SPEC_NAKED(fetype))
2550 emitcode(";", "naked function: no prologue.");
2554 /* if critical function then turn interrupts off */
2555 if (SPEC_CRTCL (fetype))
2556 emitcode ("clr", "ea");
2558 /* here we need to generate the equates for the
2559 register bank if required */
2560 if (SPEC_BANK (fetype) != rbank)
2564 rbank = SPEC_BANK (fetype);
2565 for (i = 0; i < ds390_nRegs; i++)
2567 if (strcmp (regs390[i].base, "0") == 0)
2568 emitcode ("", "%s = 0x%02x",
2570 8 * rbank + regs390[i].offset);
2572 emitcode ("", "%s = %s + 0x%02x",
2575 8 * rbank + regs390[i].offset);
2579 /* if this is an interrupt service routine then
2580 save acc, b, dpl, dph */
2581 if (IS_ISR (sym->etype))
2584 if (!inExcludeList ("acc"))
2585 emitcode ("push", "acc");
2586 if (!inExcludeList ("b"))
2587 emitcode ("push", "b");
2588 if (!inExcludeList ("dpl"))
2589 emitcode ("push", "dpl");
2590 if (!inExcludeList ("dph"))
2591 emitcode ("push", "dph");
2592 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2594 emitcode ("push", "dpx");
2595 /* Make sure we're using standard DPTR */
2596 emitcode ("push", "dps");
2597 emitcode ("mov", "dps, #0x00");
2598 if (options.stack10bit)
2600 /* This ISR could conceivably use DPTR2. Better save it. */
2601 emitcode ("push", "dpl1");
2602 emitcode ("push", "dph1");
2603 emitcode ("push", "dpx1");
2604 emitcode ("push", DP2_RESULT_REG);
2607 /* if this isr has no bank i.e. is going to
2608 run with bank 0 , then we need to save more
2610 if (!SPEC_BANK (sym->etype))
2613 /* if this function does not call any other
2614 function then we can be economical and
2615 save only those registers that are used */
2620 /* if any registers used */
2623 /* save the registers used */
2624 for (i = 0; i < sym->regsUsed->size; i++)
2626 if (bitVectBitValue (sym->regsUsed, i) ||
2627 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2628 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2635 /* this function has a function call cannot
2636 determines register usage so we will have to push the
2638 saveRBank (0, ic, FALSE);
2643 /* This ISR uses a non-zero bank.
2645 * We assume that the bank is available for our
2648 * However, if this ISR calls a function which uses some
2649 * other bank, we must save that bank entirely.
2651 unsigned long banksToSave = 0;
2656 #define MAX_REGISTER_BANKS 4
2661 for (i = ic; i; i = i->next)
2663 if (i->op == ENDFUNCTION)
2665 /* we got to the end OK. */
2673 detype = getSpec(operandType (IC_LEFT(i)));
2675 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2677 /* Mark this bank for saving. */
2678 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2680 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2684 banksToSave |= (1 << SPEC_BANK(detype));
2687 /* And note that we don't need to do it in
2695 /* This is a mess; we have no idea what
2696 * register bank the called function might
2699 * The only thing I can think of to do is
2700 * throw a warning and hope.
2702 werror(W_FUNCPTR_IN_USING_ISR);
2706 if (banksToSave && options.useXstack)
2708 /* Since we aren't passing it an ic,
2709 * saveRBank will assume r0 is available to abuse.
2711 * So switch to our (trashable) bank now, so
2712 * the caller's R0 isn't trashed.
2714 emitcode ("push", "psw");
2715 emitcode ("mov", "psw,#0x%02x",
2716 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2720 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2722 if (banksToSave & (1 << ix))
2724 saveRBank(ix, NULL, FALSE);
2728 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2733 /* if callee-save to be used for this function
2734 then save the registers being used in this function */
2735 if (sym->calleeSave)
2739 /* if any registers used */
2742 /* save the registers used */
2743 for (i = 0; i < sym->regsUsed->size; i++)
2745 if (bitVectBitValue (sym->regsUsed, i) ||
2746 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2748 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2756 /* set the register bank to the desired value */
2757 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2760 emitcode ("push", "psw");
2761 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2764 if (IS_RENT (sym->etype) || options.stackAuto)
2767 if (options.useXstack)
2769 emitcode ("mov", "r0,%s", spname);
2770 emitcode ("mov", "a,_bp");
2771 emitcode ("movx", "@r0,a");
2772 emitcode ("inc", "%s", spname);
2776 /* set up the stack */
2777 emitcode ("push", "_bp"); /* save the callers stack */
2779 emitcode ("mov", "_bp,%s", spname);
2782 /* adjust the stack for the function */
2788 werror (W_STACK_OVERFLOW, sym->name);
2790 if (i > 3 && sym->recvSize < 4)
2793 emitcode ("mov", "a,sp");
2794 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2795 emitcode ("mov", "sp,a");
2800 emitcode ("inc", "sp");
2806 emitcode ("mov", "a,_spx");
2807 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2808 emitcode ("mov", "_spx,a");
2813 /*-----------------------------------------------------------------*/
2814 /* genEndFunction - generates epilogue for functions */
2815 /*-----------------------------------------------------------------*/
2817 genEndFunction (iCode * ic)
2819 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2821 D (emitcode (";", "genEndFunction "););
2823 if (SPEC_NAKED(sym->etype))
2825 emitcode(";", "naked function: no epilogue.");
2829 if (IS_RENT (sym->etype) || options.stackAuto)
2831 emitcode ("mov", "%s,_bp", spname);
2834 /* if use external stack but some variables were
2835 added to the local stack then decrement the
2837 if (options.useXstack && sym->stack)
2839 emitcode ("mov", "a,sp");
2840 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2841 emitcode ("mov", "sp,a");
2845 if ((IS_RENT (sym->etype) || options.stackAuto))
2847 if (options.useXstack)
2849 emitcode ("mov", "r0,%s", spname);
2850 emitcode ("movx", "a,@r0");
2851 emitcode ("mov", "_bp,a");
2852 emitcode ("dec", "%s", spname);
2856 emitcode ("pop", "_bp");
2860 /* restore the register bank */
2861 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2863 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2864 || !options.useXstack)
2866 /* Special case of ISR using non-zero bank with useXstack
2869 emitcode ("pop", "psw");
2873 if (IS_ISR (sym->etype))
2876 /* now we need to restore the registers */
2877 /* if this isr has no bank i.e. is going to
2878 run with bank 0 , then we need to save more
2880 if (!SPEC_BANK (sym->etype))
2882 /* if this function does not call any other
2883 function then we can be economical and
2884 save only those registers that are used */
2889 /* if any registers used */
2892 /* save the registers used */
2893 for (i = sym->regsUsed->size; i >= 0; i--)
2895 if (bitVectBitValue (sym->regsUsed, i) ||
2896 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2897 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2904 /* this function has a function call cannot
2905 determines register usage so we will have to pop the
2907 unsaveRBank (0, ic, FALSE);
2912 /* This ISR uses a non-zero bank.
2914 * Restore any register banks saved by genFunction
2917 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2920 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2922 if (savedBanks & (1 << ix))
2924 unsaveRBank(ix, NULL, FALSE);
2928 if (options.useXstack)
2930 /* Restore bank AFTER calling unsaveRBank,
2931 * since it can trash r0.
2933 emitcode ("pop", "psw");
2937 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2939 if (options.stack10bit)
2941 emitcode ("pop", DP2_RESULT_REG);
2942 emitcode ("pop", "dpx1");
2943 emitcode ("pop", "dph1");
2944 emitcode ("pop", "dpl1");
2946 emitcode ("pop", "dps");
2947 emitcode ("pop", "dpx");
2949 if (!inExcludeList ("dph"))
2950 emitcode ("pop", "dph");
2951 if (!inExcludeList ("dpl"))
2952 emitcode ("pop", "dpl");
2953 if (!inExcludeList ("b"))
2954 emitcode ("pop", "b");
2955 if (!inExcludeList ("acc"))
2956 emitcode ("pop", "acc");
2958 if (SPEC_CRTCL (sym->etype))
2959 emitcode ("setb", "ea");
2961 /* if debug then send end of function */
2962 if (options.debug && currFunc) {
2964 emitcode ("", "C$%s$%d$%d$%d ==.",
2965 FileBaseName (ic->filename), currFunc->lastLine,
2966 ic->level, ic->block);
2967 if (IS_STATIC (currFunc->etype))
2968 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2970 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2974 emitcode ("reti", "");
2978 if (SPEC_CRTCL (sym->etype))
2979 emitcode ("setb", "ea");
2981 if (sym->calleeSave)
2985 /* if any registers used */
2988 /* save the registers used */
2989 for (i = sym->regsUsed->size; i >= 0; i--)
2991 if (bitVectBitValue (sym->regsUsed, i) ||
2992 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2993 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2999 /* if debug then send end of function */
3000 if (options.debug && currFunc)
3003 emitcode ("", "C$%s$%d$%d$%d ==.",
3004 FileBaseName (ic->filename), currFunc->lastLine,
3005 ic->level, ic->block);
3006 if (IS_STATIC (currFunc->etype))
3007 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3009 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3013 emitcode ("ret", "");
3018 /*-----------------------------------------------------------------*/
3019 /* genRet - generate code for return statement */
3020 /*-----------------------------------------------------------------*/
3024 int size, offset = 0, pushed = 0;
3026 D (emitcode (";", "genRet ");
3029 /* if we have no return value then
3030 just generate the "ret" */
3034 /* we have something to return then
3035 move the return value into place */
3036 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3037 size = AOP_SIZE (IC_LEFT (ic));
3039 _startLazyDPSEvaluation ();
3043 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3045 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3046 FALSE, TRUE, FALSE);
3047 emitcode ("push", "%s", l);
3052 /* Since A is the last element of fReturn,
3053 * is is OK to clobber it in the aopGet.
3055 l = aopGet (AOP (IC_LEFT (ic)), offset,
3056 FALSE, FALSE, TRUE);
3057 if (strcmp (fReturn[offset], l))
3058 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3061 _endLazyDPSEvaluation ();
3068 if (strcmp (fReturn[pushed], "a"))
3069 emitcode ("pop", fReturn[pushed]);
3071 emitcode ("pop", "acc");
3074 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3077 /* generate a jump to the return label
3078 if the next is not the return statement */
3079 if (!(ic->next && ic->next->op == LABEL &&
3080 IC_LABEL (ic->next) == returnLabel))
3082 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3086 /*-----------------------------------------------------------------*/
3087 /* genLabel - generates a label */
3088 /*-----------------------------------------------------------------*/
3090 genLabel (iCode * ic)
3092 /* special case never generate */
3093 if (IC_LABEL (ic) == entryLabel)
3096 D (emitcode (";", "genLabel ");
3099 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3102 /*-----------------------------------------------------------------*/
3103 /* genGoto - generates a ljmp */
3104 /*-----------------------------------------------------------------*/
3106 genGoto (iCode * ic)
3108 D (emitcode (";", "genGoto ");
3110 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3113 /*-----------------------------------------------------------------*/
3114 /* findLabelBackwards: walks back through the iCode chain looking */
3115 /* for the given label. Returns number of iCode instructions */
3116 /* between that label and given ic. */
3117 /* Returns zero if label not found. */
3118 /*-----------------------------------------------------------------*/
3120 findLabelBackwards (iCode * ic, int key)
3129 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3131 /* printf("findLabelBackwards = %d\n", count); */
3139 /*-----------------------------------------------------------------*/
3140 /* genPlusIncr :- does addition with increment if possible */
3141 /*-----------------------------------------------------------------*/
3143 genPlusIncr (iCode * ic)
3145 unsigned int icount;
3146 unsigned int size = getDataSize (IC_RESULT (ic));
3148 /* will try to generate an increment */
3149 /* if the right side is not a literal
3151 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3154 /* if the literal value of the right hand side
3155 is greater than 4 then it is not worth it */
3156 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3159 /* if increment 16 bits in register */
3161 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3162 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3163 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3171 /* If the next instruction is a goto and the goto target
3172 * is <= 5 instructions previous to this, we can generate
3173 * jumps straight to that target.
3175 if (ic->next && ic->next->op == GOTO
3176 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3179 emitcode (";", "tail increment optimized (range %d)", labelRange);
3180 tlbl = IC_LABEL (ic->next);
3185 tlbl = newiTempLabel (NULL);
3188 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3189 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3190 IS_AOP_PREG (IC_RESULT (ic)))
3191 emitcode ("cjne", "%s,#0x00,%05d$"
3192 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3196 emitcode ("clr", "a");
3197 emitcode ("cjne", "a,%s,%05d$"
3198 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3202 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3205 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3206 IS_AOP_PREG (IC_RESULT (ic)))
3207 emitcode ("cjne", "%s,#0x00,%05d$"
3208 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3211 emitcode ("cjne", "a,%s,%05d$"
3212 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3215 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3219 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3220 IS_AOP_PREG (IC_RESULT (ic)))
3221 emitcode ("cjne", "%s,#0x00,%05d$"
3222 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3226 emitcode ("cjne", "a,%s,%05d$"
3227 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3230 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3235 emitcode ("", "%05d$:", tlbl->key + 100);
3240 /* if the sizes are greater than 1 then we cannot */
3241 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3242 AOP_SIZE (IC_LEFT (ic)) > 1)
3245 /* we can if the aops of the left & result match or
3246 if they are in registers and the registers are the
3249 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3250 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3251 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3256 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3257 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3258 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3263 _startLazyDPSEvaluation ();
3266 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3268 _endLazyDPSEvaluation ();
3277 /*-----------------------------------------------------------------*/
3278 /* outBitAcc - output a bit in acc */
3279 /*-----------------------------------------------------------------*/
3281 outBitAcc (operand * result)
3283 symbol *tlbl = newiTempLabel (NULL);
3284 /* if the result is a bit */
3285 if (AOP_TYPE (result) == AOP_CRY)
3287 aopPut (AOP (result), "a", 0);
3291 emitcode ("jz", "%05d$", tlbl->key + 100);
3292 emitcode ("mov", "a,%s", one);
3293 emitcode ("", "%05d$:", tlbl->key + 100);
3298 /*-----------------------------------------------------------------*/
3299 /* genPlusBits - generates code for addition of two bits */
3300 /*-----------------------------------------------------------------*/
3302 genPlusBits (iCode * ic)
3304 D (emitcode (";", "genPlusBits ");
3306 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3308 symbol *lbl = newiTempLabel (NULL);
3309 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3310 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3311 emitcode ("cpl", "c");
3312 emitcode ("", "%05d$:", (lbl->key + 100));
3313 outBitC (IC_RESULT (ic));
3317 emitcode ("clr", "a");
3318 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3319 emitcode ("rlc", "a");
3320 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3321 emitcode ("addc", "a,#0x00");
3322 outAcc (IC_RESULT (ic));
3327 adjustArithmeticResult (iCode * ic)
3329 if (opIsGptr (IC_RESULT (ic)) &&
3330 opIsGptr (IC_LEFT (ic)) &&
3331 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3333 aopPut (AOP (IC_RESULT (ic)),
3334 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3338 if (opIsGptr (IC_RESULT (ic)) &&
3339 opIsGptr (IC_RIGHT (ic)) &&
3340 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3342 aopPut (AOP (IC_RESULT (ic)),
3343 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3347 if (opIsGptr (IC_RESULT (ic)) &&
3348 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3349 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3350 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3351 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3354 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3355 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3359 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3360 // (because all three operands are in far space).
3361 #define AOP_OP_3(ic) \
3362 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3363 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3364 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3365 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3366 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3367 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3369 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3371 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3374 // Macro to aopOp all three operands of an ic. If this cannot be done,
3375 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3376 // will be set TRUE. The caller must then handle the case specially, noting
3377 // that the IC_RESULT operand is not aopOp'd.
3378 #define AOP_OP_3_NOFATAL(ic, rc) \
3379 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3380 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3381 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3382 isOperandInFarSpace(IC_RESULT(ic))) \
3384 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3389 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3390 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3392 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3393 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3395 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3397 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3401 // aopOp the left & right operands of an ic.
3402 #define AOP_OP_2(ic) \
3403 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3404 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3406 // convienience macro.
3407 #define AOP_SET_LOCALS(ic) \
3408 left = IC_LEFT(ic); \
3409 right = IC_RIGHT(ic); \
3410 result = IC_RESULT(ic);
3413 // Given an integer value of pushedSize bytes on the stack,
3414 // adjust it to be resultSize bytes, either by discarding
3415 // the most significant bytes or by zero-padding.
3417 // On exit from this macro, pushedSize will have been adjusted to
3418 // equal resultSize, and ACC may be trashed.
3419 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3420 /* If the pushed data is bigger than the result, \
3421 * simply discard unused bytes. Icky, but works. \
3423 while (pushedSize > resultSize) \
3425 D (emitcode (";", "discarding unused result byte."););\
3426 emitcode ("pop", "acc"); \
3429 if (pushedSize < resultSize) \
3431 emitcode ("clr", "a"); \
3432 /* Conversly, we haven't pushed enough here. \
3433 * just zero-pad, and all is well. \
3435 while (pushedSize < resultSize) \
3437 emitcode("push", "acc"); \
3441 assert(pushedSize == resultSize);
3443 /*-----------------------------------------------------------------*/
3444 /* genPlus - generates code for addition */
3445 /*-----------------------------------------------------------------*/
3447 genPlus (iCode * ic)
3449 int size, offset = 0;
3450 bool pushResult = FALSE;
3453 D (emitcode (";", "genPlus "););
3455 /* special cases :- */
3457 AOP_OP_3_NOFATAL (ic, pushResult);
3460 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3465 /* if literal, literal on the right or
3466 if left requires ACC or right is already
3468 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3469 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3470 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3472 operand *t = IC_RIGHT (ic);
3473 IC_RIGHT (ic) = IC_LEFT (ic);
3475 emitcode (";", "Swapped plus args.");
3478 /* if both left & right are in bit
3480 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3481 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3487 /* if left in bit space & right literal */
3488 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3489 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3491 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3492 /* if result in bit space */
3493 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3495 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3496 emitcode ("cpl", "c");
3497 outBitC (IC_RESULT (ic));
3501 size = getDataSize (IC_RESULT (ic));
3502 _startLazyDPSEvaluation ();
3505 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3506 emitcode ("addc", "a,#00");
3507 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3509 _endLazyDPSEvaluation ();
3514 /* if I can do an increment instead
3515 of add then GOOD for ME */
3516 if (genPlusIncr (ic) == TRUE)
3518 emitcode (";", "did genPlusIncr");
3523 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3525 _startLazyDPSEvaluation ();
3528 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3530 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3532 emitcode ("add", "a,%s",
3533 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3535 emitcode ("addc", "a,%s",
3536 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3540 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3542 /* right is going to use ACC or we would have taken the
3545 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3547 D(emitcode(";", "+ AOP_ACC special case."););
3548 emitcode("xch", "a, %s", DP2_RESULT_REG);
3550 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3553 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3556 emitcode("add", "a, %s", DP2_RESULT_REG);
3560 emitcode ("add", "a,%s",
3561 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3566 emitcode ("addc", "a,%s",
3567 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3572 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3576 emitcode ("push", "acc");
3580 _endLazyDPSEvaluation ();
3584 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3586 size = getDataSize (IC_LEFT (ic));
3587 rSize = getDataSize (IC_RESULT (ic));
3589 ADJUST_PUSHED_RESULT(size, rSize);
3591 _startLazyDPSEvaluation ();
3594 emitcode ("pop", "acc");
3595 aopPut (AOP (IC_RESULT (ic)), "a", size);
3597 _endLazyDPSEvaluation ();
3600 adjustArithmeticResult (ic);
3603 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3604 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3605 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3608 /*-----------------------------------------------------------------*/
3609 /* genMinusDec :- does subtraction with deccrement if possible */
3610 /*-----------------------------------------------------------------*/
3612 genMinusDec (iCode * ic)
3614 unsigned int icount;
3615 unsigned int size = getDataSize (IC_RESULT (ic));
3617 /* will try to generate an increment */
3618 /* if the right side is not a literal
3620 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3623 /* if the literal value of the right hand side
3624 is greater than 4 then it is not worth it */
3625 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3628 /* if decrement 16 bits in register */
3629 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3630 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3631 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3639 /* If the next instruction is a goto and the goto target
3640 * is <= 5 instructions previous to this, we can generate
3641 * jumps straight to that target.
3643 if (ic->next && ic->next->op == GOTO
3644 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3647 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3648 tlbl = IC_LABEL (ic->next);
3653 tlbl = newiTempLabel (NULL);
3657 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3658 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3659 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3660 IS_AOP_PREG (IC_RESULT (ic)))
3661 emitcode ("cjne", "%s,#0xff,%05d$"
3662 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3666 emitcode ("mov", "a,#0xff");
3667 emitcode ("cjne", "a,%s,%05d$"
3668 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3671 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3674 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3676 IS_AOP_PREG (IC_RESULT (ic)))
3677 emitcode ("cjne", "%s,#0xff,%05d$"
3678 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3682 emitcode ("cjne", "a,%s,%05d$"
3683 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3686 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3690 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3691 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3692 IS_AOP_PREG (IC_RESULT (ic)))
3693 emitcode ("cjne", "%s,#0xff,%05d$"
3694 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3698 emitcode ("cjne", "a,%s,%05d$"
3699 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3702 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3706 emitcode ("", "%05d$:", tlbl->key + 100);
3711 /* if the sizes are greater than 1 then we cannot */
3712 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3713 AOP_SIZE (IC_LEFT (ic)) > 1)
3716 /* we can if the aops of the left & result match or
3717 if they are in registers and the registers are the
3720 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3721 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3722 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3725 _startLazyDPSEvaluation ();
3728 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3730 _endLazyDPSEvaluation ();
3738 /*-----------------------------------------------------------------*/
3739 /* addSign - complete with sign */
3740 /*-----------------------------------------------------------------*/
3742 addSign (operand * result, int offset, int sign)
3744 int size = (getDataSize (result) - offset);
3747 _startLazyDPSEvaluation();
3750 emitcode ("rlc", "a");
3751 emitcode ("subb", "a,acc");
3754 aopPut (AOP (result), "a", offset++);
3761 aopPut (AOP (result), zero, offset++);
3764 _endLazyDPSEvaluation();
3768 /*-----------------------------------------------------------------*/
3769 /* genMinusBits - generates code for subtraction of two bits */
3770 /*-----------------------------------------------------------------*/
3772 genMinusBits (iCode * ic)
3774 symbol *lbl = newiTempLabel (NULL);
3776 D (emitcode (";", "genMinusBits "););
3778 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3780 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3781 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3782 emitcode ("cpl", "c");
3783 emitcode ("", "%05d$:", (lbl->key + 100));
3784 outBitC (IC_RESULT (ic));
3788 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3789 emitcode ("subb", "a,acc");
3790 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3791 emitcode ("inc", "a");
3792 emitcode ("", "%05d$:", (lbl->key + 100));
3793 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3794 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3798 /*-----------------------------------------------------------------*/
3799 /* genMinus - generates code for subtraction */
3800 /*-----------------------------------------------------------------*/
3802 genMinus (iCode * ic)
3804 int size, offset = 0;
3806 unsigned long lit = 0L;
3807 bool pushResult = FALSE;
3809 D (emitcode (";", "genMinus "););
3811 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3812 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3813 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3814 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3820 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3822 /* special cases :- */
3823 /* if both left & right are in bit space */
3824 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3825 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3831 /* if I can do an decrement instead
3832 of subtract then GOOD for ME */
3833 if (genMinusDec (ic) == TRUE)
3838 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3840 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3846 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3851 /* if literal, add a,#-lit, else normal subb */
3852 _startLazyDPSEvaluation ();
3855 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3856 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3857 emitcode ("subb", "a,%s",
3858 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3861 /* first add without previous c */
3863 if (!size && lit==-1) {
3864 emitcode ("dec", "a");
3866 emitcode ("add", "a,#0x%02x",
3867 (unsigned int) (lit & 0x0FFL));
3870 emitcode ("addc", "a,#0x%02x",
3871 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3877 emitcode ("push", "acc");
3881 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3885 _endLazyDPSEvaluation ();
3889 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3891 size = getDataSize (IC_LEFT (ic));
3892 rSize = getDataSize (IC_RESULT (ic));
3894 ADJUST_PUSHED_RESULT(size, rSize);
3896 _startLazyDPSEvaluation ();
3899 emitcode ("pop", "acc");
3900 aopPut (AOP (IC_RESULT (ic)), "a", size);
3902 _endLazyDPSEvaluation ();
3905 adjustArithmeticResult (ic);
3908 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3909 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3910 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3914 /*-----------------------------------------------------------------*/
3915 /* genMultbits :- multiplication of bits */
3916 /*-----------------------------------------------------------------*/
3918 genMultbits (operand * left,
3922 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3923 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3928 /*-----------------------------------------------------------------*/
3929 /* genMultOneByte : 8*8=8/16 bit multiplication */
3930 /*-----------------------------------------------------------------*/
3932 genMultOneByte (operand * left,
3936 sym_link *opetype = operandType (result);
3938 int size=AOP_SIZE(result);
3940 if (size<1 || size>2) {
3941 // this should never happen
3942 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3943 AOP_SIZE(result), __FILE__, lineno);
3947 /* (if two literals: the value is computed before) */
3948 /* if one literal, literal on the right */
3949 if (AOP_TYPE (left) == AOP_LIT)
3954 emitcode (";", "swapped left and right");
3957 if (SPEC_USIGN(opetype)
3958 // ignore the sign of left and right, what else can we do?
3959 || (SPEC_USIGN(operandType(left)) &&
3960 SPEC_USIGN(operandType(right)))) {
3961 // just an unsigned 8*8=8/16 multiply
3962 //emitcode (";","unsigned");
3963 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3964 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3965 emitcode ("mul", "ab");
3966 aopPut (AOP (result), "a", 0);
3968 aopPut (AOP (result), "b", 1);
3973 // we have to do a signed multiply
3975 emitcode (";", "signed");
3976 emitcode ("clr", "F0"); // reset sign flag
3977 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3979 lbl=newiTempLabel(NULL);
3980 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3981 // left side is negative, 8-bit two's complement, this fails for -128
3982 emitcode ("setb", "F0"); // set sign flag
3983 emitcode ("cpl", "a");
3984 emitcode ("inc", "a");
3986 emitcode ("", "%05d$:", lbl->key+100);
3989 if (AOP_TYPE(right)==AOP_LIT) {
3990 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3991 /* AND literal negative */
3992 if ((int) val < 0) {
3993 emitcode ("cpl", "F0"); // complement sign flag
3994 emitcode ("mov", "b,#0x%02x", -val);
3996 emitcode ("mov", "b,#0x%02x", val);
3999 lbl=newiTempLabel(NULL);
4000 emitcode ("mov", "b,a");
4001 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4002 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4003 // right side is negative, 8-bit two's complement
4004 emitcode ("cpl", "F0"); // complement sign flag
4005 emitcode ("cpl", "a");
4006 emitcode ("inc", "a");
4007 emitcode ("", "%05d$:", lbl->key+100);
4009 emitcode ("mul", "ab");
4011 lbl=newiTempLabel(NULL);
4012 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4013 // only ONE op was negative, we have to do a 8/16-bit two's complement
4014 emitcode ("cpl", "a"); // lsb
4016 emitcode ("inc", "a");
4018 emitcode ("add", "a,#1");
4019 emitcode ("xch", "a,b");
4020 emitcode ("cpl", "a"); // msb
4021 emitcode ("addc", "a,#0");
4022 emitcode ("xch", "a,b");
4025 emitcode ("", "%05d$:", lbl->key+100);
4026 aopPut (AOP (result), "a", 0);
4028 aopPut (AOP (result), "b", 1);
4032 /*-----------------------------------------------------------------*/
4033 /* genMult - generates code for multiplication */
4034 /*-----------------------------------------------------------------*/
4036 genMult (iCode * ic)
4038 operand *left = IC_LEFT (ic);
4039 operand *right = IC_RIGHT (ic);
4040 operand *result = IC_RESULT (ic);
4042 D (emitcode (";", "genMult "););
4044 /* assign the amsops */
4047 /* special cases first */
4049 if (AOP_TYPE (left) == AOP_CRY &&
4050 AOP_TYPE (right) == AOP_CRY)
4052 genMultbits (left, right, result);
4056 /* if both are of size == 1 */
4057 if (AOP_SIZE (left) == 1 &&
4058 AOP_SIZE (right) == 1)
4060 genMultOneByte (left, right, result);
4064 /* should have been converted to function call */
4068 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4069 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4070 freeAsmop (result, NULL, ic, TRUE);
4073 /*-----------------------------------------------------------------*/
4074 /* genDivbits :- division of bits */
4075 /*-----------------------------------------------------------------*/
4077 genDivbits (operand * left,
4084 /* the result must be bit */
4085 LOAD_AB_FOR_DIV (left, right, l);
4086 emitcode ("div", "ab");
4087 emitcode ("rrc", "a");
4088 aopPut (AOP (result), "c", 0);
4091 /*-----------------------------------------------------------------*/
4092 /* genDivOneByte : 8 bit division */
4093 /*-----------------------------------------------------------------*/
4095 genDivOneByte (operand * left,
4099 sym_link *opetype = operandType (result);
4104 size = AOP_SIZE (result) - 1;
4106 /* signed or unsigned */
4107 if (SPEC_USIGN (opetype))
4109 /* unsigned is easy */
4110 LOAD_AB_FOR_DIV (left, right, l);
4111 emitcode ("div", "ab");
4112 aopPut (AOP (result), "a", 0);
4114 aopPut (AOP (result), zero, offset++);
4118 /* signed is a little bit more difficult */
4120 /* save the signs of the operands */
4121 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4123 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4124 emitcode ("push", "acc"); /* save it on the stack */
4126 /* now sign adjust for both left & right */
4127 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4129 lbl = newiTempLabel (NULL);
4130 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4131 emitcode ("cpl", "a");
4132 emitcode ("inc", "a");
4133 emitcode ("", "%05d$:", (lbl->key + 100));
4134 emitcode ("mov", "b,a");
4136 /* sign adjust left side */
4137 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4140 lbl = newiTempLabel (NULL);
4141 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4142 emitcode ("cpl", "a");
4143 emitcode ("inc", "a");
4144 emitcode ("", "%05d$:", (lbl->key + 100));
4146 /* now the division */
4147 emitcode ("nop", "; workaround for DS80C390 div bug.");
4148 emitcode ("div", "ab");
4149 /* we are interested in the lower order
4151 emitcode ("mov", "b,a");
4152 lbl = newiTempLabel (NULL);
4153 emitcode ("pop", "acc");
4154 /* if there was an over flow we don't
4155 adjust the sign of the result */
4156 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4157 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4159 emitcode ("clr", "a");
4160 emitcode ("subb", "a,b");
4161 emitcode ("mov", "b,a");
4162 emitcode ("", "%05d$:", (lbl->key + 100));
4164 /* now we are done */
4165 aopPut (AOP (result), "b", 0);
4168 emitcode ("mov", "c,b.7");
4169 emitcode ("subb", "a,acc");
4172 aopPut (AOP (result), "a", offset++);
4176 /*-----------------------------------------------------------------*/
4177 /* genDiv - generates code for division */
4178 /*-----------------------------------------------------------------*/
4182 operand *left = IC_LEFT (ic);
4183 operand *right = IC_RIGHT (ic);
4184 operand *result = IC_RESULT (ic);
4186 D (emitcode (";", "genDiv ");
4189 /* assign the amsops */
4192 /* special cases first */
4194 if (AOP_TYPE (left) == AOP_CRY &&
4195 AOP_TYPE (right) == AOP_CRY)
4197 genDivbits (left, right, result);
4201 /* if both are of size == 1 */
4202 if (AOP_SIZE (left) == 1 &&
4203 AOP_SIZE (right) == 1)
4205 genDivOneByte (left, right, result);
4209 /* should have been converted to function call */
4212 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4214 freeAsmop (result, NULL, ic, TRUE);
4217 /*-----------------------------------------------------------------*/
4218 /* genModbits :- modulus of bits */
4219 /*-----------------------------------------------------------------*/
4221 genModbits (operand * left,
4228 /* the result must be bit */
4229 LOAD_AB_FOR_DIV (left, right, l);
4230 emitcode ("div", "ab");
4231 emitcode ("mov", "a,b");
4232 emitcode ("rrc", "a");
4233 aopPut (AOP (result), "c", 0);
4236 /*-----------------------------------------------------------------*/
4237 /* genModOneByte : 8 bit modulus */
4238 /*-----------------------------------------------------------------*/
4240 genModOneByte (operand * left,
4244 sym_link *opetype = operandType (result);
4248 /* signed or unsigned */
4249 if (SPEC_USIGN (opetype))
4251 /* unsigned is easy */
4252 LOAD_AB_FOR_DIV (left, right, l);
4253 emitcode ("div", "ab");
4254 aopPut (AOP (result), "b", 0);
4258 /* signed is a little bit more difficult */
4260 /* save the signs of the operands */
4261 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4264 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4265 emitcode ("push", "acc"); /* save it on the stack */
4267 /* now sign adjust for both left & right */
4268 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4271 lbl = newiTempLabel (NULL);
4272 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4273 emitcode ("cpl", "a");
4274 emitcode ("inc", "a");
4275 emitcode ("", "%05d$:", (lbl->key + 100));
4276 emitcode ("mov", "b,a");
4278 /* sign adjust left side */
4279 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4282 lbl = newiTempLabel (NULL);
4283 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4284 emitcode ("cpl", "a");
4285 emitcode ("inc", "a");
4286 emitcode ("", "%05d$:", (lbl->key + 100));
4288 /* now the multiplication */
4289 emitcode ("nop", "; workaround for DS80C390 div bug.");
4290 emitcode ("div", "ab");
4291 /* we are interested in the lower order
4293 lbl = newiTempLabel (NULL);
4294 emitcode ("pop", "acc");
4295 /* if there was an over flow we don't
4296 adjust the sign of the result */
4297 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4298 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4300 emitcode ("clr", "a");
4301 emitcode ("subb", "a,b");
4302 emitcode ("mov", "b,a");
4303 emitcode ("", "%05d$:", (lbl->key + 100));
4305 /* now we are done */
4306 aopPut (AOP (result), "b", 0);
4310 /*-----------------------------------------------------------------*/
4311 /* genMod - generates code for division */
4312 /*-----------------------------------------------------------------*/
4316 operand *left = IC_LEFT (ic);
4317 operand *right = IC_RIGHT (ic);
4318 operand *result = IC_RESULT (ic);
4320 D (emitcode (";", "genMod ");
4323 /* assign the amsops */
4326 /* special cases first */
4328 if (AOP_TYPE (left) == AOP_CRY &&
4329 AOP_TYPE (right) == AOP_CRY)
4331 genModbits (left, right, result);
4335 /* if both are of size == 1 */
4336 if (AOP_SIZE (left) == 1 &&
4337 AOP_SIZE (right) == 1)
4339 genModOneByte (left, right, result);
4343 /* should have been converted to function call */
4347 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4348 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4349 freeAsmop (result, NULL, ic, TRUE);
4352 /*-----------------------------------------------------------------*/
4353 /* genIfxJump :- will create a jump depending on the ifx */
4354 /*-----------------------------------------------------------------*/
4356 genIfxJump (iCode * ic, char *jval)
4359 symbol *tlbl = newiTempLabel (NULL);
4362 D (emitcode (";", "genIfxJump ");
4365 /* if true label then we jump if condition
4369 jlbl = IC_TRUE (ic);
4370 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4371 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4375 /* false label is present */
4376 jlbl = IC_FALSE (ic);
4377 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4378 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4380 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4381 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4383 emitcode (inst, "%05d$", tlbl->key + 100);
4384 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4385 emitcode ("", "%05d$:", tlbl->key + 100);
4387 /* mark the icode as generated */
4391 /*-----------------------------------------------------------------*/
4392 /* genCmp :- greater or less than comparison */
4393 /*-----------------------------------------------------------------*/
4395 genCmp (operand * left, operand * right,
4396 iCode * ic, iCode * ifx, int sign)
4398 int size, offset = 0;
4399 unsigned long lit = 0L;
4402 D (emitcode (";", "genCmp");
4405 result = IC_RESULT (ic);
4407 /* if left & right are bit variables */
4408 if (AOP_TYPE (left) == AOP_CRY &&
4409 AOP_TYPE (right) == AOP_CRY)
4411 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4412 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4416 /* subtract right from left if at the
4417 end the carry flag is set then we know that
4418 left is greater than right */
4419 size = max (AOP_SIZE (left), AOP_SIZE (right));
4421 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4422 if ((size == 1) && !sign &&
4423 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4425 symbol *lbl = newiTempLabel (NULL);
4426 emitcode ("cjne", "%s,%s,%05d$",
4427 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4428 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4430 emitcode ("", "%05d$:", lbl->key + 100);
4434 if (AOP_TYPE (right) == AOP_LIT)
4436 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4437 /* optimize if(x < 0) or if(x >= 0) */
4446 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4448 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4449 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4451 aopOp (result, ic, FALSE, FALSE);
4453 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4455 freeAsmop (result, NULL, ic, TRUE);
4456 genIfxJump (ifx, "acc.7");
4461 emitcode ("rlc", "a");
4463 goto release_freedLR;
4471 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4472 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4473 emitcode (";", "genCmp #2");
4474 if (sign && (size == 0))
4476 emitcode (";", "genCmp #3");
4477 emitcode ("xrl", "a,#0x80");
4478 if (AOP_TYPE (right) == AOP_LIT)
4480 unsigned long lit = (unsigned long)
4481 floatFromVal (AOP (right)->aopu.aop_lit);
4482 emitcode (";", "genCmp #3.1");
4483 emitcode ("subb", "a,#0x%02x",
4484 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4488 emitcode (";", "genCmp #3.2");
4489 if (AOP_NEEDSACC (right))
4491 emitcode ("push", "acc");
4493 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4494 FALSE, FALSE, FALSE));
4495 emitcode ("xrl", "b,#0x80");
4496 if (AOP_NEEDSACC (right))
4498 emitcode ("pop", "acc");
4500 emitcode ("subb", "a,b");
4507 emitcode (";", "genCmp #4");
4508 if (AOP_NEEDSACC (right))
4511 emitcode (";", "genCmp #4.1");
4512 emitcode ("xch", "a, b");
4513 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4514 emitcode ("xch", "a, b");
4519 emitcode (";", "genCmp #4.2");
4520 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4523 emitcode ("subb", "a,%s", s);
4530 /* Don't need the left & right operands any more; do need the result. */
4531 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4532 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4534 aopOp (result, ic, FALSE, FALSE);
4538 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4544 /* if the result is used in the next
4545 ifx conditional branch then generate
4546 code a little differently */
4549 genIfxJump (ifx, "c");
4555 /* leave the result in acc */
4557 freeAsmop (result, NULL, ic, TRUE);
4560 /*-----------------------------------------------------------------*/
4561 /* genCmpGt :- greater than comparison */
4562 /*-----------------------------------------------------------------*/
4564 genCmpGt (iCode * ic, iCode * ifx)
4566 operand *left, *right;
4567 sym_link *letype, *retype;
4570 D (emitcode (";", "genCmpGt ");
4573 left = IC_LEFT (ic);
4574 right = IC_RIGHT (ic);
4576 letype = getSpec (operandType (left));
4577 retype = getSpec (operandType (right));
4578 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4580 /* assign the left & right amsops */
4583 genCmp (right, left, ic, ifx, sign);
4586 /*-----------------------------------------------------------------*/
4587 /* genCmpLt - less than comparisons */
4588 /*-----------------------------------------------------------------*/
4590 genCmpLt (iCode * ic, iCode * ifx)
4592 operand *left, *right;
4593 sym_link *letype, *retype;
4596 D (emitcode (";", "genCmpLt "););
4598 left = IC_LEFT (ic);
4599 right = IC_RIGHT (ic);
4601 letype = getSpec (operandType (left));
4602 retype = getSpec (operandType (right));
4603 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4605 /* assign the left & right amsops */
4608 genCmp (left, right, ic, ifx, sign);
4611 /*-----------------------------------------------------------------*/
4612 /* gencjneshort - compare and jump if not equal */
4613 /*-----------------------------------------------------------------*/
4615 gencjneshort (operand * left, operand * right, symbol * lbl)
4617 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4619 unsigned long lit = 0L;
4621 D (emitcode (";", "gencjneshort");
4624 /* if the left side is a literal or
4625 if the right is in a pointer register and left
4627 if ((AOP_TYPE (left) == AOP_LIT) ||
4628 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4635 if (AOP_TYPE (right) == AOP_LIT)
4636 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4638 if (opIsGptr (left) || opIsGptr (right))
4640 /* We are comparing a generic pointer to something.
4641 * Exclude the generic type byte from the comparison.
4644 D (emitcode (";", "cjneshort: generic ptr special case.");
4649 /* if the right side is a literal then anything goes */
4650 if (AOP_TYPE (right) == AOP_LIT &&
4651 AOP_TYPE (left) != AOP_DIR)
4655 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4657 emitcode ("cjne", "a,%s,%05d$",
4658 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4664 /* if the right side is in a register or in direct space or
4665 if the left is a pointer register & right is not */
4666 else if (AOP_TYPE (right) == AOP_REG ||
4667 AOP_TYPE (right) == AOP_DIR ||
4668 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4669 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4673 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4674 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4675 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4676 emitcode ("jnz", "%05d$", lbl->key + 100);
4678 emitcode ("cjne", "a,%s,%05d$",
4679 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4686 /* right is a pointer reg need both a & b */
4689 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4690 if (strcmp (l, "b"))
4691 emitcode ("mov", "b,%s", l);
4692 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4693 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4699 /*-----------------------------------------------------------------*/
4700 /* gencjne - compare and jump if not equal */
4701 /*-----------------------------------------------------------------*/
4703 gencjne (operand * left, operand * right, symbol * lbl)
4705 symbol *tlbl = newiTempLabel (NULL);
4707 D (emitcode (";", "gencjne");
4710 gencjneshort (left, right, lbl);
4712 emitcode ("mov", "a,%s", one);
4713 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4714 emitcode ("", "%05d$:", lbl->key + 100);
4715 emitcode ("clr", "a");
4716 emitcode ("", "%05d$:", tlbl->key + 100);
4719 /*-----------------------------------------------------------------*/
4720 /* genCmpEq - generates code for equal to */
4721 /*-----------------------------------------------------------------*/
4723 genCmpEq (iCode * ic, iCode * ifx)
4725 operand *left, *right, *result;
4727 D (emitcode (";", "genCmpEq ");
4731 AOP_SET_LOCALS (ic);
4733 /* if literal, literal on the right or
4734 if the right is in a pointer register and left
4736 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4737 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4739 operand *t = IC_RIGHT (ic);
4740 IC_RIGHT (ic) = IC_LEFT (ic);
4744 if (ifx && /* !AOP_SIZE(result) */
4745 OP_SYMBOL (result) &&
4746 OP_SYMBOL (result)->regType == REG_CND)
4749 /* if they are both bit variables */
4750 if (AOP_TYPE (left) == AOP_CRY &&
4751 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4753 if (AOP_TYPE (right) == AOP_LIT)
4755 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4758 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4759 emitcode ("cpl", "c");
4763 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4767 emitcode ("clr", "c");
4769 /* AOP_TYPE(right) == AOP_CRY */
4773 symbol *lbl = newiTempLabel (NULL);
4774 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4775 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4776 emitcode ("cpl", "c");
4777 emitcode ("", "%05d$:", (lbl->key + 100));
4779 /* if true label then we jump if condition
4781 tlbl = newiTempLabel (NULL);
4784 emitcode ("jnc", "%05d$", tlbl->key + 100);
4785 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4789 emitcode ("jc", "%05d$", tlbl->key + 100);
4790 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4792 emitcode ("", "%05d$:", tlbl->key + 100);
4796 tlbl = newiTempLabel (NULL);
4797 gencjneshort (left, right, tlbl);
4800 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4801 emitcode ("", "%05d$:", tlbl->key + 100);
4805 symbol *lbl = newiTempLabel (NULL);
4806 emitcode ("sjmp", "%05d$", lbl->key + 100);
4807 emitcode ("", "%05d$:", tlbl->key + 100);
4808 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4809 emitcode ("", "%05d$:", lbl->key + 100);
4812 /* mark the icode as generated */
4815 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4816 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4820 /* if they are both bit variables */
4821 if (AOP_TYPE (left) == AOP_CRY &&
4822 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4824 if (AOP_TYPE (right) == AOP_LIT)
4826 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4829 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4830 emitcode ("cpl", "c");
4834 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4838 emitcode ("clr", "c");
4840 /* AOP_TYPE(right) == AOP_CRY */
4844 symbol *lbl = newiTempLabel (NULL);
4845 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4846 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4847 emitcode ("cpl", "c");
4848 emitcode ("", "%05d$:", (lbl->key + 100));
4851 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4852 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4854 aopOp (result, ic, TRUE, FALSE);
4857 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4864 genIfxJump (ifx, "c");
4867 /* if the result is used in an arithmetic operation
4868 then put the result in place */
4873 gencjne (left, right, newiTempLabel (NULL));
4875 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4876 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4878 aopOp (result, ic, TRUE, FALSE);
4880 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4882 aopPut (AOP (result), "a", 0);
4887 genIfxJump (ifx, "a");
4890 /* if the result is used in an arithmetic operation
4891 then put the result in place */
4892 if (AOP_TYPE (result) != AOP_CRY)
4894 /* leave the result in acc */
4898 freeAsmop (result, NULL, ic, TRUE);
4901 /*-----------------------------------------------------------------*/
4902 /* ifxForOp - returns the icode containing the ifx for operand */
4903 /*-----------------------------------------------------------------*/
4905 ifxForOp (operand * op, iCode * ic)
4907 /* if true symbol then needs to be assigned */
4908 if (IS_TRUE_SYMOP (op))
4911 /* if this has register type condition and
4912 the next instruction is ifx with the same operand
4913 and live to of the operand is upto the ifx only then */
4915 ic->next->op == IFX &&
4916 IC_COND (ic->next)->key == op->key &&
4917 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4922 /*-----------------------------------------------------------------*/
4923 /* genAndOp - for && operation */
4924 /*-----------------------------------------------------------------*/
4926 genAndOp (iCode * ic)
4928 operand *left, *right, *result;
4931 D (emitcode (";", "genAndOp "););
4933 /* note here that && operations that are in an
4934 if statement are taken away by backPatchLabels
4935 only those used in arthmetic operations remain */
4937 AOP_SET_LOCALS (ic);
4939 /* if both are bit variables */
4940 if (AOP_TYPE (left) == AOP_CRY &&
4941 AOP_TYPE (right) == AOP_CRY)
4943 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4944 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4946 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4948 aopOp (result,ic,FALSE, FALSE);
4953 tlbl = newiTempLabel (NULL);
4955 emitcode ("jz", "%05d$", tlbl->key + 100);
4957 emitcode ("", "%05d$:", tlbl->key + 100);
4958 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4959 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4961 aopOp (result,ic,FALSE, FALSE);
4964 freeAsmop (result, NULL, ic, TRUE);
4968 /*-----------------------------------------------------------------*/
4969 /* genOrOp - for || operation */
4970 /*-----------------------------------------------------------------*/
4972 genOrOp (iCode * ic)
4974 operand *left, *right, *result;
4977 D (emitcode (";", "genOrOp "););
4979 /* note here that || operations that are in an
4980 if statement are taken away by backPatchLabels
4981 only those used in arthmetic operations remain */
4983 AOP_SET_LOCALS (ic);
4985 /* if both are bit variables */
4986 if (AOP_TYPE (left) == AOP_CRY &&
4987 AOP_TYPE (right) == AOP_CRY)
4989 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4990 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4991 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4992 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4994 aopOp (result,ic,FALSE, FALSE);
5000 tlbl = newiTempLabel (NULL);
5002 emitcode ("jnz", "%05d$", tlbl->key + 100);
5004 emitcode ("", "%05d$:", tlbl->key + 100);
5005 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5006 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5008 aopOp (result,ic,FALSE, FALSE);
5013 freeAsmop (result, NULL, ic, TRUE);
5016 /*-----------------------------------------------------------------*/
5017 /* isLiteralBit - test if lit == 2^n */
5018 /*-----------------------------------------------------------------*/
5020 isLiteralBit (unsigned long lit)
5022 unsigned long pw[32] =
5023 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5024 0x100L, 0x200L, 0x400L, 0x800L,
5025 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5026 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5027 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5028 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5029 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5032 for (idx = 0; idx < 32; idx++)
5038 /*-----------------------------------------------------------------*/
5039 /* continueIfTrue - */
5040 /*-----------------------------------------------------------------*/
5042 continueIfTrue (iCode * ic)
5045 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5049 /*-----------------------------------------------------------------*/
5051 /*-----------------------------------------------------------------*/
5053 jumpIfTrue (iCode * ic)
5056 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5060 /*-----------------------------------------------------------------*/
5061 /* jmpTrueOrFalse - */
5062 /*-----------------------------------------------------------------*/
5064 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5066 // ugly but optimized by peephole
5069 symbol *nlbl = newiTempLabel (NULL);
5070 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5071 emitcode ("", "%05d$:", tlbl->key + 100);
5072 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5073 emitcode ("", "%05d$:", nlbl->key + 100);
5077 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5078 emitcode ("", "%05d$:", tlbl->key + 100);
5083 // Generate code to perform a bit-wise logic operation
5084 // on two operands in far space (assumed to already have been
5085 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5086 // in far space. This requires pushing the result on the stack
5087 // then popping it into the result.
5089 genFarFarLogicOp(iCode *ic, char *logicOp)
5091 int size, resultSize, compSize;
5095 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5096 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5097 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5099 _startLazyDPSEvaluation();
5100 for (size = compSize; (size--); offset++)
5102 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5103 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5104 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5106 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5107 emitcode ("push", "acc");
5109 _endLazyDPSEvaluation();
5111 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5112 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5113 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5115 resultSize = AOP_SIZE(IC_RESULT(ic));
5117 ADJUST_PUSHED_RESULT(compSize, resultSize);
5119 _startLazyDPSEvaluation();
5122 emitcode ("pop", "acc");
5123 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5125 _endLazyDPSEvaluation();
5126 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5130 /*-----------------------------------------------------------------*/
5131 /* genAnd - code for and */
5132 /*-----------------------------------------------------------------*/
5134 genAnd (iCode * ic, iCode * ifx)
5136 operand *left, *right, *result;
5137 int size, offset = 0;
5138 unsigned long lit = 0L;
5143 D (emitcode (";", "genAnd "););
5145 AOP_OP_3_NOFATAL (ic, pushResult);
5146 AOP_SET_LOCALS (ic);
5150 genFarFarLogicOp(ic, "anl");
5155 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5157 AOP_TYPE (left), AOP_TYPE (right));
5158 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5160 AOP_SIZE (left), AOP_SIZE (right));
5163 /* if left is a literal & right is not then exchange them */
5164 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5165 AOP_NEEDSACC (left))
5167 operand *tmp = right;
5172 /* if result = right then exchange them */
5173 if (sameRegs (AOP (result), AOP (right)))
5175 operand *tmp = right;
5180 /* if right is bit then exchange them */
5181 if (AOP_TYPE (right) == AOP_CRY &&
5182 AOP_TYPE (left) != AOP_CRY)
5184 operand *tmp = right;
5188 if (AOP_TYPE (right) == AOP_LIT)
5189 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5191 size = AOP_SIZE (result);
5194 // result = bit & yy;
5195 if (AOP_TYPE (left) == AOP_CRY)
5197 // c = bit & literal;
5198 if (AOP_TYPE (right) == AOP_LIT)
5202 if (size && sameRegs (AOP (result), AOP (left)))
5205 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5210 if (size && (AOP_TYPE (result) == AOP_CRY))
5212 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5215 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5220 emitcode ("clr", "c");
5225 if (AOP_TYPE (right) == AOP_CRY)
5228 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5229 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5234 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5236 emitcode ("rrc", "a");
5237 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5245 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5246 genIfxJump (ifx, "c");
5250 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5251 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5252 if ((AOP_TYPE (right) == AOP_LIT) &&
5253 (AOP_TYPE (result) == AOP_CRY) &&
5254 (AOP_TYPE (left) != AOP_CRY))
5256 int posbit = isLiteralBit (lit);
5261 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5264 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5270 sprintf (buffer, "acc.%d", posbit & 0x07);
5271 genIfxJump (ifx, buffer);
5278 symbol *tlbl = newiTempLabel (NULL);
5279 int sizel = AOP_SIZE (left);
5281 emitcode ("setb", "c");
5284 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5286 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5288 if ((posbit = isLiteralBit (bytelit)) != 0)
5289 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5292 if (bytelit != 0x0FFL)
5293 emitcode ("anl", "a,%s",
5294 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5295 emitcode ("jnz", "%05d$", tlbl->key + 100);
5300 // bit = left & literal
5303 emitcode ("clr", "c");
5304 emitcode ("", "%05d$:", tlbl->key + 100);
5306 // if(left & literal)
5310 jmpTrueOrFalse (ifx, tlbl);
5318 /* if left is same as result */
5319 if (sameRegs (AOP (result), AOP (left)))
5321 for (; size--; offset++)
5323 if (AOP_TYPE (right) == AOP_LIT)
5325 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5327 else if (bytelit == 0)
5328 aopPut (AOP (result), zero, offset);
5329 else if (IS_AOP_PREG (result))
5331 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5332 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5333 aopPut (AOP (result), "a", offset);
5336 emitcode ("anl", "%s,%s",
5337 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5338 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5342 if (AOP_TYPE (left) == AOP_ACC)
5343 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5346 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5347 if (IS_AOP_PREG (result))
5349 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5350 aopPut (AOP (result), "a", offset);
5354 emitcode ("anl", "%s,a",
5355 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5362 // left & result in different registers
5363 if (AOP_TYPE (result) == AOP_CRY)
5366 // if(size), result in bit
5367 // if(!size && ifx), conditional oper: if(left & right)
5368 symbol *tlbl = newiTempLabel (NULL);
5369 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5371 emitcode ("setb", "c");
5374 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5375 emitcode ("anl", "a,%s",
5376 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5378 if (AOP_TYPE(left)==AOP_ACC) {
5379 emitcode("mov", "b,a");
5380 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5381 emitcode("anl", "a,b");
5383 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5384 emitcode ("anl", "a,%s",
5385 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5388 emitcode ("jnz", "%05d$", tlbl->key + 100);
5394 emitcode ("", "%05d$:", tlbl->key + 100);
5398 jmpTrueOrFalse (ifx, tlbl);
5402 for (; (size--); offset++)
5405 // result = left & right
5406 if (AOP_TYPE (right) == AOP_LIT)
5408 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5410 aopPut (AOP (result),
5411 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5415 else if (bytelit == 0)
5417 aopPut (AOP (result), zero, offset);
5420 D (emitcode (";", "better literal AND.");
5422 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5423 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5424 FALSE, FALSE, FALSE));
5429 // faster than result <- left, anl result,right
5430 // and better if result is SFR
5431 if (AOP_TYPE (left) == AOP_ACC)
5433 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5434 FALSE, FALSE, FALSE));
5438 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5439 emitcode ("anl", "a,%s",
5440 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5443 aopPut (AOP (result), "a", offset);
5449 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5450 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5451 freeAsmop (result, NULL, ic, TRUE);
5455 /*-----------------------------------------------------------------*/
5456 /* genOr - code for or */
5457 /*-----------------------------------------------------------------*/
5459 genOr (iCode * ic, iCode * ifx)
5461 operand *left, *right, *result;
5462 int size, offset = 0;
5463 unsigned long lit = 0L;
5466 D (emitcode (";", "genOr "););
5468 AOP_OP_3_NOFATAL (ic, pushResult);
5469 AOP_SET_LOCALS (ic);
5473 genFarFarLogicOp(ic, "orl");
5479 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5481 AOP_TYPE (left), AOP_TYPE (right));
5482 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5484 AOP_SIZE (left), AOP_SIZE (right));
5487 /* if left is a literal & right is not then exchange them */
5488 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5489 AOP_NEEDSACC (left))
5491 operand *tmp = right;
5496 /* if result = right then exchange them */
5497 if (sameRegs (AOP (result), AOP (right)))
5499 operand *tmp = right;
5504 /* if right is bit then exchange them */
5505 if (AOP_TYPE (right) == AOP_CRY &&
5506 AOP_TYPE (left) != AOP_CRY)
5508 operand *tmp = right;
5512 if (AOP_TYPE (right) == AOP_LIT)
5513 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5515 size = AOP_SIZE (result);
5519 if (AOP_TYPE (left) == AOP_CRY)
5521 if (AOP_TYPE (right) == AOP_LIT)
5523 // c = bit & literal;
5526 // lit != 0 => result = 1
5527 if (AOP_TYPE (result) == AOP_CRY)
5530 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5532 continueIfTrue (ifx);
5535 emitcode ("setb", "c");
5539 // lit == 0 => result = left
5540 if (size && sameRegs (AOP (result), AOP (left)))
5542 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5547 if (AOP_TYPE (right) == AOP_CRY)
5550 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5551 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5556 symbol *tlbl = newiTempLabel (NULL);
5557 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5558 emitcode ("setb", "c");
5559 emitcode ("jb", "%s,%05d$",
5560 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5562 emitcode ("jnz", "%05d$", tlbl->key + 100);
5563 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5565 jmpTrueOrFalse (ifx, tlbl);
5571 emitcode ("", "%05d$:", tlbl->key + 100);
5580 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5581 genIfxJump (ifx, "c");
5585 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5586 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5587 if ((AOP_TYPE (right) == AOP_LIT) &&
5588 (AOP_TYPE (result) == AOP_CRY) &&
5589 (AOP_TYPE (left) != AOP_CRY))
5595 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5597 continueIfTrue (ifx);
5602 // lit = 0, result = boolean(left)
5604 emitcode ("setb", "c");
5608 symbol *tlbl = newiTempLabel (NULL);
5609 emitcode ("jnz", "%05d$", tlbl->key + 100);
5611 emitcode ("", "%05d$:", tlbl->key + 100);
5615 genIfxJump (ifx, "a");
5623 /* if left is same as result */
5624 if (sameRegs (AOP (result), AOP (left)))
5626 for (; size--; offset++)
5628 if (AOP_TYPE (right) == AOP_LIT)
5630 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5636 if (IS_AOP_PREG (left))
5638 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5639 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5640 aopPut (AOP (result), "a", offset);
5644 emitcode ("orl", "%s,%s",
5645 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5646 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5652 if (AOP_TYPE (left) == AOP_ACC)
5654 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5658 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5659 if (IS_AOP_PREG (left))
5661 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5662 aopPut (AOP (result), "a", offset);
5666 emitcode ("orl", "%s,a",
5667 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5675 // left & result in different registers
5676 if (AOP_TYPE (result) == AOP_CRY)
5679 // if(size), result in bit
5680 // if(!size && ifx), conditional oper: if(left | right)
5681 symbol *tlbl = newiTempLabel (NULL);
5682 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5684 emitcode ("setb", "c");
5687 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5688 emitcode ("orl", "a,%s",
5689 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5691 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5692 emitcode ("orl", "a,%s",
5693 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5695 emitcode ("jnz", "%05d$", tlbl->key + 100);
5701 emitcode ("", "%05d$:", tlbl->key + 100);
5705 jmpTrueOrFalse (ifx, tlbl);
5709 for (; (size--); offset++)
5712 // result = left & right
5713 if (AOP_TYPE (right) == AOP_LIT)
5715 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5717 aopPut (AOP (result),
5718 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5722 D (emitcode (";", "better literal OR.");
5724 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5725 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5726 FALSE, FALSE, FALSE));
5731 // faster than result <- left, anl result,right
5732 // and better if result is SFR
5733 if (AOP_TYPE (left) == AOP_ACC)
5735 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5736 FALSE, FALSE, FALSE));
5740 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5741 emitcode ("orl", "a,%s",
5742 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5745 aopPut (AOP (result), "a", offset);
5751 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5752 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5753 freeAsmop (result, NULL, ic, TRUE);
5756 /*-----------------------------------------------------------------*/
5757 /* genXor - code for xclusive or */
5758 /*-----------------------------------------------------------------*/
5760 genXor (iCode * ic, iCode * ifx)
5762 operand *left, *right, *result;
5763 int size, offset = 0;
5764 unsigned long lit = 0L;
5767 D (emitcode (";", "genXor "););
5769 AOP_OP_3_NOFATAL (ic, pushResult);
5770 AOP_SET_LOCALS (ic);
5774 genFarFarLogicOp(ic, "xrl");
5779 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5781 AOP_TYPE (left), AOP_TYPE (right));
5782 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5784 AOP_SIZE (left), AOP_SIZE (right));
5787 /* if left is a literal & right is not ||
5788 if left needs acc & right does not */
5789 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5790 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5792 operand *tmp = right;
5797 /* if result = right then exchange them */
5798 if (sameRegs (AOP (result), AOP (right)))
5800 operand *tmp = right;
5805 /* if right is bit then exchange them */
5806 if (AOP_TYPE (right) == AOP_CRY &&
5807 AOP_TYPE (left) != AOP_CRY)
5809 operand *tmp = right;
5813 if (AOP_TYPE (right) == AOP_LIT)
5814 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5816 size = AOP_SIZE (result);
5820 if (AOP_TYPE (left) == AOP_CRY)
5822 if (AOP_TYPE (right) == AOP_LIT)
5824 // c = bit & literal;
5827 // lit>>1 != 0 => result = 1
5828 if (AOP_TYPE (result) == AOP_CRY)
5831 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5833 continueIfTrue (ifx);
5836 emitcode ("setb", "c");
5843 // lit == 0, result = left
5844 if (size && sameRegs (AOP (result), AOP (left)))
5846 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5850 // lit == 1, result = not(left)
5851 if (size && sameRegs (AOP (result), AOP (left)))
5853 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5858 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5859 emitcode ("cpl", "c");
5868 symbol *tlbl = newiTempLabel (NULL);
5869 if (AOP_TYPE (right) == AOP_CRY)
5872 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5876 int sizer = AOP_SIZE (right);
5878 // if val>>1 != 0, result = 1
5879 emitcode ("setb", "c");
5882 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5884 // test the msb of the lsb
5885 emitcode ("anl", "a,#0xfe");
5886 emitcode ("jnz", "%05d$", tlbl->key + 100);
5890 emitcode ("rrc", "a");
5892 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5893 emitcode ("cpl", "c");
5894 emitcode ("", "%05d$:", (tlbl->key + 100));
5901 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5902 genIfxJump (ifx, "c");
5906 if (sameRegs (AOP (result), AOP (left)))
5908 /* if left is same as result */
5909 for (; size--; offset++)
5911 if (AOP_TYPE (right) == AOP_LIT)
5913 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5915 else if (IS_AOP_PREG (left))
5917 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5918 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5919 aopPut (AOP (result), "a", offset);
5922 emitcode ("xrl", "%s,%s",
5923 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5924 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5928 if (AOP_TYPE (left) == AOP_ACC)
5929 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5932 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5933 if (IS_AOP_PREG (left))
5935 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5936 aopPut (AOP (result), "a", offset);
5939 emitcode ("xrl", "%s,a",
5940 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5947 // left & result in different registers
5948 if (AOP_TYPE (result) == AOP_CRY)
5951 // if(size), result in bit
5952 // if(!size && ifx), conditional oper: if(left ^ right)
5953 symbol *tlbl = newiTempLabel (NULL);
5954 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5956 emitcode ("setb", "c");
5959 if ((AOP_TYPE (right) == AOP_LIT) &&
5960 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5962 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5966 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5967 emitcode ("xrl", "a,%s",
5968 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5970 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5971 emitcode ("xrl", "a,%s",
5972 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5975 emitcode ("jnz", "%05d$", tlbl->key + 100);
5981 emitcode ("", "%05d$:", tlbl->key + 100);
5985 jmpTrueOrFalse (ifx, tlbl);
5988 for (; (size--); offset++)
5991 // result = left & right
5992 if (AOP_TYPE (right) == AOP_LIT)
5994 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5996 aopPut (AOP (result),
5997 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6001 D (emitcode (";", "better literal XOR.");
6003 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6004 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6005 FALSE, FALSE, FALSE));
6009 // faster than result <- left, anl result,right
6010 // and better if result is SFR
6011 if (AOP_TYPE (left) == AOP_ACC)
6013 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6014 FALSE, FALSE, FALSE));
6018 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6019 emitcode ("xrl", "a,%s",
6020 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6023 aopPut (AOP (result), "a", offset);
6028 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030 freeAsmop (result, NULL, ic, TRUE);
6033 /*-----------------------------------------------------------------*/
6034 /* genInline - write the inline code out */
6035 /*-----------------------------------------------------------------*/
6037 genInline (iCode * ic)
6039 char *buffer, *bp, *bp1;
6041 D (emitcode (";", "genInline ");
6044 _G.inLine += (!options.asmpeep);
6046 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6047 strcpy (buffer, IC_INLINE (ic));
6049 /* emit each line as a code */
6074 /* emitcode("",buffer); */
6075 _G.inLine -= (!options.asmpeep);
6078 /*-----------------------------------------------------------------*/
6079 /* genRRC - rotate right with carry */
6080 /*-----------------------------------------------------------------*/
6084 operand *left, *result;
6085 int size, offset = 0;
6088 D (emitcode (";", "genRRC ");
6091 /* rotate right with carry */
6092 left = IC_LEFT (ic);
6093 result = IC_RESULT (ic);
6094 aopOp (left, ic, FALSE, FALSE);
6095 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6097 /* move it to the result */
6098 size = AOP_SIZE (result);
6102 _startLazyDPSEvaluation ();
6105 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6107 emitcode ("rrc", "a");
6108 if (AOP_SIZE (result) > 1)
6109 aopPut (AOP (result), "a", offset--);
6111 _endLazyDPSEvaluation ();
6113 /* now we need to put the carry into the
6114 highest order byte of the result */
6115 if (AOP_SIZE (result) > 1)
6117 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6120 emitcode ("mov", "acc.7,c");
6121 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6122 freeAsmop (left, NULL, ic, TRUE);
6123 freeAsmop (result, NULL, ic, TRUE);
6126 /*-----------------------------------------------------------------*/
6127 /* genRLC - generate code for rotate left with carry */
6128 /*-----------------------------------------------------------------*/
6132 operand *left, *result;
6133 int size, offset = 0;
6136 D (emitcode (";", "genRLC ");
6139 /* rotate right with carry */
6140 left = IC_LEFT (ic);
6141 result = IC_RESULT (ic);
6142 aopOp (left, ic, FALSE, FALSE);
6143 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6145 /* move it to the result */
6146 size = AOP_SIZE (result);
6150 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6152 emitcode ("add", "a,acc");
6153 if (AOP_SIZE (result) > 1)
6155 aopPut (AOP (result), "a", offset++);
6158 _startLazyDPSEvaluation ();
6161 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6163 emitcode ("rlc", "a");
6164 if (AOP_SIZE (result) > 1)
6165 aopPut (AOP (result), "a", offset++);
6167 _endLazyDPSEvaluation ();
6169 /* now we need to put the carry into the
6170 highest order byte of the result */
6171 if (AOP_SIZE (result) > 1)
6173 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6176 emitcode ("mov", "acc.0,c");
6177 aopPut (AOP (result), "a", 0);
6178 freeAsmop (left, NULL, ic, TRUE);
6179 freeAsmop (result, NULL, ic, TRUE);
6182 /*-----------------------------------------------------------------*/
6183 /* genGetHbit - generates code get highest order bit */
6184 /*-----------------------------------------------------------------*/
6186 genGetHbit (iCode * ic)
6188 operand *left, *result;
6189 left = IC_LEFT (ic);
6190 result = IC_RESULT (ic);
6191 aopOp (left, ic, FALSE, FALSE);
6192 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6194 D (emitcode (";", "genGetHbit ");
6197 /* get the highest order byte into a */
6198 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6199 if (AOP_TYPE (result) == AOP_CRY)
6201 emitcode ("rlc", "a");
6206 emitcode ("rl", "a");
6207 emitcode ("anl", "a,#0x01");
6212 freeAsmop (left, NULL, ic, TRUE);
6213 freeAsmop (result, NULL, ic, TRUE);
6216 /*-----------------------------------------------------------------*/
6217 /* AccRol - rotate left accumulator by known count */
6218 /*-----------------------------------------------------------------*/
6220 AccRol (int shCount)
6222 shCount &= 0x0007; // shCount : 0..7
6229 emitcode ("rl", "a");
6232 emitcode ("rl", "a");
6233 emitcode ("rl", "a");
6236 emitcode ("swap", "a");
6237 emitcode ("rr", "a");
6240 emitcode ("swap", "a");
6243 emitcode ("swap", "a");
6244 emitcode ("rl", "a");
6247 emitcode ("rr", "a");
6248 emitcode ("rr", "a");
6251 emitcode ("rr", "a");
6256 /*-----------------------------------------------------------------*/
6257 /* AccLsh - left shift accumulator by known count */
6258 /*-----------------------------------------------------------------*/
6260 AccLsh (int shCount)
6265 emitcode ("add", "a,acc");
6266 else if (shCount == 2)
6268 emitcode ("add", "a,acc");
6269 emitcode ("add", "a,acc");
6273 /* rotate left accumulator */
6275 /* and kill the lower order bits */
6276 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6281 /*-----------------------------------------------------------------*/
6282 /* AccRsh - right shift accumulator by known count */
6283 /*-----------------------------------------------------------------*/
6285 AccRsh (int shCount)
6292 emitcode ("rrc", "a");
6296 /* rotate right accumulator */
6297 AccRol (8 - shCount);
6298 /* and kill the higher order bits */
6299 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6304 #ifdef BETTER_LITERAL_SHIFT
6305 /*-----------------------------------------------------------------*/
6306 /* AccSRsh - signed right shift accumulator by known count */
6307 /*-----------------------------------------------------------------*/
6309 AccSRsh (int shCount)
6316 emitcode ("mov", "c,acc.7");
6317 emitcode ("rrc", "a");
6319 else if (shCount == 2)
6321 emitcode ("mov", "c,acc.7");
6322 emitcode ("rrc", "a");
6323 emitcode ("mov", "c,acc.7");
6324 emitcode ("rrc", "a");
6328 tlbl = newiTempLabel (NULL);
6329 /* rotate right accumulator */
6330 AccRol (8 - shCount);
6331 /* and kill the higher order bits */
6332 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6333 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6334 emitcode ("orl", "a,#0x%02x",
6335 (unsigned char) ~SRMask[shCount]);
6336 emitcode ("", "%05d$:", tlbl->key + 100);
6342 #ifdef BETTER_LITERAL_SHIFT
6343 /*-----------------------------------------------------------------*/
6344 /* shiftR1Left2Result - shift right one byte from left to result */
6345 /*-----------------------------------------------------------------*/
6347 shiftR1Left2Result (operand * left, int offl,
6348 operand * result, int offr,
6349 int shCount, int sign)
6351 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6352 /* shift right accumulator */
6357 aopPut (AOP (result), "a", offr);
6361 #ifdef BETTER_LITERAL_SHIFT
6362 /*-----------------------------------------------------------------*/
6363 /* shiftL1Left2Result - shift left one byte from left to result */
6364 /*-----------------------------------------------------------------*/
6366 shiftL1Left2Result (operand * left, int offl,
6367 operand * result, int offr, int shCount)
6369 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6370 /* shift left accumulator */
6372 aopPut (AOP (result), "a", offr);
6376 #ifdef BETTER_LITERAL_SHIFT
6377 /*-----------------------------------------------------------------*/
6378 /* movLeft2Result - move byte from left to result */
6379 /*-----------------------------------------------------------------*/
6381 movLeft2Result (operand * left, int offl,
6382 operand * result, int offr, int sign)
6385 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6387 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6389 if (*l == '@' && (IS_AOP_PREG (result)))
6391 emitcode ("mov", "a,%s", l);
6392 aopPut (AOP (result), "a", offr);
6398 aopPut (AOP (result), l, offr);
6402 /* MSB sign in acc.7 ! */
6403 if (getDataSize (left) == offl + 1)
6405 emitcode ("mov", "a,%s", l);
6406 aopPut (AOP (result), "a", offr);
6414 #ifdef BETTER_LITERAL_SHIFT
6415 /*-----------------------------------------------------------------*/
6416 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6417 /*-----------------------------------------------------------------*/
6421 emitcode ("rrc", "a");
6422 emitcode ("xch", "a,%s", x);
6423 emitcode ("rrc", "a");
6424 emitcode ("xch", "a,%s", x);
6428 #ifdef BETTER_LITERAL_SHIFT
6430 /*-----------------------------------------------------------------*/
6431 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6432 /*-----------------------------------------------------------------*/
6436 emitcode ("xch", "a,%s", x);
6437 emitcode ("rlc", "a");
6438 emitcode ("xch", "a,%s", x);
6439 emitcode ("rlc", "a");
6443 #ifdef BETTER_LITERAL_SHIFT
6444 /*-----------------------------------------------------------------*/
6445 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6446 /*-----------------------------------------------------------------*/
6450 emitcode ("xch", "a,%s", x);
6451 emitcode ("add", "a,acc");
6452 emitcode ("xch", "a,%s", x);
6453 emitcode ("rlc", "a");
6457 #ifdef BETTER_LITERAL_SHIFT
6458 /*-----------------------------------------------------------------*/
6459 /* AccAXLsh - left shift a:x by known count (0..7) */
6460 /*-----------------------------------------------------------------*/
6462 AccAXLsh (char *x, int shCount)
6477 case 5: // AAAAABBB:CCCCCDDD
6479 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6481 emitcode ("anl", "a,#0x%02x",
6482 SLMask[shCount]); // BBB00000:CCCCCDDD
6484 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6486 AccRol (shCount); // DDDCCCCC:BBB00000
6488 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6490 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6492 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6494 emitcode ("anl", "a,#0x%02x",
6495 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6497 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6499 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6502 case 6: // AAAAAABB:CCCCCCDD
6503 emitcode ("anl", "a,#0x%02x",
6504 SRMask[shCount]); // 000000BB:CCCCCCDD
6505 emitcode ("mov", "c,acc.0"); // c = B
6506 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6508 AccAXRrl1 (x); // BCCCCCCD:D000000B
6509 AccAXRrl1 (x); // BBCCCCCC:DD000000
6511 emitcode("rrc","a");
6512 emitcode("xch","a,%s", x);
6513 emitcode("rrc","a");
6514 emitcode("mov","c,acc.0"); //<< get correct bit
6515 emitcode("xch","a,%s", x);
6517 emitcode("rrc","a");
6518 emitcode("xch","a,%s", x);
6519 emitcode("rrc","a");
6520 emitcode("xch","a,%s", x);
6523 case 7: // a:x <<= 7
6525 emitcode ("anl", "a,#0x%02x",
6526 SRMask[shCount]); // 0000000B:CCCCCCCD
6528 emitcode ("mov", "c,acc.0"); // c = B
6530 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6532 AccAXRrl1 (x); // BCCCCCCC:D0000000
6541 #ifdef BETTER_LITERAL_SHIFT
6543 /*-----------------------------------------------------------------*/
6544 /* AccAXRsh - right shift a:x known count (0..7) */
6545 /*-----------------------------------------------------------------*/
6547 AccAXRsh (char *x, int shCount)
6555 AccAXRrl1 (x); // 0->a:x
6560 AccAXRrl1 (x); // 0->a:x
6563 AccAXRrl1 (x); // 0->a:x
6568 case 5: // AAAAABBB:CCCCCDDD = a:x
6570 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6572 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6574 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6576 emitcode ("anl", "a,#0x%02x",
6577 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6579 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6581 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6583 emitcode ("anl", "a,#0x%02x",
6584 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6586 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6588 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6590 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6593 case 6: // AABBBBBB:CCDDDDDD
6595 emitcode ("mov", "c,acc.7");
6596 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6598 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6600 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6602 emitcode ("anl", "a,#0x%02x",
6603 SRMask[shCount]); // 000000AA:BBBBBBCC
6606 case 7: // ABBBBBBB:CDDDDDDD
6608 emitcode ("mov", "c,acc.7"); // c = A
6610 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6612 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6614 emitcode ("anl", "a,#0x%02x",
6615 SRMask[shCount]); // 0000000A:BBBBBBBC
6624 #ifdef BETTER_LITERAL_SHIFT
6625 /*-----------------------------------------------------------------*/
6626 /* AccAXRshS - right shift signed a:x known count (0..7) */
6627 /*-----------------------------------------------------------------*/
6629 AccAXRshS (char *x, int shCount)
6637 emitcode ("mov", "c,acc.7");
6638 AccAXRrl1 (x); // s->a:x
6642 emitcode ("mov", "c,acc.7");
6643 AccAXRrl1 (x); // s->a:x
6645 emitcode ("mov", "c,acc.7");
6646 AccAXRrl1 (x); // s->a:x
6651 case 5: // AAAAABBB:CCCCCDDD = a:x
6653 tlbl = newiTempLabel (NULL);
6654 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6656 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6658 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6660 emitcode ("anl", "a,#0x%02x",
6661 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6663 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6665 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6667 emitcode ("anl", "a,#0x%02x",
6668 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6670 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6672 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6674 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6676 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6677 emitcode ("orl", "a,#0x%02x",
6678 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6680 emitcode ("", "%05d$:", tlbl->key + 100);
6681 break; // SSSSAAAA:BBBCCCCC
6683 case 6: // AABBBBBB:CCDDDDDD
6685 tlbl = newiTempLabel (NULL);
6686 emitcode ("mov", "c,acc.7");
6687 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6689 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6691 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6693 emitcode ("anl", "a,#0x%02x",
6694 SRMask[shCount]); // 000000AA:BBBBBBCC
6696 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6697 emitcode ("orl", "a,#0x%02x",
6698 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6700 emitcode ("", "%05d$:", tlbl->key + 100);
6702 case 7: // ABBBBBBB:CDDDDDDD
6704 tlbl = newiTempLabel (NULL);
6705 emitcode ("mov", "c,acc.7"); // c = A
6707 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6709 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6711 emitcode ("anl", "a,#0x%02x",
6712 SRMask[shCount]); // 0000000A:BBBBBBBC
6714 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6715 emitcode ("orl", "a,#0x%02x",
6716 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6718 emitcode ("", "%05d$:", tlbl->key + 100);
6726 #ifdef BETTER_LITERAL_SHIFT
6728 _loadLeftIntoAx(char **lsb,
6734 // Get the initial value from left into a pair of registers.
6735 // MSB must be in A, LSB can be any register.
6737 // If the result is held in registers, it is an optimization
6738 // if the LSB can be held in the register which will hold the,
6739 // result LSB since this saves us from having to copy it into
6740 // the result following AccAXLsh.
6742 // If the result is addressed indirectly, this is not a gain.
6743 if (AOP_NEEDSACC(result))
6747 _startLazyDPSEvaluation();
6748 if (AOP_TYPE(left) == AOP_DPTR2)
6751 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6752 // get LSB in DP2_RESULT_REG.
6753 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6754 assert(!strcmp(leftByte, DP2_RESULT_REG));
6758 // get LSB into DP2_RESULT_REG
6759 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6760 if (strcmp(leftByte, DP2_RESULT_REG))
6763 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6766 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6767 assert(strcmp(leftByte, DP2_RESULT_REG));
6770 _endLazyDPSEvaluation();
6771 *lsb = DP2_RESULT_REG;
6775 if (sameRegs (AOP (result), AOP (left)) &&
6776 ((offl + MSB16) == offr))
6778 /* don't crash result[offr] */
6779 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6780 emitcode ("xch", "a,%s",
6781 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6785 movLeft2Result (left, offl, result, offr, 0);
6786 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6788 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6789 assert(strcmp(*lsb,"a"));
6794 _storeAxResults(char *lsb,
6798 _startLazyDPSEvaluation();
6799 if (AOP_NEEDSACC(result))
6801 /* We have to explicitly update the result LSB.
6803 emitcode("xch","a,%s", lsb);
6804 aopPut(AOP(result), "a", offr);
6805 emitcode("mov","a,%s", lsb);
6807 if (getDataSize (result) > 1)
6809 aopPut (AOP (result), "a", offr + MSB16);
6811 _endLazyDPSEvaluation();
6814 /*-----------------------------------------------------------------*/
6815 /* shiftL2Left2Result - shift left two bytes from left to result */
6816 /*-----------------------------------------------------------------*/
6818 shiftL2Left2Result (operand * left, int offl,
6819 operand * result, int offr, int shCount)
6823 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6825 AccAXLsh (lsb, shCount);
6827 _storeAxResults(lsb, result, offr);
6831 #ifdef BETTER_LITERAL_SHIFT
6832 /*-----------------------------------------------------------------*/
6833 /* shiftR2Left2Result - shift right two bytes from left to result */
6834 /*-----------------------------------------------------------------*/
6836 shiftR2Left2Result (operand * left, int offl,
6837 operand * result, int offr,
6838 int shCount, int sign)
6842 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6844 /* a:x >> shCount (x = lsb(result)) */
6847 AccAXRshS(lsb, shCount);
6851 AccAXRsh(lsb, shCount);
6854 _storeAxResults(lsb, result, offr);
6860 /*-----------------------------------------------------------------*/
6861 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6862 /*-----------------------------------------------------------------*/
6864 shiftLLeftOrResult (operand * left, int offl,
6865 operand * result, int offr, int shCount)
6867 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6868 /* shift left accumulator */
6870 /* or with result */
6871 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6872 /* back to result */
6873 aopPut (AOP (result), "a", offr);
6879 /*-----------------------------------------------------------------*/
6880 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6881 /*-----------------------------------------------------------------*/
6883 shiftRLeftOrResult (operand * left, int offl,
6884 operand * result, int offr, int shCount)
6886 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6887 /* shift right accumulator */
6889 /* or with result */
6890 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6891 /* back to result */
6892 aopPut (AOP (result), "a", offr);
6896 #ifdef BETTER_LITERAL_SHIFT
6897 /*-----------------------------------------------------------------*/
6898 /* genlshOne - left shift a one byte quantity by known count */
6899 /*-----------------------------------------------------------------*/
6901 genlshOne (operand * result, operand * left, int shCount)
6903 D (emitcode (";", "genlshOne "););
6904 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6908 #ifdef BETTER_LITERAL_SHIFT
6909 /*-----------------------------------------------------------------*/
6910 /* genlshTwo - left shift two bytes by known amount != 0 */
6911 /*-----------------------------------------------------------------*/
6913 genlshTwo (operand * result, operand * left, int shCount)
6917 D (emitcode (";", "genlshTwo "););
6919 size = getDataSize (result);
6921 /* if shCount >= 8 */
6926 _startLazyDPSEvaluation();
6932 _endLazyDPSEvaluation();
6933 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6934 aopPut (AOP (result), zero, LSB);
6938 movLeft2Result (left, LSB, result, MSB16, 0);
6939 aopPut (AOP (result), zero, LSB);
6940 _endLazyDPSEvaluation();
6945 aopPut (AOP (result), zero, LSB);
6946 _endLazyDPSEvaluation();
6950 /* 1 <= shCount <= 7 */
6955 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6959 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6967 /*-----------------------------------------------------------------*/
6968 /* shiftLLong - shift left one long from left to result */
6969 /* offl = LSB or MSB16 */
6970 /*-----------------------------------------------------------------*/
6972 shiftLLong (operand * left, operand * result, int offr)
6975 int size = AOP_SIZE (result);
6977 if (size >= LSB + offr)
6979 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6981 emitcode ("add", "a,acc");
6982 if (sameRegs (AOP (left), AOP (result)) &&
6983 size >= MSB16 + offr && offr != LSB)
6984 emitcode ("xch", "a,%s",
6985 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6987 aopPut (AOP (result), "a", LSB + offr);
6990 if (size >= MSB16 + offr)
6992 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6994 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6997 emitcode ("rlc", "a");
6998 if (sameRegs (AOP (left), AOP (result)) &&
6999 size >= MSB24 + offr && offr != LSB)
7000 emitcode ("xch", "a,%s",
7001 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7003 aopPut (AOP (result), "a", MSB16 + offr);
7006 if (size >= MSB24 + offr)
7008 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7010 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7013 emitcode ("rlc", "a");
7014 if (sameRegs (AOP (left), AOP (result)) &&
7015 size >= MSB32 + offr && offr != LSB)
7016 emitcode ("xch", "a,%s",
7017 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7019 aopPut (AOP (result), "a", MSB24 + offr);
7022 if (size > MSB32 + offr)
7024 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7026 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7029 emitcode ("rlc", "a");
7030 aopPut (AOP (result), "a", MSB32 + offr);
7033 aopPut (AOP (result), zero, LSB);
7039 /*-----------------------------------------------------------------*/
7040 /* genlshFour - shift four byte by a known amount != 0 */
7041 /*-----------------------------------------------------------------*/
7043 genlshFour (operand * result, operand * left, int shCount)
7047 D (emitcode (";", "genlshFour ");
7050 size = AOP_SIZE (result);
7052 /* if shifting more that 3 bytes */
7057 /* lowest order of left goes to the highest
7058 order of the destination */
7059 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7061 movLeft2Result (left, LSB, result, MSB32, 0);
7062 aopPut (AOP (result), zero, LSB);
7063 aopPut (AOP (result), zero, MSB16);
7064 aopPut (AOP (result), zero, MSB24);
7068 /* more than two bytes */
7069 else if (shCount >= 16)
7071 /* lower order two bytes goes to higher order two bytes */
7073 /* if some more remaining */
7075 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7078 movLeft2Result (left, MSB16, result, MSB32, 0);
7079 movLeft2Result (left, LSB, result, MSB24, 0);
7081 aopPut (AOP (result), zero, MSB16);
7082 aopPut (AOP (result), zero, LSB);
7086 /* if more than 1 byte */
7087 else if (shCount >= 8)
7089 /* lower order three bytes goes to higher order three bytes */
7094 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7096 movLeft2Result (left, LSB, result, MSB16, 0);
7102 movLeft2Result (left, MSB24, result, MSB32, 0);
7103 movLeft2Result (left, MSB16, result, MSB24, 0);
7104 movLeft2Result (left, LSB, result, MSB16, 0);
7105 aopPut (AOP (result), zero, LSB);
7107 else if (shCount == 1)
7108 shiftLLong (left, result, MSB16);
7111 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7112 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7113 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7114 aopPut (AOP (result), zero, LSB);
7119 /* 1 <= shCount <= 7 */
7120 else if (shCount <= 2)
7122 shiftLLong (left, result, LSB);
7124 shiftLLong (result, result, LSB);
7126 /* 3 <= shCount <= 7, optimize */
7129 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7130 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7131 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7136 #ifdef BETTER_LITERAL_SHIFT
7137 /*-----------------------------------------------------------------*/
7138 /* genLeftShiftLiteral - left shifting by known count */
7139 /*-----------------------------------------------------------------*/
7141 genLeftShiftLiteral (operand * left,
7146 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7149 size = getSize (operandType (result));
7151 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7153 /* We only handle certain easy cases so far. */
7155 && (shCount < (size * 8))
7159 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7163 freeAsmop (right, NULL, ic, TRUE);
7165 aopOp(left, ic, FALSE, FALSE);
7166 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7169 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7171 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7172 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7174 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7177 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7179 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7180 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7182 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7188 emitcode ("; shift left ", "result %d, left %d", size,
7192 /* I suppose that the left size >= result size */
7195 _startLazyDPSEvaluation();
7198 movLeft2Result (left, size, result, size, 0);
7200 _endLazyDPSEvaluation();
7202 else if (shCount >= (size * 8))
7204 _startLazyDPSEvaluation();
7207 aopPut (AOP (result), zero, size);
7209 _endLazyDPSEvaluation();
7216 genlshOne (result, left, shCount);
7220 genlshTwo (result, left, shCount);
7224 genlshFour (result, left, shCount);
7228 fprintf(stderr, "*** ack! mystery literal shift!\n");
7232 freeAsmop (left, NULL, ic, TRUE);
7233 freeAsmop (result, NULL, ic, TRUE);
7238 /*-----------------------------------------------------------------*/
7239 /* genLeftShift - generates code for left shifting */
7240 /*-----------------------------------------------------------------*/
7242 genLeftShift (iCode * ic)
7244 operand *left, *right, *result;
7247 symbol *tlbl, *tlbl1;
7249 D (emitcode (";", "genLeftShift "););
7251 right = IC_RIGHT (ic);
7252 left = IC_LEFT (ic);
7253 result = IC_RESULT (ic);
7255 aopOp (right, ic, FALSE, FALSE);
7258 #ifdef BETTER_LITERAL_SHIFT
7259 /* if the shift count is known then do it
7260 as efficiently as possible */
7261 if (AOP_TYPE (right) == AOP_LIT)
7263 if (genLeftShiftLiteral (left, right, result, ic))
7270 /* shift count is unknown then we have to form
7271 a loop get the loop count in B : Note: we take
7272 only the lower order byte since shifting
7273 more that 32 bits make no sense anyway, ( the
7274 largest size of an object can be only 32 bits ) */
7276 if (AOP_TYPE (right) == AOP_LIT)
7278 /* Really should be handled by genLeftShiftLiteral,
7279 * but since I'm too lazy to fix that today, at least we can make
7280 * some small improvement.
7282 emitcode("mov", "b,#0x%02x",
7283 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7287 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7288 emitcode ("inc", "b");
7290 freeAsmop (right, NULL, ic, TRUE);
7291 aopOp (left, ic, FALSE, FALSE);
7292 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7294 /* now move the left to the result if they are not the
7296 if (!sameRegs (AOP (left), AOP (result)) &&
7297 AOP_SIZE (result) > 1)
7300 size = AOP_SIZE (result);
7302 _startLazyDPSEvaluation ();
7305 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7306 if (*l == '@' && (IS_AOP_PREG (result)))
7309 emitcode ("mov", "a,%s", l);
7310 aopPut (AOP (result), "a", offset);
7313 aopPut (AOP (result), l, offset);
7316 _endLazyDPSEvaluation ();
7319 tlbl = newiTempLabel (NULL);
7320 size = AOP_SIZE (result);
7322 tlbl1 = newiTempLabel (NULL);
7324 /* if it is only one byte then */
7327 symbol *tlbl1 = newiTempLabel (NULL);
7329 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7331 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7332 emitcode ("", "%05d$:", tlbl->key + 100);
7333 emitcode ("add", "a,acc");
7334 emitcode ("", "%05d$:", tlbl1->key + 100);
7335 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7336 aopPut (AOP (result), "a", 0);
7340 reAdjustPreg (AOP (result));
7342 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7343 emitcode ("", "%05d$:", tlbl->key + 100);
7344 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7346 emitcode ("add", "a,acc");
7347 aopPut (AOP (result), "a", offset++);
7348 _startLazyDPSEvaluation ();
7351 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7353 emitcode ("rlc", "a");
7354 aopPut (AOP (result), "a", offset++);
7356 _endLazyDPSEvaluation ();
7357 reAdjustPreg (AOP (result));
7359 emitcode ("", "%05d$:", tlbl1->key + 100);
7360 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7362 freeAsmop (left, NULL, ic, TRUE);
7363 freeAsmop (result, NULL, ic, TRUE);
7366 #ifdef BETTER_LITERAL_SHIFT
7367 /*-----------------------------------------------------------------*/
7368 /* genrshOne - right shift a one byte quantity by known count */
7369 /*-----------------------------------------------------------------*/
7371 genrshOne (operand * result, operand * left,
7372 int shCount, int sign)
7374 D (emitcode (";", "genrshOne"););
7375 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7379 #ifdef BETTER_LITERAL_SHIFT
7380 /*-----------------------------------------------------------------*/
7381 /* genrshTwo - right shift two bytes by known amount != 0 */
7382 /*-----------------------------------------------------------------*/
7384 genrshTwo (operand * result, operand * left,
7385 int shCount, int sign)
7387 D (emitcode (";", "genrshTwo"););
7389 /* if shCount >= 8 */
7393 _startLazyDPSEvaluation();
7396 shiftR1Left2Result (left, MSB16, result, LSB,
7401 movLeft2Result (left, MSB16, result, LSB, sign);
7403 addSign (result, MSB16, sign);
7404 _endLazyDPSEvaluation();
7407 /* 1 <= shCount <= 7 */
7410 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7417 /*-----------------------------------------------------------------*/
7418 /* shiftRLong - shift right one long from left to result */
7419 /* offl = LSB or MSB16 */
7420 /*-----------------------------------------------------------------*/
7422 shiftRLong (operand * left, int offl,
7423 operand * result, int sign)
7425 int isSameRegs=sameRegs(AOP(left),AOP(result));
7427 if (isSameRegs && offl>1) {
7428 // we are in big trouble, but this shouldn't happen
7429 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7432 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7437 emitcode ("rlc", "a");
7438 emitcode ("subb", "a,acc");
7439 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7441 aopPut (AOP(result), zero, MSB32);
7446 emitcode ("clr", "c");
7448 emitcode ("mov", "c,acc.7");
7451 emitcode ("rrc", "a");
7453 if (isSameRegs && offl==MSB16) {
7454 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7456 aopPut (AOP (result), "a", MSB32);
7457 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7460 emitcode ("rrc", "a");
7461 if (isSameRegs && offl==1) {
7462 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7464 aopPut (AOP (result), "a", MSB24);
7465 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7467 emitcode ("rrc", "a");
7468 aopPut (AOP (result), "a", MSB16 - offl);
7472 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7473 emitcode ("rrc", "a");
7474 aopPut (AOP (result), "a", LSB);
7481 /*-----------------------------------------------------------------*/
7482 /* genrshFour - shift four byte by a known amount != 0 */
7483 /*-----------------------------------------------------------------*/
7485 genrshFour (operand * result, operand * left,
7486 int shCount, int sign)
7488 D (emitcode (";", "genrshFour");
7491 /* if shifting more that 3 bytes */
7496 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7498 movLeft2Result (left, MSB32, result, LSB, sign);
7499 addSign (result, MSB16, sign);
7501 else if (shCount >= 16)
7505 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7508 movLeft2Result (left, MSB24, result, LSB, 0);
7509 movLeft2Result (left, MSB32, result, MSB16, sign);
7511 addSign (result, MSB24, sign);
7513 else if (shCount >= 8)
7517 shiftRLong (left, MSB16, result, sign);
7518 else if (shCount == 0)
7520 movLeft2Result (left, MSB16, result, LSB, 0);
7521 movLeft2Result (left, MSB24, result, MSB16, 0);
7522 movLeft2Result (left, MSB32, result, MSB24, sign);
7523 addSign (result, MSB32, sign);
7527 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7528 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7529 /* the last shift is signed */
7530 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7531 addSign (result, MSB32, sign);
7535 { /* 1 <= shCount <= 7 */
7538 shiftRLong (left, LSB, result, sign);
7540 shiftRLong (result, LSB, result, sign);
7544 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7545 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7546 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7552 #ifdef BETTER_LITERAL_SHIFT
7553 /*-----------------------------------------------------------------*/
7554 /* genRightShiftLiteral - right shifting by known count */
7555 /*-----------------------------------------------------------------*/
7557 genRightShiftLiteral (operand * left,
7563 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7566 size = getSize (operandType (result));
7568 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7570 /* We only handle certain easy cases so far. */
7572 && (shCount < (size * 8))
7576 D(emitcode (";", "genRightShiftLiteral wimping out"););
7580 freeAsmop (right, NULL, ic, TRUE);
7582 aopOp (left, ic, FALSE, FALSE);
7583 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7586 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7590 /* test the LEFT size !!! */
7592 /* I suppose that the left size >= result size */
7595 size = getDataSize (result);
7596 _startLazyDPSEvaluation();
7599 movLeft2Result (left, size, result, size, 0);
7601 _endLazyDPSEvaluation();
7603 else if (shCount >= (size * 8))
7607 /* get sign in acc.7 */
7608 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7610 addSign (result, LSB, sign);
7617 genrshOne (result, left, shCount, sign);
7621 genrshTwo (result, left, shCount, sign);
7625 genrshFour (result, left, shCount, sign);
7632 freeAsmop (left, NULL, ic, TRUE);
7633 freeAsmop (result, NULL, ic, TRUE);
7639 /*-----------------------------------------------------------------*/
7640 /* genSignedRightShift - right shift of signed number */
7641 /*-----------------------------------------------------------------*/
7643 genSignedRightShift (iCode * ic)
7645 operand *right, *left, *result;
7648 symbol *tlbl, *tlbl1;
7650 D (emitcode (";", "genSignedRightShift "););
7652 /* we do it the hard way put the shift count in b
7653 and loop thru preserving the sign */
7655 right = IC_RIGHT (ic);
7656 left = IC_LEFT (ic);
7657 result = IC_RESULT (ic);
7659 aopOp (right, ic, FALSE, FALSE);
7661 #ifdef BETTER_LITERAL_SHIFT
7662 if (AOP_TYPE (right) == AOP_LIT)
7664 if (genRightShiftLiteral (left, right, result, ic, 1))
7670 /* shift count is unknown then we have to form
7671 a loop get the loop count in B : Note: we take
7672 only the lower order byte since shifting
7673 more that 32 bits make no sense anyway, ( the
7674 largest size of an object can be only 32 bits ) */
7676 if (AOP_TYPE (right) == AOP_LIT)
7678 /* Really should be handled by genRightShiftLiteral,
7679 * but since I'm too lazy to fix that today, at least we can make
7680 * some small improvement.
7682 emitcode("mov", "b,#0x%02x",
7683 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7687 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7688 emitcode ("inc", "b");
7690 freeAsmop (right, NULL, ic, TRUE);
7691 aopOp (left, ic, FALSE, FALSE);
7692 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7694 /* now move the left to the result if they are not the
7696 if (!sameRegs (AOP (left), AOP (result)) &&
7697 AOP_SIZE (result) > 1)
7700 size = AOP_SIZE (result);
7702 _startLazyDPSEvaluation ();
7705 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7706 if (*l == '@' && IS_AOP_PREG (result))
7709 emitcode ("mov", "a,%s", l);
7710 aopPut (AOP (result), "a", offset);
7713 aopPut (AOP (result), l, offset);
7716 _endLazyDPSEvaluation ();
7719 /* mov the highest order bit to OVR */
7720 tlbl = newiTempLabel (NULL);
7721 tlbl1 = newiTempLabel (NULL);
7723 size = AOP_SIZE (result);
7725 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7726 emitcode ("rlc", "a");
7727 emitcode ("mov", "ov,c");
7728 /* if it is only one byte then */
7731 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7733 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7734 emitcode ("", "%05d$:", tlbl->key + 100);
7735 emitcode ("mov", "c,ov");
7736 emitcode ("rrc", "a");
7737 emitcode ("", "%05d$:", tlbl1->key + 100);
7738 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7739 aopPut (AOP (result), "a", 0);
7743 reAdjustPreg (AOP (result));
7744 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7745 emitcode ("", "%05d$:", tlbl->key + 100);
7746 emitcode ("mov", "c,ov");
7747 _startLazyDPSEvaluation ();
7750 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7752 emitcode ("rrc", "a");
7753 aopPut (AOP (result), "a", offset--);
7755 _endLazyDPSEvaluation ();
7756 reAdjustPreg (AOP (result));
7757 emitcode ("", "%05d$:", tlbl1->key + 100);
7758 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7761 freeAsmop (left, NULL, ic, TRUE);
7762 freeAsmop (result, NULL, ic, TRUE);
7765 /*-----------------------------------------------------------------*/
7766 /* genRightShift - generate code for right shifting */
7767 /*-----------------------------------------------------------------*/
7769 genRightShift (iCode * ic)
7771 operand *right, *left, *result;
7775 symbol *tlbl, *tlbl1;
7777 D (emitcode (";", "genRightShift "););
7779 /* if signed then we do it the hard way preserve the
7780 sign bit moving it inwards */
7781 retype = getSpec (operandType (IC_RESULT (ic)));
7783 if (!SPEC_USIGN (retype))
7785 genSignedRightShift (ic);
7789 /* signed & unsigned types are treated the same : i.e. the
7790 signed is NOT propagated inwards : quoting from the
7791 ANSI - standard : "for E1 >> E2, is equivalent to division
7792 by 2**E2 if unsigned or if it has a non-negative value,
7793 otherwise the result is implementation defined ", MY definition
7794 is that the sign does not get propagated */
7796 right = IC_RIGHT (ic);
7797 left = IC_LEFT (ic);
7798 result = IC_RESULT (ic);
7800 aopOp (right, ic, FALSE, FALSE);
7802 #ifdef BETTER_LITERAL_SHIFT
7803 /* if the shift count is known then do it
7804 as efficiently as possible */
7805 if (AOP_TYPE (right) == AOP_LIT)
7807 if (genRightShiftLiteral (left, right, result, ic, 0))
7814 /* shift count is unknown then we have to form
7815 a loop get the loop count in B : Note: we take
7816 only the lower order byte since shifting
7817 more that 32 bits make no sense anyway, ( the
7818 largest size of an object can be only 32 bits ) */
7820 if (AOP_TYPE (right) == AOP_LIT)
7822 /* Really should be handled by genRightShiftLiteral,
7823 * but since I'm too lazy to fix that today, at least we can make
7824 * some small improvement.
7826 emitcode("mov", "b,#0x%02x",
7827 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7831 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7832 emitcode ("inc", "b");
7834 freeAsmop (right, NULL, ic, TRUE);
7835 aopOp (left, ic, FALSE, FALSE);
7836 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7838 /* now move the left to the result if they are not the
7840 if (!sameRegs (AOP (left), AOP (result)) &&
7841 AOP_SIZE (result) > 1)
7844 size = AOP_SIZE (result);
7846 _startLazyDPSEvaluation ();
7849 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7850 if (*l == '@' && IS_AOP_PREG (result))
7853 emitcode ("mov", "a,%s", l);
7854 aopPut (AOP (result), "a", offset);
7857 aopPut (AOP (result), l, offset);
7860 _endLazyDPSEvaluation ();
7863 tlbl = newiTempLabel (NULL);
7864 tlbl1 = newiTempLabel (NULL);
7865 size = AOP_SIZE (result);
7868 /* if it is only one byte then */
7871 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7873 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7874 emitcode ("", "%05d$:", tlbl->key + 100);
7876 emitcode ("rrc", "a");
7877 emitcode ("", "%05d$:", tlbl1->key + 100);
7878 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7879 aopPut (AOP (result), "a", 0);
7883 reAdjustPreg (AOP (result));
7884 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7885 emitcode ("", "%05d$:", tlbl->key + 100);
7887 _startLazyDPSEvaluation ();
7890 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7892 emitcode ("rrc", "a");
7893 aopPut (AOP (result), "a", offset--);
7895 _endLazyDPSEvaluation ();
7896 reAdjustPreg (AOP (result));
7898 emitcode ("", "%05d$:", tlbl1->key + 100);
7899 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7902 freeAsmop (left, NULL, ic, TRUE);
7903 freeAsmop (result, NULL, ic, TRUE);
7906 /*-----------------------------------------------------------------*/
7907 /* genUnpackBits - generates code for unpacking bits */
7908 /*-----------------------------------------------------------------*/
7910 genUnpackBits (operand * result, char *rname, int ptype)
7917 D (emitcode (";", "genUnpackBits ");
7920 etype = getSpec (operandType (result));
7922 /* read the first byte */
7928 emitcode ("mov", "a,@%s", rname);
7932 emitcode ("movx", "a,@%s", rname);
7936 emitcode ("movx", "a,@dptr");
7940 emitcode ("clr", "a");
7941 emitcode ("movc", "a,@a+dptr");
7945 emitcode ("lcall", "__gptrget");
7949 /* if we have bitdisplacement then it fits */
7950 /* into this byte completely or if length is */
7951 /* less than a byte */
7952 if ((shCnt = SPEC_BSTR (etype)) ||
7953 (SPEC_BLEN (etype) <= 8))
7956 /* shift right acc */
7959 emitcode ("anl", "a,#0x%02x",
7960 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7961 aopPut (AOP (result), "a", offset);
7965 /* bit field did not fit in a byte */
7966 rlen = SPEC_BLEN (etype) - 8;
7967 aopPut (AOP (result), "a", offset++);
7976 emitcode ("inc", "%s", rname);
7977 emitcode ("mov", "a,@%s", rname);
7981 emitcode ("inc", "%s", rname);
7982 emitcode ("movx", "a,@%s", rname);
7986 emitcode ("inc", "dptr");
7987 emitcode ("movx", "a,@dptr");
7991 emitcode ("clr", "a");
7992 emitcode ("inc", "dptr");
7993 emitcode ("movc", "a,@a+dptr");
7997 emitcode ("inc", "dptr");
7998 emitcode ("lcall", "__gptrget");
8003 /* if we are done */
8007 aopPut (AOP (result), "a", offset++);
8013 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8014 aopPut (AOP (result), "a", offset);
8021 /*-----------------------------------------------------------------*/
8022 /* genDataPointerGet - generates code when ptr offset is known */
8023 /*-----------------------------------------------------------------*/
8025 genDataPointerGet (operand * left,
8031 int size, offset = 0;
8032 aopOp (result, ic, TRUE, FALSE);
8034 /* get the string representation of the name */
8035 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8036 size = AOP_SIZE (result);
8037 _startLazyDPSEvaluation ();
8041 sprintf (buffer, "(%s + %d)", l + 1, offset);
8043 sprintf (buffer, "%s", l + 1);
8044 aopPut (AOP (result), buffer, offset++);
8046 _endLazyDPSEvaluation ();
8048 freeAsmop (left, NULL, ic, TRUE);
8049 freeAsmop (result, NULL, ic, TRUE);
8052 /*-----------------------------------------------------------------*/
8053 /* genNearPointerGet - emitcode for near pointer fetch */
8054 /*-----------------------------------------------------------------*/
8056 genNearPointerGet (operand * left,
8063 sym_link *rtype, *retype, *letype;
8064 sym_link *ltype = operandType (left);
8067 rtype = operandType (result);
8068 retype = getSpec (rtype);
8069 letype = getSpec (ltype);
8071 aopOp (left, ic, FALSE, FALSE);
8073 /* if left is rematerialisable and
8074 result is not bit variable type and
8075 the left is pointer to data space i.e
8076 lower 128 bytes of space */
8077 if (AOP_TYPE (left) == AOP_IMMD &&
8078 !IS_BITVAR (retype) &&
8079 !IS_BITVAR (letype) &&
8080 DCL_TYPE (ltype) == POINTER)
8082 genDataPointerGet (left, result, ic);
8086 /* if the value is already in a pointer register
8087 then don't need anything more */
8088 if (!AOP_INPREG (AOP (left)))
8090 /* otherwise get a free pointer register */
8092 preg = getFreePtr (ic, &aop, FALSE);
8093 emitcode ("mov", "%s,%s",
8095 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8099 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8101 freeAsmop (left, NULL, ic, TRUE);
8102 aopOp (result, ic, FALSE, FALSE);
8104 /* if bitfield then unpack the bits */
8105 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8106 genUnpackBits (result, rname, POINTER);
8109 /* we have can just get the values */
8110 int size = AOP_SIZE (result);
8115 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8118 emitcode ("mov", "a,@%s", rname);
8119 aopPut (AOP (result), "a", offset);
8123 sprintf (buffer, "@%s", rname);
8124 aopPut (AOP (result), buffer, offset);
8128 emitcode ("inc", "%s", rname);
8132 /* now some housekeeping stuff */
8135 /* we had to allocate for this iCode */
8136 freeAsmop (NULL, aop, ic, TRUE);
8140 /* we did not allocate which means left
8141 already in a pointer register, then
8142 if size > 0 && this could be used again
8143 we have to point it back to where it
8145 if (AOP_SIZE (result) > 1 &&
8146 !OP_SYMBOL (left)->remat &&
8147 (OP_SYMBOL (left)->liveTo > ic->seq ||
8150 int size = AOP_SIZE (result) - 1;
8152 emitcode ("dec", "%s", rname);
8157 freeAsmop (result, NULL, ic, TRUE);
8161 /*-----------------------------------------------------------------*/
8162 /* genPagedPointerGet - emitcode for paged pointer fetch */
8163 /*-----------------------------------------------------------------*/
8165 genPagedPointerGet (operand * left,
8172 sym_link *rtype, *retype, *letype;
8174 rtype = operandType (result);
8175 retype = getSpec (rtype);
8176 letype = getSpec (operandType (left));
8177 aopOp (left, ic, FALSE, FALSE);
8179 /* if the value is already in a pointer register
8180 then don't need anything more */
8181 if (!AOP_INPREG (AOP (left)))
8183 /* otherwise get a free pointer register */
8185 preg = getFreePtr (ic, &aop, FALSE);
8186 emitcode ("mov", "%s,%s",
8188 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8192 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8194 freeAsmop (left, NULL, ic, TRUE);
8195 aopOp (result, ic, FALSE, FALSE);
8197 /* if bitfield then unpack the bits */
8198 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8199 genUnpackBits (result, rname, PPOINTER);
8202 /* we have can just get the values */
8203 int size = AOP_SIZE (result);
8209 emitcode ("movx", "a,@%s", rname);
8210 aopPut (AOP (result), "a", offset);
8215 emitcode ("inc", "%s", rname);
8219 /* now some housekeeping stuff */
8222 /* we had to allocate for this iCode */
8223 freeAsmop (NULL, aop, ic, TRUE);
8227 /* we did not allocate which means left
8228 already in a pointer register, then
8229 if size > 0 && this could be used again
8230 we have to point it back to where it
8232 if (AOP_SIZE (result) > 1 &&
8233 !OP_SYMBOL (left)->remat &&
8234 (OP_SYMBOL (left)->liveTo > ic->seq ||
8237 int size = AOP_SIZE (result) - 1;
8239 emitcode ("dec", "%s", rname);
8244 freeAsmop (result, NULL, ic, TRUE);
8249 /*-----------------------------------------------------------------*/
8250 /* genFarPointerGet - gget value from far space */
8251 /*-----------------------------------------------------------------*/
8253 genFarPointerGet (operand * left,
8254 operand * result, iCode * ic)
8257 sym_link *retype = getSpec (operandType (result));
8258 sym_link *letype = getSpec (operandType (left));
8259 D (emitcode (";", "genFarPointerGet");
8262 aopOp (left, ic, FALSE, FALSE);
8264 /* if the operand is already in dptr
8265 then we do nothing else we move the value to dptr */
8266 if (AOP_TYPE (left) != AOP_STR)
8268 /* if this is remateriazable */
8269 if (AOP_TYPE (left) == AOP_IMMD)
8271 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8275 /* we need to get it byte by byte */
8276 _startLazyDPSEvaluation ();
8277 if (AOP_TYPE (left) != AOP_DPTR)
8279 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8280 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8281 if (options.model == MODEL_FLAT24)
8282 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8286 /* We need to generate a load to DPTR indirect through DPTR. */
8287 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8289 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8290 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8291 if (options.model == MODEL_FLAT24)
8292 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8293 emitcode ("pop", "dph");
8294 emitcode ("pop", "dpl");
8296 _endLazyDPSEvaluation ();
8299 /* so dptr know contains the address */
8300 freeAsmop (left, NULL, ic, TRUE);
8301 aopOp (result, ic, FALSE, TRUE);
8303 /* if bit then unpack */
8304 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8305 genUnpackBits (result, "dptr", FPOINTER);
8308 size = AOP_SIZE (result);
8311 _startLazyDPSEvaluation ();
8318 emitcode ("movx", "a,@dptr");
8320 emitcode ("inc", "dptr");
8322 aopPut (AOP (result), "a", offset++);
8324 _endLazyDPSEvaluation ();
8327 freeAsmop (result, NULL, ic, TRUE);
8330 /*-----------------------------------------------------------------*/
8331 /* emitcodePointerGet - gget value from code space */
8332 /*-----------------------------------------------------------------*/
8334 emitcodePointerGet (operand * left,
8335 operand * result, iCode * ic)
8338 sym_link *retype = getSpec (operandType (result));
8340 aopOp (left, ic, FALSE, FALSE);
8342 /* if the operand is already in dptr
8343 then we do nothing else we move the value to dptr */
8344 if (AOP_TYPE (left) != AOP_STR)
8346 /* if this is remateriazable */
8347 if (AOP_TYPE (left) == AOP_IMMD)
8349 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8352 { /* we need to get it byte by byte */
8353 _startLazyDPSEvaluation ();
8354 if (AOP_TYPE (left) != AOP_DPTR)
8356 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8357 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8358 if (options.model == MODEL_FLAT24)
8359 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8363 /* We need to generate a load to DPTR indirect through DPTR. */
8364 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8366 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8367 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8368 if (options.model == MODEL_FLAT24)
8369 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8370 emitcode ("pop", "dph");
8371 emitcode ("pop", "dpl");
8373 _endLazyDPSEvaluation ();
8376 /* so dptr know contains the address */
8377 freeAsmop (left, NULL, ic, TRUE);
8378 aopOp (result, ic, FALSE, TRUE);
8380 /* if bit then unpack */
8381 if (IS_BITVAR (retype))
8382 genUnpackBits (result, "dptr", CPOINTER);
8385 size = AOP_SIZE (result);
8388 _startLazyDPSEvaluation ();
8394 emitcode ("clr", "a");
8395 emitcode ("movc", "a,@a+dptr");
8397 emitcode ("inc", "dptr");
8398 aopPut (AOP (result), "a", offset++);
8400 _endLazyDPSEvaluation ();
8403 freeAsmop (result, NULL, ic, TRUE);
8406 /*-----------------------------------------------------------------*/
8407 /* genGenPointerGet - gget value from generic pointer space */
8408 /*-----------------------------------------------------------------*/
8410 genGenPointerGet (operand * left,
8411 operand * result, iCode * ic)
8414 sym_link *retype = getSpec (operandType (result));
8415 sym_link *letype = getSpec (operandType (left));
8417 D (emitcode (";", "genGenPointerGet "); );
8419 aopOp (left, ic, FALSE, TRUE);
8421 /* if the operand is already in dptr
8422 then we do nothing else we move the value to dptr */
8423 if (AOP_TYPE (left) != AOP_STR)
8425 /* if this is remateriazable */
8426 if (AOP_TYPE (left) == AOP_IMMD)
8428 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8429 emitcode ("mov", "b,#%d", pointerCode (retype));
8432 { /* we need to get it byte by byte */
8433 _startLazyDPSEvaluation ();
8434 if (AOP(left)->type==AOP_DPTR2) {
8436 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8439 emitcode ("mov", "dpl,%s", l);
8440 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8443 emitcode ("mov", "dph,%s", l);
8444 if (options.model == MODEL_FLAT24) {
8445 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8448 emitcode ("mov", "dpx,%s", l);
8449 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8451 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8454 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8455 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8456 if (options.model == MODEL_FLAT24) {
8457 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8458 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8460 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8463 _endLazyDPSEvaluation ();
8466 /* so dptr know contains the address */
8467 freeAsmop (left, NULL, ic, TRUE);
8468 aopOp (result, ic, FALSE, TRUE);
8470 /* if bit then unpack */
8471 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8472 genUnpackBits (result, "dptr", GPOINTER);
8475 size = AOP_SIZE (result);
8480 emitcode ("lcall", "__gptrget");
8481 aopPut (AOP (result), "a", offset++);
8483 emitcode ("inc", "dptr");
8487 freeAsmop (result, NULL, ic, TRUE);
8490 /*-----------------------------------------------------------------*/
8491 /* genPointerGet - generate code for pointer get */
8492 /*-----------------------------------------------------------------*/
8494 genPointerGet (iCode * ic)
8496 operand *left, *result;
8497 sym_link *type, *etype;
8500 D (emitcode (";", "genPointerGet ");
8503 left = IC_LEFT (ic);
8504 result = IC_RESULT (ic);
8506 /* depending on the type of pointer we need to
8507 move it to the correct pointer register */
8508 type = operandType (left);
8509 etype = getSpec (type);
8510 /* if left is of type of pointer then it is simple */
8511 if (IS_PTR (type) && !IS_FUNC (type->next))
8512 p_type = DCL_TYPE (type);
8515 /* we have to go by the storage class */
8516 p_type = PTR_TYPE (SPEC_OCLS (etype));
8519 /* now that we have the pointer type we assign
8520 the pointer values */
8526 genNearPointerGet (left, result, ic);
8530 genPagedPointerGet (left, result, ic);
8534 genFarPointerGet (left, result, ic);
8538 emitcodePointerGet (left, result, ic);
8542 genGenPointerGet (left, result, ic);
8548 /*-----------------------------------------------------------------*/
8549 /* genPackBits - generates code for packed bit storage */
8550 /*-----------------------------------------------------------------*/
8552 genPackBits (sym_link * etype,
8554 char *rname, int p_type)
8562 blen = SPEC_BLEN (etype);
8563 bstr = SPEC_BSTR (etype);
8565 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8568 /* if the bit lenth is less than or */
8569 /* it exactly fits a byte then */
8570 if (SPEC_BLEN (etype) <= 8)
8572 shCount = SPEC_BSTR (etype);
8574 /* shift left acc */
8577 if (SPEC_BLEN (etype) < 8)
8578 { /* if smaller than a byte */
8584 emitcode ("mov", "b,a");
8585 emitcode ("mov", "a,@%s", rname);
8589 emitcode ("mov", "b,a");
8590 emitcode ("movx", "a,@dptr");
8594 emitcode ("push", "b");
8595 emitcode ("push", "acc");
8596 emitcode ("lcall", "__gptrget");
8597 emitcode ("pop", "b");
8601 emitcode ("anl", "a,#0x%02x", (unsigned char)
8602 ((unsigned char) (0xFF << (blen + bstr)) |
8603 (unsigned char) (0xFF >> (8 - bstr))));
8604 emitcode ("orl", "a,b");
8605 if (p_type == GPOINTER)
8606 emitcode ("pop", "b");
8613 emitcode ("mov", "@%s,a", rname);
8617 emitcode ("movx", "@dptr,a");
8621 emitcode ("lcall", "__gptrput");
8626 if (SPEC_BLEN (etype) <= 8)
8629 emitcode ("inc", "%s", rname);
8630 rLen = SPEC_BLEN (etype);
8632 /* now generate for lengths greater than one byte */
8636 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8648 emitcode ("mov", "@%s,a", rname);
8651 emitcode ("mov", "@%s,%s", rname, l);
8656 emitcode ("movx", "@dptr,a");
8661 emitcode ("lcall", "__gptrput");
8664 emitcode ("inc", "%s", rname);
8669 /* last last was not complete */
8672 /* save the byte & read byte */
8676 emitcode ("mov", "b,a");
8677 emitcode ("mov", "a,@%s", rname);
8681 emitcode ("mov", "b,a");
8682 emitcode ("movx", "a,@dptr");
8686 emitcode ("push", "b");
8687 emitcode ("push", "acc");
8688 emitcode ("lcall", "__gptrget");
8689 emitcode ("pop", "b");
8693 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8694 emitcode ("orl", "a,b");
8697 if (p_type == GPOINTER)
8698 emitcode ("pop", "b");
8704 emitcode ("mov", "@%s,a", rname);
8708 emitcode ("movx", "@dptr,a");
8712 emitcode ("lcall", "__gptrput");
8716 /*-----------------------------------------------------------------*/
8717 /* genDataPointerSet - remat pointer to data space */
8718 /*-----------------------------------------------------------------*/
8720 genDataPointerSet (operand * right,
8724 int size, offset = 0;
8725 char *l, buffer[256];
8727 aopOp (right, ic, FALSE, FALSE);
8729 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8730 size = AOP_SIZE (right);
8734 sprintf (buffer, "(%s + %d)", l + 1, offset);
8736 sprintf (buffer, "%s", l + 1);
8737 emitcode ("mov", "%s,%s", buffer,
8738 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8741 freeAsmop (right, NULL, ic, TRUE);
8742 freeAsmop (result, NULL, ic, TRUE);
8745 /*-----------------------------------------------------------------*/
8746 /* genNearPointerSet - emitcode for near pointer put */
8747 /*-----------------------------------------------------------------*/
8749 genNearPointerSet (operand * right,
8756 sym_link *retype, *letype;
8757 sym_link *ptype = operandType (result);
8759 retype = getSpec (operandType (right));
8760 letype = getSpec (ptype);
8762 aopOp (result, ic, FALSE, FALSE);
8764 /* if the result is rematerializable &
8765 in data space & not a bit variable */
8766 if (AOP_TYPE (result) == AOP_IMMD &&
8767 DCL_TYPE (ptype) == POINTER &&
8768 !IS_BITVAR (retype) &&
8769 !IS_BITVAR (letype))
8771 genDataPointerSet (right, result, ic);
8775 /* if the value is already in a pointer register
8776 then don't need anything more */
8777 if (!AOP_INPREG (AOP (result)))
8779 /* otherwise get a free pointer register */
8781 preg = getFreePtr (ic, &aop, FALSE);
8782 emitcode ("mov", "%s,%s",
8784 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8788 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8790 freeAsmop (result, NULL, ic, TRUE);
8791 aopOp (right, ic, FALSE, FALSE);
8793 /* if bitfield then unpack the bits */
8794 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8795 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8798 /* we have can just get the values */
8799 int size = AOP_SIZE (right);
8804 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8808 emitcode ("mov", "@%s,a", rname);
8811 emitcode ("mov", "@%s,%s", rname, l);
8813 emitcode ("inc", "%s", rname);
8818 /* now some housekeeping stuff */
8821 /* we had to allocate for this iCode */
8822 freeAsmop (NULL, aop, ic, TRUE);
8826 /* we did not allocate which means left
8827 already in a pointer register, then
8828 if size > 0 && this could be used again
8829 we have to point it back to where it
8831 if (AOP_SIZE (right) > 1 &&
8832 !OP_SYMBOL (result)->remat &&
8833 (OP_SYMBOL (result)->liveTo > ic->seq ||
8836 int size = AOP_SIZE (right) - 1;
8838 emitcode ("dec", "%s", rname);
8843 freeAsmop (right, NULL, ic, TRUE);
8848 /*-----------------------------------------------------------------*/
8849 /* genPagedPointerSet - emitcode for Paged pointer put */
8850 /*-----------------------------------------------------------------*/
8852 genPagedPointerSet (operand * right,
8859 sym_link *retype, *letype;
8861 retype = getSpec (operandType (right));
8862 letype = getSpec (operandType (result));
8864 aopOp (result, ic, FALSE, FALSE);
8866 /* if the value is already in a pointer register
8867 then don't need anything more */
8868 if (!AOP_INPREG (AOP (result)))
8870 /* otherwise get a free pointer register */
8872 preg = getFreePtr (ic, &aop, FALSE);
8873 emitcode ("mov", "%s,%s",
8875 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8879 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8881 freeAsmop (result, NULL, ic, TRUE);
8882 aopOp (right, ic, FALSE, FALSE);
8884 /* if bitfield then unpack the bits */
8885 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8886 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8889 /* we have can just get the values */
8890 int size = AOP_SIZE (right);
8895 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8898 emitcode ("movx", "@%s,a", rname);
8901 emitcode ("inc", "%s", rname);
8907 /* now some housekeeping stuff */
8910 /* we had to allocate for this iCode */
8911 freeAsmop (NULL, aop, ic, TRUE);
8915 /* we did not allocate which means left
8916 already in a pointer register, then
8917 if size > 0 && this could be used again
8918 we have to point it back to where it
8920 if (AOP_SIZE (right) > 1 &&
8921 !OP_SYMBOL (result)->remat &&
8922 (OP_SYMBOL (result)->liveTo > ic->seq ||
8925 int size = AOP_SIZE (right) - 1;
8927 emitcode ("dec", "%s", rname);
8932 freeAsmop (right, NULL, ic, TRUE);
8937 /*-----------------------------------------------------------------*/
8938 /* genFarPointerSet - set value from far space */
8939 /*-----------------------------------------------------------------*/
8941 genFarPointerSet (operand * right,
8942 operand * result, iCode * ic)
8945 sym_link *retype = getSpec (operandType (right));
8946 sym_link *letype = getSpec (operandType (result));
8948 aopOp (result, ic, FALSE, FALSE);
8950 /* if the operand is already in dptr
8951 then we do nothing else we move the value to dptr */
8952 if (AOP_TYPE (result) != AOP_STR)
8954 /* if this is remateriazable */
8955 if (AOP_TYPE (result) == AOP_IMMD)
8956 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8959 /* we need to get it byte by byte */
8960 _startLazyDPSEvaluation ();
8961 if (AOP_TYPE (result) != AOP_DPTR)
8963 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8964 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8965 if (options.model == MODEL_FLAT24)
8966 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8970 /* We need to generate a load to DPTR indirect through DPTR. */
8971 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8973 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8974 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8975 if (options.model == MODEL_FLAT24)
8976 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8977 emitcode ("pop", "dph");
8978 emitcode ("pop", "dpl");
8980 _endLazyDPSEvaluation ();
8983 /* so dptr know contains the address */
8984 freeAsmop (result, NULL, ic, TRUE);
8985 aopOp (right, ic, FALSE, TRUE);
8987 /* if bit then unpack */
8988 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8989 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8992 size = AOP_SIZE (right);
8995 _startLazyDPSEvaluation ();
8998 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9004 emitcode ("movx", "@dptr,a");
9006 emitcode ("inc", "dptr");
9008 _endLazyDPSEvaluation ();
9011 freeAsmop (right, NULL, ic, TRUE);
9014 /*-----------------------------------------------------------------*/
9015 /* genGenPointerSet - set value from generic pointer space */
9016 /*-----------------------------------------------------------------*/
9018 genGenPointerSet (operand * right,
9019 operand * result, iCode * ic)
9022 sym_link *retype = getSpec (operandType (right));
9023 sym_link *letype = getSpec (operandType (result));
9025 aopOp (result, ic, FALSE, TRUE);
9027 /* if the operand is already in dptr
9028 then we do nothing else we move the value to dptr */
9029 if (AOP_TYPE (result) != AOP_STR)
9031 _startLazyDPSEvaluation ();
9032 /* if this is remateriazable */
9033 if (AOP_TYPE (result) == AOP_IMMD)
9035 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9036 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9039 { /* we need to get it byte by byte */
9040 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9041 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9042 if (options.model == MODEL_FLAT24) {
9043 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9044 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9046 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9049 _endLazyDPSEvaluation ();
9051 /* so dptr know contains the address */
9052 freeAsmop (result, NULL, ic, TRUE);
9053 aopOp (right, ic, FALSE, TRUE);
9055 /* if bit then unpack */
9056 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9057 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9060 size = AOP_SIZE (right);
9063 _startLazyDPSEvaluation ();
9066 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9072 emitcode ("lcall", "__gptrput");
9074 emitcode ("inc", "dptr");
9076 _endLazyDPSEvaluation ();
9079 freeAsmop (right, NULL, ic, TRUE);
9082 /*-----------------------------------------------------------------*/
9083 /* genPointerSet - stores the value into a pointer location */
9084 /*-----------------------------------------------------------------*/
9086 genPointerSet (iCode * ic)
9088 operand *right, *result;
9089 sym_link *type, *etype;
9092 D (emitcode (";", "genPointerSet ");
9095 right = IC_RIGHT (ic);
9096 result = IC_RESULT (ic);
9098 /* depending on the type of pointer we need to
9099 move it to the correct pointer register */
9100 type = operandType (result);
9101 etype = getSpec (type);
9102 /* if left is of type of pointer then it is simple */
9103 if (IS_PTR (type) && !IS_FUNC (type->next))
9105 p_type = DCL_TYPE (type);
9109 /* we have to go by the storage class */
9110 p_type = PTR_TYPE (SPEC_OCLS (etype));
9113 /* now that we have the pointer type we assign
9114 the pointer values */
9120 genNearPointerSet (right, result, ic);
9124 genPagedPointerSet (right, result, ic);
9128 genFarPointerSet (right, result, ic);
9132 genGenPointerSet (right, result, ic);
9138 /*-----------------------------------------------------------------*/
9139 /* genIfx - generate code for Ifx statement */
9140 /*-----------------------------------------------------------------*/
9142 genIfx (iCode * ic, iCode * popIc)
9144 operand *cond = IC_COND (ic);
9147 D (emitcode (";", "genIfx "););
9149 aopOp (cond, ic, FALSE, FALSE);
9151 /* get the value into acc */
9152 if (AOP_TYPE (cond) != AOP_CRY)
9156 /* the result is now in the accumulator */
9157 freeAsmop (cond, NULL, ic, TRUE);
9159 /* if there was something to be popped then do it */
9163 /* if the condition is a bit variable */
9164 if (isbit && IS_ITEMP (cond) &&
9166 genIfxJump (ic, SPIL_LOC (cond)->rname);
9167 else if (isbit && !IS_ITEMP (cond))
9168 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9170 genIfxJump (ic, "a");
9175 /*-----------------------------------------------------------------*/
9176 /* genAddrOf - generates code for address of */
9177 /*-----------------------------------------------------------------*/
9179 genAddrOf (iCode * ic)
9181 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9184 D (emitcode (";", "genAddrOf ");
9187 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9189 /* if the operand is on the stack then we
9190 need to get the stack offset of this
9194 /* if it has an offset then we need to compute
9198 emitcode ("mov", "a,_bp");
9199 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9200 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9204 /* we can just move _bp */
9205 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9207 /* fill the result with zero */
9208 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9211 if (options.stack10bit && size < (FPTRSIZE - 1))
9214 "*** warning: pointer to stack var truncated.\n");
9221 if (options.stack10bit && offset == 2)
9223 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9227 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9234 /* object not on stack then we need the name */
9235 size = AOP_SIZE (IC_RESULT (ic));
9240 char s[SDCC_NAME_MAX];
9242 sprintf (s, "#(%s >> %d)",
9246 sprintf (s, "#%s", sym->rname);
9247 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9251 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9255 /*-----------------------------------------------------------------*/
9256 /* genArrayInit - generates code for address of */
9257 /*-----------------------------------------------------------------*/
9259 genArrayInit (iCode * ic)
9263 int elementSize = 0, eIndex;
9264 unsigned val, lastVal;
9266 operand *left=IC_LEFT(ic);
9268 D (emitcode (";", "genArrayInit "););
9270 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9272 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9274 // Load immediate value into DPTR.
9275 emitcode("mov", "dptr, %s",
9276 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9278 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9281 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9282 "Unexpected operand to genArrayInit.\n");
9285 // a regression because of SDCCcse.c:1.52
9286 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9287 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9288 if (options.model == MODEL_FLAT24)
9289 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9293 type = operandType(IC_LEFT(ic));
9295 if (type && type->next)
9297 elementSize = getSize(type->next);
9301 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9302 "can't determine element size in genArrayInit.\n");
9306 iLoop = IC_ARRAYILIST(ic);
9311 bool firstpass = TRUE;
9313 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9314 iLoop->count, (int)iLoop->literalValue, elementSize);
9320 symbol *tlbl = NULL;
9322 count = ix > 256 ? 256 : ix;
9326 tlbl = newiTempLabel (NULL);
9327 if (firstpass || (count & 0xff))
9329 emitcode("mov", "b, #0x%x", count & 0xff);
9332 emitcode ("", "%05d$:", tlbl->key + 100);
9337 for (eIndex = 0; eIndex < elementSize; eIndex++)
9339 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9342 emitcode("mov", "a, #0x%x", val);
9346 emitcode("movx", "@dptr, a");
9347 emitcode("inc", "dptr");
9352 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9358 iLoop = iLoop->next;
9361 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9364 /*-----------------------------------------------------------------*/
9365 /* genFarFarAssign - assignment when both are in far space */
9366 /*-----------------------------------------------------------------*/
9368 genFarFarAssign (operand * result, operand * right, iCode * ic)
9370 int size = AOP_SIZE (right);
9372 symbol *rSym = NULL;
9376 /* quick & easy case. */
9377 D(emitcode(";","genFarFarAssign (1 byte case)"););
9378 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9379 freeAsmop (right, NULL, ic, FALSE);
9380 /* now assign DPTR to result */
9382 aopOp(result, ic, FALSE, FALSE);
9384 aopPut(AOP(result), "a", 0);
9385 freeAsmop(result, NULL, ic, FALSE);
9389 /* See if we've got an underlying symbol to abuse. */
9390 if (IS_SYMOP(result) && OP_SYMBOL(result))
9392 if (IS_TRUE_SYMOP(result))
9394 rSym = OP_SYMBOL(result);
9396 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9398 rSym = OP_SYMBOL(result)->usl.spillLoc;
9402 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9404 /* We can use the '390 auto-toggle feature to good effect here. */
9406 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9407 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9408 emitcode ("mov", "dptr,#%s", rSym->rname);
9409 /* DP2 = result, DP1 = right, DP1 is current. */
9412 emitcode("movx", "a,@dptr");
9413 emitcode("movx", "@dptr,a");
9416 emitcode("inc", "dptr");
9417 emitcode("inc", "dptr");
9420 emitcode("mov", "dps, #0");
9421 freeAsmop (right, NULL, ic, FALSE);
9423 some alternative code for processors without auto-toggle
9424 no time to test now, so later well put in...kpb
9425 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9426 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9427 emitcode ("mov", "dptr,#%s", rSym->rname);
9428 /* DP2 = result, DP1 = right, DP1 is current. */
9432 emitcode("movx", "a,@dptr");
9434 emitcode("inc", "dptr");
9435 emitcode("inc", "dps");
9436 emitcode("movx", "@dptr,a");
9438 emitcode("inc", "dptr");
9439 emitcode("inc", "dps");
9441 emitcode("mov", "dps, #0");
9442 freeAsmop (right, NULL, ic, FALSE);
9447 D (emitcode (";", "genFarFarAssign"););
9448 aopOp (result, ic, TRUE, TRUE);
9450 _startLazyDPSEvaluation ();
9454 aopPut (AOP (result),
9455 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9458 _endLazyDPSEvaluation ();
9459 freeAsmop (result, NULL, ic, FALSE);
9460 freeAsmop (right, NULL, ic, FALSE);
9464 /*-----------------------------------------------------------------*/
9465 /* genAssign - generate code for assignment */
9466 /*-----------------------------------------------------------------*/
9468 genAssign (iCode * ic)
9470 operand *result, *right;
9472 unsigned long lit = 0L;
9474 D (emitcode (";", "genAssign ");
9477 result = IC_RESULT (ic);
9478 right = IC_RIGHT (ic);
9480 /* if they are the same */
9481 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9484 aopOp (right, ic, FALSE, FALSE);
9486 emitcode (";", "genAssign: resultIsFar = %s",
9487 isOperandInFarSpace (result) ?
9490 /* special case both in far space */
9491 if ((AOP_TYPE (right) == AOP_DPTR ||
9492 AOP_TYPE (right) == AOP_DPTR2) &&
9493 /* IS_TRUE_SYMOP(result) && */
9494 isOperandInFarSpace (result))
9496 genFarFarAssign (result, right, ic);
9500 aopOp (result, ic, TRUE, FALSE);
9502 /* if they are the same registers */
9503 if (sameRegs (AOP (right), AOP (result)))
9506 /* if the result is a bit */
9507 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9509 /* if the right size is a literal then
9510 we know what the value is */
9511 if (AOP_TYPE (right) == AOP_LIT)
9513 if (((int) operandLitValue (right)))
9514 aopPut (AOP (result), one, 0);
9516 aopPut (AOP (result), zero, 0);
9520 /* the right is also a bit variable */
9521 if (AOP_TYPE (right) == AOP_CRY)
9523 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9524 aopPut (AOP (result), "c", 0);
9530 aopPut (AOP (result), "a", 0);
9534 /* bit variables done */
9536 size = AOP_SIZE (result);
9538 if (AOP_TYPE (right) == AOP_LIT)
9539 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9542 (AOP_TYPE (result) != AOP_REG) &&
9543 (AOP_TYPE (right) == AOP_LIT) &&
9544 !IS_FLOAT (operandType (right)))
9546 _startLazyDPSEvaluation ();
9547 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9549 aopPut (AOP (result),
9550 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9555 /* And now fill the rest with zeros. */
9558 emitcode ("clr", "a");
9562 aopPut (AOP (result), "a", offset++);
9564 _endLazyDPSEvaluation ();
9568 _startLazyDPSEvaluation ();
9571 aopPut (AOP (result),
9572 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9576 _endLazyDPSEvaluation ();
9580 freeAsmop (right, NULL, ic, FALSE);
9581 freeAsmop (result, NULL, ic, TRUE);
9584 /*-----------------------------------------------------------------*/
9585 /* genJumpTab - generates code for jump table */
9586 /*-----------------------------------------------------------------*/
9588 genJumpTab (iCode * ic)
9593 D (emitcode (";", "genJumpTab ");
9596 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9597 /* get the condition into accumulator */
9598 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9600 /* multiply by four! */
9601 emitcode ("add", "a,acc");
9602 emitcode ("add", "a,acc");
9603 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9605 jtab = newiTempLabel (NULL);
9606 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9607 emitcode ("jmp", "@a+dptr");
9608 emitcode ("", "%05d$:", jtab->key + 100);
9609 /* now generate the jump labels */
9610 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9611 jtab = setNextItem (IC_JTLABELS (ic)))
9612 emitcode ("ljmp", "%05d$", jtab->key + 100);
9616 /*-----------------------------------------------------------------*/
9617 /* genCast - gen code for casting */
9618 /*-----------------------------------------------------------------*/
9620 genCast (iCode * ic)
9622 operand *result = IC_RESULT (ic);
9623 sym_link *ctype = operandType (IC_LEFT (ic));
9624 sym_link *rtype = operandType (IC_RIGHT (ic));
9625 operand *right = IC_RIGHT (ic);
9628 D (emitcode (";", "genCast ");
9631 /* if they are equivalent then do nothing */
9632 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9635 aopOp (right, ic, FALSE, FALSE);
9636 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9638 /* if the result is a bit */
9639 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9640 if (IS_BITVAR(OP_SYMBOL(result)->type))
9642 /* if the right size is a literal then
9643 we know what the value is */
9644 if (AOP_TYPE (right) == AOP_LIT)
9646 if (((int) operandLitValue (right)))
9647 aopPut (AOP (result), one, 0);
9649 aopPut (AOP (result), zero, 0);
9654 /* the right is also a bit variable */
9655 if (AOP_TYPE (right) == AOP_CRY)
9657 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9658 aopPut (AOP (result), "c", 0);
9664 aopPut (AOP (result), "a", 0);
9668 /* if they are the same size : or less */
9669 if (AOP_SIZE (result) <= AOP_SIZE (right))
9672 /* if they are in the same place */
9673 if (sameRegs (AOP (right), AOP (result)))
9676 /* if they in different places then copy */
9677 size = AOP_SIZE (result);
9679 _startLazyDPSEvaluation ();
9682 aopPut (AOP (result),
9683 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9687 _endLazyDPSEvaluation ();
9692 /* if the result is of type pointer */
9697 sym_link *type = operandType (right);
9699 /* pointer to generic pointer */
9700 if (IS_GENPTR (ctype))
9706 p_type = DCL_TYPE (type);
9710 #if OLD_CAST_BEHAVIOR
9711 /* KV: we are converting a non-pointer type to
9712 * a generic pointer. This (ifdef'd out) code
9713 * says that the resulting generic pointer
9714 * should have the same class as the storage
9715 * location of the non-pointer variable.
9717 * For example, converting an int (which happens
9718 * to be stored in DATA space) to a pointer results
9719 * in a DATA generic pointer; if the original int
9720 * in XDATA space, so will be the resulting pointer.
9722 * I don't like that behavior, and thus this change:
9723 * all such conversions will be forced to XDATA and
9724 * throw a warning. If you want some non-XDATA
9725 * type, or you want to suppress the warning, you
9726 * must go through an intermediate cast, like so:
9728 * char _generic *gp = (char _xdata *)(intVar);
9730 sym_link *etype = getSpec (type);
9732 /* we have to go by the storage class */
9733 if (SPEC_OCLS (etype) != generic)
9735 p_type = PTR_TYPE (SPEC_OCLS (etype));
9740 /* Converting unknown class (i.e. register variable)
9741 * to generic pointer. This is not good, but
9742 * we'll make a guess (and throw a warning).
9745 werror (W_INT_TO_GEN_PTR_CAST);
9749 /* the first two bytes are known */
9750 size = GPTRSIZE - 1;
9752 _startLazyDPSEvaluation ();
9755 aopPut (AOP (result),
9756 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9760 _endLazyDPSEvaluation ();
9762 /* the last byte depending on type */
9780 /* this should never happen */
9781 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9782 "got unknown pointer type");
9785 aopPut (AOP (result), l, GPTRSIZE - 1);
9789 /* just copy the pointers */
9790 size = AOP_SIZE (result);
9792 _startLazyDPSEvaluation ();
9795 aopPut (AOP (result),
9796 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9800 _endLazyDPSEvaluation ();
9804 /* so we now know that the size of destination is greater
9805 than the size of the source */
9806 /* we move to result for the size of source */
9807 size = AOP_SIZE (right);
9809 _startLazyDPSEvaluation ();
9812 aopPut (AOP (result),
9813 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9817 _endLazyDPSEvaluation ();
9819 /* now depending on the sign of the source && destination */
9820 size = AOP_SIZE (result) - AOP_SIZE (right);
9821 /* if unsigned or not an integral type */
9822 /* also, if the source is a bit, we don't need to sign extend, because
9823 * it can't possibly have set the sign bit.
9825 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9829 aopPut (AOP (result), zero, offset++);
9834 /* we need to extend the sign :{ */
9835 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9836 FALSE, FALSE, TRUE);
9838 emitcode ("rlc", "a");
9839 emitcode ("subb", "a,acc");
9841 aopPut (AOP (result), "a", offset++);
9844 /* we are done hurray !!!! */
9847 freeAsmop (right, NULL, ic, TRUE);
9848 freeAsmop (result, NULL, ic, TRUE);
9852 /*-----------------------------------------------------------------*/
9853 /* genDjnz - generate decrement & jump if not zero instrucion */
9854 /*-----------------------------------------------------------------*/
9856 genDjnz (iCode * ic, iCode * ifx)
9862 /* if the if condition has a false label
9863 then we cannot save */
9867 /* if the minus is not of the form
9869 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9870 !IS_OP_LITERAL (IC_RIGHT (ic)))
9873 if (operandLitValue (IC_RIGHT (ic)) != 1)
9876 /* if the size of this greater than one then no
9878 if (getSize (operandType (IC_RESULT (ic))) > 1)
9881 /* otherwise we can save BIG */
9882 D(emitcode(";", "genDjnz"););
9884 lbl = newiTempLabel (NULL);
9885 lbl1 = newiTempLabel (NULL);
9887 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9889 if (AOP_NEEDSACC(IC_RESULT(ic)))
9891 /* If the result is accessed indirectly via
9892 * the accumulator, we must explicitly write
9893 * it back after the decrement.
9895 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9897 if (strcmp(rByte, "a"))
9899 /* Something is hopelessly wrong */
9900 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9901 __FILE__, __LINE__);
9902 /* We can just give up; the generated code will be inefficient,
9905 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9908 emitcode ("dec", "%s", rByte);
9909 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9910 emitcode ("jnz", "%05d$", lbl->key + 100);
9912 else if (IS_AOP_PREG (IC_RESULT (ic)))
9914 emitcode ("dec", "%s",
9915 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9916 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9917 emitcode ("jnz", "%05d$", lbl->key + 100);
9921 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9924 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9925 emitcode ("", "%05d$:", lbl->key + 100);
9926 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9927 emitcode ("", "%05d$:", lbl1->key + 100);
9929 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9934 /*-----------------------------------------------------------------*/
9935 /* genReceive - generate code for a receive iCode */
9936 /*-----------------------------------------------------------------*/
9938 genReceive (iCode * ic)
9941 D (emitcode (";", "genReceive ");
9944 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9945 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9946 IS_TRUE_SYMOP (IC_RESULT (ic))))
9948 int size = getSize (operandType (IC_RESULT (ic)));
9949 int offset = fReturnSizeDS390 - size;
9952 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9953 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9956 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9957 size = AOP_SIZE (IC_RESULT (ic));
9961 emitcode ("pop", "acc");
9962 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9969 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9971 assignResultValue (IC_RESULT (ic));
9974 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9977 /*-----------------------------------------------------------------*/
9978 /* gen390Code - generate code for Dallas 390 based controllers */
9979 /*-----------------------------------------------------------------*/
9981 gen390Code (iCode * lic)
9986 lineHead = lineCurr = NULL;
9988 if (options.model == MODEL_FLAT24) {
9989 fReturnSizeDS390 = 5;
9990 fReturn = fReturn24;
9992 fReturnSizeDS390 = 4;
9993 fReturn = fReturn16;
9994 options.stack10bit=0;
9998 /* print the allocation information */
10000 printAllocInfo (currFunc, codeOutFile);
10002 /* if debug information required */
10003 if (options.debug && currFunc)
10005 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10007 if (IS_STATIC (currFunc->etype))
10008 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10010 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10013 /* stack pointer name */
10014 if (options.useXstack)
10020 for (ic = lic; ic; ic = ic->next)
10023 if (cln != ic->lineno)
10028 emitcode ("", "C$%s$%d$%d$%d ==.",
10029 FileBaseName (ic->filename), ic->lineno,
10030 ic->level, ic->block);
10033 emitcode (";", "%s %d", ic->filename, ic->lineno);
10036 /* if the result is marked as
10037 spilt and rematerializable or code for
10038 this has already been generated then
10040 if (resultRemat (ic) || ic->generated)
10043 /* depending on the operation */
10063 /* IPOP happens only when trying to restore a
10064 spilt live range, if there is an ifx statement
10065 following this pop then the if statement might
10066 be using some of the registers being popped which
10067 would destory the contents of the register so
10068 we need to check for this condition and handle it */
10070 ic->next->op == IFX &&
10071 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10072 genIfx (ic->next, ic);
10090 genEndFunction (ic);
10110 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10127 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10131 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10138 /* note these two are xlated by algebraic equivalence
10139 during parsing SDCC.y */
10140 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10141 "got '>=' or '<=' shouldn't have come here");
10145 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10157 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10161 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10165 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10189 genRightShift (ic);
10192 case GET_VALUE_AT_ADDRESS:
10193 genPointerGet (ic);
10197 if (POINTER_SET (ic))
10198 genPointerSet (ic);
10224 addSet (&_G.sendSet, ic);
10237 /* now we are ready to call the
10238 peep hole optimizer */
10239 if (!options.nopeep)
10240 peepHole (&lineHead);
10242 /* now do the actual printing */
10243 printLine (lineHead, codeOutFile);