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 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3362 // Please don't bring it back without a really good reason.
3363 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3364 // (because all three operands are in far space).
3365 #define AOP_OP_3(ic) \
3366 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3367 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3368 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3369 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3370 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3371 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3373 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3375 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3379 // Macro to aopOp all three operands of an ic. If this cannot be done,
3380 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3381 // will be set TRUE. The caller must then handle the case specially, noting
3382 // that the IC_RESULT operand is not aopOp'd.
3383 #define AOP_OP_3_NOFATAL(ic, rc) \
3384 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3385 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3386 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3387 isOperandInFarSpace(IC_RESULT(ic))) \
3389 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3394 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3395 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3397 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3398 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3400 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3402 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3406 // aopOp the left & right operands of an ic.
3407 #define AOP_OP_2(ic) \
3408 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3409 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3411 // convienience macro.
3412 #define AOP_SET_LOCALS(ic) \
3413 left = IC_LEFT(ic); \
3414 right = IC_RIGHT(ic); \
3415 result = IC_RESULT(ic);
3418 // Given an integer value of pushedSize bytes on the stack,
3419 // adjust it to be resultSize bytes, either by discarding
3420 // the most significant bytes or by zero-padding.
3422 // On exit from this macro, pushedSize will have been adjusted to
3423 // equal resultSize, and ACC may be trashed.
3424 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3425 /* If the pushed data is bigger than the result, \
3426 * simply discard unused bytes. Icky, but works. \
3428 while (pushedSize > resultSize) \
3430 D (emitcode (";", "discarding unused result byte."););\
3431 emitcode ("pop", "acc"); \
3434 if (pushedSize < resultSize) \
3436 emitcode ("clr", "a"); \
3437 /* Conversly, we haven't pushed enough here. \
3438 * just zero-pad, and all is well. \
3440 while (pushedSize < resultSize) \
3442 emitcode("push", "acc"); \
3446 assert(pushedSize == resultSize);
3448 /*-----------------------------------------------------------------*/
3449 /* genPlus - generates code for addition */
3450 /*-----------------------------------------------------------------*/
3452 genPlus (iCode * ic)
3454 int size, offset = 0;
3455 bool pushResult = FALSE;
3458 D (emitcode (";", "genPlus "););
3460 /* special cases :- */
3462 AOP_OP_3_NOFATAL (ic, pushResult);
3465 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3470 /* if literal, literal on the right or
3471 if left requires ACC or right is already
3473 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3474 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3475 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3477 operand *t = IC_RIGHT (ic);
3478 IC_RIGHT (ic) = IC_LEFT (ic);
3480 emitcode (";", "Swapped plus args.");
3483 /* if both left & right are in bit
3485 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3486 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3492 /* if left in bit space & right literal */
3493 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3494 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3496 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3497 /* if result in bit space */
3498 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3500 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3501 emitcode ("cpl", "c");
3502 outBitC (IC_RESULT (ic));
3506 size = getDataSize (IC_RESULT (ic));
3507 _startLazyDPSEvaluation ();
3510 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3511 emitcode ("addc", "a,#00");
3512 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3514 _endLazyDPSEvaluation ();
3519 /* if I can do an increment instead
3520 of add then GOOD for ME */
3521 if (genPlusIncr (ic) == TRUE)
3523 emitcode (";", "did genPlusIncr");
3528 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3530 _startLazyDPSEvaluation ();
3533 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3535 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3537 emitcode ("add", "a,%s",
3538 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3540 emitcode ("addc", "a,%s",
3541 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3545 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3547 /* right is going to use ACC or we would have taken the
3550 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3552 D(emitcode(";", "+ AOP_ACC special case."););
3553 emitcode("xch", "a, %s", DP2_RESULT_REG);
3555 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3558 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3561 emitcode("add", "a, %s", DP2_RESULT_REG);
3565 emitcode ("add", "a,%s",
3566 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3571 emitcode ("addc", "a,%s",
3572 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3577 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3581 emitcode ("push", "acc");
3585 _endLazyDPSEvaluation ();
3589 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3591 size = getDataSize (IC_LEFT (ic));
3592 rSize = getDataSize (IC_RESULT (ic));
3594 ADJUST_PUSHED_RESULT(size, rSize);
3596 _startLazyDPSEvaluation ();
3599 emitcode ("pop", "acc");
3600 aopPut (AOP (IC_RESULT (ic)), "a", size);
3602 _endLazyDPSEvaluation ();
3605 adjustArithmeticResult (ic);
3608 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3609 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3610 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3613 /*-----------------------------------------------------------------*/
3614 /* genMinusDec :- does subtraction with deccrement if possible */
3615 /*-----------------------------------------------------------------*/
3617 genMinusDec (iCode * ic)
3619 unsigned int icount;
3620 unsigned int size = getDataSize (IC_RESULT (ic));
3622 /* will try to generate an increment */
3623 /* if the right side is not a literal
3625 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3628 /* if the literal value of the right hand side
3629 is greater than 4 then it is not worth it */
3630 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3633 /* if decrement 16 bits in register */
3634 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3635 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3636 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3644 /* If the next instruction is a goto and the goto target
3645 * is <= 5 instructions previous to this, we can generate
3646 * jumps straight to that target.
3648 if (ic->next && ic->next->op == GOTO
3649 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3652 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3653 tlbl = IC_LABEL (ic->next);
3658 tlbl = newiTempLabel (NULL);
3662 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3663 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3664 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3665 IS_AOP_PREG (IC_RESULT (ic)))
3666 emitcode ("cjne", "%s,#0xff,%05d$"
3667 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3671 emitcode ("mov", "a,#0xff");
3672 emitcode ("cjne", "a,%s,%05d$"
3673 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3676 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3679 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3680 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3681 IS_AOP_PREG (IC_RESULT (ic)))
3682 emitcode ("cjne", "%s,#0xff,%05d$"
3683 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3687 emitcode ("cjne", "a,%s,%05d$"
3688 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3691 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3695 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3696 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3697 IS_AOP_PREG (IC_RESULT (ic)))
3698 emitcode ("cjne", "%s,#0xff,%05d$"
3699 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3703 emitcode ("cjne", "a,%s,%05d$"
3704 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3707 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3711 emitcode ("", "%05d$:", tlbl->key + 100);
3716 /* if the sizes are greater than 1 then we cannot */
3717 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3718 AOP_SIZE (IC_LEFT (ic)) > 1)
3721 /* we can if the aops of the left & result match or
3722 if they are in registers and the registers are the
3725 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3726 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3727 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3730 _startLazyDPSEvaluation ();
3733 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3735 _endLazyDPSEvaluation ();
3743 /*-----------------------------------------------------------------*/
3744 /* addSign - complete with sign */
3745 /*-----------------------------------------------------------------*/
3747 addSign (operand * result, int offset, int sign)
3749 int size = (getDataSize (result) - offset);
3752 _startLazyDPSEvaluation();
3755 emitcode ("rlc", "a");
3756 emitcode ("subb", "a,acc");
3759 aopPut (AOP (result), "a", offset++);
3766 aopPut (AOP (result), zero, offset++);
3769 _endLazyDPSEvaluation();
3773 /*-----------------------------------------------------------------*/
3774 /* genMinusBits - generates code for subtraction of two bits */
3775 /*-----------------------------------------------------------------*/
3777 genMinusBits (iCode * ic)
3779 symbol *lbl = newiTempLabel (NULL);
3781 D (emitcode (";", "genMinusBits "););
3783 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3785 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3786 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3787 emitcode ("cpl", "c");
3788 emitcode ("", "%05d$:", (lbl->key + 100));
3789 outBitC (IC_RESULT (ic));
3793 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3794 emitcode ("subb", "a,acc");
3795 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3796 emitcode ("inc", "a");
3797 emitcode ("", "%05d$:", (lbl->key + 100));
3798 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3799 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3803 /*-----------------------------------------------------------------*/
3804 /* genMinus - generates code for subtraction */
3805 /*-----------------------------------------------------------------*/
3807 genMinus (iCode * ic)
3809 int size, offset = 0;
3811 unsigned long lit = 0L;
3812 bool pushResult = FALSE;
3814 D (emitcode (";", "genMinus "););
3816 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3817 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3818 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3819 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3825 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3827 /* special cases :- */
3828 /* if both left & right are in bit space */
3829 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3830 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3836 /* if I can do an decrement instead
3837 of subtract then GOOD for ME */
3838 if (genMinusDec (ic) == TRUE)
3843 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3845 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3851 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3856 /* if literal, add a,#-lit, else normal subb */
3857 _startLazyDPSEvaluation ();
3860 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3861 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3862 emitcode ("subb", "a,%s",
3863 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3866 /* first add without previous c */
3868 if (!size && lit==-1) {
3869 emitcode ("dec", "a");
3871 emitcode ("add", "a,#0x%02x",
3872 (unsigned int) (lit & 0x0FFL));
3875 emitcode ("addc", "a,#0x%02x",
3876 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3882 emitcode ("push", "acc");
3886 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3890 _endLazyDPSEvaluation ();
3894 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3896 size = getDataSize (IC_LEFT (ic));
3897 rSize = getDataSize (IC_RESULT (ic));
3899 ADJUST_PUSHED_RESULT(size, rSize);
3901 _startLazyDPSEvaluation ();
3904 emitcode ("pop", "acc");
3905 aopPut (AOP (IC_RESULT (ic)), "a", size);
3907 _endLazyDPSEvaluation ();
3910 adjustArithmeticResult (ic);
3913 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3914 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3915 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3919 /*-----------------------------------------------------------------*/
3920 /* genMultbits :- multiplication of bits */
3921 /*-----------------------------------------------------------------*/
3923 genMultbits (operand * left,
3928 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3929 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3930 aopOp(result, ic, TRUE, FALSE);
3935 /*-----------------------------------------------------------------*/
3936 /* genMultOneByte : 8*8=8/16 bit multiplication */
3937 /*-----------------------------------------------------------------*/
3939 genMultOneByte (operand * left,
3944 sym_link *opetype = operandType (result);
3948 /* (if two literals: the value is computed before) */
3949 /* if one literal, literal on the right */
3950 if (AOP_TYPE (left) == AOP_LIT)
3955 emitcode (";", "swapped left and right");
3958 if (SPEC_USIGN(opetype)
3959 // ignore the sign of left and right, what else can we do?
3960 || (SPEC_USIGN(operandType(left)) &&
3961 SPEC_USIGN(operandType(right)))) {
3962 // just an unsigned 8*8=8/16 multiply
3963 //emitcode (";","unsigned");
3964 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3965 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3966 emitcode ("mul", "ab");
3969 aopOp(result, ic, TRUE, FALSE);
3971 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3973 // this should never happen
3974 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3975 AOP_SIZE(result), __FILE__, lineno);
3979 aopPut (AOP (result), "a", 0);
3981 if (AOP_SIZE(result)==2)
3983 aopPut (AOP (result), "b", 1);
3988 // we have to do a signed multiply
3990 emitcode (";", "signed");
3991 emitcode ("clr", "F0"); // reset sign flag
3992 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3994 lbl=newiTempLabel(NULL);
3995 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3996 // left side is negative, 8-bit two's complement, this fails for -128
3997 emitcode ("setb", "F0"); // set sign flag
3998 emitcode ("cpl", "a");
3999 emitcode ("inc", "a");
4001 emitcode ("", "%05d$:", lbl->key+100);
4004 if (AOP_TYPE(right)==AOP_LIT) {
4005 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4006 /* AND literal negative */
4007 if ((int) val < 0) {
4008 emitcode ("cpl", "F0"); // complement sign flag
4009 emitcode ("mov", "b,#0x%02x", -val);
4011 emitcode ("mov", "b,#0x%02x", val);
4014 lbl=newiTempLabel(NULL);
4015 emitcode ("mov", "b,a");
4016 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4017 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4018 // right side is negative, 8-bit two's complement
4019 emitcode ("cpl", "F0"); // complement sign flag
4020 emitcode ("cpl", "a");
4021 emitcode ("inc", "a");
4022 emitcode ("", "%05d$:", lbl->key+100);
4024 emitcode ("mul", "ab");
4027 aopOp(result, ic, TRUE, FALSE);
4029 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4031 // this should never happen
4032 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4033 AOP_SIZE(result), __FILE__, lineno);
4037 lbl=newiTempLabel(NULL);
4038 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4039 // only ONE op was negative, we have to do a 8/16-bit two's complement
4040 emitcode ("cpl", "a"); // lsb
4041 if (AOP_SIZE(result)==1) {
4042 emitcode ("inc", "a");
4044 emitcode ("add", "a,#1");
4045 emitcode ("xch", "a,b");
4046 emitcode ("cpl", "a"); // msb
4047 emitcode ("addc", "a,#0");
4048 emitcode ("xch", "a,b");
4051 emitcode ("", "%05d$:", lbl->key+100);
4052 aopPut (AOP (result), "a", 0);
4054 if (AOP_SIZE(result)==2) {
4055 aopPut (AOP (result), "b", 1);
4059 /*-----------------------------------------------------------------*/
4060 /* genMult - generates code for multiplication */
4061 /*-----------------------------------------------------------------*/
4063 genMult (iCode * ic)
4065 operand *left = IC_LEFT (ic);
4066 operand *right = IC_RIGHT (ic);
4067 operand *result = IC_RESULT (ic);
4069 D (emitcode (";", "genMult "););
4071 /* assign the amsops */
4074 /* special cases first */
4076 if (AOP_TYPE (left) == AOP_CRY &&
4077 AOP_TYPE (right) == AOP_CRY)
4079 genMultbits (left, right, result, ic);
4083 /* if both are of size == 1 */
4084 if (AOP_SIZE (left) == 1 &&
4085 AOP_SIZE (right) == 1)
4087 genMultOneByte (left, right, result, ic);
4091 /* should have been converted to function call */
4095 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4096 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4097 freeAsmop (result, NULL, ic, TRUE);
4100 /*-----------------------------------------------------------------*/
4101 /* genDivbits :- division of bits */
4102 /*-----------------------------------------------------------------*/
4104 genDivbits (operand * left,
4112 /* the result must be bit */
4113 LOAD_AB_FOR_DIV (left, right, l);
4114 emitcode ("div", "ab");
4115 emitcode ("rrc", "a");
4116 aopOp(result, ic, TRUE, FALSE);
4118 aopPut (AOP (result), "c", 0);
4121 /*-----------------------------------------------------------------*/
4122 /* genDivOneByte : 8 bit division */
4123 /*-----------------------------------------------------------------*/
4125 genDivOneByte (operand * left,
4130 sym_link *opetype = operandType (result);
4136 /* signed or unsigned */
4137 if (SPEC_USIGN (opetype))
4139 /* unsigned is easy */
4140 LOAD_AB_FOR_DIV (left, right, l);
4141 emitcode ("div", "ab");
4144 aopOp(result, ic, TRUE, FALSE);
4145 aopPut (AOP (result), "a", 0);
4148 size = AOP_SIZE (result) - 1;
4152 aopPut (AOP (result), zero, offset++);
4157 /* signed is a little bit more difficult */
4159 /* save the signs of the operands */
4160 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4162 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4163 emitcode ("push", "acc"); /* save it on the stack */
4165 /* now sign adjust for both left & right */
4166 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4168 lbl = newiTempLabel (NULL);
4169 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4170 emitcode ("cpl", "a");
4171 emitcode ("inc", "a");
4172 emitcode ("", "%05d$:", (lbl->key + 100));
4173 emitcode ("mov", "b,a");
4175 /* sign adjust left side */
4176 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4179 lbl = newiTempLabel (NULL);
4180 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4181 emitcode ("cpl", "a");
4182 emitcode ("inc", "a");
4183 emitcode ("", "%05d$:", (lbl->key + 100));
4185 /* now the division */
4186 emitcode ("nop", "; workaround for DS80C390 div bug.");
4187 emitcode ("div", "ab");
4188 /* we are interested in the lower order
4190 emitcode ("mov", "b,a");
4191 lbl = newiTempLabel (NULL);
4192 emitcode ("pop", "acc");
4193 /* if there was an over flow we don't
4194 adjust the sign of the result */
4195 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4196 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4198 emitcode ("clr", "a");
4199 emitcode ("subb", "a,b");
4200 emitcode ("mov", "b,a");
4201 emitcode ("", "%05d$:", (lbl->key + 100));
4203 /* now we are done */
4205 aopOp(result, ic, TRUE, FALSE);
4207 aopPut (AOP (result), "b", 0);
4209 size = AOP_SIZE (result) - 1;
4213 emitcode ("mov", "c,b.7");
4214 emitcode ("subb", "a,acc");
4218 aopPut (AOP (result), "a", offset++);
4224 /*-----------------------------------------------------------------*/
4225 /* genDiv - generates code for division */
4226 /*-----------------------------------------------------------------*/
4230 operand *left = IC_LEFT (ic);
4231 operand *right = IC_RIGHT (ic);
4232 operand *result = IC_RESULT (ic);
4234 D (emitcode (";", "genDiv "););
4236 /* assign the amsops */
4239 /* special cases first */
4241 if (AOP_TYPE (left) == AOP_CRY &&
4242 AOP_TYPE (right) == AOP_CRY)
4244 genDivbits (left, right, result, ic);
4248 /* if both are of size == 1 */
4249 if (AOP_SIZE (left) == 1 &&
4250 AOP_SIZE (right) == 1)
4252 genDivOneByte (left, right, result, ic);
4256 /* should have been converted to function call */
4259 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4260 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4261 freeAsmop (result, NULL, ic, TRUE);
4264 /*-----------------------------------------------------------------*/
4265 /* genModbits :- modulus of bits */
4266 /*-----------------------------------------------------------------*/
4268 genModbits (operand * left,
4276 /* the result must be bit */
4277 LOAD_AB_FOR_DIV (left, right, l);
4278 emitcode ("div", "ab");
4279 emitcode ("mov", "a,b");
4280 emitcode ("rrc", "a");
4281 aopOp(result, ic, TRUE, FALSE);
4282 aopPut (AOP (result), "c", 0);
4285 /*-----------------------------------------------------------------*/
4286 /* genModOneByte : 8 bit modulus */
4287 /*-----------------------------------------------------------------*/
4289 genModOneByte (operand * left,
4294 sym_link *opetype = operandType (result);
4298 /* signed or unsigned */
4299 if (SPEC_USIGN (opetype))
4301 /* unsigned is easy */
4302 LOAD_AB_FOR_DIV (left, right, l);
4303 emitcode ("div", "ab");
4304 aopOp(result, ic, TRUE, FALSE);
4305 aopPut (AOP (result), "b", 0);
4309 /* signed is a little bit more difficult */
4311 /* save the signs of the operands */
4312 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4315 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4316 emitcode ("push", "acc"); /* save it on the stack */
4318 /* now sign adjust for both left & right */
4319 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4322 lbl = newiTempLabel (NULL);
4323 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4324 emitcode ("cpl", "a");
4325 emitcode ("inc", "a");
4326 emitcode ("", "%05d$:", (lbl->key + 100));
4327 emitcode ("mov", "b,a");
4329 /* sign adjust left side */
4330 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4333 lbl = newiTempLabel (NULL);
4334 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4335 emitcode ("cpl", "a");
4336 emitcode ("inc", "a");
4337 emitcode ("", "%05d$:", (lbl->key + 100));
4339 /* now the multiplication */
4340 emitcode ("nop", "; workaround for DS80C390 div bug.");
4341 emitcode ("div", "ab");
4342 /* we are interested in the lower order
4344 lbl = newiTempLabel (NULL);
4345 emitcode ("pop", "acc");
4346 /* if there was an over flow we don't
4347 adjust the sign of the result */
4348 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4349 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4351 emitcode ("clr", "a");
4352 emitcode ("subb", "a,b");
4353 emitcode ("mov", "b,a");
4354 emitcode ("", "%05d$:", (lbl->key + 100));
4356 /* now we are done */
4357 aopOp(result, ic, TRUE, FALSE);
4358 aopPut (AOP (result), "b", 0);
4362 /*-----------------------------------------------------------------*/
4363 /* genMod - generates code for division */
4364 /*-----------------------------------------------------------------*/
4368 operand *left = IC_LEFT (ic);
4369 operand *right = IC_RIGHT (ic);
4370 operand *result = IC_RESULT (ic);
4372 D (emitcode (";", "genMod "); );
4374 /* assign the amsops */
4377 /* special cases first */
4379 if (AOP_TYPE (left) == AOP_CRY &&
4380 AOP_TYPE (right) == AOP_CRY)
4382 genModbits (left, right, result, ic);
4386 /* if both are of size == 1 */
4387 if (AOP_SIZE (left) == 1 &&
4388 AOP_SIZE (right) == 1)
4390 genModOneByte (left, right, result, ic);
4394 /* should have been converted to function call */
4398 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4399 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4400 freeAsmop (result, NULL, ic, TRUE);
4403 /*-----------------------------------------------------------------*/
4404 /* genIfxJump :- will create a jump depending on the ifx */
4405 /*-----------------------------------------------------------------*/
4407 genIfxJump (iCode * ic, char *jval)
4410 symbol *tlbl = newiTempLabel (NULL);
4413 D (emitcode (";", "genIfxJump ");
4416 /* if true label then we jump if condition
4420 jlbl = IC_TRUE (ic);
4421 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4422 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4426 /* false label is present */
4427 jlbl = IC_FALSE (ic);
4428 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4429 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4431 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4432 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4434 emitcode (inst, "%05d$", tlbl->key + 100);
4435 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4436 emitcode ("", "%05d$:", tlbl->key + 100);
4438 /* mark the icode as generated */
4442 /*-----------------------------------------------------------------*/
4443 /* genCmp :- greater or less than comparison */
4444 /*-----------------------------------------------------------------*/
4446 genCmp (operand * left, operand * right,
4447 iCode * ic, iCode * ifx, int sign)
4449 int size, offset = 0;
4450 unsigned long lit = 0L;
4453 D (emitcode (";", "genCmp");
4456 result = IC_RESULT (ic);
4458 /* if left & right are bit variables */
4459 if (AOP_TYPE (left) == AOP_CRY &&
4460 AOP_TYPE (right) == AOP_CRY)
4462 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4463 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4467 /* subtract right from left if at the
4468 end the carry flag is set then we know that
4469 left is greater than right */
4470 size = max (AOP_SIZE (left), AOP_SIZE (right));
4472 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4473 if ((size == 1) && !sign &&
4474 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4476 symbol *lbl = newiTempLabel (NULL);
4477 emitcode ("cjne", "%s,%s,%05d$",
4478 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4479 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4481 emitcode ("", "%05d$:", lbl->key + 100);
4485 if (AOP_TYPE (right) == AOP_LIT)
4487 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4488 /* optimize if(x < 0) or if(x >= 0) */
4497 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4499 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4500 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4502 aopOp (result, ic, FALSE, FALSE);
4504 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4506 freeAsmop (result, NULL, ic, TRUE);
4507 genIfxJump (ifx, "acc.7");
4512 emitcode ("rlc", "a");
4514 goto release_freedLR;
4522 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4523 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4524 emitcode (";", "genCmp #2");
4525 if (sign && (size == 0))
4527 emitcode (";", "genCmp #3");
4528 emitcode ("xrl", "a,#0x80");
4529 if (AOP_TYPE (right) == AOP_LIT)
4531 unsigned long lit = (unsigned long)
4532 floatFromVal (AOP (right)->aopu.aop_lit);
4533 emitcode (";", "genCmp #3.1");
4534 emitcode ("subb", "a,#0x%02x",
4535 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4539 emitcode (";", "genCmp #3.2");
4540 if (AOP_NEEDSACC (right))
4542 emitcode ("push", "acc");
4544 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4545 FALSE, FALSE, FALSE));
4546 emitcode ("xrl", "b,#0x80");
4547 if (AOP_NEEDSACC (right))
4549 emitcode ("pop", "acc");
4551 emitcode ("subb", "a,b");
4558 emitcode (";", "genCmp #4");
4559 if (AOP_NEEDSACC (right))
4562 emitcode (";", "genCmp #4.1");
4563 emitcode ("xch", "a, b");
4564 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4565 emitcode ("xch", "a, b");
4570 emitcode (";", "genCmp #4.2");
4571 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4574 emitcode ("subb", "a,%s", s);
4581 /* Don't need the left & right operands any more; do need the result. */
4582 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4583 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4585 aopOp (result, ic, FALSE, FALSE);
4589 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4595 /* if the result is used in the next
4596 ifx conditional branch then generate
4597 code a little differently */
4600 genIfxJump (ifx, "c");
4606 /* leave the result in acc */
4608 freeAsmop (result, NULL, ic, TRUE);
4611 /*-----------------------------------------------------------------*/
4612 /* genCmpGt :- greater than comparison */
4613 /*-----------------------------------------------------------------*/
4615 genCmpGt (iCode * ic, iCode * ifx)
4617 operand *left, *right;
4618 sym_link *letype, *retype;
4621 D (emitcode (";", "genCmpGt ");
4624 left = IC_LEFT (ic);
4625 right = IC_RIGHT (ic);
4627 letype = getSpec (operandType (left));
4628 retype = getSpec (operandType (right));
4629 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4631 /* assign the left & right amsops */
4634 genCmp (right, left, ic, ifx, sign);
4637 /*-----------------------------------------------------------------*/
4638 /* genCmpLt - less than comparisons */
4639 /*-----------------------------------------------------------------*/
4641 genCmpLt (iCode * ic, iCode * ifx)
4643 operand *left, *right;
4644 sym_link *letype, *retype;
4647 D (emitcode (";", "genCmpLt "););
4649 left = IC_LEFT (ic);
4650 right = IC_RIGHT (ic);
4652 letype = getSpec (operandType (left));
4653 retype = getSpec (operandType (right));
4654 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4656 /* assign the left & right amsops */
4659 genCmp (left, right, ic, ifx, sign);
4662 /*-----------------------------------------------------------------*/
4663 /* gencjneshort - compare and jump if not equal */
4664 /*-----------------------------------------------------------------*/
4666 gencjneshort (operand * left, operand * right, symbol * lbl)
4668 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4670 unsigned long lit = 0L;
4672 D (emitcode (";", "gencjneshort");
4675 /* if the left side is a literal or
4676 if the right is in a pointer register and left
4678 if ((AOP_TYPE (left) == AOP_LIT) ||
4679 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4686 if (AOP_TYPE (right) == AOP_LIT)
4687 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4689 if (opIsGptr (left) || opIsGptr (right))
4691 /* We are comparing a generic pointer to something.
4692 * Exclude the generic type byte from the comparison.
4695 D (emitcode (";", "cjneshort: generic ptr special case.");
4700 /* if the right side is a literal then anything goes */
4701 if (AOP_TYPE (right) == AOP_LIT &&
4702 AOP_TYPE (left) != AOP_DIR)
4706 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4708 emitcode ("cjne", "a,%s,%05d$",
4709 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4715 /* if the right side is in a register or in direct space or
4716 if the left is a pointer register & right is not */
4717 else if (AOP_TYPE (right) == AOP_REG ||
4718 AOP_TYPE (right) == AOP_DIR ||
4719 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4720 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4724 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4725 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4726 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4727 emitcode ("jnz", "%05d$", lbl->key + 100);
4729 emitcode ("cjne", "a,%s,%05d$",
4730 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4737 /* right is a pointer reg need both a & b */
4740 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4741 if (strcmp (l, "b"))
4742 emitcode ("mov", "b,%s", l);
4743 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4744 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4750 /*-----------------------------------------------------------------*/
4751 /* gencjne - compare and jump if not equal */
4752 /*-----------------------------------------------------------------*/
4754 gencjne (operand * left, operand * right, symbol * lbl)
4756 symbol *tlbl = newiTempLabel (NULL);
4758 D (emitcode (";", "gencjne");
4761 gencjneshort (left, right, lbl);
4763 emitcode ("mov", "a,%s", one);
4764 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4765 emitcode ("", "%05d$:", lbl->key + 100);
4766 emitcode ("clr", "a");
4767 emitcode ("", "%05d$:", tlbl->key + 100);
4770 /*-----------------------------------------------------------------*/
4771 /* genCmpEq - generates code for equal to */
4772 /*-----------------------------------------------------------------*/
4774 genCmpEq (iCode * ic, iCode * ifx)
4776 operand *left, *right, *result;
4778 D (emitcode (";", "genCmpEq ");
4782 AOP_SET_LOCALS (ic);
4784 /* if literal, literal on the right or
4785 if the right is in a pointer register and left
4787 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4788 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4790 operand *t = IC_RIGHT (ic);
4791 IC_RIGHT (ic) = IC_LEFT (ic);
4795 if (ifx && /* !AOP_SIZE(result) */
4796 OP_SYMBOL (result) &&
4797 OP_SYMBOL (result)->regType == REG_CND)
4800 /* if they are both bit variables */
4801 if (AOP_TYPE (left) == AOP_CRY &&
4802 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4804 if (AOP_TYPE (right) == AOP_LIT)
4806 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4809 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4810 emitcode ("cpl", "c");
4814 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4818 emitcode ("clr", "c");
4820 /* AOP_TYPE(right) == AOP_CRY */
4824 symbol *lbl = newiTempLabel (NULL);
4825 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4826 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4827 emitcode ("cpl", "c");
4828 emitcode ("", "%05d$:", (lbl->key + 100));
4830 /* if true label then we jump if condition
4832 tlbl = newiTempLabel (NULL);
4835 emitcode ("jnc", "%05d$", tlbl->key + 100);
4836 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4840 emitcode ("jc", "%05d$", tlbl->key + 100);
4841 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4843 emitcode ("", "%05d$:", tlbl->key + 100);
4847 tlbl = newiTempLabel (NULL);
4848 gencjneshort (left, right, tlbl);
4851 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4852 emitcode ("", "%05d$:", tlbl->key + 100);
4856 symbol *lbl = newiTempLabel (NULL);
4857 emitcode ("sjmp", "%05d$", lbl->key + 100);
4858 emitcode ("", "%05d$:", tlbl->key + 100);
4859 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4860 emitcode ("", "%05d$:", lbl->key + 100);
4863 /* mark the icode as generated */
4866 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4867 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4871 /* if they are both bit variables */
4872 if (AOP_TYPE (left) == AOP_CRY &&
4873 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4875 if (AOP_TYPE (right) == AOP_LIT)
4877 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4880 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4881 emitcode ("cpl", "c");
4885 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4889 emitcode ("clr", "c");
4891 /* AOP_TYPE(right) == AOP_CRY */
4895 symbol *lbl = newiTempLabel (NULL);
4896 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4897 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4898 emitcode ("cpl", "c");
4899 emitcode ("", "%05d$:", (lbl->key + 100));
4902 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4903 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4905 aopOp (result, ic, TRUE, FALSE);
4908 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4915 genIfxJump (ifx, "c");
4918 /* if the result is used in an arithmetic operation
4919 then put the result in place */
4924 gencjne (left, right, newiTempLabel (NULL));
4926 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4927 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4929 aopOp (result, ic, TRUE, FALSE);
4931 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4933 aopPut (AOP (result), "a", 0);
4938 genIfxJump (ifx, "a");
4941 /* if the result is used in an arithmetic operation
4942 then put the result in place */
4943 if (AOP_TYPE (result) != AOP_CRY)
4945 /* leave the result in acc */
4949 freeAsmop (result, NULL, ic, TRUE);
4952 /*-----------------------------------------------------------------*/
4953 /* ifxForOp - returns the icode containing the ifx for operand */
4954 /*-----------------------------------------------------------------*/
4956 ifxForOp (operand * op, iCode * ic)
4958 /* if true symbol then needs to be assigned */
4959 if (IS_TRUE_SYMOP (op))
4962 /* if this has register type condition and
4963 the next instruction is ifx with the same operand
4964 and live to of the operand is upto the ifx only then */
4966 ic->next->op == IFX &&
4967 IC_COND (ic->next)->key == op->key &&
4968 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4973 /*-----------------------------------------------------------------*/
4974 /* genAndOp - for && operation */
4975 /*-----------------------------------------------------------------*/
4977 genAndOp (iCode * ic)
4979 operand *left, *right, *result;
4982 D (emitcode (";", "genAndOp "););
4984 /* note here that && operations that are in an
4985 if statement are taken away by backPatchLabels
4986 only those used in arthmetic operations remain */
4988 AOP_SET_LOCALS (ic);
4990 /* if both are bit variables */
4991 if (AOP_TYPE (left) == AOP_CRY &&
4992 AOP_TYPE (right) == AOP_CRY)
4994 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4995 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4999 aopOp (result,ic,FALSE, FALSE);
5004 tlbl = newiTempLabel (NULL);
5006 emitcode ("jz", "%05d$", tlbl->key + 100);
5008 emitcode ("", "%05d$:", tlbl->key + 100);
5009 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5010 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5012 aopOp (result,ic,FALSE, FALSE);
5015 freeAsmop (result, NULL, ic, TRUE);
5019 /*-----------------------------------------------------------------*/
5020 /* genOrOp - for || operation */
5021 /*-----------------------------------------------------------------*/
5023 genOrOp (iCode * ic)
5025 operand *left, *right, *result;
5028 D (emitcode (";", "genOrOp "););
5030 /* note here that || operations that are in an
5031 if statement are taken away by backPatchLabels
5032 only those used in arthmetic operations remain */
5034 AOP_SET_LOCALS (ic);
5036 /* if both are bit variables */
5037 if (AOP_TYPE (left) == AOP_CRY &&
5038 AOP_TYPE (right) == AOP_CRY)
5040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5041 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5042 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5043 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5045 aopOp (result,ic,FALSE, FALSE);
5051 tlbl = newiTempLabel (NULL);
5053 emitcode ("jnz", "%05d$", tlbl->key + 100);
5055 emitcode ("", "%05d$:", tlbl->key + 100);
5056 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5057 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5059 aopOp (result,ic,FALSE, FALSE);
5064 freeAsmop (result, NULL, ic, TRUE);
5067 /*-----------------------------------------------------------------*/
5068 /* isLiteralBit - test if lit == 2^n */
5069 /*-----------------------------------------------------------------*/
5071 isLiteralBit (unsigned long lit)
5073 unsigned long pw[32] =
5074 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5075 0x100L, 0x200L, 0x400L, 0x800L,
5076 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5077 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5078 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5079 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5080 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5083 for (idx = 0; idx < 32; idx++)
5089 /*-----------------------------------------------------------------*/
5090 /* continueIfTrue - */
5091 /*-----------------------------------------------------------------*/
5093 continueIfTrue (iCode * ic)
5096 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5100 /*-----------------------------------------------------------------*/
5102 /*-----------------------------------------------------------------*/
5104 jumpIfTrue (iCode * ic)
5107 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5111 /*-----------------------------------------------------------------*/
5112 /* jmpTrueOrFalse - */
5113 /*-----------------------------------------------------------------*/
5115 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5117 // ugly but optimized by peephole
5120 symbol *nlbl = newiTempLabel (NULL);
5121 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5122 emitcode ("", "%05d$:", tlbl->key + 100);
5123 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5124 emitcode ("", "%05d$:", nlbl->key + 100);
5128 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5129 emitcode ("", "%05d$:", tlbl->key + 100);
5134 // Generate code to perform a bit-wise logic operation
5135 // on two operands in far space (assumed to already have been
5136 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5137 // in far space. This requires pushing the result on the stack
5138 // then popping it into the result.
5140 genFarFarLogicOp(iCode *ic, char *logicOp)
5142 int size, resultSize, compSize;
5146 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5147 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5148 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5150 _startLazyDPSEvaluation();
5151 for (size = compSize; (size--); offset++)
5153 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5154 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5155 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5157 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5158 emitcode ("push", "acc");
5160 _endLazyDPSEvaluation();
5162 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5163 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5164 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5166 resultSize = AOP_SIZE(IC_RESULT(ic));
5168 ADJUST_PUSHED_RESULT(compSize, resultSize);
5170 _startLazyDPSEvaluation();
5173 emitcode ("pop", "acc");
5174 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5176 _endLazyDPSEvaluation();
5177 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5181 /*-----------------------------------------------------------------*/
5182 /* genAnd - code for and */
5183 /*-----------------------------------------------------------------*/
5185 genAnd (iCode * ic, iCode * ifx)
5187 operand *left, *right, *result;
5188 int size, offset = 0;
5189 unsigned long lit = 0L;
5194 D (emitcode (";", "genAnd "););
5196 AOP_OP_3_NOFATAL (ic, pushResult);
5197 AOP_SET_LOCALS (ic);
5201 genFarFarLogicOp(ic, "anl");
5206 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5208 AOP_TYPE (left), AOP_TYPE (right));
5209 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5211 AOP_SIZE (left), AOP_SIZE (right));
5214 /* if left is a literal & right is not then exchange them */
5215 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5216 AOP_NEEDSACC (left))
5218 operand *tmp = right;
5223 /* if result = right then exchange them */
5224 if (sameRegs (AOP (result), AOP (right)))
5226 operand *tmp = right;
5231 /* if right is bit then exchange them */
5232 if (AOP_TYPE (right) == AOP_CRY &&
5233 AOP_TYPE (left) != AOP_CRY)
5235 operand *tmp = right;
5239 if (AOP_TYPE (right) == AOP_LIT)
5240 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5242 size = AOP_SIZE (result);
5245 // result = bit & yy;
5246 if (AOP_TYPE (left) == AOP_CRY)
5248 // c = bit & literal;
5249 if (AOP_TYPE (right) == AOP_LIT)
5253 if (size && sameRegs (AOP (result), AOP (left)))
5256 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5261 if (size && (AOP_TYPE (result) == AOP_CRY))
5263 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5266 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5271 emitcode ("clr", "c");
5276 if (AOP_TYPE (right) == AOP_CRY)
5279 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5280 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5285 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5287 emitcode ("rrc", "a");
5288 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5296 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5297 genIfxJump (ifx, "c");
5301 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5302 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5303 if ((AOP_TYPE (right) == AOP_LIT) &&
5304 (AOP_TYPE (result) == AOP_CRY) &&
5305 (AOP_TYPE (left) != AOP_CRY))
5307 int posbit = isLiteralBit (lit);
5312 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5315 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5321 sprintf (buffer, "acc.%d", posbit & 0x07);
5322 genIfxJump (ifx, buffer);
5329 symbol *tlbl = newiTempLabel (NULL);
5330 int sizel = AOP_SIZE (left);
5332 emitcode ("setb", "c");
5335 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5337 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5339 if ((posbit = isLiteralBit (bytelit)) != 0)
5340 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5343 if (bytelit != 0x0FFL)
5344 emitcode ("anl", "a,%s",
5345 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5346 emitcode ("jnz", "%05d$", tlbl->key + 100);
5351 // bit = left & literal
5354 emitcode ("clr", "c");
5355 emitcode ("", "%05d$:", tlbl->key + 100);
5357 // if(left & literal)
5361 jmpTrueOrFalse (ifx, tlbl);
5369 /* if left is same as result */
5370 if (sameRegs (AOP (result), AOP (left)))
5372 for (; size--; offset++)
5374 if (AOP_TYPE (right) == AOP_LIT)
5376 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5378 else if (bytelit == 0)
5379 aopPut (AOP (result), zero, offset);
5380 else if (IS_AOP_PREG (result))
5382 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5383 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5384 aopPut (AOP (result), "a", offset);
5387 emitcode ("anl", "%s,%s",
5388 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5389 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5393 if (AOP_TYPE (left) == AOP_ACC)
5394 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5397 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5398 if (IS_AOP_PREG (result))
5400 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5401 aopPut (AOP (result), "a", offset);
5405 emitcode ("anl", "%s,a",
5406 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5413 // left & result in different registers
5414 if (AOP_TYPE (result) == AOP_CRY)
5417 // if(size), result in bit
5418 // if(!size && ifx), conditional oper: if(left & right)
5419 symbol *tlbl = newiTempLabel (NULL);
5420 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5422 emitcode ("setb", "c");
5425 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5426 emitcode ("anl", "a,%s",
5427 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5429 if (AOP_TYPE(left)==AOP_ACC) {
5430 emitcode("mov", "b,a");
5431 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5432 emitcode("anl", "a,b");
5434 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5435 emitcode ("anl", "a,%s",
5436 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5439 emitcode ("jnz", "%05d$", tlbl->key + 100);
5445 emitcode ("", "%05d$:", tlbl->key + 100);
5449 jmpTrueOrFalse (ifx, tlbl);
5453 for (; (size--); offset++)
5456 // result = left & right
5457 if (AOP_TYPE (right) == AOP_LIT)
5459 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5461 aopPut (AOP (result),
5462 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5466 else if (bytelit == 0)
5468 aopPut (AOP (result), zero, offset);
5471 D (emitcode (";", "better literal AND.");
5473 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5474 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5475 FALSE, FALSE, FALSE));
5480 // faster than result <- left, anl result,right
5481 // and better if result is SFR
5482 if (AOP_TYPE (left) == AOP_ACC)
5484 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5485 FALSE, FALSE, FALSE));
5489 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5490 emitcode ("anl", "a,%s",
5491 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5494 aopPut (AOP (result), "a", offset);
5500 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5501 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502 freeAsmop (result, NULL, ic, TRUE);
5506 /*-----------------------------------------------------------------*/
5507 /* genOr - code for or */
5508 /*-----------------------------------------------------------------*/
5510 genOr (iCode * ic, iCode * ifx)
5512 operand *left, *right, *result;
5513 int size, offset = 0;
5514 unsigned long lit = 0L;
5517 D (emitcode (";", "genOr "););
5519 AOP_OP_3_NOFATAL (ic, pushResult);
5520 AOP_SET_LOCALS (ic);
5524 genFarFarLogicOp(ic, "orl");
5530 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5532 AOP_TYPE (left), AOP_TYPE (right));
5533 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5535 AOP_SIZE (left), AOP_SIZE (right));
5538 /* if left is a literal & right is not then exchange them */
5539 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5540 AOP_NEEDSACC (left))
5542 operand *tmp = right;
5547 /* if result = right then exchange them */
5548 if (sameRegs (AOP (result), AOP (right)))
5550 operand *tmp = right;
5555 /* if right is bit then exchange them */
5556 if (AOP_TYPE (right) == AOP_CRY &&
5557 AOP_TYPE (left) != AOP_CRY)
5559 operand *tmp = right;
5563 if (AOP_TYPE (right) == AOP_LIT)
5564 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5566 size = AOP_SIZE (result);
5570 if (AOP_TYPE (left) == AOP_CRY)
5572 if (AOP_TYPE (right) == AOP_LIT)
5574 // c = bit & literal;
5577 // lit != 0 => result = 1
5578 if (AOP_TYPE (result) == AOP_CRY)
5581 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5583 continueIfTrue (ifx);
5586 emitcode ("setb", "c");
5590 // lit == 0 => result = left
5591 if (size && sameRegs (AOP (result), AOP (left)))
5593 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5598 if (AOP_TYPE (right) == AOP_CRY)
5601 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5602 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5607 symbol *tlbl = newiTempLabel (NULL);
5608 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5609 emitcode ("setb", "c");
5610 emitcode ("jb", "%s,%05d$",
5611 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5613 emitcode ("jnz", "%05d$", tlbl->key + 100);
5614 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5616 jmpTrueOrFalse (ifx, tlbl);
5622 emitcode ("", "%05d$:", tlbl->key + 100);
5631 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5632 genIfxJump (ifx, "c");
5636 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5637 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5638 if ((AOP_TYPE (right) == AOP_LIT) &&
5639 (AOP_TYPE (result) == AOP_CRY) &&
5640 (AOP_TYPE (left) != AOP_CRY))
5646 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5648 continueIfTrue (ifx);
5653 // lit = 0, result = boolean(left)
5655 emitcode ("setb", "c");
5659 symbol *tlbl = newiTempLabel (NULL);
5660 emitcode ("jnz", "%05d$", tlbl->key + 100);
5662 emitcode ("", "%05d$:", tlbl->key + 100);
5666 genIfxJump (ifx, "a");
5674 /* if left is same as result */
5675 if (sameRegs (AOP (result), AOP (left)))
5677 for (; size--; offset++)
5679 if (AOP_TYPE (right) == AOP_LIT)
5681 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5687 if (IS_AOP_PREG (left))
5689 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5690 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5691 aopPut (AOP (result), "a", offset);
5695 emitcode ("orl", "%s,%s",
5696 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5697 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5703 if (AOP_TYPE (left) == AOP_ACC)
5705 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5709 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5710 if (IS_AOP_PREG (left))
5712 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5713 aopPut (AOP (result), "a", offset);
5717 emitcode ("orl", "%s,a",
5718 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5726 // left & result in different registers
5727 if (AOP_TYPE (result) == AOP_CRY)
5730 // if(size), result in bit
5731 // if(!size && ifx), conditional oper: if(left | right)
5732 symbol *tlbl = newiTempLabel (NULL);
5733 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5735 emitcode ("setb", "c");
5738 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5739 emitcode ("orl", "a,%s",
5740 aopGet (AOP (right), offset, 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));
5746 emitcode ("jnz", "%05d$", tlbl->key + 100);
5752 emitcode ("", "%05d$:", tlbl->key + 100);
5756 jmpTrueOrFalse (ifx, tlbl);
5760 for (; (size--); offset++)
5763 // result = left & right
5764 if (AOP_TYPE (right) == AOP_LIT)
5766 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5768 aopPut (AOP (result),
5769 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5773 D (emitcode (";", "better literal OR.");
5775 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5776 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5777 FALSE, FALSE, FALSE));
5782 // faster than result <- left, anl result,right
5783 // and better if result is SFR
5784 if (AOP_TYPE (left) == AOP_ACC)
5786 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5787 FALSE, FALSE, FALSE));
5791 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5792 emitcode ("orl", "a,%s",
5793 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5796 aopPut (AOP (result), "a", offset);
5802 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5803 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5804 freeAsmop (result, NULL, ic, TRUE);
5807 /*-----------------------------------------------------------------*/
5808 /* genXor - code for xclusive or */
5809 /*-----------------------------------------------------------------*/
5811 genXor (iCode * ic, iCode * ifx)
5813 operand *left, *right, *result;
5814 int size, offset = 0;
5815 unsigned long lit = 0L;
5818 D (emitcode (";", "genXor "););
5820 AOP_OP_3_NOFATAL (ic, pushResult);
5821 AOP_SET_LOCALS (ic);
5825 genFarFarLogicOp(ic, "xrl");
5830 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5832 AOP_TYPE (left), AOP_TYPE (right));
5833 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5835 AOP_SIZE (left), AOP_SIZE (right));
5838 /* if left is a literal & right is not ||
5839 if left needs acc & right does not */
5840 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5841 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5843 operand *tmp = right;
5848 /* if result = right then exchange them */
5849 if (sameRegs (AOP (result), AOP (right)))
5851 operand *tmp = right;
5856 /* if right is bit then exchange them */
5857 if (AOP_TYPE (right) == AOP_CRY &&
5858 AOP_TYPE (left) != AOP_CRY)
5860 operand *tmp = right;
5864 if (AOP_TYPE (right) == AOP_LIT)
5865 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5867 size = AOP_SIZE (result);
5871 if (AOP_TYPE (left) == AOP_CRY)
5873 if (AOP_TYPE (right) == AOP_LIT)
5875 // c = bit & literal;
5878 // lit>>1 != 0 => result = 1
5879 if (AOP_TYPE (result) == AOP_CRY)
5882 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5884 continueIfTrue (ifx);
5887 emitcode ("setb", "c");
5894 // lit == 0, result = left
5895 if (size && sameRegs (AOP (result), AOP (left)))
5897 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5901 // lit == 1, result = not(left)
5902 if (size && sameRegs (AOP (result), AOP (left)))
5904 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5909 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5910 emitcode ("cpl", "c");
5919 symbol *tlbl = newiTempLabel (NULL);
5920 if (AOP_TYPE (right) == AOP_CRY)
5923 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5927 int sizer = AOP_SIZE (right);
5929 // if val>>1 != 0, result = 1
5930 emitcode ("setb", "c");
5933 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5935 // test the msb of the lsb
5936 emitcode ("anl", "a,#0xfe");
5937 emitcode ("jnz", "%05d$", tlbl->key + 100);
5941 emitcode ("rrc", "a");
5943 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5944 emitcode ("cpl", "c");
5945 emitcode ("", "%05d$:", (tlbl->key + 100));
5952 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5953 genIfxJump (ifx, "c");
5957 if (sameRegs (AOP (result), AOP (left)))
5959 /* if left is same as result */
5960 for (; size--; offset++)
5962 if (AOP_TYPE (right) == AOP_LIT)
5964 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5966 else if (IS_AOP_PREG (left))
5968 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5969 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5970 aopPut (AOP (result), "a", offset);
5973 emitcode ("xrl", "%s,%s",
5974 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5975 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5979 if (AOP_TYPE (left) == AOP_ACC)
5980 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5983 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5984 if (IS_AOP_PREG (left))
5986 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5987 aopPut (AOP (result), "a", offset);
5990 emitcode ("xrl", "%s,a",
5991 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5998 // left & result in different registers
5999 if (AOP_TYPE (result) == AOP_CRY)
6002 // if(size), result in bit
6003 // if(!size && ifx), conditional oper: if(left ^ right)
6004 symbol *tlbl = newiTempLabel (NULL);
6005 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6007 emitcode ("setb", "c");
6010 if ((AOP_TYPE (right) == AOP_LIT) &&
6011 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6013 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6017 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6018 emitcode ("xrl", "a,%s",
6019 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6021 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6022 emitcode ("xrl", "a,%s",
6023 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6026 emitcode ("jnz", "%05d$", tlbl->key + 100);
6032 emitcode ("", "%05d$:", tlbl->key + 100);
6036 jmpTrueOrFalse (ifx, tlbl);
6039 for (; (size--); offset++)
6042 // result = left & right
6043 if (AOP_TYPE (right) == AOP_LIT)
6045 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6047 aopPut (AOP (result),
6048 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6052 D (emitcode (";", "better literal XOR.");
6054 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6055 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6056 FALSE, FALSE, FALSE));
6060 // faster than result <- left, anl result,right
6061 // and better if result is SFR
6062 if (AOP_TYPE (left) == AOP_ACC)
6064 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6065 FALSE, FALSE, FALSE));
6069 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6070 emitcode ("xrl", "a,%s",
6071 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6074 aopPut (AOP (result), "a", offset);
6079 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6080 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6081 freeAsmop (result, NULL, ic, TRUE);
6084 /*-----------------------------------------------------------------*/
6085 /* genInline - write the inline code out */
6086 /*-----------------------------------------------------------------*/
6088 genInline (iCode * ic)
6090 char *buffer, *bp, *bp1;
6092 D (emitcode (";", "genInline ");
6095 _G.inLine += (!options.asmpeep);
6097 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6098 strcpy (buffer, IC_INLINE (ic));
6100 /* emit each line as a code */
6125 /* emitcode("",buffer); */
6126 _G.inLine -= (!options.asmpeep);
6129 /*-----------------------------------------------------------------*/
6130 /* genRRC - rotate right with carry */
6131 /*-----------------------------------------------------------------*/
6135 operand *left, *result;
6136 int size, offset = 0;
6139 D (emitcode (";", "genRRC ");
6142 /* rotate right with carry */
6143 left = IC_LEFT (ic);
6144 result = IC_RESULT (ic);
6145 aopOp (left, ic, FALSE, FALSE);
6146 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6148 /* move it to the result */
6149 size = AOP_SIZE (result);
6153 _startLazyDPSEvaluation ();
6156 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6158 emitcode ("rrc", "a");
6159 if (AOP_SIZE (result) > 1)
6160 aopPut (AOP (result), "a", offset--);
6162 _endLazyDPSEvaluation ();
6164 /* now we need to put the carry into the
6165 highest order byte of the result */
6166 if (AOP_SIZE (result) > 1)
6168 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6171 emitcode ("mov", "acc.7,c");
6172 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6173 freeAsmop (left, NULL, ic, TRUE);
6174 freeAsmop (result, NULL, ic, TRUE);
6177 /*-----------------------------------------------------------------*/
6178 /* genRLC - generate code for rotate left with carry */
6179 /*-----------------------------------------------------------------*/
6183 operand *left, *result;
6184 int size, offset = 0;
6187 D (emitcode (";", "genRLC ");
6190 /* rotate right with carry */
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 /* move it to the result */
6197 size = AOP_SIZE (result);
6201 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6203 emitcode ("add", "a,acc");
6204 if (AOP_SIZE (result) > 1)
6206 aopPut (AOP (result), "a", offset++);
6209 _startLazyDPSEvaluation ();
6212 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6214 emitcode ("rlc", "a");
6215 if (AOP_SIZE (result) > 1)
6216 aopPut (AOP (result), "a", offset++);
6218 _endLazyDPSEvaluation ();
6220 /* now we need to put the carry into the
6221 highest order byte of the result */
6222 if (AOP_SIZE (result) > 1)
6224 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6227 emitcode ("mov", "acc.0,c");
6228 aopPut (AOP (result), "a", 0);
6229 freeAsmop (left, NULL, ic, TRUE);
6230 freeAsmop (result, NULL, ic, TRUE);
6233 /*-----------------------------------------------------------------*/
6234 /* genGetHbit - generates code get highest order bit */
6235 /*-----------------------------------------------------------------*/
6237 genGetHbit (iCode * ic)
6239 operand *left, *result;
6240 left = IC_LEFT (ic);
6241 result = IC_RESULT (ic);
6242 aopOp (left, ic, FALSE, FALSE);
6243 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6245 D (emitcode (";", "genGetHbit ");
6248 /* get the highest order byte into a */
6249 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6250 if (AOP_TYPE (result) == AOP_CRY)
6252 emitcode ("rlc", "a");
6257 emitcode ("rl", "a");
6258 emitcode ("anl", "a,#0x01");
6263 freeAsmop (left, NULL, ic, TRUE);
6264 freeAsmop (result, NULL, ic, TRUE);
6267 /*-----------------------------------------------------------------*/
6268 /* AccRol - rotate left accumulator by known count */
6269 /*-----------------------------------------------------------------*/
6271 AccRol (int shCount)
6273 shCount &= 0x0007; // shCount : 0..7
6280 emitcode ("rl", "a");
6283 emitcode ("rl", "a");
6284 emitcode ("rl", "a");
6287 emitcode ("swap", "a");
6288 emitcode ("rr", "a");
6291 emitcode ("swap", "a");
6294 emitcode ("swap", "a");
6295 emitcode ("rl", "a");
6298 emitcode ("rr", "a");
6299 emitcode ("rr", "a");
6302 emitcode ("rr", "a");
6307 /*-----------------------------------------------------------------*/
6308 /* AccLsh - left shift accumulator by known count */
6309 /*-----------------------------------------------------------------*/
6311 AccLsh (int shCount)
6316 emitcode ("add", "a,acc");
6317 else if (shCount == 2)
6319 emitcode ("add", "a,acc");
6320 emitcode ("add", "a,acc");
6324 /* rotate left accumulator */
6326 /* and kill the lower order bits */
6327 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6332 /*-----------------------------------------------------------------*/
6333 /* AccRsh - right shift accumulator by known count */
6334 /*-----------------------------------------------------------------*/
6336 AccRsh (int shCount)
6343 emitcode ("rrc", "a");
6347 /* rotate right accumulator */
6348 AccRol (8 - shCount);
6349 /* and kill the higher order bits */
6350 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6355 #ifdef BETTER_LITERAL_SHIFT
6356 /*-----------------------------------------------------------------*/
6357 /* AccSRsh - signed right shift accumulator by known count */
6358 /*-----------------------------------------------------------------*/
6360 AccSRsh (int shCount)
6367 emitcode ("mov", "c,acc.7");
6368 emitcode ("rrc", "a");
6370 else if (shCount == 2)
6372 emitcode ("mov", "c,acc.7");
6373 emitcode ("rrc", "a");
6374 emitcode ("mov", "c,acc.7");
6375 emitcode ("rrc", "a");
6379 tlbl = newiTempLabel (NULL);
6380 /* rotate right accumulator */
6381 AccRol (8 - shCount);
6382 /* and kill the higher order bits */
6383 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6384 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6385 emitcode ("orl", "a,#0x%02x",
6386 (unsigned char) ~SRMask[shCount]);
6387 emitcode ("", "%05d$:", tlbl->key + 100);
6393 #ifdef BETTER_LITERAL_SHIFT
6394 /*-----------------------------------------------------------------*/
6395 /* shiftR1Left2Result - shift right one byte from left to result */
6396 /*-----------------------------------------------------------------*/
6398 shiftR1Left2Result (operand * left, int offl,
6399 operand * result, int offr,
6400 int shCount, int sign)
6402 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6403 /* shift right accumulator */
6408 aopPut (AOP (result), "a", offr);
6412 #ifdef BETTER_LITERAL_SHIFT
6413 /*-----------------------------------------------------------------*/
6414 /* shiftL1Left2Result - shift left one byte from left to result */
6415 /*-----------------------------------------------------------------*/
6417 shiftL1Left2Result (operand * left, int offl,
6418 operand * result, int offr, int shCount)
6420 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6421 /* shift left accumulator */
6423 aopPut (AOP (result), "a", offr);
6427 #ifdef BETTER_LITERAL_SHIFT
6428 /*-----------------------------------------------------------------*/
6429 /* movLeft2Result - move byte from left to result */
6430 /*-----------------------------------------------------------------*/
6432 movLeft2Result (operand * left, int offl,
6433 operand * result, int offr, int sign)
6436 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6438 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6440 if (*l == '@' && (IS_AOP_PREG (result)))
6442 emitcode ("mov", "a,%s", l);
6443 aopPut (AOP (result), "a", offr);
6449 aopPut (AOP (result), l, offr);
6453 /* MSB sign in acc.7 ! */
6454 if (getDataSize (left) == offl + 1)
6456 emitcode ("mov", "a,%s", l);
6457 aopPut (AOP (result), "a", offr);
6465 #ifdef BETTER_LITERAL_SHIFT
6466 /*-----------------------------------------------------------------*/
6467 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6468 /*-----------------------------------------------------------------*/
6472 emitcode ("rrc", "a");
6473 emitcode ("xch", "a,%s", x);
6474 emitcode ("rrc", "a");
6475 emitcode ("xch", "a,%s", x);
6479 #ifdef BETTER_LITERAL_SHIFT
6481 /*-----------------------------------------------------------------*/
6482 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6483 /*-----------------------------------------------------------------*/
6487 emitcode ("xch", "a,%s", x);
6488 emitcode ("rlc", "a");
6489 emitcode ("xch", "a,%s", x);
6490 emitcode ("rlc", "a");
6494 #ifdef BETTER_LITERAL_SHIFT
6495 /*-----------------------------------------------------------------*/
6496 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6497 /*-----------------------------------------------------------------*/
6501 emitcode ("xch", "a,%s", x);
6502 emitcode ("add", "a,acc");
6503 emitcode ("xch", "a,%s", x);
6504 emitcode ("rlc", "a");
6508 #ifdef BETTER_LITERAL_SHIFT
6509 /*-----------------------------------------------------------------*/
6510 /* AccAXLsh - left shift a:x by known count (0..7) */
6511 /*-----------------------------------------------------------------*/
6513 AccAXLsh (char *x, int shCount)
6528 case 5: // AAAAABBB:CCCCCDDD
6530 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6532 emitcode ("anl", "a,#0x%02x",
6533 SLMask[shCount]); // BBB00000:CCCCCDDD
6535 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6537 AccRol (shCount); // DDDCCCCC:BBB00000
6539 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6541 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6543 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6545 emitcode ("anl", "a,#0x%02x",
6546 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6548 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6550 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6553 case 6: // AAAAAABB:CCCCCCDD
6554 emitcode ("anl", "a,#0x%02x",
6555 SRMask[shCount]); // 000000BB:CCCCCCDD
6556 emitcode ("mov", "c,acc.0"); // c = B
6557 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6559 AccAXRrl1 (x); // BCCCCCCD:D000000B
6560 AccAXRrl1 (x); // BBCCCCCC:DD000000
6562 emitcode("rrc","a");
6563 emitcode("xch","a,%s", x);
6564 emitcode("rrc","a");
6565 emitcode("mov","c,acc.0"); //<< get correct bit
6566 emitcode("xch","a,%s", x);
6568 emitcode("rrc","a");
6569 emitcode("xch","a,%s", x);
6570 emitcode("rrc","a");
6571 emitcode("xch","a,%s", x);
6574 case 7: // a:x <<= 7
6576 emitcode ("anl", "a,#0x%02x",
6577 SRMask[shCount]); // 0000000B:CCCCCCCD
6579 emitcode ("mov", "c,acc.0"); // c = B
6581 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6583 AccAXRrl1 (x); // BCCCCCCC:D0000000
6592 #ifdef BETTER_LITERAL_SHIFT
6594 /*-----------------------------------------------------------------*/
6595 /* AccAXRsh - right shift a:x known count (0..7) */
6596 /*-----------------------------------------------------------------*/
6598 AccAXRsh (char *x, int shCount)
6606 AccAXRrl1 (x); // 0->a:x
6611 AccAXRrl1 (x); // 0->a:x
6614 AccAXRrl1 (x); // 0->a:x
6619 case 5: // AAAAABBB:CCCCCDDD = a:x
6621 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6623 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6625 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6627 emitcode ("anl", "a,#0x%02x",
6628 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6630 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6632 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6634 emitcode ("anl", "a,#0x%02x",
6635 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6637 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6639 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6641 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6644 case 6: // AABBBBBB:CCDDDDDD
6646 emitcode ("mov", "c,acc.7");
6647 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6649 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6651 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6653 emitcode ("anl", "a,#0x%02x",
6654 SRMask[shCount]); // 000000AA:BBBBBBCC
6657 case 7: // ABBBBBBB:CDDDDDDD
6659 emitcode ("mov", "c,acc.7"); // c = A
6661 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6663 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6665 emitcode ("anl", "a,#0x%02x",
6666 SRMask[shCount]); // 0000000A:BBBBBBBC
6675 #ifdef BETTER_LITERAL_SHIFT
6676 /*-----------------------------------------------------------------*/
6677 /* AccAXRshS - right shift signed a:x known count (0..7) */
6678 /*-----------------------------------------------------------------*/
6680 AccAXRshS (char *x, int shCount)
6688 emitcode ("mov", "c,acc.7");
6689 AccAXRrl1 (x); // s->a:x
6693 emitcode ("mov", "c,acc.7");
6694 AccAXRrl1 (x); // s->a:x
6696 emitcode ("mov", "c,acc.7");
6697 AccAXRrl1 (x); // s->a:x
6702 case 5: // AAAAABBB:CCCCCDDD = a:x
6704 tlbl = newiTempLabel (NULL);
6705 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6707 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6709 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6711 emitcode ("anl", "a,#0x%02x",
6712 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6714 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6716 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6718 emitcode ("anl", "a,#0x%02x",
6719 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6721 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6723 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6725 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6727 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6728 emitcode ("orl", "a,#0x%02x",
6729 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6731 emitcode ("", "%05d$:", tlbl->key + 100);
6732 break; // SSSSAAAA:BBBCCCCC
6734 case 6: // AABBBBBB:CCDDDDDD
6736 tlbl = newiTempLabel (NULL);
6737 emitcode ("mov", "c,acc.7");
6738 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6740 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6742 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6744 emitcode ("anl", "a,#0x%02x",
6745 SRMask[shCount]); // 000000AA:BBBBBBCC
6747 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6748 emitcode ("orl", "a,#0x%02x",
6749 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6751 emitcode ("", "%05d$:", tlbl->key + 100);
6753 case 7: // ABBBBBBB:CDDDDDDD
6755 tlbl = newiTempLabel (NULL);
6756 emitcode ("mov", "c,acc.7"); // c = A
6758 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6760 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6762 emitcode ("anl", "a,#0x%02x",
6763 SRMask[shCount]); // 0000000A:BBBBBBBC
6765 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6766 emitcode ("orl", "a,#0x%02x",
6767 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6769 emitcode ("", "%05d$:", tlbl->key + 100);
6777 #ifdef BETTER_LITERAL_SHIFT
6779 _loadLeftIntoAx(char **lsb,
6785 // Get the initial value from left into a pair of registers.
6786 // MSB must be in A, LSB can be any register.
6788 // If the result is held in registers, it is an optimization
6789 // if the LSB can be held in the register which will hold the,
6790 // result LSB since this saves us from having to copy it into
6791 // the result following AccAXLsh.
6793 // If the result is addressed indirectly, this is not a gain.
6794 if (AOP_NEEDSACC(result))
6798 _startLazyDPSEvaluation();
6799 if (AOP_TYPE(left) == AOP_DPTR2)
6802 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6803 // get LSB in DP2_RESULT_REG.
6804 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6805 assert(!strcmp(leftByte, DP2_RESULT_REG));
6809 // get LSB into DP2_RESULT_REG
6810 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6811 if (strcmp(leftByte, DP2_RESULT_REG))
6814 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6817 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6818 assert(strcmp(leftByte, DP2_RESULT_REG));
6821 _endLazyDPSEvaluation();
6822 *lsb = DP2_RESULT_REG;
6826 if (sameRegs (AOP (result), AOP (left)) &&
6827 ((offl + MSB16) == offr))
6829 /* don't crash result[offr] */
6830 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6831 emitcode ("xch", "a,%s",
6832 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6836 movLeft2Result (left, offl, result, offr, 0);
6837 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6839 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6840 assert(strcmp(*lsb,"a"));
6845 _storeAxResults(char *lsb,
6849 _startLazyDPSEvaluation();
6850 if (AOP_NEEDSACC(result))
6852 /* We have to explicitly update the result LSB.
6854 emitcode("xch","a,%s", lsb);
6855 aopPut(AOP(result), "a", offr);
6856 emitcode("mov","a,%s", lsb);
6858 if (getDataSize (result) > 1)
6860 aopPut (AOP (result), "a", offr + MSB16);
6862 _endLazyDPSEvaluation();
6865 /*-----------------------------------------------------------------*/
6866 /* shiftL2Left2Result - shift left two bytes from left to result */
6867 /*-----------------------------------------------------------------*/
6869 shiftL2Left2Result (operand * left, int offl,
6870 operand * result, int offr, int shCount)
6874 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6876 AccAXLsh (lsb, shCount);
6878 _storeAxResults(lsb, result, offr);
6882 #ifdef BETTER_LITERAL_SHIFT
6883 /*-----------------------------------------------------------------*/
6884 /* shiftR2Left2Result - shift right two bytes from left to result */
6885 /*-----------------------------------------------------------------*/
6887 shiftR2Left2Result (operand * left, int offl,
6888 operand * result, int offr,
6889 int shCount, int sign)
6893 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6895 /* a:x >> shCount (x = lsb(result)) */
6898 AccAXRshS(lsb, shCount);
6902 AccAXRsh(lsb, shCount);
6905 _storeAxResults(lsb, result, offr);
6911 /*-----------------------------------------------------------------*/
6912 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6913 /*-----------------------------------------------------------------*/
6915 shiftLLeftOrResult (operand * left, int offl,
6916 operand * result, int offr, int shCount)
6918 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6919 /* shift left accumulator */
6921 /* or with result */
6922 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6923 /* back to result */
6924 aopPut (AOP (result), "a", offr);
6930 /*-----------------------------------------------------------------*/
6931 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6932 /*-----------------------------------------------------------------*/
6934 shiftRLeftOrResult (operand * left, int offl,
6935 operand * result, int offr, int shCount)
6937 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6938 /* shift right accumulator */
6940 /* or with result */
6941 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6942 /* back to result */
6943 aopPut (AOP (result), "a", offr);
6947 #ifdef BETTER_LITERAL_SHIFT
6948 /*-----------------------------------------------------------------*/
6949 /* genlshOne - left shift a one byte quantity by known count */
6950 /*-----------------------------------------------------------------*/
6952 genlshOne (operand * result, operand * left, int shCount)
6954 D (emitcode (";", "genlshOne "););
6955 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6959 #ifdef BETTER_LITERAL_SHIFT
6960 /*-----------------------------------------------------------------*/
6961 /* genlshTwo - left shift two bytes by known amount != 0 */
6962 /*-----------------------------------------------------------------*/
6964 genlshTwo (operand * result, operand * left, int shCount)
6968 D (emitcode (";", "genlshTwo "););
6970 size = getDataSize (result);
6972 /* if shCount >= 8 */
6977 _startLazyDPSEvaluation();
6983 _endLazyDPSEvaluation();
6984 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6985 aopPut (AOP (result), zero, LSB);
6989 movLeft2Result (left, LSB, result, MSB16, 0);
6990 aopPut (AOP (result), zero, LSB);
6991 _endLazyDPSEvaluation();
6996 aopPut (AOP (result), zero, LSB);
6997 _endLazyDPSEvaluation();
7001 /* 1 <= shCount <= 7 */
7006 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7010 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7018 /*-----------------------------------------------------------------*/
7019 /* shiftLLong - shift left one long from left to result */
7020 /* offl = LSB or MSB16 */
7021 /*-----------------------------------------------------------------*/
7023 shiftLLong (operand * left, operand * result, int offr)
7026 int size = AOP_SIZE (result);
7028 if (size >= LSB + offr)
7030 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7032 emitcode ("add", "a,acc");
7033 if (sameRegs (AOP (left), AOP (result)) &&
7034 size >= MSB16 + offr && offr != LSB)
7035 emitcode ("xch", "a,%s",
7036 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7038 aopPut (AOP (result), "a", LSB + offr);
7041 if (size >= MSB16 + offr)
7043 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7045 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7048 emitcode ("rlc", "a");
7049 if (sameRegs (AOP (left), AOP (result)) &&
7050 size >= MSB24 + offr && offr != LSB)
7051 emitcode ("xch", "a,%s",
7052 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7054 aopPut (AOP (result), "a", MSB16 + offr);
7057 if (size >= MSB24 + offr)
7059 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7061 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7064 emitcode ("rlc", "a");
7065 if (sameRegs (AOP (left), AOP (result)) &&
7066 size >= MSB32 + offr && offr != LSB)
7067 emitcode ("xch", "a,%s",
7068 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7070 aopPut (AOP (result), "a", MSB24 + offr);
7073 if (size > MSB32 + offr)
7075 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7077 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7080 emitcode ("rlc", "a");
7081 aopPut (AOP (result), "a", MSB32 + offr);
7084 aopPut (AOP (result), zero, LSB);
7090 /*-----------------------------------------------------------------*/
7091 /* genlshFour - shift four byte by a known amount != 0 */
7092 /*-----------------------------------------------------------------*/
7094 genlshFour (operand * result, operand * left, int shCount)
7098 D (emitcode (";", "genlshFour ");
7101 size = AOP_SIZE (result);
7103 /* if shifting more that 3 bytes */
7108 /* lowest order of left goes to the highest
7109 order of the destination */
7110 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7112 movLeft2Result (left, LSB, result, MSB32, 0);
7113 aopPut (AOP (result), zero, LSB);
7114 aopPut (AOP (result), zero, MSB16);
7115 aopPut (AOP (result), zero, MSB24);
7119 /* more than two bytes */
7120 else if (shCount >= 16)
7122 /* lower order two bytes goes to higher order two bytes */
7124 /* if some more remaining */
7126 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7129 movLeft2Result (left, MSB16, result, MSB32, 0);
7130 movLeft2Result (left, LSB, result, MSB24, 0);
7132 aopPut (AOP (result), zero, MSB16);
7133 aopPut (AOP (result), zero, LSB);
7137 /* if more than 1 byte */
7138 else if (shCount >= 8)
7140 /* lower order three bytes goes to higher order three bytes */
7145 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7147 movLeft2Result (left, LSB, result, MSB16, 0);
7153 movLeft2Result (left, MSB24, result, MSB32, 0);
7154 movLeft2Result (left, MSB16, result, MSB24, 0);
7155 movLeft2Result (left, LSB, result, MSB16, 0);
7156 aopPut (AOP (result), zero, LSB);
7158 else if (shCount == 1)
7159 shiftLLong (left, result, MSB16);
7162 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7163 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7164 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7165 aopPut (AOP (result), zero, LSB);
7170 /* 1 <= shCount <= 7 */
7171 else if (shCount <= 2)
7173 shiftLLong (left, result, LSB);
7175 shiftLLong (result, result, LSB);
7177 /* 3 <= shCount <= 7, optimize */
7180 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7181 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7182 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7187 #ifdef BETTER_LITERAL_SHIFT
7188 /*-----------------------------------------------------------------*/
7189 /* genLeftShiftLiteral - left shifting by known count */
7190 /*-----------------------------------------------------------------*/
7192 genLeftShiftLiteral (operand * left,
7197 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7200 size = getSize (operandType (result));
7202 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7204 /* We only handle certain easy cases so far. */
7206 && (shCount < (size * 8))
7210 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7214 freeAsmop (right, NULL, ic, TRUE);
7216 aopOp(left, ic, FALSE, FALSE);
7217 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7220 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7222 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7223 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7225 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7228 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7230 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7231 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7233 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7239 emitcode ("; shift left ", "result %d, left %d", size,
7243 /* I suppose that the left size >= result size */
7246 _startLazyDPSEvaluation();
7249 movLeft2Result (left, size, result, size, 0);
7251 _endLazyDPSEvaluation();
7253 else if (shCount >= (size * 8))
7255 _startLazyDPSEvaluation();
7258 aopPut (AOP (result), zero, size);
7260 _endLazyDPSEvaluation();
7267 genlshOne (result, left, shCount);
7271 genlshTwo (result, left, shCount);
7275 genlshFour (result, left, shCount);
7279 fprintf(stderr, "*** ack! mystery literal shift!\n");
7283 freeAsmop (left, NULL, ic, TRUE);
7284 freeAsmop (result, NULL, ic, TRUE);
7289 /*-----------------------------------------------------------------*/
7290 /* genLeftShift - generates code for left shifting */
7291 /*-----------------------------------------------------------------*/
7293 genLeftShift (iCode * ic)
7295 operand *left, *right, *result;
7298 symbol *tlbl, *tlbl1;
7300 D (emitcode (";", "genLeftShift "););
7302 right = IC_RIGHT (ic);
7303 left = IC_LEFT (ic);
7304 result = IC_RESULT (ic);
7306 aopOp (right, ic, FALSE, FALSE);
7309 #ifdef BETTER_LITERAL_SHIFT
7310 /* if the shift count is known then do it
7311 as efficiently as possible */
7312 if (AOP_TYPE (right) == AOP_LIT)
7314 if (genLeftShiftLiteral (left, right, result, ic))
7321 /* shift count is unknown then we have to form
7322 a loop get the loop count in B : Note: we take
7323 only the lower order byte since shifting
7324 more that 32 bits make no sense anyway, ( the
7325 largest size of an object can be only 32 bits ) */
7327 if (AOP_TYPE (right) == AOP_LIT)
7329 /* Really should be handled by genLeftShiftLiteral,
7330 * but since I'm too lazy to fix that today, at least we can make
7331 * some small improvement.
7333 emitcode("mov", "b,#0x%02x",
7334 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7338 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7339 emitcode ("inc", "b");
7341 freeAsmop (right, NULL, ic, TRUE);
7342 aopOp (left, ic, FALSE, FALSE);
7343 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7345 /* now move the left to the result if they are not the
7347 if (!sameRegs (AOP (left), AOP (result)) &&
7348 AOP_SIZE (result) > 1)
7351 size = AOP_SIZE (result);
7353 _startLazyDPSEvaluation ();
7356 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7357 if (*l == '@' && (IS_AOP_PREG (result)))
7360 emitcode ("mov", "a,%s", l);
7361 aopPut (AOP (result), "a", offset);
7364 aopPut (AOP (result), l, offset);
7367 _endLazyDPSEvaluation ();
7370 tlbl = newiTempLabel (NULL);
7371 size = AOP_SIZE (result);
7373 tlbl1 = newiTempLabel (NULL);
7375 /* if it is only one byte then */
7378 symbol *tlbl1 = newiTempLabel (NULL);
7380 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7382 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7383 emitcode ("", "%05d$:", tlbl->key + 100);
7384 emitcode ("add", "a,acc");
7385 emitcode ("", "%05d$:", tlbl1->key + 100);
7386 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7387 aopPut (AOP (result), "a", 0);
7391 reAdjustPreg (AOP (result));
7393 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7394 emitcode ("", "%05d$:", tlbl->key + 100);
7395 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7397 emitcode ("add", "a,acc");
7398 aopPut (AOP (result), "a", offset++);
7399 _startLazyDPSEvaluation ();
7402 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7404 emitcode ("rlc", "a");
7405 aopPut (AOP (result), "a", offset++);
7407 _endLazyDPSEvaluation ();
7408 reAdjustPreg (AOP (result));
7410 emitcode ("", "%05d$:", tlbl1->key + 100);
7411 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7413 freeAsmop (left, NULL, ic, TRUE);
7414 freeAsmop (result, NULL, ic, TRUE);
7417 #ifdef BETTER_LITERAL_SHIFT
7418 /*-----------------------------------------------------------------*/
7419 /* genrshOne - right shift a one byte quantity by known count */
7420 /*-----------------------------------------------------------------*/
7422 genrshOne (operand * result, operand * left,
7423 int shCount, int sign)
7425 D (emitcode (";", "genrshOne"););
7426 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7430 #ifdef BETTER_LITERAL_SHIFT
7431 /*-----------------------------------------------------------------*/
7432 /* genrshTwo - right shift two bytes by known amount != 0 */
7433 /*-----------------------------------------------------------------*/
7435 genrshTwo (operand * result, operand * left,
7436 int shCount, int sign)
7438 D (emitcode (";", "genrshTwo"););
7440 /* if shCount >= 8 */
7444 _startLazyDPSEvaluation();
7447 shiftR1Left2Result (left, MSB16, result, LSB,
7452 movLeft2Result (left, MSB16, result, LSB, sign);
7454 addSign (result, MSB16, sign);
7455 _endLazyDPSEvaluation();
7458 /* 1 <= shCount <= 7 */
7461 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7468 /*-----------------------------------------------------------------*/
7469 /* shiftRLong - shift right one long from left to result */
7470 /* offl = LSB or MSB16 */
7471 /*-----------------------------------------------------------------*/
7473 shiftRLong (operand * left, int offl,
7474 operand * result, int sign)
7476 int isSameRegs=sameRegs(AOP(left),AOP(result));
7478 if (isSameRegs && offl>1) {
7479 // we are in big trouble, but this shouldn't happen
7480 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7483 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7488 emitcode ("rlc", "a");
7489 emitcode ("subb", "a,acc");
7490 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7492 aopPut (AOP(result), zero, MSB32);
7497 emitcode ("clr", "c");
7499 emitcode ("mov", "c,acc.7");
7502 emitcode ("rrc", "a");
7504 if (isSameRegs && offl==MSB16) {
7505 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7507 aopPut (AOP (result), "a", MSB32);
7508 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7511 emitcode ("rrc", "a");
7512 if (isSameRegs && offl==1) {
7513 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7515 aopPut (AOP (result), "a", MSB24);
7516 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7518 emitcode ("rrc", "a");
7519 aopPut (AOP (result), "a", MSB16 - offl);
7523 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7524 emitcode ("rrc", "a");
7525 aopPut (AOP (result), "a", LSB);
7532 /*-----------------------------------------------------------------*/
7533 /* genrshFour - shift four byte by a known amount != 0 */
7534 /*-----------------------------------------------------------------*/
7536 genrshFour (operand * result, operand * left,
7537 int shCount, int sign)
7539 D (emitcode (";", "genrshFour");
7542 /* if shifting more that 3 bytes */
7547 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7549 movLeft2Result (left, MSB32, result, LSB, sign);
7550 addSign (result, MSB16, sign);
7552 else if (shCount >= 16)
7556 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7559 movLeft2Result (left, MSB24, result, LSB, 0);
7560 movLeft2Result (left, MSB32, result, MSB16, sign);
7562 addSign (result, MSB24, sign);
7564 else if (shCount >= 8)
7568 shiftRLong (left, MSB16, result, sign);
7569 else if (shCount == 0)
7571 movLeft2Result (left, MSB16, result, LSB, 0);
7572 movLeft2Result (left, MSB24, result, MSB16, 0);
7573 movLeft2Result (left, MSB32, result, MSB24, sign);
7574 addSign (result, MSB32, sign);
7578 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7579 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7580 /* the last shift is signed */
7581 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7582 addSign (result, MSB32, sign);
7586 { /* 1 <= shCount <= 7 */
7589 shiftRLong (left, LSB, result, sign);
7591 shiftRLong (result, LSB, result, sign);
7595 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7596 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7597 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7603 #ifdef BETTER_LITERAL_SHIFT
7604 /*-----------------------------------------------------------------*/
7605 /* genRightShiftLiteral - right shifting by known count */
7606 /*-----------------------------------------------------------------*/
7608 genRightShiftLiteral (operand * left,
7614 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7617 size = getSize (operandType (result));
7619 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7621 /* We only handle certain easy cases so far. */
7623 && (shCount < (size * 8))
7627 D(emitcode (";", "genRightShiftLiteral wimping out"););
7631 freeAsmop (right, NULL, ic, TRUE);
7633 aopOp (left, ic, FALSE, FALSE);
7634 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7637 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7641 /* test the LEFT size !!! */
7643 /* I suppose that the left size >= result size */
7646 size = getDataSize (result);
7647 _startLazyDPSEvaluation();
7650 movLeft2Result (left, size, result, size, 0);
7652 _endLazyDPSEvaluation();
7654 else if (shCount >= (size * 8))
7658 /* get sign in acc.7 */
7659 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7661 addSign (result, LSB, sign);
7668 genrshOne (result, left, shCount, sign);
7672 genrshTwo (result, left, shCount, sign);
7676 genrshFour (result, left, shCount, sign);
7683 freeAsmop (left, NULL, ic, TRUE);
7684 freeAsmop (result, NULL, ic, TRUE);
7690 /*-----------------------------------------------------------------*/
7691 /* genSignedRightShift - right shift of signed number */
7692 /*-----------------------------------------------------------------*/
7694 genSignedRightShift (iCode * ic)
7696 operand *right, *left, *result;
7699 symbol *tlbl, *tlbl1;
7701 D (emitcode (";", "genSignedRightShift "););
7703 /* we do it the hard way put the shift count in b
7704 and loop thru preserving the sign */
7706 right = IC_RIGHT (ic);
7707 left = IC_LEFT (ic);
7708 result = IC_RESULT (ic);
7710 aopOp (right, ic, FALSE, FALSE);
7712 #ifdef BETTER_LITERAL_SHIFT
7713 if (AOP_TYPE (right) == AOP_LIT)
7715 if (genRightShiftLiteral (left, right, result, ic, 1))
7721 /* shift count is unknown then we have to form
7722 a loop get the loop count in B : Note: we take
7723 only the lower order byte since shifting
7724 more that 32 bits make no sense anyway, ( the
7725 largest size of an object can be only 32 bits ) */
7727 if (AOP_TYPE (right) == AOP_LIT)
7729 /* Really should be handled by genRightShiftLiteral,
7730 * but since I'm too lazy to fix that today, at least we can make
7731 * some small improvement.
7733 emitcode("mov", "b,#0x%02x",
7734 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7738 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7739 emitcode ("inc", "b");
7741 freeAsmop (right, NULL, ic, TRUE);
7742 aopOp (left, ic, FALSE, FALSE);
7743 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7745 /* now move the left to the result if they are not the
7747 if (!sameRegs (AOP (left), AOP (result)) &&
7748 AOP_SIZE (result) > 1)
7751 size = AOP_SIZE (result);
7753 _startLazyDPSEvaluation ();
7756 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7757 if (*l == '@' && IS_AOP_PREG (result))
7760 emitcode ("mov", "a,%s", l);
7761 aopPut (AOP (result), "a", offset);
7764 aopPut (AOP (result), l, offset);
7767 _endLazyDPSEvaluation ();
7770 /* mov the highest order bit to OVR */
7771 tlbl = newiTempLabel (NULL);
7772 tlbl1 = newiTempLabel (NULL);
7774 size = AOP_SIZE (result);
7776 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7777 emitcode ("rlc", "a");
7778 emitcode ("mov", "ov,c");
7779 /* if it is only one byte then */
7782 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7784 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7785 emitcode ("", "%05d$:", tlbl->key + 100);
7786 emitcode ("mov", "c,ov");
7787 emitcode ("rrc", "a");
7788 emitcode ("", "%05d$:", tlbl1->key + 100);
7789 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7790 aopPut (AOP (result), "a", 0);
7794 reAdjustPreg (AOP (result));
7795 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7796 emitcode ("", "%05d$:", tlbl->key + 100);
7797 emitcode ("mov", "c,ov");
7798 _startLazyDPSEvaluation ();
7801 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7803 emitcode ("rrc", "a");
7804 aopPut (AOP (result), "a", offset--);
7806 _endLazyDPSEvaluation ();
7807 reAdjustPreg (AOP (result));
7808 emitcode ("", "%05d$:", tlbl1->key + 100);
7809 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7812 freeAsmop (left, NULL, ic, TRUE);
7813 freeAsmop (result, NULL, ic, TRUE);
7816 /*-----------------------------------------------------------------*/
7817 /* genRightShift - generate code for right shifting */
7818 /*-----------------------------------------------------------------*/
7820 genRightShift (iCode * ic)
7822 operand *right, *left, *result;
7826 symbol *tlbl, *tlbl1;
7828 D (emitcode (";", "genRightShift "););
7830 /* if signed then we do it the hard way preserve the
7831 sign bit moving it inwards */
7832 retype = getSpec (operandType (IC_RESULT (ic)));
7834 if (!SPEC_USIGN (retype))
7836 genSignedRightShift (ic);
7840 /* signed & unsigned types are treated the same : i.e. the
7841 signed is NOT propagated inwards : quoting from the
7842 ANSI - standard : "for E1 >> E2, is equivalent to division
7843 by 2**E2 if unsigned or if it has a non-negative value,
7844 otherwise the result is implementation defined ", MY definition
7845 is that the sign does not get propagated */
7847 right = IC_RIGHT (ic);
7848 left = IC_LEFT (ic);
7849 result = IC_RESULT (ic);
7851 aopOp (right, ic, FALSE, FALSE);
7853 #ifdef BETTER_LITERAL_SHIFT
7854 /* if the shift count is known then do it
7855 as efficiently as possible */
7856 if (AOP_TYPE (right) == AOP_LIT)
7858 if (genRightShiftLiteral (left, right, result, ic, 0))
7865 /* shift count is unknown then we have to form
7866 a loop get the loop count in B : Note: we take
7867 only the lower order byte since shifting
7868 more that 32 bits make no sense anyway, ( the
7869 largest size of an object can be only 32 bits ) */
7871 if (AOP_TYPE (right) == AOP_LIT)
7873 /* Really should be handled by genRightShiftLiteral,
7874 * but since I'm too lazy to fix that today, at least we can make
7875 * some small improvement.
7877 emitcode("mov", "b,#0x%02x",
7878 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7882 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7883 emitcode ("inc", "b");
7885 freeAsmop (right, NULL, ic, TRUE);
7886 aopOp (left, ic, FALSE, FALSE);
7887 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7889 /* now move the left to the result if they are not the
7891 if (!sameRegs (AOP (left), AOP (result)) &&
7892 AOP_SIZE (result) > 1)
7895 size = AOP_SIZE (result);
7897 _startLazyDPSEvaluation ();
7900 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7901 if (*l == '@' && IS_AOP_PREG (result))
7904 emitcode ("mov", "a,%s", l);
7905 aopPut (AOP (result), "a", offset);
7908 aopPut (AOP (result), l, offset);
7911 _endLazyDPSEvaluation ();
7914 tlbl = newiTempLabel (NULL);
7915 tlbl1 = newiTempLabel (NULL);
7916 size = AOP_SIZE (result);
7919 /* if it is only one byte then */
7922 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7924 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7925 emitcode ("", "%05d$:", tlbl->key + 100);
7927 emitcode ("rrc", "a");
7928 emitcode ("", "%05d$:", tlbl1->key + 100);
7929 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7930 aopPut (AOP (result), "a", 0);
7934 reAdjustPreg (AOP (result));
7935 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7936 emitcode ("", "%05d$:", tlbl->key + 100);
7938 _startLazyDPSEvaluation ();
7941 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7943 emitcode ("rrc", "a");
7944 aopPut (AOP (result), "a", offset--);
7946 _endLazyDPSEvaluation ();
7947 reAdjustPreg (AOP (result));
7949 emitcode ("", "%05d$:", tlbl1->key + 100);
7950 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7953 freeAsmop (left, NULL, ic, TRUE);
7954 freeAsmop (result, NULL, ic, TRUE);
7957 /*-----------------------------------------------------------------*/
7958 /* genUnpackBits - generates code for unpacking bits */
7959 /*-----------------------------------------------------------------*/
7961 genUnpackBits (operand * result, char *rname, int ptype)
7968 D (emitcode (";", "genUnpackBits ");
7971 etype = getSpec (operandType (result));
7973 /* read the first byte */
7979 emitcode ("mov", "a,@%s", rname);
7983 emitcode ("movx", "a,@%s", rname);
7987 emitcode ("movx", "a,@dptr");
7991 emitcode ("clr", "a");
7992 emitcode ("movc", "a,@a+dptr");
7996 emitcode ("lcall", "__gptrget");
8000 /* if we have bitdisplacement then it fits */
8001 /* into this byte completely or if length is */
8002 /* less than a byte */
8003 if ((shCnt = SPEC_BSTR (etype)) ||
8004 (SPEC_BLEN (etype) <= 8))
8007 /* shift right acc */
8010 emitcode ("anl", "a,#0x%02x",
8011 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8012 aopPut (AOP (result), "a", offset);
8016 /* bit field did not fit in a byte */
8017 rlen = SPEC_BLEN (etype) - 8;
8018 aopPut (AOP (result), "a", offset++);
8027 emitcode ("inc", "%s", rname);
8028 emitcode ("mov", "a,@%s", rname);
8032 emitcode ("inc", "%s", rname);
8033 emitcode ("movx", "a,@%s", rname);
8037 emitcode ("inc", "dptr");
8038 emitcode ("movx", "a,@dptr");
8042 emitcode ("clr", "a");
8043 emitcode ("inc", "dptr");
8044 emitcode ("movc", "a,@a+dptr");
8048 emitcode ("inc", "dptr");
8049 emitcode ("lcall", "__gptrget");
8054 /* if we are done */
8058 aopPut (AOP (result), "a", offset++);
8064 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8065 aopPut (AOP (result), "a", offset);
8072 /*-----------------------------------------------------------------*/
8073 /* genDataPointerGet - generates code when ptr offset is known */
8074 /*-----------------------------------------------------------------*/
8076 genDataPointerGet (operand * left,
8082 int size, offset = 0;
8083 aopOp (result, ic, TRUE, FALSE);
8085 /* get the string representation of the name */
8086 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8087 size = AOP_SIZE (result);
8088 _startLazyDPSEvaluation ();
8092 sprintf (buffer, "(%s + %d)", l + 1, offset);
8094 sprintf (buffer, "%s", l + 1);
8095 aopPut (AOP (result), buffer, offset++);
8097 _endLazyDPSEvaluation ();
8099 freeAsmop (left, NULL, ic, TRUE);
8100 freeAsmop (result, NULL, ic, TRUE);
8103 /*-----------------------------------------------------------------*/
8104 /* genNearPointerGet - emitcode for near pointer fetch */
8105 /*-----------------------------------------------------------------*/
8107 genNearPointerGet (operand * left,
8114 sym_link *rtype, *retype, *letype;
8115 sym_link *ltype = operandType (left);
8118 rtype = operandType (result);
8119 retype = getSpec (rtype);
8120 letype = getSpec (ltype);
8122 aopOp (left, ic, FALSE, FALSE);
8124 /* if left is rematerialisable and
8125 result is not bit variable type and
8126 the left is pointer to data space i.e
8127 lower 128 bytes of space */
8128 if (AOP_TYPE (left) == AOP_IMMD &&
8129 !IS_BITVAR (retype) &&
8130 !IS_BITVAR (letype) &&
8131 DCL_TYPE (ltype) == POINTER)
8133 genDataPointerGet (left, result, ic);
8137 /* if the value is already in a pointer register
8138 then don't need anything more */
8139 if (!AOP_INPREG (AOP (left)))
8141 /* otherwise get a free pointer register */
8143 preg = getFreePtr (ic, &aop, FALSE);
8144 emitcode ("mov", "%s,%s",
8146 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8150 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8152 freeAsmop (left, NULL, ic, TRUE);
8153 aopOp (result, ic, FALSE, FALSE);
8155 /* if bitfield then unpack the bits */
8156 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8157 genUnpackBits (result, rname, POINTER);
8160 /* we have can just get the values */
8161 int size = AOP_SIZE (result);
8166 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8169 emitcode ("mov", "a,@%s", rname);
8170 aopPut (AOP (result), "a", offset);
8174 sprintf (buffer, "@%s", rname);
8175 aopPut (AOP (result), buffer, offset);
8179 emitcode ("inc", "%s", rname);
8183 /* now some housekeeping stuff */
8186 /* we had to allocate for this iCode */
8187 freeAsmop (NULL, aop, ic, TRUE);
8191 /* we did not allocate which means left
8192 already in a pointer register, then
8193 if size > 0 && this could be used again
8194 we have to point it back to where it
8196 if (AOP_SIZE (result) > 1 &&
8197 !OP_SYMBOL (left)->remat &&
8198 (OP_SYMBOL (left)->liveTo > ic->seq ||
8201 int size = AOP_SIZE (result) - 1;
8203 emitcode ("dec", "%s", rname);
8208 freeAsmop (result, NULL, ic, TRUE);
8212 /*-----------------------------------------------------------------*/
8213 /* genPagedPointerGet - emitcode for paged pointer fetch */
8214 /*-----------------------------------------------------------------*/
8216 genPagedPointerGet (operand * left,
8223 sym_link *rtype, *retype, *letype;
8225 rtype = operandType (result);
8226 retype = getSpec (rtype);
8227 letype = getSpec (operandType (left));
8228 aopOp (left, ic, FALSE, FALSE);
8230 /* if the value is already in a pointer register
8231 then don't need anything more */
8232 if (!AOP_INPREG (AOP (left)))
8234 /* otherwise get a free pointer register */
8236 preg = getFreePtr (ic, &aop, FALSE);
8237 emitcode ("mov", "%s,%s",
8239 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8243 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8245 freeAsmop (left, NULL, ic, TRUE);
8246 aopOp (result, ic, FALSE, FALSE);
8248 /* if bitfield then unpack the bits */
8249 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8250 genUnpackBits (result, rname, PPOINTER);
8253 /* we have can just get the values */
8254 int size = AOP_SIZE (result);
8260 emitcode ("movx", "a,@%s", rname);
8261 aopPut (AOP (result), "a", offset);
8266 emitcode ("inc", "%s", rname);
8270 /* now some housekeeping stuff */
8273 /* we had to allocate for this iCode */
8274 freeAsmop (NULL, aop, ic, TRUE);
8278 /* we did not allocate which means left
8279 already in a pointer register, then
8280 if size > 0 && this could be used again
8281 we have to point it back to where it
8283 if (AOP_SIZE (result) > 1 &&
8284 !OP_SYMBOL (left)->remat &&
8285 (OP_SYMBOL (left)->liveTo > ic->seq ||
8288 int size = AOP_SIZE (result) - 1;
8290 emitcode ("dec", "%s", rname);
8295 freeAsmop (result, NULL, ic, TRUE);
8300 /*-----------------------------------------------------------------*/
8301 /* genFarPointerGet - gget value from far space */
8302 /*-----------------------------------------------------------------*/
8304 genFarPointerGet (operand * left,
8305 operand * result, iCode * ic)
8308 sym_link *retype = getSpec (operandType (result));
8309 sym_link *letype = getSpec (operandType (left));
8310 D (emitcode (";", "genFarPointerGet");
8313 aopOp (left, ic, FALSE, FALSE);
8315 /* if the operand is already in dptr
8316 then we do nothing else we move the value to dptr */
8317 if (AOP_TYPE (left) != AOP_STR)
8319 /* if this is remateriazable */
8320 if (AOP_TYPE (left) == AOP_IMMD)
8322 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8326 /* we need to get it byte by byte */
8327 _startLazyDPSEvaluation ();
8328 if (AOP_TYPE (left) != AOP_DPTR)
8330 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8331 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8332 if (options.model == MODEL_FLAT24)
8333 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8337 /* We need to generate a load to DPTR indirect through DPTR. */
8338 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8340 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8341 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8342 if (options.model == MODEL_FLAT24)
8343 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8344 emitcode ("pop", "dph");
8345 emitcode ("pop", "dpl");
8347 _endLazyDPSEvaluation ();
8350 /* so dptr know contains the address */
8351 freeAsmop (left, NULL, ic, TRUE);
8352 aopOp (result, ic, FALSE, TRUE);
8354 /* if bit then unpack */
8355 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8356 genUnpackBits (result, "dptr", FPOINTER);
8359 size = AOP_SIZE (result);
8362 _startLazyDPSEvaluation ();
8369 emitcode ("movx", "a,@dptr");
8371 emitcode ("inc", "dptr");
8373 aopPut (AOP (result), "a", offset++);
8375 _endLazyDPSEvaluation ();
8378 freeAsmop (result, NULL, ic, TRUE);
8381 /*-----------------------------------------------------------------*/
8382 /* emitcodePointerGet - gget value from code space */
8383 /*-----------------------------------------------------------------*/
8385 emitcodePointerGet (operand * left,
8386 operand * result, iCode * ic)
8389 sym_link *retype = getSpec (operandType (result));
8391 aopOp (left, ic, FALSE, FALSE);
8393 /* if the operand is already in dptr
8394 then we do nothing else we move the value to dptr */
8395 if (AOP_TYPE (left) != AOP_STR)
8397 /* if this is remateriazable */
8398 if (AOP_TYPE (left) == AOP_IMMD)
8400 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8403 { /* we need to get it byte by byte */
8404 _startLazyDPSEvaluation ();
8405 if (AOP_TYPE (left) != AOP_DPTR)
8407 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8408 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8409 if (options.model == MODEL_FLAT24)
8410 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8414 /* We need to generate a load to DPTR indirect through DPTR. */
8415 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8417 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8418 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8419 if (options.model == MODEL_FLAT24)
8420 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8421 emitcode ("pop", "dph");
8422 emitcode ("pop", "dpl");
8424 _endLazyDPSEvaluation ();
8427 /* so dptr know contains the address */
8428 freeAsmop (left, NULL, ic, TRUE);
8429 aopOp (result, ic, FALSE, TRUE);
8431 /* if bit then unpack */
8432 if (IS_BITVAR (retype))
8433 genUnpackBits (result, "dptr", CPOINTER);
8436 size = AOP_SIZE (result);
8439 _startLazyDPSEvaluation ();
8445 emitcode ("clr", "a");
8446 emitcode ("movc", "a,@a+dptr");
8448 emitcode ("inc", "dptr");
8449 aopPut (AOP (result), "a", offset++);
8451 _endLazyDPSEvaluation ();
8454 freeAsmop (result, NULL, ic, TRUE);
8457 /*-----------------------------------------------------------------*/
8458 /* genGenPointerGet - gget value from generic pointer space */
8459 /*-----------------------------------------------------------------*/
8461 genGenPointerGet (operand * left,
8462 operand * result, iCode * ic)
8465 sym_link *retype = getSpec (operandType (result));
8466 sym_link *letype = getSpec (operandType (left));
8468 D (emitcode (";", "genGenPointerGet "); );
8470 aopOp (left, ic, FALSE, TRUE);
8472 /* if the operand is already in dptr
8473 then we do nothing else we move the value to dptr */
8474 if (AOP_TYPE (left) != AOP_STR)
8476 /* if this is remateriazable */
8477 if (AOP_TYPE (left) == AOP_IMMD)
8479 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8480 emitcode ("mov", "b,#%d", pointerCode (retype));
8483 { /* we need to get it byte by byte */
8484 _startLazyDPSEvaluation ();
8485 if (AOP(left)->type==AOP_DPTR2) {
8487 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8490 emitcode ("mov", "dpl,%s", l);
8491 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8494 emitcode ("mov", "dph,%s", l);
8495 if (options.model == MODEL_FLAT24) {
8496 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8499 emitcode ("mov", "dpx,%s", l);
8500 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8502 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8505 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8506 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8507 if (options.model == MODEL_FLAT24) {
8508 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8509 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8511 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8514 _endLazyDPSEvaluation ();
8517 /* so dptr know contains the address */
8518 freeAsmop (left, NULL, ic, TRUE);
8519 aopOp (result, ic, FALSE, TRUE);
8521 /* if bit then unpack */
8522 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8523 genUnpackBits (result, "dptr", GPOINTER);
8526 size = AOP_SIZE (result);
8531 emitcode ("lcall", "__gptrget");
8532 aopPut (AOP (result), "a", offset++);
8534 emitcode ("inc", "dptr");
8538 freeAsmop (result, NULL, ic, TRUE);
8541 /*-----------------------------------------------------------------*/
8542 /* genPointerGet - generate code for pointer get */
8543 /*-----------------------------------------------------------------*/
8545 genPointerGet (iCode * ic)
8547 operand *left, *result;
8548 sym_link *type, *etype;
8551 D (emitcode (";", "genPointerGet ");
8554 left = IC_LEFT (ic);
8555 result = IC_RESULT (ic);
8557 /* depending on the type of pointer we need to
8558 move it to the correct pointer register */
8559 type = operandType (left);
8560 etype = getSpec (type);
8561 /* if left is of type of pointer then it is simple */
8562 if (IS_PTR (type) && !IS_FUNC (type->next))
8563 p_type = DCL_TYPE (type);
8566 /* we have to go by the storage class */
8567 p_type = PTR_TYPE (SPEC_OCLS (etype));
8570 /* now that we have the pointer type we assign
8571 the pointer values */
8577 genNearPointerGet (left, result, ic);
8581 genPagedPointerGet (left, result, ic);
8585 genFarPointerGet (left, result, ic);
8589 emitcodePointerGet (left, result, ic);
8593 genGenPointerGet (left, result, ic);
8599 /*-----------------------------------------------------------------*/
8600 /* genPackBits - generates code for packed bit storage */
8601 /*-----------------------------------------------------------------*/
8603 genPackBits (sym_link * etype,
8605 char *rname, int p_type)
8613 blen = SPEC_BLEN (etype);
8614 bstr = SPEC_BSTR (etype);
8616 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8619 /* if the bit lenth is less than or */
8620 /* it exactly fits a byte then */
8621 if (SPEC_BLEN (etype) <= 8)
8623 shCount = SPEC_BSTR (etype);
8625 /* shift left acc */
8628 if (SPEC_BLEN (etype) < 8)
8629 { /* if smaller than a byte */
8635 emitcode ("mov", "b,a");
8636 emitcode ("mov", "a,@%s", rname);
8640 emitcode ("mov", "b,a");
8641 emitcode ("movx", "a,@dptr");
8645 emitcode ("push", "b");
8646 emitcode ("push", "acc");
8647 emitcode ("lcall", "__gptrget");
8648 emitcode ("pop", "b");
8652 emitcode ("anl", "a,#0x%02x", (unsigned char)
8653 ((unsigned char) (0xFF << (blen + bstr)) |
8654 (unsigned char) (0xFF >> (8 - bstr))));
8655 emitcode ("orl", "a,b");
8656 if (p_type == GPOINTER)
8657 emitcode ("pop", "b");
8664 emitcode ("mov", "@%s,a", rname);
8668 emitcode ("movx", "@dptr,a");
8672 emitcode ("lcall", "__gptrput");
8677 if (SPEC_BLEN (etype) <= 8)
8680 emitcode ("inc", "%s", rname);
8681 rLen = SPEC_BLEN (etype);
8683 /* now generate for lengths greater than one byte */
8687 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8699 emitcode ("mov", "@%s,a", rname);
8702 emitcode ("mov", "@%s,%s", rname, l);
8707 emitcode ("movx", "@dptr,a");
8712 emitcode ("lcall", "__gptrput");
8715 emitcode ("inc", "%s", rname);
8720 /* last last was not complete */
8723 /* save the byte & read byte */
8727 emitcode ("mov", "b,a");
8728 emitcode ("mov", "a,@%s", rname);
8732 emitcode ("mov", "b,a");
8733 emitcode ("movx", "a,@dptr");
8737 emitcode ("push", "b");
8738 emitcode ("push", "acc");
8739 emitcode ("lcall", "__gptrget");
8740 emitcode ("pop", "b");
8744 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8745 emitcode ("orl", "a,b");
8748 if (p_type == GPOINTER)
8749 emitcode ("pop", "b");
8755 emitcode ("mov", "@%s,a", rname);
8759 emitcode ("movx", "@dptr,a");
8763 emitcode ("lcall", "__gptrput");
8767 /*-----------------------------------------------------------------*/
8768 /* genDataPointerSet - remat pointer to data space */
8769 /*-----------------------------------------------------------------*/
8771 genDataPointerSet (operand * right,
8775 int size, offset = 0;
8776 char *l, buffer[256];
8778 aopOp (right, ic, FALSE, FALSE);
8780 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8781 size = AOP_SIZE (right);
8785 sprintf (buffer, "(%s + %d)", l + 1, offset);
8787 sprintf (buffer, "%s", l + 1);
8788 emitcode ("mov", "%s,%s", buffer,
8789 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8792 freeAsmop (right, NULL, ic, TRUE);
8793 freeAsmop (result, NULL, ic, TRUE);
8796 /*-----------------------------------------------------------------*/
8797 /* genNearPointerSet - emitcode for near pointer put */
8798 /*-----------------------------------------------------------------*/
8800 genNearPointerSet (operand * right,
8807 sym_link *retype, *letype;
8808 sym_link *ptype = operandType (result);
8810 retype = getSpec (operandType (right));
8811 letype = getSpec (ptype);
8813 aopOp (result, ic, FALSE, FALSE);
8815 /* if the result is rematerializable &
8816 in data space & not a bit variable */
8817 if (AOP_TYPE (result) == AOP_IMMD &&
8818 DCL_TYPE (ptype) == POINTER &&
8819 !IS_BITVAR (retype) &&
8820 !IS_BITVAR (letype))
8822 genDataPointerSet (right, result, ic);
8826 /* if the value is already in a pointer register
8827 then don't need anything more */
8828 if (!AOP_INPREG (AOP (result)))
8830 /* otherwise get a free pointer register */
8832 preg = getFreePtr (ic, &aop, FALSE);
8833 emitcode ("mov", "%s,%s",
8835 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8839 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8841 freeAsmop (result, NULL, ic, TRUE);
8842 aopOp (right, ic, FALSE, FALSE);
8844 /* if bitfield then unpack the bits */
8845 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8846 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8849 /* we have can just get the values */
8850 int size = AOP_SIZE (right);
8855 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8859 emitcode ("mov", "@%s,a", rname);
8862 emitcode ("mov", "@%s,%s", rname, l);
8864 emitcode ("inc", "%s", rname);
8869 /* now some housekeeping stuff */
8872 /* we had to allocate for this iCode */
8873 freeAsmop (NULL, aop, ic, TRUE);
8877 /* we did not allocate which means left
8878 already in a pointer register, then
8879 if size > 0 && this could be used again
8880 we have to point it back to where it
8882 if (AOP_SIZE (right) > 1 &&
8883 !OP_SYMBOL (result)->remat &&
8884 (OP_SYMBOL (result)->liveTo > ic->seq ||
8887 int size = AOP_SIZE (right) - 1;
8889 emitcode ("dec", "%s", rname);
8894 freeAsmop (right, NULL, ic, TRUE);
8899 /*-----------------------------------------------------------------*/
8900 /* genPagedPointerSet - emitcode for Paged pointer put */
8901 /*-----------------------------------------------------------------*/
8903 genPagedPointerSet (operand * right,
8910 sym_link *retype, *letype;
8912 retype = getSpec (operandType (right));
8913 letype = getSpec (operandType (result));
8915 aopOp (result, ic, FALSE, FALSE);
8917 /* if the value is already in a pointer register
8918 then don't need anything more */
8919 if (!AOP_INPREG (AOP (result)))
8921 /* otherwise get a free pointer register */
8923 preg = getFreePtr (ic, &aop, FALSE);
8924 emitcode ("mov", "%s,%s",
8926 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8930 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8932 freeAsmop (result, NULL, ic, TRUE);
8933 aopOp (right, ic, FALSE, FALSE);
8935 /* if bitfield then unpack the bits */
8936 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8937 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8940 /* we have can just get the values */
8941 int size = AOP_SIZE (right);
8946 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8949 emitcode ("movx", "@%s,a", rname);
8952 emitcode ("inc", "%s", rname);
8958 /* now some housekeeping stuff */
8961 /* we had to allocate for this iCode */
8962 freeAsmop (NULL, aop, ic, TRUE);
8966 /* we did not allocate which means left
8967 already in a pointer register, then
8968 if size > 0 && this could be used again
8969 we have to point it back to where it
8971 if (AOP_SIZE (right) > 1 &&
8972 !OP_SYMBOL (result)->remat &&
8973 (OP_SYMBOL (result)->liveTo > ic->seq ||
8976 int size = AOP_SIZE (right) - 1;
8978 emitcode ("dec", "%s", rname);
8983 freeAsmop (right, NULL, ic, TRUE);
8988 /*-----------------------------------------------------------------*/
8989 /* genFarPointerSet - set value from far space */
8990 /*-----------------------------------------------------------------*/
8992 genFarPointerSet (operand * right,
8993 operand * result, iCode * ic)
8996 sym_link *retype = getSpec (operandType (right));
8997 sym_link *letype = getSpec (operandType (result));
8999 aopOp (result, ic, FALSE, FALSE);
9001 /* if the operand is already in dptr
9002 then we do nothing else we move the value to dptr */
9003 if (AOP_TYPE (result) != AOP_STR)
9005 /* if this is remateriazable */
9006 if (AOP_TYPE (result) == AOP_IMMD)
9007 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9010 /* we need to get it byte by byte */
9011 _startLazyDPSEvaluation ();
9012 if (AOP_TYPE (result) != AOP_DPTR)
9014 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9015 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9016 if (options.model == MODEL_FLAT24)
9017 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9021 /* We need to generate a load to DPTR indirect through DPTR. */
9022 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9024 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9025 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9026 if (options.model == MODEL_FLAT24)
9027 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9028 emitcode ("pop", "dph");
9029 emitcode ("pop", "dpl");
9031 _endLazyDPSEvaluation ();
9034 /* so dptr know contains the address */
9035 freeAsmop (result, NULL, ic, TRUE);
9036 aopOp (right, ic, FALSE, TRUE);
9038 /* if bit then unpack */
9039 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9040 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9043 size = AOP_SIZE (right);
9046 _startLazyDPSEvaluation ();
9049 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9055 emitcode ("movx", "@dptr,a");
9057 emitcode ("inc", "dptr");
9059 _endLazyDPSEvaluation ();
9062 freeAsmop (right, NULL, ic, TRUE);
9065 /*-----------------------------------------------------------------*/
9066 /* genGenPointerSet - set value from generic pointer space */
9067 /*-----------------------------------------------------------------*/
9069 genGenPointerSet (operand * right,
9070 operand * result, iCode * ic)
9073 sym_link *retype = getSpec (operandType (right));
9074 sym_link *letype = getSpec (operandType (result));
9076 aopOp (result, ic, FALSE, TRUE);
9078 /* if the operand is already in dptr
9079 then we do nothing else we move the value to dptr */
9080 if (AOP_TYPE (result) != AOP_STR)
9082 _startLazyDPSEvaluation ();
9083 /* if this is remateriazable */
9084 if (AOP_TYPE (result) == AOP_IMMD)
9086 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9087 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9090 { /* we need to get it byte by byte */
9091 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9092 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9093 if (options.model == MODEL_FLAT24) {
9094 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9095 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9097 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9100 _endLazyDPSEvaluation ();
9102 /* so dptr know contains the address */
9103 freeAsmop (result, NULL, ic, TRUE);
9104 aopOp (right, ic, FALSE, TRUE);
9106 /* if bit then unpack */
9107 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9108 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9111 size = AOP_SIZE (right);
9114 _startLazyDPSEvaluation ();
9117 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9123 emitcode ("lcall", "__gptrput");
9125 emitcode ("inc", "dptr");
9127 _endLazyDPSEvaluation ();
9130 freeAsmop (right, NULL, ic, TRUE);
9133 /*-----------------------------------------------------------------*/
9134 /* genPointerSet - stores the value into a pointer location */
9135 /*-----------------------------------------------------------------*/
9137 genPointerSet (iCode * ic)
9139 operand *right, *result;
9140 sym_link *type, *etype;
9143 D (emitcode (";", "genPointerSet ");
9146 right = IC_RIGHT (ic);
9147 result = IC_RESULT (ic);
9149 /* depending on the type of pointer we need to
9150 move it to the correct pointer register */
9151 type = operandType (result);
9152 etype = getSpec (type);
9153 /* if left is of type of pointer then it is simple */
9154 if (IS_PTR (type) && !IS_FUNC (type->next))
9156 p_type = DCL_TYPE (type);
9160 /* we have to go by the storage class */
9161 p_type = PTR_TYPE (SPEC_OCLS (etype));
9164 /* now that we have the pointer type we assign
9165 the pointer values */
9171 genNearPointerSet (right, result, ic);
9175 genPagedPointerSet (right, result, ic);
9179 genFarPointerSet (right, result, ic);
9183 genGenPointerSet (right, result, ic);
9189 /*-----------------------------------------------------------------*/
9190 /* genIfx - generate code for Ifx statement */
9191 /*-----------------------------------------------------------------*/
9193 genIfx (iCode * ic, iCode * popIc)
9195 operand *cond = IC_COND (ic);
9198 D (emitcode (";", "genIfx "););
9200 aopOp (cond, ic, FALSE, FALSE);
9202 /* get the value into acc */
9203 if (AOP_TYPE (cond) != AOP_CRY)
9207 /* the result is now in the accumulator */
9208 freeAsmop (cond, NULL, ic, TRUE);
9210 /* if there was something to be popped then do it */
9214 /* if the condition is a bit variable */
9215 if (isbit && IS_ITEMP (cond) &&
9217 genIfxJump (ic, SPIL_LOC (cond)->rname);
9218 else if (isbit && !IS_ITEMP (cond))
9219 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9221 genIfxJump (ic, "a");
9226 /*-----------------------------------------------------------------*/
9227 /* genAddrOf - generates code for address of */
9228 /*-----------------------------------------------------------------*/
9230 genAddrOf (iCode * ic)
9232 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9235 D (emitcode (";", "genAddrOf ");
9238 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9240 /* if the operand is on the stack then we
9241 need to get the stack offset of this
9245 /* if it has an offset then we need to compute
9249 emitcode ("mov", "a,_bp");
9250 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9251 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9255 /* we can just move _bp */
9256 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9258 /* fill the result with zero */
9259 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9262 if (options.stack10bit && size < (FPTRSIZE - 1))
9265 "*** warning: pointer to stack var truncated.\n");
9272 if (options.stack10bit && offset == 2)
9274 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9278 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9285 /* object not on stack then we need the name */
9286 size = AOP_SIZE (IC_RESULT (ic));
9291 char s[SDCC_NAME_MAX];
9293 sprintf (s, "#(%s >> %d)",
9297 sprintf (s, "#%s", sym->rname);
9298 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9302 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9306 /*-----------------------------------------------------------------*/
9307 /* genArrayInit - generates code for address of */
9308 /*-----------------------------------------------------------------*/
9310 genArrayInit (iCode * ic)
9314 int elementSize = 0, eIndex;
9315 unsigned val, lastVal;
9317 operand *left=IC_LEFT(ic);
9319 D (emitcode (";", "genArrayInit "););
9321 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9323 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9325 // Load immediate value into DPTR.
9326 emitcode("mov", "dptr, %s",
9327 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9329 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9332 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9333 "Unexpected operand to genArrayInit.\n");
9336 // a regression because of SDCCcse.c:1.52
9337 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9338 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9339 if (options.model == MODEL_FLAT24)
9340 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9344 type = operandType(IC_LEFT(ic));
9346 if (type && type->next)
9348 elementSize = getSize(type->next);
9352 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9353 "can't determine element size in genArrayInit.\n");
9357 iLoop = IC_ARRAYILIST(ic);
9362 bool firstpass = TRUE;
9364 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9365 iLoop->count, (int)iLoop->literalValue, elementSize);
9371 symbol *tlbl = NULL;
9373 count = ix > 256 ? 256 : ix;
9377 tlbl = newiTempLabel (NULL);
9378 if (firstpass || (count & 0xff))
9380 emitcode("mov", "b, #0x%x", count & 0xff);
9383 emitcode ("", "%05d$:", tlbl->key + 100);
9388 for (eIndex = 0; eIndex < elementSize; eIndex++)
9390 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9393 emitcode("mov", "a, #0x%x", val);
9397 emitcode("movx", "@dptr, a");
9398 emitcode("inc", "dptr");
9403 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9409 iLoop = iLoop->next;
9412 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9415 /*-----------------------------------------------------------------*/
9416 /* genFarFarAssign - assignment when both are in far space */
9417 /*-----------------------------------------------------------------*/
9419 genFarFarAssign (operand * result, operand * right, iCode * ic)
9421 int size = AOP_SIZE (right);
9423 symbol *rSym = NULL;
9427 /* quick & easy case. */
9428 D(emitcode(";","genFarFarAssign (1 byte case)"););
9429 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9430 freeAsmop (right, NULL, ic, FALSE);
9431 /* now assign DPTR to result */
9433 aopOp(result, ic, FALSE, FALSE);
9435 aopPut(AOP(result), "a", 0);
9436 freeAsmop(result, NULL, ic, FALSE);
9440 /* See if we've got an underlying symbol to abuse. */
9441 if (IS_SYMOP(result) && OP_SYMBOL(result))
9443 if (IS_TRUE_SYMOP(result))
9445 rSym = OP_SYMBOL(result);
9447 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9449 rSym = OP_SYMBOL(result)->usl.spillLoc;
9453 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9455 /* We can use the '390 auto-toggle feature to good effect here. */
9457 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9458 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9459 emitcode ("mov", "dptr,#%s", rSym->rname);
9460 /* DP2 = result, DP1 = right, DP1 is current. */
9463 emitcode("movx", "a,@dptr");
9464 emitcode("movx", "@dptr,a");
9467 emitcode("inc", "dptr");
9468 emitcode("inc", "dptr");
9471 emitcode("mov", "dps, #0");
9472 freeAsmop (right, NULL, ic, FALSE);
9474 some alternative code for processors without auto-toggle
9475 no time to test now, so later well put in...kpb
9476 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9477 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9478 emitcode ("mov", "dptr,#%s", rSym->rname);
9479 /* DP2 = result, DP1 = right, DP1 is current. */
9483 emitcode("movx", "a,@dptr");
9485 emitcode("inc", "dptr");
9486 emitcode("inc", "dps");
9487 emitcode("movx", "@dptr,a");
9489 emitcode("inc", "dptr");
9490 emitcode("inc", "dps");
9492 emitcode("mov", "dps, #0");
9493 freeAsmop (right, NULL, ic, FALSE);
9498 D (emitcode (";", "genFarFarAssign"););
9499 aopOp (result, ic, TRUE, TRUE);
9501 _startLazyDPSEvaluation ();
9505 aopPut (AOP (result),
9506 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9509 _endLazyDPSEvaluation ();
9510 freeAsmop (result, NULL, ic, FALSE);
9511 freeAsmop (right, NULL, ic, FALSE);
9515 /*-----------------------------------------------------------------*/
9516 /* genAssign - generate code for assignment */
9517 /*-----------------------------------------------------------------*/
9519 genAssign (iCode * ic)
9521 operand *result, *right;
9523 unsigned long lit = 0L;
9525 D (emitcode (";", "genAssign ");
9528 result = IC_RESULT (ic);
9529 right = IC_RIGHT (ic);
9531 /* if they are the same */
9532 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9535 aopOp (right, ic, FALSE, FALSE);
9537 emitcode (";", "genAssign: resultIsFar = %s",
9538 isOperandInFarSpace (result) ?
9541 /* special case both in far space */
9542 if ((AOP_TYPE (right) == AOP_DPTR ||
9543 AOP_TYPE (right) == AOP_DPTR2) &&
9544 /* IS_TRUE_SYMOP(result) && */
9545 isOperandInFarSpace (result))
9547 genFarFarAssign (result, right, ic);
9551 aopOp (result, ic, TRUE, FALSE);
9553 /* if they are the same registers */
9554 if (sameRegs (AOP (right), AOP (result)))
9557 /* if the result is a bit */
9558 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9560 /* if the right size is a literal then
9561 we know what the value is */
9562 if (AOP_TYPE (right) == AOP_LIT)
9564 if (((int) operandLitValue (right)))
9565 aopPut (AOP (result), one, 0);
9567 aopPut (AOP (result), zero, 0);
9571 /* the right is also a bit variable */
9572 if (AOP_TYPE (right) == AOP_CRY)
9574 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9575 aopPut (AOP (result), "c", 0);
9581 aopPut (AOP (result), "a", 0);
9585 /* bit variables done */
9587 size = AOP_SIZE (result);
9589 if (AOP_TYPE (right) == AOP_LIT)
9590 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9593 (AOP_TYPE (result) != AOP_REG) &&
9594 (AOP_TYPE (right) == AOP_LIT) &&
9595 !IS_FLOAT (operandType (right)))
9597 _startLazyDPSEvaluation ();
9598 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9600 aopPut (AOP (result),
9601 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9606 /* And now fill the rest with zeros. */
9609 emitcode ("clr", "a");
9613 aopPut (AOP (result), "a", offset++);
9615 _endLazyDPSEvaluation ();
9619 _startLazyDPSEvaluation ();
9622 aopPut (AOP (result),
9623 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9627 _endLazyDPSEvaluation ();
9631 freeAsmop (right, NULL, ic, FALSE);
9632 freeAsmop (result, NULL, ic, TRUE);
9635 /*-----------------------------------------------------------------*/
9636 /* genJumpTab - generates code for jump table */
9637 /*-----------------------------------------------------------------*/
9639 genJumpTab (iCode * ic)
9644 D (emitcode (";", "genJumpTab ");
9647 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9648 /* get the condition into accumulator */
9649 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9651 /* multiply by four! */
9652 emitcode ("add", "a,acc");
9653 emitcode ("add", "a,acc");
9654 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9656 jtab = newiTempLabel (NULL);
9657 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9658 emitcode ("jmp", "@a+dptr");
9659 emitcode ("", "%05d$:", jtab->key + 100);
9660 /* now generate the jump labels */
9661 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9662 jtab = setNextItem (IC_JTLABELS (ic)))
9663 emitcode ("ljmp", "%05d$", jtab->key + 100);
9667 /*-----------------------------------------------------------------*/
9668 /* genCast - gen code for casting */
9669 /*-----------------------------------------------------------------*/
9671 genCast (iCode * ic)
9673 operand *result = IC_RESULT (ic);
9674 sym_link *ctype = operandType (IC_LEFT (ic));
9675 sym_link *rtype = operandType (IC_RIGHT (ic));
9676 operand *right = IC_RIGHT (ic);
9679 D (emitcode (";", "genCast ");
9682 /* if they are equivalent then do nothing */
9683 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9686 aopOp (right, ic, FALSE, FALSE);
9687 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9689 /* if the result is a bit */
9690 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9691 if (IS_BITVAR(OP_SYMBOL(result)->type))
9693 /* if the right size is a literal then
9694 we know what the value is */
9695 if (AOP_TYPE (right) == AOP_LIT)
9697 if (((int) operandLitValue (right)))
9698 aopPut (AOP (result), one, 0);
9700 aopPut (AOP (result), zero, 0);
9705 /* the right is also a bit variable */
9706 if (AOP_TYPE (right) == AOP_CRY)
9708 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9709 aopPut (AOP (result), "c", 0);
9715 aopPut (AOP (result), "a", 0);
9719 /* if they are the same size : or less */
9720 if (AOP_SIZE (result) <= AOP_SIZE (right))
9723 /* if they are in the same place */
9724 if (sameRegs (AOP (right), AOP (result)))
9727 /* if they in different places then copy */
9728 size = AOP_SIZE (result);
9730 _startLazyDPSEvaluation ();
9733 aopPut (AOP (result),
9734 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9738 _endLazyDPSEvaluation ();
9743 /* if the result is of type pointer */
9748 sym_link *type = operandType (right);
9750 /* pointer to generic pointer */
9751 if (IS_GENPTR (ctype))
9757 p_type = DCL_TYPE (type);
9761 #if OLD_CAST_BEHAVIOR
9762 /* KV: we are converting a non-pointer type to
9763 * a generic pointer. This (ifdef'd out) code
9764 * says that the resulting generic pointer
9765 * should have the same class as the storage
9766 * location of the non-pointer variable.
9768 * For example, converting an int (which happens
9769 * to be stored in DATA space) to a pointer results
9770 * in a DATA generic pointer; if the original int
9771 * in XDATA space, so will be the resulting pointer.
9773 * I don't like that behavior, and thus this change:
9774 * all such conversions will be forced to XDATA and
9775 * throw a warning. If you want some non-XDATA
9776 * type, or you want to suppress the warning, you
9777 * must go through an intermediate cast, like so:
9779 * char _generic *gp = (char _xdata *)(intVar);
9781 sym_link *etype = getSpec (type);
9783 /* we have to go by the storage class */
9784 if (SPEC_OCLS (etype) != generic)
9786 p_type = PTR_TYPE (SPEC_OCLS (etype));
9791 /* Converting unknown class (i.e. register variable)
9792 * to generic pointer. This is not good, but
9793 * we'll make a guess (and throw a warning).
9796 werror (W_INT_TO_GEN_PTR_CAST);
9800 /* the first two bytes are known */
9801 size = GPTRSIZE - 1;
9803 _startLazyDPSEvaluation ();
9806 aopPut (AOP (result),
9807 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9811 _endLazyDPSEvaluation ();
9813 /* the last byte depending on type */
9831 /* this should never happen */
9832 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9833 "got unknown pointer type");
9836 aopPut (AOP (result), l, GPTRSIZE - 1);
9840 /* just copy the pointers */
9841 size = AOP_SIZE (result);
9843 _startLazyDPSEvaluation ();
9846 aopPut (AOP (result),
9847 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9851 _endLazyDPSEvaluation ();
9855 /* so we now know that the size of destination is greater
9856 than the size of the source */
9857 /* we move to result for the size of source */
9858 size = AOP_SIZE (right);
9860 _startLazyDPSEvaluation ();
9863 aopPut (AOP (result),
9864 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9868 _endLazyDPSEvaluation ();
9870 /* now depending on the sign of the source && destination */
9871 size = AOP_SIZE (result) - AOP_SIZE (right);
9872 /* if unsigned or not an integral type */
9873 /* also, if the source is a bit, we don't need to sign extend, because
9874 * it can't possibly have set the sign bit.
9876 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9880 aopPut (AOP (result), zero, offset++);
9885 /* we need to extend the sign :{ */
9886 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9887 FALSE, FALSE, TRUE);
9889 emitcode ("rlc", "a");
9890 emitcode ("subb", "a,acc");
9892 aopPut (AOP (result), "a", offset++);
9895 /* we are done hurray !!!! */
9898 freeAsmop (right, NULL, ic, TRUE);
9899 freeAsmop (result, NULL, ic, TRUE);
9903 /*-----------------------------------------------------------------*/
9904 /* genDjnz - generate decrement & jump if not zero instrucion */
9905 /*-----------------------------------------------------------------*/
9907 genDjnz (iCode * ic, iCode * ifx)
9913 /* if the if condition has a false label
9914 then we cannot save */
9918 /* if the minus is not of the form
9920 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9921 !IS_OP_LITERAL (IC_RIGHT (ic)))
9924 if (operandLitValue (IC_RIGHT (ic)) != 1)
9927 /* if the size of this greater than one then no
9929 if (getSize (operandType (IC_RESULT (ic))) > 1)
9932 /* otherwise we can save BIG */
9933 D(emitcode(";", "genDjnz"););
9935 lbl = newiTempLabel (NULL);
9936 lbl1 = newiTempLabel (NULL);
9938 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9940 if (AOP_NEEDSACC(IC_RESULT(ic)))
9942 /* If the result is accessed indirectly via
9943 * the accumulator, we must explicitly write
9944 * it back after the decrement.
9946 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9948 if (strcmp(rByte, "a"))
9950 /* Something is hopelessly wrong */
9951 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9952 __FILE__, __LINE__);
9953 /* We can just give up; the generated code will be inefficient,
9956 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9959 emitcode ("dec", "%s", rByte);
9960 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9961 emitcode ("jnz", "%05d$", lbl->key + 100);
9963 else if (IS_AOP_PREG (IC_RESULT (ic)))
9965 emitcode ("dec", "%s",
9966 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9967 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9968 emitcode ("jnz", "%05d$", lbl->key + 100);
9972 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9975 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9976 emitcode ("", "%05d$:", lbl->key + 100);
9977 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9978 emitcode ("", "%05d$:", lbl1->key + 100);
9980 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9985 /*-----------------------------------------------------------------*/
9986 /* genReceive - generate code for a receive iCode */
9987 /*-----------------------------------------------------------------*/
9989 genReceive (iCode * ic)
9992 D (emitcode (";", "genReceive ");
9995 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9996 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9997 IS_TRUE_SYMOP (IC_RESULT (ic))))
9999 int size = getSize (operandType (IC_RESULT (ic)));
10000 int offset = fReturnSizeDS390 - size;
10003 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10004 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10007 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10008 size = AOP_SIZE (IC_RESULT (ic));
10012 emitcode ("pop", "acc");
10013 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10020 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10022 assignResultValue (IC_RESULT (ic));
10025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10028 /*-----------------------------------------------------------------*/
10029 /* gen390Code - generate code for Dallas 390 based controllers */
10030 /*-----------------------------------------------------------------*/
10032 gen390Code (iCode * lic)
10037 lineHead = lineCurr = NULL;
10039 if (options.model == MODEL_FLAT24) {
10040 fReturnSizeDS390 = 5;
10041 fReturn = fReturn24;
10043 fReturnSizeDS390 = 4;
10044 fReturn = fReturn16;
10045 options.stack10bit=0;
10049 /* print the allocation information */
10051 printAllocInfo (currFunc, codeOutFile);
10053 /* if debug information required */
10054 if (options.debug && currFunc)
10056 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10058 if (IS_STATIC (currFunc->etype))
10059 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10061 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10064 /* stack pointer name */
10065 if (options.useXstack)
10071 for (ic = lic; ic; ic = ic->next)
10074 if (cln != ic->lineno)
10079 emitcode ("", "C$%s$%d$%d$%d ==.",
10080 FileBaseName (ic->filename), ic->lineno,
10081 ic->level, ic->block);
10084 emitcode (";", "%s %d", ic->filename, ic->lineno);
10087 /* if the result is marked as
10088 spilt and rematerializable or code for
10089 this has already been generated then
10091 if (resultRemat (ic) || ic->generated)
10094 /* depending on the operation */
10114 /* IPOP happens only when trying to restore a
10115 spilt live range, if there is an ifx statement
10116 following this pop then the if statement might
10117 be using some of the registers being popped which
10118 would destory the contents of the register so
10119 we need to check for this condition and handle it */
10121 ic->next->op == IFX &&
10122 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10123 genIfx (ic->next, ic);
10141 genEndFunction (ic);
10161 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10178 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10182 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10189 /* note these two are xlated by algebraic equivalence
10190 during parsing SDCC.y */
10191 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10192 "got '>=' or '<=' shouldn't have come here");
10196 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10208 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10212 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10216 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10240 genRightShift (ic);
10243 case GET_VALUE_AT_ADDRESS:
10244 genPointerGet (ic);
10248 if (POINTER_SET (ic))
10249 genPointerSet (ic);
10275 addSet (&_G.sendSet, ic);
10288 /* now we are ready to call the
10289 peep hole optimizer */
10290 if (!options.nopeep)
10291 peepHole (&lineHead);
10293 /* now do the actual printing */
10294 printLine (lineHead, codeOutFile);