1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 #define BETTER_LITERAL_SHIFT
57 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
70 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
71 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
74 static char *fReturn24[] =
75 {"dpl", "dph", "dpx", "b", "a"};
76 static char *fReturn16[] =
77 {"dpl", "dph", "b", "a"};
78 static char **fReturn = fReturn24;
79 static char *accUse[] =
82 static short rbank = -1;
96 static void saveRBank (int, iCode *, bool);
98 #define RESULTONSTACK(x) \
99 (IC_RESULT(x) && IC_RESULT(x)->aop && \
100 IC_RESULT(x)->aop->type == AOP_STK )
102 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
103 #define MOVA(x) { char *_mova_tmp = strdup(x); \
104 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106 emitcode("mov","a,%s",_mova_tmp); \
110 #define CLRC emitcode("clr","c")
111 #define SETC emitcode("setb","c")
113 // A scratch register which will be used to hold
114 // result bytes from operands in far space via DPTR2.
115 #define DP2_RESULT_REG "ap"
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
120 static unsigned char SLMask[] =
121 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
125 0x07, 0x03, 0x01, 0x00};
132 /*-----------------------------------------------------------------*/
133 /* emitcode - writes the code into a file : for now it is simple */
134 /*-----------------------------------------------------------------*/
136 emitcode (char *inst, char *fmt,...)
139 char lb[INITIAL_INLINEASM];
147 sprintf (lb, "%s\t", inst);
149 sprintf (lb, "%s", inst);
150 vsprintf (lb + (strlen (lb)), fmt, ap);
153 vsprintf (lb, fmt, ap);
155 while (isspace (*lbp))
159 lineCurr = (lineCurr ?
160 connectLine (lineCurr, newLineNode (lb)) :
161 (lineHead = newLineNode (lb)));
162 lineCurr->isInline = _G.inLine;
163 lineCurr->isDebug = _G.debugLine;
167 /*-----------------------------------------------------------------*/
168 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
169 /*-----------------------------------------------------------------*/
171 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 bool r0iu = FALSE, r1iu = FALSE;
174 bool r0ou = FALSE, r1ou = FALSE;
176 /* the logic: if r0 & r1 used in the instruction
177 then we are in trouble otherwise */
179 /* first check if r0 & r1 are used by this
180 instruction, in which case we are in trouble */
181 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
182 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
187 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
188 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190 /* if no usage of r0 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
194 (*aopp)->type = AOP_R0;
196 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
199 /* if no usage of r1 then return it */
202 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
203 (*aopp)->type = AOP_R1;
205 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
208 /* now we know they both have usage */
209 /* if r0 not used in this instruction */
212 /* push it if not already pushed */
215 emitcode ("push", "%s",
216 ds390_regWithIdx (R0_IDX)->dname);
220 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
221 (*aopp)->type = AOP_R0;
223 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
226 /* if r1 not used then */
230 /* push it if not already pushed */
233 emitcode ("push", "%s",
234 ds390_regWithIdx (R1_IDX)->dname);
238 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
239 (*aopp)->type = AOP_R1;
240 return ds390_regWithIdx (R1_IDX);
244 /* I said end of world but not quite end of world yet */
245 /* if this is a result then we can push it on the stack */
248 (*aopp)->type = AOP_STK;
252 /* other wise this is true end of the world */
253 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
254 "getFreePtr should never reach here");
258 /*-----------------------------------------------------------------*/
259 /* newAsmop - creates a new asmOp */
260 /*-----------------------------------------------------------------*/
262 newAsmop (short type)
266 aop = Safe_calloc (1, sizeof (asmop));
271 static int _currentDPS; /* Current processor DPS. */
272 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
273 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
275 /*-----------------------------------------------------------------*/
276 /* genSetDPTR: generate code to select which DPTR is in use (zero */
277 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
278 /* alternate DPTR (DPL1/DPH1/DPX1). */
279 /*-----------------------------------------------------------------*/
284 /* If we are doing lazy evaluation, simply note the desired
285 * change, but don't emit any code yet.
295 emitcode ("mov", "dps, #0x00");
300 emitcode ("mov", "dps, #0x01");
304 /*-----------------------------------------------------------------*/
305 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /* Any code that operates on DPTR (NB: not on the individual */
308 /* components, like DPH) *must* call _flushLazyDPS() before using */
309 /* DPTR within a lazy DPS evaluation block. */
311 /* Note that aopPut and aopGet already contain the proper calls to */
312 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
313 /* DPS evaluation block. */
315 /* Also, _flushLazyDPS must be called before any flow control */
316 /* operations that could potentially branch out of the block. */
318 /* Lazy DPS evaluation is simply an optimization (though an */
319 /* important one), so if in doubt, leave it out. */
320 /*-----------------------------------------------------------------*/
322 _startLazyDPSEvaluation (void)
326 #ifdef BETTER_LITERAL_SHIFT
333 /*-----------------------------------------------------------------*/
334 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
335 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /*-----------------------------------------------------------------*/
347 if (_desiredDPS != _currentDPS)
351 emitcode ("inc", "dps");
355 emitcode ("dec", "dps");
357 _currentDPS = _desiredDPS;
361 /*-----------------------------------------------------------------*/
362 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
364 /* Forces us back to the safe state (standard DPTR selected). */
365 /*-----------------------------------------------------------------*/
367 _endLazyDPSEvaluation (void)
369 #ifdef BETTER_LITERAL_SHIFT
388 /*-----------------------------------------------------------------*/
389 /* pointerCode - returns the code for a pointer type */
390 /*-----------------------------------------------------------------*/
392 pointerCode (sym_link * etype)
395 return PTR_TYPE (SPEC_OCLS (etype));
399 /*-----------------------------------------------------------------*/
400 /* aopForSym - for a true symbol */
401 /*-----------------------------------------------------------------*/
403 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
406 memmap *space = SPEC_OCLS (sym->etype);
408 /* if already has one */
412 /* assign depending on the storage class */
413 /* if it is on the stack or indirectly addressable */
414 /* space we need to assign either r0 or r1 to it */
415 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417 sym->aop = aop = newAsmop (0);
418 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
419 aop->size = getSize (sym->type);
421 /* now assign the address of the variable to
422 the pointer register */
423 if (aop->type != AOP_STK)
429 emitcode ("push", "acc");
431 emitcode ("mov", "a,_bp");
432 emitcode ("add", "a,#0x%02x",
434 ((char) (sym->stack - _G.nRegsSaved)) :
435 ((char) sym->stack)) & 0xff);
436 emitcode ("mov", "%s,a",
437 aop->aopu.aop_ptr->name);
440 emitcode ("pop", "acc");
443 emitcode ("mov", "%s,#%s",
444 aop->aopu.aop_ptr->name,
446 aop->paged = space->paged;
449 aop->aopu.aop_stk = sym->stack;
453 if (sym->onStack && options.stack10bit)
455 /* It's on the 10 bit stack, which is located in
460 emitcode ("push", "acc");
462 emitcode ("mov", "a,_bp");
463 emitcode ("add", "a,#0x%02x",
465 ((char) (sym->stack - _G.nRegsSaved)) :
466 ((char) sym->stack)) & 0xff);
470 if (options.model == MODEL_FLAT24)
471 emitcode ("mov", "dpx1,#0x40");
473 emitcode ("mov", "dph1,#0x00");
474 emitcode ("mov", "dpl1, a");
478 if (options.model == MODEL_FLAT24)
479 emitcode ("mov", "dpx,#0x40");
480 emitcode ("mov", "dph,#0x00");
481 emitcode ("mov", "dpl, a");
485 emitcode ("pop", "acc");
487 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
488 aop->size = getSize (sym->type);
492 /* if in bit space */
493 if (IN_BITSPACE (space))
495 sym->aop = aop = newAsmop (AOP_CRY);
496 aop->aopu.aop_dir = sym->rname;
497 aop->size = getSize (sym->type);
500 /* if it is in direct space */
501 if (IN_DIRSPACE (space))
503 sym->aop = aop = newAsmop (AOP_DIR);
504 aop->aopu.aop_dir = sym->rname;
505 aop->size = getSize (sym->type);
509 /* special case for a function */
510 if (IS_FUNC (sym->type))
512 sym->aop = aop = newAsmop (AOP_IMMD);
513 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
514 strcpy (aop->aopu.aop_immd, sym->rname);
515 aop->size = FPTRSIZE;
519 /* only remaining is far space */
520 /* in which case DPTR gets the address */
521 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
526 emitcode ("mov", "dptr,#%s", sym->rname);
531 emitcode ("mov", "dptr,#%s", sym->rname);
533 aop->size = getSize (sym->type);
535 /* if it is in code space */
536 if (IN_CODESPACE (space))
542 /*-----------------------------------------------------------------*/
543 /* aopForRemat - rematerialzes an object */
544 /*-----------------------------------------------------------------*/
546 aopForRemat (symbol * sym)
548 iCode *ic = sym->rematiCode;
549 asmop *aop = newAsmop (AOP_IMMD);
556 val += (int) operandLitValue (IC_RIGHT (ic));
557 else if (ic->op == '-')
558 val -= (int) operandLitValue (IC_RIGHT (ic));
562 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
566 sprintf (buffer, "(%s %c 0x%04x)",
567 OP_SYMBOL (IC_LEFT (ic))->rname,
568 val >= 0 ? '+' : '-',
571 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
573 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
574 strcpy (aop->aopu.aop_immd, buffer);
578 /*-----------------------------------------------------------------*/
579 /* regsInCommon - two operands have some registers in common */
580 /*-----------------------------------------------------------------*/
582 regsInCommon (operand * op1, operand * op2)
587 /* if they have registers in common */
588 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
591 sym1 = OP_SYMBOL (op1);
592 sym2 = OP_SYMBOL (op2);
594 if (sym1->nRegs == 0 || sym2->nRegs == 0)
597 for (i = 0; i < sym1->nRegs; i++)
603 for (j = 0; j < sym2->nRegs; j++)
608 if (sym2->regs[j] == sym1->regs[i])
616 /*-----------------------------------------------------------------*/
617 /* operandsEqu - equivalent */
618 /*-----------------------------------------------------------------*/
620 operandsEqu (operand * op1, operand * op2)
624 /* if they not symbols */
625 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
628 sym1 = OP_SYMBOL (op1);
629 sym2 = OP_SYMBOL (op2);
631 /* if both are itemps & one is spilt
632 and the other is not then false */
633 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
634 sym1->isspilt != sym2->isspilt)
637 /* if they are the same */
641 if (strcmp (sym1->rname, sym2->rname) == 0)
645 /* if left is a tmp & right is not */
646 if (IS_ITEMP (op1) &&
649 (sym1->usl.spillLoc == sym2))
652 if (IS_ITEMP (op2) &&
656 (sym2->usl.spillLoc == sym1))
662 /*-----------------------------------------------------------------*/
663 /* sameRegs - two asmops have the same registers */
664 /*-----------------------------------------------------------------*/
666 sameRegs (asmop * aop1, asmop * aop2)
672 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
679 if (aop1->type != AOP_REG ||
680 aop2->type != AOP_REG)
683 if (aop1->size != aop2->size)
686 for (i = 0; i < aop1->size; i++)
687 if (aop1->aopu.aop_reg[i] !=
688 aop2->aopu.aop_reg[i])
694 /*-----------------------------------------------------------------*/
695 /* aopOp - allocates an asmop for an operand : */
696 /*-----------------------------------------------------------------*/
698 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
707 /* if this a literal */
708 if (IS_OP_LITERAL (op))
710 op->aop = aop = newAsmop (AOP_LIT);
711 aop->aopu.aop_lit = op->operand.valOperand;
712 aop->size = getSize (operandType (op));
716 /* if already has a asmop then continue */
720 /* if the underlying symbol has a aop */
721 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
723 op->aop = OP_SYMBOL (op)->aop;
727 /* if this is a true symbol */
728 if (IS_TRUE_SYMOP (op))
730 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
734 /* this is a temporary : this has
740 e) can be a return use only */
742 sym = OP_SYMBOL (op);
745 /* if the type is a conditional */
746 if (sym->regType == REG_CND)
748 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
753 /* if it is spilt then two situations
755 b) has a spill location */
756 if (sym->isspilt || sym->nRegs == 0)
759 /* rematerialize it NOW */
762 sym->aop = op->aop = aop =
764 aop->size = getSize (sym->type);
771 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
772 aop->size = getSize (sym->type);
773 for (i = 0; i < 2; i++)
774 aop->aopu.aop_str[i] = accUse[i];
784 /* a AOP_STR uses DPTR, but DPTR is already in use;
787 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
790 aop = op->aop = sym->aop = newAsmop (AOP_STR);
791 aop->size = getSize (sym->type);
792 for (i = 0; i < (int) fReturnSizeDS390; i++)
793 aop->aopu.aop_str[i] = fReturn[i];
797 /* else spill location */
798 sym->aop = op->aop = aop =
799 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
800 aop->size = getSize (sym->type);
804 /* must be in a register */
805 sym->aop = op->aop = aop = newAsmop (AOP_REG);
806 aop->size = sym->nRegs;
807 for (i = 0; i < sym->nRegs; i++)
808 aop->aopu.aop_reg[i] = sym->regs[i];
811 /*-----------------------------------------------------------------*/
812 /* freeAsmop - free up the asmop given to an operand */
813 /*----------------------------------------------------------------*/
815 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
832 /* depending on the asmop type only three cases need work AOP_RO
833 , AOP_R1 && AOP_STK */
841 emitcode ("pop", "ar0");
845 bitVectUnSetBit (ic->rUsed, R0_IDX);
853 emitcode ("pop", "ar1");
857 bitVectUnSetBit (ic->rUsed, R1_IDX);
863 int stk = aop->aopu.aop_stk + aop->size;
864 bitVectUnSetBit (ic->rUsed, R0_IDX);
865 bitVectUnSetBit (ic->rUsed, R1_IDX);
867 getFreePtr (ic, &aop, FALSE);
869 if (options.stack10bit)
871 /* I'm not sure what to do here yet... */
874 "*** Warning: probably generating bad code for "
875 "10 bit stack mode.\n");
880 emitcode ("mov", "a,_bp");
881 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
882 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
886 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
891 emitcode ("pop", "acc");
892 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
895 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
898 freeAsmop (op, NULL, ic, TRUE);
901 emitcode ("pop", "ar0");
907 emitcode ("pop", "ar1");
914 /* all other cases just dealloc */
920 OP_SYMBOL (op)->aop = NULL;
921 /* if the symbol has a spill */
923 SPIL_LOC (op)->aop = NULL;
928 /*------------------------------------------------------------------*/
929 /* aopGet - for fetching value of the aop */
931 /* Set canClobberACC if you are sure it is OK to clobber the value */
932 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
933 /* just less efficient. */
934 /*------------------------------------------------------------------*/
946 /* offset is greater than
948 if (offset > (aop->size - 1) &&
949 aop->type != AOP_LIT)
952 /* depending on type */
958 /* if we need to increment it */
959 while (offset > aop->coff)
961 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
965 while (offset < aop->coff)
967 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
974 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
975 return (dname ? "acc" : "a");
977 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
978 rs = Safe_calloc (1, strlen (s) + 1);
985 if (aop->type == AOP_DPTR2)
991 emitcode ("xch", "a, %s", DP2_RESULT_REG);
997 while (offset > aop->coff)
999 emitcode ("inc", "dptr");
1003 while (offset < aop->coff)
1005 emitcode ("lcall", "__decdptr");
1012 emitcode ("clr", "a");
1013 emitcode ("movc", "a,@a+dptr");
1017 emitcode ("movx", "a,@dptr");
1020 if (aop->type == AOP_DPTR2)
1026 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1027 return DP2_RESULT_REG;
1030 return (dname ? "acc" : "a");
1034 sprintf (s, "#%s", aop->aopu.aop_immd);
1036 sprintf (s, "#(%s >> %d)",
1041 aop->aopu.aop_immd);
1042 rs = Safe_calloc (1, strlen (s) + 1);
1048 sprintf (s, "(%s + %d)",
1052 sprintf (s, "%s", aop->aopu.aop_dir);
1053 rs = Safe_calloc (1, strlen (s) + 1);
1059 return aop->aopu.aop_reg[offset]->dname;
1061 return aop->aopu.aop_reg[offset]->name;
1064 emitcode ("clr", "a");
1065 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1066 emitcode ("rlc", "a");
1067 return (dname ? "acc" : "a");
1070 if (!offset && dname)
1072 return aop->aopu.aop_str[offset];
1075 return aopLiteral (aop->aopu.aop_lit, offset);
1079 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1083 return aop->aopu.aop_str[offset];
1087 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1088 "aopget got unsupported aop->type");
1091 /*-----------------------------------------------------------------*/
1092 /* aopPut - puts a string for a aop */
1093 /*-----------------------------------------------------------------*/
1095 aopPut (asmop * aop, char *s, int offset)
1099 if (aop->size && offset > (aop->size - 1))
1101 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1102 "aopPut got offset > aop->size");
1106 /* will assign value to value */
1107 /* depending on where it is ofcourse */
1112 sprintf (d, "(%s + %d)",
1113 aop->aopu.aop_dir, offset);
1115 sprintf (d, "%s", aop->aopu.aop_dir);
1118 emitcode ("mov", "%s,%s", d, s);
1123 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1124 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1127 strcmp (s, "r0") == 0 ||
1128 strcmp (s, "r1") == 0 ||
1129 strcmp (s, "r2") == 0 ||
1130 strcmp (s, "r3") == 0 ||
1131 strcmp (s, "r4") == 0 ||
1132 strcmp (s, "r5") == 0 ||
1133 strcmp (s, "r6") == 0 ||
1134 strcmp (s, "r7") == 0)
1135 emitcode ("mov", "%s,%s",
1136 aop->aopu.aop_reg[offset]->dname, s);
1138 emitcode ("mov", "%s,%s",
1139 aop->aopu.aop_reg[offset]->name, s);
1146 if (aop->type == AOP_DPTR2)
1154 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1155 "aopPut writting to code space");
1159 while (offset > aop->coff)
1162 emitcode ("inc", "dptr");
1165 while (offset < aop->coff)
1168 emitcode ("lcall", "__decdptr");
1173 /* if not in accumulater */
1176 emitcode ("movx", "@dptr,a");
1178 if (aop->type == AOP_DPTR2)
1186 while (offset > aop->coff)
1189 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1191 while (offset < aop->coff)
1194 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1201 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1207 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1209 else if (strcmp (s, "r0") == 0 ||
1210 strcmp (s, "r1") == 0 ||
1211 strcmp (s, "r2") == 0 ||
1212 strcmp (s, "r3") == 0 ||
1213 strcmp (s, "r4") == 0 ||
1214 strcmp (s, "r5") == 0 ||
1215 strcmp (s, "r6") == 0 ||
1216 strcmp (s, "r7") == 0)
1219 sprintf (buffer, "a%s", s);
1220 emitcode ("mov", "@%s,%s",
1221 aop->aopu.aop_ptr->name, buffer);
1224 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1229 if (strcmp (s, "a") == 0)
1230 emitcode ("push", "acc");
1232 emitcode ("push", "%s", s);
1237 /* if bit variable */
1238 if (!aop->aopu.aop_dir)
1240 emitcode ("clr", "a");
1241 emitcode ("rlc", "a");
1246 emitcode ("clr", "%s", aop->aopu.aop_dir);
1248 emitcode ("setb", "%s", aop->aopu.aop_dir);
1249 else if (!strcmp (s, "c"))
1250 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1253 if (strcmp (s, "a"))
1258 symbol *lbl = newiTempLabel (NULL);
1259 emitcode ("clr", "c");
1260 emitcode ("jz", "%05d$", lbl->key + 100);
1261 emitcode ("cpl", "c");
1262 emitcode ("", "%05d$:", lbl->key + 100);
1263 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1271 if (strcmp (aop->aopu.aop_str[offset], s))
1272 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1277 if (!offset && (strcmp (s, "acc") == 0))
1280 if (strcmp (aop->aopu.aop_str[offset], s))
1281 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286 "aopPut got unsupported aop->type");
1293 /*--------------------------------------------------------------------*/
1294 /* reAdjustPreg - points a register back to where it should (coff==0) */
1295 /*--------------------------------------------------------------------*/
1297 reAdjustPreg (asmop * aop)
1299 if ((aop->coff==0) || (aop->size <= 1)) {
1308 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1312 if (aop->type == AOP_DPTR2)
1319 emitcode ("lcall", "__decdptr");
1322 if (aop->type == AOP_DPTR2)
1332 #define AOP(op) op->aop
1333 #define AOP_TYPE(op) AOP(op)->type
1334 #define AOP_SIZE(op) AOP(op)->size
1335 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1336 AOP_TYPE(x) == AOP_R0))
1338 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1339 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1342 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1343 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1344 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1346 /* Workaround for DS80C390 bug: div ab may return bogus results
1347 * if A is accessed in instruction immediately before the div.
1349 * Will be fixed in B4 rev of processor, Dallas claims.
1352 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1353 if (!AOP_NEEDSACC(RIGHT)) \
1355 /* We can load A first, then B, since \
1356 * B (the RIGHT operand) won't clobber A, \
1357 * thus avoiding touching A right before the div. \
1359 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1360 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1362 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1366 /* Just stuff in a nop after loading A. */ \
1367 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1368 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1370 emitcode("nop", "; workaround for DS80C390 div bug."); \
1373 /*-----------------------------------------------------------------*/
1374 /* genNotFloat - generates not for float operations */
1375 /*-----------------------------------------------------------------*/
1377 genNotFloat (operand * op, operand * res)
1383 D (emitcode (";", "genNotFloat ");
1386 /* we will put 127 in the first byte of
1388 aopPut (AOP (res), "#127", 0);
1389 size = AOP_SIZE (op) - 1;
1392 _startLazyDPSEvaluation ();
1393 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1398 emitcode ("orl", "a,%s",
1400 offset++, FALSE, FALSE, FALSE));
1402 _endLazyDPSEvaluation ();
1404 tlbl = newiTempLabel (NULL);
1405 aopPut (res->aop, one, 1);
1406 emitcode ("jz", "%05d$", (tlbl->key + 100));
1407 aopPut (res->aop, zero, 1);
1408 emitcode ("", "%05d$:", (tlbl->key + 100));
1410 size = res->aop->size - 2;
1412 /* put zeros in the rest */
1414 aopPut (res->aop, zero, offset++);
1417 /*-----------------------------------------------------------------*/
1418 /* opIsGptr: returns non-zero if the passed operand is */
1419 /* a generic pointer type. */
1420 /*-----------------------------------------------------------------*/
1422 opIsGptr (operand * op)
1424 sym_link *type = operandType (op);
1426 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1433 /*-----------------------------------------------------------------*/
1434 /* getDataSize - get the operand data size */
1435 /*-----------------------------------------------------------------*/
1437 getDataSize (operand * op)
1440 size = AOP_SIZE (op);
1441 if (size == GPTRSIZE)
1443 sym_link *type = operandType (op);
1444 if (IS_GENPTR (type))
1446 /* generic pointer; arithmetic operations
1447 * should ignore the high byte (pointer type).
1455 /*-----------------------------------------------------------------*/
1456 /* outAcc - output Acc */
1457 /*-----------------------------------------------------------------*/
1459 outAcc (operand * result)
1462 size = getDataSize (result);
1465 aopPut (AOP (result), "a", 0);
1468 /* unsigned or positive */
1471 aopPut (AOP (result), zero, offset++);
1476 /*-----------------------------------------------------------------*/
1477 /* outBitC - output a bit C */
1478 /*-----------------------------------------------------------------*/
1480 outBitC (operand * result)
1482 /* if the result is bit */
1483 if (AOP_TYPE (result) == AOP_CRY)
1485 aopPut (AOP (result), "c", 0);
1489 emitcode ("clr", "a");
1490 emitcode ("rlc", "a");
1495 /*-----------------------------------------------------------------*/
1496 /* toBoolean - emit code for orl a,operator(sizeop) */
1497 /*-----------------------------------------------------------------*/
1499 toBoolean (operand * oper)
1501 int size = AOP_SIZE (oper) - 1;
1505 /* The generic part of a generic pointer should
1506 * not participate in it's truth value.
1508 * i.e. 0x10000000 is zero.
1510 if (opIsGptr (oper))
1512 D (emitcode (";", "toBoolean: generic ptr special case.");
1517 _startLazyDPSEvaluation ();
1518 if (AOP_NEEDSACC (oper) && size)
1521 emitcode ("push", "b");
1522 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1526 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1532 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1536 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1539 _endLazyDPSEvaluation ();
1543 emitcode ("mov", "a,b");
1544 emitcode ("pop", "b");
1549 /*-----------------------------------------------------------------*/
1550 /* genNot - generate code for ! operation */
1551 /*-----------------------------------------------------------------*/
1556 sym_link *optype = operandType (IC_LEFT (ic));
1558 D (emitcode (";", "genNot ");
1561 /* assign asmOps to operand & result */
1562 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1563 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1565 /* if in bit space then a special case */
1566 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1568 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1569 emitcode ("cpl", "c");
1570 outBitC (IC_RESULT (ic));
1574 /* if type float then do float */
1575 if (IS_FLOAT (optype))
1577 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1581 toBoolean (IC_LEFT (ic));
1583 tlbl = newiTempLabel (NULL);
1584 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1585 emitcode ("", "%05d$:", tlbl->key + 100);
1586 outBitC (IC_RESULT (ic));
1589 /* release the aops */
1590 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1591 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1595 /*-----------------------------------------------------------------*/
1596 /* genCpl - generate code for complement */
1597 /*-----------------------------------------------------------------*/
1604 D (emitcode (";", "genCpl ");
1608 /* assign asmOps to operand & result */
1609 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1610 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1612 /* if both are in bit space then
1614 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1615 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1618 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1619 emitcode ("cpl", "c");
1620 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1624 size = AOP_SIZE (IC_RESULT (ic));
1625 _startLazyDPSEvaluation ();
1628 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1630 emitcode ("cpl", "a");
1631 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1633 _endLazyDPSEvaluation ();
1637 /* release the aops */
1638 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1639 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1642 /*-----------------------------------------------------------------*/
1643 /* genUminusFloat - unary minus for floating points */
1644 /*-----------------------------------------------------------------*/
1646 genUminusFloat (operand * op, operand * result)
1648 int size, offset = 0;
1650 /* for this we just need to flip the
1651 first it then copy the rest in place */
1652 D (emitcode (";", "genUminusFloat");
1655 _startLazyDPSEvaluation ();
1656 size = AOP_SIZE (op) - 1;
1657 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1660 emitcode ("cpl", "acc.7");
1661 aopPut (AOP (result), "a", 3);
1665 aopPut (AOP (result),
1666 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1670 _endLazyDPSEvaluation ();
1673 /*-----------------------------------------------------------------*/
1674 /* genUminus - unary minus code generation */
1675 /*-----------------------------------------------------------------*/
1677 genUminus (iCode * ic)
1680 sym_link *optype, *rtype;
1682 D (emitcode (";", "genUminus ");
1687 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1688 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1690 /* if both in bit space then special
1692 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1693 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1696 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1697 emitcode ("cpl", "c");
1698 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1702 optype = operandType (IC_LEFT (ic));
1703 rtype = operandType (IC_RESULT (ic));
1705 /* if float then do float stuff */
1706 if (IS_FLOAT (optype))
1708 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1712 /* otherwise subtract from zero */
1713 size = AOP_SIZE (IC_LEFT (ic));
1715 _startLazyDPSEvaluation ();
1718 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1719 if (!strcmp (l, "a"))
1723 emitcode ("cpl", "a");
1724 emitcode ("addc", "a,#0");
1730 emitcode ("clr", "a");
1731 emitcode ("subb", "a,%s", l);
1733 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1735 _endLazyDPSEvaluation ();
1737 /* if any remaining bytes in the result */
1738 /* we just need to propagate the sign */
1739 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1741 emitcode ("rlc", "a");
1742 emitcode ("subb", "a,acc");
1744 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1748 /* release the aops */
1749 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1750 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1753 /*-----------------------------------------------------------------*/
1754 /* saveRegisters - will look for a call and save the registers */
1755 /*-----------------------------------------------------------------*/
1757 saveRegisters (iCode * lic)
1765 for (ic = lic; ic; ic = ic->next)
1766 if (ic->op == CALL || ic->op == PCALL)
1771 fprintf (stderr, "found parameter push with no function call\n");
1775 /* if the registers have been saved already then
1777 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1778 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1781 /* find the registers in use at this time
1782 and push them away to safety */
1783 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1787 if (options.useXstack)
1789 if (bitVectBitValue (rsave, R0_IDX))
1790 emitcode ("mov", "b,r0");
1791 emitcode ("mov", "r0,%s", spname);
1792 for (i = 0; i < ds390_nRegs; i++)
1794 if (bitVectBitValue (rsave, i))
1797 emitcode ("mov", "a,b");
1799 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1800 emitcode ("movx", "@r0,a");
1801 emitcode ("inc", "r0");
1804 emitcode ("mov", "%s,r0", spname);
1805 if (bitVectBitValue (rsave, R0_IDX))
1806 emitcode ("mov", "r0,b");
1809 for (i = 0; i < ds390_nRegs; i++)
1811 if (bitVectBitValue (rsave, i))
1812 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1815 detype = getSpec (operandType (IC_LEFT (ic)));
1818 /*-----------------------------------------------------------------*/
1819 /* unsaveRegisters - pop the pushed registers */
1820 /*-----------------------------------------------------------------*/
1822 unsaveRegisters (iCode * ic)
1826 /* find the registers in use at this time
1827 and push them away to safety */
1828 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1831 if (options.useXstack)
1833 emitcode ("mov", "r0,%s", spname);
1834 for (i = ds390_nRegs; i >= 0; i--)
1836 if (bitVectBitValue (rsave, i))
1838 emitcode ("dec", "r0");
1839 emitcode ("movx", "a,@r0");
1841 emitcode ("mov", "b,a");
1843 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1847 emitcode ("mov", "%s,r0", spname);
1848 if (bitVectBitValue (rsave, R0_IDX))
1849 emitcode ("mov", "r0,b");
1852 for (i = ds390_nRegs; i >= 0; i--)
1854 if (bitVectBitValue (rsave, i))
1855 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1861 /*-----------------------------------------------------------------*/
1863 /*-----------------------------------------------------------------*/
1865 pushSide (operand * oper, int size)
1868 _startLazyDPSEvaluation ();
1871 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1872 if (AOP_TYPE (oper) != AOP_REG &&
1873 AOP_TYPE (oper) != AOP_DIR &&
1876 emitcode ("mov", "a,%s", l);
1877 emitcode ("push", "acc");
1880 emitcode ("push", "%s", l);
1882 _endLazyDPSEvaluation ();
1885 /*-----------------------------------------------------------------*/
1886 /* assignResultValue - */
1887 /*-----------------------------------------------------------------*/
1889 assignResultValue (operand * oper)
1892 int size = AOP_SIZE (oper);
1894 _startLazyDPSEvaluation ();
1897 aopPut (AOP (oper), fReturn[offset], offset);
1900 _endLazyDPSEvaluation ();
1904 /*-----------------------------------------------------------------*/
1905 /* genXpush - pushes onto the external stack */
1906 /*-----------------------------------------------------------------*/
1908 genXpush (iCode * ic)
1910 asmop *aop = newAsmop (0);
1912 int size, offset = 0;
1914 D (emitcode (";", "genXpush ");
1917 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1918 r = getFreePtr (ic, &aop, FALSE);
1921 emitcode ("mov", "%s,_spx", r->name);
1923 size = AOP_SIZE (IC_LEFT (ic));
1924 _startLazyDPSEvaluation ();
1928 char *l = aopGet (AOP (IC_LEFT (ic)),
1929 offset++, FALSE, FALSE, TRUE);
1931 emitcode ("movx", "@%s,a", r->name);
1932 emitcode ("inc", "%s", r->name);
1935 _endLazyDPSEvaluation ();
1938 emitcode ("mov", "_spx,%s", r->name);
1940 freeAsmop (NULL, aop, ic, TRUE);
1941 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1944 /*-----------------------------------------------------------------*/
1945 /* genIpush - genrate code for pushing this gets a little complex */
1946 /*-----------------------------------------------------------------*/
1948 genIpush (iCode * ic)
1950 int size, offset = 0;
1953 D (emitcode (";", "genIpush ");
1956 /* if this is not a parm push : ie. it is spill push
1957 and spill push is always done on the local stack */
1961 /* and the item is spilt then do nothing */
1962 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1965 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1966 size = AOP_SIZE (IC_LEFT (ic));
1967 /* push it on the stack */
1968 _startLazyDPSEvaluation ();
1971 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1977 emitcode ("push", "%s", l);
1979 _endLazyDPSEvaluation ();
1983 /* this is a paramter push: in this case we call
1984 the routine to find the call and save those
1985 registers that need to be saved */
1988 /* if use external stack then call the external
1989 stack pushing routine */
1990 if (options.useXstack)
1996 /* then do the push */
1997 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1999 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2000 size = AOP_SIZE (IC_LEFT (ic));
2002 _startLazyDPSEvaluation ();
2005 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2006 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2007 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2010 emitcode ("mov", "a,%s", l);
2011 emitcode ("push", "acc");
2014 emitcode ("push", "%s", l);
2016 _endLazyDPSEvaluation ();
2018 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2021 /*-----------------------------------------------------------------*/
2022 /* genIpop - recover the registers: can happen only for spilling */
2023 /*-----------------------------------------------------------------*/
2025 genIpop (iCode * ic)
2029 D (emitcode (";", "genIpop ");
2033 /* if the temp was not pushed then */
2034 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2037 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2038 size = AOP_SIZE (IC_LEFT (ic));
2039 offset = (size - 1);
2040 _startLazyDPSEvaluation ();
2043 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2044 FALSE, TRUE, TRUE));
2046 _endLazyDPSEvaluation ();
2048 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2051 /*-----------------------------------------------------------------*/
2052 /* unsaveRBank - restores the resgister bank from stack */
2053 /*-----------------------------------------------------------------*/
2055 unsaveRBank (int bank, iCode * ic, bool popPsw)
2061 if (options.useXstack)
2065 /* Assume r0 is available for use. */
2066 r = ds390_regWithIdx (R0_IDX);;
2071 r = getFreePtr (ic, &aop, FALSE);
2073 emitcode ("mov", "%s,_spx", r->name);
2078 if (options.useXstack)
2080 emitcode ("movx", "a,@%s", r->name);
2081 emitcode ("mov", "psw,a");
2082 emitcode ("dec", "%s", r->name);
2086 emitcode ("pop", "psw");
2090 for (i = (ds390_nRegs - 1); i >= 0; i--)
2092 if (options.useXstack)
2094 emitcode ("movx", "a,@%s", r->name);
2095 emitcode ("mov", "(%s+%d),a",
2096 regs390[i].base, 8 * bank + regs390[i].offset);
2097 emitcode ("dec", "%s", r->name);
2101 emitcode ("pop", "(%s+%d)",
2102 regs390[i].base, 8 * bank + regs390[i].offset);
2105 if (options.useXstack)
2107 emitcode ("mov", "_spx,%s", r->name);
2112 freeAsmop (NULL, aop, ic, TRUE);
2116 /*-----------------------------------------------------------------*/
2117 /* saveRBank - saves an entire register bank on the stack */
2118 /*-----------------------------------------------------------------*/
2120 saveRBank (int bank, iCode * ic, bool pushPsw)
2126 if (options.useXstack)
2130 /* Assume r0 is available for use. */
2131 r = ds390_regWithIdx (R0_IDX);;
2136 r = getFreePtr (ic, &aop, FALSE);
2138 emitcode ("mov", "%s,_spx", r->name);
2141 for (i = 0; i < ds390_nRegs; i++)
2143 if (options.useXstack)
2145 emitcode ("inc", "%s", r->name);
2146 emitcode ("mov", "a,(%s+%d)",
2147 regs390[i].base, 8 * bank + regs390[i].offset);
2148 emitcode ("movx", "@%s,a", r->name);
2151 emitcode ("push", "(%s+%d)",
2152 regs390[i].base, 8 * bank + regs390[i].offset);
2157 if (options.useXstack)
2159 emitcode ("mov", "a,psw");
2160 emitcode ("movx", "@%s,a", r->name);
2161 emitcode ("inc", "%s", r->name);
2162 emitcode ("mov", "_spx,%s", r->name);
2166 emitcode ("push", "psw");
2169 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2174 freeAsmop (NULL, aop, ic, TRUE);
2183 /*-----------------------------------------------------------------*/
2184 /* genCall - generates a call statement */
2185 /*-----------------------------------------------------------------*/
2187 genCall (iCode * ic)
2190 bool restoreBank = FALSE;
2191 bool swapBanks = FALSE;
2193 D (emitcode (";", "genCall "););
2195 /* if we are calling a not _naked function that is not using
2196 the same register bank then we need to save the
2197 destination registers on the stack */
2198 dtype = operandType (IC_LEFT (ic));
2199 if (dtype && !IFFUNC_ISNAKED(dtype) &&
2200 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2201 IFFUNC_ISISR (currFunc->type))
2205 /* This is unexpected; the bank should have been saved in
2208 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2214 /* if caller saves & we have not saved then */
2218 /* if send set is not empty the assign */
2219 /* We've saved all the registers we care about;
2220 * therefore, we may clobber any register not used
2221 * in the calling convention (i.e. anything not in
2228 for (sic = setFirstItem (_G.sendSet); sic;
2229 sic = setNextItem (_G.sendSet))
2231 int size, offset = 0;
2233 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2234 size = AOP_SIZE (IC_LEFT (sic));
2236 _startLazyDPSEvaluation ();
2239 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2240 FALSE, FALSE, TRUE);
2241 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2243 emitcode("mov", "%s,%s", regs390[offset].name, l);
2245 else if (strcmp (l, fReturn[offset]))
2247 emitcode ("mov", "%s,%s",
2253 _endLazyDPSEvaluation ();
2254 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2256 size = AOP_SIZE (IC_LEFT (sic));
2264 emitcode("mov", "%s,%s",
2265 fReturn[size], regs390[size].name);
2268 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2275 emitcode ("mov", "psw,#0x%02x",
2276 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2280 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2281 OP_SYMBOL (IC_LEFT (ic))->rname :
2282 OP_SYMBOL (IC_LEFT (ic))->name));
2286 emitcode ("mov", "psw,#0x%02x",
2287 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2290 /* if we need assign a result value */
2291 if ((IS_ITEMP (IC_RESULT (ic)) &&
2292 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2293 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2294 IS_TRUE_SYMOP (IC_RESULT (ic)))
2296 if (isOperandInFarSpace (IC_RESULT (ic))
2297 && getSize (operandType (IC_RESULT (ic))) <= 2)
2299 int size = getSize (operandType (IC_RESULT (ic)));
2301 /* Special case for 1 or 2 byte return in far space. */
2305 emitcode ("mov", "b,%s", fReturn[1]);
2308 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2309 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2313 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2315 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2320 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2323 assignResultValue (IC_RESULT (ic));
2325 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2329 /* adjust the stack for parameters if
2334 if (ic->parmBytes > 3)
2336 emitcode ("mov", "a,%s", spname);
2337 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2338 emitcode ("mov", "%s,a", spname);
2341 for (i = 0; i < ic->parmBytes; i++)
2342 emitcode ("dec", "%s", spname);
2345 /* if we hade saved some registers then unsave them */
2346 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2347 unsaveRegisters (ic);
2349 /* if register bank was saved then pop them */
2351 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2354 /*-----------------------------------------------------------------*/
2355 /* genPcall - generates a call by pointer statement */
2356 /*-----------------------------------------------------------------*/
2358 genPcall (iCode * ic)
2361 symbol *rlbl = newiTempLabel (NULL);
2363 D (emitcode (";", "genPcall ");
2367 /* if caller saves & we have not saved then */
2371 /* if we are calling a function that is not using
2372 the same register bank then we need to save the
2373 destination registers on the stack */
2374 dtype = operandType (IC_LEFT (ic));
2376 IFFUNC_ISISR (currFunc->type) &&
2377 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2378 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2381 /* push the return address on to the stack */
2382 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2383 emitcode ("push", "acc");
2384 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2385 emitcode ("push", "acc");
2387 if (options.model == MODEL_FLAT24)
2389 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2390 emitcode ("push", "acc");
2393 /* now push the calling address */
2394 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2396 pushSide (IC_LEFT (ic), FPTRSIZE);
2398 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2400 /* if send set is not empty the assign */
2405 for (sic = setFirstItem (_G.sendSet); sic;
2406 sic = setNextItem (_G.sendSet))
2408 int size, offset = 0;
2410 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2411 size = AOP_SIZE (IC_LEFT (sic));
2412 _startLazyDPSEvaluation ();
2415 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2416 FALSE, FALSE, TRUE);
2417 if (strcmp (l, fReturn[offset]))
2419 emitcode ("mov", "%s,%s",
2425 _endLazyDPSEvaluation ();
2426 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2431 emitcode ("ret", "");
2432 emitcode ("", "%05d$:", (rlbl->key + 100));
2435 /* if we need assign a result value */
2436 if ((IS_ITEMP (IC_RESULT (ic)) &&
2437 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2438 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2439 IS_TRUE_SYMOP (IC_RESULT (ic)))
2443 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2446 assignResultValue (IC_RESULT (ic));
2448 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2451 /* adjust the stack for parameters if
2456 if (ic->parmBytes > 3)
2458 emitcode ("mov", "a,%s", spname);
2459 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2460 emitcode ("mov", "%s,a", spname);
2463 for (i = 0; i < ic->parmBytes; i++)
2464 emitcode ("dec", "%s", spname);
2468 /* if register bank was saved then unsave them */
2470 (FUNC_REGBANK (currFunc->type) !=
2471 FUNC_REGBANK (dtype)))
2472 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2474 /* if we hade saved some registers then
2477 unsaveRegisters (ic);
2481 /*-----------------------------------------------------------------*/
2482 /* resultRemat - result is rematerializable */
2483 /*-----------------------------------------------------------------*/
2485 resultRemat (iCode * ic)
2487 if (SKIP_IC (ic) || ic->op == IFX)
2490 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2492 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2493 if (sym->remat && !POINTER_SET (ic))
2500 #if defined(__BORLANDC__) || defined(_MSC_VER)
2501 #define STRCASECMP stricmp
2503 #define STRCASECMP strcasecmp
2506 /*-----------------------------------------------------------------*/
2507 /* inExcludeList - return 1 if the string is in exclude Reg list */
2508 /*-----------------------------------------------------------------*/
2510 inExcludeList (char *s)
2514 if (options.excludeRegs[i] &&
2515 STRCASECMP (options.excludeRegs[i], "none") == 0)
2518 for (i = 0; options.excludeRegs[i]; i++)
2520 if (options.excludeRegs[i] &&
2521 STRCASECMP (s, options.excludeRegs[i]) == 0)
2527 /*-----------------------------------------------------------------*/
2528 /* genFunction - generated code for function entry */
2529 /*-----------------------------------------------------------------*/
2531 genFunction (iCode * ic)
2535 bool switchedPSW = FALSE;
2537 D (emitcode (";", "genFunction "););
2540 /* create the function header */
2541 emitcode (";", "-----------------------------------------");
2542 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2543 emitcode (";", "-----------------------------------------");
2545 emitcode ("", "%s:", sym->rname);
2546 ftype = operandType (IC_LEFT (ic));
2548 if (IFFUNC_ISNAKED(ftype))
2550 emitcode(";", "naked function: no prologue.");
2554 /* if critical function then turn interrupts off */
2555 if (IFFUNC_ISCRITICAL (ftype))
2556 emitcode ("clr", "ea");
2558 /* here we need to generate the equates for the
2559 register bank if required */
2560 if (FUNC_REGBANK (ftype) != rbank)
2564 rbank = FUNC_REGBANK (ftype);
2565 for (i = 0; i < ds390_nRegs; i++)
2567 if (strcmp (regs390[i].base, "0") == 0)
2568 emitcode ("", "%s = 0x%02x",
2570 8 * rbank + regs390[i].offset);
2572 emitcode ("", "%s = %s + 0x%02x",
2575 8 * rbank + regs390[i].offset);
2579 /* if this is an interrupt service routine then
2580 save acc, b, dpl, dph */
2581 if (IFFUNC_ISISR (sym->type))
2584 if (!inExcludeList ("acc"))
2585 emitcode ("push", "acc");
2586 if (!inExcludeList ("b"))
2587 emitcode ("push", "b");
2588 if (!inExcludeList ("dpl"))
2589 emitcode ("push", "dpl");
2590 if (!inExcludeList ("dph"))
2591 emitcode ("push", "dph");
2592 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2594 emitcode ("push", "dpx");
2595 /* Make sure we're using standard DPTR */
2596 emitcode ("push", "dps");
2597 emitcode ("mov", "dps, #0x00");
2598 if (options.stack10bit)
2600 /* This ISR could conceivably use DPTR2. Better save it. */
2601 emitcode ("push", "dpl1");
2602 emitcode ("push", "dph1");
2603 emitcode ("push", "dpx1");
2604 emitcode ("push", DP2_RESULT_REG);
2607 /* if this isr has no bank i.e. is going to
2608 run with bank 0 , then we need to save more
2610 if (!FUNC_REGBANK (sym->type))
2613 /* if this function does not call any other
2614 function then we can be economical and
2615 save only those registers that are used */
2616 if (!IFFUNC_HASFCALL(sym->type))
2620 /* if any registers used */
2623 /* save the registers used */
2624 for (i = 0; i < sym->regsUsed->size; i++)
2626 if (bitVectBitValue (sym->regsUsed, i) ||
2627 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2628 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2635 /* this function has a function call cannot
2636 determines register usage so we will have to push the
2638 saveRBank (0, ic, FALSE);
2643 /* This ISR uses a non-zero bank.
2645 * We assume that the bank is available for our
2648 * However, if this ISR calls a function which uses some
2649 * other bank, we must save that bank entirely.
2651 unsigned long banksToSave = 0;
2653 if (IFFUNC_HASFCALL(sym->type))
2656 #define MAX_REGISTER_BANKS 4
2661 for (i = ic; i; i = i->next)
2663 if (i->op == ENDFUNCTION)
2665 /* we got to the end OK. */
2673 dtype = operandType (IC_LEFT(i));
2675 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2677 /* Mark this bank for saving. */
2678 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2680 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2684 banksToSave |= (1 << FUNC_REGBANK(dtype));
2687 /* And note that we don't need to do it in
2695 /* This is a mess; we have no idea what
2696 * register bank the called function might
2699 * The only thing I can think of to do is
2700 * throw a warning and hope.
2702 werror(W_FUNCPTR_IN_USING_ISR);
2706 if (banksToSave && options.useXstack)
2708 /* Since we aren't passing it an ic,
2709 * saveRBank will assume r0 is available to abuse.
2711 * So switch to our (trashable) bank now, so
2712 * the caller's R0 isn't trashed.
2714 emitcode ("push", "psw");
2715 emitcode ("mov", "psw,#0x%02x",
2716 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2720 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2722 if (banksToSave & (1 << ix))
2724 saveRBank(ix, NULL, FALSE);
2728 // jwk: this needs a closer look
2729 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2734 /* if callee-save to be used for this function
2735 then save the registers being used in this function */
2736 if (IFFUNC_CALLEESAVES(sym->type))
2740 /* if any registers used */
2743 /* save the registers used */
2744 for (i = 0; i < sym->regsUsed->size; i++)
2746 if (bitVectBitValue (sym->regsUsed, i) ||
2747 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2749 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2757 /* set the register bank to the desired value */
2758 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2761 emitcode ("push", "psw");
2762 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2765 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2768 if (options.useXstack)
2770 emitcode ("mov", "r0,%s", spname);
2771 emitcode ("mov", "a,_bp");
2772 emitcode ("movx", "@r0,a");
2773 emitcode ("inc", "%s", spname);
2777 /* set up the stack */
2778 emitcode ("push", "_bp"); /* save the callers stack */
2780 emitcode ("mov", "_bp,%s", spname);
2783 /* adjust the stack for the function */
2789 werror (W_STACK_OVERFLOW, sym->name);
2791 if (i > 3 && sym->recvSize < 4)
2794 emitcode ("mov", "a,sp");
2795 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2796 emitcode ("mov", "sp,a");
2801 emitcode ("inc", "sp");
2807 emitcode ("mov", "a,_spx");
2808 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2809 emitcode ("mov", "_spx,a");
2814 /*-----------------------------------------------------------------*/
2815 /* genEndFunction - generates epilogue for functions */
2816 /*-----------------------------------------------------------------*/
2818 genEndFunction (iCode * ic)
2820 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2822 D (emitcode (";", "genEndFunction "););
2824 if (IFFUNC_ISNAKED(sym->type))
2826 emitcode(";", "naked function: no epilogue.");
2830 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2832 emitcode ("mov", "%s,_bp", spname);
2835 /* if use external stack but some variables were
2836 added to the local stack then decrement the
2838 if (options.useXstack && sym->stack)
2840 emitcode ("mov", "a,sp");
2841 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2842 emitcode ("mov", "sp,a");
2846 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2848 if (options.useXstack)
2850 emitcode ("mov", "r0,%s", spname);
2851 emitcode ("movx", "a,@r0");
2852 emitcode ("mov", "_bp,a");
2853 emitcode ("dec", "%s", spname);
2857 emitcode ("pop", "_bp");
2861 /* restore the register bank */
2862 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2864 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2865 || !options.useXstack)
2867 /* Special case of ISR using non-zero bank with useXstack
2870 emitcode ("pop", "psw");
2874 if (IFFUNC_ISISR (sym->type))
2877 /* now we need to restore the registers */
2878 /* if this isr has no bank i.e. is going to
2879 run with bank 0 , then we need to save more
2881 if (!FUNC_REGBANK (sym->type))
2883 /* if this function does not call any other
2884 function then we can be economical and
2885 save only those registers that are used */
2886 if (!IFFUNC_HASFCALL(sym->type))
2890 /* if any registers used */
2893 /* save the registers used */
2894 for (i = sym->regsUsed->size; i >= 0; i--)
2896 if (bitVectBitValue (sym->regsUsed, i) ||
2897 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2898 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2905 /* this function has a function call cannot
2906 determines register usage so we will have to pop the
2908 unsaveRBank (0, ic, FALSE);
2913 /* This ISR uses a non-zero bank.
2915 * Restore any register banks saved by genFunction
2918 // jwk: this needs a closer look
2919 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2922 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2924 if (savedBanks & (1 << ix))
2926 unsaveRBank(ix, NULL, FALSE);
2930 if (options.useXstack)
2932 /* Restore bank AFTER calling unsaveRBank,
2933 * since it can trash r0.
2935 emitcode ("pop", "psw");
2939 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2941 if (options.stack10bit)
2943 emitcode ("pop", DP2_RESULT_REG);
2944 emitcode ("pop", "dpx1");
2945 emitcode ("pop", "dph1");
2946 emitcode ("pop", "dpl1");
2948 emitcode ("pop", "dps");
2949 emitcode ("pop", "dpx");
2951 if (!inExcludeList ("dph"))
2952 emitcode ("pop", "dph");
2953 if (!inExcludeList ("dpl"))
2954 emitcode ("pop", "dpl");
2955 if (!inExcludeList ("b"))
2956 emitcode ("pop", "b");
2957 if (!inExcludeList ("acc"))
2958 emitcode ("pop", "acc");
2960 if (IFFUNC_ISCRITICAL (sym->type))
2961 emitcode ("setb", "ea");
2963 /* if debug then send end of function */
2964 if (options.debug && currFunc) {
2966 emitcode ("", "C$%s$%d$%d$%d ==.",
2967 FileBaseName (ic->filename), currFunc->lastLine,
2968 ic->level, ic->block);
2969 if (IS_STATIC (currFunc->etype))
2970 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2972 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2976 emitcode ("reti", "");
2980 if (IFFUNC_ISCRITICAL (sym->type))
2981 emitcode ("setb", "ea");
2983 if (IFFUNC_CALLEESAVES(sym->type))
2987 /* if any registers used */
2990 /* save the registers used */
2991 for (i = sym->regsUsed->size; i >= 0; i--)
2993 if (bitVectBitValue (sym->regsUsed, i) ||
2994 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2995 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3001 /* if debug then send end of function */
3002 if (options.debug && currFunc)
3005 emitcode ("", "C$%s$%d$%d$%d ==.",
3006 FileBaseName (ic->filename), currFunc->lastLine,
3007 ic->level, ic->block);
3008 if (IS_STATIC (currFunc->etype))
3009 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3011 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3015 emitcode ("ret", "");
3020 /*-----------------------------------------------------------------*/
3021 /* genRet - generate code for return statement */
3022 /*-----------------------------------------------------------------*/
3026 int size, offset = 0, pushed = 0;
3028 D (emitcode (";", "genRet ");
3031 /* if we have no return value then
3032 just generate the "ret" */
3036 /* we have something to return then
3037 move the return value into place */
3038 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3039 size = AOP_SIZE (IC_LEFT (ic));
3041 _startLazyDPSEvaluation ();
3045 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3047 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3048 FALSE, TRUE, FALSE);
3049 emitcode ("push", "%s", l);
3054 /* Since A is the last element of fReturn,
3055 * is is OK to clobber it in the aopGet.
3057 l = aopGet (AOP (IC_LEFT (ic)), offset,
3058 FALSE, FALSE, TRUE);
3059 if (strcmp (fReturn[offset], l))
3060 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3063 _endLazyDPSEvaluation ();
3070 if (strcmp (fReturn[pushed], "a"))
3071 emitcode ("pop", fReturn[pushed]);
3073 emitcode ("pop", "acc");
3076 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3079 /* generate a jump to the return label
3080 if the next is not the return statement */
3081 if (!(ic->next && ic->next->op == LABEL &&
3082 IC_LABEL (ic->next) == returnLabel))
3084 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3088 /*-----------------------------------------------------------------*/
3089 /* genLabel - generates a label */
3090 /*-----------------------------------------------------------------*/
3092 genLabel (iCode * ic)
3094 /* special case never generate */
3095 if (IC_LABEL (ic) == entryLabel)
3098 D (emitcode (";", "genLabel ");
3101 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3104 /*-----------------------------------------------------------------*/
3105 /* genGoto - generates a ljmp */
3106 /*-----------------------------------------------------------------*/
3108 genGoto (iCode * ic)
3110 D (emitcode (";", "genGoto ");
3112 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3115 /*-----------------------------------------------------------------*/
3116 /* findLabelBackwards: walks back through the iCode chain looking */
3117 /* for the given label. Returns number of iCode instructions */
3118 /* between that label and given ic. */
3119 /* Returns zero if label not found. */
3120 /*-----------------------------------------------------------------*/
3122 findLabelBackwards (iCode * ic, int key)
3131 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3133 /* printf("findLabelBackwards = %d\n", count); */
3141 /*-----------------------------------------------------------------*/
3142 /* genPlusIncr :- does addition with increment if possible */
3143 /*-----------------------------------------------------------------*/
3145 genPlusIncr (iCode * ic)
3147 unsigned int icount;
3148 unsigned int size = getDataSize (IC_RESULT (ic));
3150 /* will try to generate an increment */
3151 /* if the right side is not a literal
3153 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3156 /* if the literal value of the right hand side
3157 is greater than 4 then it is not worth it */
3158 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3161 /* if increment 16 bits in register */
3163 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3164 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3165 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3173 /* If the next instruction is a goto and the goto target
3174 * is <= 5 instructions previous to this, we can generate
3175 * jumps straight to that target.
3177 if (ic->next && ic->next->op == GOTO
3178 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3181 emitcode (";", "tail increment optimized (range %d)", labelRange);
3182 tlbl = IC_LABEL (ic->next);
3187 tlbl = newiTempLabel (NULL);
3190 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3191 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3192 IS_AOP_PREG (IC_RESULT (ic)))
3193 emitcode ("cjne", "%s,#0x00,%05d$"
3194 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3198 emitcode ("clr", "a");
3199 emitcode ("cjne", "a,%s,%05d$"
3200 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3204 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3207 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3208 IS_AOP_PREG (IC_RESULT (ic)))
3209 emitcode ("cjne", "%s,#0x00,%05d$"
3210 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3213 emitcode ("cjne", "a,%s,%05d$"
3214 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3217 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3221 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3222 IS_AOP_PREG (IC_RESULT (ic)))
3223 emitcode ("cjne", "%s,#0x00,%05d$"
3224 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3228 emitcode ("cjne", "a,%s,%05d$"
3229 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3232 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3237 emitcode ("", "%05d$:", tlbl->key + 100);
3242 /* if the sizes are greater than 1 then we cannot */
3243 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3244 AOP_SIZE (IC_LEFT (ic)) > 1)
3247 /* we can if the aops of the left & result match or
3248 if they are in registers and the registers are the
3251 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3252 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3253 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3258 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3259 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3260 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3265 _startLazyDPSEvaluation ();
3268 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3270 _endLazyDPSEvaluation ();
3279 /*-----------------------------------------------------------------*/
3280 /* outBitAcc - output a bit in acc */
3281 /*-----------------------------------------------------------------*/
3283 outBitAcc (operand * result)
3285 symbol *tlbl = newiTempLabel (NULL);
3286 /* if the result is a bit */
3287 if (AOP_TYPE (result) == AOP_CRY)
3289 aopPut (AOP (result), "a", 0);
3293 emitcode ("jz", "%05d$", tlbl->key + 100);
3294 emitcode ("mov", "a,%s", one);
3295 emitcode ("", "%05d$:", tlbl->key + 100);
3300 /*-----------------------------------------------------------------*/
3301 /* genPlusBits - generates code for addition of two bits */
3302 /*-----------------------------------------------------------------*/
3304 genPlusBits (iCode * ic)
3306 D (emitcode (";", "genPlusBits ");
3308 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3310 symbol *lbl = newiTempLabel (NULL);
3311 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3312 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3313 emitcode ("cpl", "c");
3314 emitcode ("", "%05d$:", (lbl->key + 100));
3315 outBitC (IC_RESULT (ic));
3319 emitcode ("clr", "a");
3320 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3321 emitcode ("rlc", "a");
3322 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3323 emitcode ("addc", "a,#0x00");
3324 outAcc (IC_RESULT (ic));
3329 adjustArithmeticResult (iCode * ic)
3331 if (opIsGptr (IC_RESULT (ic)) &&
3332 opIsGptr (IC_LEFT (ic)) &&
3333 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3335 aopPut (AOP (IC_RESULT (ic)),
3336 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3340 if (opIsGptr (IC_RESULT (ic)) &&
3341 opIsGptr (IC_RIGHT (ic)) &&
3342 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3344 aopPut (AOP (IC_RESULT (ic)),
3345 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3349 if (opIsGptr (IC_RESULT (ic)) &&
3350 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3351 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3352 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3353 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3356 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3357 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3361 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3362 // Please don't bring it back without a really good reason.
3363 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3364 // (because all three operands are in far space).
3365 #define AOP_OP_3(ic) \
3366 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3367 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3368 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3369 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3370 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3371 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3373 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3375 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3379 // Macro to aopOp all three operands of an ic. If this cannot be done,
3380 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3381 // will be set TRUE. The caller must then handle the case specially, noting
3382 // that the IC_RESULT operand is not aopOp'd.
3383 #define AOP_OP_3_NOFATAL(ic, rc) \
3384 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3385 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3386 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3387 isOperandInFarSpace(IC_RESULT(ic))) \
3389 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3394 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3395 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3397 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3398 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3400 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3402 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3406 // aopOp the left & right operands of an ic.
3407 #define AOP_OP_2(ic) \
3408 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3409 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3411 // convienience macro.
3412 #define AOP_SET_LOCALS(ic) \
3413 left = IC_LEFT(ic); \
3414 right = IC_RIGHT(ic); \
3415 result = IC_RESULT(ic);
3418 // Given an integer value of pushedSize bytes on the stack,
3419 // adjust it to be resultSize bytes, either by discarding
3420 // the most significant bytes or by zero-padding.
3422 // On exit from this macro, pushedSize will have been adjusted to
3423 // equal resultSize, and ACC may be trashed.
3424 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3425 /* If the pushed data is bigger than the result, \
3426 * simply discard unused bytes. Icky, but works. \
3428 while (pushedSize > resultSize) \
3430 D (emitcode (";", "discarding unused result byte."););\
3431 emitcode ("pop", "acc"); \
3434 if (pushedSize < resultSize) \
3436 emitcode ("clr", "a"); \
3437 /* Conversly, we haven't pushed enough here. \
3438 * just zero-pad, and all is well. \
3440 while (pushedSize < resultSize) \
3442 emitcode("push", "acc"); \
3446 assert(pushedSize == resultSize);
3448 /*-----------------------------------------------------------------*/
3449 /* genPlus - generates code for addition */
3450 /*-----------------------------------------------------------------*/
3452 genPlus (iCode * ic)
3454 int size, offset = 0;
3455 bool pushResult = FALSE;
3458 D (emitcode (";", "genPlus "););
3460 /* special cases :- */
3462 AOP_OP_3_NOFATAL (ic, pushResult);
3465 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3470 /* if literal, literal on the right or
3471 if left requires ACC or right is already
3473 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3474 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3475 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3477 operand *t = IC_RIGHT (ic);
3478 IC_RIGHT (ic) = IC_LEFT (ic);
3480 emitcode (";", "Swapped plus args.");
3483 /* if both left & right are in bit
3485 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3486 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3492 /* if left in bit space & right literal */
3493 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3494 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3496 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3497 /* if result in bit space */
3498 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3500 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3501 emitcode ("cpl", "c");
3502 outBitC (IC_RESULT (ic));
3506 size = getDataSize (IC_RESULT (ic));
3507 _startLazyDPSEvaluation ();
3510 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3511 emitcode ("addc", "a,#00");
3512 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3514 _endLazyDPSEvaluation ();
3519 /* if I can do an increment instead
3520 of add then GOOD for ME */
3521 if (genPlusIncr (ic) == TRUE)
3523 emitcode (";", "did genPlusIncr");
3528 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3530 _startLazyDPSEvaluation ();
3533 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3535 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3537 emitcode ("add", "a,%s",
3538 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3540 emitcode ("addc", "a,%s",
3541 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3545 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3547 /* right is going to use ACC or we would have taken the
3550 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3552 D(emitcode(";", "+ AOP_ACC special case."););
3553 emitcode("xch", "a, %s", DP2_RESULT_REG);
3555 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3558 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3561 emitcode("add", "a, %s", DP2_RESULT_REG);
3565 emitcode ("add", "a,%s",
3566 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3571 emitcode ("addc", "a,%s",
3572 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3577 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3581 emitcode ("push", "acc");
3585 _endLazyDPSEvaluation ();
3589 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3591 size = getDataSize (IC_LEFT (ic));
3592 rSize = getDataSize (IC_RESULT (ic));
3594 ADJUST_PUSHED_RESULT(size, rSize);
3596 _startLazyDPSEvaluation ();
3599 emitcode ("pop", "acc");
3600 aopPut (AOP (IC_RESULT (ic)), "a", size);
3602 _endLazyDPSEvaluation ();
3605 adjustArithmeticResult (ic);
3608 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3609 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3610 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3613 /*-----------------------------------------------------------------*/
3614 /* genMinusDec :- does subtraction with deccrement if possible */
3615 /*-----------------------------------------------------------------*/
3617 genMinusDec (iCode * ic)
3619 unsigned int icount;
3620 unsigned int size = getDataSize (IC_RESULT (ic));
3622 /* will try to generate an increment */
3623 /* if the right side is not a literal
3625 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3628 /* if the literal value of the right hand side
3629 is greater than 4 then it is not worth it */
3630 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3633 /* if decrement 16 bits in register */
3634 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3635 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3636 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3644 /* If the next instruction is a goto and the goto target
3645 * is <= 5 instructions previous to this, we can generate
3646 * jumps straight to that target.
3648 if (ic->next && ic->next->op == GOTO
3649 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3652 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3653 tlbl = IC_LABEL (ic->next);
3658 tlbl = newiTempLabel (NULL);
3662 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3663 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3664 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3665 IS_AOP_PREG (IC_RESULT (ic)))
3666 emitcode ("cjne", "%s,#0xff,%05d$"
3667 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3671 emitcode ("mov", "a,#0xff");
3672 emitcode ("cjne", "a,%s,%05d$"
3673 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3676 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3679 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3680 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3681 IS_AOP_PREG (IC_RESULT (ic)))
3682 emitcode ("cjne", "%s,#0xff,%05d$"
3683 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3687 emitcode ("cjne", "a,%s,%05d$"
3688 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3691 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3695 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3696 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3697 IS_AOP_PREG (IC_RESULT (ic)))
3698 emitcode ("cjne", "%s,#0xff,%05d$"
3699 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3703 emitcode ("cjne", "a,%s,%05d$"
3704 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3707 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3711 emitcode ("", "%05d$:", tlbl->key + 100);
3716 /* if the sizes are greater than 1 then we cannot */
3717 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3718 AOP_SIZE (IC_LEFT (ic)) > 1)
3721 /* we can if the aops of the left & result match or
3722 if they are in registers and the registers are the
3725 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3726 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3727 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3730 _startLazyDPSEvaluation ();
3733 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3735 _endLazyDPSEvaluation ();
3743 /*-----------------------------------------------------------------*/
3744 /* addSign - complete with sign */
3745 /*-----------------------------------------------------------------*/
3747 addSign (operand * result, int offset, int sign)
3749 int size = (getDataSize (result) - offset);
3752 _startLazyDPSEvaluation();
3755 emitcode ("rlc", "a");
3756 emitcode ("subb", "a,acc");
3759 aopPut (AOP (result), "a", offset++);
3766 aopPut (AOP (result), zero, offset++);
3769 _endLazyDPSEvaluation();
3773 /*-----------------------------------------------------------------*/
3774 /* genMinusBits - generates code for subtraction of two bits */
3775 /*-----------------------------------------------------------------*/
3777 genMinusBits (iCode * ic)
3779 symbol *lbl = newiTempLabel (NULL);
3781 D (emitcode (";", "genMinusBits "););
3783 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3785 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3786 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3787 emitcode ("cpl", "c");
3788 emitcode ("", "%05d$:", (lbl->key + 100));
3789 outBitC (IC_RESULT (ic));
3793 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3794 emitcode ("subb", "a,acc");
3795 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3796 emitcode ("inc", "a");
3797 emitcode ("", "%05d$:", (lbl->key + 100));
3798 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3799 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3803 /*-----------------------------------------------------------------*/
3804 /* genMinus - generates code for subtraction */
3805 /*-----------------------------------------------------------------*/
3807 genMinus (iCode * ic)
3809 int size, offset = 0;
3811 unsigned long lit = 0L;
3812 bool pushResult = FALSE;
3814 D (emitcode (";", "genMinus "););
3816 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3817 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3818 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3819 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3825 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3827 /* special cases :- */
3828 /* if both left & right are in bit space */
3829 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3830 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3836 /* if I can do an decrement instead
3837 of subtract then GOOD for ME */
3838 if (genMinusDec (ic) == TRUE)
3843 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3845 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3851 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3856 /* if literal, add a,#-lit, else normal subb */
3857 _startLazyDPSEvaluation ();
3860 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3861 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3862 emitcode ("subb", "a,%s",
3863 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3866 /* first add without previous c */
3868 if (!size && lit==-1) {
3869 emitcode ("dec", "a");
3871 emitcode ("add", "a,#0x%02x",
3872 (unsigned int) (lit & 0x0FFL));
3875 emitcode ("addc", "a,#0x%02x",
3876 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3882 emitcode ("push", "acc");
3886 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3890 _endLazyDPSEvaluation ();
3894 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3896 size = getDataSize (IC_LEFT (ic));
3897 rSize = getDataSize (IC_RESULT (ic));
3899 ADJUST_PUSHED_RESULT(size, rSize);
3901 _startLazyDPSEvaluation ();
3904 emitcode ("pop", "acc");
3905 aopPut (AOP (IC_RESULT (ic)), "a", size);
3907 _endLazyDPSEvaluation ();
3910 adjustArithmeticResult (ic);
3913 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3914 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3915 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3919 /*-----------------------------------------------------------------*/
3920 /* genMultbits :- multiplication of bits */
3921 /*-----------------------------------------------------------------*/
3923 genMultbits (operand * left,
3928 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3929 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3930 aopOp(result, ic, TRUE, FALSE);
3935 /*-----------------------------------------------------------------*/
3936 /* genMultOneByte : 8*8=8/16 bit multiplication */
3937 /*-----------------------------------------------------------------*/
3939 genMultOneByte (operand * left,
3944 sym_link *opetype = operandType (result);
3948 /* (if two literals: the value is computed before) */
3949 /* if one literal, literal on the right */
3950 if (AOP_TYPE (left) == AOP_LIT)
3955 emitcode (";", "swapped left and right");
3958 if (SPEC_USIGN(opetype)
3959 // ignore the sign of left and right, what else can we do?
3960 || (SPEC_USIGN(operandType(left)) &&
3961 SPEC_USIGN(operandType(right)))) {
3962 // just an unsigned 8*8=8/16 multiply
3963 //emitcode (";","unsigned");
3964 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3965 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3966 emitcode ("mul", "ab");
3969 aopOp(result, ic, TRUE, FALSE);
3971 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
3973 // this should never happen
3974 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3975 AOP_SIZE(result), __FILE__, lineno);
3979 aopPut (AOP (result), "a", 0);
3981 if (AOP_SIZE(result)==2)
3983 aopPut (AOP (result), "b", 1);
3988 // we have to do a signed multiply
3990 emitcode (";", "signed");
3991 emitcode ("clr", "F0"); // reset sign flag
3992 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3994 lbl=newiTempLabel(NULL);
3995 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3996 // left side is negative, 8-bit two's complement, this fails for -128
3997 emitcode ("setb", "F0"); // set sign flag
3998 emitcode ("cpl", "a");
3999 emitcode ("inc", "a");
4001 emitcode ("", "%05d$:", lbl->key+100);
4004 if (AOP_TYPE(right)==AOP_LIT) {
4005 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4006 /* AND literal negative */
4007 if ((int) val < 0) {
4008 emitcode ("cpl", "F0"); // complement sign flag
4009 emitcode ("mov", "b,#0x%02x", -val);
4011 emitcode ("mov", "b,#0x%02x", val);
4014 lbl=newiTempLabel(NULL);
4015 emitcode ("mov", "b,a");
4016 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4017 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4018 // right side is negative, 8-bit two's complement
4019 emitcode ("cpl", "F0"); // complement sign flag
4020 emitcode ("cpl", "a");
4021 emitcode ("inc", "a");
4022 emitcode ("", "%05d$:", lbl->key+100);
4024 emitcode ("mul", "ab");
4027 aopOp(result, ic, TRUE, FALSE);
4029 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4031 // this should never happen
4032 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4033 AOP_SIZE(result), __FILE__, lineno);
4037 lbl=newiTempLabel(NULL);
4038 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4039 // only ONE op was negative, we have to do a 8/16-bit two's complement
4040 emitcode ("cpl", "a"); // lsb
4041 if (AOP_SIZE(result)==1) {
4042 emitcode ("inc", "a");
4044 emitcode ("add", "a,#1");
4045 emitcode ("xch", "a,b");
4046 emitcode ("cpl", "a"); // msb
4047 emitcode ("addc", "a,#0");
4048 emitcode ("xch", "a,b");
4051 emitcode ("", "%05d$:", lbl->key+100);
4052 aopPut (AOP (result), "a", 0);
4054 if (AOP_SIZE(result)==2) {
4055 aopPut (AOP (result), "b", 1);
4059 /*-----------------------------------------------------------------*/
4060 /* genMult - generates code for multiplication */
4061 /*-----------------------------------------------------------------*/
4063 genMult (iCode * ic)
4065 operand *left = IC_LEFT (ic);
4066 operand *right = IC_RIGHT (ic);
4067 operand *result = IC_RESULT (ic);
4069 D (emitcode (";", "genMult "););
4071 /* assign the amsops */
4074 /* special cases first */
4076 if (AOP_TYPE (left) == AOP_CRY &&
4077 AOP_TYPE (right) == AOP_CRY)
4079 genMultbits (left, right, result, ic);
4083 /* if both are of size == 1 */
4084 if (AOP_SIZE (left) == 1 &&
4085 AOP_SIZE (right) == 1)
4087 genMultOneByte (left, right, result, ic);
4091 /* should have been converted to function call */
4095 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4096 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4097 freeAsmop (result, NULL, ic, TRUE);
4100 /*-----------------------------------------------------------------*/
4101 /* genDivbits :- division of bits */
4102 /*-----------------------------------------------------------------*/
4104 genDivbits (operand * left,
4112 /* the result must be bit */
4113 LOAD_AB_FOR_DIV (left, right, l);
4114 emitcode ("div", "ab");
4115 emitcode ("rrc", "a");
4116 aopOp(result, ic, TRUE, FALSE);
4118 aopPut (AOP (result), "c", 0);
4121 /*-----------------------------------------------------------------*/
4122 /* genDivOneByte : 8 bit division */
4123 /*-----------------------------------------------------------------*/
4125 genDivOneByte (operand * left,
4130 sym_link *opetype = operandType (result);
4136 /* signed or unsigned */
4137 if (SPEC_USIGN (opetype))
4139 /* unsigned is easy */
4140 LOAD_AB_FOR_DIV (left, right, l);
4141 emitcode ("div", "ab");
4144 aopOp(result, ic, TRUE, FALSE);
4145 aopPut (AOP (result), "a", 0);
4148 size = AOP_SIZE (result) - 1;
4152 aopPut (AOP (result), zero, offset++);
4157 /* signed is a little bit more difficult */
4159 /* save the signs of the operands */
4160 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4162 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4163 emitcode ("push", "acc"); /* save it on the stack */
4165 /* now sign adjust for both left & right */
4166 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4168 lbl = newiTempLabel (NULL);
4169 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4170 emitcode ("cpl", "a");
4171 emitcode ("inc", "a");
4172 emitcode ("", "%05d$:", (lbl->key + 100));
4173 emitcode ("mov", "b,a");
4175 /* sign adjust left side */
4176 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4179 lbl = newiTempLabel (NULL);
4180 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4181 emitcode ("cpl", "a");
4182 emitcode ("inc", "a");
4183 emitcode ("", "%05d$:", (lbl->key + 100));
4185 /* now the division */
4186 emitcode ("nop", "; workaround for DS80C390 div bug.");
4187 emitcode ("div", "ab");
4188 /* we are interested in the lower order
4190 emitcode ("mov", "b,a");
4191 lbl = newiTempLabel (NULL);
4192 emitcode ("pop", "acc");
4193 /* if there was an over flow we don't
4194 adjust the sign of the result */
4195 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4196 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4198 emitcode ("clr", "a");
4199 emitcode ("subb", "a,b");
4200 emitcode ("mov", "b,a");
4201 emitcode ("", "%05d$:", (lbl->key + 100));
4203 /* now we are done */
4205 aopOp(result, ic, TRUE, FALSE);
4207 aopPut (AOP (result), "b", 0);
4209 size = AOP_SIZE (result) - 1;
4213 emitcode ("mov", "c,b.7");
4214 emitcode ("subb", "a,acc");
4218 aopPut (AOP (result), "a", offset++);
4224 /*-----------------------------------------------------------------*/
4225 /* genDiv - generates code for division */
4226 /*-----------------------------------------------------------------*/
4230 operand *left = IC_LEFT (ic);
4231 operand *right = IC_RIGHT (ic);
4232 operand *result = IC_RESULT (ic);
4234 D (emitcode (";", "genDiv "););
4236 /* assign the amsops */
4239 /* special cases first */
4241 if (AOP_TYPE (left) == AOP_CRY &&
4242 AOP_TYPE (right) == AOP_CRY)
4244 genDivbits (left, right, result, ic);
4248 /* if both are of size == 1 */
4249 if (AOP_SIZE (left) == 1 &&
4250 AOP_SIZE (right) == 1)
4252 genDivOneByte (left, right, result, ic);
4256 /* should have been converted to function call */
4259 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4260 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4261 freeAsmop (result, NULL, ic, TRUE);
4264 /*-----------------------------------------------------------------*/
4265 /* genModbits :- modulus of bits */
4266 /*-----------------------------------------------------------------*/
4268 genModbits (operand * left,
4276 /* the result must be bit */
4277 LOAD_AB_FOR_DIV (left, right, l);
4278 emitcode ("div", "ab");
4279 emitcode ("mov", "a,b");
4280 emitcode ("rrc", "a");
4281 aopOp(result, ic, TRUE, FALSE);
4282 aopPut (AOP (result), "c", 0);
4285 /*-----------------------------------------------------------------*/
4286 /* genModOneByte : 8 bit modulus */
4287 /*-----------------------------------------------------------------*/
4289 genModOneByte (operand * left,
4294 sym_link *opetype = operandType (result);
4298 /* signed or unsigned */
4299 if (SPEC_USIGN (opetype))
4301 /* unsigned is easy */
4302 LOAD_AB_FOR_DIV (left, right, l);
4303 emitcode ("div", "ab");
4304 aopOp(result, ic, TRUE, FALSE);
4305 aopPut (AOP (result), "b", 0);
4309 /* signed is a little bit more difficult */
4311 /* save the signs of the operands */
4312 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4315 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4316 emitcode ("push", "acc"); /* save it on the stack */
4318 /* now sign adjust for both left & right */
4319 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4322 lbl = newiTempLabel (NULL);
4323 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4324 emitcode ("cpl", "a");
4325 emitcode ("inc", "a");
4326 emitcode ("", "%05d$:", (lbl->key + 100));
4327 emitcode ("mov", "b,a");
4329 /* sign adjust left side */
4330 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4333 lbl = newiTempLabel (NULL);
4334 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4335 emitcode ("cpl", "a");
4336 emitcode ("inc", "a");
4337 emitcode ("", "%05d$:", (lbl->key + 100));
4339 /* now the multiplication */
4340 emitcode ("nop", "; workaround for DS80C390 div bug.");
4341 emitcode ("div", "ab");
4342 /* we are interested in the lower order
4344 lbl = newiTempLabel (NULL);
4345 emitcode ("pop", "acc");
4346 /* if there was an over flow we don't
4347 adjust the sign of the result */
4348 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4349 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4351 emitcode ("clr", "a");
4352 emitcode ("subb", "a,b");
4353 emitcode ("mov", "b,a");
4354 emitcode ("", "%05d$:", (lbl->key + 100));
4356 /* now we are done */
4357 aopOp(result, ic, TRUE, FALSE);
4358 aopPut (AOP (result), "b", 0);
4362 /*-----------------------------------------------------------------*/
4363 /* genMod - generates code for division */
4364 /*-----------------------------------------------------------------*/
4368 operand *left = IC_LEFT (ic);
4369 operand *right = IC_RIGHT (ic);
4370 operand *result = IC_RESULT (ic);
4372 D (emitcode (";", "genMod "); );
4374 /* assign the amsops */
4377 /* special cases first */
4379 if (AOP_TYPE (left) == AOP_CRY &&
4380 AOP_TYPE (right) == AOP_CRY)
4382 genModbits (left, right, result, ic);
4386 /* if both are of size == 1 */
4387 if (AOP_SIZE (left) == 1 &&
4388 AOP_SIZE (right) == 1)
4390 genModOneByte (left, right, result, ic);
4394 /* should have been converted to function call */
4398 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4399 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4400 freeAsmop (result, NULL, ic, TRUE);
4403 /*-----------------------------------------------------------------*/
4404 /* genIfxJump :- will create a jump depending on the ifx */
4405 /*-----------------------------------------------------------------*/
4407 genIfxJump (iCode * ic, char *jval)
4410 symbol *tlbl = newiTempLabel (NULL);
4413 D (emitcode (";", "genIfxJump ");
4416 /* if true label then we jump if condition
4420 jlbl = IC_TRUE (ic);
4421 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4422 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4426 /* false label is present */
4427 jlbl = IC_FALSE (ic);
4428 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4429 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4431 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4432 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4434 emitcode (inst, "%05d$", tlbl->key + 100);
4435 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4436 emitcode ("", "%05d$:", tlbl->key + 100);
4438 /* mark the icode as generated */
4442 /*-----------------------------------------------------------------*/
4443 /* genCmp :- greater or less than comparison */
4444 /*-----------------------------------------------------------------*/
4446 genCmp (operand * left, operand * right,
4447 iCode * ic, iCode * ifx, int sign)
4449 int size, offset = 0;
4450 unsigned long lit = 0L;
4453 D (emitcode (";", "genCmp");
4456 result = IC_RESULT (ic);
4458 /* if left & right are bit variables */
4459 if (AOP_TYPE (left) == AOP_CRY &&
4460 AOP_TYPE (right) == AOP_CRY)
4462 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4463 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4467 /* subtract right from left if at the
4468 end the carry flag is set then we know that
4469 left is greater than right */
4470 size = max (AOP_SIZE (left), AOP_SIZE (right));
4472 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4473 if ((size == 1) && !sign &&
4474 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4476 symbol *lbl = newiTempLabel (NULL);
4477 emitcode ("cjne", "%s,%s,%05d$",
4478 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4479 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4481 emitcode ("", "%05d$:", lbl->key + 100);
4485 if (AOP_TYPE (right) == AOP_LIT)
4487 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4488 /* optimize if(x < 0) or if(x >= 0) */
4497 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4499 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4500 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4502 aopOp (result, ic, FALSE, FALSE);
4504 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4506 freeAsmop (result, NULL, ic, TRUE);
4507 genIfxJump (ifx, "acc.7");
4512 emitcode ("rlc", "a");
4514 goto release_freedLR;
4522 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4523 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4524 emitcode (";", "genCmp #2");
4525 if (sign && (size == 0))
4527 emitcode (";", "genCmp #3");
4528 emitcode ("xrl", "a,#0x80");
4529 if (AOP_TYPE (right) == AOP_LIT)
4531 unsigned long lit = (unsigned long)
4532 floatFromVal (AOP (right)->aopu.aop_lit);
4533 emitcode (";", "genCmp #3.1");
4534 emitcode ("subb", "a,#0x%02x",
4535 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4539 emitcode (";", "genCmp #3.2");
4540 if (AOP_NEEDSACC (right))
4542 emitcode ("push", "acc");
4544 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4545 FALSE, FALSE, FALSE));
4546 emitcode ("xrl", "b,#0x80");
4547 if (AOP_NEEDSACC (right))
4549 emitcode ("pop", "acc");
4551 emitcode ("subb", "a,b");
4558 emitcode (";", "genCmp #4");
4559 if (AOP_NEEDSACC (right))
4562 emitcode (";", "genCmp #4.1");
4563 emitcode ("xch", "a, b");
4564 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4565 emitcode ("xch", "a, b");
4570 emitcode (";", "genCmp #4.2");
4571 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4574 emitcode ("subb", "a,%s", s);
4581 /* Don't need the left & right operands any more; do need the result. */
4582 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4583 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4585 aopOp (result, ic, FALSE, FALSE);
4589 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4595 /* if the result is used in the next
4596 ifx conditional branch then generate
4597 code a little differently */
4600 genIfxJump (ifx, "c");
4606 /* leave the result in acc */
4608 freeAsmop (result, NULL, ic, TRUE);
4611 /*-----------------------------------------------------------------*/
4612 /* genCmpGt :- greater than comparison */
4613 /*-----------------------------------------------------------------*/
4615 genCmpGt (iCode * ic, iCode * ifx)
4617 operand *left, *right;
4618 sym_link *letype, *retype;
4621 D (emitcode (";", "genCmpGt ");
4624 left = IC_LEFT (ic);
4625 right = IC_RIGHT (ic);
4627 letype = getSpec (operandType (left));
4628 retype = getSpec (operandType (right));
4629 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4631 /* assign the left & right amsops */
4634 genCmp (right, left, ic, ifx, sign);
4637 /*-----------------------------------------------------------------*/
4638 /* genCmpLt - less than comparisons */
4639 /*-----------------------------------------------------------------*/
4641 genCmpLt (iCode * ic, iCode * ifx)
4643 operand *left, *right;
4644 sym_link *letype, *retype;
4647 D (emitcode (";", "genCmpLt "););
4649 left = IC_LEFT (ic);
4650 right = IC_RIGHT (ic);
4652 letype = getSpec (operandType (left));
4653 retype = getSpec (operandType (right));
4654 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4656 /* assign the left & right amsops */
4659 genCmp (left, right, ic, ifx, sign);
4662 /*-----------------------------------------------------------------*/
4663 /* gencjneshort - compare and jump if not equal */
4664 /*-----------------------------------------------------------------*/
4666 gencjneshort (operand * left, operand * right, symbol * lbl)
4668 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4670 unsigned long lit = 0L;
4672 D (emitcode (";", "gencjneshort");
4675 /* if the left side is a literal or
4676 if the right is in a pointer register and left
4678 if ((AOP_TYPE (left) == AOP_LIT) ||
4679 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4686 if (AOP_TYPE (right) == AOP_LIT)
4687 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4689 if (opIsGptr (left) || opIsGptr (right))
4691 /* We are comparing a generic pointer to something.
4692 * Exclude the generic type byte from the comparison.
4695 D (emitcode (";", "cjneshort: generic ptr special case.");
4700 /* if the right side is a literal then anything goes */
4701 if (AOP_TYPE (right) == AOP_LIT &&
4702 AOP_TYPE (left) != AOP_DIR)
4706 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4708 emitcode ("cjne", "a,%s,%05d$",
4709 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4715 /* if the right side is in a register or in direct space or
4716 if the left is a pointer register & right is not */
4717 else if (AOP_TYPE (right) == AOP_REG ||
4718 AOP_TYPE (right) == AOP_DIR ||
4719 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4720 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4724 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4725 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4726 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4727 emitcode ("jnz", "%05d$", lbl->key + 100);
4729 emitcode ("cjne", "a,%s,%05d$",
4730 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4737 /* right is a pointer reg need both a & b */
4740 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4741 if (strcmp (l, "b"))
4742 emitcode ("mov", "b,%s", l);
4743 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4744 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4750 /*-----------------------------------------------------------------*/
4751 /* gencjne - compare and jump if not equal */
4752 /*-----------------------------------------------------------------*/
4754 gencjne (operand * left, operand * right, symbol * lbl)
4756 symbol *tlbl = newiTempLabel (NULL);
4758 D (emitcode (";", "gencjne");
4761 gencjneshort (left, right, lbl);
4763 emitcode ("mov", "a,%s", one);
4764 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4765 emitcode ("", "%05d$:", lbl->key + 100);
4766 emitcode ("clr", "a");
4767 emitcode ("", "%05d$:", tlbl->key + 100);
4770 /*-----------------------------------------------------------------*/
4771 /* genCmpEq - generates code for equal to */
4772 /*-----------------------------------------------------------------*/
4774 genCmpEq (iCode * ic, iCode * ifx)
4776 operand *left, *right, *result;
4778 D (emitcode (";", "genCmpEq ");
4782 AOP_SET_LOCALS (ic);
4784 /* if literal, literal on the right or
4785 if the right is in a pointer register and left
4787 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4788 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4790 operand *t = IC_RIGHT (ic);
4791 IC_RIGHT (ic) = IC_LEFT (ic);
4795 if (ifx && /* !AOP_SIZE(result) */
4796 OP_SYMBOL (result) &&
4797 OP_SYMBOL (result)->regType == REG_CND)
4800 /* if they are both bit variables */
4801 if (AOP_TYPE (left) == AOP_CRY &&
4802 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4804 if (AOP_TYPE (right) == AOP_LIT)
4806 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4809 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4810 emitcode ("cpl", "c");
4814 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4818 emitcode ("clr", "c");
4820 /* AOP_TYPE(right) == AOP_CRY */
4824 symbol *lbl = newiTempLabel (NULL);
4825 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4826 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4827 emitcode ("cpl", "c");
4828 emitcode ("", "%05d$:", (lbl->key + 100));
4830 /* if true label then we jump if condition
4832 tlbl = newiTempLabel (NULL);
4835 emitcode ("jnc", "%05d$", tlbl->key + 100);
4836 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4840 emitcode ("jc", "%05d$", tlbl->key + 100);
4841 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4843 emitcode ("", "%05d$:", tlbl->key + 100);
4847 tlbl = newiTempLabel (NULL);
4848 gencjneshort (left, right, tlbl);
4851 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4852 emitcode ("", "%05d$:", tlbl->key + 100);
4856 symbol *lbl = newiTempLabel (NULL);
4857 emitcode ("sjmp", "%05d$", lbl->key + 100);
4858 emitcode ("", "%05d$:", tlbl->key + 100);
4859 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4860 emitcode ("", "%05d$:", lbl->key + 100);
4863 /* mark the icode as generated */
4866 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4867 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4871 /* if they are both bit variables */
4872 if (AOP_TYPE (left) == AOP_CRY &&
4873 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4875 if (AOP_TYPE (right) == AOP_LIT)
4877 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4880 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4881 emitcode ("cpl", "c");
4885 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4889 emitcode ("clr", "c");
4891 /* AOP_TYPE(right) == AOP_CRY */
4895 symbol *lbl = newiTempLabel (NULL);
4896 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4897 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4898 emitcode ("cpl", "c");
4899 emitcode ("", "%05d$:", (lbl->key + 100));
4902 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4903 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4905 aopOp (result, ic, TRUE, FALSE);
4908 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4915 genIfxJump (ifx, "c");
4918 /* if the result is used in an arithmetic operation
4919 then put the result in place */
4924 gencjne (left, right, newiTempLabel (NULL));
4926 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4927 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4929 aopOp (result, ic, TRUE, FALSE);
4931 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4933 aopPut (AOP (result), "a", 0);
4938 genIfxJump (ifx, "a");
4941 /* if the result is used in an arithmetic operation
4942 then put the result in place */
4943 if (AOP_TYPE (result) != AOP_CRY)
4945 /* leave the result in acc */
4949 freeAsmop (result, NULL, ic, TRUE);
4952 /*-----------------------------------------------------------------*/
4953 /* ifxForOp - returns the icode containing the ifx for operand */
4954 /*-----------------------------------------------------------------*/
4956 ifxForOp (operand * op, iCode * ic)
4958 /* if true symbol then needs to be assigned */
4959 if (IS_TRUE_SYMOP (op))
4962 /* if this has register type condition and
4963 the next instruction is ifx with the same operand
4964 and live to of the operand is upto the ifx only then */
4966 ic->next->op == IFX &&
4967 IC_COND (ic->next)->key == op->key &&
4968 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4973 /*-----------------------------------------------------------------*/
4974 /* genAndOp - for && operation */
4975 /*-----------------------------------------------------------------*/
4977 genAndOp (iCode * ic)
4979 operand *left, *right, *result;
4982 D (emitcode (";", "genAndOp "););
4984 /* note here that && operations that are in an
4985 if statement are taken away by backPatchLabels
4986 only those used in arthmetic operations remain */
4988 AOP_SET_LOCALS (ic);
4990 /* if both are bit variables */
4991 if (AOP_TYPE (left) == AOP_CRY &&
4992 AOP_TYPE (right) == AOP_CRY)
4994 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4995 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4999 aopOp (result,ic,FALSE, FALSE);
5004 tlbl = newiTempLabel (NULL);
5006 emitcode ("jz", "%05d$", tlbl->key + 100);
5008 emitcode ("", "%05d$:", tlbl->key + 100);
5009 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5010 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5012 aopOp (result,ic,FALSE, FALSE);
5015 freeAsmop (result, NULL, ic, TRUE);
5019 /*-----------------------------------------------------------------*/
5020 /* genOrOp - for || operation */
5021 /*-----------------------------------------------------------------*/
5023 genOrOp (iCode * ic)
5025 operand *left, *right, *result;
5028 D (emitcode (";", "genOrOp "););
5030 /* note here that || operations that are in an
5031 if statement are taken away by backPatchLabels
5032 only those used in arthmetic operations remain */
5034 AOP_SET_LOCALS (ic);
5036 /* if both are bit variables */
5037 if (AOP_TYPE (left) == AOP_CRY &&
5038 AOP_TYPE (right) == AOP_CRY)
5040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5041 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5042 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5043 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5045 aopOp (result,ic,FALSE, FALSE);
5051 tlbl = newiTempLabel (NULL);
5053 emitcode ("jnz", "%05d$", tlbl->key + 100);
5055 emitcode ("", "%05d$:", tlbl->key + 100);
5056 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5057 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5059 aopOp (result,ic,FALSE, FALSE);
5064 freeAsmop (result, NULL, ic, TRUE);
5067 /*-----------------------------------------------------------------*/
5068 /* isLiteralBit - test if lit == 2^n */
5069 /*-----------------------------------------------------------------*/
5071 isLiteralBit (unsigned long lit)
5073 unsigned long pw[32] =
5074 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5075 0x100L, 0x200L, 0x400L, 0x800L,
5076 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5077 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5078 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5079 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5080 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5083 for (idx = 0; idx < 32; idx++)
5089 /*-----------------------------------------------------------------*/
5090 /* continueIfTrue - */
5091 /*-----------------------------------------------------------------*/
5093 continueIfTrue (iCode * ic)
5096 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5100 /*-----------------------------------------------------------------*/
5102 /*-----------------------------------------------------------------*/
5104 jumpIfTrue (iCode * ic)
5107 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5111 /*-----------------------------------------------------------------*/
5112 /* jmpTrueOrFalse - */
5113 /*-----------------------------------------------------------------*/
5115 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5117 // ugly but optimized by peephole
5120 symbol *nlbl = newiTempLabel (NULL);
5121 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5122 emitcode ("", "%05d$:", tlbl->key + 100);
5123 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5124 emitcode ("", "%05d$:", nlbl->key + 100);
5128 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5129 emitcode ("", "%05d$:", tlbl->key + 100);
5134 // Generate code to perform a bit-wise logic operation
5135 // on two operands in far space (assumed to already have been
5136 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5137 // in far space. This requires pushing the result on the stack
5138 // then popping it into the result.
5140 genFarFarLogicOp(iCode *ic, char *logicOp)
5142 int size, resultSize, compSize;
5146 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5147 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5148 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5150 _startLazyDPSEvaluation();
5151 for (size = compSize; (size--); offset++)
5153 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5154 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5155 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5157 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5158 emitcode ("push", "acc");
5160 _endLazyDPSEvaluation();
5162 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5163 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5164 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5166 resultSize = AOP_SIZE(IC_RESULT(ic));
5168 ADJUST_PUSHED_RESULT(compSize, resultSize);
5170 _startLazyDPSEvaluation();
5173 emitcode ("pop", "acc");
5174 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5176 _endLazyDPSEvaluation();
5177 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5181 /*-----------------------------------------------------------------*/
5182 /* genAnd - code for and */
5183 /*-----------------------------------------------------------------*/
5185 genAnd (iCode * ic, iCode * ifx)
5187 operand *left, *right, *result;
5188 int size, offset = 0;
5189 unsigned long lit = 0L;
5194 D (emitcode (";", "genAnd "););
5196 AOP_OP_3_NOFATAL (ic, pushResult);
5197 AOP_SET_LOCALS (ic);
5201 genFarFarLogicOp(ic, "anl");
5206 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5208 AOP_TYPE (left), AOP_TYPE (right));
5209 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5211 AOP_SIZE (left), AOP_SIZE (right));
5214 /* if left is a literal & right is not then exchange them */
5215 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5216 AOP_NEEDSACC (left))
5218 operand *tmp = right;
5223 /* if result = right then exchange them */
5224 if (sameRegs (AOP (result), AOP (right)))
5226 operand *tmp = right;
5231 /* if right is bit then exchange them */
5232 if (AOP_TYPE (right) == AOP_CRY &&
5233 AOP_TYPE (left) != AOP_CRY)
5235 operand *tmp = right;
5239 if (AOP_TYPE (right) == AOP_LIT)
5240 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5242 size = AOP_SIZE (result);
5245 // result = bit & yy;
5246 if (AOP_TYPE (left) == AOP_CRY)
5248 // c = bit & literal;
5249 if (AOP_TYPE (right) == AOP_LIT)
5253 if (size && sameRegs (AOP (result), AOP (left)))
5256 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5261 if (size && (AOP_TYPE (result) == AOP_CRY))
5263 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5266 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5271 emitcode ("clr", "c");
5276 if (AOP_TYPE (right) == AOP_CRY)
5279 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5280 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5285 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5287 emitcode ("rrc", "a");
5288 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5296 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5297 genIfxJump (ifx, "c");
5301 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5302 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5303 if ((AOP_TYPE (right) == AOP_LIT) &&
5304 (AOP_TYPE (result) == AOP_CRY) &&
5305 (AOP_TYPE (left) != AOP_CRY))
5307 int posbit = isLiteralBit (lit);
5312 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5315 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5321 sprintf (buffer, "acc.%d", posbit & 0x07);
5322 genIfxJump (ifx, buffer);
5329 symbol *tlbl = newiTempLabel (NULL);
5330 int sizel = AOP_SIZE (left);
5332 emitcode ("setb", "c");
5335 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5337 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5339 if ((posbit = isLiteralBit (bytelit)) != 0)
5340 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5343 if (bytelit != 0x0FFL)
5344 emitcode ("anl", "a,%s",
5345 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5346 emitcode ("jnz", "%05d$", tlbl->key + 100);
5351 // bit = left & literal
5354 emitcode ("clr", "c");
5355 emitcode ("", "%05d$:", tlbl->key + 100);
5357 // if(left & literal)
5361 jmpTrueOrFalse (ifx, tlbl);
5369 /* if left is same as result */
5370 if (sameRegs (AOP (result), AOP (left)))
5372 for (; size--; offset++)
5374 if (AOP_TYPE (right) == AOP_LIT)
5376 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5378 else if (bytelit == 0)
5379 aopPut (AOP (result), zero, offset);
5380 else if (IS_AOP_PREG (result))
5382 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5383 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5384 aopPut (AOP (result), "a", offset);
5387 emitcode ("anl", "%s,%s",
5388 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5389 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5393 if (AOP_TYPE (left) == AOP_ACC)
5394 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5397 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5398 if (IS_AOP_PREG (result))
5400 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5401 aopPut (AOP (result), "a", offset);
5405 emitcode ("anl", "%s,a",
5406 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5413 // left & result in different registers
5414 if (AOP_TYPE (result) == AOP_CRY)
5417 // if(size), result in bit
5418 // if(!size && ifx), conditional oper: if(left & right)
5419 symbol *tlbl = newiTempLabel (NULL);
5420 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5422 emitcode ("setb", "c");
5425 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5426 emitcode ("anl", "a,%s",
5427 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5429 if (AOP_TYPE(left)==AOP_ACC) {
5430 emitcode("mov", "b,a");
5431 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5432 emitcode("anl", "a,b");
5434 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5435 emitcode ("anl", "a,%s",
5436 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5439 emitcode ("jnz", "%05d$", tlbl->key + 100);
5445 emitcode ("", "%05d$:", tlbl->key + 100);
5449 jmpTrueOrFalse (ifx, tlbl);
5453 for (; (size--); offset++)
5456 // result = left & right
5457 if (AOP_TYPE (right) == AOP_LIT)
5459 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5461 aopPut (AOP (result),
5462 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5466 else if (bytelit == 0)
5468 aopPut (AOP (result), zero, offset);
5471 D (emitcode (";", "better literal AND.");
5473 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5474 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5475 FALSE, FALSE, FALSE));
5480 // faster than result <- left, anl result,right
5481 // and better if result is SFR
5482 if (AOP_TYPE (left) == AOP_ACC)
5484 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5485 FALSE, FALSE, FALSE));
5489 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5490 emitcode ("anl", "a,%s",
5491 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5494 aopPut (AOP (result), "a", offset);
5500 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5501 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502 freeAsmop (result, NULL, ic, TRUE);
5506 /*-----------------------------------------------------------------*/
5507 /* genOr - code for or */
5508 /*-----------------------------------------------------------------*/
5510 genOr (iCode * ic, iCode * ifx)
5512 operand *left, *right, *result;
5513 int size, offset = 0;
5514 unsigned long lit = 0L;
5517 D (emitcode (";", "genOr "););
5519 AOP_OP_3_NOFATAL (ic, pushResult);
5520 AOP_SET_LOCALS (ic);
5524 genFarFarLogicOp(ic, "orl");
5530 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5532 AOP_TYPE (left), AOP_TYPE (right));
5533 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5535 AOP_SIZE (left), AOP_SIZE (right));
5538 /* if left is a literal & right is not then exchange them */
5539 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5540 AOP_NEEDSACC (left))
5542 operand *tmp = right;
5547 /* if result = right then exchange them */
5548 if (sameRegs (AOP (result), AOP (right)))
5550 operand *tmp = right;
5555 /* if right is bit then exchange them */
5556 if (AOP_TYPE (right) == AOP_CRY &&
5557 AOP_TYPE (left) != AOP_CRY)
5559 operand *tmp = right;
5563 if (AOP_TYPE (right) == AOP_LIT)
5564 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5566 size = AOP_SIZE (result);
5570 if (AOP_TYPE (left) == AOP_CRY)
5572 if (AOP_TYPE (right) == AOP_LIT)
5574 // c = bit & literal;
5577 // lit != 0 => result = 1
5578 if (AOP_TYPE (result) == AOP_CRY)
5581 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5583 continueIfTrue (ifx);
5586 emitcode ("setb", "c");
5590 // lit == 0 => result = left
5591 if (size && sameRegs (AOP (result), AOP (left)))
5593 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5598 if (AOP_TYPE (right) == AOP_CRY)
5601 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5602 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5607 symbol *tlbl = newiTempLabel (NULL);
5608 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5609 emitcode ("setb", "c");
5610 emitcode ("jb", "%s,%05d$",
5611 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5613 emitcode ("jnz", "%05d$", tlbl->key + 100);
5614 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5616 jmpTrueOrFalse (ifx, tlbl);
5622 emitcode ("", "%05d$:", tlbl->key + 100);
5631 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5632 genIfxJump (ifx, "c");
5636 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5637 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5638 if ((AOP_TYPE (right) == AOP_LIT) &&
5639 (AOP_TYPE (result) == AOP_CRY) &&
5640 (AOP_TYPE (left) != AOP_CRY))
5646 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5648 continueIfTrue (ifx);
5653 // lit = 0, result = boolean(left)
5655 emitcode ("setb", "c");
5659 symbol *tlbl = newiTempLabel (NULL);
5660 emitcode ("jnz", "%05d$", tlbl->key + 100);
5662 emitcode ("", "%05d$:", tlbl->key + 100);
5666 genIfxJump (ifx, "a");
5674 /* if left is same as result */
5675 if (sameRegs (AOP (result), AOP (left)))
5677 for (; size--; offset++)
5679 if (AOP_TYPE (right) == AOP_LIT)
5681 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5687 if (IS_AOP_PREG (left))
5689 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5690 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5691 aopPut (AOP (result), "a", offset);
5695 emitcode ("orl", "%s,%s",
5696 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5697 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5703 if (AOP_TYPE (left) == AOP_ACC)
5705 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5709 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5710 if (IS_AOP_PREG (left))
5712 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5713 aopPut (AOP (result), "a", offset);
5717 emitcode ("orl", "%s,a",
5718 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5726 // left & result in different registers
5727 if (AOP_TYPE (result) == AOP_CRY)
5730 // if(size), result in bit
5731 // if(!size && ifx), conditional oper: if(left | right)
5732 symbol *tlbl = newiTempLabel (NULL);
5733 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5735 emitcode ("setb", "c");
5738 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5739 emitcode ("orl", "a,%s",
5740 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5742 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5743 emitcode ("orl", "a,%s",
5744 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5746 emitcode ("jnz", "%05d$", tlbl->key + 100);
5752 emitcode ("", "%05d$:", tlbl->key + 100);
5756 jmpTrueOrFalse (ifx, tlbl);
5760 _startLazyDPSEvaluation();
5761 for (; (size--); offset++)
5764 // result = left & right
5765 if (AOP_TYPE (right) == AOP_LIT)
5767 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5769 aopPut (AOP (result),
5770 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5774 D (emitcode (";", "better literal OR."););
5775 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5776 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5777 FALSE, FALSE, FALSE));
5782 // faster than result <- left, anl result,right
5783 // and better if result is SFR
5784 if (AOP_TYPE (left) == AOP_ACC)
5786 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5787 FALSE, FALSE, FALSE));
5791 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5792 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5794 emitcode("mov", "b,a");
5798 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5799 emitcode ("orl", "a,%s", rOp);
5802 aopPut (AOP (result), "a", offset);
5804 _endLazyDPSEvaluation();
5809 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5810 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5811 freeAsmop (result, NULL, ic, TRUE);
5814 /*-----------------------------------------------------------------*/
5815 /* genXor - code for xclusive or */
5816 /*-----------------------------------------------------------------*/
5818 genXor (iCode * ic, iCode * ifx)
5820 operand *left, *right, *result;
5821 int size, offset = 0;
5822 unsigned long lit = 0L;
5825 D (emitcode (";", "genXor "););
5827 AOP_OP_3_NOFATAL (ic, pushResult);
5828 AOP_SET_LOCALS (ic);
5832 genFarFarLogicOp(ic, "xrl");
5837 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5839 AOP_TYPE (left), AOP_TYPE (right));
5840 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5842 AOP_SIZE (left), AOP_SIZE (right));
5845 /* if left is a literal & right is not ||
5846 if left needs acc & right does not */
5847 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5848 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5850 operand *tmp = right;
5855 /* if result = right then exchange them */
5856 if (sameRegs (AOP (result), AOP (right)))
5858 operand *tmp = right;
5863 /* if right is bit then exchange them */
5864 if (AOP_TYPE (right) == AOP_CRY &&
5865 AOP_TYPE (left) != AOP_CRY)
5867 operand *tmp = right;
5871 if (AOP_TYPE (right) == AOP_LIT)
5872 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5874 size = AOP_SIZE (result);
5878 if (AOP_TYPE (left) == AOP_CRY)
5880 if (AOP_TYPE (right) == AOP_LIT)
5882 // c = bit & literal;
5885 // lit>>1 != 0 => result = 1
5886 if (AOP_TYPE (result) == AOP_CRY)
5889 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5891 continueIfTrue (ifx);
5894 emitcode ("setb", "c");
5901 // lit == 0, result = left
5902 if (size && sameRegs (AOP (result), AOP (left)))
5904 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5908 // lit == 1, result = not(left)
5909 if (size && sameRegs (AOP (result), AOP (left)))
5911 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5916 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5917 emitcode ("cpl", "c");
5926 symbol *tlbl = newiTempLabel (NULL);
5927 if (AOP_TYPE (right) == AOP_CRY)
5930 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5934 int sizer = AOP_SIZE (right);
5936 // if val>>1 != 0, result = 1
5937 emitcode ("setb", "c");
5940 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5942 // test the msb of the lsb
5943 emitcode ("anl", "a,#0xfe");
5944 emitcode ("jnz", "%05d$", tlbl->key + 100);
5948 emitcode ("rrc", "a");
5950 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5951 emitcode ("cpl", "c");
5952 emitcode ("", "%05d$:", (tlbl->key + 100));
5959 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5960 genIfxJump (ifx, "c");
5964 if (sameRegs (AOP (result), AOP (left)))
5966 /* if left is same as result */
5967 for (; size--; offset++)
5969 if (AOP_TYPE (right) == AOP_LIT)
5971 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5973 else if (IS_AOP_PREG (left))
5975 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5976 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5977 aopPut (AOP (result), "a", offset);
5980 emitcode ("xrl", "%s,%s",
5981 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5982 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5986 if (AOP_TYPE (left) == AOP_ACC)
5987 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5990 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5991 if (IS_AOP_PREG (left))
5993 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5994 aopPut (AOP (result), "a", offset);
5997 emitcode ("xrl", "%s,a",
5998 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6005 // left & result in different registers
6006 if (AOP_TYPE (result) == AOP_CRY)
6009 // if(size), result in bit
6010 // if(!size && ifx), conditional oper: if(left ^ right)
6011 symbol *tlbl = newiTempLabel (NULL);
6012 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6014 emitcode ("setb", "c");
6017 if ((AOP_TYPE (right) == AOP_LIT) &&
6018 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6020 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6024 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6025 emitcode ("xrl", "a,%s",
6026 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6028 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6029 emitcode ("xrl", "a,%s",
6030 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6033 emitcode ("jnz", "%05d$", tlbl->key + 100);
6039 emitcode ("", "%05d$:", tlbl->key + 100);
6043 jmpTrueOrFalse (ifx, tlbl);
6046 for (; (size--); offset++)
6049 // result = left & right
6050 if (AOP_TYPE (right) == AOP_LIT)
6052 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6054 aopPut (AOP (result),
6055 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6059 D (emitcode (";", "better literal XOR.");
6061 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6062 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6063 FALSE, FALSE, FALSE));
6067 // faster than result <- left, anl result,right
6068 // and better if result is SFR
6069 if (AOP_TYPE (left) == AOP_ACC)
6071 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6072 FALSE, FALSE, FALSE));
6076 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6077 emitcode ("xrl", "a,%s",
6078 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6081 aopPut (AOP (result), "a", offset);
6086 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6087 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6088 freeAsmop (result, NULL, ic, TRUE);
6091 /*-----------------------------------------------------------------*/
6092 /* genInline - write the inline code out */
6093 /*-----------------------------------------------------------------*/
6095 genInline (iCode * ic)
6097 char *buffer, *bp, *bp1;
6099 D (emitcode (";", "genInline ");
6102 _G.inLine += (!options.asmpeep);
6104 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6105 strcpy (buffer, IC_INLINE (ic));
6107 /* emit each line as a code */
6132 /* emitcode("",buffer); */
6133 _G.inLine -= (!options.asmpeep);
6136 /*-----------------------------------------------------------------*/
6137 /* genRRC - rotate right with carry */
6138 /*-----------------------------------------------------------------*/
6142 operand *left, *result;
6143 int size, offset = 0;
6146 D (emitcode (";", "genRRC ");
6149 /* rotate right with carry */
6150 left = IC_LEFT (ic);
6151 result = IC_RESULT (ic);
6152 aopOp (left, ic, FALSE, FALSE);
6153 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6155 /* move it to the result */
6156 size = AOP_SIZE (result);
6160 _startLazyDPSEvaluation ();
6163 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6165 emitcode ("rrc", "a");
6166 if (AOP_SIZE (result) > 1)
6167 aopPut (AOP (result), "a", offset--);
6169 _endLazyDPSEvaluation ();
6171 /* now we need to put the carry into the
6172 highest order byte of the result */
6173 if (AOP_SIZE (result) > 1)
6175 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6178 emitcode ("mov", "acc.7,c");
6179 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6180 freeAsmop (left, NULL, ic, TRUE);
6181 freeAsmop (result, NULL, ic, TRUE);
6184 /*-----------------------------------------------------------------*/
6185 /* genRLC - generate code for rotate left with carry */
6186 /*-----------------------------------------------------------------*/
6190 operand *left, *result;
6191 int size, offset = 0;
6194 D (emitcode (";", "genRLC ");
6197 /* rotate right with carry */
6198 left = IC_LEFT (ic);
6199 result = IC_RESULT (ic);
6200 aopOp (left, ic, FALSE, FALSE);
6201 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6203 /* move it to the result */
6204 size = AOP_SIZE (result);
6208 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6210 emitcode ("add", "a,acc");
6211 if (AOP_SIZE (result) > 1)
6213 aopPut (AOP (result), "a", offset++);
6216 _startLazyDPSEvaluation ();
6219 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6221 emitcode ("rlc", "a");
6222 if (AOP_SIZE (result) > 1)
6223 aopPut (AOP (result), "a", offset++);
6225 _endLazyDPSEvaluation ();
6227 /* now we need to put the carry into the
6228 highest order byte of the result */
6229 if (AOP_SIZE (result) > 1)
6231 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6234 emitcode ("mov", "acc.0,c");
6235 aopPut (AOP (result), "a", 0);
6236 freeAsmop (left, NULL, ic, TRUE);
6237 freeAsmop (result, NULL, ic, TRUE);
6240 /*-----------------------------------------------------------------*/
6241 /* genGetHbit - generates code get highest order bit */
6242 /*-----------------------------------------------------------------*/
6244 genGetHbit (iCode * ic)
6246 operand *left, *result;
6247 left = IC_LEFT (ic);
6248 result = IC_RESULT (ic);
6249 aopOp (left, ic, FALSE, FALSE);
6250 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6252 D (emitcode (";", "genGetHbit ");
6255 /* get the highest order byte into a */
6256 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6257 if (AOP_TYPE (result) == AOP_CRY)
6259 emitcode ("rlc", "a");
6264 emitcode ("rl", "a");
6265 emitcode ("anl", "a,#0x01");
6270 freeAsmop (left, NULL, ic, TRUE);
6271 freeAsmop (result, NULL, ic, TRUE);
6274 /*-----------------------------------------------------------------*/
6275 /* AccRol - rotate left accumulator by known count */
6276 /*-----------------------------------------------------------------*/
6278 AccRol (int shCount)
6280 shCount &= 0x0007; // shCount : 0..7
6287 emitcode ("rl", "a");
6290 emitcode ("rl", "a");
6291 emitcode ("rl", "a");
6294 emitcode ("swap", "a");
6295 emitcode ("rr", "a");
6298 emitcode ("swap", "a");
6301 emitcode ("swap", "a");
6302 emitcode ("rl", "a");
6305 emitcode ("rr", "a");
6306 emitcode ("rr", "a");
6309 emitcode ("rr", "a");
6314 /*-----------------------------------------------------------------*/
6315 /* AccLsh - left shift accumulator by known count */
6316 /*-----------------------------------------------------------------*/
6318 AccLsh (int shCount)
6323 emitcode ("add", "a,acc");
6324 else if (shCount == 2)
6326 emitcode ("add", "a,acc");
6327 emitcode ("add", "a,acc");
6331 /* rotate left accumulator */
6333 /* and kill the lower order bits */
6334 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6339 /*-----------------------------------------------------------------*/
6340 /* AccRsh - right shift accumulator by known count */
6341 /*-----------------------------------------------------------------*/
6343 AccRsh (int shCount)
6350 emitcode ("rrc", "a");
6354 /* rotate right accumulator */
6355 AccRol (8 - shCount);
6356 /* and kill the higher order bits */
6357 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6362 #ifdef BETTER_LITERAL_SHIFT
6363 /*-----------------------------------------------------------------*/
6364 /* AccSRsh - signed right shift accumulator by known count */
6365 /*-----------------------------------------------------------------*/
6367 AccSRsh (int shCount)
6374 emitcode ("mov", "c,acc.7");
6375 emitcode ("rrc", "a");
6377 else if (shCount == 2)
6379 emitcode ("mov", "c,acc.7");
6380 emitcode ("rrc", "a");
6381 emitcode ("mov", "c,acc.7");
6382 emitcode ("rrc", "a");
6386 tlbl = newiTempLabel (NULL);
6387 /* rotate right accumulator */
6388 AccRol (8 - shCount);
6389 /* and kill the higher order bits */
6390 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6391 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6392 emitcode ("orl", "a,#0x%02x",
6393 (unsigned char) ~SRMask[shCount]);
6394 emitcode ("", "%05d$:", tlbl->key + 100);
6400 #ifdef BETTER_LITERAL_SHIFT
6401 /*-----------------------------------------------------------------*/
6402 /* shiftR1Left2Result - shift right one byte from left to result */
6403 /*-----------------------------------------------------------------*/
6405 shiftR1Left2Result (operand * left, int offl,
6406 operand * result, int offr,
6407 int shCount, int sign)
6409 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6410 /* shift right accumulator */
6415 aopPut (AOP (result), "a", offr);
6419 #ifdef BETTER_LITERAL_SHIFT
6420 /*-----------------------------------------------------------------*/
6421 /* shiftL1Left2Result - shift left one byte from left to result */
6422 /*-----------------------------------------------------------------*/
6424 shiftL1Left2Result (operand * left, int offl,
6425 operand * result, int offr, int shCount)
6427 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6428 /* shift left accumulator */
6430 aopPut (AOP (result), "a", offr);
6434 #ifdef BETTER_LITERAL_SHIFT
6435 /*-----------------------------------------------------------------*/
6436 /* movLeft2Result - move byte from left to result */
6437 /*-----------------------------------------------------------------*/
6439 movLeft2Result (operand * left, int offl,
6440 operand * result, int offr, int sign)
6443 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6445 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6447 if (*l == '@' && (IS_AOP_PREG (result)))
6449 emitcode ("mov", "a,%s", l);
6450 aopPut (AOP (result), "a", offr);
6456 aopPut (AOP (result), l, offr);
6460 /* MSB sign in acc.7 ! */
6461 if (getDataSize (left) == offl + 1)
6463 emitcode ("mov", "a,%s", l);
6464 aopPut (AOP (result), "a", offr);
6472 #ifdef BETTER_LITERAL_SHIFT
6473 /*-----------------------------------------------------------------*/
6474 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6475 /*-----------------------------------------------------------------*/
6479 emitcode ("rrc", "a");
6480 emitcode ("xch", "a,%s", x);
6481 emitcode ("rrc", "a");
6482 emitcode ("xch", "a,%s", x);
6486 #ifdef BETTER_LITERAL_SHIFT
6488 /*-----------------------------------------------------------------*/
6489 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6490 /*-----------------------------------------------------------------*/
6494 emitcode ("xch", "a,%s", x);
6495 emitcode ("rlc", "a");
6496 emitcode ("xch", "a,%s", x);
6497 emitcode ("rlc", "a");
6501 #ifdef BETTER_LITERAL_SHIFT
6502 /*-----------------------------------------------------------------*/
6503 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6504 /*-----------------------------------------------------------------*/
6508 emitcode ("xch", "a,%s", x);
6509 emitcode ("add", "a,acc");
6510 emitcode ("xch", "a,%s", x);
6511 emitcode ("rlc", "a");
6515 #ifdef BETTER_LITERAL_SHIFT
6516 /*-----------------------------------------------------------------*/
6517 /* AccAXLsh - left shift a:x by known count (0..7) */
6518 /*-----------------------------------------------------------------*/
6520 AccAXLsh (char *x, int shCount)
6535 case 5: // AAAAABBB:CCCCCDDD
6537 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6539 emitcode ("anl", "a,#0x%02x",
6540 SLMask[shCount]); // BBB00000:CCCCCDDD
6542 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6544 AccRol (shCount); // DDDCCCCC:BBB00000
6546 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6548 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6550 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6552 emitcode ("anl", "a,#0x%02x",
6553 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6555 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6557 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6560 case 6: // AAAAAABB:CCCCCCDD
6561 emitcode ("anl", "a,#0x%02x",
6562 SRMask[shCount]); // 000000BB:CCCCCCDD
6563 emitcode ("mov", "c,acc.0"); // c = B
6564 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6566 AccAXRrl1 (x); // BCCCCCCD:D000000B
6567 AccAXRrl1 (x); // BBCCCCCC:DD000000
6569 emitcode("rrc","a");
6570 emitcode("xch","a,%s", x);
6571 emitcode("rrc","a");
6572 emitcode("mov","c,acc.0"); //<< get correct bit
6573 emitcode("xch","a,%s", x);
6575 emitcode("rrc","a");
6576 emitcode("xch","a,%s", x);
6577 emitcode("rrc","a");
6578 emitcode("xch","a,%s", x);
6581 case 7: // a:x <<= 7
6583 emitcode ("anl", "a,#0x%02x",
6584 SRMask[shCount]); // 0000000B:CCCCCCCD
6586 emitcode ("mov", "c,acc.0"); // c = B
6588 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6590 AccAXRrl1 (x); // BCCCCCCC:D0000000
6599 #ifdef BETTER_LITERAL_SHIFT
6601 /*-----------------------------------------------------------------*/
6602 /* AccAXRsh - right shift a:x known count (0..7) */
6603 /*-----------------------------------------------------------------*/
6605 AccAXRsh (char *x, int shCount)
6613 AccAXRrl1 (x); // 0->a:x
6618 AccAXRrl1 (x); // 0->a:x
6621 AccAXRrl1 (x); // 0->a:x
6626 case 5: // AAAAABBB:CCCCCDDD = a:x
6628 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6630 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6632 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6634 emitcode ("anl", "a,#0x%02x",
6635 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6637 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6639 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6641 emitcode ("anl", "a,#0x%02x",
6642 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6644 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6646 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6648 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6651 case 6: // AABBBBBB:CCDDDDDD
6653 emitcode ("mov", "c,acc.7");
6654 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6656 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6658 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6660 emitcode ("anl", "a,#0x%02x",
6661 SRMask[shCount]); // 000000AA:BBBBBBCC
6664 case 7: // ABBBBBBB:CDDDDDDD
6666 emitcode ("mov", "c,acc.7"); // c = A
6668 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6670 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6672 emitcode ("anl", "a,#0x%02x",
6673 SRMask[shCount]); // 0000000A:BBBBBBBC
6682 #ifdef BETTER_LITERAL_SHIFT
6683 /*-----------------------------------------------------------------*/
6684 /* AccAXRshS - right shift signed a:x known count (0..7) */
6685 /*-----------------------------------------------------------------*/
6687 AccAXRshS (char *x, int shCount)
6695 emitcode ("mov", "c,acc.7");
6696 AccAXRrl1 (x); // s->a:x
6700 emitcode ("mov", "c,acc.7");
6701 AccAXRrl1 (x); // s->a:x
6703 emitcode ("mov", "c,acc.7");
6704 AccAXRrl1 (x); // s->a:x
6709 case 5: // AAAAABBB:CCCCCDDD = a:x
6711 tlbl = newiTempLabel (NULL);
6712 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6714 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6716 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6718 emitcode ("anl", "a,#0x%02x",
6719 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6721 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6723 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6725 emitcode ("anl", "a,#0x%02x",
6726 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6728 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6730 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6732 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6734 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6735 emitcode ("orl", "a,#0x%02x",
6736 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6738 emitcode ("", "%05d$:", tlbl->key + 100);
6739 break; // SSSSAAAA:BBBCCCCC
6741 case 6: // AABBBBBB:CCDDDDDD
6743 tlbl = newiTempLabel (NULL);
6744 emitcode ("mov", "c,acc.7");
6745 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6747 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6749 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6751 emitcode ("anl", "a,#0x%02x",
6752 SRMask[shCount]); // 000000AA:BBBBBBCC
6754 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6755 emitcode ("orl", "a,#0x%02x",
6756 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6758 emitcode ("", "%05d$:", tlbl->key + 100);
6760 case 7: // ABBBBBBB:CDDDDDDD
6762 tlbl = newiTempLabel (NULL);
6763 emitcode ("mov", "c,acc.7"); // c = A
6765 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6767 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6769 emitcode ("anl", "a,#0x%02x",
6770 SRMask[shCount]); // 0000000A:BBBBBBBC
6772 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6773 emitcode ("orl", "a,#0x%02x",
6774 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6776 emitcode ("", "%05d$:", tlbl->key + 100);
6784 #ifdef BETTER_LITERAL_SHIFT
6786 _loadLeftIntoAx(char **lsb,
6792 // Get the initial value from left into a pair of registers.
6793 // MSB must be in A, LSB can be any register.
6795 // If the result is held in registers, it is an optimization
6796 // if the LSB can be held in the register which will hold the,
6797 // result LSB since this saves us from having to copy it into
6798 // the result following AccAXLsh.
6800 // If the result is addressed indirectly, this is not a gain.
6801 if (AOP_NEEDSACC(result))
6805 _startLazyDPSEvaluation();
6806 if (AOP_TYPE(left) == AOP_DPTR2)
6809 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6810 // get LSB in DP2_RESULT_REG.
6811 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6812 assert(!strcmp(leftByte, DP2_RESULT_REG));
6816 // get LSB into DP2_RESULT_REG
6817 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6818 if (strcmp(leftByte, DP2_RESULT_REG))
6821 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6824 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6825 assert(strcmp(leftByte, DP2_RESULT_REG));
6828 _endLazyDPSEvaluation();
6829 *lsb = DP2_RESULT_REG;
6833 if (sameRegs (AOP (result), AOP (left)) &&
6834 ((offl + MSB16) == offr))
6836 /* don't crash result[offr] */
6837 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6838 emitcode ("xch", "a,%s",
6839 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6843 movLeft2Result (left, offl, result, offr, 0);
6844 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6846 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6847 assert(strcmp(*lsb,"a"));
6852 _storeAxResults(char *lsb,
6856 _startLazyDPSEvaluation();
6857 if (AOP_NEEDSACC(result))
6859 /* We have to explicitly update the result LSB.
6861 emitcode("xch","a,%s", lsb);
6862 aopPut(AOP(result), "a", offr);
6863 emitcode("mov","a,%s", lsb);
6865 if (getDataSize (result) > 1)
6867 aopPut (AOP (result), "a", offr + MSB16);
6869 _endLazyDPSEvaluation();
6872 /*-----------------------------------------------------------------*/
6873 /* shiftL2Left2Result - shift left two bytes from left to result */
6874 /*-----------------------------------------------------------------*/
6876 shiftL2Left2Result (operand * left, int offl,
6877 operand * result, int offr, int shCount)
6881 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6883 AccAXLsh (lsb, shCount);
6885 _storeAxResults(lsb, result, offr);
6889 #ifdef BETTER_LITERAL_SHIFT
6890 /*-----------------------------------------------------------------*/
6891 /* shiftR2Left2Result - shift right two bytes from left to result */
6892 /*-----------------------------------------------------------------*/
6894 shiftR2Left2Result (operand * left, int offl,
6895 operand * result, int offr,
6896 int shCount, int sign)
6900 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6902 /* a:x >> shCount (x = lsb(result)) */
6905 AccAXRshS(lsb, shCount);
6909 AccAXRsh(lsb, shCount);
6912 _storeAxResults(lsb, result, offr);
6918 /*-----------------------------------------------------------------*/
6919 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6920 /*-----------------------------------------------------------------*/
6922 shiftLLeftOrResult (operand * left, int offl,
6923 operand * result, int offr, int shCount)
6925 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6926 /* shift left accumulator */
6928 /* or with result */
6929 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6930 /* back to result */
6931 aopPut (AOP (result), "a", offr);
6937 /*-----------------------------------------------------------------*/
6938 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6939 /*-----------------------------------------------------------------*/
6941 shiftRLeftOrResult (operand * left, int offl,
6942 operand * result, int offr, int shCount)
6944 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6945 /* shift right accumulator */
6947 /* or with result */
6948 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6949 /* back to result */
6950 aopPut (AOP (result), "a", offr);
6954 #ifdef BETTER_LITERAL_SHIFT
6955 /*-----------------------------------------------------------------*/
6956 /* genlshOne - left shift a one byte quantity by known count */
6957 /*-----------------------------------------------------------------*/
6959 genlshOne (operand * result, operand * left, int shCount)
6961 D (emitcode (";", "genlshOne "););
6962 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6966 #ifdef BETTER_LITERAL_SHIFT
6967 /*-----------------------------------------------------------------*/
6968 /* genlshTwo - left shift two bytes by known amount != 0 */
6969 /*-----------------------------------------------------------------*/
6971 genlshTwo (operand * result, operand * left, int shCount)
6975 D (emitcode (";", "genlshTwo "););
6977 size = getDataSize (result);
6979 /* if shCount >= 8 */
6984 _startLazyDPSEvaluation();
6990 _endLazyDPSEvaluation();
6991 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6992 aopPut (AOP (result), zero, LSB);
6996 movLeft2Result (left, LSB, result, MSB16, 0);
6997 aopPut (AOP (result), zero, LSB);
6998 _endLazyDPSEvaluation();
7003 aopPut (AOP (result), zero, LSB);
7004 _endLazyDPSEvaluation();
7008 /* 1 <= shCount <= 7 */
7013 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7017 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7025 /*-----------------------------------------------------------------*/
7026 /* shiftLLong - shift left one long from left to result */
7027 /* offl = LSB or MSB16 */
7028 /*-----------------------------------------------------------------*/
7030 shiftLLong (operand * left, operand * result, int offr)
7033 int size = AOP_SIZE (result);
7035 if (size >= LSB + offr)
7037 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7039 emitcode ("add", "a,acc");
7040 if (sameRegs (AOP (left), AOP (result)) &&
7041 size >= MSB16 + offr && offr != LSB)
7042 emitcode ("xch", "a,%s",
7043 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7045 aopPut (AOP (result), "a", LSB + offr);
7048 if (size >= MSB16 + offr)
7050 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7052 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7055 emitcode ("rlc", "a");
7056 if (sameRegs (AOP (left), AOP (result)) &&
7057 size >= MSB24 + offr && offr != LSB)
7058 emitcode ("xch", "a,%s",
7059 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7061 aopPut (AOP (result), "a", MSB16 + offr);
7064 if (size >= MSB24 + offr)
7066 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7068 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7071 emitcode ("rlc", "a");
7072 if (sameRegs (AOP (left), AOP (result)) &&
7073 size >= MSB32 + offr && offr != LSB)
7074 emitcode ("xch", "a,%s",
7075 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7077 aopPut (AOP (result), "a", MSB24 + offr);
7080 if (size > MSB32 + offr)
7082 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7084 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7087 emitcode ("rlc", "a");
7088 aopPut (AOP (result), "a", MSB32 + offr);
7091 aopPut (AOP (result), zero, LSB);
7097 /*-----------------------------------------------------------------*/
7098 /* genlshFour - shift four byte by a known amount != 0 */
7099 /*-----------------------------------------------------------------*/
7101 genlshFour (operand * result, operand * left, int shCount)
7105 D (emitcode (";", "genlshFour ");
7108 size = AOP_SIZE (result);
7110 /* if shifting more that 3 bytes */
7115 /* lowest order of left goes to the highest
7116 order of the destination */
7117 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7119 movLeft2Result (left, LSB, result, MSB32, 0);
7120 aopPut (AOP (result), zero, LSB);
7121 aopPut (AOP (result), zero, MSB16);
7122 aopPut (AOP (result), zero, MSB24);
7126 /* more than two bytes */
7127 else if (shCount >= 16)
7129 /* lower order two bytes goes to higher order two bytes */
7131 /* if some more remaining */
7133 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7136 movLeft2Result (left, MSB16, result, MSB32, 0);
7137 movLeft2Result (left, LSB, result, MSB24, 0);
7139 aopPut (AOP (result), zero, MSB16);
7140 aopPut (AOP (result), zero, LSB);
7144 /* if more than 1 byte */
7145 else if (shCount >= 8)
7147 /* lower order three bytes goes to higher order three bytes */
7152 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7154 movLeft2Result (left, LSB, result, MSB16, 0);
7160 movLeft2Result (left, MSB24, result, MSB32, 0);
7161 movLeft2Result (left, MSB16, result, MSB24, 0);
7162 movLeft2Result (left, LSB, result, MSB16, 0);
7163 aopPut (AOP (result), zero, LSB);
7165 else if (shCount == 1)
7166 shiftLLong (left, result, MSB16);
7169 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7170 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7171 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7172 aopPut (AOP (result), zero, LSB);
7177 /* 1 <= shCount <= 7 */
7178 else if (shCount <= 2)
7180 shiftLLong (left, result, LSB);
7182 shiftLLong (result, result, LSB);
7184 /* 3 <= shCount <= 7, optimize */
7187 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7188 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7189 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7194 #ifdef BETTER_LITERAL_SHIFT
7195 /*-----------------------------------------------------------------*/
7196 /* genLeftShiftLiteral - left shifting by known count */
7197 /*-----------------------------------------------------------------*/
7199 genLeftShiftLiteral (operand * left,
7204 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7207 size = getSize (operandType (result));
7209 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7211 /* We only handle certain easy cases so far. */
7213 && (shCount < (size * 8))
7217 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7221 freeAsmop (right, NULL, ic, TRUE);
7223 aopOp(left, ic, FALSE, FALSE);
7224 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7227 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7229 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7230 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7232 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7235 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7237 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7238 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7240 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7246 emitcode ("; shift left ", "result %d, left %d", size,
7250 /* I suppose that the left size >= result size */
7253 _startLazyDPSEvaluation();
7256 movLeft2Result (left, size, result, size, 0);
7258 _endLazyDPSEvaluation();
7260 else if (shCount >= (size * 8))
7262 _startLazyDPSEvaluation();
7265 aopPut (AOP (result), zero, size);
7267 _endLazyDPSEvaluation();
7274 genlshOne (result, left, shCount);
7278 genlshTwo (result, left, shCount);
7282 genlshFour (result, left, shCount);
7286 fprintf(stderr, "*** ack! mystery literal shift!\n");
7290 freeAsmop (left, NULL, ic, TRUE);
7291 freeAsmop (result, NULL, ic, TRUE);
7296 /*-----------------------------------------------------------------*/
7297 /* genLeftShift - generates code for left shifting */
7298 /*-----------------------------------------------------------------*/
7300 genLeftShift (iCode * ic)
7302 operand *left, *right, *result;
7305 symbol *tlbl, *tlbl1;
7307 D (emitcode (";", "genLeftShift "););
7309 right = IC_RIGHT (ic);
7310 left = IC_LEFT (ic);
7311 result = IC_RESULT (ic);
7313 aopOp (right, ic, FALSE, FALSE);
7316 #ifdef BETTER_LITERAL_SHIFT
7317 /* if the shift count is known then do it
7318 as efficiently as possible */
7319 if (AOP_TYPE (right) == AOP_LIT)
7321 if (genLeftShiftLiteral (left, right, result, ic))
7328 /* shift count is unknown then we have to form
7329 a loop get the loop count in B : Note: we take
7330 only the lower order byte since shifting
7331 more that 32 bits make no sense anyway, ( the
7332 largest size of an object can be only 32 bits ) */
7334 if (AOP_TYPE (right) == AOP_LIT)
7336 /* Really should be handled by genLeftShiftLiteral,
7337 * but since I'm too lazy to fix that today, at least we can make
7338 * some small improvement.
7340 emitcode("mov", "b,#0x%02x",
7341 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7345 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7346 emitcode ("inc", "b");
7348 freeAsmop (right, NULL, ic, TRUE);
7349 aopOp (left, ic, FALSE, FALSE);
7350 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7352 /* now move the left to the result if they are not the
7354 if (!sameRegs (AOP (left), AOP (result)) &&
7355 AOP_SIZE (result) > 1)
7358 size = AOP_SIZE (result);
7360 _startLazyDPSEvaluation ();
7363 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7364 if (*l == '@' && (IS_AOP_PREG (result)))
7367 emitcode ("mov", "a,%s", l);
7368 aopPut (AOP (result), "a", offset);
7371 aopPut (AOP (result), l, offset);
7374 _endLazyDPSEvaluation ();
7377 tlbl = newiTempLabel (NULL);
7378 size = AOP_SIZE (result);
7380 tlbl1 = newiTempLabel (NULL);
7382 /* if it is only one byte then */
7385 symbol *tlbl1 = newiTempLabel (NULL);
7387 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7389 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7390 emitcode ("", "%05d$:", tlbl->key + 100);
7391 emitcode ("add", "a,acc");
7392 emitcode ("", "%05d$:", tlbl1->key + 100);
7393 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7394 aopPut (AOP (result), "a", 0);
7398 reAdjustPreg (AOP (result));
7400 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7401 emitcode ("", "%05d$:", tlbl->key + 100);
7402 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7404 emitcode ("add", "a,acc");
7405 aopPut (AOP (result), "a", offset++);
7406 _startLazyDPSEvaluation ();
7409 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7411 emitcode ("rlc", "a");
7412 aopPut (AOP (result), "a", offset++);
7414 _endLazyDPSEvaluation ();
7415 reAdjustPreg (AOP (result));
7417 emitcode ("", "%05d$:", tlbl1->key + 100);
7418 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7420 freeAsmop (left, NULL, ic, TRUE);
7421 freeAsmop (result, NULL, ic, TRUE);
7424 #ifdef BETTER_LITERAL_SHIFT
7425 /*-----------------------------------------------------------------*/
7426 /* genrshOne - right shift a one byte quantity by known count */
7427 /*-----------------------------------------------------------------*/
7429 genrshOne (operand * result, operand * left,
7430 int shCount, int sign)
7432 D (emitcode (";", "genrshOne"););
7433 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7437 #ifdef BETTER_LITERAL_SHIFT
7438 /*-----------------------------------------------------------------*/
7439 /* genrshTwo - right shift two bytes by known amount != 0 */
7440 /*-----------------------------------------------------------------*/
7442 genrshTwo (operand * result, operand * left,
7443 int shCount, int sign)
7445 D (emitcode (";", "genrshTwo"););
7447 /* if shCount >= 8 */
7451 _startLazyDPSEvaluation();
7454 shiftR1Left2Result (left, MSB16, result, LSB,
7459 movLeft2Result (left, MSB16, result, LSB, sign);
7461 addSign (result, MSB16, sign);
7462 _endLazyDPSEvaluation();
7465 /* 1 <= shCount <= 7 */
7468 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7475 /*-----------------------------------------------------------------*/
7476 /* shiftRLong - shift right one long from left to result */
7477 /* offl = LSB or MSB16 */
7478 /*-----------------------------------------------------------------*/
7480 shiftRLong (operand * left, int offl,
7481 operand * result, int sign)
7483 int isSameRegs=sameRegs(AOP(left),AOP(result));
7485 if (isSameRegs && offl>1) {
7486 // we are in big trouble, but this shouldn't happen
7487 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7490 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7495 emitcode ("rlc", "a");
7496 emitcode ("subb", "a,acc");
7497 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7499 aopPut (AOP(result), zero, MSB32);
7504 emitcode ("clr", "c");
7506 emitcode ("mov", "c,acc.7");
7509 emitcode ("rrc", "a");
7511 if (isSameRegs && offl==MSB16) {
7512 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7514 aopPut (AOP (result), "a", MSB32);
7515 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7518 emitcode ("rrc", "a");
7519 if (isSameRegs && offl==1) {
7520 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7522 aopPut (AOP (result), "a", MSB24);
7523 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7525 emitcode ("rrc", "a");
7526 aopPut (AOP (result), "a", MSB16 - offl);
7530 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7531 emitcode ("rrc", "a");
7532 aopPut (AOP (result), "a", LSB);
7539 /*-----------------------------------------------------------------*/
7540 /* genrshFour - shift four byte by a known amount != 0 */
7541 /*-----------------------------------------------------------------*/
7543 genrshFour (operand * result, operand * left,
7544 int shCount, int sign)
7546 D (emitcode (";", "genrshFour");
7549 /* if shifting more that 3 bytes */
7554 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7556 movLeft2Result (left, MSB32, result, LSB, sign);
7557 addSign (result, MSB16, sign);
7559 else if (shCount >= 16)
7563 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7566 movLeft2Result (left, MSB24, result, LSB, 0);
7567 movLeft2Result (left, MSB32, result, MSB16, sign);
7569 addSign (result, MSB24, sign);
7571 else if (shCount >= 8)
7575 shiftRLong (left, MSB16, result, sign);
7576 else if (shCount == 0)
7578 movLeft2Result (left, MSB16, result, LSB, 0);
7579 movLeft2Result (left, MSB24, result, MSB16, 0);
7580 movLeft2Result (left, MSB32, result, MSB24, sign);
7581 addSign (result, MSB32, sign);
7585 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7586 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7587 /* the last shift is signed */
7588 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7589 addSign (result, MSB32, sign);
7593 { /* 1 <= shCount <= 7 */
7596 shiftRLong (left, LSB, result, sign);
7598 shiftRLong (result, LSB, result, sign);
7602 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7603 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7604 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7610 #ifdef BETTER_LITERAL_SHIFT
7611 /*-----------------------------------------------------------------*/
7612 /* genRightShiftLiteral - right shifting by known count */
7613 /*-----------------------------------------------------------------*/
7615 genRightShiftLiteral (operand * left,
7621 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7624 size = getSize (operandType (result));
7626 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7628 /* We only handle certain easy cases so far. */
7630 && (shCount < (size * 8))
7634 D(emitcode (";", "genRightShiftLiteral wimping out"););
7638 freeAsmop (right, NULL, ic, TRUE);
7640 aopOp (left, ic, FALSE, FALSE);
7641 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7644 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7648 /* test the LEFT size !!! */
7650 /* I suppose that the left size >= result size */
7653 size = getDataSize (result);
7654 _startLazyDPSEvaluation();
7657 movLeft2Result (left, size, result, size, 0);
7659 _endLazyDPSEvaluation();
7661 else if (shCount >= (size * 8))
7665 /* get sign in acc.7 */
7666 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7668 addSign (result, LSB, sign);
7675 genrshOne (result, left, shCount, sign);
7679 genrshTwo (result, left, shCount, sign);
7683 genrshFour (result, left, shCount, sign);
7690 freeAsmop (left, NULL, ic, TRUE);
7691 freeAsmop (result, NULL, ic, TRUE);
7697 /*-----------------------------------------------------------------*/
7698 /* genSignedRightShift - right shift of signed number */
7699 /*-----------------------------------------------------------------*/
7701 genSignedRightShift (iCode * ic)
7703 operand *right, *left, *result;
7706 symbol *tlbl, *tlbl1;
7708 D (emitcode (";", "genSignedRightShift "););
7710 /* we do it the hard way put the shift count in b
7711 and loop thru preserving the sign */
7713 right = IC_RIGHT (ic);
7714 left = IC_LEFT (ic);
7715 result = IC_RESULT (ic);
7717 aopOp (right, ic, FALSE, FALSE);
7719 #ifdef BETTER_LITERAL_SHIFT
7720 if (AOP_TYPE (right) == AOP_LIT)
7722 if (genRightShiftLiteral (left, right, result, ic, 1))
7728 /* shift count is unknown then we have to form
7729 a loop get the loop count in B : Note: we take
7730 only the lower order byte since shifting
7731 more that 32 bits make no sense anyway, ( the
7732 largest size of an object can be only 32 bits ) */
7734 if (AOP_TYPE (right) == AOP_LIT)
7736 /* Really should be handled by genRightShiftLiteral,
7737 * but since I'm too lazy to fix that today, at least we can make
7738 * some small improvement.
7740 emitcode("mov", "b,#0x%02x",
7741 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7745 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7746 emitcode ("inc", "b");
7748 freeAsmop (right, NULL, ic, TRUE);
7749 aopOp (left, ic, FALSE, FALSE);
7750 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7752 /* now move the left to the result if they are not the
7754 if (!sameRegs (AOP (left), AOP (result)) &&
7755 AOP_SIZE (result) > 1)
7758 size = AOP_SIZE (result);
7760 _startLazyDPSEvaluation ();
7763 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7764 if (*l == '@' && IS_AOP_PREG (result))
7767 emitcode ("mov", "a,%s", l);
7768 aopPut (AOP (result), "a", offset);
7771 aopPut (AOP (result), l, offset);
7774 _endLazyDPSEvaluation ();
7777 /* mov the highest order bit to OVR */
7778 tlbl = newiTempLabel (NULL);
7779 tlbl1 = newiTempLabel (NULL);
7781 size = AOP_SIZE (result);
7783 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7784 emitcode ("rlc", "a");
7785 emitcode ("mov", "ov,c");
7786 /* if it is only one byte then */
7789 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7791 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7792 emitcode ("", "%05d$:", tlbl->key + 100);
7793 emitcode ("mov", "c,ov");
7794 emitcode ("rrc", "a");
7795 emitcode ("", "%05d$:", tlbl1->key + 100);
7796 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7797 aopPut (AOP (result), "a", 0);
7801 reAdjustPreg (AOP (result));
7802 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7803 emitcode ("", "%05d$:", tlbl->key + 100);
7804 emitcode ("mov", "c,ov");
7805 _startLazyDPSEvaluation ();
7808 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7810 emitcode ("rrc", "a");
7811 aopPut (AOP (result), "a", offset--);
7813 _endLazyDPSEvaluation ();
7814 reAdjustPreg (AOP (result));
7815 emitcode ("", "%05d$:", tlbl1->key + 100);
7816 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7819 freeAsmop (left, NULL, ic, TRUE);
7820 freeAsmop (result, NULL, ic, TRUE);
7823 /*-----------------------------------------------------------------*/
7824 /* genRightShift - generate code for right shifting */
7825 /*-----------------------------------------------------------------*/
7827 genRightShift (iCode * ic)
7829 operand *right, *left, *result;
7833 symbol *tlbl, *tlbl1;
7835 D (emitcode (";", "genRightShift "););
7837 /* if signed then we do it the hard way preserve the
7838 sign bit moving it inwards */
7839 retype = getSpec (operandType (IC_RESULT (ic)));
7841 if (!SPEC_USIGN (retype))
7843 genSignedRightShift (ic);
7847 /* signed & unsigned types are treated the same : i.e. the
7848 signed is NOT propagated inwards : quoting from the
7849 ANSI - standard : "for E1 >> E2, is equivalent to division
7850 by 2**E2 if unsigned or if it has a non-negative value,
7851 otherwise the result is implementation defined ", MY definition
7852 is that the sign does not get propagated */
7854 right = IC_RIGHT (ic);
7855 left = IC_LEFT (ic);
7856 result = IC_RESULT (ic);
7858 aopOp (right, ic, FALSE, FALSE);
7860 #ifdef BETTER_LITERAL_SHIFT
7861 /* if the shift count is known then do it
7862 as efficiently as possible */
7863 if (AOP_TYPE (right) == AOP_LIT)
7865 if (genRightShiftLiteral (left, right, result, ic, 0))
7872 /* shift count is unknown then we have to form
7873 a loop get the loop count in B : Note: we take
7874 only the lower order byte since shifting
7875 more that 32 bits make no sense anyway, ( the
7876 largest size of an object can be only 32 bits ) */
7878 if (AOP_TYPE (right) == AOP_LIT)
7880 /* Really should be handled by genRightShiftLiteral,
7881 * but since I'm too lazy to fix that today, at least we can make
7882 * some small improvement.
7884 emitcode("mov", "b,#0x%02x",
7885 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7889 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7890 emitcode ("inc", "b");
7892 freeAsmop (right, NULL, ic, TRUE);
7893 aopOp (left, ic, FALSE, FALSE);
7894 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7896 /* now move the left to the result if they are not the
7898 if (!sameRegs (AOP (left), AOP (result)) &&
7899 AOP_SIZE (result) > 1)
7902 size = AOP_SIZE (result);
7904 _startLazyDPSEvaluation ();
7907 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7908 if (*l == '@' && IS_AOP_PREG (result))
7911 emitcode ("mov", "a,%s", l);
7912 aopPut (AOP (result), "a", offset);
7915 aopPut (AOP (result), l, offset);
7918 _endLazyDPSEvaluation ();
7921 tlbl = newiTempLabel (NULL);
7922 tlbl1 = newiTempLabel (NULL);
7923 size = AOP_SIZE (result);
7926 /* if it is only one byte then */
7929 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7931 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7932 emitcode ("", "%05d$:", tlbl->key + 100);
7934 emitcode ("rrc", "a");
7935 emitcode ("", "%05d$:", tlbl1->key + 100);
7936 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7937 aopPut (AOP (result), "a", 0);
7941 reAdjustPreg (AOP (result));
7942 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7943 emitcode ("", "%05d$:", tlbl->key + 100);
7945 _startLazyDPSEvaluation ();
7948 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7950 emitcode ("rrc", "a");
7951 aopPut (AOP (result), "a", offset--);
7953 _endLazyDPSEvaluation ();
7954 reAdjustPreg (AOP (result));
7956 emitcode ("", "%05d$:", tlbl1->key + 100);
7957 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7960 freeAsmop (left, NULL, ic, TRUE);
7961 freeAsmop (result, NULL, ic, TRUE);
7964 /*-----------------------------------------------------------------*/
7965 /* genUnpackBits - generates code for unpacking bits */
7966 /*-----------------------------------------------------------------*/
7968 genUnpackBits (operand * result, char *rname, int ptype)
7975 D (emitcode (";", "genUnpackBits ");
7978 etype = getSpec (operandType (result));
7980 /* read the first byte */
7986 emitcode ("mov", "a,@%s", rname);
7990 emitcode ("movx", "a,@%s", rname);
7994 emitcode ("movx", "a,@dptr");
7998 emitcode ("clr", "a");
7999 emitcode ("movc", "a,@a+dptr");
8003 emitcode ("lcall", "__gptrget");
8007 /* if we have bitdisplacement then it fits */
8008 /* into this byte completely or if length is */
8009 /* less than a byte */
8010 if ((shCnt = SPEC_BSTR (etype)) ||
8011 (SPEC_BLEN (etype) <= 8))
8014 /* shift right acc */
8017 emitcode ("anl", "a,#0x%02x",
8018 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8019 aopPut (AOP (result), "a", offset);
8023 /* bit field did not fit in a byte */
8024 rlen = SPEC_BLEN (etype) - 8;
8025 aopPut (AOP (result), "a", offset++);
8034 emitcode ("inc", "%s", rname);
8035 emitcode ("mov", "a,@%s", rname);
8039 emitcode ("inc", "%s", rname);
8040 emitcode ("movx", "a,@%s", rname);
8044 emitcode ("inc", "dptr");
8045 emitcode ("movx", "a,@dptr");
8049 emitcode ("clr", "a");
8050 emitcode ("inc", "dptr");
8051 emitcode ("movc", "a,@a+dptr");
8055 emitcode ("inc", "dptr");
8056 emitcode ("lcall", "__gptrget");
8061 /* if we are done */
8065 aopPut (AOP (result), "a", offset++);
8071 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8072 aopPut (AOP (result), "a", offset);
8079 /*-----------------------------------------------------------------*/
8080 /* genDataPointerGet - generates code when ptr offset is known */
8081 /*-----------------------------------------------------------------*/
8083 genDataPointerGet (operand * left,
8089 int size, offset = 0;
8090 aopOp (result, ic, TRUE, FALSE);
8092 /* get the string representation of the name */
8093 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8094 size = AOP_SIZE (result);
8095 _startLazyDPSEvaluation ();
8099 sprintf (buffer, "(%s + %d)", l + 1, offset);
8101 sprintf (buffer, "%s", l + 1);
8102 aopPut (AOP (result), buffer, offset++);
8104 _endLazyDPSEvaluation ();
8106 freeAsmop (left, NULL, ic, TRUE);
8107 freeAsmop (result, NULL, ic, TRUE);
8110 /*-----------------------------------------------------------------*/
8111 /* genNearPointerGet - emitcode for near pointer fetch */
8112 /*-----------------------------------------------------------------*/
8114 genNearPointerGet (operand * left,
8121 sym_link *rtype, *retype, *letype;
8122 sym_link *ltype = operandType (left);
8125 rtype = operandType (result);
8126 retype = getSpec (rtype);
8127 letype = getSpec (ltype);
8129 aopOp (left, ic, FALSE, FALSE);
8131 /* if left is rematerialisable and
8132 result is not bit variable type and
8133 the left is pointer to data space i.e
8134 lower 128 bytes of space */
8135 if (AOP_TYPE (left) == AOP_IMMD &&
8136 !IS_BITVAR (retype) &&
8137 !IS_BITVAR (letype) &&
8138 DCL_TYPE (ltype) == POINTER)
8140 genDataPointerGet (left, result, ic);
8144 /* if the value is already in a pointer register
8145 then don't need anything more */
8146 if (!AOP_INPREG (AOP (left)))
8148 /* otherwise get a free pointer register */
8150 preg = getFreePtr (ic, &aop, FALSE);
8151 emitcode ("mov", "%s,%s",
8153 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8157 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8159 freeAsmop (left, NULL, ic, TRUE);
8160 aopOp (result, ic, FALSE, FALSE);
8162 /* if bitfield then unpack the bits */
8163 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8164 genUnpackBits (result, rname, POINTER);
8167 /* we have can just get the values */
8168 int size = AOP_SIZE (result);
8173 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8176 emitcode ("mov", "a,@%s", rname);
8177 aopPut (AOP (result), "a", offset);
8181 sprintf (buffer, "@%s", rname);
8182 aopPut (AOP (result), buffer, offset);
8186 emitcode ("inc", "%s", rname);
8190 /* now some housekeeping stuff */
8193 /* we had to allocate for this iCode */
8194 freeAsmop (NULL, aop, ic, TRUE);
8198 /* we did not allocate which means left
8199 already in a pointer register, then
8200 if size > 0 && this could be used again
8201 we have to point it back to where it
8203 if (AOP_SIZE (result) > 1 &&
8204 !OP_SYMBOL (left)->remat &&
8205 (OP_SYMBOL (left)->liveTo > ic->seq ||
8208 int size = AOP_SIZE (result) - 1;
8210 emitcode ("dec", "%s", rname);
8215 freeAsmop (result, NULL, ic, TRUE);
8219 /*-----------------------------------------------------------------*/
8220 /* genPagedPointerGet - emitcode for paged pointer fetch */
8221 /*-----------------------------------------------------------------*/
8223 genPagedPointerGet (operand * left,
8230 sym_link *rtype, *retype, *letype;
8232 rtype = operandType (result);
8233 retype = getSpec (rtype);
8234 letype = getSpec (operandType (left));
8235 aopOp (left, ic, FALSE, FALSE);
8237 /* if the value is already in a pointer register
8238 then don't need anything more */
8239 if (!AOP_INPREG (AOP (left)))
8241 /* otherwise get a free pointer register */
8243 preg = getFreePtr (ic, &aop, FALSE);
8244 emitcode ("mov", "%s,%s",
8246 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8250 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8252 freeAsmop (left, NULL, ic, TRUE);
8253 aopOp (result, ic, FALSE, FALSE);
8255 /* if bitfield then unpack the bits */
8256 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8257 genUnpackBits (result, rname, PPOINTER);
8260 /* we have can just get the values */
8261 int size = AOP_SIZE (result);
8267 emitcode ("movx", "a,@%s", rname);
8268 aopPut (AOP (result), "a", offset);
8273 emitcode ("inc", "%s", rname);
8277 /* now some housekeeping stuff */
8280 /* we had to allocate for this iCode */
8281 freeAsmop (NULL, aop, ic, TRUE);
8285 /* we did not allocate which means left
8286 already in a pointer register, then
8287 if size > 0 && this could be used again
8288 we have to point it back to where it
8290 if (AOP_SIZE (result) > 1 &&
8291 !OP_SYMBOL (left)->remat &&
8292 (OP_SYMBOL (left)->liveTo > ic->seq ||
8295 int size = AOP_SIZE (result) - 1;
8297 emitcode ("dec", "%s", rname);
8302 freeAsmop (result, NULL, ic, TRUE);
8307 /*-----------------------------------------------------------------*/
8308 /* genFarPointerGet - gget value from far space */
8309 /*-----------------------------------------------------------------*/
8311 genFarPointerGet (operand * left,
8312 operand * result, iCode * ic)
8315 sym_link *retype = getSpec (operandType (result));
8316 sym_link *letype = getSpec (operandType (left));
8317 D (emitcode (";", "genFarPointerGet");
8320 aopOp (left, ic, FALSE, FALSE);
8322 /* if the operand is already in dptr
8323 then we do nothing else we move the value to dptr */
8324 if (AOP_TYPE (left) != AOP_STR)
8326 /* if this is remateriazable */
8327 if (AOP_TYPE (left) == AOP_IMMD)
8329 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8333 /* we need to get it byte by byte */
8334 _startLazyDPSEvaluation ();
8335 if (AOP_TYPE (left) != AOP_DPTR)
8337 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8338 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8339 if (options.model == MODEL_FLAT24)
8340 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8344 /* We need to generate a load to DPTR indirect through DPTR. */
8345 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8347 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8348 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8349 if (options.model == MODEL_FLAT24)
8350 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8351 emitcode ("pop", "dph");
8352 emitcode ("pop", "dpl");
8354 _endLazyDPSEvaluation ();
8357 /* so dptr know contains the address */
8358 freeAsmop (left, NULL, ic, TRUE);
8359 aopOp (result, ic, FALSE, TRUE);
8361 /* if bit then unpack */
8362 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8363 genUnpackBits (result, "dptr", FPOINTER);
8366 size = AOP_SIZE (result);
8369 _startLazyDPSEvaluation ();
8376 emitcode ("movx", "a,@dptr");
8378 emitcode ("inc", "dptr");
8380 aopPut (AOP (result), "a", offset++);
8382 _endLazyDPSEvaluation ();
8385 freeAsmop (result, NULL, ic, TRUE);
8388 /*-----------------------------------------------------------------*/
8389 /* emitcodePointerGet - gget value from code space */
8390 /*-----------------------------------------------------------------*/
8392 emitcodePointerGet (operand * left,
8393 operand * result, iCode * ic)
8396 sym_link *retype = getSpec (operandType (result));
8398 aopOp (left, ic, FALSE, FALSE);
8400 /* if the operand is already in dptr
8401 then we do nothing else we move the value to dptr */
8402 if (AOP_TYPE (left) != AOP_STR)
8404 /* if this is remateriazable */
8405 if (AOP_TYPE (left) == AOP_IMMD)
8407 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8410 { /* we need to get it byte by byte */
8411 _startLazyDPSEvaluation ();
8412 if (AOP_TYPE (left) != AOP_DPTR)
8414 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8415 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8416 if (options.model == MODEL_FLAT24)
8417 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8421 /* We need to generate a load to DPTR indirect through DPTR. */
8422 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8424 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8425 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8426 if (options.model == MODEL_FLAT24)
8427 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8428 emitcode ("pop", "dph");
8429 emitcode ("pop", "dpl");
8431 _endLazyDPSEvaluation ();
8434 /* so dptr know contains the address */
8435 freeAsmop (left, NULL, ic, TRUE);
8436 aopOp (result, ic, FALSE, TRUE);
8438 /* if bit then unpack */
8439 if (IS_BITVAR (retype))
8440 genUnpackBits (result, "dptr", CPOINTER);
8443 size = AOP_SIZE (result);
8446 _startLazyDPSEvaluation ();
8452 emitcode ("clr", "a");
8453 emitcode ("movc", "a,@a+dptr");
8455 emitcode ("inc", "dptr");
8456 aopPut (AOP (result), "a", offset++);
8458 _endLazyDPSEvaluation ();
8461 freeAsmop (result, NULL, ic, TRUE);
8464 /*-----------------------------------------------------------------*/
8465 /* genGenPointerGet - gget value from generic pointer space */
8466 /*-----------------------------------------------------------------*/
8468 genGenPointerGet (operand * left,
8469 operand * result, iCode * ic)
8472 sym_link *retype = getSpec (operandType (result));
8473 sym_link *letype = getSpec (operandType (left));
8475 D (emitcode (";", "genGenPointerGet "); );
8477 aopOp (left, ic, FALSE, TRUE);
8479 /* if the operand is already in dptr
8480 then we do nothing else we move the value to dptr */
8481 if (AOP_TYPE (left) != AOP_STR)
8483 /* if this is remateriazable */
8484 if (AOP_TYPE (left) == AOP_IMMD)
8486 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8487 emitcode ("mov", "b,#%d", pointerCode (retype));
8490 { /* we need to get it byte by byte */
8491 _startLazyDPSEvaluation ();
8492 if (AOP(left)->type==AOP_DPTR2) {
8494 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8497 emitcode ("mov", "dpl,%s", l);
8498 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8501 emitcode ("mov", "dph,%s", l);
8502 if (options.model == MODEL_FLAT24) {
8503 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8506 emitcode ("mov", "dpx,%s", l);
8507 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8509 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8512 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8513 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8514 if (options.model == MODEL_FLAT24) {
8515 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8516 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8518 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8521 _endLazyDPSEvaluation ();
8524 /* so dptr know contains the address */
8525 freeAsmop (left, NULL, ic, TRUE);
8526 aopOp (result, ic, FALSE, TRUE);
8528 /* if bit then unpack */
8529 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8530 genUnpackBits (result, "dptr", GPOINTER);
8533 size = AOP_SIZE (result);
8538 emitcode ("lcall", "__gptrget");
8539 aopPut (AOP (result), "a", offset++);
8541 emitcode ("inc", "dptr");
8545 freeAsmop (result, NULL, ic, TRUE);
8548 /*-----------------------------------------------------------------*/
8549 /* genPointerGet - generate code for pointer get */
8550 /*-----------------------------------------------------------------*/
8552 genPointerGet (iCode * ic)
8554 operand *left, *result;
8555 sym_link *type, *etype;
8558 D (emitcode (";", "genPointerGet ");
8561 left = IC_LEFT (ic);
8562 result = IC_RESULT (ic);
8564 /* depending on the type of pointer we need to
8565 move it to the correct pointer register */
8566 type = operandType (left);
8567 etype = getSpec (type);
8568 /* if left is of type of pointer then it is simple */
8569 if (IS_PTR (type) && !IS_FUNC (type->next))
8570 p_type = DCL_TYPE (type);
8573 /* we have to go by the storage class */
8574 p_type = PTR_TYPE (SPEC_OCLS (etype));
8577 /* now that we have the pointer type we assign
8578 the pointer values */
8584 genNearPointerGet (left, result, ic);
8588 genPagedPointerGet (left, result, ic);
8592 genFarPointerGet (left, result, ic);
8596 emitcodePointerGet (left, result, ic);
8600 genGenPointerGet (left, result, ic);
8606 /*-----------------------------------------------------------------*/
8607 /* genPackBits - generates code for packed bit storage */
8608 /*-----------------------------------------------------------------*/
8610 genPackBits (sym_link * etype,
8612 char *rname, int p_type)
8620 blen = SPEC_BLEN (etype);
8621 bstr = SPEC_BSTR (etype);
8623 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8626 /* if the bit lenth is less than or */
8627 /* it exactly fits a byte then */
8628 if (SPEC_BLEN (etype) <= 8)
8630 shCount = SPEC_BSTR (etype);
8632 /* shift left acc */
8635 if (SPEC_BLEN (etype) < 8)
8636 { /* if smaller than a byte */
8642 emitcode ("mov", "b,a");
8643 emitcode ("mov", "a,@%s", rname);
8647 emitcode ("mov", "b,a");
8648 emitcode ("movx", "a,@dptr");
8652 emitcode ("push", "b");
8653 emitcode ("push", "acc");
8654 emitcode ("lcall", "__gptrget");
8655 emitcode ("pop", "b");
8659 emitcode ("anl", "a,#0x%02x", (unsigned char)
8660 ((unsigned char) (0xFF << (blen + bstr)) |
8661 (unsigned char) (0xFF >> (8 - bstr))));
8662 emitcode ("orl", "a,b");
8663 if (p_type == GPOINTER)
8664 emitcode ("pop", "b");
8671 emitcode ("mov", "@%s,a", rname);
8675 emitcode ("movx", "@dptr,a");
8679 emitcode ("lcall", "__gptrput");
8684 if (SPEC_BLEN (etype) <= 8)
8687 emitcode ("inc", "%s", rname);
8688 rLen = SPEC_BLEN (etype);
8690 /* now generate for lengths greater than one byte */
8694 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8706 emitcode ("mov", "@%s,a", rname);
8709 emitcode ("mov", "@%s,%s", rname, l);
8714 emitcode ("movx", "@dptr,a");
8719 emitcode ("lcall", "__gptrput");
8722 emitcode ("inc", "%s", rname);
8727 /* last last was not complete */
8730 /* save the byte & read byte */
8734 emitcode ("mov", "b,a");
8735 emitcode ("mov", "a,@%s", rname);
8739 emitcode ("mov", "b,a");
8740 emitcode ("movx", "a,@dptr");
8744 emitcode ("push", "b");
8745 emitcode ("push", "acc");
8746 emitcode ("lcall", "__gptrget");
8747 emitcode ("pop", "b");
8751 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8752 emitcode ("orl", "a,b");
8755 if (p_type == GPOINTER)
8756 emitcode ("pop", "b");
8762 emitcode ("mov", "@%s,a", rname);
8766 emitcode ("movx", "@dptr,a");
8770 emitcode ("lcall", "__gptrput");
8774 /*-----------------------------------------------------------------*/
8775 /* genDataPointerSet - remat pointer to data space */
8776 /*-----------------------------------------------------------------*/
8778 genDataPointerSet (operand * right,
8782 int size, offset = 0;
8783 char *l, buffer[256];
8785 aopOp (right, ic, FALSE, FALSE);
8787 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8788 size = AOP_SIZE (right);
8792 sprintf (buffer, "(%s + %d)", l + 1, offset);
8794 sprintf (buffer, "%s", l + 1);
8795 emitcode ("mov", "%s,%s", buffer,
8796 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8799 freeAsmop (right, NULL, ic, TRUE);
8800 freeAsmop (result, NULL, ic, TRUE);
8803 /*-----------------------------------------------------------------*/
8804 /* genNearPointerSet - emitcode for near pointer put */
8805 /*-----------------------------------------------------------------*/
8807 genNearPointerSet (operand * right,
8814 sym_link *retype, *letype;
8815 sym_link *ptype = operandType (result);
8817 retype = getSpec (operandType (right));
8818 letype = getSpec (ptype);
8820 aopOp (result, ic, FALSE, FALSE);
8822 /* if the result is rematerializable &
8823 in data space & not a bit variable */
8824 if (AOP_TYPE (result) == AOP_IMMD &&
8825 DCL_TYPE (ptype) == POINTER &&
8826 !IS_BITVAR (retype) &&
8827 !IS_BITVAR (letype))
8829 genDataPointerSet (right, result, ic);
8833 /* if the value is already in a pointer register
8834 then don't need anything more */
8835 if (!AOP_INPREG (AOP (result)))
8837 /* otherwise get a free pointer register */
8839 preg = getFreePtr (ic, &aop, FALSE);
8840 emitcode ("mov", "%s,%s",
8842 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8846 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8848 freeAsmop (result, NULL, ic, TRUE);
8849 aopOp (right, ic, FALSE, FALSE);
8851 /* if bitfield then unpack the bits */
8852 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8853 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8856 /* we have can just get the values */
8857 int size = AOP_SIZE (right);
8862 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8866 emitcode ("mov", "@%s,a", rname);
8869 emitcode ("mov", "@%s,%s", rname, l);
8871 emitcode ("inc", "%s", rname);
8876 /* now some housekeeping stuff */
8879 /* we had to allocate for this iCode */
8880 freeAsmop (NULL, aop, ic, TRUE);
8884 /* we did not allocate which means left
8885 already in a pointer register, then
8886 if size > 0 && this could be used again
8887 we have to point it back to where it
8889 if (AOP_SIZE (right) > 1 &&
8890 !OP_SYMBOL (result)->remat &&
8891 (OP_SYMBOL (result)->liveTo > ic->seq ||
8894 int size = AOP_SIZE (right) - 1;
8896 emitcode ("dec", "%s", rname);
8901 freeAsmop (right, NULL, ic, TRUE);
8906 /*-----------------------------------------------------------------*/
8907 /* genPagedPointerSet - emitcode for Paged pointer put */
8908 /*-----------------------------------------------------------------*/
8910 genPagedPointerSet (operand * right,
8917 sym_link *retype, *letype;
8919 retype = getSpec (operandType (right));
8920 letype = getSpec (operandType (result));
8922 aopOp (result, ic, FALSE, FALSE);
8924 /* if the value is already in a pointer register
8925 then don't need anything more */
8926 if (!AOP_INPREG (AOP (result)))
8928 /* otherwise get a free pointer register */
8930 preg = getFreePtr (ic, &aop, FALSE);
8931 emitcode ("mov", "%s,%s",
8933 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8937 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8939 freeAsmop (result, NULL, ic, TRUE);
8940 aopOp (right, ic, FALSE, FALSE);
8942 /* if bitfield then unpack the bits */
8943 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8944 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8947 /* we have can just get the values */
8948 int size = AOP_SIZE (right);
8953 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8956 emitcode ("movx", "@%s,a", rname);
8959 emitcode ("inc", "%s", rname);
8965 /* now some housekeeping stuff */
8968 /* we had to allocate for this iCode */
8969 freeAsmop (NULL, aop, ic, TRUE);
8973 /* we did not allocate which means left
8974 already in a pointer register, then
8975 if size > 0 && this could be used again
8976 we have to point it back to where it
8978 if (AOP_SIZE (right) > 1 &&
8979 !OP_SYMBOL (result)->remat &&
8980 (OP_SYMBOL (result)->liveTo > ic->seq ||
8983 int size = AOP_SIZE (right) - 1;
8985 emitcode ("dec", "%s", rname);
8990 freeAsmop (right, NULL, ic, TRUE);
8995 /*-----------------------------------------------------------------*/
8996 /* genFarPointerSet - set value from far space */
8997 /*-----------------------------------------------------------------*/
8999 genFarPointerSet (operand * right,
9000 operand * result, iCode * ic)
9003 sym_link *retype = getSpec (operandType (right));
9004 sym_link *letype = getSpec (operandType (result));
9006 aopOp (result, ic, FALSE, FALSE);
9008 /* if the operand is already in dptr
9009 then we do nothing else we move the value to dptr */
9010 if (AOP_TYPE (result) != AOP_STR)
9012 /* if this is remateriazable */
9013 if (AOP_TYPE (result) == AOP_IMMD)
9014 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9017 /* we need to get it byte by byte */
9018 _startLazyDPSEvaluation ();
9019 if (AOP_TYPE (result) != AOP_DPTR)
9021 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9022 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9023 if (options.model == MODEL_FLAT24)
9024 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9028 /* We need to generate a load to DPTR indirect through DPTR. */
9029 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9031 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9032 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9033 if (options.model == MODEL_FLAT24)
9034 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9035 emitcode ("pop", "dph");
9036 emitcode ("pop", "dpl");
9038 _endLazyDPSEvaluation ();
9041 /* so dptr know contains the address */
9042 freeAsmop (result, NULL, ic, TRUE);
9043 aopOp (right, ic, FALSE, TRUE);
9045 /* if bit then unpack */
9046 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9047 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9050 size = AOP_SIZE (right);
9053 _startLazyDPSEvaluation ();
9056 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9062 emitcode ("movx", "@dptr,a");
9064 emitcode ("inc", "dptr");
9066 _endLazyDPSEvaluation ();
9069 freeAsmop (right, NULL, ic, TRUE);
9072 /*-----------------------------------------------------------------*/
9073 /* genGenPointerSet - set value from generic pointer space */
9074 /*-----------------------------------------------------------------*/
9076 genGenPointerSet (operand * right,
9077 operand * result, iCode * ic)
9080 sym_link *retype = getSpec (operandType (right));
9081 sym_link *letype = getSpec (operandType (result));
9083 aopOp (result, ic, FALSE, TRUE);
9085 /* if the operand is already in dptr
9086 then we do nothing else we move the value to dptr */
9087 if (AOP_TYPE (result) != AOP_STR)
9089 _startLazyDPSEvaluation ();
9090 /* if this is remateriazable */
9091 if (AOP_TYPE (result) == AOP_IMMD)
9093 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9094 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9097 { /* we need to get it byte by byte */
9098 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9099 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9100 if (options.model == MODEL_FLAT24) {
9101 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9102 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9104 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9107 _endLazyDPSEvaluation ();
9109 /* so dptr know contains the address */
9110 freeAsmop (result, NULL, ic, TRUE);
9111 aopOp (right, ic, FALSE, TRUE);
9113 /* if bit then unpack */
9114 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9115 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9118 size = AOP_SIZE (right);
9121 _startLazyDPSEvaluation ();
9124 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9130 emitcode ("lcall", "__gptrput");
9132 emitcode ("inc", "dptr");
9134 _endLazyDPSEvaluation ();
9137 freeAsmop (right, NULL, ic, TRUE);
9140 /*-----------------------------------------------------------------*/
9141 /* genPointerSet - stores the value into a pointer location */
9142 /*-----------------------------------------------------------------*/
9144 genPointerSet (iCode * ic)
9146 operand *right, *result;
9147 sym_link *type, *etype;
9150 D (emitcode (";", "genPointerSet ");
9153 right = IC_RIGHT (ic);
9154 result = IC_RESULT (ic);
9156 /* depending on the type of pointer we need to
9157 move it to the correct pointer register */
9158 type = operandType (result);
9159 etype = getSpec (type);
9160 /* if left is of type of pointer then it is simple */
9161 if (IS_PTR (type) && !IS_FUNC (type->next))
9163 p_type = DCL_TYPE (type);
9167 /* we have to go by the storage class */
9168 p_type = PTR_TYPE (SPEC_OCLS (etype));
9171 /* now that we have the pointer type we assign
9172 the pointer values */
9178 genNearPointerSet (right, result, ic);
9182 genPagedPointerSet (right, result, ic);
9186 genFarPointerSet (right, result, ic);
9190 genGenPointerSet (right, result, ic);
9196 /*-----------------------------------------------------------------*/
9197 /* genIfx - generate code for Ifx statement */
9198 /*-----------------------------------------------------------------*/
9200 genIfx (iCode * ic, iCode * popIc)
9202 operand *cond = IC_COND (ic);
9205 D (emitcode (";", "genIfx "););
9207 aopOp (cond, ic, FALSE, FALSE);
9209 /* get the value into acc */
9210 if (AOP_TYPE (cond) != AOP_CRY)
9214 /* the result is now in the accumulator */
9215 freeAsmop (cond, NULL, ic, TRUE);
9217 /* if there was something to be popped then do it */
9221 /* if the condition is a bit variable */
9222 if (isbit && IS_ITEMP (cond) &&
9224 genIfxJump (ic, SPIL_LOC (cond)->rname);
9225 else if (isbit && !IS_ITEMP (cond))
9226 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9228 genIfxJump (ic, "a");
9233 /*-----------------------------------------------------------------*/
9234 /* genAddrOf - generates code for address of */
9235 /*-----------------------------------------------------------------*/
9237 genAddrOf (iCode * ic)
9239 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9242 D (emitcode (";", "genAddrOf ");
9245 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9247 /* if the operand is on the stack then we
9248 need to get the stack offset of this
9252 /* if it has an offset then we need to compute
9256 emitcode ("mov", "a,_bp");
9257 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9258 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9262 /* we can just move _bp */
9263 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9265 /* fill the result with zero */
9266 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9269 if (options.stack10bit && size < (FPTRSIZE - 1))
9272 "*** warning: pointer to stack var truncated.\n");
9279 if (options.stack10bit && offset == 2)
9281 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9285 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9292 /* object not on stack then we need the name */
9293 size = AOP_SIZE (IC_RESULT (ic));
9298 char s[SDCC_NAME_MAX];
9300 sprintf (s, "#(%s >> %d)",
9304 sprintf (s, "#%s", sym->rname);
9305 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9309 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9313 /*-----------------------------------------------------------------*/
9314 /* genArrayInit - generates code for address of */
9315 /*-----------------------------------------------------------------*/
9317 genArrayInit (iCode * ic)
9321 int elementSize = 0, eIndex;
9322 unsigned val, lastVal;
9324 operand *left=IC_LEFT(ic);
9326 D (emitcode (";", "genArrayInit "););
9328 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9330 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9332 // Load immediate value into DPTR.
9333 emitcode("mov", "dptr, %s",
9334 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9336 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9339 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9340 "Unexpected operand to genArrayInit.\n");
9343 // a regression because of SDCCcse.c:1.52
9344 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9345 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9346 if (options.model == MODEL_FLAT24)
9347 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9351 type = operandType(IC_LEFT(ic));
9353 if (type && type->next)
9355 elementSize = getSize(type->next);
9359 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9360 "can't determine element size in genArrayInit.\n");
9364 iLoop = IC_ARRAYILIST(ic);
9369 bool firstpass = TRUE;
9371 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9372 iLoop->count, (int)iLoop->literalValue, elementSize);
9378 symbol *tlbl = NULL;
9380 count = ix > 256 ? 256 : ix;
9384 tlbl = newiTempLabel (NULL);
9385 if (firstpass || (count & 0xff))
9387 emitcode("mov", "b, #0x%x", count & 0xff);
9390 emitcode ("", "%05d$:", tlbl->key + 100);
9395 for (eIndex = 0; eIndex < elementSize; eIndex++)
9397 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9400 emitcode("mov", "a, #0x%x", val);
9404 emitcode("movx", "@dptr, a");
9405 emitcode("inc", "dptr");
9410 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9416 iLoop = iLoop->next;
9419 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9422 /*-----------------------------------------------------------------*/
9423 /* genFarFarAssign - assignment when both are in far space */
9424 /*-----------------------------------------------------------------*/
9426 genFarFarAssign (operand * result, operand * right, iCode * ic)
9428 int size = AOP_SIZE (right);
9430 symbol *rSym = NULL;
9434 /* quick & easy case. */
9435 D(emitcode(";","genFarFarAssign (1 byte case)"););
9436 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9437 freeAsmop (right, NULL, ic, FALSE);
9438 /* now assign DPTR to result */
9440 aopOp(result, ic, FALSE, FALSE);
9442 aopPut(AOP(result), "a", 0);
9443 freeAsmop(result, NULL, ic, FALSE);
9447 /* See if we've got an underlying symbol to abuse. */
9448 if (IS_SYMOP(result) && OP_SYMBOL(result))
9450 if (IS_TRUE_SYMOP(result))
9452 rSym = OP_SYMBOL(result);
9454 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9456 rSym = OP_SYMBOL(result)->usl.spillLoc;
9460 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9462 /* We can use the '390 auto-toggle feature to good effect here. */
9464 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9465 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9466 emitcode ("mov", "dptr,#%s", rSym->rname);
9467 /* DP2 = result, DP1 = right, DP1 is current. */
9470 emitcode("movx", "a,@dptr");
9471 emitcode("movx", "@dptr,a");
9474 emitcode("inc", "dptr");
9475 emitcode("inc", "dptr");
9478 emitcode("mov", "dps, #0");
9479 freeAsmop (right, NULL, ic, FALSE);
9481 some alternative code for processors without auto-toggle
9482 no time to test now, so later well put in...kpb
9483 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9484 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9485 emitcode ("mov", "dptr,#%s", rSym->rname);
9486 /* DP2 = result, DP1 = right, DP1 is current. */
9490 emitcode("movx", "a,@dptr");
9492 emitcode("inc", "dptr");
9493 emitcode("inc", "dps");
9494 emitcode("movx", "@dptr,a");
9496 emitcode("inc", "dptr");
9497 emitcode("inc", "dps");
9499 emitcode("mov", "dps, #0");
9500 freeAsmop (right, NULL, ic, FALSE);
9505 D (emitcode (";", "genFarFarAssign"););
9506 aopOp (result, ic, TRUE, TRUE);
9508 _startLazyDPSEvaluation ();
9512 aopPut (AOP (result),
9513 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9516 _endLazyDPSEvaluation ();
9517 freeAsmop (result, NULL, ic, FALSE);
9518 freeAsmop (right, NULL, ic, FALSE);
9522 /*-----------------------------------------------------------------*/
9523 /* genAssign - generate code for assignment */
9524 /*-----------------------------------------------------------------*/
9526 genAssign (iCode * ic)
9528 operand *result, *right;
9530 unsigned long lit = 0L;
9532 D (emitcode (";", "genAssign ");
9535 result = IC_RESULT (ic);
9536 right = IC_RIGHT (ic);
9538 /* if they are the same */
9539 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9542 aopOp (right, ic, FALSE, FALSE);
9544 emitcode (";", "genAssign: resultIsFar = %s",
9545 isOperandInFarSpace (result) ?
9548 /* special case both in far space */
9549 if ((AOP_TYPE (right) == AOP_DPTR ||
9550 AOP_TYPE (right) == AOP_DPTR2) &&
9551 /* IS_TRUE_SYMOP(result) && */
9552 isOperandInFarSpace (result))
9554 genFarFarAssign (result, right, ic);
9558 aopOp (result, ic, TRUE, FALSE);
9560 /* if they are the same registers */
9561 if (sameRegs (AOP (right), AOP (result)))
9564 /* if the result is a bit */
9565 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9567 /* if the right size is a literal then
9568 we know what the value is */
9569 if (AOP_TYPE (right) == AOP_LIT)
9571 if (((int) operandLitValue (right)))
9572 aopPut (AOP (result), one, 0);
9574 aopPut (AOP (result), zero, 0);
9578 /* the right is also a bit variable */
9579 if (AOP_TYPE (right) == AOP_CRY)
9581 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9582 aopPut (AOP (result), "c", 0);
9588 aopPut (AOP (result), "a", 0);
9592 /* bit variables done */
9594 size = AOP_SIZE (result);
9596 if (AOP_TYPE (right) == AOP_LIT)
9597 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9600 (AOP_TYPE (result) != AOP_REG) &&
9601 (AOP_TYPE (right) == AOP_LIT) &&
9602 !IS_FLOAT (operandType (right)))
9604 _startLazyDPSEvaluation ();
9605 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9607 aopPut (AOP (result),
9608 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9613 /* And now fill the rest with zeros. */
9616 emitcode ("clr", "a");
9620 aopPut (AOP (result), "a", offset++);
9622 _endLazyDPSEvaluation ();
9626 _startLazyDPSEvaluation ();
9629 aopPut (AOP (result),
9630 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9634 _endLazyDPSEvaluation ();
9638 freeAsmop (right, NULL, ic, FALSE);
9639 freeAsmop (result, NULL, ic, TRUE);
9642 /*-----------------------------------------------------------------*/
9643 /* genJumpTab - generates code for jump table */
9644 /*-----------------------------------------------------------------*/
9646 genJumpTab (iCode * ic)
9651 D (emitcode (";", "genJumpTab ");
9654 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9655 /* get the condition into accumulator */
9656 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9658 /* multiply by four! */
9659 emitcode ("add", "a,acc");
9660 emitcode ("add", "a,acc");
9661 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9663 jtab = newiTempLabel (NULL);
9664 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9665 emitcode ("jmp", "@a+dptr");
9666 emitcode ("", "%05d$:", jtab->key + 100);
9667 /* now generate the jump labels */
9668 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9669 jtab = setNextItem (IC_JTLABELS (ic)))
9670 emitcode ("ljmp", "%05d$", jtab->key + 100);
9674 /*-----------------------------------------------------------------*/
9675 /* genCast - gen code for casting */
9676 /*-----------------------------------------------------------------*/
9678 genCast (iCode * ic)
9680 operand *result = IC_RESULT (ic);
9681 sym_link *ctype = operandType (IC_LEFT (ic));
9682 sym_link *rtype = operandType (IC_RIGHT (ic));
9683 operand *right = IC_RIGHT (ic);
9686 D (emitcode (";", "genCast ");
9689 /* if they are equivalent then do nothing */
9690 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9693 aopOp (right, ic, FALSE, FALSE);
9694 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9696 /* if the result is a bit */
9697 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9698 if (IS_BITVAR(OP_SYMBOL(result)->type))
9700 /* if the right size is a literal then
9701 we know what the value is */
9702 if (AOP_TYPE (right) == AOP_LIT)
9704 if (((int) operandLitValue (right)))
9705 aopPut (AOP (result), one, 0);
9707 aopPut (AOP (result), zero, 0);
9712 /* the right is also a bit variable */
9713 if (AOP_TYPE (right) == AOP_CRY)
9715 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9716 aopPut (AOP (result), "c", 0);
9722 aopPut (AOP (result), "a", 0);
9726 /* if they are the same size : or less */
9727 if (AOP_SIZE (result) <= AOP_SIZE (right))
9730 /* if they are in the same place */
9731 if (sameRegs (AOP (right), AOP (result)))
9734 /* if they in different places then copy */
9735 size = AOP_SIZE (result);
9737 _startLazyDPSEvaluation ();
9740 aopPut (AOP (result),
9741 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9745 _endLazyDPSEvaluation ();
9750 /* if the result is of type pointer */
9755 sym_link *type = operandType (right);
9757 /* pointer to generic pointer */
9758 if (IS_GENPTR (ctype))
9764 p_type = DCL_TYPE (type);
9768 #if OLD_CAST_BEHAVIOR
9769 /* KV: we are converting a non-pointer type to
9770 * a generic pointer. This (ifdef'd out) code
9771 * says that the resulting generic pointer
9772 * should have the same class as the storage
9773 * location of the non-pointer variable.
9775 * For example, converting an int (which happens
9776 * to be stored in DATA space) to a pointer results
9777 * in a DATA generic pointer; if the original int
9778 * in XDATA space, so will be the resulting pointer.
9780 * I don't like that behavior, and thus this change:
9781 * all such conversions will be forced to XDATA and
9782 * throw a warning. If you want some non-XDATA
9783 * type, or you want to suppress the warning, you
9784 * must go through an intermediate cast, like so:
9786 * char _generic *gp = (char _xdata *)(intVar);
9788 sym_link *etype = getSpec (type);
9790 /* we have to go by the storage class */
9791 if (SPEC_OCLS (etype) != generic)
9793 p_type = PTR_TYPE (SPEC_OCLS (etype));
9798 /* Converting unknown class (i.e. register variable)
9799 * to generic pointer. This is not good, but
9800 * we'll make a guess (and throw a warning).
9803 werror (W_INT_TO_GEN_PTR_CAST);
9807 /* the first two bytes are known */
9808 size = GPTRSIZE - 1;
9810 _startLazyDPSEvaluation ();
9813 aopPut (AOP (result),
9814 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9818 _endLazyDPSEvaluation ();
9820 /* the last byte depending on type */
9838 /* this should never happen */
9839 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9840 "got unknown pointer type");
9843 aopPut (AOP (result), l, GPTRSIZE - 1);
9847 /* just copy the pointers */
9848 size = AOP_SIZE (result);
9850 _startLazyDPSEvaluation ();
9853 aopPut (AOP (result),
9854 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9858 _endLazyDPSEvaluation ();
9862 /* so we now know that the size of destination is greater
9863 than the size of the source */
9864 /* we move to result for the size of source */
9865 size = AOP_SIZE (right);
9867 _startLazyDPSEvaluation ();
9870 aopPut (AOP (result),
9871 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9875 _endLazyDPSEvaluation ();
9877 /* now depending on the sign of the source && destination */
9878 size = AOP_SIZE (result) - AOP_SIZE (right);
9879 /* if unsigned or not an integral type */
9880 /* also, if the source is a bit, we don't need to sign extend, because
9881 * it can't possibly have set the sign bit.
9883 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9887 aopPut (AOP (result), zero, offset++);
9892 /* we need to extend the sign :{ */
9893 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9894 FALSE, FALSE, TRUE);
9896 emitcode ("rlc", "a");
9897 emitcode ("subb", "a,acc");
9899 aopPut (AOP (result), "a", offset++);
9902 /* we are done hurray !!!! */
9905 freeAsmop (right, NULL, ic, TRUE);
9906 freeAsmop (result, NULL, ic, TRUE);
9910 /*-----------------------------------------------------------------*/
9911 /* genDjnz - generate decrement & jump if not zero instrucion */
9912 /*-----------------------------------------------------------------*/
9914 genDjnz (iCode * ic, iCode * ifx)
9920 /* if the if condition has a false label
9921 then we cannot save */
9925 /* if the minus is not of the form
9927 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9928 !IS_OP_LITERAL (IC_RIGHT (ic)))
9931 if (operandLitValue (IC_RIGHT (ic)) != 1)
9934 /* if the size of this greater than one then no
9936 if (getSize (operandType (IC_RESULT (ic))) > 1)
9939 /* otherwise we can save BIG */
9940 D(emitcode(";", "genDjnz"););
9942 lbl = newiTempLabel (NULL);
9943 lbl1 = newiTempLabel (NULL);
9945 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9947 if (AOP_NEEDSACC(IC_RESULT(ic)))
9949 /* If the result is accessed indirectly via
9950 * the accumulator, we must explicitly write
9951 * it back after the decrement.
9953 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9955 if (strcmp(rByte, "a"))
9957 /* Something is hopelessly wrong */
9958 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9959 __FILE__, __LINE__);
9960 /* We can just give up; the generated code will be inefficient,
9963 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9966 emitcode ("dec", "%s", rByte);
9967 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9968 emitcode ("jnz", "%05d$", lbl->key + 100);
9970 else if (IS_AOP_PREG (IC_RESULT (ic)))
9972 emitcode ("dec", "%s",
9973 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9974 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9975 emitcode ("jnz", "%05d$", lbl->key + 100);
9979 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9982 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9983 emitcode ("", "%05d$:", lbl->key + 100);
9984 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9985 emitcode ("", "%05d$:", lbl1->key + 100);
9987 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9992 /*-----------------------------------------------------------------*/
9993 /* genReceive - generate code for a receive iCode */
9994 /*-----------------------------------------------------------------*/
9996 genReceive (iCode * ic)
9999 D (emitcode (";", "genReceive ");
10002 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10003 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10004 IS_TRUE_SYMOP (IC_RESULT (ic))))
10006 int size = getSize (operandType (IC_RESULT (ic)));
10007 int offset = fReturnSizeDS390 - size;
10010 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10011 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10014 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10015 size = AOP_SIZE (IC_RESULT (ic));
10019 emitcode ("pop", "acc");
10020 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10027 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10029 assignResultValue (IC_RESULT (ic));
10032 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10035 /*-----------------------------------------------------------------*/
10036 /* gen390Code - generate code for Dallas 390 based controllers */
10037 /*-----------------------------------------------------------------*/
10039 gen390Code (iCode * lic)
10044 lineHead = lineCurr = NULL;
10046 if (options.model == MODEL_FLAT24) {
10047 fReturnSizeDS390 = 5;
10048 fReturn = fReturn24;
10050 fReturnSizeDS390 = 4;
10051 fReturn = fReturn16;
10052 options.stack10bit=0;
10056 /* print the allocation information */
10058 printAllocInfo (currFunc, codeOutFile);
10060 /* if debug information required */
10061 if (options.debug && currFunc)
10063 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10065 if (IS_STATIC (currFunc->etype))
10066 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10068 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10071 /* stack pointer name */
10072 if (options.useXstack)
10078 for (ic = lic; ic; ic = ic->next)
10081 if (cln != ic->lineno)
10086 emitcode ("", "C$%s$%d$%d$%d ==.",
10087 FileBaseName (ic->filename), ic->lineno,
10088 ic->level, ic->block);
10091 emitcode (";", "%s %d", ic->filename, ic->lineno);
10094 /* if the result is marked as
10095 spilt and rematerializable or code for
10096 this has already been generated then
10098 if (resultRemat (ic) || ic->generated)
10101 /* depending on the operation */
10121 /* IPOP happens only when trying to restore a
10122 spilt live range, if there is an ifx statement
10123 following this pop then the if statement might
10124 be using some of the registers being popped which
10125 would destory the contents of the register so
10126 we need to check for this condition and handle it */
10128 ic->next->op == IFX &&
10129 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10130 genIfx (ic->next, ic);
10148 genEndFunction (ic);
10168 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10185 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10189 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10196 /* note these two are xlated by algebraic equivalence
10197 during parsing SDCC.y */
10198 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10199 "got '>=' or '<=' shouldn't have come here");
10203 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10215 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10219 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10223 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10247 genRightShift (ic);
10250 case GET_VALUE_AT_ADDRESS:
10251 genPointerGet (ic);
10255 if (POINTER_SET (ic))
10256 genPointerSet (ic);
10282 addSet (&_G.sendSet, ic);
10295 /* now we are ready to call the
10296 peep hole optimizer */
10297 if (!options.nopeep)
10298 peepHole (&lineHead);
10300 /* now do the actual printing */
10301 printLine (lineHead, codeOutFile);