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 || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1778 IFFUNC_ISNAKED(OP_SYM_TYPE(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 dtype = operandType (IC_LEFT (ic));
2199 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2200 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2201 IFFUNC_ISISR (currFunc->type))
2205 /* This is unexpected; the bank should have been saved in
2208 saveRBank (FUNC_REGBANK (dtype), 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 ((FUNC_REGBANK(dtype)) << 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 ((FUNC_REGBANK(currFunc->type)) << 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 && !IFFUNC_CALLEESAVES(dtype))
2347 unsaveRegisters (ic);
2349 /* if register bank was saved then pop them */
2351 unsaveRBank (FUNC_REGBANK (dtype), 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 dtype = operandType (IC_LEFT (ic));
2376 IFFUNC_ISISR (currFunc->type) &&
2377 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2378 saveRBank (FUNC_REGBANK (dtype), 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 (FUNC_REGBANK (currFunc->type) !=
2471 FUNC_REGBANK (dtype)))
2472 unsaveRBank (FUNC_REGBANK (dtype), 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 ftype = operandType (IC_LEFT (ic));
2548 if (IFFUNC_ISNAKED(ftype))
2550 emitcode(";", "naked function: no prologue.");
2554 /* if critical function then turn interrupts off */
2555 if (IFFUNC_ISCRITICAL (ftype))
2556 emitcode ("clr", "ea");
2558 /* here we need to generate the equates for the
2559 register bank if required */
2560 if (FUNC_REGBANK (ftype) != rbank)
2564 rbank = FUNC_REGBANK (ftype);
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 (IFFUNC_ISISR (sym->type))
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 (!FUNC_REGBANK (sym->type))
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 */
2616 if (!IFFUNC_HASFCALL(sym->type))
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;
2653 if (IFFUNC_HASFCALL(sym->type))
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 dtype = operandType (IC_LEFT(i));
2675 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2677 /* Mark this bank for saving. */
2678 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2680 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2684 banksToSave |= (1 << FUNC_REGBANK(dtype));
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 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2720 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2722 if (banksToSave & (1 << ix))
2724 saveRBank(ix, NULL, FALSE);
2728 // jwk: this needs a closer look
2729 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2734 /* if callee-save to be used for this function
2735 then save the registers being used in this function */
2736 if (IFFUNC_CALLEESAVES(sym->type))
2740 /* if any registers used */
2743 /* save the registers used */
2744 for (i = 0; i < sym->regsUsed->size; i++)
2746 if (bitVectBitValue (sym->regsUsed, i) ||
2747 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2749 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2757 /* set the register bank to the desired value */
2758 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2761 emitcode ("push", "psw");
2762 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2765 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2768 if (options.useXstack)
2770 emitcode ("mov", "r0,%s", spname);
2771 emitcode ("mov", "a,_bp");
2772 emitcode ("movx", "@r0,a");
2773 emitcode ("inc", "%s", spname);
2777 /* set up the stack */
2778 emitcode ("push", "_bp"); /* save the callers stack */
2780 emitcode ("mov", "_bp,%s", spname);
2783 /* adjust the stack for the function */
2789 werror (W_STACK_OVERFLOW, sym->name);
2791 if (i > 3 && sym->recvSize < 4)
2794 emitcode ("mov", "a,sp");
2795 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2796 emitcode ("mov", "sp,a");
2801 emitcode ("inc", "sp");
2807 emitcode ("mov", "a,_spx");
2808 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2809 emitcode ("mov", "_spx,a");
2814 /*-----------------------------------------------------------------*/
2815 /* genEndFunction - generates epilogue for functions */
2816 /*-----------------------------------------------------------------*/
2818 genEndFunction (iCode * ic)
2820 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2822 D (emitcode (";", "genEndFunction "););
2824 if (IFFUNC_ISNAKED(sym->type))
2826 emitcode(";", "naked function: no epilogue.");
2830 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2832 emitcode ("mov", "%s,_bp", spname);
2835 /* if use external stack but some variables were
2836 added to the local stack then decrement the
2838 if (options.useXstack && sym->stack)
2840 emitcode ("mov", "a,sp");
2841 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2842 emitcode ("mov", "sp,a");
2846 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2848 if (options.useXstack)
2850 emitcode ("mov", "r0,%s", spname);
2851 emitcode ("movx", "a,@r0");
2852 emitcode ("mov", "_bp,a");
2853 emitcode ("dec", "%s", spname);
2857 emitcode ("pop", "_bp");
2861 /* restore the register bank */
2862 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2864 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2865 || !options.useXstack)
2867 /* Special case of ISR using non-zero bank with useXstack
2870 emitcode ("pop", "psw");
2874 if (IFFUNC_ISISR (sym->type))
2877 /* now we need to restore the registers */
2878 /* if this isr has no bank i.e. is going to
2879 run with bank 0 , then we need to save more
2881 if (!FUNC_REGBANK (sym->type))
2883 /* if this function does not call any other
2884 function then we can be economical and
2885 save only those registers that are used */
2886 if (!IFFUNC_HASFCALL(sym->type))
2890 /* if any registers used */
2893 /* save the registers used */
2894 for (i = sym->regsUsed->size; i >= 0; i--)
2896 if (bitVectBitValue (sym->regsUsed, i) ||
2897 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2898 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2905 /* this function has a function call cannot
2906 determines register usage so we will have to pop the
2908 unsaveRBank (0, ic, FALSE);
2913 /* This ISR uses a non-zero bank.
2915 * Restore any register banks saved by genFunction
2918 // jwk: this needs a closer look
2919 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2922 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2924 if (savedBanks & (1 << ix))
2926 unsaveRBank(ix, NULL, FALSE);
2930 if (options.useXstack)
2932 /* Restore bank AFTER calling unsaveRBank,
2933 * since it can trash r0.
2935 emitcode ("pop", "psw");
2939 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2941 if (options.stack10bit)
2943 emitcode ("pop", DP2_RESULT_REG);
2944 emitcode ("pop", "dpx1");
2945 emitcode ("pop", "dph1");
2946 emitcode ("pop", "dpl1");
2948 emitcode ("pop", "dps");
2949 emitcode ("pop", "dpx");
2951 if (!inExcludeList ("dph"))
2952 emitcode ("pop", "dph");
2953 if (!inExcludeList ("dpl"))
2954 emitcode ("pop", "dpl");
2955 if (!inExcludeList ("b"))
2956 emitcode ("pop", "b");
2957 if (!inExcludeList ("acc"))
2958 emitcode ("pop", "acc");
2960 if (IFFUNC_ISCRITICAL (sym->type))
2961 emitcode ("setb", "ea");
2963 /* if debug then send end of function */
2964 if (options.debug && currFunc) {
2966 emitcode ("", "C$%s$%d$%d$%d ==.",
2967 FileBaseName (ic->filename), currFunc->lastLine,
2968 ic->level, ic->block);
2969 if (IS_STATIC (currFunc->etype))
2970 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2972 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2976 emitcode ("reti", "");
2980 if (IFFUNC_ISCRITICAL (sym->type))
2981 emitcode ("setb", "ea");
2983 if (IFFUNC_CALLEESAVES(sym->type))
2987 /* if any registers used */
2990 /* save the registers used */
2991 for (i = sym->regsUsed->size; i >= 0; i--)
2993 if (bitVectBitValue (sym->regsUsed, i) ||
2994 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2995 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3001 /* if debug then send end of function */
3002 if (options.debug && currFunc)
3005 emitcode ("", "C$%s$%d$%d$%d ==.",
3006 FileBaseName (ic->filename), currFunc->lastLine,
3007 ic->level, ic->block);
3008 if (IS_STATIC (currFunc->etype))
3009 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3011 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3015 emitcode ("ret", "");
3020 /*-----------------------------------------------------------------*/
3021 /* genRet - generate code for return statement */
3022 /*-----------------------------------------------------------------*/
3026 int size, offset = 0, pushed = 0;
3028 D (emitcode (";", "genRet ");
3031 /* if we have no return value then
3032 just generate the "ret" */
3036 /* we have something to return then
3037 move the return value into place */
3038 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3039 size = AOP_SIZE (IC_LEFT (ic));
3041 _startLazyDPSEvaluation ();
3045 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3047 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3048 FALSE, TRUE, FALSE);
3049 emitcode ("push", "%s", l);
3054 /* Since A is the last element of fReturn,
3055 * is is OK to clobber it in the aopGet.
3057 l = aopGet (AOP (IC_LEFT (ic)), offset,
3058 FALSE, FALSE, TRUE);
3059 if (strcmp (fReturn[offset], l))
3060 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3063 _endLazyDPSEvaluation ();
3070 if (strcmp (fReturn[pushed], "a"))
3071 emitcode ("pop", fReturn[pushed]);
3073 emitcode ("pop", "acc");
3076 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3079 /* generate a jump to the return label
3080 if the next is not the return statement */
3081 if (!(ic->next && ic->next->op == LABEL &&
3082 IC_LABEL (ic->next) == returnLabel))
3084 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3088 /*-----------------------------------------------------------------*/
3089 /* genLabel - generates a label */
3090 /*-----------------------------------------------------------------*/
3092 genLabel (iCode * ic)
3094 /* special case never generate */
3095 if (IC_LABEL (ic) == entryLabel)
3098 D (emitcode (";", "genLabel ");
3101 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3104 /*-----------------------------------------------------------------*/
3105 /* genGoto - generates a ljmp */
3106 /*-----------------------------------------------------------------*/
3108 genGoto (iCode * ic)
3110 D (emitcode (";", "genGoto ");
3112 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3115 /*-----------------------------------------------------------------*/
3116 /* findLabelBackwards: walks back through the iCode chain looking */
3117 /* for the given label. Returns number of iCode instructions */
3118 /* between that label and given ic. */
3119 /* Returns zero if label not found. */
3120 /*-----------------------------------------------------------------*/
3122 findLabelBackwards (iCode * ic, int key)
3131 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3133 /* printf("findLabelBackwards = %d\n", count); */
3141 /*-----------------------------------------------------------------*/
3142 /* genPlusIncr :- does addition with increment if possible */
3143 /*-----------------------------------------------------------------*/
3145 genPlusIncr (iCode * ic)
3147 unsigned int icount;
3148 unsigned int size = getDataSize (IC_RESULT (ic));
3150 /* will try to generate an increment */
3151 /* if the right side is not a literal
3153 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3156 /* if the literal value of the right hand side
3157 is greater than 4 then it is not worth it */
3158 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3161 /* if increment 16 bits in register */
3163 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3164 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3165 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3173 /* If the next instruction is a goto and the goto target
3174 * is <= 5 instructions previous to this, we can generate
3175 * jumps straight to that target.
3177 if (ic->next && ic->next->op == GOTO
3178 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3181 emitcode (";", "tail increment optimized (range %d)", labelRange);
3182 tlbl = IC_LABEL (ic->next);
3187 tlbl = newiTempLabel (NULL);
3190 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3191 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3192 IS_AOP_PREG (IC_RESULT (ic)))
3193 emitcode ("cjne", "%s,#0x00,%05d$"
3194 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3198 emitcode ("clr", "a");
3199 emitcode ("cjne", "a,%s,%05d$"
3200 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3204 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3207 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3208 IS_AOP_PREG (IC_RESULT (ic)))
3209 emitcode ("cjne", "%s,#0x00,%05d$"
3210 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3213 emitcode ("cjne", "a,%s,%05d$"
3214 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3217 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3221 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3222 IS_AOP_PREG (IC_RESULT (ic)))
3223 emitcode ("cjne", "%s,#0x00,%05d$"
3224 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3228 emitcode ("cjne", "a,%s,%05d$"
3229 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3232 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3237 emitcode ("", "%05d$:", tlbl->key + 100);
3242 /* if the sizes are greater than 1 then we cannot */
3243 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3244 AOP_SIZE (IC_LEFT (ic)) > 1)
3247 /* we can if the aops of the left & result match or
3248 if they are in registers and the registers are the
3251 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3252 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3253 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3258 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3259 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3260 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3265 _startLazyDPSEvaluation ();
3268 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3270 _endLazyDPSEvaluation ();
3279 /*-----------------------------------------------------------------*/
3280 /* outBitAcc - output a bit in acc */
3281 /*-----------------------------------------------------------------*/
3283 outBitAcc (operand * result)
3285 symbol *tlbl = newiTempLabel (NULL);
3286 /* if the result is a bit */
3287 if (AOP_TYPE (result) == AOP_CRY)
3289 aopPut (AOP (result), "a", 0);
3293 emitcode ("jz", "%05d$", tlbl->key + 100);
3294 emitcode ("mov", "a,%s", one);
3295 emitcode ("", "%05d$:", tlbl->key + 100);
3300 /*-----------------------------------------------------------------*/
3301 /* genPlusBits - generates code for addition of two bits */
3302 /*-----------------------------------------------------------------*/
3304 genPlusBits (iCode * ic)
3306 D (emitcode (";", "genPlusBits ");
3308 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3310 symbol *lbl = newiTempLabel (NULL);
3311 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3312 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3313 emitcode ("cpl", "c");
3314 emitcode ("", "%05d$:", (lbl->key + 100));
3315 outBitC (IC_RESULT (ic));
3319 emitcode ("clr", "a");
3320 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3321 emitcode ("rlc", "a");
3322 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3323 emitcode ("addc", "a,#0x00");
3324 outAcc (IC_RESULT (ic));
3329 adjustArithmeticResult (iCode * ic)
3331 if (opIsGptr (IC_RESULT (ic)) &&
3332 opIsGptr (IC_LEFT (ic)) &&
3333 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3335 aopPut (AOP (IC_RESULT (ic)),
3336 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3340 if (opIsGptr (IC_RESULT (ic)) &&
3341 opIsGptr (IC_RIGHT (ic)) &&
3342 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3344 aopPut (AOP (IC_RESULT (ic)),
3345 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3349 if (opIsGptr (IC_RESULT (ic)) &&
3350 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3351 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3352 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3353 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3356 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3357 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3361 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3362 // (because all three operands are in far space).
3363 #define AOP_OP_3(ic) \
3364 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3365 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3366 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3367 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3368 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3369 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3371 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3373 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3376 // Macro to aopOp all three operands of an ic. If this cannot be done,
3377 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3378 // will be set TRUE. The caller must then handle the case specially, noting
3379 // that the IC_RESULT operand is not aopOp'd.
3380 #define AOP_OP_3_NOFATAL(ic, rc) \
3381 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3382 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3383 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3384 isOperandInFarSpace(IC_RESULT(ic))) \
3386 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3391 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3392 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3394 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3395 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3397 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3399 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3403 // aopOp the left & right operands of an ic.
3404 #define AOP_OP_2(ic) \
3405 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3406 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3408 // convienience macro.
3409 #define AOP_SET_LOCALS(ic) \
3410 left = IC_LEFT(ic); \
3411 right = IC_RIGHT(ic); \
3412 result = IC_RESULT(ic);
3415 // Given an integer value of pushedSize bytes on the stack,
3416 // adjust it to be resultSize bytes, either by discarding
3417 // the most significant bytes or by zero-padding.
3419 // On exit from this macro, pushedSize will have been adjusted to
3420 // equal resultSize, and ACC may be trashed.
3421 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3422 /* If the pushed data is bigger than the result, \
3423 * simply discard unused bytes. Icky, but works. \
3425 while (pushedSize > resultSize) \
3427 D (emitcode (";", "discarding unused result byte."););\
3428 emitcode ("pop", "acc"); \
3431 if (pushedSize < resultSize) \
3433 emitcode ("clr", "a"); \
3434 /* Conversly, we haven't pushed enough here. \
3435 * just zero-pad, and all is well. \
3437 while (pushedSize < resultSize) \
3439 emitcode("push", "acc"); \
3443 assert(pushedSize == resultSize);
3445 /*-----------------------------------------------------------------*/
3446 /* genPlus - generates code for addition */
3447 /*-----------------------------------------------------------------*/
3449 genPlus (iCode * ic)
3451 int size, offset = 0;
3452 bool pushResult = FALSE;
3455 D (emitcode (";", "genPlus "););
3457 /* special cases :- */
3459 AOP_OP_3_NOFATAL (ic, pushResult);
3462 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3467 /* if literal, literal on the right or
3468 if left requires ACC or right is already
3470 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3471 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3472 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3474 operand *t = IC_RIGHT (ic);
3475 IC_RIGHT (ic) = IC_LEFT (ic);
3477 emitcode (";", "Swapped plus args.");
3480 /* if both left & right are in bit
3482 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3483 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3489 /* if left in bit space & right literal */
3490 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3491 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3493 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3494 /* if result in bit space */
3495 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3497 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3498 emitcode ("cpl", "c");
3499 outBitC (IC_RESULT (ic));
3503 size = getDataSize (IC_RESULT (ic));
3504 _startLazyDPSEvaluation ();
3507 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3508 emitcode ("addc", "a,#00");
3509 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3511 _endLazyDPSEvaluation ();
3516 /* if I can do an increment instead
3517 of add then GOOD for ME */
3518 if (genPlusIncr (ic) == TRUE)
3520 emitcode (";", "did genPlusIncr");
3525 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3527 _startLazyDPSEvaluation ();
3530 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3532 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3534 emitcode ("add", "a,%s",
3535 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3537 emitcode ("addc", "a,%s",
3538 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3542 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3544 /* right is going to use ACC or we would have taken the
3547 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3549 D(emitcode(";", "+ AOP_ACC special case."););
3550 emitcode("xch", "a, %s", DP2_RESULT_REG);
3552 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3555 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3558 emitcode("add", "a, %s", DP2_RESULT_REG);
3562 emitcode ("add", "a,%s",
3563 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3568 emitcode ("addc", "a,%s",
3569 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3574 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3578 emitcode ("push", "acc");
3582 _endLazyDPSEvaluation ();
3586 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3588 size = getDataSize (IC_LEFT (ic));
3589 rSize = getDataSize (IC_RESULT (ic));
3591 ADJUST_PUSHED_RESULT(size, rSize);
3593 _startLazyDPSEvaluation ();
3596 emitcode ("pop", "acc");
3597 aopPut (AOP (IC_RESULT (ic)), "a", size);
3599 _endLazyDPSEvaluation ();
3602 adjustArithmeticResult (ic);
3605 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3606 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3607 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3610 /*-----------------------------------------------------------------*/
3611 /* genMinusDec :- does subtraction with deccrement if possible */
3612 /*-----------------------------------------------------------------*/
3614 genMinusDec (iCode * ic)
3616 unsigned int icount;
3617 unsigned int size = getDataSize (IC_RESULT (ic));
3619 /* will try to generate an increment */
3620 /* if the right side is not a literal
3622 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3625 /* if the literal value of the right hand side
3626 is greater than 4 then it is not worth it */
3627 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3630 /* if decrement 16 bits in register */
3631 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3632 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3633 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3641 /* If the next instruction is a goto and the goto target
3642 * is <= 5 instructions previous to this, we can generate
3643 * jumps straight to that target.
3645 if (ic->next && ic->next->op == GOTO
3646 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3649 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3650 tlbl = IC_LABEL (ic->next);
3655 tlbl = newiTempLabel (NULL);
3659 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3660 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3661 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3662 IS_AOP_PREG (IC_RESULT (ic)))
3663 emitcode ("cjne", "%s,#0xff,%05d$"
3664 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3668 emitcode ("mov", "a,#0xff");
3669 emitcode ("cjne", "a,%s,%05d$"
3670 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3673 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3676 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3677 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3678 IS_AOP_PREG (IC_RESULT (ic)))
3679 emitcode ("cjne", "%s,#0xff,%05d$"
3680 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3684 emitcode ("cjne", "a,%s,%05d$"
3685 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3688 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3692 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3693 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3694 IS_AOP_PREG (IC_RESULT (ic)))
3695 emitcode ("cjne", "%s,#0xff,%05d$"
3696 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3700 emitcode ("cjne", "a,%s,%05d$"
3701 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3704 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3708 emitcode ("", "%05d$:", tlbl->key + 100);
3713 /* if the sizes are greater than 1 then we cannot */
3714 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3715 AOP_SIZE (IC_LEFT (ic)) > 1)
3718 /* we can if the aops of the left & result match or
3719 if they are in registers and the registers are the
3722 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3723 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3724 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3727 _startLazyDPSEvaluation ();
3730 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3732 _endLazyDPSEvaluation ();
3740 /*-----------------------------------------------------------------*/
3741 /* addSign - complete with sign */
3742 /*-----------------------------------------------------------------*/
3744 addSign (operand * result, int offset, int sign)
3746 int size = (getDataSize (result) - offset);
3749 _startLazyDPSEvaluation();
3752 emitcode ("rlc", "a");
3753 emitcode ("subb", "a,acc");
3756 aopPut (AOP (result), "a", offset++);
3763 aopPut (AOP (result), zero, offset++);
3766 _endLazyDPSEvaluation();
3770 /*-----------------------------------------------------------------*/
3771 /* genMinusBits - generates code for subtraction of two bits */
3772 /*-----------------------------------------------------------------*/
3774 genMinusBits (iCode * ic)
3776 symbol *lbl = newiTempLabel (NULL);
3778 D (emitcode (";", "genMinusBits "););
3780 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3782 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3783 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3784 emitcode ("cpl", "c");
3785 emitcode ("", "%05d$:", (lbl->key + 100));
3786 outBitC (IC_RESULT (ic));
3790 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3791 emitcode ("subb", "a,acc");
3792 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3793 emitcode ("inc", "a");
3794 emitcode ("", "%05d$:", (lbl->key + 100));
3795 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3796 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3800 /*-----------------------------------------------------------------*/
3801 /* genMinus - generates code for subtraction */
3802 /*-----------------------------------------------------------------*/
3804 genMinus (iCode * ic)
3806 int size, offset = 0;
3808 unsigned long lit = 0L;
3809 bool pushResult = FALSE;
3811 D (emitcode (";", "genMinus "););
3813 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3814 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3815 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3816 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3822 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3824 /* special cases :- */
3825 /* if both left & right are in bit space */
3826 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3827 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3833 /* if I can do an decrement instead
3834 of subtract then GOOD for ME */
3835 if (genMinusDec (ic) == TRUE)
3840 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3842 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3848 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3853 /* if literal, add a,#-lit, else normal subb */
3854 _startLazyDPSEvaluation ();
3857 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3858 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3859 emitcode ("subb", "a,%s",
3860 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3863 /* first add without previous c */
3865 if (!size && lit==-1) {
3866 emitcode ("dec", "a");
3868 emitcode ("add", "a,#0x%02x",
3869 (unsigned int) (lit & 0x0FFL));
3872 emitcode ("addc", "a,#0x%02x",
3873 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3879 emitcode ("push", "acc");
3883 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3887 _endLazyDPSEvaluation ();
3891 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3893 size = getDataSize (IC_LEFT (ic));
3894 rSize = getDataSize (IC_RESULT (ic));
3896 ADJUST_PUSHED_RESULT(size, rSize);
3898 _startLazyDPSEvaluation ();
3901 emitcode ("pop", "acc");
3902 aopPut (AOP (IC_RESULT (ic)), "a", size);
3904 _endLazyDPSEvaluation ();
3907 adjustArithmeticResult (ic);
3910 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3911 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3912 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3916 /*-----------------------------------------------------------------*/
3917 /* genMultbits :- multiplication of bits */
3918 /*-----------------------------------------------------------------*/
3920 genMultbits (operand * left,
3924 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3925 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3930 /*-----------------------------------------------------------------*/
3931 /* genMultOneByte : 8*8=8/16 bit multiplication */
3932 /*-----------------------------------------------------------------*/
3934 genMultOneByte (operand * left,
3938 sym_link *opetype = operandType (result);
3940 int size=AOP_SIZE(result);
3942 if (size<1 || size>2) {
3943 // this should never happen
3944 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3945 AOP_SIZE(result), __FILE__, lineno);
3949 /* (if two literals: the value is computed before) */
3950 /* if one literal, literal on the right */
3951 if (AOP_TYPE (left) == AOP_LIT)
3956 emitcode (";", "swapped left and right");
3959 if (SPEC_USIGN(opetype)
3960 // ignore the sign of left and right, what else can we do?
3961 || (SPEC_USIGN(operandType(left)) &&
3962 SPEC_USIGN(operandType(right)))) {
3963 // just an unsigned 8*8=8/16 multiply
3964 //emitcode (";","unsigned");
3965 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3966 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3967 emitcode ("mul", "ab");
3968 aopPut (AOP (result), "a", 0);
3970 aopPut (AOP (result), "b", 1);
3975 // we have to do a signed multiply
3977 emitcode (";", "signed");
3978 emitcode ("clr", "F0"); // reset sign flag
3979 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3981 lbl=newiTempLabel(NULL);
3982 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3983 // left side is negative, 8-bit two's complement, this fails for -128
3984 emitcode ("setb", "F0"); // set sign flag
3985 emitcode ("cpl", "a");
3986 emitcode ("inc", "a");
3988 emitcode ("", "%05d$:", lbl->key+100);
3991 if (AOP_TYPE(right)==AOP_LIT) {
3992 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3993 /* AND literal negative */
3994 if ((int) val < 0) {
3995 emitcode ("cpl", "F0"); // complement sign flag
3996 emitcode ("mov", "b,#0x%02x", -val);
3998 emitcode ("mov", "b,#0x%02x", val);
4001 lbl=newiTempLabel(NULL);
4002 emitcode ("mov", "b,a");
4003 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4004 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4005 // right side is negative, 8-bit two's complement
4006 emitcode ("cpl", "F0"); // complement sign flag
4007 emitcode ("cpl", "a");
4008 emitcode ("inc", "a");
4009 emitcode ("", "%05d$:", lbl->key+100);
4011 emitcode ("mul", "ab");
4013 lbl=newiTempLabel(NULL);
4014 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4015 // only ONE op was negative, we have to do a 8/16-bit two's complement
4016 emitcode ("cpl", "a"); // lsb
4018 emitcode ("inc", "a");
4020 emitcode ("add", "a,#1");
4021 emitcode ("xch", "a,b");
4022 emitcode ("cpl", "a"); // msb
4023 emitcode ("addc", "a,#0");
4024 emitcode ("xch", "a,b");
4027 emitcode ("", "%05d$:", lbl->key+100);
4028 aopPut (AOP (result), "a", 0);
4030 aopPut (AOP (result), "b", 1);
4034 /*-----------------------------------------------------------------*/
4035 /* genMult - generates code for multiplication */
4036 /*-----------------------------------------------------------------*/
4038 genMult (iCode * ic)
4040 operand *left = IC_LEFT (ic);
4041 operand *right = IC_RIGHT (ic);
4042 operand *result = IC_RESULT (ic);
4044 D (emitcode (";", "genMult "););
4046 /* assign the amsops */
4049 /* special cases first */
4051 if (AOP_TYPE (left) == AOP_CRY &&
4052 AOP_TYPE (right) == AOP_CRY)
4054 genMultbits (left, right, result);
4058 /* if both are of size == 1 */
4059 if (AOP_SIZE (left) == 1 &&
4060 AOP_SIZE (right) == 1)
4062 genMultOneByte (left, right, result);
4066 /* should have been converted to function call */
4070 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4071 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4072 freeAsmop (result, NULL, ic, TRUE);
4075 /*-----------------------------------------------------------------*/
4076 /* genDivbits :- division of bits */
4077 /*-----------------------------------------------------------------*/
4079 genDivbits (operand * left,
4086 /* the result must be bit */
4087 LOAD_AB_FOR_DIV (left, right, l);
4088 emitcode ("div", "ab");
4089 emitcode ("rrc", "a");
4090 aopPut (AOP (result), "c", 0);
4093 /*-----------------------------------------------------------------*/
4094 /* genDivOneByte : 8 bit division */
4095 /*-----------------------------------------------------------------*/
4097 genDivOneByte (operand * left,
4101 sym_link *opetype = operandType (result);
4106 size = AOP_SIZE (result) - 1;
4108 /* signed or unsigned */
4109 if (SPEC_USIGN (opetype))
4111 /* unsigned is easy */
4112 LOAD_AB_FOR_DIV (left, right, l);
4113 emitcode ("div", "ab");
4114 aopPut (AOP (result), "a", 0);
4116 aopPut (AOP (result), zero, offset++);
4120 /* signed is a little bit more difficult */
4122 /* save the signs of the operands */
4123 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4125 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4126 emitcode ("push", "acc"); /* save it on the stack */
4128 /* now sign adjust for both left & right */
4129 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4131 lbl = newiTempLabel (NULL);
4132 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4133 emitcode ("cpl", "a");
4134 emitcode ("inc", "a");
4135 emitcode ("", "%05d$:", (lbl->key + 100));
4136 emitcode ("mov", "b,a");
4138 /* sign adjust left side */
4139 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4142 lbl = newiTempLabel (NULL);
4143 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4144 emitcode ("cpl", "a");
4145 emitcode ("inc", "a");
4146 emitcode ("", "%05d$:", (lbl->key + 100));
4148 /* now the division */
4149 emitcode ("nop", "; workaround for DS80C390 div bug.");
4150 emitcode ("div", "ab");
4151 /* we are interested in the lower order
4153 emitcode ("mov", "b,a");
4154 lbl = newiTempLabel (NULL);
4155 emitcode ("pop", "acc");
4156 /* if there was an over flow we don't
4157 adjust the sign of the result */
4158 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4159 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4161 emitcode ("clr", "a");
4162 emitcode ("subb", "a,b");
4163 emitcode ("mov", "b,a");
4164 emitcode ("", "%05d$:", (lbl->key + 100));
4166 /* now we are done */
4167 aopPut (AOP (result), "b", 0);
4170 emitcode ("mov", "c,b.7");
4171 emitcode ("subb", "a,acc");
4174 aopPut (AOP (result), "a", offset++);
4178 /*-----------------------------------------------------------------*/
4179 /* genDiv - generates code for division */
4180 /*-----------------------------------------------------------------*/
4184 operand *left = IC_LEFT (ic);
4185 operand *right = IC_RIGHT (ic);
4186 operand *result = IC_RESULT (ic);
4188 D (emitcode (";", "genDiv ");
4191 /* assign the amsops */
4194 /* special cases first */
4196 if (AOP_TYPE (left) == AOP_CRY &&
4197 AOP_TYPE (right) == AOP_CRY)
4199 genDivbits (left, right, result);
4203 /* if both are of size == 1 */
4204 if (AOP_SIZE (left) == 1 &&
4205 AOP_SIZE (right) == 1)
4207 genDivOneByte (left, right, result);
4211 /* should have been converted to function call */
4214 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4216 freeAsmop (result, NULL, ic, TRUE);
4219 /*-----------------------------------------------------------------*/
4220 /* genModbits :- modulus of bits */
4221 /*-----------------------------------------------------------------*/
4223 genModbits (operand * left,
4230 /* the result must be bit */
4231 LOAD_AB_FOR_DIV (left, right, l);
4232 emitcode ("div", "ab");
4233 emitcode ("mov", "a,b");
4234 emitcode ("rrc", "a");
4235 aopPut (AOP (result), "c", 0);
4238 /*-----------------------------------------------------------------*/
4239 /* genModOneByte : 8 bit modulus */
4240 /*-----------------------------------------------------------------*/
4242 genModOneByte (operand * left,
4246 sym_link *opetype = operandType (result);
4250 /* signed or unsigned */
4251 if (SPEC_USIGN (opetype))
4253 /* unsigned is easy */
4254 LOAD_AB_FOR_DIV (left, right, l);
4255 emitcode ("div", "ab");
4256 aopPut (AOP (result), "b", 0);
4260 /* signed is a little bit more difficult */
4262 /* save the signs of the operands */
4263 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4266 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4267 emitcode ("push", "acc"); /* save it on the stack */
4269 /* now sign adjust for both left & right */
4270 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4273 lbl = newiTempLabel (NULL);
4274 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4275 emitcode ("cpl", "a");
4276 emitcode ("inc", "a");
4277 emitcode ("", "%05d$:", (lbl->key + 100));
4278 emitcode ("mov", "b,a");
4280 /* sign adjust left side */
4281 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4284 lbl = newiTempLabel (NULL);
4285 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4286 emitcode ("cpl", "a");
4287 emitcode ("inc", "a");
4288 emitcode ("", "%05d$:", (lbl->key + 100));
4290 /* now the multiplication */
4291 emitcode ("nop", "; workaround for DS80C390 div bug.");
4292 emitcode ("div", "ab");
4293 /* we are interested in the lower order
4295 lbl = newiTempLabel (NULL);
4296 emitcode ("pop", "acc");
4297 /* if there was an over flow we don't
4298 adjust the sign of the result */
4299 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4300 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4302 emitcode ("clr", "a");
4303 emitcode ("subb", "a,b");
4304 emitcode ("mov", "b,a");
4305 emitcode ("", "%05d$:", (lbl->key + 100));
4307 /* now we are done */
4308 aopPut (AOP (result), "b", 0);
4312 /*-----------------------------------------------------------------*/
4313 /* genMod - generates code for division */
4314 /*-----------------------------------------------------------------*/
4318 operand *left = IC_LEFT (ic);
4319 operand *right = IC_RIGHT (ic);
4320 operand *result = IC_RESULT (ic);
4322 D (emitcode (";", "genMod ");
4325 /* assign the amsops */
4328 /* special cases first */
4330 if (AOP_TYPE (left) == AOP_CRY &&
4331 AOP_TYPE (right) == AOP_CRY)
4333 genModbits (left, right, result);
4337 /* if both are of size == 1 */
4338 if (AOP_SIZE (left) == 1 &&
4339 AOP_SIZE (right) == 1)
4341 genModOneByte (left, right, result);
4345 /* should have been converted to function call */
4349 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4350 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4351 freeAsmop (result, NULL, ic, TRUE);
4354 /*-----------------------------------------------------------------*/
4355 /* genIfxJump :- will create a jump depending on the ifx */
4356 /*-----------------------------------------------------------------*/
4358 genIfxJump (iCode * ic, char *jval)
4361 symbol *tlbl = newiTempLabel (NULL);
4364 D (emitcode (";", "genIfxJump ");
4367 /* if true label then we jump if condition
4371 jlbl = IC_TRUE (ic);
4372 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4373 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4377 /* false label is present */
4378 jlbl = IC_FALSE (ic);
4379 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4380 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4382 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4383 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4385 emitcode (inst, "%05d$", tlbl->key + 100);
4386 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4387 emitcode ("", "%05d$:", tlbl->key + 100);
4389 /* mark the icode as generated */
4393 /*-----------------------------------------------------------------*/
4394 /* genCmp :- greater or less than comparison */
4395 /*-----------------------------------------------------------------*/
4397 genCmp (operand * left, operand * right,
4398 iCode * ic, iCode * ifx, int sign)
4400 int size, offset = 0;
4401 unsigned long lit = 0L;
4404 D (emitcode (";", "genCmp");
4407 result = IC_RESULT (ic);
4409 /* if left & right are bit variables */
4410 if (AOP_TYPE (left) == AOP_CRY &&
4411 AOP_TYPE (right) == AOP_CRY)
4413 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4414 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4418 /* subtract right from left if at the
4419 end the carry flag is set then we know that
4420 left is greater than right */
4421 size = max (AOP_SIZE (left), AOP_SIZE (right));
4423 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4424 if ((size == 1) && !sign &&
4425 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4427 symbol *lbl = newiTempLabel (NULL);
4428 emitcode ("cjne", "%s,%s,%05d$",
4429 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4430 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4432 emitcode ("", "%05d$:", lbl->key + 100);
4436 if (AOP_TYPE (right) == AOP_LIT)
4438 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4439 /* optimize if(x < 0) or if(x >= 0) */
4448 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4450 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4451 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4453 aopOp (result, ic, FALSE, FALSE);
4455 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4457 freeAsmop (result, NULL, ic, TRUE);
4458 genIfxJump (ifx, "acc.7");
4463 emitcode ("rlc", "a");
4465 goto release_freedLR;
4473 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4474 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4475 emitcode (";", "genCmp #2");
4476 if (sign && (size == 0))
4478 emitcode (";", "genCmp #3");
4479 emitcode ("xrl", "a,#0x80");
4480 if (AOP_TYPE (right) == AOP_LIT)
4482 unsigned long lit = (unsigned long)
4483 floatFromVal (AOP (right)->aopu.aop_lit);
4484 emitcode (";", "genCmp #3.1");
4485 emitcode ("subb", "a,#0x%02x",
4486 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4490 emitcode (";", "genCmp #3.2");
4491 if (AOP_NEEDSACC (right))
4493 emitcode ("push", "acc");
4495 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4496 FALSE, FALSE, FALSE));
4497 emitcode ("xrl", "b,#0x80");
4498 if (AOP_NEEDSACC (right))
4500 emitcode ("pop", "acc");
4502 emitcode ("subb", "a,b");
4509 emitcode (";", "genCmp #4");
4510 if (AOP_NEEDSACC (right))
4513 emitcode (";", "genCmp #4.1");
4514 emitcode ("xch", "a, b");
4515 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4516 emitcode ("xch", "a, b");
4521 emitcode (";", "genCmp #4.2");
4522 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4525 emitcode ("subb", "a,%s", s);
4532 /* Don't need the left & right operands any more; do need the result. */
4533 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4534 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4536 aopOp (result, ic, FALSE, FALSE);
4540 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4546 /* if the result is used in the next
4547 ifx conditional branch then generate
4548 code a little differently */
4551 genIfxJump (ifx, "c");
4557 /* leave the result in acc */
4559 freeAsmop (result, NULL, ic, TRUE);
4562 /*-----------------------------------------------------------------*/
4563 /* genCmpGt :- greater than comparison */
4564 /*-----------------------------------------------------------------*/
4566 genCmpGt (iCode * ic, iCode * ifx)
4568 operand *left, *right;
4569 sym_link *letype, *retype;
4572 D (emitcode (";", "genCmpGt ");
4575 left = IC_LEFT (ic);
4576 right = IC_RIGHT (ic);
4578 letype = getSpec (operandType (left));
4579 retype = getSpec (operandType (right));
4580 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4582 /* assign the left & right amsops */
4585 genCmp (right, left, ic, ifx, sign);
4588 /*-----------------------------------------------------------------*/
4589 /* genCmpLt - less than comparisons */
4590 /*-----------------------------------------------------------------*/
4592 genCmpLt (iCode * ic, iCode * ifx)
4594 operand *left, *right;
4595 sym_link *letype, *retype;
4598 D (emitcode (";", "genCmpLt "););
4600 left = IC_LEFT (ic);
4601 right = IC_RIGHT (ic);
4603 letype = getSpec (operandType (left));
4604 retype = getSpec (operandType (right));
4605 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4607 /* assign the left & right amsops */
4610 genCmp (left, right, ic, ifx, sign);
4613 /*-----------------------------------------------------------------*/
4614 /* gencjneshort - compare and jump if not equal */
4615 /*-----------------------------------------------------------------*/
4617 gencjneshort (operand * left, operand * right, symbol * lbl)
4619 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4621 unsigned long lit = 0L;
4623 D (emitcode (";", "gencjneshort");
4626 /* if the left side is a literal or
4627 if the right is in a pointer register and left
4629 if ((AOP_TYPE (left) == AOP_LIT) ||
4630 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4637 if (AOP_TYPE (right) == AOP_LIT)
4638 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4640 if (opIsGptr (left) || opIsGptr (right))
4642 /* We are comparing a generic pointer to something.
4643 * Exclude the generic type byte from the comparison.
4646 D (emitcode (";", "cjneshort: generic ptr special case.");
4651 /* if the right side is a literal then anything goes */
4652 if (AOP_TYPE (right) == AOP_LIT &&
4653 AOP_TYPE (left) != AOP_DIR)
4657 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4659 emitcode ("cjne", "a,%s,%05d$",
4660 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4666 /* if the right side is in a register or in direct space or
4667 if the left is a pointer register & right is not */
4668 else if (AOP_TYPE (right) == AOP_REG ||
4669 AOP_TYPE (right) == AOP_DIR ||
4670 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4671 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4675 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4676 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4677 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4678 emitcode ("jnz", "%05d$", lbl->key + 100);
4680 emitcode ("cjne", "a,%s,%05d$",
4681 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4688 /* right is a pointer reg need both a & b */
4691 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4692 if (strcmp (l, "b"))
4693 emitcode ("mov", "b,%s", l);
4694 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4695 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4701 /*-----------------------------------------------------------------*/
4702 /* gencjne - compare and jump if not equal */
4703 /*-----------------------------------------------------------------*/
4705 gencjne (operand * left, operand * right, symbol * lbl)
4707 symbol *tlbl = newiTempLabel (NULL);
4709 D (emitcode (";", "gencjne");
4712 gencjneshort (left, right, lbl);
4714 emitcode ("mov", "a,%s", one);
4715 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4716 emitcode ("", "%05d$:", lbl->key + 100);
4717 emitcode ("clr", "a");
4718 emitcode ("", "%05d$:", tlbl->key + 100);
4721 /*-----------------------------------------------------------------*/
4722 /* genCmpEq - generates code for equal to */
4723 /*-----------------------------------------------------------------*/
4725 genCmpEq (iCode * ic, iCode * ifx)
4727 operand *left, *right, *result;
4729 D (emitcode (";", "genCmpEq ");
4733 AOP_SET_LOCALS (ic);
4735 /* if literal, literal on the right or
4736 if the right is in a pointer register and left
4738 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4739 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4741 operand *t = IC_RIGHT (ic);
4742 IC_RIGHT (ic) = IC_LEFT (ic);
4746 if (ifx && /* !AOP_SIZE(result) */
4747 OP_SYMBOL (result) &&
4748 OP_SYMBOL (result)->regType == REG_CND)
4751 /* if they are both bit variables */
4752 if (AOP_TYPE (left) == AOP_CRY &&
4753 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4755 if (AOP_TYPE (right) == AOP_LIT)
4757 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4760 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4761 emitcode ("cpl", "c");
4765 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4769 emitcode ("clr", "c");
4771 /* AOP_TYPE(right) == AOP_CRY */
4775 symbol *lbl = newiTempLabel (NULL);
4776 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4777 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4778 emitcode ("cpl", "c");
4779 emitcode ("", "%05d$:", (lbl->key + 100));
4781 /* if true label then we jump if condition
4783 tlbl = newiTempLabel (NULL);
4786 emitcode ("jnc", "%05d$", tlbl->key + 100);
4787 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4791 emitcode ("jc", "%05d$", tlbl->key + 100);
4792 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4794 emitcode ("", "%05d$:", tlbl->key + 100);
4798 tlbl = newiTempLabel (NULL);
4799 gencjneshort (left, right, tlbl);
4802 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4803 emitcode ("", "%05d$:", tlbl->key + 100);
4807 symbol *lbl = newiTempLabel (NULL);
4808 emitcode ("sjmp", "%05d$", lbl->key + 100);
4809 emitcode ("", "%05d$:", tlbl->key + 100);
4810 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4811 emitcode ("", "%05d$:", lbl->key + 100);
4814 /* mark the icode as generated */
4817 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4818 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4822 /* if they are both bit variables */
4823 if (AOP_TYPE (left) == AOP_CRY &&
4824 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4826 if (AOP_TYPE (right) == AOP_LIT)
4828 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4831 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4832 emitcode ("cpl", "c");
4836 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4840 emitcode ("clr", "c");
4842 /* AOP_TYPE(right) == AOP_CRY */
4846 symbol *lbl = newiTempLabel (NULL);
4847 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4848 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4849 emitcode ("cpl", "c");
4850 emitcode ("", "%05d$:", (lbl->key + 100));
4853 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4854 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4856 aopOp (result, ic, TRUE, FALSE);
4859 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4866 genIfxJump (ifx, "c");
4869 /* if the result is used in an arithmetic operation
4870 then put the result in place */
4875 gencjne (left, right, newiTempLabel (NULL));
4877 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4878 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4880 aopOp (result, ic, TRUE, FALSE);
4882 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4884 aopPut (AOP (result), "a", 0);
4889 genIfxJump (ifx, "a");
4892 /* if the result is used in an arithmetic operation
4893 then put the result in place */
4894 if (AOP_TYPE (result) != AOP_CRY)
4896 /* leave the result in acc */
4900 freeAsmop (result, NULL, ic, TRUE);
4903 /*-----------------------------------------------------------------*/
4904 /* ifxForOp - returns the icode containing the ifx for operand */
4905 /*-----------------------------------------------------------------*/
4907 ifxForOp (operand * op, iCode * ic)
4909 /* if true symbol then needs to be assigned */
4910 if (IS_TRUE_SYMOP (op))
4913 /* if this has register type condition and
4914 the next instruction is ifx with the same operand
4915 and live to of the operand is upto the ifx only then */
4917 ic->next->op == IFX &&
4918 IC_COND (ic->next)->key == op->key &&
4919 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4924 /*-----------------------------------------------------------------*/
4925 /* genAndOp - for && operation */
4926 /*-----------------------------------------------------------------*/
4928 genAndOp (iCode * ic)
4930 operand *left, *right, *result;
4933 D (emitcode (";", "genAndOp "););
4935 /* note here that && operations that are in an
4936 if statement are taken away by backPatchLabels
4937 only those used in arthmetic operations remain */
4939 AOP_SET_LOCALS (ic);
4941 /* if both are bit variables */
4942 if (AOP_TYPE (left) == AOP_CRY &&
4943 AOP_TYPE (right) == AOP_CRY)
4945 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4946 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950 aopOp (result,ic,FALSE, FALSE);
4955 tlbl = newiTempLabel (NULL);
4957 emitcode ("jz", "%05d$", tlbl->key + 100);
4959 emitcode ("", "%05d$:", tlbl->key + 100);
4960 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4961 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4963 aopOp (result,ic,FALSE, FALSE);
4966 freeAsmop (result, NULL, ic, TRUE);
4970 /*-----------------------------------------------------------------*/
4971 /* genOrOp - for || operation */
4972 /*-----------------------------------------------------------------*/
4974 genOrOp (iCode * ic)
4976 operand *left, *right, *result;
4979 D (emitcode (";", "genOrOp "););
4981 /* note here that || operations that are in an
4982 if statement are taken away by backPatchLabels
4983 only those used in arthmetic operations remain */
4985 AOP_SET_LOCALS (ic);
4987 /* if both are bit variables */
4988 if (AOP_TYPE (left) == AOP_CRY &&
4989 AOP_TYPE (right) == AOP_CRY)
4991 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4992 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4993 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4994 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4996 aopOp (result,ic,FALSE, FALSE);
5002 tlbl = newiTempLabel (NULL);
5004 emitcode ("jnz", "%05d$", tlbl->key + 100);
5006 emitcode ("", "%05d$:", tlbl->key + 100);
5007 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5008 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5010 aopOp (result,ic,FALSE, FALSE);
5015 freeAsmop (result, NULL, ic, TRUE);
5018 /*-----------------------------------------------------------------*/
5019 /* isLiteralBit - test if lit == 2^n */
5020 /*-----------------------------------------------------------------*/
5022 isLiteralBit (unsigned long lit)
5024 unsigned long pw[32] =
5025 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5026 0x100L, 0x200L, 0x400L, 0x800L,
5027 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5028 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5029 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5030 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5031 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5034 for (idx = 0; idx < 32; idx++)
5040 /*-----------------------------------------------------------------*/
5041 /* continueIfTrue - */
5042 /*-----------------------------------------------------------------*/
5044 continueIfTrue (iCode * ic)
5047 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5051 /*-----------------------------------------------------------------*/
5053 /*-----------------------------------------------------------------*/
5055 jumpIfTrue (iCode * ic)
5058 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5062 /*-----------------------------------------------------------------*/
5063 /* jmpTrueOrFalse - */
5064 /*-----------------------------------------------------------------*/
5066 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5068 // ugly but optimized by peephole
5071 symbol *nlbl = newiTempLabel (NULL);
5072 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5073 emitcode ("", "%05d$:", tlbl->key + 100);
5074 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5075 emitcode ("", "%05d$:", nlbl->key + 100);
5079 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5080 emitcode ("", "%05d$:", tlbl->key + 100);
5085 // Generate code to perform a bit-wise logic operation
5086 // on two operands in far space (assumed to already have been
5087 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5088 // in far space. This requires pushing the result on the stack
5089 // then popping it into the result.
5091 genFarFarLogicOp(iCode *ic, char *logicOp)
5093 int size, resultSize, compSize;
5097 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5098 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5099 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5101 _startLazyDPSEvaluation();
5102 for (size = compSize; (size--); offset++)
5104 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5105 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5106 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5108 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5109 emitcode ("push", "acc");
5111 _endLazyDPSEvaluation();
5113 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5114 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5115 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5117 resultSize = AOP_SIZE(IC_RESULT(ic));
5119 ADJUST_PUSHED_RESULT(compSize, resultSize);
5121 _startLazyDPSEvaluation();
5124 emitcode ("pop", "acc");
5125 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5127 _endLazyDPSEvaluation();
5128 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5132 /*-----------------------------------------------------------------*/
5133 /* genAnd - code for and */
5134 /*-----------------------------------------------------------------*/
5136 genAnd (iCode * ic, iCode * ifx)
5138 operand *left, *right, *result;
5139 int size, offset = 0;
5140 unsigned long lit = 0L;
5145 D (emitcode (";", "genAnd "););
5147 AOP_OP_3_NOFATAL (ic, pushResult);
5148 AOP_SET_LOCALS (ic);
5152 genFarFarLogicOp(ic, "anl");
5157 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5159 AOP_TYPE (left), AOP_TYPE (right));
5160 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5162 AOP_SIZE (left), AOP_SIZE (right));
5165 /* if left is a literal & right is not then exchange them */
5166 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5167 AOP_NEEDSACC (left))
5169 operand *tmp = right;
5174 /* if result = right then exchange them */
5175 if (sameRegs (AOP (result), AOP (right)))
5177 operand *tmp = right;
5182 /* if right is bit then exchange them */
5183 if (AOP_TYPE (right) == AOP_CRY &&
5184 AOP_TYPE (left) != AOP_CRY)
5186 operand *tmp = right;
5190 if (AOP_TYPE (right) == AOP_LIT)
5191 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5193 size = AOP_SIZE (result);
5196 // result = bit & yy;
5197 if (AOP_TYPE (left) == AOP_CRY)
5199 // c = bit & literal;
5200 if (AOP_TYPE (right) == AOP_LIT)
5204 if (size && sameRegs (AOP (result), AOP (left)))
5207 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5212 if (size && (AOP_TYPE (result) == AOP_CRY))
5214 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5217 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5222 emitcode ("clr", "c");
5227 if (AOP_TYPE (right) == AOP_CRY)
5230 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5231 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5236 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5238 emitcode ("rrc", "a");
5239 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5247 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5248 genIfxJump (ifx, "c");
5252 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5253 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5254 if ((AOP_TYPE (right) == AOP_LIT) &&
5255 (AOP_TYPE (result) == AOP_CRY) &&
5256 (AOP_TYPE (left) != AOP_CRY))
5258 int posbit = isLiteralBit (lit);
5263 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5266 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5272 sprintf (buffer, "acc.%d", posbit & 0x07);
5273 genIfxJump (ifx, buffer);
5280 symbol *tlbl = newiTempLabel (NULL);
5281 int sizel = AOP_SIZE (left);
5283 emitcode ("setb", "c");
5286 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5288 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5290 if ((posbit = isLiteralBit (bytelit)) != 0)
5291 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5294 if (bytelit != 0x0FFL)
5295 emitcode ("anl", "a,%s",
5296 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5297 emitcode ("jnz", "%05d$", tlbl->key + 100);
5302 // bit = left & literal
5305 emitcode ("clr", "c");
5306 emitcode ("", "%05d$:", tlbl->key + 100);
5308 // if(left & literal)
5312 jmpTrueOrFalse (ifx, tlbl);
5320 /* if left is same as result */
5321 if (sameRegs (AOP (result), AOP (left)))
5323 for (; size--; offset++)
5325 if (AOP_TYPE (right) == AOP_LIT)
5327 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5329 else if (bytelit == 0)
5330 aopPut (AOP (result), zero, offset);
5331 else if (IS_AOP_PREG (result))
5333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5334 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5335 aopPut (AOP (result), "a", offset);
5338 emitcode ("anl", "%s,%s",
5339 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5340 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5344 if (AOP_TYPE (left) == AOP_ACC)
5345 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5348 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5349 if (IS_AOP_PREG (result))
5351 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5352 aopPut (AOP (result), "a", offset);
5356 emitcode ("anl", "%s,a",
5357 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5364 // left & result in different registers
5365 if (AOP_TYPE (result) == AOP_CRY)
5368 // if(size), result in bit
5369 // if(!size && ifx), conditional oper: if(left & right)
5370 symbol *tlbl = newiTempLabel (NULL);
5371 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5373 emitcode ("setb", "c");
5376 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5377 emitcode ("anl", "a,%s",
5378 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5380 if (AOP_TYPE(left)==AOP_ACC) {
5381 emitcode("mov", "b,a");
5382 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5383 emitcode("anl", "a,b");
5385 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5386 emitcode ("anl", "a,%s",
5387 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5390 emitcode ("jnz", "%05d$", tlbl->key + 100);
5396 emitcode ("", "%05d$:", tlbl->key + 100);
5400 jmpTrueOrFalse (ifx, tlbl);
5404 for (; (size--); offset++)
5407 // result = left & right
5408 if (AOP_TYPE (right) == AOP_LIT)
5410 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5412 aopPut (AOP (result),
5413 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5417 else if (bytelit == 0)
5419 aopPut (AOP (result), zero, offset);
5422 D (emitcode (";", "better literal AND.");
5424 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5425 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5426 FALSE, FALSE, FALSE));
5431 // faster than result <- left, anl result,right
5432 // and better if result is SFR
5433 if (AOP_TYPE (left) == AOP_ACC)
5435 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5436 FALSE, FALSE, FALSE));
5440 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5441 emitcode ("anl", "a,%s",
5442 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5445 aopPut (AOP (result), "a", offset);
5451 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5452 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5453 freeAsmop (result, NULL, ic, TRUE);
5457 /*-----------------------------------------------------------------*/
5458 /* genOr - code for or */
5459 /*-----------------------------------------------------------------*/
5461 genOr (iCode * ic, iCode * ifx)
5463 operand *left, *right, *result;
5464 int size, offset = 0;
5465 unsigned long lit = 0L;
5468 D (emitcode (";", "genOr "););
5470 AOP_OP_3_NOFATAL (ic, pushResult);
5471 AOP_SET_LOCALS (ic);
5475 genFarFarLogicOp(ic, "orl");
5481 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5483 AOP_TYPE (left), AOP_TYPE (right));
5484 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5486 AOP_SIZE (left), AOP_SIZE (right));
5489 /* if left is a literal & right is not then exchange them */
5490 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5491 AOP_NEEDSACC (left))
5493 operand *tmp = right;
5498 /* if result = right then exchange them */
5499 if (sameRegs (AOP (result), AOP (right)))
5501 operand *tmp = right;
5506 /* if right is bit then exchange them */
5507 if (AOP_TYPE (right) == AOP_CRY &&
5508 AOP_TYPE (left) != AOP_CRY)
5510 operand *tmp = right;
5514 if (AOP_TYPE (right) == AOP_LIT)
5515 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5517 size = AOP_SIZE (result);
5521 if (AOP_TYPE (left) == AOP_CRY)
5523 if (AOP_TYPE (right) == AOP_LIT)
5525 // c = bit & literal;
5528 // lit != 0 => result = 1
5529 if (AOP_TYPE (result) == AOP_CRY)
5532 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5534 continueIfTrue (ifx);
5537 emitcode ("setb", "c");
5541 // lit == 0 => result = left
5542 if (size && sameRegs (AOP (result), AOP (left)))
5544 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5549 if (AOP_TYPE (right) == AOP_CRY)
5552 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5553 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5558 symbol *tlbl = newiTempLabel (NULL);
5559 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5560 emitcode ("setb", "c");
5561 emitcode ("jb", "%s,%05d$",
5562 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5564 emitcode ("jnz", "%05d$", tlbl->key + 100);
5565 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5567 jmpTrueOrFalse (ifx, tlbl);
5573 emitcode ("", "%05d$:", tlbl->key + 100);
5582 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5583 genIfxJump (ifx, "c");
5587 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5588 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5589 if ((AOP_TYPE (right) == AOP_LIT) &&
5590 (AOP_TYPE (result) == AOP_CRY) &&
5591 (AOP_TYPE (left) != AOP_CRY))
5597 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5599 continueIfTrue (ifx);
5604 // lit = 0, result = boolean(left)
5606 emitcode ("setb", "c");
5610 symbol *tlbl = newiTempLabel (NULL);
5611 emitcode ("jnz", "%05d$", tlbl->key + 100);
5613 emitcode ("", "%05d$:", tlbl->key + 100);
5617 genIfxJump (ifx, "a");
5625 /* if left is same as result */
5626 if (sameRegs (AOP (result), AOP (left)))
5628 for (; size--; offset++)
5630 if (AOP_TYPE (right) == AOP_LIT)
5632 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5638 if (IS_AOP_PREG (left))
5640 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5641 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5642 aopPut (AOP (result), "a", offset);
5646 emitcode ("orl", "%s,%s",
5647 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5648 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5654 if (AOP_TYPE (left) == AOP_ACC)
5656 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5660 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5661 if (IS_AOP_PREG (left))
5663 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5664 aopPut (AOP (result), "a", offset);
5668 emitcode ("orl", "%s,a",
5669 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5677 // left & result in different registers
5678 if (AOP_TYPE (result) == AOP_CRY)
5681 // if(size), result in bit
5682 // if(!size && ifx), conditional oper: if(left | right)
5683 symbol *tlbl = newiTempLabel (NULL);
5684 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5686 emitcode ("setb", "c");
5689 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5690 emitcode ("orl", "a,%s",
5691 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5693 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5694 emitcode ("orl", "a,%s",
5695 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5697 emitcode ("jnz", "%05d$", tlbl->key + 100);
5703 emitcode ("", "%05d$:", tlbl->key + 100);
5707 jmpTrueOrFalse (ifx, tlbl);
5711 for (; (size--); offset++)
5714 // result = left & right
5715 if (AOP_TYPE (right) == AOP_LIT)
5717 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5719 aopPut (AOP (result),
5720 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5724 D (emitcode (";", "better literal OR.");
5726 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5727 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5728 FALSE, FALSE, FALSE));
5733 // faster than result <- left, anl result,right
5734 // and better if result is SFR
5735 if (AOP_TYPE (left) == AOP_ACC)
5737 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5738 FALSE, FALSE, FALSE));
5742 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5743 emitcode ("orl", "a,%s",
5744 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5747 aopPut (AOP (result), "a", offset);
5753 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5754 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5755 freeAsmop (result, NULL, ic, TRUE);
5758 /*-----------------------------------------------------------------*/
5759 /* genXor - code for xclusive or */
5760 /*-----------------------------------------------------------------*/
5762 genXor (iCode * ic, iCode * ifx)
5764 operand *left, *right, *result;
5765 int size, offset = 0;
5766 unsigned long lit = 0L;
5769 D (emitcode (";", "genXor "););
5771 AOP_OP_3_NOFATAL (ic, pushResult);
5772 AOP_SET_LOCALS (ic);
5776 genFarFarLogicOp(ic, "xrl");
5781 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5783 AOP_TYPE (left), AOP_TYPE (right));
5784 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5786 AOP_SIZE (left), AOP_SIZE (right));
5789 /* if left is a literal & right is not ||
5790 if left needs acc & right does not */
5791 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5792 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5794 operand *tmp = right;
5799 /* if result = right then exchange them */
5800 if (sameRegs (AOP (result), AOP (right)))
5802 operand *tmp = right;
5807 /* if right is bit then exchange them */
5808 if (AOP_TYPE (right) == AOP_CRY &&
5809 AOP_TYPE (left) != AOP_CRY)
5811 operand *tmp = right;
5815 if (AOP_TYPE (right) == AOP_LIT)
5816 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5818 size = AOP_SIZE (result);
5822 if (AOP_TYPE (left) == AOP_CRY)
5824 if (AOP_TYPE (right) == AOP_LIT)
5826 // c = bit & literal;
5829 // lit>>1 != 0 => result = 1
5830 if (AOP_TYPE (result) == AOP_CRY)
5833 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5835 continueIfTrue (ifx);
5838 emitcode ("setb", "c");
5845 // lit == 0, result = left
5846 if (size && sameRegs (AOP (result), AOP (left)))
5848 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5852 // lit == 1, result = not(left)
5853 if (size && sameRegs (AOP (result), AOP (left)))
5855 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5860 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5861 emitcode ("cpl", "c");
5870 symbol *tlbl = newiTempLabel (NULL);
5871 if (AOP_TYPE (right) == AOP_CRY)
5874 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5878 int sizer = AOP_SIZE (right);
5880 // if val>>1 != 0, result = 1
5881 emitcode ("setb", "c");
5884 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5886 // test the msb of the lsb
5887 emitcode ("anl", "a,#0xfe");
5888 emitcode ("jnz", "%05d$", tlbl->key + 100);
5892 emitcode ("rrc", "a");
5894 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5895 emitcode ("cpl", "c");
5896 emitcode ("", "%05d$:", (tlbl->key + 100));
5903 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5904 genIfxJump (ifx, "c");
5908 if (sameRegs (AOP (result), AOP (left)))
5910 /* if left is same as result */
5911 for (; size--; offset++)
5913 if (AOP_TYPE (right) == AOP_LIT)
5915 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5917 else if (IS_AOP_PREG (left))
5919 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5920 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5921 aopPut (AOP (result), "a", offset);
5924 emitcode ("xrl", "%s,%s",
5925 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5926 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5930 if (AOP_TYPE (left) == AOP_ACC)
5931 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5934 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5935 if (IS_AOP_PREG (left))
5937 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5938 aopPut (AOP (result), "a", offset);
5941 emitcode ("xrl", "%s,a",
5942 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5949 // left & result in different registers
5950 if (AOP_TYPE (result) == AOP_CRY)
5953 // if(size), result in bit
5954 // if(!size && ifx), conditional oper: if(left ^ right)
5955 symbol *tlbl = newiTempLabel (NULL);
5956 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5958 emitcode ("setb", "c");
5961 if ((AOP_TYPE (right) == AOP_LIT) &&
5962 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5964 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5968 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5969 emitcode ("xrl", "a,%s",
5970 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5972 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5973 emitcode ("xrl", "a,%s",
5974 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5977 emitcode ("jnz", "%05d$", tlbl->key + 100);
5983 emitcode ("", "%05d$:", tlbl->key + 100);
5987 jmpTrueOrFalse (ifx, tlbl);
5990 for (; (size--); offset++)
5993 // result = left & right
5994 if (AOP_TYPE (right) == AOP_LIT)
5996 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5998 aopPut (AOP (result),
5999 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6003 D (emitcode (";", "better literal XOR.");
6005 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6006 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6007 FALSE, FALSE, FALSE));
6011 // faster than result <- left, anl result,right
6012 // and better if result is SFR
6013 if (AOP_TYPE (left) == AOP_ACC)
6015 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6016 FALSE, FALSE, FALSE));
6020 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6021 emitcode ("xrl", "a,%s",
6022 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6025 aopPut (AOP (result), "a", offset);
6030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6031 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6032 freeAsmop (result, NULL, ic, TRUE);
6035 /*-----------------------------------------------------------------*/
6036 /* genInline - write the inline code out */
6037 /*-----------------------------------------------------------------*/
6039 genInline (iCode * ic)
6041 char *buffer, *bp, *bp1;
6043 D (emitcode (";", "genInline ");
6046 _G.inLine += (!options.asmpeep);
6048 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6049 strcpy (buffer, IC_INLINE (ic));
6051 /* emit each line as a code */
6076 /* emitcode("",buffer); */
6077 _G.inLine -= (!options.asmpeep);
6080 /*-----------------------------------------------------------------*/
6081 /* genRRC - rotate right with carry */
6082 /*-----------------------------------------------------------------*/
6086 operand *left, *result;
6087 int size, offset = 0;
6090 D (emitcode (";", "genRRC ");
6093 /* rotate right with carry */
6094 left = IC_LEFT (ic);
6095 result = IC_RESULT (ic);
6096 aopOp (left, ic, FALSE, FALSE);
6097 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6099 /* move it to the result */
6100 size = AOP_SIZE (result);
6104 _startLazyDPSEvaluation ();
6107 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6109 emitcode ("rrc", "a");
6110 if (AOP_SIZE (result) > 1)
6111 aopPut (AOP (result), "a", offset--);
6113 _endLazyDPSEvaluation ();
6115 /* now we need to put the carry into the
6116 highest order byte of the result */
6117 if (AOP_SIZE (result) > 1)
6119 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6122 emitcode ("mov", "acc.7,c");
6123 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6124 freeAsmop (left, NULL, ic, TRUE);
6125 freeAsmop (result, NULL, ic, TRUE);
6128 /*-----------------------------------------------------------------*/
6129 /* genRLC - generate code for rotate left with carry */
6130 /*-----------------------------------------------------------------*/
6134 operand *left, *result;
6135 int size, offset = 0;
6138 D (emitcode (";", "genRLC ");
6141 /* rotate right with carry */
6142 left = IC_LEFT (ic);
6143 result = IC_RESULT (ic);
6144 aopOp (left, ic, FALSE, FALSE);
6145 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6147 /* move it to the result */
6148 size = AOP_SIZE (result);
6152 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6154 emitcode ("add", "a,acc");
6155 if (AOP_SIZE (result) > 1)
6157 aopPut (AOP (result), "a", offset++);
6160 _startLazyDPSEvaluation ();
6163 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6165 emitcode ("rlc", "a");
6166 if (AOP_SIZE (result) > 1)
6167 aopPut (AOP (result), "a", offset++);
6169 _endLazyDPSEvaluation ();
6171 /* now we need to put the carry into the
6172 highest order byte of the result */
6173 if (AOP_SIZE (result) > 1)
6175 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6178 emitcode ("mov", "acc.0,c");
6179 aopPut (AOP (result), "a", 0);
6180 freeAsmop (left, NULL, ic, TRUE);
6181 freeAsmop (result, NULL, ic, TRUE);
6184 /*-----------------------------------------------------------------*/
6185 /* genGetHbit - generates code get highest order bit */
6186 /*-----------------------------------------------------------------*/
6188 genGetHbit (iCode * ic)
6190 operand *left, *result;
6191 left = IC_LEFT (ic);
6192 result = IC_RESULT (ic);
6193 aopOp (left, ic, FALSE, FALSE);
6194 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6196 D (emitcode (";", "genGetHbit ");
6199 /* get the highest order byte into a */
6200 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6201 if (AOP_TYPE (result) == AOP_CRY)
6203 emitcode ("rlc", "a");
6208 emitcode ("rl", "a");
6209 emitcode ("anl", "a,#0x01");
6214 freeAsmop (left, NULL, ic, TRUE);
6215 freeAsmop (result, NULL, ic, TRUE);
6218 /*-----------------------------------------------------------------*/
6219 /* AccRol - rotate left accumulator by known count */
6220 /*-----------------------------------------------------------------*/
6222 AccRol (int shCount)
6224 shCount &= 0x0007; // shCount : 0..7
6231 emitcode ("rl", "a");
6234 emitcode ("rl", "a");
6235 emitcode ("rl", "a");
6238 emitcode ("swap", "a");
6239 emitcode ("rr", "a");
6242 emitcode ("swap", "a");
6245 emitcode ("swap", "a");
6246 emitcode ("rl", "a");
6249 emitcode ("rr", "a");
6250 emitcode ("rr", "a");
6253 emitcode ("rr", "a");
6258 /*-----------------------------------------------------------------*/
6259 /* AccLsh - left shift accumulator by known count */
6260 /*-----------------------------------------------------------------*/
6262 AccLsh (int shCount)
6267 emitcode ("add", "a,acc");
6268 else if (shCount == 2)
6270 emitcode ("add", "a,acc");
6271 emitcode ("add", "a,acc");
6275 /* rotate left accumulator */
6277 /* and kill the lower order bits */
6278 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6283 /*-----------------------------------------------------------------*/
6284 /* AccRsh - right shift accumulator by known count */
6285 /*-----------------------------------------------------------------*/
6287 AccRsh (int shCount)
6294 emitcode ("rrc", "a");
6298 /* rotate right accumulator */
6299 AccRol (8 - shCount);
6300 /* and kill the higher order bits */
6301 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6306 #ifdef BETTER_LITERAL_SHIFT
6307 /*-----------------------------------------------------------------*/
6308 /* AccSRsh - signed right shift accumulator by known count */
6309 /*-----------------------------------------------------------------*/
6311 AccSRsh (int shCount)
6318 emitcode ("mov", "c,acc.7");
6319 emitcode ("rrc", "a");
6321 else if (shCount == 2)
6323 emitcode ("mov", "c,acc.7");
6324 emitcode ("rrc", "a");
6325 emitcode ("mov", "c,acc.7");
6326 emitcode ("rrc", "a");
6330 tlbl = newiTempLabel (NULL);
6331 /* rotate right accumulator */
6332 AccRol (8 - shCount);
6333 /* and kill the higher order bits */
6334 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6335 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6336 emitcode ("orl", "a,#0x%02x",
6337 (unsigned char) ~SRMask[shCount]);
6338 emitcode ("", "%05d$:", tlbl->key + 100);
6344 #ifdef BETTER_LITERAL_SHIFT
6345 /*-----------------------------------------------------------------*/
6346 /* shiftR1Left2Result - shift right one byte from left to result */
6347 /*-----------------------------------------------------------------*/
6349 shiftR1Left2Result (operand * left, int offl,
6350 operand * result, int offr,
6351 int shCount, int sign)
6353 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6354 /* shift right accumulator */
6359 aopPut (AOP (result), "a", offr);
6363 #ifdef BETTER_LITERAL_SHIFT
6364 /*-----------------------------------------------------------------*/
6365 /* shiftL1Left2Result - shift left one byte from left to result */
6366 /*-----------------------------------------------------------------*/
6368 shiftL1Left2Result (operand * left, int offl,
6369 operand * result, int offr, int shCount)
6371 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6372 /* shift left accumulator */
6374 aopPut (AOP (result), "a", offr);
6378 #ifdef BETTER_LITERAL_SHIFT
6379 /*-----------------------------------------------------------------*/
6380 /* movLeft2Result - move byte from left to result */
6381 /*-----------------------------------------------------------------*/
6383 movLeft2Result (operand * left, int offl,
6384 operand * result, int offr, int sign)
6387 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6389 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6391 if (*l == '@' && (IS_AOP_PREG (result)))
6393 emitcode ("mov", "a,%s", l);
6394 aopPut (AOP (result), "a", offr);
6400 aopPut (AOP (result), l, offr);
6404 /* MSB sign in acc.7 ! */
6405 if (getDataSize (left) == offl + 1)
6407 emitcode ("mov", "a,%s", l);
6408 aopPut (AOP (result), "a", offr);
6416 #ifdef BETTER_LITERAL_SHIFT
6417 /*-----------------------------------------------------------------*/
6418 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6419 /*-----------------------------------------------------------------*/
6423 emitcode ("rrc", "a");
6424 emitcode ("xch", "a,%s", x);
6425 emitcode ("rrc", "a");
6426 emitcode ("xch", "a,%s", x);
6430 #ifdef BETTER_LITERAL_SHIFT
6432 /*-----------------------------------------------------------------*/
6433 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6434 /*-----------------------------------------------------------------*/
6438 emitcode ("xch", "a,%s", x);
6439 emitcode ("rlc", "a");
6440 emitcode ("xch", "a,%s", x);
6441 emitcode ("rlc", "a");
6445 #ifdef BETTER_LITERAL_SHIFT
6446 /*-----------------------------------------------------------------*/
6447 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6448 /*-----------------------------------------------------------------*/
6452 emitcode ("xch", "a,%s", x);
6453 emitcode ("add", "a,acc");
6454 emitcode ("xch", "a,%s", x);
6455 emitcode ("rlc", "a");
6459 #ifdef BETTER_LITERAL_SHIFT
6460 /*-----------------------------------------------------------------*/
6461 /* AccAXLsh - left shift a:x by known count (0..7) */
6462 /*-----------------------------------------------------------------*/
6464 AccAXLsh (char *x, int shCount)
6479 case 5: // AAAAABBB:CCCCCDDD
6481 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6483 emitcode ("anl", "a,#0x%02x",
6484 SLMask[shCount]); // BBB00000:CCCCCDDD
6486 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6488 AccRol (shCount); // DDDCCCCC:BBB00000
6490 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6492 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6494 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6496 emitcode ("anl", "a,#0x%02x",
6497 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6499 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6501 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6504 case 6: // AAAAAABB:CCCCCCDD
6505 emitcode ("anl", "a,#0x%02x",
6506 SRMask[shCount]); // 000000BB:CCCCCCDD
6507 emitcode ("mov", "c,acc.0"); // c = B
6508 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6510 AccAXRrl1 (x); // BCCCCCCD:D000000B
6511 AccAXRrl1 (x); // BBCCCCCC:DD000000
6513 emitcode("rrc","a");
6514 emitcode("xch","a,%s", x);
6515 emitcode("rrc","a");
6516 emitcode("mov","c,acc.0"); //<< get correct bit
6517 emitcode("xch","a,%s", x);
6519 emitcode("rrc","a");
6520 emitcode("xch","a,%s", x);
6521 emitcode("rrc","a");
6522 emitcode("xch","a,%s", x);
6525 case 7: // a:x <<= 7
6527 emitcode ("anl", "a,#0x%02x",
6528 SRMask[shCount]); // 0000000B:CCCCCCCD
6530 emitcode ("mov", "c,acc.0"); // c = B
6532 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6534 AccAXRrl1 (x); // BCCCCCCC:D0000000
6543 #ifdef BETTER_LITERAL_SHIFT
6545 /*-----------------------------------------------------------------*/
6546 /* AccAXRsh - right shift a:x known count (0..7) */
6547 /*-----------------------------------------------------------------*/
6549 AccAXRsh (char *x, int shCount)
6557 AccAXRrl1 (x); // 0->a:x
6562 AccAXRrl1 (x); // 0->a:x
6565 AccAXRrl1 (x); // 0->a:x
6570 case 5: // AAAAABBB:CCCCCDDD = a:x
6572 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6574 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6576 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6578 emitcode ("anl", "a,#0x%02x",
6579 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6581 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6583 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6585 emitcode ("anl", "a,#0x%02x",
6586 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6588 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6590 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6592 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6595 case 6: // AABBBBBB:CCDDDDDD
6597 emitcode ("mov", "c,acc.7");
6598 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6600 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6602 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6604 emitcode ("anl", "a,#0x%02x",
6605 SRMask[shCount]); // 000000AA:BBBBBBCC
6608 case 7: // ABBBBBBB:CDDDDDDD
6610 emitcode ("mov", "c,acc.7"); // c = A
6612 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6614 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6616 emitcode ("anl", "a,#0x%02x",
6617 SRMask[shCount]); // 0000000A:BBBBBBBC
6626 #ifdef BETTER_LITERAL_SHIFT
6627 /*-----------------------------------------------------------------*/
6628 /* AccAXRshS - right shift signed a:x known count (0..7) */
6629 /*-----------------------------------------------------------------*/
6631 AccAXRshS (char *x, int shCount)
6639 emitcode ("mov", "c,acc.7");
6640 AccAXRrl1 (x); // s->a:x
6644 emitcode ("mov", "c,acc.7");
6645 AccAXRrl1 (x); // s->a:x
6647 emitcode ("mov", "c,acc.7");
6648 AccAXRrl1 (x); // s->a:x
6653 case 5: // AAAAABBB:CCCCCDDD = a:x
6655 tlbl = newiTempLabel (NULL);
6656 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6658 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6660 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6662 emitcode ("anl", "a,#0x%02x",
6663 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6665 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6667 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6669 emitcode ("anl", "a,#0x%02x",
6670 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6672 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6674 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6676 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6678 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6679 emitcode ("orl", "a,#0x%02x",
6680 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6682 emitcode ("", "%05d$:", tlbl->key + 100);
6683 break; // SSSSAAAA:BBBCCCCC
6685 case 6: // AABBBBBB:CCDDDDDD
6687 tlbl = newiTempLabel (NULL);
6688 emitcode ("mov", "c,acc.7");
6689 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6691 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6693 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6695 emitcode ("anl", "a,#0x%02x",
6696 SRMask[shCount]); // 000000AA:BBBBBBCC
6698 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6699 emitcode ("orl", "a,#0x%02x",
6700 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6702 emitcode ("", "%05d$:", tlbl->key + 100);
6704 case 7: // ABBBBBBB:CDDDDDDD
6706 tlbl = newiTempLabel (NULL);
6707 emitcode ("mov", "c,acc.7"); // c = A
6709 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6711 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6713 emitcode ("anl", "a,#0x%02x",
6714 SRMask[shCount]); // 0000000A:BBBBBBBC
6716 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6717 emitcode ("orl", "a,#0x%02x",
6718 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6720 emitcode ("", "%05d$:", tlbl->key + 100);
6728 #ifdef BETTER_LITERAL_SHIFT
6730 _loadLeftIntoAx(char **lsb,
6736 // Get the initial value from left into a pair of registers.
6737 // MSB must be in A, LSB can be any register.
6739 // If the result is held in registers, it is an optimization
6740 // if the LSB can be held in the register which will hold the,
6741 // result LSB since this saves us from having to copy it into
6742 // the result following AccAXLsh.
6744 // If the result is addressed indirectly, this is not a gain.
6745 if (AOP_NEEDSACC(result))
6749 _startLazyDPSEvaluation();
6750 if (AOP_TYPE(left) == AOP_DPTR2)
6753 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6754 // get LSB in DP2_RESULT_REG.
6755 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6756 assert(!strcmp(leftByte, DP2_RESULT_REG));
6760 // get LSB into DP2_RESULT_REG
6761 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6762 if (strcmp(leftByte, DP2_RESULT_REG))
6765 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6768 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6769 assert(strcmp(leftByte, DP2_RESULT_REG));
6772 _endLazyDPSEvaluation();
6773 *lsb = DP2_RESULT_REG;
6777 if (sameRegs (AOP (result), AOP (left)) &&
6778 ((offl + MSB16) == offr))
6780 /* don't crash result[offr] */
6781 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6782 emitcode ("xch", "a,%s",
6783 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6787 movLeft2Result (left, offl, result, offr, 0);
6788 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6790 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6791 assert(strcmp(*lsb,"a"));
6796 _storeAxResults(char *lsb,
6800 _startLazyDPSEvaluation();
6801 if (AOP_NEEDSACC(result))
6803 /* We have to explicitly update the result LSB.
6805 emitcode("xch","a,%s", lsb);
6806 aopPut(AOP(result), "a", offr);
6807 emitcode("mov","a,%s", lsb);
6809 if (getDataSize (result) > 1)
6811 aopPut (AOP (result), "a", offr + MSB16);
6813 _endLazyDPSEvaluation();
6816 /*-----------------------------------------------------------------*/
6817 /* shiftL2Left2Result - shift left two bytes from left to result */
6818 /*-----------------------------------------------------------------*/
6820 shiftL2Left2Result (operand * left, int offl,
6821 operand * result, int offr, int shCount)
6825 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6827 AccAXLsh (lsb, shCount);
6829 _storeAxResults(lsb, result, offr);
6833 #ifdef BETTER_LITERAL_SHIFT
6834 /*-----------------------------------------------------------------*/
6835 /* shiftR2Left2Result - shift right two bytes from left to result */
6836 /*-----------------------------------------------------------------*/
6838 shiftR2Left2Result (operand * left, int offl,
6839 operand * result, int offr,
6840 int shCount, int sign)
6844 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6846 /* a:x >> shCount (x = lsb(result)) */
6849 AccAXRshS(lsb, shCount);
6853 AccAXRsh(lsb, shCount);
6856 _storeAxResults(lsb, result, offr);
6862 /*-----------------------------------------------------------------*/
6863 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6864 /*-----------------------------------------------------------------*/
6866 shiftLLeftOrResult (operand * left, int offl,
6867 operand * result, int offr, int shCount)
6869 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6870 /* shift left accumulator */
6872 /* or with result */
6873 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6874 /* back to result */
6875 aopPut (AOP (result), "a", offr);
6881 /*-----------------------------------------------------------------*/
6882 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6883 /*-----------------------------------------------------------------*/
6885 shiftRLeftOrResult (operand * left, int offl,
6886 operand * result, int offr, int shCount)
6888 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6889 /* shift right accumulator */
6891 /* or with result */
6892 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6893 /* back to result */
6894 aopPut (AOP (result), "a", offr);
6898 #ifdef BETTER_LITERAL_SHIFT
6899 /*-----------------------------------------------------------------*/
6900 /* genlshOne - left shift a one byte quantity by known count */
6901 /*-----------------------------------------------------------------*/
6903 genlshOne (operand * result, operand * left, int shCount)
6905 D (emitcode (";", "genlshOne "););
6906 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6910 #ifdef BETTER_LITERAL_SHIFT
6911 /*-----------------------------------------------------------------*/
6912 /* genlshTwo - left shift two bytes by known amount != 0 */
6913 /*-----------------------------------------------------------------*/
6915 genlshTwo (operand * result, operand * left, int shCount)
6919 D (emitcode (";", "genlshTwo "););
6921 size = getDataSize (result);
6923 /* if shCount >= 8 */
6928 _startLazyDPSEvaluation();
6934 _endLazyDPSEvaluation();
6935 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6936 aopPut (AOP (result), zero, LSB);
6940 movLeft2Result (left, LSB, result, MSB16, 0);
6941 aopPut (AOP (result), zero, LSB);
6942 _endLazyDPSEvaluation();
6947 aopPut (AOP (result), zero, LSB);
6948 _endLazyDPSEvaluation();
6952 /* 1 <= shCount <= 7 */
6957 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6961 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6969 /*-----------------------------------------------------------------*/
6970 /* shiftLLong - shift left one long from left to result */
6971 /* offl = LSB or MSB16 */
6972 /*-----------------------------------------------------------------*/
6974 shiftLLong (operand * left, operand * result, int offr)
6977 int size = AOP_SIZE (result);
6979 if (size >= LSB + offr)
6981 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6983 emitcode ("add", "a,acc");
6984 if (sameRegs (AOP (left), AOP (result)) &&
6985 size >= MSB16 + offr && offr != LSB)
6986 emitcode ("xch", "a,%s",
6987 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6989 aopPut (AOP (result), "a", LSB + offr);
6992 if (size >= MSB16 + offr)
6994 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6996 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6999 emitcode ("rlc", "a");
7000 if (sameRegs (AOP (left), AOP (result)) &&
7001 size >= MSB24 + offr && offr != LSB)
7002 emitcode ("xch", "a,%s",
7003 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7005 aopPut (AOP (result), "a", MSB16 + offr);
7008 if (size >= MSB24 + offr)
7010 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7012 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7015 emitcode ("rlc", "a");
7016 if (sameRegs (AOP (left), AOP (result)) &&
7017 size >= MSB32 + offr && offr != LSB)
7018 emitcode ("xch", "a,%s",
7019 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7021 aopPut (AOP (result), "a", MSB24 + offr);
7024 if (size > MSB32 + offr)
7026 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7028 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7031 emitcode ("rlc", "a");
7032 aopPut (AOP (result), "a", MSB32 + offr);
7035 aopPut (AOP (result), zero, LSB);
7041 /*-----------------------------------------------------------------*/
7042 /* genlshFour - shift four byte by a known amount != 0 */
7043 /*-----------------------------------------------------------------*/
7045 genlshFour (operand * result, operand * left, int shCount)
7049 D (emitcode (";", "genlshFour ");
7052 size = AOP_SIZE (result);
7054 /* if shifting more that 3 bytes */
7059 /* lowest order of left goes to the highest
7060 order of the destination */
7061 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7063 movLeft2Result (left, LSB, result, MSB32, 0);
7064 aopPut (AOP (result), zero, LSB);
7065 aopPut (AOP (result), zero, MSB16);
7066 aopPut (AOP (result), zero, MSB24);
7070 /* more than two bytes */
7071 else if (shCount >= 16)
7073 /* lower order two bytes goes to higher order two bytes */
7075 /* if some more remaining */
7077 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7080 movLeft2Result (left, MSB16, result, MSB32, 0);
7081 movLeft2Result (left, LSB, result, MSB24, 0);
7083 aopPut (AOP (result), zero, MSB16);
7084 aopPut (AOP (result), zero, LSB);
7088 /* if more than 1 byte */
7089 else if (shCount >= 8)
7091 /* lower order three bytes goes to higher order three bytes */
7096 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7098 movLeft2Result (left, LSB, result, MSB16, 0);
7104 movLeft2Result (left, MSB24, result, MSB32, 0);
7105 movLeft2Result (left, MSB16, result, MSB24, 0);
7106 movLeft2Result (left, LSB, result, MSB16, 0);
7107 aopPut (AOP (result), zero, LSB);
7109 else if (shCount == 1)
7110 shiftLLong (left, result, MSB16);
7113 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7114 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7115 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7116 aopPut (AOP (result), zero, LSB);
7121 /* 1 <= shCount <= 7 */
7122 else if (shCount <= 2)
7124 shiftLLong (left, result, LSB);
7126 shiftLLong (result, result, LSB);
7128 /* 3 <= shCount <= 7, optimize */
7131 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7132 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7133 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7138 #ifdef BETTER_LITERAL_SHIFT
7139 /*-----------------------------------------------------------------*/
7140 /* genLeftShiftLiteral - left shifting by known count */
7141 /*-----------------------------------------------------------------*/
7143 genLeftShiftLiteral (operand * left,
7148 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7151 size = getSize (operandType (result));
7153 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7155 /* We only handle certain easy cases so far. */
7157 && (shCount < (size * 8))
7161 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7165 freeAsmop (right, NULL, ic, TRUE);
7167 aopOp(left, ic, FALSE, FALSE);
7168 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7171 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7173 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7174 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7176 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7179 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7181 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7182 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7184 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7190 emitcode ("; shift left ", "result %d, left %d", size,
7194 /* I suppose that the left size >= result size */
7197 _startLazyDPSEvaluation();
7200 movLeft2Result (left, size, result, size, 0);
7202 _endLazyDPSEvaluation();
7204 else if (shCount >= (size * 8))
7206 _startLazyDPSEvaluation();
7209 aopPut (AOP (result), zero, size);
7211 _endLazyDPSEvaluation();
7218 genlshOne (result, left, shCount);
7222 genlshTwo (result, left, shCount);
7226 genlshFour (result, left, shCount);
7230 fprintf(stderr, "*** ack! mystery literal shift!\n");
7234 freeAsmop (left, NULL, ic, TRUE);
7235 freeAsmop (result, NULL, ic, TRUE);
7240 /*-----------------------------------------------------------------*/
7241 /* genLeftShift - generates code for left shifting */
7242 /*-----------------------------------------------------------------*/
7244 genLeftShift (iCode * ic)
7246 operand *left, *right, *result;
7249 symbol *tlbl, *tlbl1;
7251 D (emitcode (";", "genLeftShift "););
7253 right = IC_RIGHT (ic);
7254 left = IC_LEFT (ic);
7255 result = IC_RESULT (ic);
7257 aopOp (right, ic, FALSE, FALSE);
7260 #ifdef BETTER_LITERAL_SHIFT
7261 /* if the shift count is known then do it
7262 as efficiently as possible */
7263 if (AOP_TYPE (right) == AOP_LIT)
7265 if (genLeftShiftLiteral (left, right, result, ic))
7272 /* shift count is unknown then we have to form
7273 a loop get the loop count in B : Note: we take
7274 only the lower order byte since shifting
7275 more that 32 bits make no sense anyway, ( the
7276 largest size of an object can be only 32 bits ) */
7278 if (AOP_TYPE (right) == AOP_LIT)
7280 /* Really should be handled by genLeftShiftLiteral,
7281 * but since I'm too lazy to fix that today, at least we can make
7282 * some small improvement.
7284 emitcode("mov", "b,#0x%02x",
7285 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7289 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7290 emitcode ("inc", "b");
7292 freeAsmop (right, NULL, ic, TRUE);
7293 aopOp (left, ic, FALSE, FALSE);
7294 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7296 /* now move the left to the result if they are not the
7298 if (!sameRegs (AOP (left), AOP (result)) &&
7299 AOP_SIZE (result) > 1)
7302 size = AOP_SIZE (result);
7304 _startLazyDPSEvaluation ();
7307 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7308 if (*l == '@' && (IS_AOP_PREG (result)))
7311 emitcode ("mov", "a,%s", l);
7312 aopPut (AOP (result), "a", offset);
7315 aopPut (AOP (result), l, offset);
7318 _endLazyDPSEvaluation ();
7321 tlbl = newiTempLabel (NULL);
7322 size = AOP_SIZE (result);
7324 tlbl1 = newiTempLabel (NULL);
7326 /* if it is only one byte then */
7329 symbol *tlbl1 = newiTempLabel (NULL);
7331 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7333 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7334 emitcode ("", "%05d$:", tlbl->key + 100);
7335 emitcode ("add", "a,acc");
7336 emitcode ("", "%05d$:", tlbl1->key + 100);
7337 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7338 aopPut (AOP (result), "a", 0);
7342 reAdjustPreg (AOP (result));
7344 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7345 emitcode ("", "%05d$:", tlbl->key + 100);
7346 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7348 emitcode ("add", "a,acc");
7349 aopPut (AOP (result), "a", offset++);
7350 _startLazyDPSEvaluation ();
7353 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7355 emitcode ("rlc", "a");
7356 aopPut (AOP (result), "a", offset++);
7358 _endLazyDPSEvaluation ();
7359 reAdjustPreg (AOP (result));
7361 emitcode ("", "%05d$:", tlbl1->key + 100);
7362 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7364 freeAsmop (left, NULL, ic, TRUE);
7365 freeAsmop (result, NULL, ic, TRUE);
7368 #ifdef BETTER_LITERAL_SHIFT
7369 /*-----------------------------------------------------------------*/
7370 /* genrshOne - right shift a one byte quantity by known count */
7371 /*-----------------------------------------------------------------*/
7373 genrshOne (operand * result, operand * left,
7374 int shCount, int sign)
7376 D (emitcode (";", "genrshOne"););
7377 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7381 #ifdef BETTER_LITERAL_SHIFT
7382 /*-----------------------------------------------------------------*/
7383 /* genrshTwo - right shift two bytes by known amount != 0 */
7384 /*-----------------------------------------------------------------*/
7386 genrshTwo (operand * result, operand * left,
7387 int shCount, int sign)
7389 D (emitcode (";", "genrshTwo"););
7391 /* if shCount >= 8 */
7395 _startLazyDPSEvaluation();
7398 shiftR1Left2Result (left, MSB16, result, LSB,
7403 movLeft2Result (left, MSB16, result, LSB, sign);
7405 addSign (result, MSB16, sign);
7406 _endLazyDPSEvaluation();
7409 /* 1 <= shCount <= 7 */
7412 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7419 /*-----------------------------------------------------------------*/
7420 /* shiftRLong - shift right one long from left to result */
7421 /* offl = LSB or MSB16 */
7422 /*-----------------------------------------------------------------*/
7424 shiftRLong (operand * left, int offl,
7425 operand * result, int sign)
7427 int isSameRegs=sameRegs(AOP(left),AOP(result));
7429 if (isSameRegs && offl>1) {
7430 // we are in big trouble, but this shouldn't happen
7431 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7434 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7439 emitcode ("rlc", "a");
7440 emitcode ("subb", "a,acc");
7441 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7443 aopPut (AOP(result), zero, MSB32);
7448 emitcode ("clr", "c");
7450 emitcode ("mov", "c,acc.7");
7453 emitcode ("rrc", "a");
7455 if (isSameRegs && offl==MSB16) {
7456 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7458 aopPut (AOP (result), "a", MSB32);
7459 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7462 emitcode ("rrc", "a");
7463 if (isSameRegs && offl==1) {
7464 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7466 aopPut (AOP (result), "a", MSB24);
7467 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7469 emitcode ("rrc", "a");
7470 aopPut (AOP (result), "a", MSB16 - offl);
7474 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7475 emitcode ("rrc", "a");
7476 aopPut (AOP (result), "a", LSB);
7483 /*-----------------------------------------------------------------*/
7484 /* genrshFour - shift four byte by a known amount != 0 */
7485 /*-----------------------------------------------------------------*/
7487 genrshFour (operand * result, operand * left,
7488 int shCount, int sign)
7490 D (emitcode (";", "genrshFour");
7493 /* if shifting more that 3 bytes */
7498 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7500 movLeft2Result (left, MSB32, result, LSB, sign);
7501 addSign (result, MSB16, sign);
7503 else if (shCount >= 16)
7507 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7510 movLeft2Result (left, MSB24, result, LSB, 0);
7511 movLeft2Result (left, MSB32, result, MSB16, sign);
7513 addSign (result, MSB24, sign);
7515 else if (shCount >= 8)
7519 shiftRLong (left, MSB16, result, sign);
7520 else if (shCount == 0)
7522 movLeft2Result (left, MSB16, result, LSB, 0);
7523 movLeft2Result (left, MSB24, result, MSB16, 0);
7524 movLeft2Result (left, MSB32, result, MSB24, sign);
7525 addSign (result, MSB32, sign);
7529 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7530 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7531 /* the last shift is signed */
7532 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7533 addSign (result, MSB32, sign);
7537 { /* 1 <= shCount <= 7 */
7540 shiftRLong (left, LSB, result, sign);
7542 shiftRLong (result, LSB, result, sign);
7546 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7547 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7548 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7554 #ifdef BETTER_LITERAL_SHIFT
7555 /*-----------------------------------------------------------------*/
7556 /* genRightShiftLiteral - right shifting by known count */
7557 /*-----------------------------------------------------------------*/
7559 genRightShiftLiteral (operand * left,
7565 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7568 size = getSize (operandType (result));
7570 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7572 /* We only handle certain easy cases so far. */
7574 && (shCount < (size * 8))
7578 D(emitcode (";", "genRightShiftLiteral wimping out"););
7582 freeAsmop (right, NULL, ic, TRUE);
7584 aopOp (left, ic, FALSE, FALSE);
7585 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7588 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7592 /* test the LEFT size !!! */
7594 /* I suppose that the left size >= result size */
7597 size = getDataSize (result);
7598 _startLazyDPSEvaluation();
7601 movLeft2Result (left, size, result, size, 0);
7603 _endLazyDPSEvaluation();
7605 else if (shCount >= (size * 8))
7609 /* get sign in acc.7 */
7610 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7612 addSign (result, LSB, sign);
7619 genrshOne (result, left, shCount, sign);
7623 genrshTwo (result, left, shCount, sign);
7627 genrshFour (result, left, shCount, sign);
7634 freeAsmop (left, NULL, ic, TRUE);
7635 freeAsmop (result, NULL, ic, TRUE);
7641 /*-----------------------------------------------------------------*/
7642 /* genSignedRightShift - right shift of signed number */
7643 /*-----------------------------------------------------------------*/
7645 genSignedRightShift (iCode * ic)
7647 operand *right, *left, *result;
7650 symbol *tlbl, *tlbl1;
7652 D (emitcode (";", "genSignedRightShift "););
7654 /* we do it the hard way put the shift count in b
7655 and loop thru preserving the sign */
7657 right = IC_RIGHT (ic);
7658 left = IC_LEFT (ic);
7659 result = IC_RESULT (ic);
7661 aopOp (right, ic, FALSE, FALSE);
7663 #ifdef BETTER_LITERAL_SHIFT
7664 if (AOP_TYPE (right) == AOP_LIT)
7666 if (genRightShiftLiteral (left, right, result, ic, 1))
7672 /* shift count is unknown then we have to form
7673 a loop get the loop count in B : Note: we take
7674 only the lower order byte since shifting
7675 more that 32 bits make no sense anyway, ( the
7676 largest size of an object can be only 32 bits ) */
7678 if (AOP_TYPE (right) == AOP_LIT)
7680 /* Really should be handled by genRightShiftLiteral,
7681 * but since I'm too lazy to fix that today, at least we can make
7682 * some small improvement.
7684 emitcode("mov", "b,#0x%02x",
7685 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7689 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7690 emitcode ("inc", "b");
7692 freeAsmop (right, NULL, ic, TRUE);
7693 aopOp (left, ic, FALSE, FALSE);
7694 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7696 /* now move the left to the result if they are not the
7698 if (!sameRegs (AOP (left), AOP (result)) &&
7699 AOP_SIZE (result) > 1)
7702 size = AOP_SIZE (result);
7704 _startLazyDPSEvaluation ();
7707 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7708 if (*l == '@' && IS_AOP_PREG (result))
7711 emitcode ("mov", "a,%s", l);
7712 aopPut (AOP (result), "a", offset);
7715 aopPut (AOP (result), l, offset);
7718 _endLazyDPSEvaluation ();
7721 /* mov the highest order bit to OVR */
7722 tlbl = newiTempLabel (NULL);
7723 tlbl1 = newiTempLabel (NULL);
7725 size = AOP_SIZE (result);
7727 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7728 emitcode ("rlc", "a");
7729 emitcode ("mov", "ov,c");
7730 /* if it is only one byte then */
7733 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7735 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7736 emitcode ("", "%05d$:", tlbl->key + 100);
7737 emitcode ("mov", "c,ov");
7738 emitcode ("rrc", "a");
7739 emitcode ("", "%05d$:", tlbl1->key + 100);
7740 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7741 aopPut (AOP (result), "a", 0);
7745 reAdjustPreg (AOP (result));
7746 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7747 emitcode ("", "%05d$:", tlbl->key + 100);
7748 emitcode ("mov", "c,ov");
7749 _startLazyDPSEvaluation ();
7752 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7754 emitcode ("rrc", "a");
7755 aopPut (AOP (result), "a", offset--);
7757 _endLazyDPSEvaluation ();
7758 reAdjustPreg (AOP (result));
7759 emitcode ("", "%05d$:", tlbl1->key + 100);
7760 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7763 freeAsmop (left, NULL, ic, TRUE);
7764 freeAsmop (result, NULL, ic, TRUE);
7767 /*-----------------------------------------------------------------*/
7768 /* genRightShift - generate code for right shifting */
7769 /*-----------------------------------------------------------------*/
7771 genRightShift (iCode * ic)
7773 operand *right, *left, *result;
7777 symbol *tlbl, *tlbl1;
7779 D (emitcode (";", "genRightShift "););
7781 /* if signed then we do it the hard way preserve the
7782 sign bit moving it inwards */
7783 retype = getSpec (operandType (IC_RESULT (ic)));
7785 if (!SPEC_USIGN (retype))
7787 genSignedRightShift (ic);
7791 /* signed & unsigned types are treated the same : i.e. the
7792 signed is NOT propagated inwards : quoting from the
7793 ANSI - standard : "for E1 >> E2, is equivalent to division
7794 by 2**E2 if unsigned or if it has a non-negative value,
7795 otherwise the result is implementation defined ", MY definition
7796 is that the sign does not get propagated */
7798 right = IC_RIGHT (ic);
7799 left = IC_LEFT (ic);
7800 result = IC_RESULT (ic);
7802 aopOp (right, ic, FALSE, FALSE);
7804 #ifdef BETTER_LITERAL_SHIFT
7805 /* if the shift count is known then do it
7806 as efficiently as possible */
7807 if (AOP_TYPE (right) == AOP_LIT)
7809 if (genRightShiftLiteral (left, right, result, ic, 0))
7816 /* shift count is unknown then we have to form
7817 a loop get the loop count in B : Note: we take
7818 only the lower order byte since shifting
7819 more that 32 bits make no sense anyway, ( the
7820 largest size of an object can be only 32 bits ) */
7822 if (AOP_TYPE (right) == AOP_LIT)
7824 /* Really should be handled by genRightShiftLiteral,
7825 * but since I'm too lazy to fix that today, at least we can make
7826 * some small improvement.
7828 emitcode("mov", "b,#0x%02x",
7829 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7833 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7834 emitcode ("inc", "b");
7836 freeAsmop (right, NULL, ic, TRUE);
7837 aopOp (left, ic, FALSE, FALSE);
7838 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7840 /* now move the left to the result if they are not the
7842 if (!sameRegs (AOP (left), AOP (result)) &&
7843 AOP_SIZE (result) > 1)
7846 size = AOP_SIZE (result);
7848 _startLazyDPSEvaluation ();
7851 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7852 if (*l == '@' && IS_AOP_PREG (result))
7855 emitcode ("mov", "a,%s", l);
7856 aopPut (AOP (result), "a", offset);
7859 aopPut (AOP (result), l, offset);
7862 _endLazyDPSEvaluation ();
7865 tlbl = newiTempLabel (NULL);
7866 tlbl1 = newiTempLabel (NULL);
7867 size = AOP_SIZE (result);
7870 /* if it is only one byte then */
7873 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7875 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7876 emitcode ("", "%05d$:", tlbl->key + 100);
7878 emitcode ("rrc", "a");
7879 emitcode ("", "%05d$:", tlbl1->key + 100);
7880 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7881 aopPut (AOP (result), "a", 0);
7885 reAdjustPreg (AOP (result));
7886 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7887 emitcode ("", "%05d$:", tlbl->key + 100);
7889 _startLazyDPSEvaluation ();
7892 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7894 emitcode ("rrc", "a");
7895 aopPut (AOP (result), "a", offset--);
7897 _endLazyDPSEvaluation ();
7898 reAdjustPreg (AOP (result));
7900 emitcode ("", "%05d$:", tlbl1->key + 100);
7901 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7904 freeAsmop (left, NULL, ic, TRUE);
7905 freeAsmop (result, NULL, ic, TRUE);
7908 /*-----------------------------------------------------------------*/
7909 /* genUnpackBits - generates code for unpacking bits */
7910 /*-----------------------------------------------------------------*/
7912 genUnpackBits (operand * result, char *rname, int ptype)
7919 D (emitcode (";", "genUnpackBits ");
7922 etype = getSpec (operandType (result));
7924 /* read the first byte */
7930 emitcode ("mov", "a,@%s", rname);
7934 emitcode ("movx", "a,@%s", rname);
7938 emitcode ("movx", "a,@dptr");
7942 emitcode ("clr", "a");
7943 emitcode ("movc", "a,@a+dptr");
7947 emitcode ("lcall", "__gptrget");
7951 /* if we have bitdisplacement then it fits */
7952 /* into this byte completely or if length is */
7953 /* less than a byte */
7954 if ((shCnt = SPEC_BSTR (etype)) ||
7955 (SPEC_BLEN (etype) <= 8))
7958 /* shift right acc */
7961 emitcode ("anl", "a,#0x%02x",
7962 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7963 aopPut (AOP (result), "a", offset);
7967 /* bit field did not fit in a byte */
7968 rlen = SPEC_BLEN (etype) - 8;
7969 aopPut (AOP (result), "a", offset++);
7978 emitcode ("inc", "%s", rname);
7979 emitcode ("mov", "a,@%s", rname);
7983 emitcode ("inc", "%s", rname);
7984 emitcode ("movx", "a,@%s", rname);
7988 emitcode ("inc", "dptr");
7989 emitcode ("movx", "a,@dptr");
7993 emitcode ("clr", "a");
7994 emitcode ("inc", "dptr");
7995 emitcode ("movc", "a,@a+dptr");
7999 emitcode ("inc", "dptr");
8000 emitcode ("lcall", "__gptrget");
8005 /* if we are done */
8009 aopPut (AOP (result), "a", offset++);
8015 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8016 aopPut (AOP (result), "a", offset);
8023 /*-----------------------------------------------------------------*/
8024 /* genDataPointerGet - generates code when ptr offset is known */
8025 /*-----------------------------------------------------------------*/
8027 genDataPointerGet (operand * left,
8033 int size, offset = 0;
8034 aopOp (result, ic, TRUE, FALSE);
8036 /* get the string representation of the name */
8037 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8038 size = AOP_SIZE (result);
8039 _startLazyDPSEvaluation ();
8043 sprintf (buffer, "(%s + %d)", l + 1, offset);
8045 sprintf (buffer, "%s", l + 1);
8046 aopPut (AOP (result), buffer, offset++);
8048 _endLazyDPSEvaluation ();
8050 freeAsmop (left, NULL, ic, TRUE);
8051 freeAsmop (result, NULL, ic, TRUE);
8054 /*-----------------------------------------------------------------*/
8055 /* genNearPointerGet - emitcode for near pointer fetch */
8056 /*-----------------------------------------------------------------*/
8058 genNearPointerGet (operand * left,
8065 sym_link *rtype, *retype, *letype;
8066 sym_link *ltype = operandType (left);
8069 rtype = operandType (result);
8070 retype = getSpec (rtype);
8071 letype = getSpec (ltype);
8073 aopOp (left, ic, FALSE, FALSE);
8075 /* if left is rematerialisable and
8076 result is not bit variable type and
8077 the left is pointer to data space i.e
8078 lower 128 bytes of space */
8079 if (AOP_TYPE (left) == AOP_IMMD &&
8080 !IS_BITVAR (retype) &&
8081 !IS_BITVAR (letype) &&
8082 DCL_TYPE (ltype) == POINTER)
8084 genDataPointerGet (left, result, ic);
8088 /* if the value is already in a pointer register
8089 then don't need anything more */
8090 if (!AOP_INPREG (AOP (left)))
8092 /* otherwise get a free pointer register */
8094 preg = getFreePtr (ic, &aop, FALSE);
8095 emitcode ("mov", "%s,%s",
8097 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8101 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8103 freeAsmop (left, NULL, ic, TRUE);
8104 aopOp (result, ic, FALSE, FALSE);
8106 /* if bitfield then unpack the bits */
8107 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8108 genUnpackBits (result, rname, POINTER);
8111 /* we have can just get the values */
8112 int size = AOP_SIZE (result);
8117 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8120 emitcode ("mov", "a,@%s", rname);
8121 aopPut (AOP (result), "a", offset);
8125 sprintf (buffer, "@%s", rname);
8126 aopPut (AOP (result), buffer, offset);
8130 emitcode ("inc", "%s", rname);
8134 /* now some housekeeping stuff */
8137 /* we had to allocate for this iCode */
8138 freeAsmop (NULL, aop, ic, TRUE);
8142 /* we did not allocate which means left
8143 already in a pointer register, then
8144 if size > 0 && this could be used again
8145 we have to point it back to where it
8147 if (AOP_SIZE (result) > 1 &&
8148 !OP_SYMBOL (left)->remat &&
8149 (OP_SYMBOL (left)->liveTo > ic->seq ||
8152 int size = AOP_SIZE (result) - 1;
8154 emitcode ("dec", "%s", rname);
8159 freeAsmop (result, NULL, ic, TRUE);
8163 /*-----------------------------------------------------------------*/
8164 /* genPagedPointerGet - emitcode for paged pointer fetch */
8165 /*-----------------------------------------------------------------*/
8167 genPagedPointerGet (operand * left,
8174 sym_link *rtype, *retype, *letype;
8176 rtype = operandType (result);
8177 retype = getSpec (rtype);
8178 letype = getSpec (operandType (left));
8179 aopOp (left, ic, FALSE, FALSE);
8181 /* if the value is already in a pointer register
8182 then don't need anything more */
8183 if (!AOP_INPREG (AOP (left)))
8185 /* otherwise get a free pointer register */
8187 preg = getFreePtr (ic, &aop, FALSE);
8188 emitcode ("mov", "%s,%s",
8190 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8194 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8196 freeAsmop (left, NULL, ic, TRUE);
8197 aopOp (result, ic, FALSE, FALSE);
8199 /* if bitfield then unpack the bits */
8200 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8201 genUnpackBits (result, rname, PPOINTER);
8204 /* we have can just get the values */
8205 int size = AOP_SIZE (result);
8211 emitcode ("movx", "a,@%s", rname);
8212 aopPut (AOP (result), "a", offset);
8217 emitcode ("inc", "%s", rname);
8221 /* now some housekeeping stuff */
8224 /* we had to allocate for this iCode */
8225 freeAsmop (NULL, aop, ic, TRUE);
8229 /* we did not allocate which means left
8230 already in a pointer register, then
8231 if size > 0 && this could be used again
8232 we have to point it back to where it
8234 if (AOP_SIZE (result) > 1 &&
8235 !OP_SYMBOL (left)->remat &&
8236 (OP_SYMBOL (left)->liveTo > ic->seq ||
8239 int size = AOP_SIZE (result) - 1;
8241 emitcode ("dec", "%s", rname);
8246 freeAsmop (result, NULL, ic, TRUE);
8251 /*-----------------------------------------------------------------*/
8252 /* genFarPointerGet - gget value from far space */
8253 /*-----------------------------------------------------------------*/
8255 genFarPointerGet (operand * left,
8256 operand * result, iCode * ic)
8259 sym_link *retype = getSpec (operandType (result));
8260 sym_link *letype = getSpec (operandType (left));
8261 D (emitcode (";", "genFarPointerGet");
8264 aopOp (left, ic, FALSE, FALSE);
8266 /* if the operand is already in dptr
8267 then we do nothing else we move the value to dptr */
8268 if (AOP_TYPE (left) != AOP_STR)
8270 /* if this is remateriazable */
8271 if (AOP_TYPE (left) == AOP_IMMD)
8273 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8277 /* we need to get it byte by byte */
8278 _startLazyDPSEvaluation ();
8279 if (AOP_TYPE (left) != AOP_DPTR)
8281 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8282 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8283 if (options.model == MODEL_FLAT24)
8284 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8288 /* We need to generate a load to DPTR indirect through DPTR. */
8289 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8291 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8292 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8293 if (options.model == MODEL_FLAT24)
8294 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8295 emitcode ("pop", "dph");
8296 emitcode ("pop", "dpl");
8298 _endLazyDPSEvaluation ();
8301 /* so dptr know contains the address */
8302 freeAsmop (left, NULL, ic, TRUE);
8303 aopOp (result, ic, FALSE, TRUE);
8305 /* if bit then unpack */
8306 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8307 genUnpackBits (result, "dptr", FPOINTER);
8310 size = AOP_SIZE (result);
8313 _startLazyDPSEvaluation ();
8320 emitcode ("movx", "a,@dptr");
8322 emitcode ("inc", "dptr");
8324 aopPut (AOP (result), "a", offset++);
8326 _endLazyDPSEvaluation ();
8329 freeAsmop (result, NULL, ic, TRUE);
8332 /*-----------------------------------------------------------------*/
8333 /* emitcodePointerGet - gget value from code space */
8334 /*-----------------------------------------------------------------*/
8336 emitcodePointerGet (operand * left,
8337 operand * result, iCode * ic)
8340 sym_link *retype = getSpec (operandType (result));
8342 aopOp (left, ic, FALSE, FALSE);
8344 /* if the operand is already in dptr
8345 then we do nothing else we move the value to dptr */
8346 if (AOP_TYPE (left) != AOP_STR)
8348 /* if this is remateriazable */
8349 if (AOP_TYPE (left) == AOP_IMMD)
8351 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8354 { /* we need to get it byte by byte */
8355 _startLazyDPSEvaluation ();
8356 if (AOP_TYPE (left) != AOP_DPTR)
8358 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8359 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8360 if (options.model == MODEL_FLAT24)
8361 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8365 /* We need to generate a load to DPTR indirect through DPTR. */
8366 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8368 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8369 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8370 if (options.model == MODEL_FLAT24)
8371 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8372 emitcode ("pop", "dph");
8373 emitcode ("pop", "dpl");
8375 _endLazyDPSEvaluation ();
8378 /* so dptr know contains the address */
8379 freeAsmop (left, NULL, ic, TRUE);
8380 aopOp (result, ic, FALSE, TRUE);
8382 /* if bit then unpack */
8383 if (IS_BITVAR (retype))
8384 genUnpackBits (result, "dptr", CPOINTER);
8387 size = AOP_SIZE (result);
8390 _startLazyDPSEvaluation ();
8396 emitcode ("clr", "a");
8397 emitcode ("movc", "a,@a+dptr");
8399 emitcode ("inc", "dptr");
8400 aopPut (AOP (result), "a", offset++);
8402 _endLazyDPSEvaluation ();
8405 freeAsmop (result, NULL, ic, TRUE);
8408 /*-----------------------------------------------------------------*/
8409 /* genGenPointerGet - gget value from generic pointer space */
8410 /*-----------------------------------------------------------------*/
8412 genGenPointerGet (operand * left,
8413 operand * result, iCode * ic)
8416 sym_link *retype = getSpec (operandType (result));
8417 sym_link *letype = getSpec (operandType (left));
8419 D (emitcode (";", "genGenPointerGet "); );
8421 aopOp (left, ic, FALSE, TRUE);
8423 /* if the operand is already in dptr
8424 then we do nothing else we move the value to dptr */
8425 if (AOP_TYPE (left) != AOP_STR)
8427 /* if this is remateriazable */
8428 if (AOP_TYPE (left) == AOP_IMMD)
8430 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8431 emitcode ("mov", "b,#%d", pointerCode (retype));
8434 { /* we need to get it byte by byte */
8435 _startLazyDPSEvaluation ();
8436 if (AOP(left)->type==AOP_DPTR2) {
8438 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8441 emitcode ("mov", "dpl,%s", l);
8442 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8445 emitcode ("mov", "dph,%s", l);
8446 if (options.model == MODEL_FLAT24) {
8447 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8450 emitcode ("mov", "dpx,%s", l);
8451 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8453 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8456 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8457 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8458 if (options.model == MODEL_FLAT24) {
8459 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8460 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8462 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8465 _endLazyDPSEvaluation ();
8468 /* so dptr know contains the address */
8469 freeAsmop (left, NULL, ic, TRUE);
8470 aopOp (result, ic, FALSE, TRUE);
8472 /* if bit then unpack */
8473 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8474 genUnpackBits (result, "dptr", GPOINTER);
8477 size = AOP_SIZE (result);
8482 emitcode ("lcall", "__gptrget");
8483 aopPut (AOP (result), "a", offset++);
8485 emitcode ("inc", "dptr");
8489 freeAsmop (result, NULL, ic, TRUE);
8492 /*-----------------------------------------------------------------*/
8493 /* genPointerGet - generate code for pointer get */
8494 /*-----------------------------------------------------------------*/
8496 genPointerGet (iCode * ic)
8498 operand *left, *result;
8499 sym_link *type, *etype;
8502 D (emitcode (";", "genPointerGet ");
8505 left = IC_LEFT (ic);
8506 result = IC_RESULT (ic);
8508 /* depending on the type of pointer we need to
8509 move it to the correct pointer register */
8510 type = operandType (left);
8511 etype = getSpec (type);
8512 /* if left is of type of pointer then it is simple */
8513 if (IS_PTR (type) && !IS_FUNC (type->next))
8514 p_type = DCL_TYPE (type);
8517 /* we have to go by the storage class */
8518 p_type = PTR_TYPE (SPEC_OCLS (etype));
8521 /* now that we have the pointer type we assign
8522 the pointer values */
8528 genNearPointerGet (left, result, ic);
8532 genPagedPointerGet (left, result, ic);
8536 genFarPointerGet (left, result, ic);
8540 emitcodePointerGet (left, result, ic);
8544 genGenPointerGet (left, result, ic);
8550 /*-----------------------------------------------------------------*/
8551 /* genPackBits - generates code for packed bit storage */
8552 /*-----------------------------------------------------------------*/
8554 genPackBits (sym_link * etype,
8556 char *rname, int p_type)
8564 blen = SPEC_BLEN (etype);
8565 bstr = SPEC_BSTR (etype);
8567 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8570 /* if the bit lenth is less than or */
8571 /* it exactly fits a byte then */
8572 if (SPEC_BLEN (etype) <= 8)
8574 shCount = SPEC_BSTR (etype);
8576 /* shift left acc */
8579 if (SPEC_BLEN (etype) < 8)
8580 { /* if smaller than a byte */
8586 emitcode ("mov", "b,a");
8587 emitcode ("mov", "a,@%s", rname);
8591 emitcode ("mov", "b,a");
8592 emitcode ("movx", "a,@dptr");
8596 emitcode ("push", "b");
8597 emitcode ("push", "acc");
8598 emitcode ("lcall", "__gptrget");
8599 emitcode ("pop", "b");
8603 emitcode ("anl", "a,#0x%02x", (unsigned char)
8604 ((unsigned char) (0xFF << (blen + bstr)) |
8605 (unsigned char) (0xFF >> (8 - bstr))));
8606 emitcode ("orl", "a,b");
8607 if (p_type == GPOINTER)
8608 emitcode ("pop", "b");
8615 emitcode ("mov", "@%s,a", rname);
8619 emitcode ("movx", "@dptr,a");
8623 emitcode ("lcall", "__gptrput");
8628 if (SPEC_BLEN (etype) <= 8)
8631 emitcode ("inc", "%s", rname);
8632 rLen = SPEC_BLEN (etype);
8634 /* now generate for lengths greater than one byte */
8638 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8650 emitcode ("mov", "@%s,a", rname);
8653 emitcode ("mov", "@%s,%s", rname, l);
8658 emitcode ("movx", "@dptr,a");
8663 emitcode ("lcall", "__gptrput");
8666 emitcode ("inc", "%s", rname);
8671 /* last last was not complete */
8674 /* save the byte & read byte */
8678 emitcode ("mov", "b,a");
8679 emitcode ("mov", "a,@%s", rname);
8683 emitcode ("mov", "b,a");
8684 emitcode ("movx", "a,@dptr");
8688 emitcode ("push", "b");
8689 emitcode ("push", "acc");
8690 emitcode ("lcall", "__gptrget");
8691 emitcode ("pop", "b");
8695 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8696 emitcode ("orl", "a,b");
8699 if (p_type == GPOINTER)
8700 emitcode ("pop", "b");
8706 emitcode ("mov", "@%s,a", rname);
8710 emitcode ("movx", "@dptr,a");
8714 emitcode ("lcall", "__gptrput");
8718 /*-----------------------------------------------------------------*/
8719 /* genDataPointerSet - remat pointer to data space */
8720 /*-----------------------------------------------------------------*/
8722 genDataPointerSet (operand * right,
8726 int size, offset = 0;
8727 char *l, buffer[256];
8729 aopOp (right, ic, FALSE, FALSE);
8731 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8732 size = AOP_SIZE (right);
8736 sprintf (buffer, "(%s + %d)", l + 1, offset);
8738 sprintf (buffer, "%s", l + 1);
8739 emitcode ("mov", "%s,%s", buffer,
8740 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8743 freeAsmop (right, NULL, ic, TRUE);
8744 freeAsmop (result, NULL, ic, TRUE);
8747 /*-----------------------------------------------------------------*/
8748 /* genNearPointerSet - emitcode for near pointer put */
8749 /*-----------------------------------------------------------------*/
8751 genNearPointerSet (operand * right,
8758 sym_link *retype, *letype;
8759 sym_link *ptype = operandType (result);
8761 retype = getSpec (operandType (right));
8762 letype = getSpec (ptype);
8764 aopOp (result, ic, FALSE, FALSE);
8766 /* if the result is rematerializable &
8767 in data space & not a bit variable */
8768 if (AOP_TYPE (result) == AOP_IMMD &&
8769 DCL_TYPE (ptype) == POINTER &&
8770 !IS_BITVAR (retype) &&
8771 !IS_BITVAR (letype))
8773 genDataPointerSet (right, result, ic);
8777 /* if the value is already in a pointer register
8778 then don't need anything more */
8779 if (!AOP_INPREG (AOP (result)))
8781 /* otherwise get a free pointer register */
8783 preg = getFreePtr (ic, &aop, FALSE);
8784 emitcode ("mov", "%s,%s",
8786 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8790 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8792 freeAsmop (result, NULL, ic, TRUE);
8793 aopOp (right, ic, FALSE, FALSE);
8795 /* if bitfield then unpack the bits */
8796 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8797 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8800 /* we have can just get the values */
8801 int size = AOP_SIZE (right);
8806 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8810 emitcode ("mov", "@%s,a", rname);
8813 emitcode ("mov", "@%s,%s", rname, l);
8815 emitcode ("inc", "%s", rname);
8820 /* now some housekeeping stuff */
8823 /* we had to allocate for this iCode */
8824 freeAsmop (NULL, aop, ic, TRUE);
8828 /* we did not allocate which means left
8829 already in a pointer register, then
8830 if size > 0 && this could be used again
8831 we have to point it back to where it
8833 if (AOP_SIZE (right) > 1 &&
8834 !OP_SYMBOL (result)->remat &&
8835 (OP_SYMBOL (result)->liveTo > ic->seq ||
8838 int size = AOP_SIZE (right) - 1;
8840 emitcode ("dec", "%s", rname);
8845 freeAsmop (right, NULL, ic, TRUE);
8850 /*-----------------------------------------------------------------*/
8851 /* genPagedPointerSet - emitcode for Paged pointer put */
8852 /*-----------------------------------------------------------------*/
8854 genPagedPointerSet (operand * right,
8861 sym_link *retype, *letype;
8863 retype = getSpec (operandType (right));
8864 letype = getSpec (operandType (result));
8866 aopOp (result, ic, FALSE, FALSE);
8868 /* if the value is already in a pointer register
8869 then don't need anything more */
8870 if (!AOP_INPREG (AOP (result)))
8872 /* otherwise get a free pointer register */
8874 preg = getFreePtr (ic, &aop, FALSE);
8875 emitcode ("mov", "%s,%s",
8877 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8881 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8883 freeAsmop (result, NULL, ic, TRUE);
8884 aopOp (right, ic, FALSE, FALSE);
8886 /* if bitfield then unpack the bits */
8887 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8888 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8891 /* we have can just get the values */
8892 int size = AOP_SIZE (right);
8897 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8900 emitcode ("movx", "@%s,a", rname);
8903 emitcode ("inc", "%s", rname);
8909 /* now some housekeeping stuff */
8912 /* we had to allocate for this iCode */
8913 freeAsmop (NULL, aop, ic, TRUE);
8917 /* we did not allocate which means left
8918 already in a pointer register, then
8919 if size > 0 && this could be used again
8920 we have to point it back to where it
8922 if (AOP_SIZE (right) > 1 &&
8923 !OP_SYMBOL (result)->remat &&
8924 (OP_SYMBOL (result)->liveTo > ic->seq ||
8927 int size = AOP_SIZE (right) - 1;
8929 emitcode ("dec", "%s", rname);
8934 freeAsmop (right, NULL, ic, TRUE);
8939 /*-----------------------------------------------------------------*/
8940 /* genFarPointerSet - set value from far space */
8941 /*-----------------------------------------------------------------*/
8943 genFarPointerSet (operand * right,
8944 operand * result, iCode * ic)
8947 sym_link *retype = getSpec (operandType (right));
8948 sym_link *letype = getSpec (operandType (result));
8950 aopOp (result, ic, FALSE, FALSE);
8952 /* if the operand is already in dptr
8953 then we do nothing else we move the value to dptr */
8954 if (AOP_TYPE (result) != AOP_STR)
8956 /* if this is remateriazable */
8957 if (AOP_TYPE (result) == AOP_IMMD)
8958 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8961 /* we need to get it byte by byte */
8962 _startLazyDPSEvaluation ();
8963 if (AOP_TYPE (result) != AOP_DPTR)
8965 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8966 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8967 if (options.model == MODEL_FLAT24)
8968 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8972 /* We need to generate a load to DPTR indirect through DPTR. */
8973 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8975 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8976 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8977 if (options.model == MODEL_FLAT24)
8978 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8979 emitcode ("pop", "dph");
8980 emitcode ("pop", "dpl");
8982 _endLazyDPSEvaluation ();
8985 /* so dptr know contains the address */
8986 freeAsmop (result, NULL, ic, TRUE);
8987 aopOp (right, ic, FALSE, TRUE);
8989 /* if bit then unpack */
8990 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8991 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8994 size = AOP_SIZE (right);
8997 _startLazyDPSEvaluation ();
9000 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9006 emitcode ("movx", "@dptr,a");
9008 emitcode ("inc", "dptr");
9010 _endLazyDPSEvaluation ();
9013 freeAsmop (right, NULL, ic, TRUE);
9016 /*-----------------------------------------------------------------*/
9017 /* genGenPointerSet - set value from generic pointer space */
9018 /*-----------------------------------------------------------------*/
9020 genGenPointerSet (operand * right,
9021 operand * result, iCode * ic)
9024 sym_link *retype = getSpec (operandType (right));
9025 sym_link *letype = getSpec (operandType (result));
9027 aopOp (result, ic, FALSE, TRUE);
9029 /* if the operand is already in dptr
9030 then we do nothing else we move the value to dptr */
9031 if (AOP_TYPE (result) != AOP_STR)
9033 _startLazyDPSEvaluation ();
9034 /* if this is remateriazable */
9035 if (AOP_TYPE (result) == AOP_IMMD)
9037 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9038 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9041 { /* we need to get it byte by byte */
9042 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9043 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9044 if (options.model == MODEL_FLAT24) {
9045 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9046 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9048 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9051 _endLazyDPSEvaluation ();
9053 /* so dptr know contains the address */
9054 freeAsmop (result, NULL, ic, TRUE);
9055 aopOp (right, ic, FALSE, TRUE);
9057 /* if bit then unpack */
9058 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9059 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9062 size = AOP_SIZE (right);
9065 _startLazyDPSEvaluation ();
9068 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9074 emitcode ("lcall", "__gptrput");
9076 emitcode ("inc", "dptr");
9078 _endLazyDPSEvaluation ();
9081 freeAsmop (right, NULL, ic, TRUE);
9084 /*-----------------------------------------------------------------*/
9085 /* genPointerSet - stores the value into a pointer location */
9086 /*-----------------------------------------------------------------*/
9088 genPointerSet (iCode * ic)
9090 operand *right, *result;
9091 sym_link *type, *etype;
9094 D (emitcode (";", "genPointerSet ");
9097 right = IC_RIGHT (ic);
9098 result = IC_RESULT (ic);
9100 /* depending on the type of pointer we need to
9101 move it to the correct pointer register */
9102 type = operandType (result);
9103 etype = getSpec (type);
9104 /* if left is of type of pointer then it is simple */
9105 if (IS_PTR (type) && !IS_FUNC (type->next))
9107 p_type = DCL_TYPE (type);
9111 /* we have to go by the storage class */
9112 p_type = PTR_TYPE (SPEC_OCLS (etype));
9115 /* now that we have the pointer type we assign
9116 the pointer values */
9122 genNearPointerSet (right, result, ic);
9126 genPagedPointerSet (right, result, ic);
9130 genFarPointerSet (right, result, ic);
9134 genGenPointerSet (right, result, ic);
9140 /*-----------------------------------------------------------------*/
9141 /* genIfx - generate code for Ifx statement */
9142 /*-----------------------------------------------------------------*/
9144 genIfx (iCode * ic, iCode * popIc)
9146 operand *cond = IC_COND (ic);
9149 D (emitcode (";", "genIfx "););
9151 aopOp (cond, ic, FALSE, FALSE);
9153 /* get the value into acc */
9154 if (AOP_TYPE (cond) != AOP_CRY)
9158 /* the result is now in the accumulator */
9159 freeAsmop (cond, NULL, ic, TRUE);
9161 /* if there was something to be popped then do it */
9165 /* if the condition is a bit variable */
9166 if (isbit && IS_ITEMP (cond) &&
9168 genIfxJump (ic, SPIL_LOC (cond)->rname);
9169 else if (isbit && !IS_ITEMP (cond))
9170 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9172 genIfxJump (ic, "a");
9177 /*-----------------------------------------------------------------*/
9178 /* genAddrOf - generates code for address of */
9179 /*-----------------------------------------------------------------*/
9181 genAddrOf (iCode * ic)
9183 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9186 D (emitcode (";", "genAddrOf ");
9189 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9191 /* if the operand is on the stack then we
9192 need to get the stack offset of this
9196 /* if it has an offset then we need to compute
9200 emitcode ("mov", "a,_bp");
9201 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9202 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9206 /* we can just move _bp */
9207 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9209 /* fill the result with zero */
9210 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9213 if (options.stack10bit && size < (FPTRSIZE - 1))
9216 "*** warning: pointer to stack var truncated.\n");
9223 if (options.stack10bit && offset == 2)
9225 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9229 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9236 /* object not on stack then we need the name */
9237 size = AOP_SIZE (IC_RESULT (ic));
9242 char s[SDCC_NAME_MAX];
9244 sprintf (s, "#(%s >> %d)",
9248 sprintf (s, "#%s", sym->rname);
9249 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9253 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9257 /*-----------------------------------------------------------------*/
9258 /* genArrayInit - generates code for address of */
9259 /*-----------------------------------------------------------------*/
9261 genArrayInit (iCode * ic)
9265 int elementSize = 0, eIndex;
9266 unsigned val, lastVal;
9268 operand *left=IC_LEFT(ic);
9270 D (emitcode (";", "genArrayInit "););
9272 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9274 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9276 // Load immediate value into DPTR.
9277 emitcode("mov", "dptr, %s",
9278 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9280 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9283 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9284 "Unexpected operand to genArrayInit.\n");
9287 // a regression because of SDCCcse.c:1.52
9288 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9289 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9290 if (options.model == MODEL_FLAT24)
9291 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9295 type = operandType(IC_LEFT(ic));
9297 if (type && type->next)
9299 elementSize = getSize(type->next);
9303 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9304 "can't determine element size in genArrayInit.\n");
9308 iLoop = IC_ARRAYILIST(ic);
9313 bool firstpass = TRUE;
9315 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9316 iLoop->count, (int)iLoop->literalValue, elementSize);
9322 symbol *tlbl = NULL;
9324 count = ix > 256 ? 256 : ix;
9328 tlbl = newiTempLabel (NULL);
9329 if (firstpass || (count & 0xff))
9331 emitcode("mov", "b, #0x%x", count & 0xff);
9334 emitcode ("", "%05d$:", tlbl->key + 100);
9339 for (eIndex = 0; eIndex < elementSize; eIndex++)
9341 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9344 emitcode("mov", "a, #0x%x", val);
9348 emitcode("movx", "@dptr, a");
9349 emitcode("inc", "dptr");
9354 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9360 iLoop = iLoop->next;
9363 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9366 /*-----------------------------------------------------------------*/
9367 /* genFarFarAssign - assignment when both are in far space */
9368 /*-----------------------------------------------------------------*/
9370 genFarFarAssign (operand * result, operand * right, iCode * ic)
9372 int size = AOP_SIZE (right);
9374 symbol *rSym = NULL;
9378 /* quick & easy case. */
9379 D(emitcode(";","genFarFarAssign (1 byte case)"););
9380 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9381 freeAsmop (right, NULL, ic, FALSE);
9382 /* now assign DPTR to result */
9384 aopOp(result, ic, FALSE, FALSE);
9386 aopPut(AOP(result), "a", 0);
9387 freeAsmop(result, NULL, ic, FALSE);
9391 /* See if we've got an underlying symbol to abuse. */
9392 if (IS_SYMOP(result) && OP_SYMBOL(result))
9394 if (IS_TRUE_SYMOP(result))
9396 rSym = OP_SYMBOL(result);
9398 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9400 rSym = OP_SYMBOL(result)->usl.spillLoc;
9404 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9406 /* We can use the '390 auto-toggle feature to good effect here. */
9408 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9409 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9410 emitcode ("mov", "dptr,#%s", rSym->rname);
9411 /* DP2 = result, DP1 = right, DP1 is current. */
9414 emitcode("movx", "a,@dptr");
9415 emitcode("movx", "@dptr,a");
9418 emitcode("inc", "dptr");
9419 emitcode("inc", "dptr");
9422 emitcode("mov", "dps, #0");
9423 freeAsmop (right, NULL, ic, FALSE);
9425 some alternative code for processors without auto-toggle
9426 no time to test now, so later well put in...kpb
9427 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9428 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9429 emitcode ("mov", "dptr,#%s", rSym->rname);
9430 /* DP2 = result, DP1 = right, DP1 is current. */
9434 emitcode("movx", "a,@dptr");
9436 emitcode("inc", "dptr");
9437 emitcode("inc", "dps");
9438 emitcode("movx", "@dptr,a");
9440 emitcode("inc", "dptr");
9441 emitcode("inc", "dps");
9443 emitcode("mov", "dps, #0");
9444 freeAsmop (right, NULL, ic, FALSE);
9449 D (emitcode (";", "genFarFarAssign"););
9450 aopOp (result, ic, TRUE, TRUE);
9452 _startLazyDPSEvaluation ();
9456 aopPut (AOP (result),
9457 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9460 _endLazyDPSEvaluation ();
9461 freeAsmop (result, NULL, ic, FALSE);
9462 freeAsmop (right, NULL, ic, FALSE);
9466 /*-----------------------------------------------------------------*/
9467 /* genAssign - generate code for assignment */
9468 /*-----------------------------------------------------------------*/
9470 genAssign (iCode * ic)
9472 operand *result, *right;
9474 unsigned long lit = 0L;
9476 D (emitcode (";", "genAssign ");
9479 result = IC_RESULT (ic);
9480 right = IC_RIGHT (ic);
9482 /* if they are the same */
9483 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9486 aopOp (right, ic, FALSE, FALSE);
9488 emitcode (";", "genAssign: resultIsFar = %s",
9489 isOperandInFarSpace (result) ?
9492 /* special case both in far space */
9493 if ((AOP_TYPE (right) == AOP_DPTR ||
9494 AOP_TYPE (right) == AOP_DPTR2) &&
9495 /* IS_TRUE_SYMOP(result) && */
9496 isOperandInFarSpace (result))
9498 genFarFarAssign (result, right, ic);
9502 aopOp (result, ic, TRUE, FALSE);
9504 /* if they are the same registers */
9505 if (sameRegs (AOP (right), AOP (result)))
9508 /* if the result is a bit */
9509 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9511 /* if the right size is a literal then
9512 we know what the value is */
9513 if (AOP_TYPE (right) == AOP_LIT)
9515 if (((int) operandLitValue (right)))
9516 aopPut (AOP (result), one, 0);
9518 aopPut (AOP (result), zero, 0);
9522 /* the right is also a bit variable */
9523 if (AOP_TYPE (right) == AOP_CRY)
9525 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9526 aopPut (AOP (result), "c", 0);
9532 aopPut (AOP (result), "a", 0);
9536 /* bit variables done */
9538 size = AOP_SIZE (result);
9540 if (AOP_TYPE (right) == AOP_LIT)
9541 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9544 (AOP_TYPE (result) != AOP_REG) &&
9545 (AOP_TYPE (right) == AOP_LIT) &&
9546 !IS_FLOAT (operandType (right)))
9548 _startLazyDPSEvaluation ();
9549 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9551 aopPut (AOP (result),
9552 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9557 /* And now fill the rest with zeros. */
9560 emitcode ("clr", "a");
9564 aopPut (AOP (result), "a", offset++);
9566 _endLazyDPSEvaluation ();
9570 _startLazyDPSEvaluation ();
9573 aopPut (AOP (result),
9574 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9578 _endLazyDPSEvaluation ();
9582 freeAsmop (right, NULL, ic, FALSE);
9583 freeAsmop (result, NULL, ic, TRUE);
9586 /*-----------------------------------------------------------------*/
9587 /* genJumpTab - generates code for jump table */
9588 /*-----------------------------------------------------------------*/
9590 genJumpTab (iCode * ic)
9595 D (emitcode (";", "genJumpTab ");
9598 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9599 /* get the condition into accumulator */
9600 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9602 /* multiply by four! */
9603 emitcode ("add", "a,acc");
9604 emitcode ("add", "a,acc");
9605 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9607 jtab = newiTempLabel (NULL);
9608 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9609 emitcode ("jmp", "@a+dptr");
9610 emitcode ("", "%05d$:", jtab->key + 100);
9611 /* now generate the jump labels */
9612 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9613 jtab = setNextItem (IC_JTLABELS (ic)))
9614 emitcode ("ljmp", "%05d$", jtab->key + 100);
9618 /*-----------------------------------------------------------------*/
9619 /* genCast - gen code for casting */
9620 /*-----------------------------------------------------------------*/
9622 genCast (iCode * ic)
9624 operand *result = IC_RESULT (ic);
9625 sym_link *ctype = operandType (IC_LEFT (ic));
9626 sym_link *rtype = operandType (IC_RIGHT (ic));
9627 operand *right = IC_RIGHT (ic);
9630 D (emitcode (";", "genCast ");
9633 /* if they are equivalent then do nothing */
9634 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9637 aopOp (right, ic, FALSE, FALSE);
9638 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9640 /* if the result is a bit */
9641 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9642 if (IS_BITVAR(OP_SYMBOL(result)->type))
9644 /* if the right size is a literal then
9645 we know what the value is */
9646 if (AOP_TYPE (right) == AOP_LIT)
9648 if (((int) operandLitValue (right)))
9649 aopPut (AOP (result), one, 0);
9651 aopPut (AOP (result), zero, 0);
9656 /* the right is also a bit variable */
9657 if (AOP_TYPE (right) == AOP_CRY)
9659 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9660 aopPut (AOP (result), "c", 0);
9666 aopPut (AOP (result), "a", 0);
9670 /* if they are the same size : or less */
9671 if (AOP_SIZE (result) <= AOP_SIZE (right))
9674 /* if they are in the same place */
9675 if (sameRegs (AOP (right), AOP (result)))
9678 /* if they in different places then copy */
9679 size = AOP_SIZE (result);
9681 _startLazyDPSEvaluation ();
9684 aopPut (AOP (result),
9685 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9689 _endLazyDPSEvaluation ();
9694 /* if the result is of type pointer */
9699 sym_link *type = operandType (right);
9701 /* pointer to generic pointer */
9702 if (IS_GENPTR (ctype))
9708 p_type = DCL_TYPE (type);
9712 #if OLD_CAST_BEHAVIOR
9713 /* KV: we are converting a non-pointer type to
9714 * a generic pointer. This (ifdef'd out) code
9715 * says that the resulting generic pointer
9716 * should have the same class as the storage
9717 * location of the non-pointer variable.
9719 * For example, converting an int (which happens
9720 * to be stored in DATA space) to a pointer results
9721 * in a DATA generic pointer; if the original int
9722 * in XDATA space, so will be the resulting pointer.
9724 * I don't like that behavior, and thus this change:
9725 * all such conversions will be forced to XDATA and
9726 * throw a warning. If you want some non-XDATA
9727 * type, or you want to suppress the warning, you
9728 * must go through an intermediate cast, like so:
9730 * char _generic *gp = (char _xdata *)(intVar);
9732 sym_link *etype = getSpec (type);
9734 /* we have to go by the storage class */
9735 if (SPEC_OCLS (etype) != generic)
9737 p_type = PTR_TYPE (SPEC_OCLS (etype));
9742 /* Converting unknown class (i.e. register variable)
9743 * to generic pointer. This is not good, but
9744 * we'll make a guess (and throw a warning).
9747 werror (W_INT_TO_GEN_PTR_CAST);
9751 /* the first two bytes are known */
9752 size = GPTRSIZE - 1;
9754 _startLazyDPSEvaluation ();
9757 aopPut (AOP (result),
9758 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9762 _endLazyDPSEvaluation ();
9764 /* the last byte depending on type */
9782 /* this should never happen */
9783 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9784 "got unknown pointer type");
9787 aopPut (AOP (result), l, GPTRSIZE - 1);
9791 /* just copy the pointers */
9792 size = AOP_SIZE (result);
9794 _startLazyDPSEvaluation ();
9797 aopPut (AOP (result),
9798 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9802 _endLazyDPSEvaluation ();
9806 /* so we now know that the size of destination is greater
9807 than the size of the source */
9808 /* we move to result for the size of source */
9809 size = AOP_SIZE (right);
9811 _startLazyDPSEvaluation ();
9814 aopPut (AOP (result),
9815 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9819 _endLazyDPSEvaluation ();
9821 /* now depending on the sign of the source && destination */
9822 size = AOP_SIZE (result) - AOP_SIZE (right);
9823 /* if unsigned or not an integral type */
9824 /* also, if the source is a bit, we don't need to sign extend, because
9825 * it can't possibly have set the sign bit.
9827 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9831 aopPut (AOP (result), zero, offset++);
9836 /* we need to extend the sign :{ */
9837 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9838 FALSE, FALSE, TRUE);
9840 emitcode ("rlc", "a");
9841 emitcode ("subb", "a,acc");
9843 aopPut (AOP (result), "a", offset++);
9846 /* we are done hurray !!!! */
9849 freeAsmop (right, NULL, ic, TRUE);
9850 freeAsmop (result, NULL, ic, TRUE);
9854 /*-----------------------------------------------------------------*/
9855 /* genDjnz - generate decrement & jump if not zero instrucion */
9856 /*-----------------------------------------------------------------*/
9858 genDjnz (iCode * ic, iCode * ifx)
9864 /* if the if condition has a false label
9865 then we cannot save */
9869 /* if the minus is not of the form
9871 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9872 !IS_OP_LITERAL (IC_RIGHT (ic)))
9875 if (operandLitValue (IC_RIGHT (ic)) != 1)
9878 /* if the size of this greater than one then no
9880 if (getSize (operandType (IC_RESULT (ic))) > 1)
9883 /* otherwise we can save BIG */
9884 D(emitcode(";", "genDjnz"););
9886 lbl = newiTempLabel (NULL);
9887 lbl1 = newiTempLabel (NULL);
9889 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9891 if (AOP_NEEDSACC(IC_RESULT(ic)))
9893 /* If the result is accessed indirectly via
9894 * the accumulator, we must explicitly write
9895 * it back after the decrement.
9897 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9899 if (strcmp(rByte, "a"))
9901 /* Something is hopelessly wrong */
9902 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9903 __FILE__, __LINE__);
9904 /* We can just give up; the generated code will be inefficient,
9907 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9910 emitcode ("dec", "%s", rByte);
9911 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9912 emitcode ("jnz", "%05d$", lbl->key + 100);
9914 else if (IS_AOP_PREG (IC_RESULT (ic)))
9916 emitcode ("dec", "%s",
9917 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9918 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9919 emitcode ("jnz", "%05d$", lbl->key + 100);
9923 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9926 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9927 emitcode ("", "%05d$:", lbl->key + 100);
9928 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9929 emitcode ("", "%05d$:", lbl1->key + 100);
9931 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9936 /*-----------------------------------------------------------------*/
9937 /* genReceive - generate code for a receive iCode */
9938 /*-----------------------------------------------------------------*/
9940 genReceive (iCode * ic)
9943 D (emitcode (";", "genReceive ");
9946 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9947 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9948 IS_TRUE_SYMOP (IC_RESULT (ic))))
9950 int size = getSize (operandType (IC_RESULT (ic)));
9951 int offset = fReturnSizeDS390 - size;
9954 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9955 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9958 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9959 size = AOP_SIZE (IC_RESULT (ic));
9963 emitcode ("pop", "acc");
9964 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9971 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9973 assignResultValue (IC_RESULT (ic));
9976 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9979 /*-----------------------------------------------------------------*/
9980 /* gen390Code - generate code for Dallas 390 based controllers */
9981 /*-----------------------------------------------------------------*/
9983 gen390Code (iCode * lic)
9988 lineHead = lineCurr = NULL;
9990 if (options.model == MODEL_FLAT24) {
9991 fReturnSizeDS390 = 5;
9992 fReturn = fReturn24;
9994 fReturnSizeDS390 = 4;
9995 fReturn = fReturn16;
9996 options.stack10bit=0;
10000 /* print the allocation information */
10002 printAllocInfo (currFunc, codeOutFile);
10004 /* if debug information required */
10005 if (options.debug && currFunc)
10007 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10009 if (IS_STATIC (currFunc->etype))
10010 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10012 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10015 /* stack pointer name */
10016 if (options.useXstack)
10022 for (ic = lic; ic; ic = ic->next)
10025 if (cln != ic->lineno)
10030 emitcode ("", "C$%s$%d$%d$%d ==.",
10031 FileBaseName (ic->filename), ic->lineno,
10032 ic->level, ic->block);
10035 emitcode (";", "%s %d", ic->filename, ic->lineno);
10038 /* if the result is marked as
10039 spilt and rematerializable or code for
10040 this has already been generated then
10042 if (resultRemat (ic) || ic->generated)
10045 /* depending on the operation */
10065 /* IPOP happens only when trying to restore a
10066 spilt live range, if there is an ifx statement
10067 following this pop then the if statement might
10068 be using some of the registers being popped which
10069 would destory the contents of the register so
10070 we need to check for this condition and handle it */
10072 ic->next->op == IFX &&
10073 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10074 genIfx (ic->next, ic);
10092 genEndFunction (ic);
10112 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10129 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10133 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10140 /* note these two are xlated by algebraic equivalence
10141 during parsing SDCC.y */
10142 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10143 "got '>=' or '<=' shouldn't have come here");
10147 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10159 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10163 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10167 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10191 genRightShift (ic);
10194 case GET_VALUE_AT_ADDRESS:
10195 genPointerGet (ic);
10199 if (POINTER_SET (ic))
10200 genPointerSet (ic);
10226 addSet (&_G.sendSet, ic);
10239 /* now we are ready to call the
10240 peep hole optimizer */
10241 if (!options.nopeep)
10242 peepHole (&lineHead);
10244 /* now do the actual printing */
10245 printLine (lineHead, codeOutFile);