1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 #define BETTER_LITERAL_SHIFT
57 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
70 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
71 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
74 static char *fReturn24[] =
75 {"dpl", "dph", "dpx", "b", "a"};
76 static char *fReturn16[] =
77 {"dpl", "dph", "b", "a"};
78 static char **fReturn = fReturn24;
79 static char *accUse[] =
82 static short rbank = -1;
96 static void saveRBank (int, iCode *, bool);
98 #define RESULTONSTACK(x) \
99 (IC_RESULT(x) && IC_RESULT(x)->aop && \
100 IC_RESULT(x)->aop->type == AOP_STK )
102 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
103 #define MOVA(x) { char *_mova_tmp = strdup(x); \
104 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106 emitcode("mov","a,%s",_mova_tmp); \
110 #define CLRC emitcode("clr","c")
111 #define SETC emitcode("setb","c")
113 // A scratch register which will be used to hold
114 // result bytes from operands in far space via DPTR2.
115 #define DP2_RESULT_REG "ap"
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
120 static unsigned char SLMask[] =
121 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
125 0x07, 0x03, 0x01, 0x00};
132 /*-----------------------------------------------------------------*/
133 /* emitcode - writes the code into a file : for now it is simple */
134 /*-----------------------------------------------------------------*/
136 emitcode (char *inst, char *fmt,...)
139 char lb[INITIAL_INLINEASM];
147 sprintf (lb, "%s\t", inst);
149 sprintf (lb, "%s", inst);
150 vsprintf (lb + (strlen (lb)), fmt, ap);
153 vsprintf (lb, fmt, ap);
155 while (isspace (*lbp))
159 lineCurr = (lineCurr ?
160 connectLine (lineCurr, newLineNode (lb)) :
161 (lineHead = newLineNode (lb)));
162 lineCurr->isInline = _G.inLine;
163 lineCurr->isDebug = _G.debugLine;
167 /*-----------------------------------------------------------------*/
168 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
169 /*-----------------------------------------------------------------*/
171 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 bool r0iu = FALSE, r1iu = FALSE;
174 bool r0ou = FALSE, r1ou = FALSE;
176 /* the logic: if r0 & r1 used in the instruction
177 then we are in trouble otherwise */
179 /* first check if r0 & r1 are used by this
180 instruction, in which case we are in trouble */
181 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
182 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
187 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
188 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190 /* if no usage of r0 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
194 (*aopp)->type = AOP_R0;
196 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
199 /* if no usage of r1 then return it */
202 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
203 (*aopp)->type = AOP_R1;
205 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
208 /* now we know they both have usage */
209 /* if r0 not used in this instruction */
212 /* push it if not already pushed */
215 emitcode ("push", "%s",
216 ds390_regWithIdx (R0_IDX)->dname);
220 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
221 (*aopp)->type = AOP_R0;
223 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
226 /* if r1 not used then */
230 /* push it if not already pushed */
233 emitcode ("push", "%s",
234 ds390_regWithIdx (R1_IDX)->dname);
238 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
239 (*aopp)->type = AOP_R1;
240 return ds390_regWithIdx (R1_IDX);
244 /* I said end of world but not quite end of world yet */
245 /* if this is a result then we can push it on the stack */
248 (*aopp)->type = AOP_STK;
252 /* other wise this is true end of the world */
253 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
254 "getFreePtr should never reach here");
258 /*-----------------------------------------------------------------*/
259 /* newAsmop - creates a new asmOp */
260 /*-----------------------------------------------------------------*/
262 newAsmop (short type)
266 aop = Safe_calloc (1, sizeof (asmop));
271 static int _currentDPS; /* Current processor DPS. */
272 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
273 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
275 /*-----------------------------------------------------------------*/
276 /* genSetDPTR: generate code to select which DPTR is in use (zero */
277 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
278 /* alternate DPTR (DPL1/DPH1/DPX1). */
279 /*-----------------------------------------------------------------*/
284 /* If we are doing lazy evaluation, simply note the desired
285 * change, but don't emit any code yet.
295 emitcode ("mov", "dps, #0x00");
300 emitcode ("mov", "dps, #0x01");
304 /*-----------------------------------------------------------------*/
305 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /* Any code that operates on DPTR (NB: not on the individual */
308 /* components, like DPH) *must* call _flushLazyDPS() before using */
309 /* DPTR within a lazy DPS evaluation block. */
311 /* Note that aopPut and aopGet already contain the proper calls to */
312 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
313 /* DPS evaluation block. */
315 /* Also, _flushLazyDPS must be called before any flow control */
316 /* operations that could potentially branch out of the block. */
318 /* Lazy DPS evaluation is simply an optimization (though an */
319 /* important one), so if in doubt, leave it out. */
320 /*-----------------------------------------------------------------*/
322 _startLazyDPSEvaluation (void)
326 #ifdef BETTER_LITERAL_SHIFT
333 /*-----------------------------------------------------------------*/
334 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
335 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /*-----------------------------------------------------------------*/
347 if (_desiredDPS != _currentDPS)
351 emitcode ("inc", "dps");
355 emitcode ("dec", "dps");
357 _currentDPS = _desiredDPS;
361 /*-----------------------------------------------------------------*/
362 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
364 /* Forces us back to the safe state (standard DPTR selected). */
365 /*-----------------------------------------------------------------*/
367 _endLazyDPSEvaluation (void)
369 #ifdef BETTER_LITERAL_SHIFT
388 /*-----------------------------------------------------------------*/
389 /* pointerCode - returns the code for a pointer type */
390 /*-----------------------------------------------------------------*/
392 pointerCode (sym_link * etype)
395 return PTR_TYPE (SPEC_OCLS (etype));
399 /*-----------------------------------------------------------------*/
400 /* aopForSym - for a true symbol */
401 /*-----------------------------------------------------------------*/
403 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
406 memmap *space = SPEC_OCLS (sym->etype);
408 /* if already has one */
412 /* assign depending on the storage class */
413 /* if it is on the stack or indirectly addressable */
414 /* space we need to assign either r0 or r1 to it */
415 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417 sym->aop = aop = newAsmop (0);
418 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
419 aop->size = getSize (sym->type);
421 /* now assign the address of the variable to
422 the pointer register */
423 if (aop->type != AOP_STK)
429 emitcode ("push", "acc");
431 emitcode ("mov", "a,_bp");
432 emitcode ("add", "a,#0x%02x",
434 ((char) (sym->stack - _G.nRegsSaved)) :
435 ((char) sym->stack)) & 0xff);
436 emitcode ("mov", "%s,a",
437 aop->aopu.aop_ptr->name);
440 emitcode ("pop", "acc");
443 emitcode ("mov", "%s,#%s",
444 aop->aopu.aop_ptr->name,
446 aop->paged = space->paged;
449 aop->aopu.aop_stk = sym->stack;
453 if (sym->onStack && options.stack10bit)
455 /* It's on the 10 bit stack, which is located in
460 emitcode ("push", "acc");
462 emitcode ("mov", "a,_bp");
463 emitcode ("add", "a,#0x%02x",
465 ((char) (sym->stack - _G.nRegsSaved)) :
466 ((char) sym->stack)) & 0xff);
470 if (options.model == MODEL_FLAT24)
471 emitcode ("mov", "dpx1,#0x40");
473 emitcode ("mov", "dph1,#0x00");
474 emitcode ("mov", "dpl1, a");
478 if (options.model == MODEL_FLAT24)
479 emitcode ("mov", "dpx,#0x40");
480 emitcode ("mov", "dph,#0x00");
481 emitcode ("mov", "dpl, a");
485 emitcode ("pop", "acc");
487 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
488 aop->size = getSize (sym->type);
492 /* if in bit space */
493 if (IN_BITSPACE (space))
495 sym->aop = aop = newAsmop (AOP_CRY);
496 aop->aopu.aop_dir = sym->rname;
497 aop->size = getSize (sym->type);
500 /* if it is in direct space */
501 if (IN_DIRSPACE (space))
503 sym->aop = aop = newAsmop (AOP_DIR);
504 aop->aopu.aop_dir = sym->rname;
505 aop->size = getSize (sym->type);
509 /* special case for a function */
510 if (IS_FUNC (sym->type))
512 sym->aop = aop = newAsmop (AOP_IMMD);
513 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
514 strcpy (aop->aopu.aop_immd, sym->rname);
515 aop->size = FPTRSIZE;
519 /* only remaining is far space */
520 /* in which case DPTR gets the address */
521 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
526 emitcode ("mov", "dptr,#%s", sym->rname);
531 emitcode ("mov", "dptr,#%s", sym->rname);
533 aop->size = getSize (sym->type);
535 /* if it is in code space */
536 if (IN_CODESPACE (space))
542 /*-----------------------------------------------------------------*/
543 /* aopForRemat - rematerialzes an object */
544 /*-----------------------------------------------------------------*/
546 aopForRemat (symbol * sym)
548 iCode *ic = sym->rematiCode;
549 asmop *aop = newAsmop (AOP_IMMD);
556 val += (int) operandLitValue (IC_RIGHT (ic));
557 else if (ic->op == '-')
558 val -= (int) operandLitValue (IC_RIGHT (ic));
562 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
566 sprintf (buffer, "(%s %c 0x%04x)",
567 OP_SYMBOL (IC_LEFT (ic))->rname,
568 val >= 0 ? '+' : '-',
571 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
573 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
574 strcpy (aop->aopu.aop_immd, buffer);
578 /*-----------------------------------------------------------------*/
579 /* regsInCommon - two operands have some registers in common */
580 /*-----------------------------------------------------------------*/
582 regsInCommon (operand * op1, operand * op2)
587 /* if they have registers in common */
588 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
591 sym1 = OP_SYMBOL (op1);
592 sym2 = OP_SYMBOL (op2);
594 if (sym1->nRegs == 0 || sym2->nRegs == 0)
597 for (i = 0; i < sym1->nRegs; i++)
603 for (j = 0; j < sym2->nRegs; j++)
608 if (sym2->regs[j] == sym1->regs[i])
616 /*-----------------------------------------------------------------*/
617 /* operandsEqu - equivalent */
618 /*-----------------------------------------------------------------*/
620 operandsEqu (operand * op1, operand * op2)
624 /* if they not symbols */
625 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
628 sym1 = OP_SYMBOL (op1);
629 sym2 = OP_SYMBOL (op2);
631 /* if both are itemps & one is spilt
632 and the other is not then false */
633 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
634 sym1->isspilt != sym2->isspilt)
637 /* if they are the same */
641 if (strcmp (sym1->rname, sym2->rname) == 0)
645 /* if left is a tmp & right is not */
646 if (IS_ITEMP (op1) &&
649 (sym1->usl.spillLoc == sym2))
652 if (IS_ITEMP (op2) &&
656 (sym2->usl.spillLoc == sym1))
662 /*-----------------------------------------------------------------*/
663 /* sameRegs - two asmops have the same registers */
664 /*-----------------------------------------------------------------*/
666 sameRegs (asmop * aop1, asmop * aop2)
672 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
679 if (aop1->type != AOP_REG ||
680 aop2->type != AOP_REG)
683 if (aop1->size != aop2->size)
686 for (i = 0; i < aop1->size; i++)
687 if (aop1->aopu.aop_reg[i] !=
688 aop2->aopu.aop_reg[i])
694 /*-----------------------------------------------------------------*/
695 /* aopOp - allocates an asmop for an operand : */
696 /*-----------------------------------------------------------------*/
698 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
707 /* if this a literal */
708 if (IS_OP_LITERAL (op))
710 op->aop = aop = newAsmop (AOP_LIT);
711 aop->aopu.aop_lit = op->operand.valOperand;
712 aop->size = getSize (operandType (op));
716 /* if already has a asmop then continue */
720 /* if the underlying symbol has a aop */
721 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
723 op->aop = OP_SYMBOL (op)->aop;
727 /* if this is a true symbol */
728 if (IS_TRUE_SYMOP (op))
730 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
734 /* this is a temporary : this has
740 e) can be a return use only */
742 sym = OP_SYMBOL (op);
745 /* if the type is a conditional */
746 if (sym->regType == REG_CND)
748 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
753 /* if it is spilt then two situations
755 b) has a spill location */
756 if (sym->isspilt || sym->nRegs == 0)
759 /* rematerialize it NOW */
762 sym->aop = op->aop = aop =
764 aop->size = getSize (sym->type);
771 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
772 aop->size = getSize (sym->type);
773 for (i = 0; i < 2; i++)
774 aop->aopu.aop_str[i] = accUse[i];
784 /* a AOP_STR uses DPTR, but DPTR is already in use;
787 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
790 aop = op->aop = sym->aop = newAsmop (AOP_STR);
791 aop->size = getSize (sym->type);
792 for (i = 0; i < (int) fReturnSizeDS390; i++)
793 aop->aopu.aop_str[i] = fReturn[i];
797 /* else spill location */
798 sym->aop = op->aop = aop =
799 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
800 aop->size = getSize (sym->type);
804 /* must be in a register */
805 sym->aop = op->aop = aop = newAsmop (AOP_REG);
806 aop->size = sym->nRegs;
807 for (i = 0; i < sym->nRegs; i++)
808 aop->aopu.aop_reg[i] = sym->regs[i];
811 /*-----------------------------------------------------------------*/
812 /* freeAsmop - free up the asmop given to an operand */
813 /*----------------------------------------------------------------*/
815 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
832 /* depending on the asmop type only three cases need work AOP_RO
833 , AOP_R1 && AOP_STK */
841 emitcode ("pop", "ar0");
845 bitVectUnSetBit (ic->rUsed, R0_IDX);
853 emitcode ("pop", "ar1");
857 bitVectUnSetBit (ic->rUsed, R1_IDX);
863 int stk = aop->aopu.aop_stk + aop->size;
864 bitVectUnSetBit (ic->rUsed, R0_IDX);
865 bitVectUnSetBit (ic->rUsed, R1_IDX);
867 getFreePtr (ic, &aop, FALSE);
869 if (options.stack10bit)
871 /* I'm not sure what to do here yet... */
874 "*** Warning: probably generating bad code for "
875 "10 bit stack mode.\n");
880 emitcode ("mov", "a,_bp");
881 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
882 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
886 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
891 emitcode ("pop", "acc");
892 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
895 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
898 freeAsmop (op, NULL, ic, TRUE);
901 emitcode ("pop", "ar0");
907 emitcode ("pop", "ar1");
914 /* all other cases just dealloc */
920 OP_SYMBOL (op)->aop = NULL;
921 /* if the symbol has a spill */
923 SPIL_LOC (op)->aop = NULL;
928 /*------------------------------------------------------------------*/
929 /* aopGet - for fetching value of the aop */
931 /* Set canClobberACC if you are sure it is OK to clobber the value */
932 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
933 /* just less efficient. */
934 /*------------------------------------------------------------------*/
946 /* offset is greater than
948 if (offset > (aop->size - 1) &&
949 aop->type != AOP_LIT)
952 /* depending on type */
958 /* if we need to increment it */
959 while (offset > aop->coff)
961 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
965 while (offset < aop->coff)
967 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
974 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
975 return (dname ? "acc" : "a");
977 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
978 rs = Safe_calloc (1, strlen (s) + 1);
985 if (aop->type == AOP_DPTR2)
991 emitcode ("xch", "a, %s", DP2_RESULT_REG);
997 while (offset > aop->coff)
999 emitcode ("inc", "dptr");
1003 while (offset < aop->coff)
1005 emitcode ("lcall", "__decdptr");
1012 emitcode ("clr", "a");
1013 emitcode ("movc", "a,@a+dptr");
1017 emitcode ("movx", "a,@dptr");
1020 if (aop->type == AOP_DPTR2)
1026 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1027 return DP2_RESULT_REG;
1030 return (dname ? "acc" : "a");
1034 sprintf (s, "#%s", aop->aopu.aop_immd);
1036 sprintf (s, "#(%s >> %d)",
1041 aop->aopu.aop_immd);
1042 rs = Safe_calloc (1, strlen (s) + 1);
1048 sprintf (s, "(%s + %d)",
1052 sprintf (s, "%s", aop->aopu.aop_dir);
1053 rs = Safe_calloc (1, strlen (s) + 1);
1059 return aop->aopu.aop_reg[offset]->dname;
1061 return aop->aopu.aop_reg[offset]->name;
1064 emitcode ("clr", "a");
1065 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1066 emitcode ("rlc", "a");
1067 return (dname ? "acc" : "a");
1070 if (!offset && dname)
1072 return aop->aopu.aop_str[offset];
1075 return aopLiteral (aop->aopu.aop_lit, offset);
1079 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1083 return aop->aopu.aop_str[offset];
1087 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1088 "aopget got unsupported aop->type");
1091 /*-----------------------------------------------------------------*/
1092 /* aopPut - puts a string for a aop */
1093 /*-----------------------------------------------------------------*/
1095 aopPut (asmop * aop, char *s, int offset)
1099 if (aop->size && offset > (aop->size - 1))
1101 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1102 "aopPut got offset > aop->size");
1106 /* will assign value to value */
1107 /* depending on where it is ofcourse */
1112 sprintf (d, "(%s + %d)",
1113 aop->aopu.aop_dir, offset);
1115 sprintf (d, "%s", aop->aopu.aop_dir);
1118 emitcode ("mov", "%s,%s", d, s);
1123 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1124 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1127 strcmp (s, "r0") == 0 ||
1128 strcmp (s, "r1") == 0 ||
1129 strcmp (s, "r2") == 0 ||
1130 strcmp (s, "r3") == 0 ||
1131 strcmp (s, "r4") == 0 ||
1132 strcmp (s, "r5") == 0 ||
1133 strcmp (s, "r6") == 0 ||
1134 strcmp (s, "r7") == 0)
1135 emitcode ("mov", "%s,%s",
1136 aop->aopu.aop_reg[offset]->dname, s);
1138 emitcode ("mov", "%s,%s",
1139 aop->aopu.aop_reg[offset]->name, s);
1146 if (aop->type == AOP_DPTR2)
1154 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1155 "aopPut writting to code space");
1159 while (offset > aop->coff)
1162 emitcode ("inc", "dptr");
1165 while (offset < aop->coff)
1168 emitcode ("lcall", "__decdptr");
1173 /* if not in accumulater */
1176 emitcode ("movx", "@dptr,a");
1178 if (aop->type == AOP_DPTR2)
1186 while (offset > aop->coff)
1189 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1191 while (offset < aop->coff)
1194 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1201 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1207 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1209 else if (strcmp (s, "r0") == 0 ||
1210 strcmp (s, "r1") == 0 ||
1211 strcmp (s, "r2") == 0 ||
1212 strcmp (s, "r3") == 0 ||
1213 strcmp (s, "r4") == 0 ||
1214 strcmp (s, "r5") == 0 ||
1215 strcmp (s, "r6") == 0 ||
1216 strcmp (s, "r7") == 0)
1219 sprintf (buffer, "a%s", s);
1220 emitcode ("mov", "@%s,%s",
1221 aop->aopu.aop_ptr->name, buffer);
1224 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1229 if (strcmp (s, "a") == 0)
1230 emitcode ("push", "acc");
1232 emitcode ("push", "%s", s);
1237 /* if bit variable */
1238 if (!aop->aopu.aop_dir)
1240 emitcode ("clr", "a");
1241 emitcode ("rlc", "a");
1246 emitcode ("clr", "%s", aop->aopu.aop_dir);
1248 emitcode ("setb", "%s", aop->aopu.aop_dir);
1249 else if (!strcmp (s, "c"))
1250 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1253 if (strcmp (s, "a"))
1258 symbol *lbl = newiTempLabel (NULL);
1259 emitcode ("clr", "c");
1260 emitcode ("jz", "%05d$", lbl->key + 100);
1261 emitcode ("cpl", "c");
1262 emitcode ("", "%05d$:", lbl->key + 100);
1263 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1271 if (strcmp (aop->aopu.aop_str[offset], s))
1272 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1277 if (!offset && (strcmp (s, "acc") == 0))
1280 if (strcmp (aop->aopu.aop_str[offset], s))
1281 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286 "aopPut got unsupported aop->type");
1293 /*--------------------------------------------------------------------*/
1294 /* reAdjustPreg - points a register back to where it should (coff==0) */
1295 /*--------------------------------------------------------------------*/
1297 reAdjustPreg (asmop * aop)
1299 if ((aop->coff==0) || (aop->size <= 1)) {
1308 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1312 if (aop->type == AOP_DPTR2)
1319 emitcode ("lcall", "__decdptr");
1322 if (aop->type == AOP_DPTR2)
1332 #define AOP(op) op->aop
1333 #define AOP_TYPE(op) AOP(op)->type
1334 #define AOP_SIZE(op) AOP(op)->size
1335 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1336 AOP_TYPE(x) == AOP_R0))
1338 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1339 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1342 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1343 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1344 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1346 /* Workaround for DS80C390 bug: div ab may return bogus results
1347 * if A is accessed in instruction immediately before the div.
1349 * Will be fixed in B4 rev of processor, Dallas claims.
1352 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1353 if (!AOP_NEEDSACC(RIGHT)) \
1355 /* We can load A first, then B, since \
1356 * B (the RIGHT operand) won't clobber A, \
1357 * thus avoiding touching A right before the div. \
1359 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1360 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1362 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1366 /* Just stuff in a nop after loading A. */ \
1367 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1368 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1370 emitcode("nop", "; workaround for DS80C390 div bug."); \
1373 /*-----------------------------------------------------------------*/
1374 /* genNotFloat - generates not for float operations */
1375 /*-----------------------------------------------------------------*/
1377 genNotFloat (operand * op, operand * res)
1383 D (emitcode (";", "genNotFloat ");
1386 /* we will put 127 in the first byte of
1388 aopPut (AOP (res), "#127", 0);
1389 size = AOP_SIZE (op) - 1;
1392 _startLazyDPSEvaluation ();
1393 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1398 emitcode ("orl", "a,%s",
1400 offset++, FALSE, FALSE, FALSE));
1402 _endLazyDPSEvaluation ();
1404 tlbl = newiTempLabel (NULL);
1405 aopPut (res->aop, one, 1);
1406 emitcode ("jz", "%05d$", (tlbl->key + 100));
1407 aopPut (res->aop, zero, 1);
1408 emitcode ("", "%05d$:", (tlbl->key + 100));
1410 size = res->aop->size - 2;
1412 /* put zeros in the rest */
1414 aopPut (res->aop, zero, offset++);
1417 /*-----------------------------------------------------------------*/
1418 /* opIsGptr: returns non-zero if the passed operand is */
1419 /* a generic pointer type. */
1420 /*-----------------------------------------------------------------*/
1422 opIsGptr (operand * op)
1424 sym_link *type = operandType (op);
1426 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1433 /*-----------------------------------------------------------------*/
1434 /* getDataSize - get the operand data size */
1435 /*-----------------------------------------------------------------*/
1437 getDataSize (operand * op)
1440 size = AOP_SIZE (op);
1441 if (size == GPTRSIZE)
1443 sym_link *type = operandType (op);
1444 if (IS_GENPTR (type))
1446 /* generic pointer; arithmetic operations
1447 * should ignore the high byte (pointer type).
1455 /*-----------------------------------------------------------------*/
1456 /* outAcc - output Acc */
1457 /*-----------------------------------------------------------------*/
1459 outAcc (operand * result)
1462 size = getDataSize (result);
1465 aopPut (AOP (result), "a", 0);
1468 /* unsigned or positive */
1471 aopPut (AOP (result), zero, offset++);
1476 /*-----------------------------------------------------------------*/
1477 /* outBitC - output a bit C */
1478 /*-----------------------------------------------------------------*/
1480 outBitC (operand * result)
1482 /* if the result is bit */
1483 if (AOP_TYPE (result) == AOP_CRY)
1485 aopPut (AOP (result), "c", 0);
1489 emitcode ("clr", "a");
1490 emitcode ("rlc", "a");
1495 /*-----------------------------------------------------------------*/
1496 /* toBoolean - emit code for orl a,operator(sizeop) */
1497 /*-----------------------------------------------------------------*/
1499 toBoolean (operand * oper)
1501 int size = AOP_SIZE (oper) - 1;
1505 /* The generic part of a generic pointer should
1506 * not participate in it's truth value.
1508 * i.e. 0x10000000 is zero.
1510 if (opIsGptr (oper))
1512 D (emitcode (";", "toBoolean: generic ptr special case.");
1517 _startLazyDPSEvaluation ();
1518 if (AOP_NEEDSACC (oper) && size)
1521 emitcode ("push", "b");
1522 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1526 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1532 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1536 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1539 _endLazyDPSEvaluation ();
1543 emitcode ("mov", "a,b");
1544 emitcode ("pop", "b");
1549 /*-----------------------------------------------------------------*/
1550 /* genNot - generate code for ! operation */
1551 /*-----------------------------------------------------------------*/
1556 sym_link *optype = operandType (IC_LEFT (ic));
1558 D (emitcode (";", "genNot ");
1561 /* assign asmOps to operand & result */
1562 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1563 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1565 /* if in bit space then a special case */
1566 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1568 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1569 emitcode ("cpl", "c");
1570 outBitC (IC_RESULT (ic));
1574 /* if type float then do float */
1575 if (IS_FLOAT (optype))
1577 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1581 toBoolean (IC_LEFT (ic));
1583 tlbl = newiTempLabel (NULL);
1584 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1585 emitcode ("", "%05d$:", tlbl->key + 100);
1586 outBitC (IC_RESULT (ic));
1589 /* release the aops */
1590 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1591 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1595 /*-----------------------------------------------------------------*/
1596 /* genCpl - generate code for complement */
1597 /*-----------------------------------------------------------------*/
1604 D (emitcode (";", "genCpl ");
1608 /* assign asmOps to operand & result */
1609 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1610 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1612 /* if both are in bit space then
1614 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1615 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1618 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1619 emitcode ("cpl", "c");
1620 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1624 size = AOP_SIZE (IC_RESULT (ic));
1625 _startLazyDPSEvaluation ();
1628 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1630 emitcode ("cpl", "a");
1631 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1633 _endLazyDPSEvaluation ();
1637 /* release the aops */
1638 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1639 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1642 /*-----------------------------------------------------------------*/
1643 /* genUminusFloat - unary minus for floating points */
1644 /*-----------------------------------------------------------------*/
1646 genUminusFloat (operand * op, operand * result)
1648 int size, offset = 0;
1650 /* for this we just need to flip the
1651 first it then copy the rest in place */
1652 D (emitcode (";", "genUminusFloat");
1655 _startLazyDPSEvaluation ();
1656 size = AOP_SIZE (op) - 1;
1657 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1660 emitcode ("cpl", "acc.7");
1661 aopPut (AOP (result), "a", 3);
1665 aopPut (AOP (result),
1666 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1670 _endLazyDPSEvaluation ();
1673 /*-----------------------------------------------------------------*/
1674 /* genUminus - unary minus code generation */
1675 /*-----------------------------------------------------------------*/
1677 genUminus (iCode * ic)
1680 sym_link *optype, *rtype;
1682 D (emitcode (";", "genUminus ");
1687 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1688 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1690 /* if both in bit space then special
1692 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1693 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1696 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1697 emitcode ("cpl", "c");
1698 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1702 optype = operandType (IC_LEFT (ic));
1703 rtype = operandType (IC_RESULT (ic));
1705 /* if float then do float stuff */
1706 if (IS_FLOAT (optype))
1708 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1712 /* otherwise subtract from zero */
1713 size = AOP_SIZE (IC_LEFT (ic));
1715 _startLazyDPSEvaluation ();
1718 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1719 if (!strcmp (l, "a"))
1723 emitcode ("cpl", "a");
1724 emitcode ("addc", "a,#0");
1730 emitcode ("clr", "a");
1731 emitcode ("subb", "a,%s", l);
1733 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1735 _endLazyDPSEvaluation ();
1737 /* if any remaining bytes in the result */
1738 /* we just need to propagate the sign */
1739 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1741 emitcode ("rlc", "a");
1742 emitcode ("subb", "a,acc");
1744 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1748 /* release the aops */
1749 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1750 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1753 /*-----------------------------------------------------------------*/
1754 /* saveRegisters - will look for a call and save the registers */
1755 /*-----------------------------------------------------------------*/
1757 saveRegisters (iCode * lic)
1765 for (ic = lic; ic; ic = ic->next)
1766 if (ic->op == CALL || ic->op == PCALL)
1771 fprintf (stderr, "found parameter push with no function call\n");
1775 /* if the registers have been saved already then
1777 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1778 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1781 /* find the registers in use at this time
1782 and push them away to safety */
1783 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1787 if (options.useXstack)
1789 if (bitVectBitValue (rsave, R0_IDX))
1790 emitcode ("mov", "b,r0");
1791 emitcode ("mov", "r0,%s", spname);
1792 for (i = 0; i < ds390_nRegs; i++)
1794 if (bitVectBitValue (rsave, i))
1797 emitcode ("mov", "a,b");
1799 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1800 emitcode ("movx", "@r0,a");
1801 emitcode ("inc", "r0");
1804 emitcode ("mov", "%s,r0", spname);
1805 if (bitVectBitValue (rsave, R0_IDX))
1806 emitcode ("mov", "r0,b");
1809 for (i = 0; i < ds390_nRegs; i++)
1811 if (bitVectBitValue (rsave, i))
1812 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1815 detype = getSpec (operandType (IC_LEFT (ic)));
1818 /*-----------------------------------------------------------------*/
1819 /* unsaveRegisters - pop the pushed registers */
1820 /*-----------------------------------------------------------------*/
1822 unsaveRegisters (iCode * ic)
1826 /* find the registers in use at this time
1827 and push them away to safety */
1828 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1831 if (options.useXstack)
1833 emitcode ("mov", "r0,%s", spname);
1834 for (i = ds390_nRegs; i >= 0; i--)
1836 if (bitVectBitValue (rsave, i))
1838 emitcode ("dec", "r0");
1839 emitcode ("movx", "a,@r0");
1841 emitcode ("mov", "b,a");
1843 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1847 emitcode ("mov", "%s,r0", spname);
1848 if (bitVectBitValue (rsave, R0_IDX))
1849 emitcode ("mov", "r0,b");
1852 for (i = ds390_nRegs; i >= 0; i--)
1854 if (bitVectBitValue (rsave, i))
1855 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1861 /*-----------------------------------------------------------------*/
1863 /*-----------------------------------------------------------------*/
1865 pushSide (operand * oper, int size)
1868 _startLazyDPSEvaluation ();
1871 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1872 if (AOP_TYPE (oper) != AOP_REG &&
1873 AOP_TYPE (oper) != AOP_DIR &&
1876 emitcode ("mov", "a,%s", l);
1877 emitcode ("push", "acc");
1880 emitcode ("push", "%s", l);
1882 _endLazyDPSEvaluation ();
1885 /*-----------------------------------------------------------------*/
1886 /* assignResultValue - */
1887 /*-----------------------------------------------------------------*/
1889 assignResultValue (operand * oper)
1892 int size = AOP_SIZE (oper);
1894 _startLazyDPSEvaluation ();
1897 aopPut (AOP (oper), fReturn[offset], offset);
1900 _endLazyDPSEvaluation ();
1904 /*-----------------------------------------------------------------*/
1905 /* genXpush - pushes onto the external stack */
1906 /*-----------------------------------------------------------------*/
1908 genXpush (iCode * ic)
1910 asmop *aop = newAsmop (0);
1912 int size, offset = 0;
1914 D (emitcode (";", "genXpush ");
1917 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1918 r = getFreePtr (ic, &aop, FALSE);
1921 emitcode ("mov", "%s,_spx", r->name);
1923 size = AOP_SIZE (IC_LEFT (ic));
1924 _startLazyDPSEvaluation ();
1928 char *l = aopGet (AOP (IC_LEFT (ic)),
1929 offset++, FALSE, FALSE, TRUE);
1931 emitcode ("movx", "@%s,a", r->name);
1932 emitcode ("inc", "%s", r->name);
1935 _endLazyDPSEvaluation ();
1938 emitcode ("mov", "_spx,%s", r->name);
1940 freeAsmop (NULL, aop, ic, TRUE);
1941 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1944 /*-----------------------------------------------------------------*/
1945 /* genIpush - genrate code for pushing this gets a little complex */
1946 /*-----------------------------------------------------------------*/
1948 genIpush (iCode * ic)
1950 int size, offset = 0;
1953 D (emitcode (";", "genIpush ");
1956 /* if this is not a parm push : ie. it is spill push
1957 and spill push is always done on the local stack */
1961 /* and the item is spilt then do nothing */
1962 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1965 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1966 size = AOP_SIZE (IC_LEFT (ic));
1967 /* push it on the stack */
1968 _startLazyDPSEvaluation ();
1971 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1977 emitcode ("push", "%s", l);
1979 _endLazyDPSEvaluation ();
1983 /* this is a paramter push: in this case we call
1984 the routine to find the call and save those
1985 registers that need to be saved */
1988 /* if use external stack then call the external
1989 stack pushing routine */
1990 if (options.useXstack)
1996 /* then do the push */
1997 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1999 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2000 size = AOP_SIZE (IC_LEFT (ic));
2002 _startLazyDPSEvaluation ();
2005 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2006 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2007 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2010 emitcode ("mov", "a,%s", l);
2011 emitcode ("push", "acc");
2014 emitcode ("push", "%s", l);
2016 _endLazyDPSEvaluation ();
2018 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2021 /*-----------------------------------------------------------------*/
2022 /* genIpop - recover the registers: can happen only for spilling */
2023 /*-----------------------------------------------------------------*/
2025 genIpop (iCode * ic)
2029 D (emitcode (";", "genIpop ");
2033 /* if the temp was not pushed then */
2034 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2037 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2038 size = AOP_SIZE (IC_LEFT (ic));
2039 offset = (size - 1);
2040 _startLazyDPSEvaluation ();
2043 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2044 FALSE, TRUE, TRUE));
2046 _endLazyDPSEvaluation ();
2048 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2051 /*-----------------------------------------------------------------*/
2052 /* unsaveRBank - restores the resgister bank from stack */
2053 /*-----------------------------------------------------------------*/
2055 unsaveRBank (int bank, iCode * ic, bool popPsw)
2061 if (options.useXstack)
2065 /* Assume r0 is available for use. */
2066 r = ds390_regWithIdx (R0_IDX);;
2071 r = getFreePtr (ic, &aop, FALSE);
2073 emitcode ("mov", "%s,_spx", r->name);
2078 if (options.useXstack)
2080 emitcode ("movx", "a,@%s", r->name);
2081 emitcode ("mov", "psw,a");
2082 emitcode ("dec", "%s", r->name);
2086 emitcode ("pop", "psw");
2090 for (i = (ds390_nRegs - 1); i >= 0; i--)
2092 if (options.useXstack)
2094 emitcode ("movx", "a,@%s", r->name);
2095 emitcode ("mov", "(%s+%d),a",
2096 regs390[i].base, 8 * bank + regs390[i].offset);
2097 emitcode ("dec", "%s", r->name);
2101 emitcode ("pop", "(%s+%d)",
2102 regs390[i].base, 8 * bank + regs390[i].offset);
2105 if (options.useXstack)
2107 emitcode ("mov", "_spx,%s", r->name);
2112 freeAsmop (NULL, aop, ic, TRUE);
2116 /*-----------------------------------------------------------------*/
2117 /* saveRBank - saves an entire register bank on the stack */
2118 /*-----------------------------------------------------------------*/
2120 saveRBank (int bank, iCode * ic, bool pushPsw)
2126 if (options.useXstack)
2130 /* Assume r0 is available for use. */
2131 r = ds390_regWithIdx (R0_IDX);;
2136 r = getFreePtr (ic, &aop, FALSE);
2138 emitcode ("mov", "%s,_spx", r->name);
2141 for (i = 0; i < ds390_nRegs; i++)
2143 if (options.useXstack)
2145 emitcode ("inc", "%s", r->name);
2146 emitcode ("mov", "a,(%s+%d)",
2147 regs390[i].base, 8 * bank + regs390[i].offset);
2148 emitcode ("movx", "@%s,a", r->name);
2151 emitcode ("push", "(%s+%d)",
2152 regs390[i].base, 8 * bank + regs390[i].offset);
2157 if (options.useXstack)
2159 emitcode ("mov", "a,psw");
2160 emitcode ("movx", "@%s,a", r->name);
2161 emitcode ("inc", "%s", r->name);
2162 emitcode ("mov", "_spx,%s", r->name);
2166 emitcode ("push", "psw");
2169 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2174 freeAsmop (NULL, aop, ic, TRUE);
2183 /*-----------------------------------------------------------------*/
2184 /* genCall - generates a call statement */
2185 /*-----------------------------------------------------------------*/
2187 genCall (iCode * ic)
2190 bool restoreBank = FALSE;
2191 bool swapBanks = FALSE;
2193 D (emitcode (";", "genCall "););
2195 /* if we are calling a not _naked function that is not using
2196 the same register bank then we need to save the
2197 destination registers on the stack */
2198 dtype = operandType (IC_LEFT (ic));
2199 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2200 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2201 IFFUNC_ISISR (currFunc->type))
2205 /* This is unexpected; the bank should have been saved in
2208 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2214 /* if caller saves & we have not saved then */
2218 /* if send set is not empty the assign */
2219 /* We've saved all the registers we care about;
2220 * therefore, we may clobber any register not used
2221 * in the calling convention (i.e. anything not in
2228 for (sic = setFirstItem (_G.sendSet); sic;
2229 sic = setNextItem (_G.sendSet))
2231 int size, offset = 0;
2233 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2234 size = AOP_SIZE (IC_LEFT (sic));
2236 _startLazyDPSEvaluation ();
2239 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2240 FALSE, FALSE, TRUE);
2241 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2243 emitcode("mov", "%s,%s", regs390[offset].name, l);
2245 else if (strcmp (l, fReturn[offset]))
2247 emitcode ("mov", "%s,%s",
2253 _endLazyDPSEvaluation ();
2254 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2256 size = AOP_SIZE (IC_LEFT (sic));
2264 emitcode("mov", "%s,%s",
2265 fReturn[size], regs390[size].name);
2268 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2275 emitcode ("mov", "psw,#0x%02x",
2276 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2280 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2281 OP_SYMBOL (IC_LEFT (ic))->rname :
2282 OP_SYMBOL (IC_LEFT (ic))->name));
2286 emitcode ("mov", "psw,#0x%02x",
2287 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2290 /* if we need assign a result value */
2291 if ((IS_ITEMP (IC_RESULT (ic)) &&
2292 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2293 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2294 IS_TRUE_SYMOP (IC_RESULT (ic)))
2296 if (isOperandInFarSpace (IC_RESULT (ic))
2297 && getSize (operandType (IC_RESULT (ic))) <= 2)
2299 int size = getSize (operandType (IC_RESULT (ic)));
2301 /* Special case for 1 or 2 byte return in far space. */
2305 emitcode ("mov", "b,%s", fReturn[1]);
2308 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2309 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2313 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2315 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2320 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2323 assignResultValue (IC_RESULT (ic));
2325 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2329 /* adjust the stack for parameters if
2334 if (ic->parmBytes > 3)
2336 emitcode ("mov", "a,%s", spname);
2337 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2338 emitcode ("mov", "%s,a", spname);
2341 for (i = 0; i < ic->parmBytes; i++)
2342 emitcode ("dec", "%s", spname);
2345 /* if we hade saved some registers then unsave them */
2346 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2347 unsaveRegisters (ic);
2349 /* if register bank was saved then pop them */
2351 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2354 /*-----------------------------------------------------------------*/
2355 /* genPcall - generates a call by pointer statement */
2356 /*-----------------------------------------------------------------*/
2358 genPcall (iCode * ic)
2361 symbol *rlbl = newiTempLabel (NULL);
2363 D (emitcode (";", "genPcall ");
2367 /* if caller saves & we have not saved then */
2371 /* if we are calling a function that is not using
2372 the same register bank then we need to save the
2373 destination registers on the stack */
2374 dtype = operandType (IC_LEFT (ic));
2376 IFFUNC_ISISR (currFunc->type) &&
2377 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2378 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2381 /* push the return address on to the stack */
2382 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2383 emitcode ("push", "acc");
2384 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2385 emitcode ("push", "acc");
2387 if (options.model == MODEL_FLAT24)
2389 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2390 emitcode ("push", "acc");
2393 /* now push the calling address */
2394 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2396 pushSide (IC_LEFT (ic), FPTRSIZE);
2398 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2400 /* if send set is not empty the assign */
2405 for (sic = setFirstItem (_G.sendSet); sic;
2406 sic = setNextItem (_G.sendSet))
2408 int size, offset = 0;
2410 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2411 size = AOP_SIZE (IC_LEFT (sic));
2412 _startLazyDPSEvaluation ();
2415 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2416 FALSE, FALSE, TRUE);
2417 if (strcmp (l, fReturn[offset]))
2419 emitcode ("mov", "%s,%s",
2425 _endLazyDPSEvaluation ();
2426 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2431 emitcode ("ret", "");
2432 emitcode ("", "%05d$:", (rlbl->key + 100));
2435 /* if we need assign a result value */
2436 if ((IS_ITEMP (IC_RESULT (ic)) &&
2437 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2438 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2439 IS_TRUE_SYMOP (IC_RESULT (ic)))
2443 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2446 assignResultValue (IC_RESULT (ic));
2448 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2451 /* adjust the stack for parameters if
2456 if (ic->parmBytes > 3)
2458 emitcode ("mov", "a,%s", spname);
2459 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2460 emitcode ("mov", "%s,a", spname);
2463 for (i = 0; i < ic->parmBytes; i++)
2464 emitcode ("dec", "%s", spname);
2468 /* if register bank was saved then unsave them */
2470 (FUNC_REGBANK (currFunc->type) !=
2471 FUNC_REGBANK (dtype)))
2472 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2474 /* if we hade saved some registers then
2477 unsaveRegisters (ic);
2481 /*-----------------------------------------------------------------*/
2482 /* resultRemat - result is rematerializable */
2483 /*-----------------------------------------------------------------*/
2485 resultRemat (iCode * ic)
2487 if (SKIP_IC (ic) || ic->op == IFX)
2490 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2492 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2493 if (sym->remat && !POINTER_SET (ic))
2500 #if defined(__BORLANDC__) || defined(_MSC_VER)
2501 #define STRCASECMP stricmp
2503 #define STRCASECMP strcasecmp
2506 /*-----------------------------------------------------------------*/
2507 /* inExcludeList - return 1 if the string is in exclude Reg list */
2508 /*-----------------------------------------------------------------*/
2510 inExcludeList (char *s)
2514 if (options.excludeRegs[i] &&
2515 STRCASECMP (options.excludeRegs[i], "none") == 0)
2518 for (i = 0; options.excludeRegs[i]; i++)
2520 if (options.excludeRegs[i] &&
2521 STRCASECMP (s, options.excludeRegs[i]) == 0)
2527 /*-----------------------------------------------------------------*/
2528 /* genFunction - generated code for function entry */
2529 /*-----------------------------------------------------------------*/
2531 genFunction (iCode * ic)
2535 bool switchedPSW = FALSE;
2537 D (emitcode (";", "genFunction "););
2540 /* create the function header */
2541 emitcode (";", "-----------------------------------------");
2542 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2543 emitcode (";", "-----------------------------------------");
2545 emitcode ("", "%s:", sym->rname);
2546 ftype = operandType (IC_LEFT (ic));
2548 if (IFFUNC_ISNAKED(ftype))
2550 emitcode(";", "naked function: no prologue.");
2554 /* if critical function then turn interrupts off */
2555 if (IFFUNC_ISCRITICAL (ftype))
2556 emitcode ("clr", "ea");
2558 /* here we need to generate the equates for the
2559 register bank if required */
2560 if (FUNC_REGBANK (ftype) != rbank)
2564 rbank = FUNC_REGBANK (ftype);
2565 for (i = 0; i < ds390_nRegs; i++)
2567 if (strcmp (regs390[i].base, "0") == 0)
2568 emitcode ("", "%s = 0x%02x",
2570 8 * rbank + regs390[i].offset);
2572 emitcode ("", "%s = %s + 0x%02x",
2575 8 * rbank + regs390[i].offset);
2579 /* if this is an interrupt service routine then
2580 save acc, b, dpl, dph */
2581 if (IFFUNC_ISISR (sym->type))
2584 if (!inExcludeList ("acc"))
2585 emitcode ("push", "acc");
2586 if (!inExcludeList ("b"))
2587 emitcode ("push", "b");
2588 if (!inExcludeList ("dpl"))
2589 emitcode ("push", "dpl");
2590 if (!inExcludeList ("dph"))
2591 emitcode ("push", "dph");
2592 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2594 emitcode ("push", "dpx");
2595 /* Make sure we're using standard DPTR */
2596 emitcode ("push", "dps");
2597 emitcode ("mov", "dps, #0x00");
2598 if (options.stack10bit)
2600 /* This ISR could conceivably use DPTR2. Better save it. */
2601 emitcode ("push", "dpl1");
2602 emitcode ("push", "dph1");
2603 emitcode ("push", "dpx1");
2604 emitcode ("push", DP2_RESULT_REG);
2607 /* if this isr has no bank i.e. is going to
2608 run with bank 0 , then we need to save more
2610 if (!FUNC_REGBANK (sym->type))
2613 /* if this function does not call any other
2614 function then we can be economical and
2615 save only those registers that are used */
2616 if (!IFFUNC_HASFCALL(sym->type))
2620 /* if any registers used */
2623 /* save the registers used */
2624 for (i = 0; i < sym->regsUsed->size; i++)
2626 if (bitVectBitValue (sym->regsUsed, i) ||
2627 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2628 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2635 /* this function has a function call cannot
2636 determines register usage so we will have to push the
2638 saveRBank (0, ic, FALSE);
2643 /* This ISR uses a non-zero bank.
2645 * We assume that the bank is available for our
2648 * However, if this ISR calls a function which uses some
2649 * other bank, we must save that bank entirely.
2651 unsigned long banksToSave = 0;
2653 if (IFFUNC_HASFCALL(sym->type))
2656 #define MAX_REGISTER_BANKS 4
2661 for (i = ic; i; i = i->next)
2663 if (i->op == ENDFUNCTION)
2665 /* we got to the end OK. */
2673 dtype = operandType (IC_LEFT(i));
2675 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2677 /* Mark this bank for saving. */
2678 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2680 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2684 banksToSave |= (1 << FUNC_REGBANK(dtype));
2687 /* And note that we don't need to do it in
2695 /* This is a mess; we have no idea what
2696 * register bank the called function might
2699 * The only thing I can think of to do is
2700 * throw a warning and hope.
2702 werror(W_FUNCPTR_IN_USING_ISR);
2706 if (banksToSave && options.useXstack)
2708 /* Since we aren't passing it an ic,
2709 * saveRBank will assume r0 is available to abuse.
2711 * So switch to our (trashable) bank now, so
2712 * the caller's R0 isn't trashed.
2714 emitcode ("push", "psw");
2715 emitcode ("mov", "psw,#0x%02x",
2716 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2720 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2722 if (banksToSave & (1 << ix))
2724 saveRBank(ix, NULL, FALSE);
2728 // jwk: this needs a closer look
2729 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2734 /* if callee-save to be used for this function
2735 then save the registers being used in this function */
2736 if (IFFUNC_CALLEESAVES(sym->type))
2740 /* if any registers used */
2743 /* save the registers used */
2744 for (i = 0; i < sym->regsUsed->size; i++)
2746 if (bitVectBitValue (sym->regsUsed, i) ||
2747 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2749 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2757 /* set the register bank to the desired value */
2758 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2761 emitcode ("push", "psw");
2762 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2765 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2768 if (options.useXstack)
2770 emitcode ("mov", "r0,%s", spname);
2771 emitcode ("mov", "a,_bp");
2772 emitcode ("movx", "@r0,a");
2773 emitcode ("inc", "%s", spname);
2777 /* set up the stack */
2778 emitcode ("push", "_bp"); /* save the callers stack */
2780 emitcode ("mov", "_bp,%s", spname);
2783 /* adjust the stack for the function */
2789 werror (W_STACK_OVERFLOW, sym->name);
2791 if (i > 3 && sym->recvSize < 4)
2794 emitcode ("mov", "a,sp");
2795 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2796 emitcode ("mov", "sp,a");
2801 emitcode ("inc", "sp");
2807 emitcode ("mov", "a,_spx");
2808 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2809 emitcode ("mov", "_spx,a");
2814 /*-----------------------------------------------------------------*/
2815 /* genEndFunction - generates epilogue for functions */
2816 /*-----------------------------------------------------------------*/
2818 genEndFunction (iCode * ic)
2820 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2822 D (emitcode (";", "genEndFunction "););
2824 if (IFFUNC_ISNAKED(sym->type))
2826 emitcode(";", "naked function: no epilogue.");
2830 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2832 emitcode ("mov", "%s,_bp", spname);
2835 /* if use external stack but some variables were
2836 added to the local stack then decrement the
2838 if (options.useXstack && sym->stack)
2840 emitcode ("mov", "a,sp");
2841 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2842 emitcode ("mov", "sp,a");
2846 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2848 if (options.useXstack)
2850 emitcode ("mov", "r0,%s", spname);
2851 emitcode ("movx", "a,@r0");
2852 emitcode ("mov", "_bp,a");
2853 emitcode ("dec", "%s", spname);
2857 emitcode ("pop", "_bp");
2861 /* restore the register bank */
2862 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2864 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2865 || !options.useXstack)
2867 /* Special case of ISR using non-zero bank with useXstack
2870 emitcode ("pop", "psw");
2874 if (IFFUNC_ISISR (sym->type))
2877 /* now we need to restore the registers */
2878 /* if this isr has no bank i.e. is going to
2879 run with bank 0 , then we need to save more
2881 if (!FUNC_REGBANK (sym->type))
2883 /* if this function does not call any other
2884 function then we can be economical and
2885 save only those registers that are used */
2886 if (!IFFUNC_HASFCALL(sym->type))
2890 /* if any registers used */
2893 /* save the registers used */
2894 for (i = sym->regsUsed->size; i >= 0; i--)
2896 if (bitVectBitValue (sym->regsUsed, i) ||
2897 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2898 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2905 /* this function has a function call cannot
2906 determines register usage so we will have to pop the
2908 unsaveRBank (0, ic, FALSE);
2913 /* This ISR uses a non-zero bank.
2915 * Restore any register banks saved by genFunction
2918 // jwk: this needs a closer look
2919 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2922 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2924 if (savedBanks & (1 << ix))
2926 unsaveRBank(ix, NULL, FALSE);
2930 if (options.useXstack)
2932 /* Restore bank AFTER calling unsaveRBank,
2933 * since it can trash r0.
2935 emitcode ("pop", "psw");
2939 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2941 if (options.stack10bit)
2943 emitcode ("pop", DP2_RESULT_REG);
2944 emitcode ("pop", "dpx1");
2945 emitcode ("pop", "dph1");
2946 emitcode ("pop", "dpl1");
2948 emitcode ("pop", "dps");
2949 emitcode ("pop", "dpx");
2951 if (!inExcludeList ("dph"))
2952 emitcode ("pop", "dph");
2953 if (!inExcludeList ("dpl"))
2954 emitcode ("pop", "dpl");
2955 if (!inExcludeList ("b"))
2956 emitcode ("pop", "b");
2957 if (!inExcludeList ("acc"))
2958 emitcode ("pop", "acc");
2960 if (IFFUNC_ISCRITICAL (sym->type))
2961 emitcode ("setb", "ea");
2963 /* if debug then send end of function */
2964 if (options.debug && currFunc) {
2966 emitcode ("", "C$%s$%d$%d$%d ==.",
2967 FileBaseName (ic->filename), currFunc->lastLine,
2968 ic->level, ic->block);
2969 if (IS_STATIC (currFunc->etype))
2970 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2972 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2976 emitcode ("reti", "");
2980 if (IFFUNC_ISCRITICAL (sym->type))
2981 emitcode ("setb", "ea");
2983 if (IFFUNC_CALLEESAVES(sym->type))
2987 /* if any registers used */
2990 /* save the registers used */
2991 for (i = sym->regsUsed->size; i >= 0; i--)
2993 if (bitVectBitValue (sym->regsUsed, i) ||
2994 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2995 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3001 /* if debug then send end of function */
3002 if (options.debug && currFunc)
3005 emitcode ("", "C$%s$%d$%d$%d ==.",
3006 FileBaseName (ic->filename), currFunc->lastLine,
3007 ic->level, ic->block);
3008 if (IS_STATIC (currFunc->etype))
3009 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3011 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3015 emitcode ("ret", "");
3020 /*-----------------------------------------------------------------*/
3021 /* genRet - generate code for return statement */
3022 /*-----------------------------------------------------------------*/
3026 int size, offset = 0, pushed = 0;
3028 D (emitcode (";", "genRet ");
3031 /* if we have no return value then
3032 just generate the "ret" */
3036 /* we have something to return then
3037 move the return value into place */
3038 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3039 size = AOP_SIZE (IC_LEFT (ic));
3041 _startLazyDPSEvaluation ();
3045 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3047 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3048 FALSE, TRUE, FALSE);
3049 emitcode ("push", "%s", l);
3054 /* Since A is the last element of fReturn,
3055 * is is OK to clobber it in the aopGet.
3057 l = aopGet (AOP (IC_LEFT (ic)), offset,
3058 FALSE, FALSE, TRUE);
3059 if (strcmp (fReturn[offset], l))
3060 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3063 _endLazyDPSEvaluation ();
3070 if (strcmp (fReturn[pushed], "a"))
3071 emitcode ("pop", fReturn[pushed]);
3073 emitcode ("pop", "acc");
3076 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3079 /* generate a jump to the return label
3080 if the next is not the return statement */
3081 if (!(ic->next && ic->next->op == LABEL &&
3082 IC_LABEL (ic->next) == returnLabel))
3084 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3088 /*-----------------------------------------------------------------*/
3089 /* genLabel - generates a label */
3090 /*-----------------------------------------------------------------*/
3092 genLabel (iCode * ic)
3094 /* special case never generate */
3095 if (IC_LABEL (ic) == entryLabel)
3098 D (emitcode (";", "genLabel ");
3101 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3104 /*-----------------------------------------------------------------*/
3105 /* genGoto - generates a ljmp */
3106 /*-----------------------------------------------------------------*/
3108 genGoto (iCode * ic)
3110 D (emitcode (";", "genGoto ");
3112 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3115 /*-----------------------------------------------------------------*/
3116 /* findLabelBackwards: walks back through the iCode chain looking */
3117 /* for the given label. Returns number of iCode instructions */
3118 /* between that label and given ic. */
3119 /* Returns zero if label not found. */
3120 /*-----------------------------------------------------------------*/
3122 findLabelBackwards (iCode * ic, int key)
3131 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3133 /* printf("findLabelBackwards = %d\n", count); */
3141 /*-----------------------------------------------------------------*/
3142 /* genPlusIncr :- does addition with increment if possible */
3143 /*-----------------------------------------------------------------*/
3145 genPlusIncr (iCode * ic)
3147 unsigned int icount;
3148 unsigned int size = getDataSize (IC_RESULT (ic));
3150 /* will try to generate an increment */
3151 /* if the right side is not a literal
3153 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3156 /* if the literal value of the right hand side
3157 is greater than 4 then it is not worth it */
3158 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3161 /* if increment 16 bits in register */
3163 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3164 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3165 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3173 /* If the next instruction is a goto and the goto target
3174 * is <= 5 instructions previous to this, we can generate
3175 * jumps straight to that target.
3177 if (ic->next && ic->next->op == GOTO
3178 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3181 emitcode (";", "tail increment optimized (range %d)", labelRange);
3182 tlbl = IC_LABEL (ic->next);
3187 tlbl = newiTempLabel (NULL);
3190 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3191 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3192 IS_AOP_PREG (IC_RESULT (ic)))
3193 emitcode ("cjne", "%s,#0x00,%05d$"
3194 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3198 emitcode ("clr", "a");
3199 emitcode ("cjne", "a,%s,%05d$"
3200 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3204 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3207 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3208 IS_AOP_PREG (IC_RESULT (ic)))
3209 emitcode ("cjne", "%s,#0x00,%05d$"
3210 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3213 emitcode ("cjne", "a,%s,%05d$"
3214 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3217 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3221 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3222 IS_AOP_PREG (IC_RESULT (ic)))
3223 emitcode ("cjne", "%s,#0x00,%05d$"
3224 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3228 emitcode ("cjne", "a,%s,%05d$"
3229 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3232 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3237 emitcode ("", "%05d$:", tlbl->key + 100);
3242 /* if the sizes are greater than 1 then we cannot */
3243 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3244 AOP_SIZE (IC_LEFT (ic)) > 1)
3247 /* we can if the aops of the left & result match or
3248 if they are in registers and the registers are the
3251 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3252 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3253 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3258 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3259 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3260 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3265 _startLazyDPSEvaluation ();
3268 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3270 _endLazyDPSEvaluation ();
3279 /*-----------------------------------------------------------------*/
3280 /* outBitAcc - output a bit in acc */
3281 /*-----------------------------------------------------------------*/
3283 outBitAcc (operand * result)
3285 symbol *tlbl = newiTempLabel (NULL);
3286 /* if the result is a bit */
3287 if (AOP_TYPE (result) == AOP_CRY)
3289 aopPut (AOP (result), "a", 0);
3293 emitcode ("jz", "%05d$", tlbl->key + 100);
3294 emitcode ("mov", "a,%s", one);
3295 emitcode ("", "%05d$:", tlbl->key + 100);
3300 /*-----------------------------------------------------------------*/
3301 /* genPlusBits - generates code for addition of two bits */
3302 /*-----------------------------------------------------------------*/
3304 genPlusBits (iCode * ic)
3306 D (emitcode (";", "genPlusBits ");
3308 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3310 symbol *lbl = newiTempLabel (NULL);
3311 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3312 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3313 emitcode ("cpl", "c");
3314 emitcode ("", "%05d$:", (lbl->key + 100));
3315 outBitC (IC_RESULT (ic));
3319 emitcode ("clr", "a");
3320 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3321 emitcode ("rlc", "a");
3322 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3323 emitcode ("addc", "a,#0x00");
3324 outAcc (IC_RESULT (ic));
3329 adjustArithmeticResult (iCode * ic)
3331 if (opIsGptr (IC_RESULT (ic)) &&
3332 opIsGptr (IC_LEFT (ic)) &&
3333 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3335 aopPut (AOP (IC_RESULT (ic)),
3336 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3340 if (opIsGptr (IC_RESULT (ic)) &&
3341 opIsGptr (IC_RIGHT (ic)) &&
3342 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3344 aopPut (AOP (IC_RESULT (ic)),
3345 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3349 if (opIsGptr (IC_RESULT (ic)) &&
3350 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3351 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3352 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3353 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3356 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3357 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3361 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3362 // (because all three operands are in far space).
3363 #define AOP_OP_3(ic) \
3364 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3365 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3366 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3367 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3368 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3369 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3371 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3373 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3376 // Macro to aopOp all three operands of an ic. If this cannot be done,
3377 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3378 // will be set TRUE. The caller must then handle the case specially, noting
3379 // that the IC_RESULT operand is not aopOp'd.
3380 #define AOP_OP_3_NOFATAL(ic, rc) \
3381 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3382 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3383 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3384 isOperandInFarSpace(IC_RESULT(ic))) \
3386 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3391 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3392 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3394 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3395 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3397 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3399 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3403 // aopOp the left & right operands of an ic.
3404 #define AOP_OP_2(ic) \
3405 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3406 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3408 // convienience macro.
3409 #define AOP_SET_LOCALS(ic) \
3410 left = IC_LEFT(ic); \
3411 right = IC_RIGHT(ic); \
3412 result = IC_RESULT(ic);
3415 // Given an integer value of pushedSize bytes on the stack,
3416 // adjust it to be resultSize bytes, either by discarding
3417 // the most significant bytes or by zero-padding.
3419 // On exit from this macro, pushedSize will have been adjusted to
3420 // equal resultSize, and ACC may be trashed.
3421 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3422 /* If the pushed data is bigger than the result, \
3423 * simply discard unused bytes. Icky, but works. \
3425 while (pushedSize > resultSize) \
3427 D (emitcode (";", "discarding unused result byte."););\
3428 emitcode ("pop", "acc"); \
3431 if (pushedSize < resultSize) \
3433 emitcode ("clr", "a"); \
3434 /* Conversly, we haven't pushed enough here. \
3435 * just zero-pad, and all is well. \
3437 while (pushedSize < resultSize) \
3439 emitcode("push", "acc"); \
3443 assert(pushedSize == resultSize);
3445 /*-----------------------------------------------------------------*/
3446 /* genPlus - generates code for addition */
3447 /*-----------------------------------------------------------------*/
3449 genPlus (iCode * ic)
3451 int size, offset = 0;
3452 bool pushResult = FALSE;
3455 D (emitcode (";", "genPlus "););
3457 /* special cases :- */
3459 AOP_OP_3_NOFATAL (ic, pushResult);
3462 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3467 /* if literal, literal on the right or
3468 if left requires ACC or right is already
3470 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3471 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3472 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3474 operand *t = IC_RIGHT (ic);
3475 IC_RIGHT (ic) = IC_LEFT (ic);
3477 emitcode (";", "Swapped plus args.");
3480 /* if both left & right are in bit
3482 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3483 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3489 /* if left in bit space & right literal */
3490 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3491 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3493 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3494 /* if result in bit space */
3495 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3497 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3498 emitcode ("cpl", "c");
3499 outBitC (IC_RESULT (ic));
3503 size = getDataSize (IC_RESULT (ic));
3504 _startLazyDPSEvaluation ();
3507 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3508 emitcode ("addc", "a,#00");
3509 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3511 _endLazyDPSEvaluation ();
3516 /* if I can do an increment instead
3517 of add then GOOD for ME */
3518 if (genPlusIncr (ic) == TRUE)
3520 emitcode (";", "did genPlusIncr");
3525 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3527 _startLazyDPSEvaluation ();
3530 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3532 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3534 emitcode ("add", "a,%s",
3535 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3537 emitcode ("addc", "a,%s",
3538 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3542 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3544 /* right is going to use ACC or we would have taken the
3547 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3549 D(emitcode(";", "+ AOP_ACC special case."););
3550 emitcode("xch", "a, %s", DP2_RESULT_REG);
3552 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3555 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3558 emitcode("add", "a, %s", DP2_RESULT_REG);
3562 emitcode ("add", "a,%s",
3563 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3568 emitcode ("addc", "a,%s",
3569 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3574 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3578 emitcode ("push", "acc");
3582 _endLazyDPSEvaluation ();
3586 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3588 size = getDataSize (IC_LEFT (ic));
3589 rSize = getDataSize (IC_RESULT (ic));
3591 ADJUST_PUSHED_RESULT(size, rSize);
3593 _startLazyDPSEvaluation ();
3596 emitcode ("pop", "acc");
3597 aopPut (AOP (IC_RESULT (ic)), "a", size);
3599 _endLazyDPSEvaluation ();
3602 adjustArithmeticResult (ic);
3605 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3606 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3607 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3610 /*-----------------------------------------------------------------*/
3611 /* genMinusDec :- does subtraction with deccrement if possible */
3612 /*-----------------------------------------------------------------*/
3614 genMinusDec (iCode * ic)
3616 unsigned int icount;
3617 unsigned int size = getDataSize (IC_RESULT (ic));
3619 /* will try to generate an increment */
3620 /* if the right side is not a literal
3622 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3625 /* if the literal value of the right hand side
3626 is greater than 4 then it is not worth it */
3627 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3630 /* if decrement 16 bits in register */
3631 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3632 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3633 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3641 /* If the next instruction is a goto and the goto target
3642 * is <= 5 instructions previous to this, we can generate
3643 * jumps straight to that target.
3645 if (ic->next && ic->next->op == GOTO
3646 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3649 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3650 tlbl = IC_LABEL (ic->next);
3655 tlbl = newiTempLabel (NULL);
3659 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3660 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3661 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3662 IS_AOP_PREG (IC_RESULT (ic)))
3663 emitcode ("cjne", "%s,#0xff,%05d$"
3664 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3668 emitcode ("mov", "a,#0xff");
3669 emitcode ("cjne", "a,%s,%05d$"
3670 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3673 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3676 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3677 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3678 IS_AOP_PREG (IC_RESULT (ic)))
3679 emitcode ("cjne", "%s,#0xff,%05d$"
3680 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3684 emitcode ("cjne", "a,%s,%05d$"
3685 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3688 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3692 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3693 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3694 IS_AOP_PREG (IC_RESULT (ic)))
3695 emitcode ("cjne", "%s,#0xff,%05d$"
3696 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3700 emitcode ("cjne", "a,%s,%05d$"
3701 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3704 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3708 emitcode ("", "%05d$:", tlbl->key + 100);
3713 /* if the sizes are greater than 1 then we cannot */
3714 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3715 AOP_SIZE (IC_LEFT (ic)) > 1)
3718 /* we can if the aops of the left & result match or
3719 if they are in registers and the registers are the
3722 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3723 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3724 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3727 _startLazyDPSEvaluation ();
3730 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3732 _endLazyDPSEvaluation ();
3740 /*-----------------------------------------------------------------*/
3741 /* addSign - complete with sign */
3742 /*-----------------------------------------------------------------*/
3744 addSign (operand * result, int offset, int sign)
3746 int size = (getDataSize (result) - offset);
3749 _startLazyDPSEvaluation();
3752 emitcode ("rlc", "a");
3753 emitcode ("subb", "a,acc");
3756 aopPut (AOP (result), "a", offset++);
3763 aopPut (AOP (result), zero, offset++);
3766 _endLazyDPSEvaluation();
3770 /*-----------------------------------------------------------------*/
3771 /* genMinusBits - generates code for subtraction of two bits */
3772 /*-----------------------------------------------------------------*/
3774 genMinusBits (iCode * ic)
3776 symbol *lbl = newiTempLabel (NULL);
3778 D (emitcode (";", "genMinusBits "););
3780 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3782 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3783 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3784 emitcode ("cpl", "c");
3785 emitcode ("", "%05d$:", (lbl->key + 100));
3786 outBitC (IC_RESULT (ic));
3790 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3791 emitcode ("subb", "a,acc");
3792 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3793 emitcode ("inc", "a");
3794 emitcode ("", "%05d$:", (lbl->key + 100));
3795 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3796 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3800 /*-----------------------------------------------------------------*/
3801 /* genMinus - generates code for subtraction */
3802 /*-----------------------------------------------------------------*/
3804 genMinus (iCode * ic)
3806 int size, offset = 0;
3808 unsigned long lit = 0L;
3809 bool pushResult = FALSE;
3811 D (emitcode (";", "genMinus "););
3813 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3814 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3815 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3816 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3822 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3824 /* special cases :- */
3825 /* if both left & right are in bit space */
3826 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3827 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3833 /* if I can do an decrement instead
3834 of subtract then GOOD for ME */
3835 if (genMinusDec (ic) == TRUE)
3840 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3842 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3848 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3853 /* if literal, add a,#-lit, else normal subb */
3854 _startLazyDPSEvaluation ();
3857 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3858 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3859 emitcode ("subb", "a,%s",
3860 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3863 /* first add without previous c */
3865 if (!size && lit==-1) {
3866 emitcode ("dec", "a");
3868 emitcode ("add", "a,#0x%02x",
3869 (unsigned int) (lit & 0x0FFL));
3872 emitcode ("addc", "a,#0x%02x",
3873 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3879 emitcode ("push", "acc");
3883 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3887 _endLazyDPSEvaluation ();
3891 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3893 size = getDataSize (IC_LEFT (ic));
3894 rSize = getDataSize (IC_RESULT (ic));
3896 ADJUST_PUSHED_RESULT(size, rSize);
3898 _startLazyDPSEvaluation ();
3901 emitcode ("pop", "acc");
3902 aopPut (AOP (IC_RESULT (ic)), "a", size);
3904 _endLazyDPSEvaluation ();
3907 adjustArithmeticResult (ic);
3910 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3911 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3912 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3916 /*-----------------------------------------------------------------*/
3917 /* genMultbits :- multiplication of bits */
3918 /*-----------------------------------------------------------------*/
3920 genMultbits (operand * left,
3925 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3926 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3927 aopOp(result, ic, TRUE, FALSE);
3932 /*-----------------------------------------------------------------*/
3933 /* genMultOneByte : 8*8=8/16 bit multiplication */
3934 /*-----------------------------------------------------------------*/
3936 genMultOneByte (operand * left,
3941 sym_link *opetype = operandType (result);
3945 /* (if two literals: the value is computed before) */
3946 /* if one literal, literal on the right */
3947 if (AOP_TYPE (left) == AOP_LIT)
3952 emitcode (";", "swapped left and right");
3955 if (SPEC_USIGN(opetype)
3956 // ignore the sign of left and right, what else can we do?
3957 || (SPEC_USIGN(operandType(left)) &&
3958 SPEC_USIGN(operandType(right)))) {
3959 // just an unsigned 8*8=8/16 multiply
3960 //emitcode (";","unsigned");
3961 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3962 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3963 emitcode ("mul", "ab");
3966 aopOp(result, ic, TRUE, FALSE);
3968 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3970 // this should never happen
3971 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3972 AOP_SIZE(result), __FILE__, lineno);
3976 aopPut (AOP (result), "a", 0);
3978 if (AOP_SIZE(result)==2)
3980 aopPut (AOP (result), "b", 1);
3985 // we have to do a signed multiply
3987 emitcode (";", "signed");
3988 emitcode ("clr", "F0"); // reset sign flag
3989 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3991 lbl=newiTempLabel(NULL);
3992 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3993 // left side is negative, 8-bit two's complement, this fails for -128
3994 emitcode ("setb", "F0"); // set sign flag
3995 emitcode ("cpl", "a");
3996 emitcode ("inc", "a");
3998 emitcode ("", "%05d$:", lbl->key+100);
4001 if (AOP_TYPE(right)==AOP_LIT) {
4002 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4003 /* AND literal negative */
4004 if ((int) val < 0) {
4005 emitcode ("cpl", "F0"); // complement sign flag
4006 emitcode ("mov", "b,#0x%02x", -val);
4008 emitcode ("mov", "b,#0x%02x", val);
4011 lbl=newiTempLabel(NULL);
4012 emitcode ("mov", "b,a");
4013 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4014 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4015 // right side is negative, 8-bit two's complement
4016 emitcode ("cpl", "F0"); // complement sign flag
4017 emitcode ("cpl", "a");
4018 emitcode ("inc", "a");
4019 emitcode ("", "%05d$:", lbl->key+100);
4021 emitcode ("mul", "ab");
4024 aopOp(result, ic, TRUE, FALSE);
4026 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4028 // this should never happen
4029 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4030 AOP_SIZE(result), __FILE__, lineno);
4034 lbl=newiTempLabel(NULL);
4035 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4036 // only ONE op was negative, we have to do a 8/16-bit two's complement
4037 emitcode ("cpl", "a"); // lsb
4038 if (AOP_SIZE(result)==1) {
4039 emitcode ("inc", "a");
4041 emitcode ("add", "a,#1");
4042 emitcode ("xch", "a,b");
4043 emitcode ("cpl", "a"); // msb
4044 emitcode ("addc", "a,#0");
4045 emitcode ("xch", "a,b");
4048 emitcode ("", "%05d$:", lbl->key+100);
4049 aopPut (AOP (result), "a", 0);
4051 if (AOP_SIZE(result)==2) {
4052 aopPut (AOP (result), "b", 1);
4056 /*-----------------------------------------------------------------*/
4057 /* genMult - generates code for multiplication */
4058 /*-----------------------------------------------------------------*/
4060 genMult (iCode * ic)
4062 operand *left = IC_LEFT (ic);
4063 operand *right = IC_RIGHT (ic);
4064 operand *result = IC_RESULT (ic);
4066 D (emitcode (";", "genMult "););
4068 /* assign the amsops */
4071 /* special cases first */
4073 if (AOP_TYPE (left) == AOP_CRY &&
4074 AOP_TYPE (right) == AOP_CRY)
4076 genMultbits (left, right, result, ic);
4080 /* if both are of size == 1 */
4081 if (AOP_SIZE (left) == 1 &&
4082 AOP_SIZE (right) == 1)
4084 genMultOneByte (left, right, result, ic);
4088 /* should have been converted to function call */
4092 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4093 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4094 freeAsmop (result, NULL, ic, TRUE);
4097 /*-----------------------------------------------------------------*/
4098 /* genDivbits :- division of bits */
4099 /*-----------------------------------------------------------------*/
4101 genDivbits (operand * left,
4109 /* the result must be bit */
4110 LOAD_AB_FOR_DIV (left, right, l);
4111 emitcode ("div", "ab");
4112 emitcode ("rrc", "a");
4113 aopOp(result, ic, TRUE, FALSE);
4115 aopPut (AOP (result), "c", 0);
4118 /*-----------------------------------------------------------------*/
4119 /* genDivOneByte : 8 bit division */
4120 /*-----------------------------------------------------------------*/
4122 genDivOneByte (operand * left,
4127 sym_link *opetype = operandType (result);
4133 /* signed or unsigned */
4134 if (SPEC_USIGN (opetype))
4136 /* unsigned is easy */
4137 LOAD_AB_FOR_DIV (left, right, l);
4138 emitcode ("div", "ab");
4141 aopOp(result, ic, TRUE, FALSE);
4142 aopPut (AOP (result), "a", 0);
4145 size = AOP_SIZE (result) - 1;
4149 aopPut (AOP (result), zero, offset++);
4154 /* signed is a little bit more difficult */
4156 /* save the signs of the operands */
4157 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4159 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4160 emitcode ("push", "acc"); /* save it on the stack */
4162 /* now sign adjust for both left & right */
4163 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4165 lbl = newiTempLabel (NULL);
4166 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4167 emitcode ("cpl", "a");
4168 emitcode ("inc", "a");
4169 emitcode ("", "%05d$:", (lbl->key + 100));
4170 emitcode ("mov", "b,a");
4172 /* sign adjust left side */
4173 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4176 lbl = newiTempLabel (NULL);
4177 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4178 emitcode ("cpl", "a");
4179 emitcode ("inc", "a");
4180 emitcode ("", "%05d$:", (lbl->key + 100));
4182 /* now the division */
4183 emitcode ("nop", "; workaround for DS80C390 div bug.");
4184 emitcode ("div", "ab");
4185 /* we are interested in the lower order
4187 emitcode ("mov", "b,a");
4188 lbl = newiTempLabel (NULL);
4189 emitcode ("pop", "acc");
4190 /* if there was an over flow we don't
4191 adjust the sign of the result */
4192 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4193 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4195 emitcode ("clr", "a");
4196 emitcode ("subb", "a,b");
4197 emitcode ("mov", "b,a");
4198 emitcode ("", "%05d$:", (lbl->key + 100));
4200 /* now we are done */
4202 aopOp(result, ic, TRUE, FALSE);
4204 aopPut (AOP (result), "b", 0);
4206 size = AOP_SIZE (result) - 1;
4210 emitcode ("mov", "c,b.7");
4211 emitcode ("subb", "a,acc");
4215 aopPut (AOP (result), "a", offset++);
4221 /*-----------------------------------------------------------------*/
4222 /* genDiv - generates code for division */
4223 /*-----------------------------------------------------------------*/
4227 operand *left = IC_LEFT (ic);
4228 operand *right = IC_RIGHT (ic);
4229 operand *result = IC_RESULT (ic);
4231 D (emitcode (";", "genDiv "););
4233 /* assign the amsops */
4236 /* special cases first */
4238 if (AOP_TYPE (left) == AOP_CRY &&
4239 AOP_TYPE (right) == AOP_CRY)
4241 genDivbits (left, right, result, ic);
4245 /* if both are of size == 1 */
4246 if (AOP_SIZE (left) == 1 &&
4247 AOP_SIZE (right) == 1)
4249 genDivOneByte (left, right, result, ic);
4253 /* should have been converted to function call */
4256 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4257 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4258 freeAsmop (result, NULL, ic, TRUE);
4261 /*-----------------------------------------------------------------*/
4262 /* genModbits :- modulus of bits */
4263 /*-----------------------------------------------------------------*/
4265 genModbits (operand * left,
4272 /* the result must be bit */
4273 LOAD_AB_FOR_DIV (left, right, l);
4274 emitcode ("div", "ab");
4275 emitcode ("mov", "a,b");
4276 emitcode ("rrc", "a");
4277 aopPut (AOP (result), "c", 0);
4280 /*-----------------------------------------------------------------*/
4281 /* genModOneByte : 8 bit modulus */
4282 /*-----------------------------------------------------------------*/
4284 genModOneByte (operand * left,
4288 sym_link *opetype = operandType (result);
4292 /* signed or unsigned */
4293 if (SPEC_USIGN (opetype))
4295 /* unsigned is easy */
4296 LOAD_AB_FOR_DIV (left, right, l);
4297 emitcode ("div", "ab");
4298 aopPut (AOP (result), "b", 0);
4302 /* signed is a little bit more difficult */
4304 /* save the signs of the operands */
4305 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4308 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4309 emitcode ("push", "acc"); /* save it on the stack */
4311 /* now sign adjust for both left & right */
4312 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4315 lbl = newiTempLabel (NULL);
4316 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4317 emitcode ("cpl", "a");
4318 emitcode ("inc", "a");
4319 emitcode ("", "%05d$:", (lbl->key + 100));
4320 emitcode ("mov", "b,a");
4322 /* sign adjust left side */
4323 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4326 lbl = newiTempLabel (NULL);
4327 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4328 emitcode ("cpl", "a");
4329 emitcode ("inc", "a");
4330 emitcode ("", "%05d$:", (lbl->key + 100));
4332 /* now the multiplication */
4333 emitcode ("nop", "; workaround for DS80C390 div bug.");
4334 emitcode ("div", "ab");
4335 /* we are interested in the lower order
4337 lbl = newiTempLabel (NULL);
4338 emitcode ("pop", "acc");
4339 /* if there was an over flow we don't
4340 adjust the sign of the result */
4341 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4342 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4344 emitcode ("clr", "a");
4345 emitcode ("subb", "a,b");
4346 emitcode ("mov", "b,a");
4347 emitcode ("", "%05d$:", (lbl->key + 100));
4349 /* now we are done */
4350 aopPut (AOP (result), "b", 0);
4354 /*-----------------------------------------------------------------*/
4355 /* genMod - generates code for division */
4356 /*-----------------------------------------------------------------*/
4360 operand *left = IC_LEFT (ic);
4361 operand *right = IC_RIGHT (ic);
4362 operand *result = IC_RESULT (ic);
4364 D (emitcode (";", "genMod ");
4367 /* assign the amsops */
4370 /* special cases first */
4372 if (AOP_TYPE (left) == AOP_CRY &&
4373 AOP_TYPE (right) == AOP_CRY)
4375 genModbits (left, right, result);
4379 /* if both are of size == 1 */
4380 if (AOP_SIZE (left) == 1 &&
4381 AOP_SIZE (right) == 1)
4383 genModOneByte (left, right, result);
4387 /* should have been converted to function call */
4391 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4392 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4393 freeAsmop (result, NULL, ic, TRUE);
4396 /*-----------------------------------------------------------------*/
4397 /* genIfxJump :- will create a jump depending on the ifx */
4398 /*-----------------------------------------------------------------*/
4400 genIfxJump (iCode * ic, char *jval)
4403 symbol *tlbl = newiTempLabel (NULL);
4406 D (emitcode (";", "genIfxJump ");
4409 /* if true label then we jump if condition
4413 jlbl = IC_TRUE (ic);
4414 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4415 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4419 /* false label is present */
4420 jlbl = IC_FALSE (ic);
4421 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4422 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4424 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4425 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4427 emitcode (inst, "%05d$", tlbl->key + 100);
4428 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4429 emitcode ("", "%05d$:", tlbl->key + 100);
4431 /* mark the icode as generated */
4435 /*-----------------------------------------------------------------*/
4436 /* genCmp :- greater or less than comparison */
4437 /*-----------------------------------------------------------------*/
4439 genCmp (operand * left, operand * right,
4440 iCode * ic, iCode * ifx, int sign)
4442 int size, offset = 0;
4443 unsigned long lit = 0L;
4446 D (emitcode (";", "genCmp");
4449 result = IC_RESULT (ic);
4451 /* if left & right are bit variables */
4452 if (AOP_TYPE (left) == AOP_CRY &&
4453 AOP_TYPE (right) == AOP_CRY)
4455 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4456 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4460 /* subtract right from left if at the
4461 end the carry flag is set then we know that
4462 left is greater than right */
4463 size = max (AOP_SIZE (left), AOP_SIZE (right));
4465 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4466 if ((size == 1) && !sign &&
4467 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4469 symbol *lbl = newiTempLabel (NULL);
4470 emitcode ("cjne", "%s,%s,%05d$",
4471 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4472 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4474 emitcode ("", "%05d$:", lbl->key + 100);
4478 if (AOP_TYPE (right) == AOP_LIT)
4480 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4481 /* optimize if(x < 0) or if(x >= 0) */
4490 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4492 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4493 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4495 aopOp (result, ic, FALSE, FALSE);
4497 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4499 freeAsmop (result, NULL, ic, TRUE);
4500 genIfxJump (ifx, "acc.7");
4505 emitcode ("rlc", "a");
4507 goto release_freedLR;
4515 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4516 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4517 emitcode (";", "genCmp #2");
4518 if (sign && (size == 0))
4520 emitcode (";", "genCmp #3");
4521 emitcode ("xrl", "a,#0x80");
4522 if (AOP_TYPE (right) == AOP_LIT)
4524 unsigned long lit = (unsigned long)
4525 floatFromVal (AOP (right)->aopu.aop_lit);
4526 emitcode (";", "genCmp #3.1");
4527 emitcode ("subb", "a,#0x%02x",
4528 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4532 emitcode (";", "genCmp #3.2");
4533 if (AOP_NEEDSACC (right))
4535 emitcode ("push", "acc");
4537 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4538 FALSE, FALSE, FALSE));
4539 emitcode ("xrl", "b,#0x80");
4540 if (AOP_NEEDSACC (right))
4542 emitcode ("pop", "acc");
4544 emitcode ("subb", "a,b");
4551 emitcode (";", "genCmp #4");
4552 if (AOP_NEEDSACC (right))
4555 emitcode (";", "genCmp #4.1");
4556 emitcode ("xch", "a, b");
4557 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4558 emitcode ("xch", "a, b");
4563 emitcode (";", "genCmp #4.2");
4564 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4567 emitcode ("subb", "a,%s", s);
4574 /* Don't need the left & right operands any more; do need the result. */
4575 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4576 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 aopOp (result, ic, FALSE, FALSE);
4582 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4588 /* if the result is used in the next
4589 ifx conditional branch then generate
4590 code a little differently */
4593 genIfxJump (ifx, "c");
4599 /* leave the result in acc */
4601 freeAsmop (result, NULL, ic, TRUE);
4604 /*-----------------------------------------------------------------*/
4605 /* genCmpGt :- greater than comparison */
4606 /*-----------------------------------------------------------------*/
4608 genCmpGt (iCode * ic, iCode * ifx)
4610 operand *left, *right;
4611 sym_link *letype, *retype;
4614 D (emitcode (";", "genCmpGt ");
4617 left = IC_LEFT (ic);
4618 right = IC_RIGHT (ic);
4620 letype = getSpec (operandType (left));
4621 retype = getSpec (operandType (right));
4622 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4624 /* assign the left & right amsops */
4627 genCmp (right, left, ic, ifx, sign);
4630 /*-----------------------------------------------------------------*/
4631 /* genCmpLt - less than comparisons */
4632 /*-----------------------------------------------------------------*/
4634 genCmpLt (iCode * ic, iCode * ifx)
4636 operand *left, *right;
4637 sym_link *letype, *retype;
4640 D (emitcode (";", "genCmpLt "););
4642 left = IC_LEFT (ic);
4643 right = IC_RIGHT (ic);
4645 letype = getSpec (operandType (left));
4646 retype = getSpec (operandType (right));
4647 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4649 /* assign the left & right amsops */
4652 genCmp (left, right, ic, ifx, sign);
4655 /*-----------------------------------------------------------------*/
4656 /* gencjneshort - compare and jump if not equal */
4657 /*-----------------------------------------------------------------*/
4659 gencjneshort (operand * left, operand * right, symbol * lbl)
4661 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4663 unsigned long lit = 0L;
4665 D (emitcode (";", "gencjneshort");
4668 /* if the left side is a literal or
4669 if the right is in a pointer register and left
4671 if ((AOP_TYPE (left) == AOP_LIT) ||
4672 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4679 if (AOP_TYPE (right) == AOP_LIT)
4680 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4682 if (opIsGptr (left) || opIsGptr (right))
4684 /* We are comparing a generic pointer to something.
4685 * Exclude the generic type byte from the comparison.
4688 D (emitcode (";", "cjneshort: generic ptr special case.");
4693 /* if the right side is a literal then anything goes */
4694 if (AOP_TYPE (right) == AOP_LIT &&
4695 AOP_TYPE (left) != AOP_DIR)
4699 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4701 emitcode ("cjne", "a,%s,%05d$",
4702 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4708 /* if the right side is in a register or in direct space or
4709 if the left is a pointer register & right is not */
4710 else if (AOP_TYPE (right) == AOP_REG ||
4711 AOP_TYPE (right) == AOP_DIR ||
4712 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4713 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4717 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4718 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4719 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4720 emitcode ("jnz", "%05d$", lbl->key + 100);
4722 emitcode ("cjne", "a,%s,%05d$",
4723 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4730 /* right is a pointer reg need both a & b */
4733 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4734 if (strcmp (l, "b"))
4735 emitcode ("mov", "b,%s", l);
4736 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4737 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4743 /*-----------------------------------------------------------------*/
4744 /* gencjne - compare and jump if not equal */
4745 /*-----------------------------------------------------------------*/
4747 gencjne (operand * left, operand * right, symbol * lbl)
4749 symbol *tlbl = newiTempLabel (NULL);
4751 D (emitcode (";", "gencjne");
4754 gencjneshort (left, right, lbl);
4756 emitcode ("mov", "a,%s", one);
4757 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4758 emitcode ("", "%05d$:", lbl->key + 100);
4759 emitcode ("clr", "a");
4760 emitcode ("", "%05d$:", tlbl->key + 100);
4763 /*-----------------------------------------------------------------*/
4764 /* genCmpEq - generates code for equal to */
4765 /*-----------------------------------------------------------------*/
4767 genCmpEq (iCode * ic, iCode * ifx)
4769 operand *left, *right, *result;
4771 D (emitcode (";", "genCmpEq ");
4775 AOP_SET_LOCALS (ic);
4777 /* if literal, literal on the right or
4778 if the right is in a pointer register and left
4780 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4781 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4783 operand *t = IC_RIGHT (ic);
4784 IC_RIGHT (ic) = IC_LEFT (ic);
4788 if (ifx && /* !AOP_SIZE(result) */
4789 OP_SYMBOL (result) &&
4790 OP_SYMBOL (result)->regType == REG_CND)
4793 /* if they are both bit variables */
4794 if (AOP_TYPE (left) == AOP_CRY &&
4795 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4797 if (AOP_TYPE (right) == AOP_LIT)
4799 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4803 emitcode ("cpl", "c");
4807 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4811 emitcode ("clr", "c");
4813 /* AOP_TYPE(right) == AOP_CRY */
4817 symbol *lbl = newiTempLabel (NULL);
4818 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4819 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4820 emitcode ("cpl", "c");
4821 emitcode ("", "%05d$:", (lbl->key + 100));
4823 /* if true label then we jump if condition
4825 tlbl = newiTempLabel (NULL);
4828 emitcode ("jnc", "%05d$", tlbl->key + 100);
4829 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4833 emitcode ("jc", "%05d$", tlbl->key + 100);
4834 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4836 emitcode ("", "%05d$:", tlbl->key + 100);
4840 tlbl = newiTempLabel (NULL);
4841 gencjneshort (left, right, tlbl);
4844 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4845 emitcode ("", "%05d$:", tlbl->key + 100);
4849 symbol *lbl = newiTempLabel (NULL);
4850 emitcode ("sjmp", "%05d$", lbl->key + 100);
4851 emitcode ("", "%05d$:", tlbl->key + 100);
4852 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4853 emitcode ("", "%05d$:", lbl->key + 100);
4856 /* mark the icode as generated */
4859 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4860 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4864 /* if they are both bit variables */
4865 if (AOP_TYPE (left) == AOP_CRY &&
4866 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4868 if (AOP_TYPE (right) == AOP_LIT)
4870 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4873 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4874 emitcode ("cpl", "c");
4878 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4882 emitcode ("clr", "c");
4884 /* AOP_TYPE(right) == AOP_CRY */
4888 symbol *lbl = newiTempLabel (NULL);
4889 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4890 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4891 emitcode ("cpl", "c");
4892 emitcode ("", "%05d$:", (lbl->key + 100));
4895 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4896 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4898 aopOp (result, ic, TRUE, FALSE);
4901 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4908 genIfxJump (ifx, "c");
4911 /* if the result is used in an arithmetic operation
4912 then put the result in place */
4917 gencjne (left, right, newiTempLabel (NULL));
4919 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4920 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4922 aopOp (result, ic, TRUE, FALSE);
4924 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4926 aopPut (AOP (result), "a", 0);
4931 genIfxJump (ifx, "a");
4934 /* if the result is used in an arithmetic operation
4935 then put the result in place */
4936 if (AOP_TYPE (result) != AOP_CRY)
4938 /* leave the result in acc */
4942 freeAsmop (result, NULL, ic, TRUE);
4945 /*-----------------------------------------------------------------*/
4946 /* ifxForOp - returns the icode containing the ifx for operand */
4947 /*-----------------------------------------------------------------*/
4949 ifxForOp (operand * op, iCode * ic)
4951 /* if true symbol then needs to be assigned */
4952 if (IS_TRUE_SYMOP (op))
4955 /* if this has register type condition and
4956 the next instruction is ifx with the same operand
4957 and live to of the operand is upto the ifx only then */
4959 ic->next->op == IFX &&
4960 IC_COND (ic->next)->key == op->key &&
4961 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4966 /*-----------------------------------------------------------------*/
4967 /* genAndOp - for && operation */
4968 /*-----------------------------------------------------------------*/
4970 genAndOp (iCode * ic)
4972 operand *left, *right, *result;
4975 D (emitcode (";", "genAndOp "););
4977 /* note here that && operations that are in an
4978 if statement are taken away by backPatchLabels
4979 only those used in arthmetic operations remain */
4981 AOP_SET_LOCALS (ic);
4983 /* if both are bit variables */
4984 if (AOP_TYPE (left) == AOP_CRY &&
4985 AOP_TYPE (right) == AOP_CRY)
4987 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4988 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4989 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4990 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4992 aopOp (result,ic,FALSE, FALSE);
4997 tlbl = newiTempLabel (NULL);
4999 emitcode ("jz", "%05d$", tlbl->key + 100);
5001 emitcode ("", "%05d$:", tlbl->key + 100);
5002 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5003 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5005 aopOp (result,ic,FALSE, FALSE);
5008 freeAsmop (result, NULL, ic, TRUE);
5012 /*-----------------------------------------------------------------*/
5013 /* genOrOp - for || operation */
5014 /*-----------------------------------------------------------------*/
5016 genOrOp (iCode * ic)
5018 operand *left, *right, *result;
5021 D (emitcode (";", "genOrOp "););
5023 /* note here that || operations that are in an
5024 if statement are taken away by backPatchLabels
5025 only those used in arthmetic operations remain */
5027 AOP_SET_LOCALS (ic);
5029 /* if both are bit variables */
5030 if (AOP_TYPE (left) == AOP_CRY &&
5031 AOP_TYPE (right) == AOP_CRY)
5033 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5034 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5035 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5036 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5038 aopOp (result,ic,FALSE, FALSE);
5044 tlbl = newiTempLabel (NULL);
5046 emitcode ("jnz", "%05d$", tlbl->key + 100);
5048 emitcode ("", "%05d$:", tlbl->key + 100);
5049 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5050 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5052 aopOp (result,ic,FALSE, FALSE);
5057 freeAsmop (result, NULL, ic, TRUE);
5060 /*-----------------------------------------------------------------*/
5061 /* isLiteralBit - test if lit == 2^n */
5062 /*-----------------------------------------------------------------*/
5064 isLiteralBit (unsigned long lit)
5066 unsigned long pw[32] =
5067 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5068 0x100L, 0x200L, 0x400L, 0x800L,
5069 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5070 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5071 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5072 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5073 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5076 for (idx = 0; idx < 32; idx++)
5082 /*-----------------------------------------------------------------*/
5083 /* continueIfTrue - */
5084 /*-----------------------------------------------------------------*/
5086 continueIfTrue (iCode * ic)
5089 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5093 /*-----------------------------------------------------------------*/
5095 /*-----------------------------------------------------------------*/
5097 jumpIfTrue (iCode * ic)
5100 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5104 /*-----------------------------------------------------------------*/
5105 /* jmpTrueOrFalse - */
5106 /*-----------------------------------------------------------------*/
5108 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5110 // ugly but optimized by peephole
5113 symbol *nlbl = newiTempLabel (NULL);
5114 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5115 emitcode ("", "%05d$:", tlbl->key + 100);
5116 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5117 emitcode ("", "%05d$:", nlbl->key + 100);
5121 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5122 emitcode ("", "%05d$:", tlbl->key + 100);
5127 // Generate code to perform a bit-wise logic operation
5128 // on two operands in far space (assumed to already have been
5129 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5130 // in far space. This requires pushing the result on the stack
5131 // then popping it into the result.
5133 genFarFarLogicOp(iCode *ic, char *logicOp)
5135 int size, resultSize, compSize;
5139 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5140 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5141 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5143 _startLazyDPSEvaluation();
5144 for (size = compSize; (size--); offset++)
5146 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5147 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5148 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5150 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5151 emitcode ("push", "acc");
5153 _endLazyDPSEvaluation();
5155 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5156 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5157 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5159 resultSize = AOP_SIZE(IC_RESULT(ic));
5161 ADJUST_PUSHED_RESULT(compSize, resultSize);
5163 _startLazyDPSEvaluation();
5166 emitcode ("pop", "acc");
5167 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5169 _endLazyDPSEvaluation();
5170 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5174 /*-----------------------------------------------------------------*/
5175 /* genAnd - code for and */
5176 /*-----------------------------------------------------------------*/
5178 genAnd (iCode * ic, iCode * ifx)
5180 operand *left, *right, *result;
5181 int size, offset = 0;
5182 unsigned long lit = 0L;
5187 D (emitcode (";", "genAnd "););
5189 AOP_OP_3_NOFATAL (ic, pushResult);
5190 AOP_SET_LOCALS (ic);
5194 genFarFarLogicOp(ic, "anl");
5199 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5201 AOP_TYPE (left), AOP_TYPE (right));
5202 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5204 AOP_SIZE (left), AOP_SIZE (right));
5207 /* if left is a literal & right is not then exchange them */
5208 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5209 AOP_NEEDSACC (left))
5211 operand *tmp = right;
5216 /* if result = right then exchange them */
5217 if (sameRegs (AOP (result), AOP (right)))
5219 operand *tmp = right;
5224 /* if right is bit then exchange them */
5225 if (AOP_TYPE (right) == AOP_CRY &&
5226 AOP_TYPE (left) != AOP_CRY)
5228 operand *tmp = right;
5232 if (AOP_TYPE (right) == AOP_LIT)
5233 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5235 size = AOP_SIZE (result);
5238 // result = bit & yy;
5239 if (AOP_TYPE (left) == AOP_CRY)
5241 // c = bit & literal;
5242 if (AOP_TYPE (right) == AOP_LIT)
5246 if (size && sameRegs (AOP (result), AOP (left)))
5249 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5254 if (size && (AOP_TYPE (result) == AOP_CRY))
5256 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5259 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5264 emitcode ("clr", "c");
5269 if (AOP_TYPE (right) == AOP_CRY)
5272 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5273 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5278 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5280 emitcode ("rrc", "a");
5281 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5289 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5290 genIfxJump (ifx, "c");
5294 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5295 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5296 if ((AOP_TYPE (right) == AOP_LIT) &&
5297 (AOP_TYPE (result) == AOP_CRY) &&
5298 (AOP_TYPE (left) != AOP_CRY))
5300 int posbit = isLiteralBit (lit);
5305 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5308 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5314 sprintf (buffer, "acc.%d", posbit & 0x07);
5315 genIfxJump (ifx, buffer);
5322 symbol *tlbl = newiTempLabel (NULL);
5323 int sizel = AOP_SIZE (left);
5325 emitcode ("setb", "c");
5328 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5330 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5332 if ((posbit = isLiteralBit (bytelit)) != 0)
5333 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5336 if (bytelit != 0x0FFL)
5337 emitcode ("anl", "a,%s",
5338 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5339 emitcode ("jnz", "%05d$", tlbl->key + 100);
5344 // bit = left & literal
5347 emitcode ("clr", "c");
5348 emitcode ("", "%05d$:", tlbl->key + 100);
5350 // if(left & literal)
5354 jmpTrueOrFalse (ifx, tlbl);
5362 /* if left is same as result */
5363 if (sameRegs (AOP (result), AOP (left)))
5365 for (; size--; offset++)
5367 if (AOP_TYPE (right) == AOP_LIT)
5369 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5371 else if (bytelit == 0)
5372 aopPut (AOP (result), zero, offset);
5373 else if (IS_AOP_PREG (result))
5375 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5376 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5377 aopPut (AOP (result), "a", offset);
5380 emitcode ("anl", "%s,%s",
5381 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5382 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5386 if (AOP_TYPE (left) == AOP_ACC)
5387 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5390 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5391 if (IS_AOP_PREG (result))
5393 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5394 aopPut (AOP (result), "a", offset);
5398 emitcode ("anl", "%s,a",
5399 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5406 // left & result in different registers
5407 if (AOP_TYPE (result) == AOP_CRY)
5410 // if(size), result in bit
5411 // if(!size && ifx), conditional oper: if(left & right)
5412 symbol *tlbl = newiTempLabel (NULL);
5413 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5415 emitcode ("setb", "c");
5418 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5419 emitcode ("anl", "a,%s",
5420 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5422 if (AOP_TYPE(left)==AOP_ACC) {
5423 emitcode("mov", "b,a");
5424 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5425 emitcode("anl", "a,b");
5427 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5428 emitcode ("anl", "a,%s",
5429 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5432 emitcode ("jnz", "%05d$", tlbl->key + 100);
5438 emitcode ("", "%05d$:", tlbl->key + 100);
5442 jmpTrueOrFalse (ifx, tlbl);
5446 for (; (size--); offset++)
5449 // result = left & right
5450 if (AOP_TYPE (right) == AOP_LIT)
5452 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5454 aopPut (AOP (result),
5455 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5459 else if (bytelit == 0)
5461 aopPut (AOP (result), zero, offset);
5464 D (emitcode (";", "better literal AND.");
5466 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5467 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5468 FALSE, FALSE, FALSE));
5473 // faster than result <- left, anl result,right
5474 // and better if result is SFR
5475 if (AOP_TYPE (left) == AOP_ACC)
5477 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5478 FALSE, FALSE, FALSE));
5482 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5483 emitcode ("anl", "a,%s",
5484 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5487 aopPut (AOP (result), "a", offset);
5493 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5494 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5495 freeAsmop (result, NULL, ic, TRUE);
5499 /*-----------------------------------------------------------------*/
5500 /* genOr - code for or */
5501 /*-----------------------------------------------------------------*/
5503 genOr (iCode * ic, iCode * ifx)
5505 operand *left, *right, *result;
5506 int size, offset = 0;
5507 unsigned long lit = 0L;
5510 D (emitcode (";", "genOr "););
5512 AOP_OP_3_NOFATAL (ic, pushResult);
5513 AOP_SET_LOCALS (ic);
5517 genFarFarLogicOp(ic, "orl");
5523 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5525 AOP_TYPE (left), AOP_TYPE (right));
5526 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5528 AOP_SIZE (left), AOP_SIZE (right));
5531 /* if left is a literal & right is not then exchange them */
5532 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5533 AOP_NEEDSACC (left))
5535 operand *tmp = right;
5540 /* if result = right then exchange them */
5541 if (sameRegs (AOP (result), AOP (right)))
5543 operand *tmp = right;
5548 /* if right is bit then exchange them */
5549 if (AOP_TYPE (right) == AOP_CRY &&
5550 AOP_TYPE (left) != AOP_CRY)
5552 operand *tmp = right;
5556 if (AOP_TYPE (right) == AOP_LIT)
5557 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5559 size = AOP_SIZE (result);
5563 if (AOP_TYPE (left) == AOP_CRY)
5565 if (AOP_TYPE (right) == AOP_LIT)
5567 // c = bit & literal;
5570 // lit != 0 => result = 1
5571 if (AOP_TYPE (result) == AOP_CRY)
5574 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5576 continueIfTrue (ifx);
5579 emitcode ("setb", "c");
5583 // lit == 0 => result = left
5584 if (size && sameRegs (AOP (result), AOP (left)))
5586 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5591 if (AOP_TYPE (right) == AOP_CRY)
5594 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5595 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5600 symbol *tlbl = newiTempLabel (NULL);
5601 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5602 emitcode ("setb", "c");
5603 emitcode ("jb", "%s,%05d$",
5604 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5606 emitcode ("jnz", "%05d$", tlbl->key + 100);
5607 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5609 jmpTrueOrFalse (ifx, tlbl);
5615 emitcode ("", "%05d$:", tlbl->key + 100);
5624 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5625 genIfxJump (ifx, "c");
5629 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5630 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5631 if ((AOP_TYPE (right) == AOP_LIT) &&
5632 (AOP_TYPE (result) == AOP_CRY) &&
5633 (AOP_TYPE (left) != AOP_CRY))
5639 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5641 continueIfTrue (ifx);
5646 // lit = 0, result = boolean(left)
5648 emitcode ("setb", "c");
5652 symbol *tlbl = newiTempLabel (NULL);
5653 emitcode ("jnz", "%05d$", tlbl->key + 100);
5655 emitcode ("", "%05d$:", tlbl->key + 100);
5659 genIfxJump (ifx, "a");
5667 /* if left is same as result */
5668 if (sameRegs (AOP (result), AOP (left)))
5670 for (; size--; offset++)
5672 if (AOP_TYPE (right) == AOP_LIT)
5674 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5680 if (IS_AOP_PREG (left))
5682 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5683 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5684 aopPut (AOP (result), "a", offset);
5688 emitcode ("orl", "%s,%s",
5689 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5690 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5696 if (AOP_TYPE (left) == AOP_ACC)
5698 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5702 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5703 if (IS_AOP_PREG (left))
5705 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5706 aopPut (AOP (result), "a", offset);
5710 emitcode ("orl", "%s,a",
5711 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5719 // left & result in different registers
5720 if (AOP_TYPE (result) == AOP_CRY)
5723 // if(size), result in bit
5724 // if(!size && ifx), conditional oper: if(left | right)
5725 symbol *tlbl = newiTempLabel (NULL);
5726 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5728 emitcode ("setb", "c");
5731 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5732 emitcode ("orl", "a,%s",
5733 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5735 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5736 emitcode ("orl", "a,%s",
5737 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5739 emitcode ("jnz", "%05d$", tlbl->key + 100);
5745 emitcode ("", "%05d$:", tlbl->key + 100);
5749 jmpTrueOrFalse (ifx, tlbl);
5753 for (; (size--); offset++)
5756 // result = left & right
5757 if (AOP_TYPE (right) == AOP_LIT)
5759 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5761 aopPut (AOP (result),
5762 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5766 D (emitcode (";", "better literal OR.");
5768 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5769 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5770 FALSE, FALSE, FALSE));
5775 // faster than result <- left, anl result,right
5776 // and better if result is SFR
5777 if (AOP_TYPE (left) == AOP_ACC)
5779 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5780 FALSE, FALSE, FALSE));
5784 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5785 emitcode ("orl", "a,%s",
5786 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5789 aopPut (AOP (result), "a", offset);
5795 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5796 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5797 freeAsmop (result, NULL, ic, TRUE);
5800 /*-----------------------------------------------------------------*/
5801 /* genXor - code for xclusive or */
5802 /*-----------------------------------------------------------------*/
5804 genXor (iCode * ic, iCode * ifx)
5806 operand *left, *right, *result;
5807 int size, offset = 0;
5808 unsigned long lit = 0L;
5811 D (emitcode (";", "genXor "););
5813 AOP_OP_3_NOFATAL (ic, pushResult);
5814 AOP_SET_LOCALS (ic);
5818 genFarFarLogicOp(ic, "xrl");
5823 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5825 AOP_TYPE (left), AOP_TYPE (right));
5826 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5828 AOP_SIZE (left), AOP_SIZE (right));
5831 /* if left is a literal & right is not ||
5832 if left needs acc & right does not */
5833 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5834 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5836 operand *tmp = right;
5841 /* if result = right then exchange them */
5842 if (sameRegs (AOP (result), AOP (right)))
5844 operand *tmp = right;
5849 /* if right is bit then exchange them */
5850 if (AOP_TYPE (right) == AOP_CRY &&
5851 AOP_TYPE (left) != AOP_CRY)
5853 operand *tmp = right;
5857 if (AOP_TYPE (right) == AOP_LIT)
5858 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5860 size = AOP_SIZE (result);
5864 if (AOP_TYPE (left) == AOP_CRY)
5866 if (AOP_TYPE (right) == AOP_LIT)
5868 // c = bit & literal;
5871 // lit>>1 != 0 => result = 1
5872 if (AOP_TYPE (result) == AOP_CRY)
5875 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5877 continueIfTrue (ifx);
5880 emitcode ("setb", "c");
5887 // lit == 0, result = left
5888 if (size && sameRegs (AOP (result), AOP (left)))
5890 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5894 // lit == 1, result = not(left)
5895 if (size && sameRegs (AOP (result), AOP (left)))
5897 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5902 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5903 emitcode ("cpl", "c");
5912 symbol *tlbl = newiTempLabel (NULL);
5913 if (AOP_TYPE (right) == AOP_CRY)
5916 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5920 int sizer = AOP_SIZE (right);
5922 // if val>>1 != 0, result = 1
5923 emitcode ("setb", "c");
5926 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5928 // test the msb of the lsb
5929 emitcode ("anl", "a,#0xfe");
5930 emitcode ("jnz", "%05d$", tlbl->key + 100);
5934 emitcode ("rrc", "a");
5936 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5937 emitcode ("cpl", "c");
5938 emitcode ("", "%05d$:", (tlbl->key + 100));
5945 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5946 genIfxJump (ifx, "c");
5950 if (sameRegs (AOP (result), AOP (left)))
5952 /* if left is same as result */
5953 for (; size--; offset++)
5955 if (AOP_TYPE (right) == AOP_LIT)
5957 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5959 else if (IS_AOP_PREG (left))
5961 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5962 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5963 aopPut (AOP (result), "a", offset);
5966 emitcode ("xrl", "%s,%s",
5967 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5968 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5972 if (AOP_TYPE (left) == AOP_ACC)
5973 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5976 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5977 if (IS_AOP_PREG (left))
5979 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5980 aopPut (AOP (result), "a", offset);
5983 emitcode ("xrl", "%s,a",
5984 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5991 // left & result in different registers
5992 if (AOP_TYPE (result) == AOP_CRY)
5995 // if(size), result in bit
5996 // if(!size && ifx), conditional oper: if(left ^ right)
5997 symbol *tlbl = newiTempLabel (NULL);
5998 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6000 emitcode ("setb", "c");
6003 if ((AOP_TYPE (right) == AOP_LIT) &&
6004 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6006 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6010 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6011 emitcode ("xrl", "a,%s",
6012 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6014 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6015 emitcode ("xrl", "a,%s",
6016 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6019 emitcode ("jnz", "%05d$", tlbl->key + 100);
6025 emitcode ("", "%05d$:", tlbl->key + 100);
6029 jmpTrueOrFalse (ifx, tlbl);
6032 for (; (size--); offset++)
6035 // result = left & right
6036 if (AOP_TYPE (right) == AOP_LIT)
6038 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6040 aopPut (AOP (result),
6041 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6045 D (emitcode (";", "better literal XOR.");
6047 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6048 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6049 FALSE, FALSE, FALSE));
6053 // faster than result <- left, anl result,right
6054 // and better if result is SFR
6055 if (AOP_TYPE (left) == AOP_ACC)
6057 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6058 FALSE, FALSE, FALSE));
6062 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6063 emitcode ("xrl", "a,%s",
6064 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6067 aopPut (AOP (result), "a", offset);
6072 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6073 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6074 freeAsmop (result, NULL, ic, TRUE);
6077 /*-----------------------------------------------------------------*/
6078 /* genInline - write the inline code out */
6079 /*-----------------------------------------------------------------*/
6081 genInline (iCode * ic)
6083 char *buffer, *bp, *bp1;
6085 D (emitcode (";", "genInline ");
6088 _G.inLine += (!options.asmpeep);
6090 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6091 strcpy (buffer, IC_INLINE (ic));
6093 /* emit each line as a code */
6118 /* emitcode("",buffer); */
6119 _G.inLine -= (!options.asmpeep);
6122 /*-----------------------------------------------------------------*/
6123 /* genRRC - rotate right with carry */
6124 /*-----------------------------------------------------------------*/
6128 operand *left, *result;
6129 int size, offset = 0;
6132 D (emitcode (";", "genRRC ");
6135 /* rotate right with carry */
6136 left = IC_LEFT (ic);
6137 result = IC_RESULT (ic);
6138 aopOp (left, ic, FALSE, FALSE);
6139 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6141 /* move it to the result */
6142 size = AOP_SIZE (result);
6146 _startLazyDPSEvaluation ();
6149 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6151 emitcode ("rrc", "a");
6152 if (AOP_SIZE (result) > 1)
6153 aopPut (AOP (result), "a", offset--);
6155 _endLazyDPSEvaluation ();
6157 /* now we need to put the carry into the
6158 highest order byte of the result */
6159 if (AOP_SIZE (result) > 1)
6161 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6164 emitcode ("mov", "acc.7,c");
6165 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6166 freeAsmop (left, NULL, ic, TRUE);
6167 freeAsmop (result, NULL, ic, TRUE);
6170 /*-----------------------------------------------------------------*/
6171 /* genRLC - generate code for rotate left with carry */
6172 /*-----------------------------------------------------------------*/
6176 operand *left, *result;
6177 int size, offset = 0;
6180 D (emitcode (";", "genRLC ");
6183 /* rotate right with carry */
6184 left = IC_LEFT (ic);
6185 result = IC_RESULT (ic);
6186 aopOp (left, ic, FALSE, FALSE);
6187 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6189 /* move it to the result */
6190 size = AOP_SIZE (result);
6194 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6196 emitcode ("add", "a,acc");
6197 if (AOP_SIZE (result) > 1)
6199 aopPut (AOP (result), "a", offset++);
6202 _startLazyDPSEvaluation ();
6205 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6207 emitcode ("rlc", "a");
6208 if (AOP_SIZE (result) > 1)
6209 aopPut (AOP (result), "a", offset++);
6211 _endLazyDPSEvaluation ();
6213 /* now we need to put the carry into the
6214 highest order byte of the result */
6215 if (AOP_SIZE (result) > 1)
6217 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6220 emitcode ("mov", "acc.0,c");
6221 aopPut (AOP (result), "a", 0);
6222 freeAsmop (left, NULL, ic, TRUE);
6223 freeAsmop (result, NULL, ic, TRUE);
6226 /*-----------------------------------------------------------------*/
6227 /* genGetHbit - generates code get highest order bit */
6228 /*-----------------------------------------------------------------*/
6230 genGetHbit (iCode * ic)
6232 operand *left, *result;
6233 left = IC_LEFT (ic);
6234 result = IC_RESULT (ic);
6235 aopOp (left, ic, FALSE, FALSE);
6236 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6238 D (emitcode (";", "genGetHbit ");
6241 /* get the highest order byte into a */
6242 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6243 if (AOP_TYPE (result) == AOP_CRY)
6245 emitcode ("rlc", "a");
6250 emitcode ("rl", "a");
6251 emitcode ("anl", "a,#0x01");
6256 freeAsmop (left, NULL, ic, TRUE);
6257 freeAsmop (result, NULL, ic, TRUE);
6260 /*-----------------------------------------------------------------*/
6261 /* AccRol - rotate left accumulator by known count */
6262 /*-----------------------------------------------------------------*/
6264 AccRol (int shCount)
6266 shCount &= 0x0007; // shCount : 0..7
6273 emitcode ("rl", "a");
6276 emitcode ("rl", "a");
6277 emitcode ("rl", "a");
6280 emitcode ("swap", "a");
6281 emitcode ("rr", "a");
6284 emitcode ("swap", "a");
6287 emitcode ("swap", "a");
6288 emitcode ("rl", "a");
6291 emitcode ("rr", "a");
6292 emitcode ("rr", "a");
6295 emitcode ("rr", "a");
6300 /*-----------------------------------------------------------------*/
6301 /* AccLsh - left shift accumulator by known count */
6302 /*-----------------------------------------------------------------*/
6304 AccLsh (int shCount)
6309 emitcode ("add", "a,acc");
6310 else if (shCount == 2)
6312 emitcode ("add", "a,acc");
6313 emitcode ("add", "a,acc");
6317 /* rotate left accumulator */
6319 /* and kill the lower order bits */
6320 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6325 /*-----------------------------------------------------------------*/
6326 /* AccRsh - right shift accumulator by known count */
6327 /*-----------------------------------------------------------------*/
6329 AccRsh (int shCount)
6336 emitcode ("rrc", "a");
6340 /* rotate right accumulator */
6341 AccRol (8 - shCount);
6342 /* and kill the higher order bits */
6343 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6348 #ifdef BETTER_LITERAL_SHIFT
6349 /*-----------------------------------------------------------------*/
6350 /* AccSRsh - signed right shift accumulator by known count */
6351 /*-----------------------------------------------------------------*/
6353 AccSRsh (int shCount)
6360 emitcode ("mov", "c,acc.7");
6361 emitcode ("rrc", "a");
6363 else if (shCount == 2)
6365 emitcode ("mov", "c,acc.7");
6366 emitcode ("rrc", "a");
6367 emitcode ("mov", "c,acc.7");
6368 emitcode ("rrc", "a");
6372 tlbl = newiTempLabel (NULL);
6373 /* rotate right accumulator */
6374 AccRol (8 - shCount);
6375 /* and kill the higher order bits */
6376 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6377 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6378 emitcode ("orl", "a,#0x%02x",
6379 (unsigned char) ~SRMask[shCount]);
6380 emitcode ("", "%05d$:", tlbl->key + 100);
6386 #ifdef BETTER_LITERAL_SHIFT
6387 /*-----------------------------------------------------------------*/
6388 /* shiftR1Left2Result - shift right one byte from left to result */
6389 /*-----------------------------------------------------------------*/
6391 shiftR1Left2Result (operand * left, int offl,
6392 operand * result, int offr,
6393 int shCount, int sign)
6395 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6396 /* shift right accumulator */
6401 aopPut (AOP (result), "a", offr);
6405 #ifdef BETTER_LITERAL_SHIFT
6406 /*-----------------------------------------------------------------*/
6407 /* shiftL1Left2Result - shift left one byte from left to result */
6408 /*-----------------------------------------------------------------*/
6410 shiftL1Left2Result (operand * left, int offl,
6411 operand * result, int offr, int shCount)
6413 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6414 /* shift left accumulator */
6416 aopPut (AOP (result), "a", offr);
6420 #ifdef BETTER_LITERAL_SHIFT
6421 /*-----------------------------------------------------------------*/
6422 /* movLeft2Result - move byte from left to result */
6423 /*-----------------------------------------------------------------*/
6425 movLeft2Result (operand * left, int offl,
6426 operand * result, int offr, int sign)
6429 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6431 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6433 if (*l == '@' && (IS_AOP_PREG (result)))
6435 emitcode ("mov", "a,%s", l);
6436 aopPut (AOP (result), "a", offr);
6442 aopPut (AOP (result), l, offr);
6446 /* MSB sign in acc.7 ! */
6447 if (getDataSize (left) == offl + 1)
6449 emitcode ("mov", "a,%s", l);
6450 aopPut (AOP (result), "a", offr);
6458 #ifdef BETTER_LITERAL_SHIFT
6459 /*-----------------------------------------------------------------*/
6460 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6461 /*-----------------------------------------------------------------*/
6465 emitcode ("rrc", "a");
6466 emitcode ("xch", "a,%s", x);
6467 emitcode ("rrc", "a");
6468 emitcode ("xch", "a,%s", x);
6472 #ifdef BETTER_LITERAL_SHIFT
6474 /*-----------------------------------------------------------------*/
6475 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6476 /*-----------------------------------------------------------------*/
6480 emitcode ("xch", "a,%s", x);
6481 emitcode ("rlc", "a");
6482 emitcode ("xch", "a,%s", x);
6483 emitcode ("rlc", "a");
6487 #ifdef BETTER_LITERAL_SHIFT
6488 /*-----------------------------------------------------------------*/
6489 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6490 /*-----------------------------------------------------------------*/
6494 emitcode ("xch", "a,%s", x);
6495 emitcode ("add", "a,acc");
6496 emitcode ("xch", "a,%s", x);
6497 emitcode ("rlc", "a");
6501 #ifdef BETTER_LITERAL_SHIFT
6502 /*-----------------------------------------------------------------*/
6503 /* AccAXLsh - left shift a:x by known count (0..7) */
6504 /*-----------------------------------------------------------------*/
6506 AccAXLsh (char *x, int shCount)
6521 case 5: // AAAAABBB:CCCCCDDD
6523 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6525 emitcode ("anl", "a,#0x%02x",
6526 SLMask[shCount]); // BBB00000:CCCCCDDD
6528 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6530 AccRol (shCount); // DDDCCCCC:BBB00000
6532 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6534 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6536 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6538 emitcode ("anl", "a,#0x%02x",
6539 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6541 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6543 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6546 case 6: // AAAAAABB:CCCCCCDD
6547 emitcode ("anl", "a,#0x%02x",
6548 SRMask[shCount]); // 000000BB:CCCCCCDD
6549 emitcode ("mov", "c,acc.0"); // c = B
6550 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6552 AccAXRrl1 (x); // BCCCCCCD:D000000B
6553 AccAXRrl1 (x); // BBCCCCCC:DD000000
6555 emitcode("rrc","a");
6556 emitcode("xch","a,%s", x);
6557 emitcode("rrc","a");
6558 emitcode("mov","c,acc.0"); //<< get correct bit
6559 emitcode("xch","a,%s", x);
6561 emitcode("rrc","a");
6562 emitcode("xch","a,%s", x);
6563 emitcode("rrc","a");
6564 emitcode("xch","a,%s", x);
6567 case 7: // a:x <<= 7
6569 emitcode ("anl", "a,#0x%02x",
6570 SRMask[shCount]); // 0000000B:CCCCCCCD
6572 emitcode ("mov", "c,acc.0"); // c = B
6574 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6576 AccAXRrl1 (x); // BCCCCCCC:D0000000
6585 #ifdef BETTER_LITERAL_SHIFT
6587 /*-----------------------------------------------------------------*/
6588 /* AccAXRsh - right shift a:x known count (0..7) */
6589 /*-----------------------------------------------------------------*/
6591 AccAXRsh (char *x, int shCount)
6599 AccAXRrl1 (x); // 0->a:x
6604 AccAXRrl1 (x); // 0->a:x
6607 AccAXRrl1 (x); // 0->a:x
6612 case 5: // AAAAABBB:CCCCCDDD = a:x
6614 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6616 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6618 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6620 emitcode ("anl", "a,#0x%02x",
6621 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6623 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6625 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6627 emitcode ("anl", "a,#0x%02x",
6628 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6630 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6632 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6634 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6637 case 6: // AABBBBBB:CCDDDDDD
6639 emitcode ("mov", "c,acc.7");
6640 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6642 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6644 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6646 emitcode ("anl", "a,#0x%02x",
6647 SRMask[shCount]); // 000000AA:BBBBBBCC
6650 case 7: // ABBBBBBB:CDDDDDDD
6652 emitcode ("mov", "c,acc.7"); // c = A
6654 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6656 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6658 emitcode ("anl", "a,#0x%02x",
6659 SRMask[shCount]); // 0000000A:BBBBBBBC
6668 #ifdef BETTER_LITERAL_SHIFT
6669 /*-----------------------------------------------------------------*/
6670 /* AccAXRshS - right shift signed a:x known count (0..7) */
6671 /*-----------------------------------------------------------------*/
6673 AccAXRshS (char *x, int shCount)
6681 emitcode ("mov", "c,acc.7");
6682 AccAXRrl1 (x); // s->a:x
6686 emitcode ("mov", "c,acc.7");
6687 AccAXRrl1 (x); // s->a:x
6689 emitcode ("mov", "c,acc.7");
6690 AccAXRrl1 (x); // s->a:x
6695 case 5: // AAAAABBB:CCCCCDDD = a:x
6697 tlbl = newiTempLabel (NULL);
6698 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6700 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6702 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6704 emitcode ("anl", "a,#0x%02x",
6705 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6707 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6709 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6711 emitcode ("anl", "a,#0x%02x",
6712 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6714 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6716 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6718 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6720 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6721 emitcode ("orl", "a,#0x%02x",
6722 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6724 emitcode ("", "%05d$:", tlbl->key + 100);
6725 break; // SSSSAAAA:BBBCCCCC
6727 case 6: // AABBBBBB:CCDDDDDD
6729 tlbl = newiTempLabel (NULL);
6730 emitcode ("mov", "c,acc.7");
6731 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6733 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6735 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6737 emitcode ("anl", "a,#0x%02x",
6738 SRMask[shCount]); // 000000AA:BBBBBBCC
6740 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6741 emitcode ("orl", "a,#0x%02x",
6742 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6744 emitcode ("", "%05d$:", tlbl->key + 100);
6746 case 7: // ABBBBBBB:CDDDDDDD
6748 tlbl = newiTempLabel (NULL);
6749 emitcode ("mov", "c,acc.7"); // c = A
6751 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6753 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6755 emitcode ("anl", "a,#0x%02x",
6756 SRMask[shCount]); // 0000000A:BBBBBBBC
6758 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6759 emitcode ("orl", "a,#0x%02x",
6760 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6762 emitcode ("", "%05d$:", tlbl->key + 100);
6770 #ifdef BETTER_LITERAL_SHIFT
6772 _loadLeftIntoAx(char **lsb,
6778 // Get the initial value from left into a pair of registers.
6779 // MSB must be in A, LSB can be any register.
6781 // If the result is held in registers, it is an optimization
6782 // if the LSB can be held in the register which will hold the,
6783 // result LSB since this saves us from having to copy it into
6784 // the result following AccAXLsh.
6786 // If the result is addressed indirectly, this is not a gain.
6787 if (AOP_NEEDSACC(result))
6791 _startLazyDPSEvaluation();
6792 if (AOP_TYPE(left) == AOP_DPTR2)
6795 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6796 // get LSB in DP2_RESULT_REG.
6797 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6798 assert(!strcmp(leftByte, DP2_RESULT_REG));
6802 // get LSB into DP2_RESULT_REG
6803 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6804 if (strcmp(leftByte, DP2_RESULT_REG))
6807 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6810 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6811 assert(strcmp(leftByte, DP2_RESULT_REG));
6814 _endLazyDPSEvaluation();
6815 *lsb = DP2_RESULT_REG;
6819 if (sameRegs (AOP (result), AOP (left)) &&
6820 ((offl + MSB16) == offr))
6822 /* don't crash result[offr] */
6823 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6824 emitcode ("xch", "a,%s",
6825 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6829 movLeft2Result (left, offl, result, offr, 0);
6830 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6832 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6833 assert(strcmp(*lsb,"a"));
6838 _storeAxResults(char *lsb,
6842 _startLazyDPSEvaluation();
6843 if (AOP_NEEDSACC(result))
6845 /* We have to explicitly update the result LSB.
6847 emitcode("xch","a,%s", lsb);
6848 aopPut(AOP(result), "a", offr);
6849 emitcode("mov","a,%s", lsb);
6851 if (getDataSize (result) > 1)
6853 aopPut (AOP (result), "a", offr + MSB16);
6855 _endLazyDPSEvaluation();
6858 /*-----------------------------------------------------------------*/
6859 /* shiftL2Left2Result - shift left two bytes from left to result */
6860 /*-----------------------------------------------------------------*/
6862 shiftL2Left2Result (operand * left, int offl,
6863 operand * result, int offr, int shCount)
6867 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6869 AccAXLsh (lsb, shCount);
6871 _storeAxResults(lsb, result, offr);
6875 #ifdef BETTER_LITERAL_SHIFT
6876 /*-----------------------------------------------------------------*/
6877 /* shiftR2Left2Result - shift right two bytes from left to result */
6878 /*-----------------------------------------------------------------*/
6880 shiftR2Left2Result (operand * left, int offl,
6881 operand * result, int offr,
6882 int shCount, int sign)
6886 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6888 /* a:x >> shCount (x = lsb(result)) */
6891 AccAXRshS(lsb, shCount);
6895 AccAXRsh(lsb, shCount);
6898 _storeAxResults(lsb, result, offr);
6904 /*-----------------------------------------------------------------*/
6905 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6906 /*-----------------------------------------------------------------*/
6908 shiftLLeftOrResult (operand * left, int offl,
6909 operand * result, int offr, int shCount)
6911 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6912 /* shift left accumulator */
6914 /* or with result */
6915 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6916 /* back to result */
6917 aopPut (AOP (result), "a", offr);
6923 /*-----------------------------------------------------------------*/
6924 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6925 /*-----------------------------------------------------------------*/
6927 shiftRLeftOrResult (operand * left, int offl,
6928 operand * result, int offr, int shCount)
6930 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6931 /* shift right accumulator */
6933 /* or with result */
6934 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6935 /* back to result */
6936 aopPut (AOP (result), "a", offr);
6940 #ifdef BETTER_LITERAL_SHIFT
6941 /*-----------------------------------------------------------------*/
6942 /* genlshOne - left shift a one byte quantity by known count */
6943 /*-----------------------------------------------------------------*/
6945 genlshOne (operand * result, operand * left, int shCount)
6947 D (emitcode (";", "genlshOne "););
6948 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6952 #ifdef BETTER_LITERAL_SHIFT
6953 /*-----------------------------------------------------------------*/
6954 /* genlshTwo - left shift two bytes by known amount != 0 */
6955 /*-----------------------------------------------------------------*/
6957 genlshTwo (operand * result, operand * left, int shCount)
6961 D (emitcode (";", "genlshTwo "););
6963 size = getDataSize (result);
6965 /* if shCount >= 8 */
6970 _startLazyDPSEvaluation();
6976 _endLazyDPSEvaluation();
6977 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6978 aopPut (AOP (result), zero, LSB);
6982 movLeft2Result (left, LSB, result, MSB16, 0);
6983 aopPut (AOP (result), zero, LSB);
6984 _endLazyDPSEvaluation();
6989 aopPut (AOP (result), zero, LSB);
6990 _endLazyDPSEvaluation();
6994 /* 1 <= shCount <= 7 */
6999 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7003 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7011 /*-----------------------------------------------------------------*/
7012 /* shiftLLong - shift left one long from left to result */
7013 /* offl = LSB or MSB16 */
7014 /*-----------------------------------------------------------------*/
7016 shiftLLong (operand * left, operand * result, int offr)
7019 int size = AOP_SIZE (result);
7021 if (size >= LSB + offr)
7023 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7025 emitcode ("add", "a,acc");
7026 if (sameRegs (AOP (left), AOP (result)) &&
7027 size >= MSB16 + offr && offr != LSB)
7028 emitcode ("xch", "a,%s",
7029 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7031 aopPut (AOP (result), "a", LSB + offr);
7034 if (size >= MSB16 + offr)
7036 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7038 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7041 emitcode ("rlc", "a");
7042 if (sameRegs (AOP (left), AOP (result)) &&
7043 size >= MSB24 + offr && offr != LSB)
7044 emitcode ("xch", "a,%s",
7045 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7047 aopPut (AOP (result), "a", MSB16 + offr);
7050 if (size >= MSB24 + offr)
7052 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7054 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7057 emitcode ("rlc", "a");
7058 if (sameRegs (AOP (left), AOP (result)) &&
7059 size >= MSB32 + offr && offr != LSB)
7060 emitcode ("xch", "a,%s",
7061 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7063 aopPut (AOP (result), "a", MSB24 + offr);
7066 if (size > MSB32 + offr)
7068 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7070 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7073 emitcode ("rlc", "a");
7074 aopPut (AOP (result), "a", MSB32 + offr);
7077 aopPut (AOP (result), zero, LSB);
7083 /*-----------------------------------------------------------------*/
7084 /* genlshFour - shift four byte by a known amount != 0 */
7085 /*-----------------------------------------------------------------*/
7087 genlshFour (operand * result, operand * left, int shCount)
7091 D (emitcode (";", "genlshFour ");
7094 size = AOP_SIZE (result);
7096 /* if shifting more that 3 bytes */
7101 /* lowest order of left goes to the highest
7102 order of the destination */
7103 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7105 movLeft2Result (left, LSB, result, MSB32, 0);
7106 aopPut (AOP (result), zero, LSB);
7107 aopPut (AOP (result), zero, MSB16);
7108 aopPut (AOP (result), zero, MSB24);
7112 /* more than two bytes */
7113 else if (shCount >= 16)
7115 /* lower order two bytes goes to higher order two bytes */
7117 /* if some more remaining */
7119 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7122 movLeft2Result (left, MSB16, result, MSB32, 0);
7123 movLeft2Result (left, LSB, result, MSB24, 0);
7125 aopPut (AOP (result), zero, MSB16);
7126 aopPut (AOP (result), zero, LSB);
7130 /* if more than 1 byte */
7131 else if (shCount >= 8)
7133 /* lower order three bytes goes to higher order three bytes */
7138 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7140 movLeft2Result (left, LSB, result, MSB16, 0);
7146 movLeft2Result (left, MSB24, result, MSB32, 0);
7147 movLeft2Result (left, MSB16, result, MSB24, 0);
7148 movLeft2Result (left, LSB, result, MSB16, 0);
7149 aopPut (AOP (result), zero, LSB);
7151 else if (shCount == 1)
7152 shiftLLong (left, result, MSB16);
7155 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7156 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7157 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7158 aopPut (AOP (result), zero, LSB);
7163 /* 1 <= shCount <= 7 */
7164 else if (shCount <= 2)
7166 shiftLLong (left, result, LSB);
7168 shiftLLong (result, result, LSB);
7170 /* 3 <= shCount <= 7, optimize */
7173 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7174 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7175 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7180 #ifdef BETTER_LITERAL_SHIFT
7181 /*-----------------------------------------------------------------*/
7182 /* genLeftShiftLiteral - left shifting by known count */
7183 /*-----------------------------------------------------------------*/
7185 genLeftShiftLiteral (operand * left,
7190 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7193 size = getSize (operandType (result));
7195 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7197 /* We only handle certain easy cases so far. */
7199 && (shCount < (size * 8))
7203 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7207 freeAsmop (right, NULL, ic, TRUE);
7209 aopOp(left, ic, FALSE, FALSE);
7210 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7213 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7215 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7216 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7218 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7221 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7223 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7224 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7226 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7232 emitcode ("; shift left ", "result %d, left %d", size,
7236 /* I suppose that the left size >= result size */
7239 _startLazyDPSEvaluation();
7242 movLeft2Result (left, size, result, size, 0);
7244 _endLazyDPSEvaluation();
7246 else if (shCount >= (size * 8))
7248 _startLazyDPSEvaluation();
7251 aopPut (AOP (result), zero, size);
7253 _endLazyDPSEvaluation();
7260 genlshOne (result, left, shCount);
7264 genlshTwo (result, left, shCount);
7268 genlshFour (result, left, shCount);
7272 fprintf(stderr, "*** ack! mystery literal shift!\n");
7276 freeAsmop (left, NULL, ic, TRUE);
7277 freeAsmop (result, NULL, ic, TRUE);
7282 /*-----------------------------------------------------------------*/
7283 /* genLeftShift - generates code for left shifting */
7284 /*-----------------------------------------------------------------*/
7286 genLeftShift (iCode * ic)
7288 operand *left, *right, *result;
7291 symbol *tlbl, *tlbl1;
7293 D (emitcode (";", "genLeftShift "););
7295 right = IC_RIGHT (ic);
7296 left = IC_LEFT (ic);
7297 result = IC_RESULT (ic);
7299 aopOp (right, ic, FALSE, FALSE);
7302 #ifdef BETTER_LITERAL_SHIFT
7303 /* if the shift count is known then do it
7304 as efficiently as possible */
7305 if (AOP_TYPE (right) == AOP_LIT)
7307 if (genLeftShiftLiteral (left, right, result, ic))
7314 /* shift count is unknown then we have to form
7315 a loop get the loop count in B : Note: we take
7316 only the lower order byte since shifting
7317 more that 32 bits make no sense anyway, ( the
7318 largest size of an object can be only 32 bits ) */
7320 if (AOP_TYPE (right) == AOP_LIT)
7322 /* Really should be handled by genLeftShiftLiteral,
7323 * but since I'm too lazy to fix that today, at least we can make
7324 * some small improvement.
7326 emitcode("mov", "b,#0x%02x",
7327 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7331 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7332 emitcode ("inc", "b");
7334 freeAsmop (right, NULL, ic, TRUE);
7335 aopOp (left, ic, FALSE, FALSE);
7336 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7338 /* now move the left to the result if they are not the
7340 if (!sameRegs (AOP (left), AOP (result)) &&
7341 AOP_SIZE (result) > 1)
7344 size = AOP_SIZE (result);
7346 _startLazyDPSEvaluation ();
7349 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7350 if (*l == '@' && (IS_AOP_PREG (result)))
7353 emitcode ("mov", "a,%s", l);
7354 aopPut (AOP (result), "a", offset);
7357 aopPut (AOP (result), l, offset);
7360 _endLazyDPSEvaluation ();
7363 tlbl = newiTempLabel (NULL);
7364 size = AOP_SIZE (result);
7366 tlbl1 = newiTempLabel (NULL);
7368 /* if it is only one byte then */
7371 symbol *tlbl1 = newiTempLabel (NULL);
7373 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7375 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7376 emitcode ("", "%05d$:", tlbl->key + 100);
7377 emitcode ("add", "a,acc");
7378 emitcode ("", "%05d$:", tlbl1->key + 100);
7379 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7380 aopPut (AOP (result), "a", 0);
7384 reAdjustPreg (AOP (result));
7386 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7387 emitcode ("", "%05d$:", tlbl->key + 100);
7388 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7390 emitcode ("add", "a,acc");
7391 aopPut (AOP (result), "a", offset++);
7392 _startLazyDPSEvaluation ();
7395 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7397 emitcode ("rlc", "a");
7398 aopPut (AOP (result), "a", offset++);
7400 _endLazyDPSEvaluation ();
7401 reAdjustPreg (AOP (result));
7403 emitcode ("", "%05d$:", tlbl1->key + 100);
7404 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7406 freeAsmop (left, NULL, ic, TRUE);
7407 freeAsmop (result, NULL, ic, TRUE);
7410 #ifdef BETTER_LITERAL_SHIFT
7411 /*-----------------------------------------------------------------*/
7412 /* genrshOne - right shift a one byte quantity by known count */
7413 /*-----------------------------------------------------------------*/
7415 genrshOne (operand * result, operand * left,
7416 int shCount, int sign)
7418 D (emitcode (";", "genrshOne"););
7419 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7423 #ifdef BETTER_LITERAL_SHIFT
7424 /*-----------------------------------------------------------------*/
7425 /* genrshTwo - right shift two bytes by known amount != 0 */
7426 /*-----------------------------------------------------------------*/
7428 genrshTwo (operand * result, operand * left,
7429 int shCount, int sign)
7431 D (emitcode (";", "genrshTwo"););
7433 /* if shCount >= 8 */
7437 _startLazyDPSEvaluation();
7440 shiftR1Left2Result (left, MSB16, result, LSB,
7445 movLeft2Result (left, MSB16, result, LSB, sign);
7447 addSign (result, MSB16, sign);
7448 _endLazyDPSEvaluation();
7451 /* 1 <= shCount <= 7 */
7454 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7461 /*-----------------------------------------------------------------*/
7462 /* shiftRLong - shift right one long from left to result */
7463 /* offl = LSB or MSB16 */
7464 /*-----------------------------------------------------------------*/
7466 shiftRLong (operand * left, int offl,
7467 operand * result, int sign)
7469 int isSameRegs=sameRegs(AOP(left),AOP(result));
7471 if (isSameRegs && offl>1) {
7472 // we are in big trouble, but this shouldn't happen
7473 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7476 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7481 emitcode ("rlc", "a");
7482 emitcode ("subb", "a,acc");
7483 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7485 aopPut (AOP(result), zero, MSB32);
7490 emitcode ("clr", "c");
7492 emitcode ("mov", "c,acc.7");
7495 emitcode ("rrc", "a");
7497 if (isSameRegs && offl==MSB16) {
7498 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7500 aopPut (AOP (result), "a", MSB32);
7501 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7504 emitcode ("rrc", "a");
7505 if (isSameRegs && offl==1) {
7506 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7508 aopPut (AOP (result), "a", MSB24);
7509 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7511 emitcode ("rrc", "a");
7512 aopPut (AOP (result), "a", MSB16 - offl);
7516 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7517 emitcode ("rrc", "a");
7518 aopPut (AOP (result), "a", LSB);
7525 /*-----------------------------------------------------------------*/
7526 /* genrshFour - shift four byte by a known amount != 0 */
7527 /*-----------------------------------------------------------------*/
7529 genrshFour (operand * result, operand * left,
7530 int shCount, int sign)
7532 D (emitcode (";", "genrshFour");
7535 /* if shifting more that 3 bytes */
7540 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7542 movLeft2Result (left, MSB32, result, LSB, sign);
7543 addSign (result, MSB16, sign);
7545 else if (shCount >= 16)
7549 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7552 movLeft2Result (left, MSB24, result, LSB, 0);
7553 movLeft2Result (left, MSB32, result, MSB16, sign);
7555 addSign (result, MSB24, sign);
7557 else if (shCount >= 8)
7561 shiftRLong (left, MSB16, result, sign);
7562 else if (shCount == 0)
7564 movLeft2Result (left, MSB16, result, LSB, 0);
7565 movLeft2Result (left, MSB24, result, MSB16, 0);
7566 movLeft2Result (left, MSB32, result, MSB24, sign);
7567 addSign (result, MSB32, sign);
7571 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7572 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7573 /* the last shift is signed */
7574 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7575 addSign (result, MSB32, sign);
7579 { /* 1 <= shCount <= 7 */
7582 shiftRLong (left, LSB, result, sign);
7584 shiftRLong (result, LSB, result, sign);
7588 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7589 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7590 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7596 #ifdef BETTER_LITERAL_SHIFT
7597 /*-----------------------------------------------------------------*/
7598 /* genRightShiftLiteral - right shifting by known count */
7599 /*-----------------------------------------------------------------*/
7601 genRightShiftLiteral (operand * left,
7607 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7610 size = getSize (operandType (result));
7612 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7614 /* We only handle certain easy cases so far. */
7616 && (shCount < (size * 8))
7620 D(emitcode (";", "genRightShiftLiteral wimping out"););
7624 freeAsmop (right, NULL, ic, TRUE);
7626 aopOp (left, ic, FALSE, FALSE);
7627 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7630 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7634 /* test the LEFT size !!! */
7636 /* I suppose that the left size >= result size */
7639 size = getDataSize (result);
7640 _startLazyDPSEvaluation();
7643 movLeft2Result (left, size, result, size, 0);
7645 _endLazyDPSEvaluation();
7647 else if (shCount >= (size * 8))
7651 /* get sign in acc.7 */
7652 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7654 addSign (result, LSB, sign);
7661 genrshOne (result, left, shCount, sign);
7665 genrshTwo (result, left, shCount, sign);
7669 genrshFour (result, left, shCount, sign);
7676 freeAsmop (left, NULL, ic, TRUE);
7677 freeAsmop (result, NULL, ic, TRUE);
7683 /*-----------------------------------------------------------------*/
7684 /* genSignedRightShift - right shift of signed number */
7685 /*-----------------------------------------------------------------*/
7687 genSignedRightShift (iCode * ic)
7689 operand *right, *left, *result;
7692 symbol *tlbl, *tlbl1;
7694 D (emitcode (";", "genSignedRightShift "););
7696 /* we do it the hard way put the shift count in b
7697 and loop thru preserving the sign */
7699 right = IC_RIGHT (ic);
7700 left = IC_LEFT (ic);
7701 result = IC_RESULT (ic);
7703 aopOp (right, ic, FALSE, FALSE);
7705 #ifdef BETTER_LITERAL_SHIFT
7706 if (AOP_TYPE (right) == AOP_LIT)
7708 if (genRightShiftLiteral (left, right, result, ic, 1))
7714 /* shift count is unknown then we have to form
7715 a loop get the loop count in B : Note: we take
7716 only the lower order byte since shifting
7717 more that 32 bits make no sense anyway, ( the
7718 largest size of an object can be only 32 bits ) */
7720 if (AOP_TYPE (right) == AOP_LIT)
7722 /* Really should be handled by genRightShiftLiteral,
7723 * but since I'm too lazy to fix that today, at least we can make
7724 * some small improvement.
7726 emitcode("mov", "b,#0x%02x",
7727 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7731 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7732 emitcode ("inc", "b");
7734 freeAsmop (right, NULL, ic, TRUE);
7735 aopOp (left, ic, FALSE, FALSE);
7736 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7738 /* now move the left to the result if they are not the
7740 if (!sameRegs (AOP (left), AOP (result)) &&
7741 AOP_SIZE (result) > 1)
7744 size = AOP_SIZE (result);
7746 _startLazyDPSEvaluation ();
7749 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7750 if (*l == '@' && IS_AOP_PREG (result))
7753 emitcode ("mov", "a,%s", l);
7754 aopPut (AOP (result), "a", offset);
7757 aopPut (AOP (result), l, offset);
7760 _endLazyDPSEvaluation ();
7763 /* mov the highest order bit to OVR */
7764 tlbl = newiTempLabel (NULL);
7765 tlbl1 = newiTempLabel (NULL);
7767 size = AOP_SIZE (result);
7769 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7770 emitcode ("rlc", "a");
7771 emitcode ("mov", "ov,c");
7772 /* if it is only one byte then */
7775 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7777 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7778 emitcode ("", "%05d$:", tlbl->key + 100);
7779 emitcode ("mov", "c,ov");
7780 emitcode ("rrc", "a");
7781 emitcode ("", "%05d$:", tlbl1->key + 100);
7782 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7783 aopPut (AOP (result), "a", 0);
7787 reAdjustPreg (AOP (result));
7788 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7789 emitcode ("", "%05d$:", tlbl->key + 100);
7790 emitcode ("mov", "c,ov");
7791 _startLazyDPSEvaluation ();
7794 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7796 emitcode ("rrc", "a");
7797 aopPut (AOP (result), "a", offset--);
7799 _endLazyDPSEvaluation ();
7800 reAdjustPreg (AOP (result));
7801 emitcode ("", "%05d$:", tlbl1->key + 100);
7802 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7805 freeAsmop (left, NULL, ic, TRUE);
7806 freeAsmop (result, NULL, ic, TRUE);
7809 /*-----------------------------------------------------------------*/
7810 /* genRightShift - generate code for right shifting */
7811 /*-----------------------------------------------------------------*/
7813 genRightShift (iCode * ic)
7815 operand *right, *left, *result;
7819 symbol *tlbl, *tlbl1;
7821 D (emitcode (";", "genRightShift "););
7823 /* if signed then we do it the hard way preserve the
7824 sign bit moving it inwards */
7825 retype = getSpec (operandType (IC_RESULT (ic)));
7827 if (!SPEC_USIGN (retype))
7829 genSignedRightShift (ic);
7833 /* signed & unsigned types are treated the same : i.e. the
7834 signed is NOT propagated inwards : quoting from the
7835 ANSI - standard : "for E1 >> E2, is equivalent to division
7836 by 2**E2 if unsigned or if it has a non-negative value,
7837 otherwise the result is implementation defined ", MY definition
7838 is that the sign does not get propagated */
7840 right = IC_RIGHT (ic);
7841 left = IC_LEFT (ic);
7842 result = IC_RESULT (ic);
7844 aopOp (right, ic, FALSE, FALSE);
7846 #ifdef BETTER_LITERAL_SHIFT
7847 /* if the shift count is known then do it
7848 as efficiently as possible */
7849 if (AOP_TYPE (right) == AOP_LIT)
7851 if (genRightShiftLiteral (left, right, result, ic, 0))
7858 /* shift count is unknown then we have to form
7859 a loop get the loop count in B : Note: we take
7860 only the lower order byte since shifting
7861 more that 32 bits make no sense anyway, ( the
7862 largest size of an object can be only 32 bits ) */
7864 if (AOP_TYPE (right) == AOP_LIT)
7866 /* Really should be handled by genRightShiftLiteral,
7867 * but since I'm too lazy to fix that today, at least we can make
7868 * some small improvement.
7870 emitcode("mov", "b,#0x%02x",
7871 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7875 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7876 emitcode ("inc", "b");
7878 freeAsmop (right, NULL, ic, TRUE);
7879 aopOp (left, ic, FALSE, FALSE);
7880 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7882 /* now move the left to the result if they are not the
7884 if (!sameRegs (AOP (left), AOP (result)) &&
7885 AOP_SIZE (result) > 1)
7888 size = AOP_SIZE (result);
7890 _startLazyDPSEvaluation ();
7893 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7894 if (*l == '@' && IS_AOP_PREG (result))
7897 emitcode ("mov", "a,%s", l);
7898 aopPut (AOP (result), "a", offset);
7901 aopPut (AOP (result), l, offset);
7904 _endLazyDPSEvaluation ();
7907 tlbl = newiTempLabel (NULL);
7908 tlbl1 = newiTempLabel (NULL);
7909 size = AOP_SIZE (result);
7912 /* if it is only one byte then */
7915 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7917 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7918 emitcode ("", "%05d$:", tlbl->key + 100);
7920 emitcode ("rrc", "a");
7921 emitcode ("", "%05d$:", tlbl1->key + 100);
7922 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7923 aopPut (AOP (result), "a", 0);
7927 reAdjustPreg (AOP (result));
7928 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7929 emitcode ("", "%05d$:", tlbl->key + 100);
7931 _startLazyDPSEvaluation ();
7934 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7936 emitcode ("rrc", "a");
7937 aopPut (AOP (result), "a", offset--);
7939 _endLazyDPSEvaluation ();
7940 reAdjustPreg (AOP (result));
7942 emitcode ("", "%05d$:", tlbl1->key + 100);
7943 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7946 freeAsmop (left, NULL, ic, TRUE);
7947 freeAsmop (result, NULL, ic, TRUE);
7950 /*-----------------------------------------------------------------*/
7951 /* genUnpackBits - generates code for unpacking bits */
7952 /*-----------------------------------------------------------------*/
7954 genUnpackBits (operand * result, char *rname, int ptype)
7961 D (emitcode (";", "genUnpackBits ");
7964 etype = getSpec (operandType (result));
7966 /* read the first byte */
7972 emitcode ("mov", "a,@%s", rname);
7976 emitcode ("movx", "a,@%s", rname);
7980 emitcode ("movx", "a,@dptr");
7984 emitcode ("clr", "a");
7985 emitcode ("movc", "a,@a+dptr");
7989 emitcode ("lcall", "__gptrget");
7993 /* if we have bitdisplacement then it fits */
7994 /* into this byte completely or if length is */
7995 /* less than a byte */
7996 if ((shCnt = SPEC_BSTR (etype)) ||
7997 (SPEC_BLEN (etype) <= 8))
8000 /* shift right acc */
8003 emitcode ("anl", "a,#0x%02x",
8004 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8005 aopPut (AOP (result), "a", offset);
8009 /* bit field did not fit in a byte */
8010 rlen = SPEC_BLEN (etype) - 8;
8011 aopPut (AOP (result), "a", offset++);
8020 emitcode ("inc", "%s", rname);
8021 emitcode ("mov", "a,@%s", rname);
8025 emitcode ("inc", "%s", rname);
8026 emitcode ("movx", "a,@%s", rname);
8030 emitcode ("inc", "dptr");
8031 emitcode ("movx", "a,@dptr");
8035 emitcode ("clr", "a");
8036 emitcode ("inc", "dptr");
8037 emitcode ("movc", "a,@a+dptr");
8041 emitcode ("inc", "dptr");
8042 emitcode ("lcall", "__gptrget");
8047 /* if we are done */
8051 aopPut (AOP (result), "a", offset++);
8057 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8058 aopPut (AOP (result), "a", offset);
8065 /*-----------------------------------------------------------------*/
8066 /* genDataPointerGet - generates code when ptr offset is known */
8067 /*-----------------------------------------------------------------*/
8069 genDataPointerGet (operand * left,
8075 int size, offset = 0;
8076 aopOp (result, ic, TRUE, FALSE);
8078 /* get the string representation of the name */
8079 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8080 size = AOP_SIZE (result);
8081 _startLazyDPSEvaluation ();
8085 sprintf (buffer, "(%s + %d)", l + 1, offset);
8087 sprintf (buffer, "%s", l + 1);
8088 aopPut (AOP (result), buffer, offset++);
8090 _endLazyDPSEvaluation ();
8092 freeAsmop (left, NULL, ic, TRUE);
8093 freeAsmop (result, NULL, ic, TRUE);
8096 /*-----------------------------------------------------------------*/
8097 /* genNearPointerGet - emitcode for near pointer fetch */
8098 /*-----------------------------------------------------------------*/
8100 genNearPointerGet (operand * left,
8107 sym_link *rtype, *retype, *letype;
8108 sym_link *ltype = operandType (left);
8111 rtype = operandType (result);
8112 retype = getSpec (rtype);
8113 letype = getSpec (ltype);
8115 aopOp (left, ic, FALSE, FALSE);
8117 /* if left is rematerialisable and
8118 result is not bit variable type and
8119 the left is pointer to data space i.e
8120 lower 128 bytes of space */
8121 if (AOP_TYPE (left) == AOP_IMMD &&
8122 !IS_BITVAR (retype) &&
8123 !IS_BITVAR (letype) &&
8124 DCL_TYPE (ltype) == POINTER)
8126 genDataPointerGet (left, result, ic);
8130 /* if the value is already in a pointer register
8131 then don't need anything more */
8132 if (!AOP_INPREG (AOP (left)))
8134 /* otherwise get a free pointer register */
8136 preg = getFreePtr (ic, &aop, FALSE);
8137 emitcode ("mov", "%s,%s",
8139 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8143 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8145 freeAsmop (left, NULL, ic, TRUE);
8146 aopOp (result, ic, FALSE, FALSE);
8148 /* if bitfield then unpack the bits */
8149 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8150 genUnpackBits (result, rname, POINTER);
8153 /* we have can just get the values */
8154 int size = AOP_SIZE (result);
8159 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8162 emitcode ("mov", "a,@%s", rname);
8163 aopPut (AOP (result), "a", offset);
8167 sprintf (buffer, "@%s", rname);
8168 aopPut (AOP (result), buffer, offset);
8172 emitcode ("inc", "%s", rname);
8176 /* now some housekeeping stuff */
8179 /* we had to allocate for this iCode */
8180 freeAsmop (NULL, aop, ic, TRUE);
8184 /* we did not allocate which means left
8185 already in a pointer register, then
8186 if size > 0 && this could be used again
8187 we have to point it back to where it
8189 if (AOP_SIZE (result) > 1 &&
8190 !OP_SYMBOL (left)->remat &&
8191 (OP_SYMBOL (left)->liveTo > ic->seq ||
8194 int size = AOP_SIZE (result) - 1;
8196 emitcode ("dec", "%s", rname);
8201 freeAsmop (result, NULL, ic, TRUE);
8205 /*-----------------------------------------------------------------*/
8206 /* genPagedPointerGet - emitcode for paged pointer fetch */
8207 /*-----------------------------------------------------------------*/
8209 genPagedPointerGet (operand * left,
8216 sym_link *rtype, *retype, *letype;
8218 rtype = operandType (result);
8219 retype = getSpec (rtype);
8220 letype = getSpec (operandType (left));
8221 aopOp (left, ic, FALSE, FALSE);
8223 /* if the value is already in a pointer register
8224 then don't need anything more */
8225 if (!AOP_INPREG (AOP (left)))
8227 /* otherwise get a free pointer register */
8229 preg = getFreePtr (ic, &aop, FALSE);
8230 emitcode ("mov", "%s,%s",
8232 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8236 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8238 freeAsmop (left, NULL, ic, TRUE);
8239 aopOp (result, ic, FALSE, FALSE);
8241 /* if bitfield then unpack the bits */
8242 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8243 genUnpackBits (result, rname, PPOINTER);
8246 /* we have can just get the values */
8247 int size = AOP_SIZE (result);
8253 emitcode ("movx", "a,@%s", rname);
8254 aopPut (AOP (result), "a", offset);
8259 emitcode ("inc", "%s", rname);
8263 /* now some housekeeping stuff */
8266 /* we had to allocate for this iCode */
8267 freeAsmop (NULL, aop, ic, TRUE);
8271 /* we did not allocate which means left
8272 already in a pointer register, then
8273 if size > 0 && this could be used again
8274 we have to point it back to where it
8276 if (AOP_SIZE (result) > 1 &&
8277 !OP_SYMBOL (left)->remat &&
8278 (OP_SYMBOL (left)->liveTo > ic->seq ||
8281 int size = AOP_SIZE (result) - 1;
8283 emitcode ("dec", "%s", rname);
8288 freeAsmop (result, NULL, ic, TRUE);
8293 /*-----------------------------------------------------------------*/
8294 /* genFarPointerGet - gget value from far space */
8295 /*-----------------------------------------------------------------*/
8297 genFarPointerGet (operand * left,
8298 operand * result, iCode * ic)
8301 sym_link *retype = getSpec (operandType (result));
8302 sym_link *letype = getSpec (operandType (left));
8303 D (emitcode (";", "genFarPointerGet");
8306 aopOp (left, ic, FALSE, FALSE);
8308 /* if the operand is already in dptr
8309 then we do nothing else we move the value to dptr */
8310 if (AOP_TYPE (left) != AOP_STR)
8312 /* if this is remateriazable */
8313 if (AOP_TYPE (left) == AOP_IMMD)
8315 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8319 /* we need to get it byte by byte */
8320 _startLazyDPSEvaluation ();
8321 if (AOP_TYPE (left) != AOP_DPTR)
8323 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8324 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8325 if (options.model == MODEL_FLAT24)
8326 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8330 /* We need to generate a load to DPTR indirect through DPTR. */
8331 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8333 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8334 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8335 if (options.model == MODEL_FLAT24)
8336 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8337 emitcode ("pop", "dph");
8338 emitcode ("pop", "dpl");
8340 _endLazyDPSEvaluation ();
8343 /* so dptr know contains the address */
8344 freeAsmop (left, NULL, ic, TRUE);
8345 aopOp (result, ic, FALSE, TRUE);
8347 /* if bit then unpack */
8348 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8349 genUnpackBits (result, "dptr", FPOINTER);
8352 size = AOP_SIZE (result);
8355 _startLazyDPSEvaluation ();
8362 emitcode ("movx", "a,@dptr");
8364 emitcode ("inc", "dptr");
8366 aopPut (AOP (result), "a", offset++);
8368 _endLazyDPSEvaluation ();
8371 freeAsmop (result, NULL, ic, TRUE);
8374 /*-----------------------------------------------------------------*/
8375 /* emitcodePointerGet - gget value from code space */
8376 /*-----------------------------------------------------------------*/
8378 emitcodePointerGet (operand * left,
8379 operand * result, iCode * ic)
8382 sym_link *retype = getSpec (operandType (result));
8384 aopOp (left, ic, FALSE, FALSE);
8386 /* if the operand is already in dptr
8387 then we do nothing else we move the value to dptr */
8388 if (AOP_TYPE (left) != AOP_STR)
8390 /* if this is remateriazable */
8391 if (AOP_TYPE (left) == AOP_IMMD)
8393 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8396 { /* we need to get it byte by byte */
8397 _startLazyDPSEvaluation ();
8398 if (AOP_TYPE (left) != AOP_DPTR)
8400 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8401 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8402 if (options.model == MODEL_FLAT24)
8403 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8407 /* We need to generate a load to DPTR indirect through DPTR. */
8408 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8410 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8411 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8412 if (options.model == MODEL_FLAT24)
8413 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8414 emitcode ("pop", "dph");
8415 emitcode ("pop", "dpl");
8417 _endLazyDPSEvaluation ();
8420 /* so dptr know contains the address */
8421 freeAsmop (left, NULL, ic, TRUE);
8422 aopOp (result, ic, FALSE, TRUE);
8424 /* if bit then unpack */
8425 if (IS_BITVAR (retype))
8426 genUnpackBits (result, "dptr", CPOINTER);
8429 size = AOP_SIZE (result);
8432 _startLazyDPSEvaluation ();
8438 emitcode ("clr", "a");
8439 emitcode ("movc", "a,@a+dptr");
8441 emitcode ("inc", "dptr");
8442 aopPut (AOP (result), "a", offset++);
8444 _endLazyDPSEvaluation ();
8447 freeAsmop (result, NULL, ic, TRUE);
8450 /*-----------------------------------------------------------------*/
8451 /* genGenPointerGet - gget value from generic pointer space */
8452 /*-----------------------------------------------------------------*/
8454 genGenPointerGet (operand * left,
8455 operand * result, iCode * ic)
8458 sym_link *retype = getSpec (operandType (result));
8459 sym_link *letype = getSpec (operandType (left));
8461 D (emitcode (";", "genGenPointerGet "); );
8463 aopOp (left, ic, FALSE, TRUE);
8465 /* if the operand is already in dptr
8466 then we do nothing else we move the value to dptr */
8467 if (AOP_TYPE (left) != AOP_STR)
8469 /* if this is remateriazable */
8470 if (AOP_TYPE (left) == AOP_IMMD)
8472 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8473 emitcode ("mov", "b,#%d", pointerCode (retype));
8476 { /* we need to get it byte by byte */
8477 _startLazyDPSEvaluation ();
8478 if (AOP(left)->type==AOP_DPTR2) {
8480 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8483 emitcode ("mov", "dpl,%s", l);
8484 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8487 emitcode ("mov", "dph,%s", l);
8488 if (options.model == MODEL_FLAT24) {
8489 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8492 emitcode ("mov", "dpx,%s", l);
8493 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8495 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8498 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8499 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8500 if (options.model == MODEL_FLAT24) {
8501 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8502 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8504 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8507 _endLazyDPSEvaluation ();
8510 /* so dptr know contains the address */
8511 freeAsmop (left, NULL, ic, TRUE);
8512 aopOp (result, ic, FALSE, TRUE);
8514 /* if bit then unpack */
8515 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8516 genUnpackBits (result, "dptr", GPOINTER);
8519 size = AOP_SIZE (result);
8524 emitcode ("lcall", "__gptrget");
8525 aopPut (AOP (result), "a", offset++);
8527 emitcode ("inc", "dptr");
8531 freeAsmop (result, NULL, ic, TRUE);
8534 /*-----------------------------------------------------------------*/
8535 /* genPointerGet - generate code for pointer get */
8536 /*-----------------------------------------------------------------*/
8538 genPointerGet (iCode * ic)
8540 operand *left, *result;
8541 sym_link *type, *etype;
8544 D (emitcode (";", "genPointerGet ");
8547 left = IC_LEFT (ic);
8548 result = IC_RESULT (ic);
8550 /* depending on the type of pointer we need to
8551 move it to the correct pointer register */
8552 type = operandType (left);
8553 etype = getSpec (type);
8554 /* if left is of type of pointer then it is simple */
8555 if (IS_PTR (type) && !IS_FUNC (type->next))
8556 p_type = DCL_TYPE (type);
8559 /* we have to go by the storage class */
8560 p_type = PTR_TYPE (SPEC_OCLS (etype));
8563 /* now that we have the pointer type we assign
8564 the pointer values */
8570 genNearPointerGet (left, result, ic);
8574 genPagedPointerGet (left, result, ic);
8578 genFarPointerGet (left, result, ic);
8582 emitcodePointerGet (left, result, ic);
8586 genGenPointerGet (left, result, ic);
8592 /*-----------------------------------------------------------------*/
8593 /* genPackBits - generates code for packed bit storage */
8594 /*-----------------------------------------------------------------*/
8596 genPackBits (sym_link * etype,
8598 char *rname, int p_type)
8606 blen = SPEC_BLEN (etype);
8607 bstr = SPEC_BSTR (etype);
8609 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8612 /* if the bit lenth is less than or */
8613 /* it exactly fits a byte then */
8614 if (SPEC_BLEN (etype) <= 8)
8616 shCount = SPEC_BSTR (etype);
8618 /* shift left acc */
8621 if (SPEC_BLEN (etype) < 8)
8622 { /* if smaller than a byte */
8628 emitcode ("mov", "b,a");
8629 emitcode ("mov", "a,@%s", rname);
8633 emitcode ("mov", "b,a");
8634 emitcode ("movx", "a,@dptr");
8638 emitcode ("push", "b");
8639 emitcode ("push", "acc");
8640 emitcode ("lcall", "__gptrget");
8641 emitcode ("pop", "b");
8645 emitcode ("anl", "a,#0x%02x", (unsigned char)
8646 ((unsigned char) (0xFF << (blen + bstr)) |
8647 (unsigned char) (0xFF >> (8 - bstr))));
8648 emitcode ("orl", "a,b");
8649 if (p_type == GPOINTER)
8650 emitcode ("pop", "b");
8657 emitcode ("mov", "@%s,a", rname);
8661 emitcode ("movx", "@dptr,a");
8665 emitcode ("lcall", "__gptrput");
8670 if (SPEC_BLEN (etype) <= 8)
8673 emitcode ("inc", "%s", rname);
8674 rLen = SPEC_BLEN (etype);
8676 /* now generate for lengths greater than one byte */
8680 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8692 emitcode ("mov", "@%s,a", rname);
8695 emitcode ("mov", "@%s,%s", rname, l);
8700 emitcode ("movx", "@dptr,a");
8705 emitcode ("lcall", "__gptrput");
8708 emitcode ("inc", "%s", rname);
8713 /* last last was not complete */
8716 /* save the byte & read byte */
8720 emitcode ("mov", "b,a");
8721 emitcode ("mov", "a,@%s", rname);
8725 emitcode ("mov", "b,a");
8726 emitcode ("movx", "a,@dptr");
8730 emitcode ("push", "b");
8731 emitcode ("push", "acc");
8732 emitcode ("lcall", "__gptrget");
8733 emitcode ("pop", "b");
8737 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8738 emitcode ("orl", "a,b");
8741 if (p_type == GPOINTER)
8742 emitcode ("pop", "b");
8748 emitcode ("mov", "@%s,a", rname);
8752 emitcode ("movx", "@dptr,a");
8756 emitcode ("lcall", "__gptrput");
8760 /*-----------------------------------------------------------------*/
8761 /* genDataPointerSet - remat pointer to data space */
8762 /*-----------------------------------------------------------------*/
8764 genDataPointerSet (operand * right,
8768 int size, offset = 0;
8769 char *l, buffer[256];
8771 aopOp (right, ic, FALSE, FALSE);
8773 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8774 size = AOP_SIZE (right);
8778 sprintf (buffer, "(%s + %d)", l + 1, offset);
8780 sprintf (buffer, "%s", l + 1);
8781 emitcode ("mov", "%s,%s", buffer,
8782 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8785 freeAsmop (right, NULL, ic, TRUE);
8786 freeAsmop (result, NULL, ic, TRUE);
8789 /*-----------------------------------------------------------------*/
8790 /* genNearPointerSet - emitcode for near pointer put */
8791 /*-----------------------------------------------------------------*/
8793 genNearPointerSet (operand * right,
8800 sym_link *retype, *letype;
8801 sym_link *ptype = operandType (result);
8803 retype = getSpec (operandType (right));
8804 letype = getSpec (ptype);
8806 aopOp (result, ic, FALSE, FALSE);
8808 /* if the result is rematerializable &
8809 in data space & not a bit variable */
8810 if (AOP_TYPE (result) == AOP_IMMD &&
8811 DCL_TYPE (ptype) == POINTER &&
8812 !IS_BITVAR (retype) &&
8813 !IS_BITVAR (letype))
8815 genDataPointerSet (right, result, ic);
8819 /* if the value is already in a pointer register
8820 then don't need anything more */
8821 if (!AOP_INPREG (AOP (result)))
8823 /* otherwise get a free pointer register */
8825 preg = getFreePtr (ic, &aop, FALSE);
8826 emitcode ("mov", "%s,%s",
8828 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8832 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8834 freeAsmop (result, NULL, ic, TRUE);
8835 aopOp (right, ic, FALSE, FALSE);
8837 /* if bitfield then unpack the bits */
8838 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8839 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8842 /* we have can just get the values */
8843 int size = AOP_SIZE (right);
8848 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8852 emitcode ("mov", "@%s,a", rname);
8855 emitcode ("mov", "@%s,%s", rname, l);
8857 emitcode ("inc", "%s", rname);
8862 /* now some housekeeping stuff */
8865 /* we had to allocate for this iCode */
8866 freeAsmop (NULL, aop, ic, TRUE);
8870 /* we did not allocate which means left
8871 already in a pointer register, then
8872 if size > 0 && this could be used again
8873 we have to point it back to where it
8875 if (AOP_SIZE (right) > 1 &&
8876 !OP_SYMBOL (result)->remat &&
8877 (OP_SYMBOL (result)->liveTo > ic->seq ||
8880 int size = AOP_SIZE (right) - 1;
8882 emitcode ("dec", "%s", rname);
8887 freeAsmop (right, NULL, ic, TRUE);
8892 /*-----------------------------------------------------------------*/
8893 /* genPagedPointerSet - emitcode for Paged pointer put */
8894 /*-----------------------------------------------------------------*/
8896 genPagedPointerSet (operand * right,
8903 sym_link *retype, *letype;
8905 retype = getSpec (operandType (right));
8906 letype = getSpec (operandType (result));
8908 aopOp (result, ic, FALSE, FALSE);
8910 /* if the value is already in a pointer register
8911 then don't need anything more */
8912 if (!AOP_INPREG (AOP (result)))
8914 /* otherwise get a free pointer register */
8916 preg = getFreePtr (ic, &aop, FALSE);
8917 emitcode ("mov", "%s,%s",
8919 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8923 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8925 freeAsmop (result, NULL, ic, TRUE);
8926 aopOp (right, ic, FALSE, FALSE);
8928 /* if bitfield then unpack the bits */
8929 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8930 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8933 /* we have can just get the values */
8934 int size = AOP_SIZE (right);
8939 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8942 emitcode ("movx", "@%s,a", rname);
8945 emitcode ("inc", "%s", rname);
8951 /* now some housekeeping stuff */
8954 /* we had to allocate for this iCode */
8955 freeAsmop (NULL, aop, ic, TRUE);
8959 /* we did not allocate which means left
8960 already in a pointer register, then
8961 if size > 0 && this could be used again
8962 we have to point it back to where it
8964 if (AOP_SIZE (right) > 1 &&
8965 !OP_SYMBOL (result)->remat &&
8966 (OP_SYMBOL (result)->liveTo > ic->seq ||
8969 int size = AOP_SIZE (right) - 1;
8971 emitcode ("dec", "%s", rname);
8976 freeAsmop (right, NULL, ic, TRUE);
8981 /*-----------------------------------------------------------------*/
8982 /* genFarPointerSet - set value from far space */
8983 /*-----------------------------------------------------------------*/
8985 genFarPointerSet (operand * right,
8986 operand * result, iCode * ic)
8989 sym_link *retype = getSpec (operandType (right));
8990 sym_link *letype = getSpec (operandType (result));
8992 aopOp (result, ic, FALSE, FALSE);
8994 /* if the operand is already in dptr
8995 then we do nothing else we move the value to dptr */
8996 if (AOP_TYPE (result) != AOP_STR)
8998 /* if this is remateriazable */
8999 if (AOP_TYPE (result) == AOP_IMMD)
9000 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9003 /* we need to get it byte by byte */
9004 _startLazyDPSEvaluation ();
9005 if (AOP_TYPE (result) != AOP_DPTR)
9007 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9008 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9009 if (options.model == MODEL_FLAT24)
9010 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9014 /* We need to generate a load to DPTR indirect through DPTR. */
9015 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9017 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9018 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9019 if (options.model == MODEL_FLAT24)
9020 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9021 emitcode ("pop", "dph");
9022 emitcode ("pop", "dpl");
9024 _endLazyDPSEvaluation ();
9027 /* so dptr know contains the address */
9028 freeAsmop (result, NULL, ic, TRUE);
9029 aopOp (right, ic, FALSE, TRUE);
9031 /* if bit then unpack */
9032 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9033 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9036 size = AOP_SIZE (right);
9039 _startLazyDPSEvaluation ();
9042 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9048 emitcode ("movx", "@dptr,a");
9050 emitcode ("inc", "dptr");
9052 _endLazyDPSEvaluation ();
9055 freeAsmop (right, NULL, ic, TRUE);
9058 /*-----------------------------------------------------------------*/
9059 /* genGenPointerSet - set value from generic pointer space */
9060 /*-----------------------------------------------------------------*/
9062 genGenPointerSet (operand * right,
9063 operand * result, iCode * ic)
9066 sym_link *retype = getSpec (operandType (right));
9067 sym_link *letype = getSpec (operandType (result));
9069 aopOp (result, ic, FALSE, TRUE);
9071 /* if the operand is already in dptr
9072 then we do nothing else we move the value to dptr */
9073 if (AOP_TYPE (result) != AOP_STR)
9075 _startLazyDPSEvaluation ();
9076 /* if this is remateriazable */
9077 if (AOP_TYPE (result) == AOP_IMMD)
9079 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9080 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9083 { /* we need to get it byte by byte */
9084 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9085 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9086 if (options.model == MODEL_FLAT24) {
9087 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9088 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9090 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9093 _endLazyDPSEvaluation ();
9095 /* so dptr know contains the address */
9096 freeAsmop (result, NULL, ic, TRUE);
9097 aopOp (right, ic, FALSE, TRUE);
9099 /* if bit then unpack */
9100 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9101 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9104 size = AOP_SIZE (right);
9107 _startLazyDPSEvaluation ();
9110 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9116 emitcode ("lcall", "__gptrput");
9118 emitcode ("inc", "dptr");
9120 _endLazyDPSEvaluation ();
9123 freeAsmop (right, NULL, ic, TRUE);
9126 /*-----------------------------------------------------------------*/
9127 /* genPointerSet - stores the value into a pointer location */
9128 /*-----------------------------------------------------------------*/
9130 genPointerSet (iCode * ic)
9132 operand *right, *result;
9133 sym_link *type, *etype;
9136 D (emitcode (";", "genPointerSet ");
9139 right = IC_RIGHT (ic);
9140 result = IC_RESULT (ic);
9142 /* depending on the type of pointer we need to
9143 move it to the correct pointer register */
9144 type = operandType (result);
9145 etype = getSpec (type);
9146 /* if left is of type of pointer then it is simple */
9147 if (IS_PTR (type) && !IS_FUNC (type->next))
9149 p_type = DCL_TYPE (type);
9153 /* we have to go by the storage class */
9154 p_type = PTR_TYPE (SPEC_OCLS (etype));
9157 /* now that we have the pointer type we assign
9158 the pointer values */
9164 genNearPointerSet (right, result, ic);
9168 genPagedPointerSet (right, result, ic);
9172 genFarPointerSet (right, result, ic);
9176 genGenPointerSet (right, result, ic);
9182 /*-----------------------------------------------------------------*/
9183 /* genIfx - generate code for Ifx statement */
9184 /*-----------------------------------------------------------------*/
9186 genIfx (iCode * ic, iCode * popIc)
9188 operand *cond = IC_COND (ic);
9191 D (emitcode (";", "genIfx "););
9193 aopOp (cond, ic, FALSE, FALSE);
9195 /* get the value into acc */
9196 if (AOP_TYPE (cond) != AOP_CRY)
9200 /* the result is now in the accumulator */
9201 freeAsmop (cond, NULL, ic, TRUE);
9203 /* if there was something to be popped then do it */
9207 /* if the condition is a bit variable */
9208 if (isbit && IS_ITEMP (cond) &&
9210 genIfxJump (ic, SPIL_LOC (cond)->rname);
9211 else if (isbit && !IS_ITEMP (cond))
9212 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9214 genIfxJump (ic, "a");
9219 /*-----------------------------------------------------------------*/
9220 /* genAddrOf - generates code for address of */
9221 /*-----------------------------------------------------------------*/
9223 genAddrOf (iCode * ic)
9225 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9228 D (emitcode (";", "genAddrOf ");
9231 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9233 /* if the operand is on the stack then we
9234 need to get the stack offset of this
9238 /* if it has an offset then we need to compute
9242 emitcode ("mov", "a,_bp");
9243 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9244 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9248 /* we can just move _bp */
9249 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9251 /* fill the result with zero */
9252 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9255 if (options.stack10bit && size < (FPTRSIZE - 1))
9258 "*** warning: pointer to stack var truncated.\n");
9265 if (options.stack10bit && offset == 2)
9267 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9271 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9278 /* object not on stack then we need the name */
9279 size = AOP_SIZE (IC_RESULT (ic));
9284 char s[SDCC_NAME_MAX];
9286 sprintf (s, "#(%s >> %d)",
9290 sprintf (s, "#%s", sym->rname);
9291 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9295 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9299 /*-----------------------------------------------------------------*/
9300 /* genArrayInit - generates code for address of */
9301 /*-----------------------------------------------------------------*/
9303 genArrayInit (iCode * ic)
9307 int elementSize = 0, eIndex;
9308 unsigned val, lastVal;
9310 operand *left=IC_LEFT(ic);
9312 D (emitcode (";", "genArrayInit "););
9314 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9316 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9318 // Load immediate value into DPTR.
9319 emitcode("mov", "dptr, %s",
9320 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9322 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9325 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9326 "Unexpected operand to genArrayInit.\n");
9329 // a regression because of SDCCcse.c:1.52
9330 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9331 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9332 if (options.model == MODEL_FLAT24)
9333 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9337 type = operandType(IC_LEFT(ic));
9339 if (type && type->next)
9341 elementSize = getSize(type->next);
9345 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9346 "can't determine element size in genArrayInit.\n");
9350 iLoop = IC_ARRAYILIST(ic);
9355 bool firstpass = TRUE;
9357 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9358 iLoop->count, (int)iLoop->literalValue, elementSize);
9364 symbol *tlbl = NULL;
9366 count = ix > 256 ? 256 : ix;
9370 tlbl = newiTempLabel (NULL);
9371 if (firstpass || (count & 0xff))
9373 emitcode("mov", "b, #0x%x", count & 0xff);
9376 emitcode ("", "%05d$:", tlbl->key + 100);
9381 for (eIndex = 0; eIndex < elementSize; eIndex++)
9383 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9386 emitcode("mov", "a, #0x%x", val);
9390 emitcode("movx", "@dptr, a");
9391 emitcode("inc", "dptr");
9396 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9402 iLoop = iLoop->next;
9405 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9408 /*-----------------------------------------------------------------*/
9409 /* genFarFarAssign - assignment when both are in far space */
9410 /*-----------------------------------------------------------------*/
9412 genFarFarAssign (operand * result, operand * right, iCode * ic)
9414 int size = AOP_SIZE (right);
9416 symbol *rSym = NULL;
9420 /* quick & easy case. */
9421 D(emitcode(";","genFarFarAssign (1 byte case)"););
9422 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9423 freeAsmop (right, NULL, ic, FALSE);
9424 /* now assign DPTR to result */
9426 aopOp(result, ic, FALSE, FALSE);
9428 aopPut(AOP(result), "a", 0);
9429 freeAsmop(result, NULL, ic, FALSE);
9433 /* See if we've got an underlying symbol to abuse. */
9434 if (IS_SYMOP(result) && OP_SYMBOL(result))
9436 if (IS_TRUE_SYMOP(result))
9438 rSym = OP_SYMBOL(result);
9440 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9442 rSym = OP_SYMBOL(result)->usl.spillLoc;
9446 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9448 /* We can use the '390 auto-toggle feature to good effect here. */
9450 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9451 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9452 emitcode ("mov", "dptr,#%s", rSym->rname);
9453 /* DP2 = result, DP1 = right, DP1 is current. */
9456 emitcode("movx", "a,@dptr");
9457 emitcode("movx", "@dptr,a");
9460 emitcode("inc", "dptr");
9461 emitcode("inc", "dptr");
9464 emitcode("mov", "dps, #0");
9465 freeAsmop (right, NULL, ic, FALSE);
9467 some alternative code for processors without auto-toggle
9468 no time to test now, so later well put in...kpb
9469 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9470 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9471 emitcode ("mov", "dptr,#%s", rSym->rname);
9472 /* DP2 = result, DP1 = right, DP1 is current. */
9476 emitcode("movx", "a,@dptr");
9478 emitcode("inc", "dptr");
9479 emitcode("inc", "dps");
9480 emitcode("movx", "@dptr,a");
9482 emitcode("inc", "dptr");
9483 emitcode("inc", "dps");
9485 emitcode("mov", "dps, #0");
9486 freeAsmop (right, NULL, ic, FALSE);
9491 D (emitcode (";", "genFarFarAssign"););
9492 aopOp (result, ic, TRUE, TRUE);
9494 _startLazyDPSEvaluation ();
9498 aopPut (AOP (result),
9499 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9502 _endLazyDPSEvaluation ();
9503 freeAsmop (result, NULL, ic, FALSE);
9504 freeAsmop (right, NULL, ic, FALSE);
9508 /*-----------------------------------------------------------------*/
9509 /* genAssign - generate code for assignment */
9510 /*-----------------------------------------------------------------*/
9512 genAssign (iCode * ic)
9514 operand *result, *right;
9516 unsigned long lit = 0L;
9518 D (emitcode (";", "genAssign ");
9521 result = IC_RESULT (ic);
9522 right = IC_RIGHT (ic);
9524 /* if they are the same */
9525 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9528 aopOp (right, ic, FALSE, FALSE);
9530 emitcode (";", "genAssign: resultIsFar = %s",
9531 isOperandInFarSpace (result) ?
9534 /* special case both in far space */
9535 if ((AOP_TYPE (right) == AOP_DPTR ||
9536 AOP_TYPE (right) == AOP_DPTR2) &&
9537 /* IS_TRUE_SYMOP(result) && */
9538 isOperandInFarSpace (result))
9540 genFarFarAssign (result, right, ic);
9544 aopOp (result, ic, TRUE, FALSE);
9546 /* if they are the same registers */
9547 if (sameRegs (AOP (right), AOP (result)))
9550 /* if the result is a bit */
9551 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9553 /* if the right size is a literal then
9554 we know what the value is */
9555 if (AOP_TYPE (right) == AOP_LIT)
9557 if (((int) operandLitValue (right)))
9558 aopPut (AOP (result), one, 0);
9560 aopPut (AOP (result), zero, 0);
9564 /* the right is also a bit variable */
9565 if (AOP_TYPE (right) == AOP_CRY)
9567 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9568 aopPut (AOP (result), "c", 0);
9574 aopPut (AOP (result), "a", 0);
9578 /* bit variables done */
9580 size = AOP_SIZE (result);
9582 if (AOP_TYPE (right) == AOP_LIT)
9583 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9586 (AOP_TYPE (result) != AOP_REG) &&
9587 (AOP_TYPE (right) == AOP_LIT) &&
9588 !IS_FLOAT (operandType (right)))
9590 _startLazyDPSEvaluation ();
9591 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9593 aopPut (AOP (result),
9594 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9599 /* And now fill the rest with zeros. */
9602 emitcode ("clr", "a");
9606 aopPut (AOP (result), "a", offset++);
9608 _endLazyDPSEvaluation ();
9612 _startLazyDPSEvaluation ();
9615 aopPut (AOP (result),
9616 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9620 _endLazyDPSEvaluation ();
9624 freeAsmop (right, NULL, ic, FALSE);
9625 freeAsmop (result, NULL, ic, TRUE);
9628 /*-----------------------------------------------------------------*/
9629 /* genJumpTab - generates code for jump table */
9630 /*-----------------------------------------------------------------*/
9632 genJumpTab (iCode * ic)
9637 D (emitcode (";", "genJumpTab ");
9640 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9641 /* get the condition into accumulator */
9642 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9644 /* multiply by four! */
9645 emitcode ("add", "a,acc");
9646 emitcode ("add", "a,acc");
9647 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9649 jtab = newiTempLabel (NULL);
9650 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9651 emitcode ("jmp", "@a+dptr");
9652 emitcode ("", "%05d$:", jtab->key + 100);
9653 /* now generate the jump labels */
9654 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9655 jtab = setNextItem (IC_JTLABELS (ic)))
9656 emitcode ("ljmp", "%05d$", jtab->key + 100);
9660 /*-----------------------------------------------------------------*/
9661 /* genCast - gen code for casting */
9662 /*-----------------------------------------------------------------*/
9664 genCast (iCode * ic)
9666 operand *result = IC_RESULT (ic);
9667 sym_link *ctype = operandType (IC_LEFT (ic));
9668 sym_link *rtype = operandType (IC_RIGHT (ic));
9669 operand *right = IC_RIGHT (ic);
9672 D (emitcode (";", "genCast ");
9675 /* if they are equivalent then do nothing */
9676 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9679 aopOp (right, ic, FALSE, FALSE);
9680 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9682 /* if the result is a bit */
9683 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9684 if (IS_BITVAR(OP_SYMBOL(result)->type))
9686 /* if the right size is a literal then
9687 we know what the value is */
9688 if (AOP_TYPE (right) == AOP_LIT)
9690 if (((int) operandLitValue (right)))
9691 aopPut (AOP (result), one, 0);
9693 aopPut (AOP (result), zero, 0);
9698 /* the right is also a bit variable */
9699 if (AOP_TYPE (right) == AOP_CRY)
9701 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9702 aopPut (AOP (result), "c", 0);
9708 aopPut (AOP (result), "a", 0);
9712 /* if they are the same size : or less */
9713 if (AOP_SIZE (result) <= AOP_SIZE (right))
9716 /* if they are in the same place */
9717 if (sameRegs (AOP (right), AOP (result)))
9720 /* if they in different places then copy */
9721 size = AOP_SIZE (result);
9723 _startLazyDPSEvaluation ();
9726 aopPut (AOP (result),
9727 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9731 _endLazyDPSEvaluation ();
9736 /* if the result is of type pointer */
9741 sym_link *type = operandType (right);
9743 /* pointer to generic pointer */
9744 if (IS_GENPTR (ctype))
9750 p_type = DCL_TYPE (type);
9754 #if OLD_CAST_BEHAVIOR
9755 /* KV: we are converting a non-pointer type to
9756 * a generic pointer. This (ifdef'd out) code
9757 * says that the resulting generic pointer
9758 * should have the same class as the storage
9759 * location of the non-pointer variable.
9761 * For example, converting an int (which happens
9762 * to be stored in DATA space) to a pointer results
9763 * in a DATA generic pointer; if the original int
9764 * in XDATA space, so will be the resulting pointer.
9766 * I don't like that behavior, and thus this change:
9767 * all such conversions will be forced to XDATA and
9768 * throw a warning. If you want some non-XDATA
9769 * type, or you want to suppress the warning, you
9770 * must go through an intermediate cast, like so:
9772 * char _generic *gp = (char _xdata *)(intVar);
9774 sym_link *etype = getSpec (type);
9776 /* we have to go by the storage class */
9777 if (SPEC_OCLS (etype) != generic)
9779 p_type = PTR_TYPE (SPEC_OCLS (etype));
9784 /* Converting unknown class (i.e. register variable)
9785 * to generic pointer. This is not good, but
9786 * we'll make a guess (and throw a warning).
9789 werror (W_INT_TO_GEN_PTR_CAST);
9793 /* the first two bytes are known */
9794 size = GPTRSIZE - 1;
9796 _startLazyDPSEvaluation ();
9799 aopPut (AOP (result),
9800 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9804 _endLazyDPSEvaluation ();
9806 /* the last byte depending on type */
9824 /* this should never happen */
9825 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9826 "got unknown pointer type");
9829 aopPut (AOP (result), l, GPTRSIZE - 1);
9833 /* just copy the pointers */
9834 size = AOP_SIZE (result);
9836 _startLazyDPSEvaluation ();
9839 aopPut (AOP (result),
9840 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9844 _endLazyDPSEvaluation ();
9848 /* so we now know that the size of destination is greater
9849 than the size of the source */
9850 /* we move to result for the size of source */
9851 size = AOP_SIZE (right);
9853 _startLazyDPSEvaluation ();
9856 aopPut (AOP (result),
9857 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9861 _endLazyDPSEvaluation ();
9863 /* now depending on the sign of the source && destination */
9864 size = AOP_SIZE (result) - AOP_SIZE (right);
9865 /* if unsigned or not an integral type */
9866 /* also, if the source is a bit, we don't need to sign extend, because
9867 * it can't possibly have set the sign bit.
9869 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9873 aopPut (AOP (result), zero, offset++);
9878 /* we need to extend the sign :{ */
9879 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9880 FALSE, FALSE, TRUE);
9882 emitcode ("rlc", "a");
9883 emitcode ("subb", "a,acc");
9885 aopPut (AOP (result), "a", offset++);
9888 /* we are done hurray !!!! */
9891 freeAsmop (right, NULL, ic, TRUE);
9892 freeAsmop (result, NULL, ic, TRUE);
9896 /*-----------------------------------------------------------------*/
9897 /* genDjnz - generate decrement & jump if not zero instrucion */
9898 /*-----------------------------------------------------------------*/
9900 genDjnz (iCode * ic, iCode * ifx)
9906 /* if the if condition has a false label
9907 then we cannot save */
9911 /* if the minus is not of the form
9913 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9914 !IS_OP_LITERAL (IC_RIGHT (ic)))
9917 if (operandLitValue (IC_RIGHT (ic)) != 1)
9920 /* if the size of this greater than one then no
9922 if (getSize (operandType (IC_RESULT (ic))) > 1)
9925 /* otherwise we can save BIG */
9926 D(emitcode(";", "genDjnz"););
9928 lbl = newiTempLabel (NULL);
9929 lbl1 = newiTempLabel (NULL);
9931 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9933 if (AOP_NEEDSACC(IC_RESULT(ic)))
9935 /* If the result is accessed indirectly via
9936 * the accumulator, we must explicitly write
9937 * it back after the decrement.
9939 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9941 if (strcmp(rByte, "a"))
9943 /* Something is hopelessly wrong */
9944 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9945 __FILE__, __LINE__);
9946 /* We can just give up; the generated code will be inefficient,
9949 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9952 emitcode ("dec", "%s", rByte);
9953 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9954 emitcode ("jnz", "%05d$", lbl->key + 100);
9956 else if (IS_AOP_PREG (IC_RESULT (ic)))
9958 emitcode ("dec", "%s",
9959 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9960 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9961 emitcode ("jnz", "%05d$", lbl->key + 100);
9965 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9968 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9969 emitcode ("", "%05d$:", lbl->key + 100);
9970 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9971 emitcode ("", "%05d$:", lbl1->key + 100);
9973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9978 /*-----------------------------------------------------------------*/
9979 /* genReceive - generate code for a receive iCode */
9980 /*-----------------------------------------------------------------*/
9982 genReceive (iCode * ic)
9985 D (emitcode (";", "genReceive ");
9988 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9989 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9990 IS_TRUE_SYMOP (IC_RESULT (ic))))
9992 int size = getSize (operandType (IC_RESULT (ic)));
9993 int offset = fReturnSizeDS390 - size;
9996 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9997 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10000 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10001 size = AOP_SIZE (IC_RESULT (ic));
10005 emitcode ("pop", "acc");
10006 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10013 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10015 assignResultValue (IC_RESULT (ic));
10018 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10021 /*-----------------------------------------------------------------*/
10022 /* gen390Code - generate code for Dallas 390 based controllers */
10023 /*-----------------------------------------------------------------*/
10025 gen390Code (iCode * lic)
10030 lineHead = lineCurr = NULL;
10032 if (options.model == MODEL_FLAT24) {
10033 fReturnSizeDS390 = 5;
10034 fReturn = fReturn24;
10036 fReturnSizeDS390 = 4;
10037 fReturn = fReturn16;
10038 options.stack10bit=0;
10042 /* print the allocation information */
10044 printAllocInfo (currFunc, codeOutFile);
10046 /* if debug information required */
10047 if (options.debug && currFunc)
10049 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10051 if (IS_STATIC (currFunc->etype))
10052 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10054 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10057 /* stack pointer name */
10058 if (options.useXstack)
10064 for (ic = lic; ic; ic = ic->next)
10067 if (cln != ic->lineno)
10072 emitcode ("", "C$%s$%d$%d$%d ==.",
10073 FileBaseName (ic->filename), ic->lineno,
10074 ic->level, ic->block);
10077 emitcode (";", "%s %d", ic->filename, ic->lineno);
10080 /* if the result is marked as
10081 spilt and rematerializable or code for
10082 this has already been generated then
10084 if (resultRemat (ic) || ic->generated)
10087 /* depending on the operation */
10107 /* IPOP happens only when trying to restore a
10108 spilt live range, if there is an ifx statement
10109 following this pop then the if statement might
10110 be using some of the registers being popped which
10111 would destory the contents of the register so
10112 we need to check for this condition and handle it */
10114 ic->next->op == IFX &&
10115 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10116 genIfx (ic->next, ic);
10134 genEndFunction (ic);
10154 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10171 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10175 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10182 /* note these two are xlated by algebraic equivalence
10183 during parsing SDCC.y */
10184 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10185 "got '>=' or '<=' shouldn't have come here");
10189 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10201 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10205 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10209 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10233 genRightShift (ic);
10236 case GET_VALUE_AT_ADDRESS:
10237 genPointerGet (ic);
10241 if (POINTER_SET (ic))
10242 genPointerSet (ic);
10268 addSet (&_G.sendSet, ic);
10281 /* now we are ready to call the
10282 peep hole optimizer */
10283 if (!options.nopeep)
10284 peepHole (&lineHead);
10286 /* now do the actual printing */
10287 printLine (lineHead, codeOutFile);