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 #ifdef LOGIC_OPS_BROKEN
5217 || AOP_NEEDSACC (left)
5221 operand *tmp = right;
5226 /* if result = right then exchange them */
5227 if (sameRegs (AOP (result), AOP (right)))
5229 operand *tmp = right;
5234 /* if right is bit then exchange them */
5235 if (AOP_TYPE (right) == AOP_CRY &&
5236 AOP_TYPE (left) != AOP_CRY)
5238 operand *tmp = right;
5242 if (AOP_TYPE (right) == AOP_LIT)
5243 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5245 size = AOP_SIZE (result);
5248 // result = bit & yy;
5249 if (AOP_TYPE (left) == AOP_CRY)
5251 // c = bit & literal;
5252 if (AOP_TYPE (right) == AOP_LIT)
5256 if (size && sameRegs (AOP (result), AOP (left)))
5259 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5264 if (size && (AOP_TYPE (result) == AOP_CRY))
5266 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5269 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5274 emitcode ("clr", "c");
5279 if (AOP_TYPE (right) == AOP_CRY)
5282 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5283 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5288 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5290 emitcode ("rrc", "a");
5291 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5299 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5300 genIfxJump (ifx, "c");
5304 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5305 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5306 if ((AOP_TYPE (right) == AOP_LIT) &&
5307 (AOP_TYPE (result) == AOP_CRY) &&
5308 (AOP_TYPE (left) != AOP_CRY))
5310 int posbit = isLiteralBit (lit);
5315 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5318 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5324 sprintf (buffer, "acc.%d", posbit & 0x07);
5325 genIfxJump (ifx, buffer);
5332 symbol *tlbl = newiTempLabel (NULL);
5333 int sizel = AOP_SIZE (left);
5335 emitcode ("setb", "c");
5338 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5340 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5342 if ((posbit = isLiteralBit (bytelit)) != 0)
5343 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5346 if (bytelit != 0x0FFL)
5347 emitcode ("anl", "a,%s",
5348 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5349 emitcode ("jnz", "%05d$", tlbl->key + 100);
5354 // bit = left & literal
5357 emitcode ("clr", "c");
5358 emitcode ("", "%05d$:", tlbl->key + 100);
5360 // if(left & literal)
5364 jmpTrueOrFalse (ifx, tlbl);
5372 /* if left is same as result */
5373 if (sameRegs (AOP (result), AOP (left)))
5375 for (; size--; offset++)
5377 if (AOP_TYPE (right) == AOP_LIT)
5379 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5381 else if (bytelit == 0)
5382 aopPut (AOP (result), zero, offset);
5383 else if (IS_AOP_PREG (result))
5385 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5386 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5387 aopPut (AOP (result), "a", offset);
5390 emitcode ("anl", "%s,%s",
5391 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5392 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5396 if (AOP_TYPE (left) == AOP_ACC)
5397 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5400 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5401 if (IS_AOP_PREG (result))
5403 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5404 aopPut (AOP (result), "a", offset);
5408 emitcode ("anl", "%s,a",
5409 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5416 // left & result in different registers
5417 if (AOP_TYPE (result) == AOP_CRY)
5420 // if(size), result in bit
5421 // if(!size && ifx), conditional oper: if(left & right)
5422 symbol *tlbl = newiTempLabel (NULL);
5423 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5425 emitcode ("setb", "c");
5428 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5429 emitcode ("anl", "a,%s",
5430 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5432 if (AOP_TYPE(left)==AOP_ACC) {
5433 emitcode("mov", "b,a");
5434 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5435 emitcode("anl", "a,b");
5437 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5438 emitcode ("anl", "a,%s",
5439 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5442 emitcode ("jnz", "%05d$", tlbl->key + 100);
5448 emitcode ("", "%05d$:", tlbl->key + 100);
5452 jmpTrueOrFalse (ifx, tlbl);
5456 for (; (size--); offset++)
5459 // result = left & right
5460 if (AOP_TYPE (right) == AOP_LIT)
5462 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5464 aopPut (AOP (result),
5465 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5469 else if (bytelit == 0)
5471 aopPut (AOP (result), zero, offset);
5474 D (emitcode (";", "better literal AND."););
5475 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5476 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5477 FALSE, FALSE, FALSE));
5482 // faster than result <- left, anl result,right
5483 // and better if result is SFR
5484 if (AOP_TYPE (left) == AOP_ACC)
5486 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5487 FALSE, FALSE, FALSE));
5491 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5492 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5494 emitcode("mov", "b,a");
5498 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5499 emitcode ("anl", "a,%s", rOp);
5502 aopPut (AOP (result), "a", offset);
5508 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5509 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5510 freeAsmop (result, NULL, ic, TRUE);
5514 /*-----------------------------------------------------------------*/
5515 /* genOr - code for or */
5516 /*-----------------------------------------------------------------*/
5518 genOr (iCode * ic, iCode * ifx)
5520 operand *left, *right, *result;
5521 int size, offset = 0;
5522 unsigned long lit = 0L;
5525 D (emitcode (";", "genOr "););
5527 AOP_OP_3_NOFATAL (ic, pushResult);
5528 AOP_SET_LOCALS (ic);
5532 genFarFarLogicOp(ic, "orl");
5538 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5540 AOP_TYPE (left), AOP_TYPE (right));
5541 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5543 AOP_SIZE (left), AOP_SIZE (right));
5546 /* if left is a literal & right is not then exchange them */
5547 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5548 #ifdef LOGIC_OPS_BROKEN
5549 || AOP_NEEDSACC (left) // I think this is a net loss now.
5553 operand *tmp = right;
5558 /* if result = right then exchange them */
5559 if (sameRegs (AOP (result), AOP (right)))
5561 operand *tmp = right;
5566 /* if right is bit then exchange them */
5567 if (AOP_TYPE (right) == AOP_CRY &&
5568 AOP_TYPE (left) != AOP_CRY)
5570 operand *tmp = right;
5574 if (AOP_TYPE (right) == AOP_LIT)
5575 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5577 size = AOP_SIZE (result);
5581 if (AOP_TYPE (left) == AOP_CRY)
5583 if (AOP_TYPE (right) == AOP_LIT)
5585 // c = bit & literal;
5588 // lit != 0 => result = 1
5589 if (AOP_TYPE (result) == AOP_CRY)
5592 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5594 continueIfTrue (ifx);
5597 emitcode ("setb", "c");
5601 // lit == 0 => result = left
5602 if (size && sameRegs (AOP (result), AOP (left)))
5604 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5609 if (AOP_TYPE (right) == AOP_CRY)
5612 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5613 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5618 symbol *tlbl = newiTempLabel (NULL);
5619 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5620 emitcode ("setb", "c");
5621 emitcode ("jb", "%s,%05d$",
5622 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5624 emitcode ("jnz", "%05d$", tlbl->key + 100);
5625 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5627 jmpTrueOrFalse (ifx, tlbl);
5633 emitcode ("", "%05d$:", tlbl->key + 100);
5642 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5643 genIfxJump (ifx, "c");
5647 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5648 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5649 if ((AOP_TYPE (right) == AOP_LIT) &&
5650 (AOP_TYPE (result) == AOP_CRY) &&
5651 (AOP_TYPE (left) != AOP_CRY))
5657 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5659 continueIfTrue (ifx);
5664 // lit = 0, result = boolean(left)
5666 emitcode ("setb", "c");
5670 symbol *tlbl = newiTempLabel (NULL);
5671 emitcode ("jnz", "%05d$", tlbl->key + 100);
5673 emitcode ("", "%05d$:", tlbl->key + 100);
5677 genIfxJump (ifx, "a");
5685 /* if left is same as result */
5686 if (sameRegs (AOP (result), AOP (left)))
5688 for (; size--; offset++)
5690 if (AOP_TYPE (right) == AOP_LIT)
5692 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5698 if (IS_AOP_PREG (left))
5700 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5701 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5702 aopPut (AOP (result), "a", offset);
5706 emitcode ("orl", "%s,%s",
5707 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5708 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5714 if (AOP_TYPE (left) == AOP_ACC)
5716 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5720 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5721 if (IS_AOP_PREG (left))
5723 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5724 aopPut (AOP (result), "a", offset);
5728 emitcode ("orl", "%s,a",
5729 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5737 // left & result in different registers
5738 if (AOP_TYPE (result) == AOP_CRY)
5741 // if(size), result in bit
5742 // if(!size && ifx), conditional oper: if(left | right)
5743 symbol *tlbl = newiTempLabel (NULL);
5744 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5746 emitcode ("setb", "c");
5749 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5750 emitcode ("orl", "a,%s",
5751 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5753 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5754 emitcode ("orl", "a,%s",
5755 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5757 emitcode ("jnz", "%05d$", tlbl->key + 100);
5763 emitcode ("", "%05d$:", tlbl->key + 100);
5767 jmpTrueOrFalse (ifx, tlbl);
5771 _startLazyDPSEvaluation();
5772 for (; (size--); offset++)
5775 // result = left & right
5776 if (AOP_TYPE (right) == AOP_LIT)
5778 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5780 aopPut (AOP (result),
5781 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5785 D (emitcode (";", "better literal OR."););
5786 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5787 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5788 FALSE, FALSE, FALSE));
5793 // faster than result <- left, anl result,right
5794 // and better if result is SFR
5795 if (AOP_TYPE (left) == AOP_ACC)
5797 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5798 FALSE, FALSE, FALSE));
5802 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5804 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5806 emitcode("mov", "b,a");
5810 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5811 emitcode ("orl", "a,%s", rOp);
5814 aopPut (AOP (result), "a", offset);
5816 _endLazyDPSEvaluation();
5821 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5822 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5823 freeAsmop (result, NULL, ic, TRUE);
5826 /*-----------------------------------------------------------------*/
5827 /* genXor - code for xclusive or */
5828 /*-----------------------------------------------------------------*/
5830 genXor (iCode * ic, iCode * ifx)
5832 operand *left, *right, *result;
5833 int size, offset = 0;
5834 unsigned long lit = 0L;
5837 D (emitcode (";", "genXor "););
5839 AOP_OP_3_NOFATAL (ic, pushResult);
5840 AOP_SET_LOCALS (ic);
5844 genFarFarLogicOp(ic, "xrl");
5849 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5851 AOP_TYPE (left), AOP_TYPE (right));
5852 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5854 AOP_SIZE (left), AOP_SIZE (right));
5857 /* if left is a literal & right is not ||
5858 if left needs acc & right does not */
5859 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5860 #ifdef LOGIC_OPS_BROKEN
5861 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
5865 operand *tmp = right;
5870 /* if result = right then exchange them */
5871 if (sameRegs (AOP (result), AOP (right)))
5873 operand *tmp = right;
5878 /* if right is bit then exchange them */
5879 if (AOP_TYPE (right) == AOP_CRY &&
5880 AOP_TYPE (left) != AOP_CRY)
5882 operand *tmp = right;
5886 if (AOP_TYPE (right) == AOP_LIT)
5887 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5889 size = AOP_SIZE (result);
5893 if (AOP_TYPE (left) == AOP_CRY)
5895 if (AOP_TYPE (right) == AOP_LIT)
5897 // c = bit & literal;
5900 // lit>>1 != 0 => result = 1
5901 if (AOP_TYPE (result) == AOP_CRY)
5904 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5906 continueIfTrue (ifx);
5909 emitcode ("setb", "c");
5916 // lit == 0, result = left
5917 if (size && sameRegs (AOP (result), AOP (left)))
5919 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5923 // lit == 1, result = not(left)
5924 if (size && sameRegs (AOP (result), AOP (left)))
5926 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5931 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5932 emitcode ("cpl", "c");
5941 symbol *tlbl = newiTempLabel (NULL);
5942 if (AOP_TYPE (right) == AOP_CRY)
5945 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5949 int sizer = AOP_SIZE (right);
5951 // if val>>1 != 0, result = 1
5952 emitcode ("setb", "c");
5955 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5957 // test the msb of the lsb
5958 emitcode ("anl", "a,#0xfe");
5959 emitcode ("jnz", "%05d$", tlbl->key + 100);
5963 emitcode ("rrc", "a");
5965 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5966 emitcode ("cpl", "c");
5967 emitcode ("", "%05d$:", (tlbl->key + 100));
5974 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5975 genIfxJump (ifx, "c");
5979 if (sameRegs (AOP (result), AOP (left)))
5981 /* if left is same as result */
5982 for (; size--; offset++)
5984 if (AOP_TYPE (right) == AOP_LIT)
5986 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5988 else if (IS_AOP_PREG (left))
5990 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5991 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5992 aopPut (AOP (result), "a", offset);
5995 emitcode ("xrl", "%s,%s",
5996 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5997 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6001 if (AOP_TYPE (left) == AOP_ACC)
6002 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6005 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6006 if (IS_AOP_PREG (left))
6008 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6009 aopPut (AOP (result), "a", offset);
6012 emitcode ("xrl", "%s,a",
6013 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6020 // left & result in different registers
6021 if (AOP_TYPE (result) == AOP_CRY)
6024 // if(size), result in bit
6025 // if(!size && ifx), conditional oper: if(left ^ right)
6026 symbol *tlbl = newiTempLabel (NULL);
6027 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6029 emitcode ("setb", "c");
6032 if ((AOP_TYPE (right) == AOP_LIT) &&
6033 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6035 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6039 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6040 emitcode ("xrl", "a,%s",
6041 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6043 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6044 emitcode ("xrl", "a,%s",
6045 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6048 emitcode ("jnz", "%05d$", tlbl->key + 100);
6054 emitcode ("", "%05d$:", tlbl->key + 100);
6058 jmpTrueOrFalse (ifx, tlbl);
6061 for (; (size--); offset++)
6064 // result = left & right
6065 if (AOP_TYPE (right) == AOP_LIT)
6067 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6069 aopPut (AOP (result),
6070 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6074 D (emitcode (";", "better literal XOR.");
6076 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6077 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6078 FALSE, FALSE, FALSE));
6082 // faster than result <- left, anl result,right
6083 // and better if result is SFR
6084 if (AOP_TYPE (left) == AOP_ACC)
6086 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6087 FALSE, FALSE, FALSE));
6091 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6092 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6094 emitcode("mov", "b,a");
6098 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6099 emitcode ("xrl", "a,%s", rOp);
6102 aopPut (AOP (result), "a", offset);
6107 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6108 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6109 freeAsmop (result, NULL, ic, TRUE);
6112 /*-----------------------------------------------------------------*/
6113 /* genInline - write the inline code out */
6114 /*-----------------------------------------------------------------*/
6116 genInline (iCode * ic)
6118 char *buffer, *bp, *bp1;
6120 D (emitcode (";", "genInline ");
6123 _G.inLine += (!options.asmpeep);
6125 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6126 strcpy (buffer, IC_INLINE (ic));
6128 /* emit each line as a code */
6153 /* emitcode("",buffer); */
6154 _G.inLine -= (!options.asmpeep);
6157 /*-----------------------------------------------------------------*/
6158 /* genRRC - rotate right with carry */
6159 /*-----------------------------------------------------------------*/
6163 operand *left, *result;
6164 int size, offset = 0;
6167 D (emitcode (";", "genRRC ");
6170 /* rotate right with carry */
6171 left = IC_LEFT (ic);
6172 result = IC_RESULT (ic);
6173 aopOp (left, ic, FALSE, FALSE);
6174 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6176 /* move it to the result */
6177 size = AOP_SIZE (result);
6181 _startLazyDPSEvaluation ();
6184 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6186 emitcode ("rrc", "a");
6187 if (AOP_SIZE (result) > 1)
6188 aopPut (AOP (result), "a", offset--);
6190 _endLazyDPSEvaluation ();
6192 /* now we need to put the carry into the
6193 highest order byte of the result */
6194 if (AOP_SIZE (result) > 1)
6196 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6199 emitcode ("mov", "acc.7,c");
6200 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6201 freeAsmop (left, NULL, ic, TRUE);
6202 freeAsmop (result, NULL, ic, TRUE);
6205 /*-----------------------------------------------------------------*/
6206 /* genRLC - generate code for rotate left with carry */
6207 /*-----------------------------------------------------------------*/
6211 operand *left, *result;
6212 int size, offset = 0;
6215 D (emitcode (";", "genRLC ");
6218 /* rotate right with carry */
6219 left = IC_LEFT (ic);
6220 result = IC_RESULT (ic);
6221 aopOp (left, ic, FALSE, FALSE);
6222 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6224 /* move it to the result */
6225 size = AOP_SIZE (result);
6229 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6231 emitcode ("add", "a,acc");
6232 if (AOP_SIZE (result) > 1)
6234 aopPut (AOP (result), "a", offset++);
6237 _startLazyDPSEvaluation ();
6240 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6242 emitcode ("rlc", "a");
6243 if (AOP_SIZE (result) > 1)
6244 aopPut (AOP (result), "a", offset++);
6246 _endLazyDPSEvaluation ();
6248 /* now we need to put the carry into the
6249 highest order byte of the result */
6250 if (AOP_SIZE (result) > 1)
6252 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6255 emitcode ("mov", "acc.0,c");
6256 aopPut (AOP (result), "a", 0);
6257 freeAsmop (left, NULL, ic, TRUE);
6258 freeAsmop (result, NULL, ic, TRUE);
6261 /*-----------------------------------------------------------------*/
6262 /* genGetHbit - generates code get highest order bit */
6263 /*-----------------------------------------------------------------*/
6265 genGetHbit (iCode * ic)
6267 operand *left, *result;
6268 left = IC_LEFT (ic);
6269 result = IC_RESULT (ic);
6270 aopOp (left, ic, FALSE, FALSE);
6271 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6273 D (emitcode (";", "genGetHbit ");
6276 /* get the highest order byte into a */
6277 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6278 if (AOP_TYPE (result) == AOP_CRY)
6280 emitcode ("rlc", "a");
6285 emitcode ("rl", "a");
6286 emitcode ("anl", "a,#0x01");
6291 freeAsmop (left, NULL, ic, TRUE);
6292 freeAsmop (result, NULL, ic, TRUE);
6295 /*-----------------------------------------------------------------*/
6296 /* AccRol - rotate left accumulator by known count */
6297 /*-----------------------------------------------------------------*/
6299 AccRol (int shCount)
6301 shCount &= 0x0007; // shCount : 0..7
6308 emitcode ("rl", "a");
6311 emitcode ("rl", "a");
6312 emitcode ("rl", "a");
6315 emitcode ("swap", "a");
6316 emitcode ("rr", "a");
6319 emitcode ("swap", "a");
6322 emitcode ("swap", "a");
6323 emitcode ("rl", "a");
6326 emitcode ("rr", "a");
6327 emitcode ("rr", "a");
6330 emitcode ("rr", "a");
6335 /*-----------------------------------------------------------------*/
6336 /* AccLsh - left shift accumulator by known count */
6337 /*-----------------------------------------------------------------*/
6339 AccLsh (int shCount)
6344 emitcode ("add", "a,acc");
6345 else if (shCount == 2)
6347 emitcode ("add", "a,acc");
6348 emitcode ("add", "a,acc");
6352 /* rotate left accumulator */
6354 /* and kill the lower order bits */
6355 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6360 /*-----------------------------------------------------------------*/
6361 /* AccRsh - right shift accumulator by known count */
6362 /*-----------------------------------------------------------------*/
6364 AccRsh (int shCount)
6371 emitcode ("rrc", "a");
6375 /* rotate right accumulator */
6376 AccRol (8 - shCount);
6377 /* and kill the higher order bits */
6378 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6383 #ifdef BETTER_LITERAL_SHIFT
6384 /*-----------------------------------------------------------------*/
6385 /* AccSRsh - signed right shift accumulator by known count */
6386 /*-----------------------------------------------------------------*/
6388 AccSRsh (int shCount)
6395 emitcode ("mov", "c,acc.7");
6396 emitcode ("rrc", "a");
6398 else if (shCount == 2)
6400 emitcode ("mov", "c,acc.7");
6401 emitcode ("rrc", "a");
6402 emitcode ("mov", "c,acc.7");
6403 emitcode ("rrc", "a");
6407 tlbl = newiTempLabel (NULL);
6408 /* rotate right accumulator */
6409 AccRol (8 - shCount);
6410 /* and kill the higher order bits */
6411 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6412 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6413 emitcode ("orl", "a,#0x%02x",
6414 (unsigned char) ~SRMask[shCount]);
6415 emitcode ("", "%05d$:", tlbl->key + 100);
6421 #ifdef BETTER_LITERAL_SHIFT
6422 /*-----------------------------------------------------------------*/
6423 /* shiftR1Left2Result - shift right one byte from left to result */
6424 /*-----------------------------------------------------------------*/
6426 shiftR1Left2Result (operand * left, int offl,
6427 operand * result, int offr,
6428 int shCount, int sign)
6430 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6431 /* shift right accumulator */
6436 aopPut (AOP (result), "a", offr);
6440 #ifdef BETTER_LITERAL_SHIFT
6441 /*-----------------------------------------------------------------*/
6442 /* shiftL1Left2Result - shift left one byte from left to result */
6443 /*-----------------------------------------------------------------*/
6445 shiftL1Left2Result (operand * left, int offl,
6446 operand * result, int offr, int shCount)
6448 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6449 /* shift left accumulator */
6451 aopPut (AOP (result), "a", offr);
6455 #ifdef BETTER_LITERAL_SHIFT
6456 /*-----------------------------------------------------------------*/
6457 /* movLeft2Result - move byte from left to result */
6458 /*-----------------------------------------------------------------*/
6460 movLeft2Result (operand * left, int offl,
6461 operand * result, int offr, int sign)
6464 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6466 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6468 if (*l == '@' && (IS_AOP_PREG (result)))
6470 emitcode ("mov", "a,%s", l);
6471 aopPut (AOP (result), "a", offr);
6477 aopPut (AOP (result), l, offr);
6481 /* MSB sign in acc.7 ! */
6482 if (getDataSize (left) == offl + 1)
6484 emitcode ("mov", "a,%s", l);
6485 aopPut (AOP (result), "a", offr);
6493 #ifdef BETTER_LITERAL_SHIFT
6494 /*-----------------------------------------------------------------*/
6495 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6496 /*-----------------------------------------------------------------*/
6500 emitcode ("rrc", "a");
6501 emitcode ("xch", "a,%s", x);
6502 emitcode ("rrc", "a");
6503 emitcode ("xch", "a,%s", x);
6507 #ifdef BETTER_LITERAL_SHIFT
6509 /*-----------------------------------------------------------------*/
6510 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6511 /*-----------------------------------------------------------------*/
6515 emitcode ("xch", "a,%s", x);
6516 emitcode ("rlc", "a");
6517 emitcode ("xch", "a,%s", x);
6518 emitcode ("rlc", "a");
6522 #ifdef BETTER_LITERAL_SHIFT
6523 /*-----------------------------------------------------------------*/
6524 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6525 /*-----------------------------------------------------------------*/
6529 emitcode ("xch", "a,%s", x);
6530 emitcode ("add", "a,acc");
6531 emitcode ("xch", "a,%s", x);
6532 emitcode ("rlc", "a");
6536 #ifdef BETTER_LITERAL_SHIFT
6537 /*-----------------------------------------------------------------*/
6538 /* AccAXLsh - left shift a:x by known count (0..7) */
6539 /*-----------------------------------------------------------------*/
6541 AccAXLsh (char *x, int shCount)
6556 case 5: // AAAAABBB:CCCCCDDD
6558 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6560 emitcode ("anl", "a,#0x%02x",
6561 SLMask[shCount]); // BBB00000:CCCCCDDD
6563 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6565 AccRol (shCount); // DDDCCCCC:BBB00000
6567 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6569 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6571 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6573 emitcode ("anl", "a,#0x%02x",
6574 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6576 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6578 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6581 case 6: // AAAAAABB:CCCCCCDD
6582 emitcode ("anl", "a,#0x%02x",
6583 SRMask[shCount]); // 000000BB:CCCCCCDD
6584 emitcode ("mov", "c,acc.0"); // c = B
6585 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6587 AccAXRrl1 (x); // BCCCCCCD:D000000B
6588 AccAXRrl1 (x); // BBCCCCCC:DD000000
6590 emitcode("rrc","a");
6591 emitcode("xch","a,%s", x);
6592 emitcode("rrc","a");
6593 emitcode("mov","c,acc.0"); //<< get correct bit
6594 emitcode("xch","a,%s", x);
6596 emitcode("rrc","a");
6597 emitcode("xch","a,%s", x);
6598 emitcode("rrc","a");
6599 emitcode("xch","a,%s", x);
6602 case 7: // a:x <<= 7
6604 emitcode ("anl", "a,#0x%02x",
6605 SRMask[shCount]); // 0000000B:CCCCCCCD
6607 emitcode ("mov", "c,acc.0"); // c = B
6609 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6611 AccAXRrl1 (x); // BCCCCCCC:D0000000
6620 #ifdef BETTER_LITERAL_SHIFT
6622 /*-----------------------------------------------------------------*/
6623 /* AccAXRsh - right shift a:x known count (0..7) */
6624 /*-----------------------------------------------------------------*/
6626 AccAXRsh (char *x, int shCount)
6634 AccAXRrl1 (x); // 0->a:x
6639 AccAXRrl1 (x); // 0->a:x
6642 AccAXRrl1 (x); // 0->a:x
6647 case 5: // AAAAABBB:CCCCCDDD = a:x
6649 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6651 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6653 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6655 emitcode ("anl", "a,#0x%02x",
6656 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6658 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6660 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6662 emitcode ("anl", "a,#0x%02x",
6663 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6665 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6667 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6669 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6672 case 6: // AABBBBBB:CCDDDDDD
6674 emitcode ("mov", "c,acc.7");
6675 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6677 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6679 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6681 emitcode ("anl", "a,#0x%02x",
6682 SRMask[shCount]); // 000000AA:BBBBBBCC
6685 case 7: // ABBBBBBB:CDDDDDDD
6687 emitcode ("mov", "c,acc.7"); // c = A
6689 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6691 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6693 emitcode ("anl", "a,#0x%02x",
6694 SRMask[shCount]); // 0000000A:BBBBBBBC
6703 #ifdef BETTER_LITERAL_SHIFT
6704 /*-----------------------------------------------------------------*/
6705 /* AccAXRshS - right shift signed a:x known count (0..7) */
6706 /*-----------------------------------------------------------------*/
6708 AccAXRshS (char *x, int shCount)
6716 emitcode ("mov", "c,acc.7");
6717 AccAXRrl1 (x); // s->a:x
6721 emitcode ("mov", "c,acc.7");
6722 AccAXRrl1 (x); // s->a:x
6724 emitcode ("mov", "c,acc.7");
6725 AccAXRrl1 (x); // s->a:x
6730 case 5: // AAAAABBB:CCCCCDDD = a:x
6732 tlbl = newiTempLabel (NULL);
6733 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6735 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6737 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6739 emitcode ("anl", "a,#0x%02x",
6740 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6742 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6744 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6746 emitcode ("anl", "a,#0x%02x",
6747 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6749 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6751 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6753 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6755 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6756 emitcode ("orl", "a,#0x%02x",
6757 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6759 emitcode ("", "%05d$:", tlbl->key + 100);
6760 break; // SSSSAAAA:BBBCCCCC
6762 case 6: // AABBBBBB:CCDDDDDD
6764 tlbl = newiTempLabel (NULL);
6765 emitcode ("mov", "c,acc.7");
6766 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6768 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6770 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6772 emitcode ("anl", "a,#0x%02x",
6773 SRMask[shCount]); // 000000AA:BBBBBBCC
6775 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6776 emitcode ("orl", "a,#0x%02x",
6777 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6779 emitcode ("", "%05d$:", tlbl->key + 100);
6781 case 7: // ABBBBBBB:CDDDDDDD
6783 tlbl = newiTempLabel (NULL);
6784 emitcode ("mov", "c,acc.7"); // c = A
6786 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6788 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6790 emitcode ("anl", "a,#0x%02x",
6791 SRMask[shCount]); // 0000000A:BBBBBBBC
6793 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6794 emitcode ("orl", "a,#0x%02x",
6795 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6797 emitcode ("", "%05d$:", tlbl->key + 100);
6805 #ifdef BETTER_LITERAL_SHIFT
6807 _loadLeftIntoAx(char **lsb,
6813 // Get the initial value from left into a pair of registers.
6814 // MSB must be in A, LSB can be any register.
6816 // If the result is held in registers, it is an optimization
6817 // if the LSB can be held in the register which will hold the,
6818 // result LSB since this saves us from having to copy it into
6819 // the result following AccAXLsh.
6821 // If the result is addressed indirectly, this is not a gain.
6822 if (AOP_NEEDSACC(result))
6826 _startLazyDPSEvaluation();
6827 if (AOP_TYPE(left) == AOP_DPTR2)
6830 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6831 // get LSB in DP2_RESULT_REG.
6832 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6833 assert(!strcmp(leftByte, DP2_RESULT_REG));
6837 // get LSB into DP2_RESULT_REG
6838 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6839 if (strcmp(leftByte, DP2_RESULT_REG))
6842 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6845 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6846 assert(strcmp(leftByte, DP2_RESULT_REG));
6849 _endLazyDPSEvaluation();
6850 *lsb = DP2_RESULT_REG;
6854 if (sameRegs (AOP (result), AOP (left)) &&
6855 ((offl + MSB16) == offr))
6857 /* don't crash result[offr] */
6858 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6859 emitcode ("xch", "a,%s",
6860 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6864 movLeft2Result (left, offl, result, offr, 0);
6865 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6867 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6868 assert(strcmp(*lsb,"a"));
6873 _storeAxResults(char *lsb,
6877 _startLazyDPSEvaluation();
6878 if (AOP_NEEDSACC(result))
6880 /* We have to explicitly update the result LSB.
6882 emitcode("xch","a,%s", lsb);
6883 aopPut(AOP(result), "a", offr);
6884 emitcode("mov","a,%s", lsb);
6886 if (getDataSize (result) > 1)
6888 aopPut (AOP (result), "a", offr + MSB16);
6890 _endLazyDPSEvaluation();
6893 /*-----------------------------------------------------------------*/
6894 /* shiftL2Left2Result - shift left two bytes from left to result */
6895 /*-----------------------------------------------------------------*/
6897 shiftL2Left2Result (operand * left, int offl,
6898 operand * result, int offr, int shCount)
6902 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6904 AccAXLsh (lsb, shCount);
6906 _storeAxResults(lsb, result, offr);
6910 #ifdef BETTER_LITERAL_SHIFT
6911 /*-----------------------------------------------------------------*/
6912 /* shiftR2Left2Result - shift right two bytes from left to result */
6913 /*-----------------------------------------------------------------*/
6915 shiftR2Left2Result (operand * left, int offl,
6916 operand * result, int offr,
6917 int shCount, int sign)
6921 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6923 /* a:x >> shCount (x = lsb(result)) */
6926 AccAXRshS(lsb, shCount);
6930 AccAXRsh(lsb, shCount);
6933 _storeAxResults(lsb, result, offr);
6939 /*-----------------------------------------------------------------*/
6940 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6941 /*-----------------------------------------------------------------*/
6943 shiftLLeftOrResult (operand * left, int offl,
6944 operand * result, int offr, int shCount)
6946 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6947 /* shift left accumulator */
6949 /* or with result */
6950 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6951 /* back to result */
6952 aopPut (AOP (result), "a", offr);
6958 /*-----------------------------------------------------------------*/
6959 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6960 /*-----------------------------------------------------------------*/
6962 shiftRLeftOrResult (operand * left, int offl,
6963 operand * result, int offr, int shCount)
6965 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6966 /* shift right accumulator */
6968 /* or with result */
6969 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6970 /* back to result */
6971 aopPut (AOP (result), "a", offr);
6975 #ifdef BETTER_LITERAL_SHIFT
6976 /*-----------------------------------------------------------------*/
6977 /* genlshOne - left shift a one byte quantity by known count */
6978 /*-----------------------------------------------------------------*/
6980 genlshOne (operand * result, operand * left, int shCount)
6982 D (emitcode (";", "genlshOne "););
6983 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6987 #ifdef BETTER_LITERAL_SHIFT
6988 /*-----------------------------------------------------------------*/
6989 /* genlshTwo - left shift two bytes by known amount != 0 */
6990 /*-----------------------------------------------------------------*/
6992 genlshTwo (operand * result, operand * left, int shCount)
6996 D (emitcode (";", "genlshTwo "););
6998 size = getDataSize (result);
7000 /* if shCount >= 8 */
7005 _startLazyDPSEvaluation();
7011 _endLazyDPSEvaluation();
7012 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7013 aopPut (AOP (result), zero, LSB);
7017 movLeft2Result (left, LSB, result, MSB16, 0);
7018 aopPut (AOP (result), zero, LSB);
7019 _endLazyDPSEvaluation();
7024 aopPut (AOP (result), zero, LSB);
7025 _endLazyDPSEvaluation();
7029 /* 1 <= shCount <= 7 */
7034 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7038 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7046 /*-----------------------------------------------------------------*/
7047 /* shiftLLong - shift left one long from left to result */
7048 /* offl = LSB or MSB16 */
7049 /*-----------------------------------------------------------------*/
7051 shiftLLong (operand * left, operand * result, int offr)
7054 int size = AOP_SIZE (result);
7056 if (size >= LSB + offr)
7058 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7060 emitcode ("add", "a,acc");
7061 if (sameRegs (AOP (left), AOP (result)) &&
7062 size >= MSB16 + offr && offr != LSB)
7063 emitcode ("xch", "a,%s",
7064 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7066 aopPut (AOP (result), "a", LSB + offr);
7069 if (size >= MSB16 + offr)
7071 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7073 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7076 emitcode ("rlc", "a");
7077 if (sameRegs (AOP (left), AOP (result)) &&
7078 size >= MSB24 + offr && offr != LSB)
7079 emitcode ("xch", "a,%s",
7080 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7082 aopPut (AOP (result), "a", MSB16 + offr);
7085 if (size >= MSB24 + offr)
7087 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7089 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7092 emitcode ("rlc", "a");
7093 if (sameRegs (AOP (left), AOP (result)) &&
7094 size >= MSB32 + offr && offr != LSB)
7095 emitcode ("xch", "a,%s",
7096 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7098 aopPut (AOP (result), "a", MSB24 + offr);
7101 if (size > MSB32 + offr)
7103 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7105 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7108 emitcode ("rlc", "a");
7109 aopPut (AOP (result), "a", MSB32 + offr);
7112 aopPut (AOP (result), zero, LSB);
7118 /*-----------------------------------------------------------------*/
7119 /* genlshFour - shift four byte by a known amount != 0 */
7120 /*-----------------------------------------------------------------*/
7122 genlshFour (operand * result, operand * left, int shCount)
7126 D (emitcode (";", "genlshFour ");
7129 size = AOP_SIZE (result);
7131 /* if shifting more that 3 bytes */
7136 /* lowest order of left goes to the highest
7137 order of the destination */
7138 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7140 movLeft2Result (left, LSB, result, MSB32, 0);
7141 aopPut (AOP (result), zero, LSB);
7142 aopPut (AOP (result), zero, MSB16);
7143 aopPut (AOP (result), zero, MSB24);
7147 /* more than two bytes */
7148 else if (shCount >= 16)
7150 /* lower order two bytes goes to higher order two bytes */
7152 /* if some more remaining */
7154 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7157 movLeft2Result (left, MSB16, result, MSB32, 0);
7158 movLeft2Result (left, LSB, result, MSB24, 0);
7160 aopPut (AOP (result), zero, MSB16);
7161 aopPut (AOP (result), zero, LSB);
7165 /* if more than 1 byte */
7166 else if (shCount >= 8)
7168 /* lower order three bytes goes to higher order three bytes */
7173 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7175 movLeft2Result (left, LSB, result, MSB16, 0);
7181 movLeft2Result (left, MSB24, result, MSB32, 0);
7182 movLeft2Result (left, MSB16, result, MSB24, 0);
7183 movLeft2Result (left, LSB, result, MSB16, 0);
7184 aopPut (AOP (result), zero, LSB);
7186 else if (shCount == 1)
7187 shiftLLong (left, result, MSB16);
7190 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7191 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7192 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7193 aopPut (AOP (result), zero, LSB);
7198 /* 1 <= shCount <= 7 */
7199 else if (shCount <= 2)
7201 shiftLLong (left, result, LSB);
7203 shiftLLong (result, result, LSB);
7205 /* 3 <= shCount <= 7, optimize */
7208 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7209 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7210 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7215 #ifdef BETTER_LITERAL_SHIFT
7216 /*-----------------------------------------------------------------*/
7217 /* genLeftShiftLiteral - left shifting by known count */
7218 /*-----------------------------------------------------------------*/
7220 genLeftShiftLiteral (operand * left,
7225 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7228 size = getSize (operandType (result));
7230 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7232 /* We only handle certain easy cases so far. */
7234 && (shCount < (size * 8))
7238 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7242 freeAsmop (right, NULL, ic, TRUE);
7244 aopOp(left, ic, FALSE, FALSE);
7245 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7248 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7250 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7251 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7253 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7256 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7258 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7259 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7261 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7267 emitcode ("; shift left ", "result %d, left %d", size,
7271 /* I suppose that the left size >= result size */
7274 _startLazyDPSEvaluation();
7277 movLeft2Result (left, size, result, size, 0);
7279 _endLazyDPSEvaluation();
7281 else if (shCount >= (size * 8))
7283 _startLazyDPSEvaluation();
7286 aopPut (AOP (result), zero, size);
7288 _endLazyDPSEvaluation();
7295 genlshOne (result, left, shCount);
7299 genlshTwo (result, left, shCount);
7303 genlshFour (result, left, shCount);
7307 fprintf(stderr, "*** ack! mystery literal shift!\n");
7311 freeAsmop (left, NULL, ic, TRUE);
7312 freeAsmop (result, NULL, ic, TRUE);
7317 /*-----------------------------------------------------------------*/
7318 /* genLeftShift - generates code for left shifting */
7319 /*-----------------------------------------------------------------*/
7321 genLeftShift (iCode * ic)
7323 operand *left, *right, *result;
7326 symbol *tlbl, *tlbl1;
7328 D (emitcode (";", "genLeftShift "););
7330 right = IC_RIGHT (ic);
7331 left = IC_LEFT (ic);
7332 result = IC_RESULT (ic);
7334 aopOp (right, ic, FALSE, FALSE);
7337 #ifdef BETTER_LITERAL_SHIFT
7338 /* if the shift count is known then do it
7339 as efficiently as possible */
7340 if (AOP_TYPE (right) == AOP_LIT)
7342 if (genLeftShiftLiteral (left, right, result, ic))
7349 /* shift count is unknown then we have to form
7350 a loop get the loop count in B : Note: we take
7351 only the lower order byte since shifting
7352 more that 32 bits make no sense anyway, ( the
7353 largest size of an object can be only 32 bits ) */
7355 if (AOP_TYPE (right) == AOP_LIT)
7357 /* Really should be handled by genLeftShiftLiteral,
7358 * but since I'm too lazy to fix that today, at least we can make
7359 * some small improvement.
7361 emitcode("mov", "b,#0x%02x",
7362 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7366 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7367 emitcode ("inc", "b");
7369 freeAsmop (right, NULL, ic, TRUE);
7370 aopOp (left, ic, FALSE, FALSE);
7371 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7373 /* now move the left to the result if they are not the
7375 if (!sameRegs (AOP (left), AOP (result)) &&
7376 AOP_SIZE (result) > 1)
7379 size = AOP_SIZE (result);
7381 _startLazyDPSEvaluation ();
7384 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7385 if (*l == '@' && (IS_AOP_PREG (result)))
7388 emitcode ("mov", "a,%s", l);
7389 aopPut (AOP (result), "a", offset);
7392 aopPut (AOP (result), l, offset);
7395 _endLazyDPSEvaluation ();
7398 tlbl = newiTempLabel (NULL);
7399 size = AOP_SIZE (result);
7401 tlbl1 = newiTempLabel (NULL);
7403 /* if it is only one byte then */
7406 symbol *tlbl1 = newiTempLabel (NULL);
7408 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7410 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7411 emitcode ("", "%05d$:", tlbl->key + 100);
7412 emitcode ("add", "a,acc");
7413 emitcode ("", "%05d$:", tlbl1->key + 100);
7414 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7415 aopPut (AOP (result), "a", 0);
7419 reAdjustPreg (AOP (result));
7421 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7422 emitcode ("", "%05d$:", tlbl->key + 100);
7423 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7425 emitcode ("add", "a,acc");
7426 aopPut (AOP (result), "a", offset++);
7427 _startLazyDPSEvaluation ();
7430 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7432 emitcode ("rlc", "a");
7433 aopPut (AOP (result), "a", offset++);
7435 _endLazyDPSEvaluation ();
7436 reAdjustPreg (AOP (result));
7438 emitcode ("", "%05d$:", tlbl1->key + 100);
7439 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7441 freeAsmop (left, NULL, ic, TRUE);
7442 freeAsmop (result, NULL, ic, TRUE);
7445 #ifdef BETTER_LITERAL_SHIFT
7446 /*-----------------------------------------------------------------*/
7447 /* genrshOne - right shift a one byte quantity by known count */
7448 /*-----------------------------------------------------------------*/
7450 genrshOne (operand * result, operand * left,
7451 int shCount, int sign)
7453 D (emitcode (";", "genrshOne"););
7454 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7458 #ifdef BETTER_LITERAL_SHIFT
7459 /*-----------------------------------------------------------------*/
7460 /* genrshTwo - right shift two bytes by known amount != 0 */
7461 /*-----------------------------------------------------------------*/
7463 genrshTwo (operand * result, operand * left,
7464 int shCount, int sign)
7466 D (emitcode (";", "genrshTwo"););
7468 /* if shCount >= 8 */
7472 _startLazyDPSEvaluation();
7475 shiftR1Left2Result (left, MSB16, result, LSB,
7480 movLeft2Result (left, MSB16, result, LSB, sign);
7482 addSign (result, MSB16, sign);
7483 _endLazyDPSEvaluation();
7486 /* 1 <= shCount <= 7 */
7489 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7496 /*-----------------------------------------------------------------*/
7497 /* shiftRLong - shift right one long from left to result */
7498 /* offl = LSB or MSB16 */
7499 /*-----------------------------------------------------------------*/
7501 shiftRLong (operand * left, int offl,
7502 operand * result, int sign)
7504 int isSameRegs=sameRegs(AOP(left),AOP(result));
7506 if (isSameRegs && offl>1) {
7507 // we are in big trouble, but this shouldn't happen
7508 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7511 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7516 emitcode ("rlc", "a");
7517 emitcode ("subb", "a,acc");
7518 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7520 aopPut (AOP(result), zero, MSB32);
7525 emitcode ("clr", "c");
7527 emitcode ("mov", "c,acc.7");
7530 emitcode ("rrc", "a");
7532 if (isSameRegs && offl==MSB16) {
7533 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7535 aopPut (AOP (result), "a", MSB32);
7536 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7539 emitcode ("rrc", "a");
7540 if (isSameRegs && offl==1) {
7541 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7543 aopPut (AOP (result), "a", MSB24);
7544 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7546 emitcode ("rrc", "a");
7547 aopPut (AOP (result), "a", MSB16 - offl);
7551 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7552 emitcode ("rrc", "a");
7553 aopPut (AOP (result), "a", LSB);
7560 /*-----------------------------------------------------------------*/
7561 /* genrshFour - shift four byte by a known amount != 0 */
7562 /*-----------------------------------------------------------------*/
7564 genrshFour (operand * result, operand * left,
7565 int shCount, int sign)
7567 D (emitcode (";", "genrshFour");
7570 /* if shifting more that 3 bytes */
7575 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7577 movLeft2Result (left, MSB32, result, LSB, sign);
7578 addSign (result, MSB16, sign);
7580 else if (shCount >= 16)
7584 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7587 movLeft2Result (left, MSB24, result, LSB, 0);
7588 movLeft2Result (left, MSB32, result, MSB16, sign);
7590 addSign (result, MSB24, sign);
7592 else if (shCount >= 8)
7596 shiftRLong (left, MSB16, result, sign);
7597 else if (shCount == 0)
7599 movLeft2Result (left, MSB16, result, LSB, 0);
7600 movLeft2Result (left, MSB24, result, MSB16, 0);
7601 movLeft2Result (left, MSB32, result, MSB24, sign);
7602 addSign (result, MSB32, sign);
7606 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7607 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7608 /* the last shift is signed */
7609 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7610 addSign (result, MSB32, sign);
7614 { /* 1 <= shCount <= 7 */
7617 shiftRLong (left, LSB, result, sign);
7619 shiftRLong (result, LSB, result, sign);
7623 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7624 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7625 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7631 #ifdef BETTER_LITERAL_SHIFT
7632 /*-----------------------------------------------------------------*/
7633 /* genRightShiftLiteral - right shifting by known count */
7634 /*-----------------------------------------------------------------*/
7636 genRightShiftLiteral (operand * left,
7642 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7645 size = getSize (operandType (result));
7647 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7649 /* We only handle certain easy cases so far. */
7651 && (shCount < (size * 8))
7655 D(emitcode (";", "genRightShiftLiteral wimping out"););
7659 freeAsmop (right, NULL, ic, TRUE);
7661 aopOp (left, ic, FALSE, FALSE);
7662 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7665 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7669 /* test the LEFT size !!! */
7671 /* I suppose that the left size >= result size */
7674 size = getDataSize (result);
7675 _startLazyDPSEvaluation();
7678 movLeft2Result (left, size, result, size, 0);
7680 _endLazyDPSEvaluation();
7682 else if (shCount >= (size * 8))
7686 /* get sign in acc.7 */
7687 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7689 addSign (result, LSB, sign);
7696 genrshOne (result, left, shCount, sign);
7700 genrshTwo (result, left, shCount, sign);
7704 genrshFour (result, left, shCount, sign);
7711 freeAsmop (left, NULL, ic, TRUE);
7712 freeAsmop (result, NULL, ic, TRUE);
7718 /*-----------------------------------------------------------------*/
7719 /* genSignedRightShift - right shift of signed number */
7720 /*-----------------------------------------------------------------*/
7722 genSignedRightShift (iCode * ic)
7724 operand *right, *left, *result;
7727 symbol *tlbl, *tlbl1;
7729 D (emitcode (";", "genSignedRightShift "););
7731 /* we do it the hard way put the shift count in b
7732 and loop thru preserving the sign */
7734 right = IC_RIGHT (ic);
7735 left = IC_LEFT (ic);
7736 result = IC_RESULT (ic);
7738 aopOp (right, ic, FALSE, FALSE);
7740 #ifdef BETTER_LITERAL_SHIFT
7741 if (AOP_TYPE (right) == AOP_LIT)
7743 if (genRightShiftLiteral (left, right, result, ic, 1))
7749 /* shift count is unknown then we have to form
7750 a loop get the loop count in B : Note: we take
7751 only the lower order byte since shifting
7752 more that 32 bits make no sense anyway, ( the
7753 largest size of an object can be only 32 bits ) */
7755 if (AOP_TYPE (right) == AOP_LIT)
7757 /* Really should be handled by genRightShiftLiteral,
7758 * but since I'm too lazy to fix that today, at least we can make
7759 * some small improvement.
7761 emitcode("mov", "b,#0x%02x",
7762 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7766 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7767 emitcode ("inc", "b");
7769 freeAsmop (right, NULL, ic, TRUE);
7770 aopOp (left, ic, FALSE, FALSE);
7771 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7773 /* now move the left to the result if they are not the
7775 if (!sameRegs (AOP (left), AOP (result)) &&
7776 AOP_SIZE (result) > 1)
7779 size = AOP_SIZE (result);
7781 _startLazyDPSEvaluation ();
7784 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7785 if (*l == '@' && IS_AOP_PREG (result))
7788 emitcode ("mov", "a,%s", l);
7789 aopPut (AOP (result), "a", offset);
7792 aopPut (AOP (result), l, offset);
7795 _endLazyDPSEvaluation ();
7798 /* mov the highest order bit to OVR */
7799 tlbl = newiTempLabel (NULL);
7800 tlbl1 = newiTempLabel (NULL);
7802 size = AOP_SIZE (result);
7804 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7805 emitcode ("rlc", "a");
7806 emitcode ("mov", "ov,c");
7807 /* if it is only one byte then */
7810 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7812 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7813 emitcode ("", "%05d$:", tlbl->key + 100);
7814 emitcode ("mov", "c,ov");
7815 emitcode ("rrc", "a");
7816 emitcode ("", "%05d$:", tlbl1->key + 100);
7817 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7818 aopPut (AOP (result), "a", 0);
7822 reAdjustPreg (AOP (result));
7823 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7824 emitcode ("", "%05d$:", tlbl->key + 100);
7825 emitcode ("mov", "c,ov");
7826 _startLazyDPSEvaluation ();
7829 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7831 emitcode ("rrc", "a");
7832 aopPut (AOP (result), "a", offset--);
7834 _endLazyDPSEvaluation ();
7835 reAdjustPreg (AOP (result));
7836 emitcode ("", "%05d$:", tlbl1->key + 100);
7837 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7840 freeAsmop (left, NULL, ic, TRUE);
7841 freeAsmop (result, NULL, ic, TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* genRightShift - generate code for right shifting */
7846 /*-----------------------------------------------------------------*/
7848 genRightShift (iCode * ic)
7850 operand *right, *left, *result;
7854 symbol *tlbl, *tlbl1;
7856 D (emitcode (";", "genRightShift "););
7858 /* if signed then we do it the hard way preserve the
7859 sign bit moving it inwards */
7860 retype = getSpec (operandType (IC_RESULT (ic)));
7862 if (!SPEC_USIGN (retype))
7864 genSignedRightShift (ic);
7868 /* signed & unsigned types are treated the same : i.e. the
7869 signed is NOT propagated inwards : quoting from the
7870 ANSI - standard : "for E1 >> E2, is equivalent to division
7871 by 2**E2 if unsigned or if it has a non-negative value,
7872 otherwise the result is implementation defined ", MY definition
7873 is that the sign does not get propagated */
7875 right = IC_RIGHT (ic);
7876 left = IC_LEFT (ic);
7877 result = IC_RESULT (ic);
7879 aopOp (right, ic, FALSE, FALSE);
7881 #ifdef BETTER_LITERAL_SHIFT
7882 /* if the shift count is known then do it
7883 as efficiently as possible */
7884 if (AOP_TYPE (right) == AOP_LIT)
7886 if (genRightShiftLiteral (left, right, result, ic, 0))
7893 /* shift count is unknown then we have to form
7894 a loop get the loop count in B : Note: we take
7895 only the lower order byte since shifting
7896 more that 32 bits make no sense anyway, ( the
7897 largest size of an object can be only 32 bits ) */
7899 if (AOP_TYPE (right) == AOP_LIT)
7901 /* Really should be handled by genRightShiftLiteral,
7902 * but since I'm too lazy to fix that today, at least we can make
7903 * some small improvement.
7905 emitcode("mov", "b,#0x%02x",
7906 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7910 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7911 emitcode ("inc", "b");
7913 freeAsmop (right, NULL, ic, TRUE);
7914 aopOp (left, ic, FALSE, FALSE);
7915 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7917 /* now move the left to the result if they are not the
7919 if (!sameRegs (AOP (left), AOP (result)) &&
7920 AOP_SIZE (result) > 1)
7923 size = AOP_SIZE (result);
7925 _startLazyDPSEvaluation ();
7928 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7929 if (*l == '@' && IS_AOP_PREG (result))
7932 emitcode ("mov", "a,%s", l);
7933 aopPut (AOP (result), "a", offset);
7936 aopPut (AOP (result), l, offset);
7939 _endLazyDPSEvaluation ();
7942 tlbl = newiTempLabel (NULL);
7943 tlbl1 = newiTempLabel (NULL);
7944 size = AOP_SIZE (result);
7947 /* if it is only one byte then */
7950 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7952 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7953 emitcode ("", "%05d$:", tlbl->key + 100);
7955 emitcode ("rrc", "a");
7956 emitcode ("", "%05d$:", tlbl1->key + 100);
7957 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7958 aopPut (AOP (result), "a", 0);
7962 reAdjustPreg (AOP (result));
7963 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7964 emitcode ("", "%05d$:", tlbl->key + 100);
7966 _startLazyDPSEvaluation ();
7969 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7971 emitcode ("rrc", "a");
7972 aopPut (AOP (result), "a", offset--);
7974 _endLazyDPSEvaluation ();
7975 reAdjustPreg (AOP (result));
7977 emitcode ("", "%05d$:", tlbl1->key + 100);
7978 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7981 freeAsmop (left, NULL, ic, TRUE);
7982 freeAsmop (result, NULL, ic, TRUE);
7985 /*-----------------------------------------------------------------*/
7986 /* genUnpackBits - generates code for unpacking bits */
7987 /*-----------------------------------------------------------------*/
7989 genUnpackBits (operand * result, char *rname, int ptype)
7996 D (emitcode (";", "genUnpackBits ");
7999 etype = getSpec (operandType (result));
8001 /* read the first byte */
8007 emitcode ("mov", "a,@%s", rname);
8011 emitcode ("movx", "a,@%s", rname);
8015 emitcode ("movx", "a,@dptr");
8019 emitcode ("clr", "a");
8020 emitcode ("movc", "a,@a+dptr");
8024 emitcode ("lcall", "__gptrget");
8028 /* if we have bitdisplacement then it fits */
8029 /* into this byte completely or if length is */
8030 /* less than a byte */
8031 if ((shCnt = SPEC_BSTR (etype)) ||
8032 (SPEC_BLEN (etype) <= 8))
8035 /* shift right acc */
8038 emitcode ("anl", "a,#0x%02x",
8039 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8040 aopPut (AOP (result), "a", offset);
8044 /* bit field did not fit in a byte */
8045 rlen = SPEC_BLEN (etype) - 8;
8046 aopPut (AOP (result), "a", offset++);
8055 emitcode ("inc", "%s", rname);
8056 emitcode ("mov", "a,@%s", rname);
8060 emitcode ("inc", "%s", rname);
8061 emitcode ("movx", "a,@%s", rname);
8065 emitcode ("inc", "dptr");
8066 emitcode ("movx", "a,@dptr");
8070 emitcode ("clr", "a");
8071 emitcode ("inc", "dptr");
8072 emitcode ("movc", "a,@a+dptr");
8076 emitcode ("inc", "dptr");
8077 emitcode ("lcall", "__gptrget");
8082 /* if we are done */
8086 aopPut (AOP (result), "a", offset++);
8092 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8093 aopPut (AOP (result), "a", offset);
8100 /*-----------------------------------------------------------------*/
8101 /* genDataPointerGet - generates code when ptr offset is known */
8102 /*-----------------------------------------------------------------*/
8104 genDataPointerGet (operand * left,
8110 int size, offset = 0;
8111 aopOp (result, ic, TRUE, FALSE);
8113 /* get the string representation of the name */
8114 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8115 size = AOP_SIZE (result);
8116 _startLazyDPSEvaluation ();
8120 sprintf (buffer, "(%s + %d)", l + 1, offset);
8122 sprintf (buffer, "%s", l + 1);
8123 aopPut (AOP (result), buffer, offset++);
8125 _endLazyDPSEvaluation ();
8127 freeAsmop (left, NULL, ic, TRUE);
8128 freeAsmop (result, NULL, ic, TRUE);
8131 /*-----------------------------------------------------------------*/
8132 /* genNearPointerGet - emitcode for near pointer fetch */
8133 /*-----------------------------------------------------------------*/
8135 genNearPointerGet (operand * left,
8142 sym_link *rtype, *retype, *letype;
8143 sym_link *ltype = operandType (left);
8146 rtype = operandType (result);
8147 retype = getSpec (rtype);
8148 letype = getSpec (ltype);
8150 aopOp (left, ic, FALSE, FALSE);
8152 /* if left is rematerialisable and
8153 result is not bit variable type and
8154 the left is pointer to data space i.e
8155 lower 128 bytes of space */
8156 if (AOP_TYPE (left) == AOP_IMMD &&
8157 !IS_BITVAR (retype) &&
8158 !IS_BITVAR (letype) &&
8159 DCL_TYPE (ltype) == POINTER)
8161 genDataPointerGet (left, result, ic);
8165 /* if the value is already in a pointer register
8166 then don't need anything more */
8167 if (!AOP_INPREG (AOP (left)))
8169 /* otherwise get a free pointer register */
8171 preg = getFreePtr (ic, &aop, FALSE);
8172 emitcode ("mov", "%s,%s",
8174 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8178 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8180 freeAsmop (left, NULL, ic, TRUE);
8181 aopOp (result, ic, FALSE, FALSE);
8183 /* if bitfield then unpack the bits */
8184 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8185 genUnpackBits (result, rname, POINTER);
8188 /* we have can just get the values */
8189 int size = AOP_SIZE (result);
8194 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8197 emitcode ("mov", "a,@%s", rname);
8198 aopPut (AOP (result), "a", offset);
8202 sprintf (buffer, "@%s", rname);
8203 aopPut (AOP (result), buffer, offset);
8207 emitcode ("inc", "%s", rname);
8211 /* now some housekeeping stuff */
8214 /* we had to allocate for this iCode */
8215 freeAsmop (NULL, aop, ic, TRUE);
8219 /* we did not allocate which means left
8220 already in a pointer register, then
8221 if size > 0 && this could be used again
8222 we have to point it back to where it
8224 if (AOP_SIZE (result) > 1 &&
8225 !OP_SYMBOL (left)->remat &&
8226 (OP_SYMBOL (left)->liveTo > ic->seq ||
8229 int size = AOP_SIZE (result) - 1;
8231 emitcode ("dec", "%s", rname);
8236 freeAsmop (result, NULL, ic, TRUE);
8240 /*-----------------------------------------------------------------*/
8241 /* genPagedPointerGet - emitcode for paged pointer fetch */
8242 /*-----------------------------------------------------------------*/
8244 genPagedPointerGet (operand * left,
8251 sym_link *rtype, *retype, *letype;
8253 rtype = operandType (result);
8254 retype = getSpec (rtype);
8255 letype = getSpec (operandType (left));
8256 aopOp (left, ic, FALSE, FALSE);
8258 /* if the value is already in a pointer register
8259 then don't need anything more */
8260 if (!AOP_INPREG (AOP (left)))
8262 /* otherwise get a free pointer register */
8264 preg = getFreePtr (ic, &aop, FALSE);
8265 emitcode ("mov", "%s,%s",
8267 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8271 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8273 freeAsmop (left, NULL, ic, TRUE);
8274 aopOp (result, ic, FALSE, FALSE);
8276 /* if bitfield then unpack the bits */
8277 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8278 genUnpackBits (result, rname, PPOINTER);
8281 /* we have can just get the values */
8282 int size = AOP_SIZE (result);
8288 emitcode ("movx", "a,@%s", rname);
8289 aopPut (AOP (result), "a", offset);
8294 emitcode ("inc", "%s", rname);
8298 /* now some housekeeping stuff */
8301 /* we had to allocate for this iCode */
8302 freeAsmop (NULL, aop, ic, TRUE);
8306 /* we did not allocate which means left
8307 already in a pointer register, then
8308 if size > 0 && this could be used again
8309 we have to point it back to where it
8311 if (AOP_SIZE (result) > 1 &&
8312 !OP_SYMBOL (left)->remat &&
8313 (OP_SYMBOL (left)->liveTo > ic->seq ||
8316 int size = AOP_SIZE (result) - 1;
8318 emitcode ("dec", "%s", rname);
8323 freeAsmop (result, NULL, ic, TRUE);
8328 /*-----------------------------------------------------------------*/
8329 /* genFarPointerGet - gget value from far space */
8330 /*-----------------------------------------------------------------*/
8332 genFarPointerGet (operand * left,
8333 operand * result, iCode * ic)
8336 sym_link *retype = getSpec (operandType (result));
8337 sym_link *letype = getSpec (operandType (left));
8338 D (emitcode (";", "genFarPointerGet");
8341 aopOp (left, ic, FALSE, FALSE);
8343 /* if the operand is already in dptr
8344 then we do nothing else we move the value to dptr */
8345 if (AOP_TYPE (left) != AOP_STR)
8347 /* if this is remateriazable */
8348 if (AOP_TYPE (left) == AOP_IMMD)
8350 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8354 /* we need to get it byte by byte */
8355 _startLazyDPSEvaluation ();
8356 if (AOP_TYPE (left) != AOP_DPTR)
8358 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8359 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8360 if (options.model == MODEL_FLAT24)
8361 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8365 /* We need to generate a load to DPTR indirect through DPTR. */
8366 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8368 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8369 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8370 if (options.model == MODEL_FLAT24)
8371 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8372 emitcode ("pop", "dph");
8373 emitcode ("pop", "dpl");
8375 _endLazyDPSEvaluation ();
8378 /* so dptr know contains the address */
8379 freeAsmop (left, NULL, ic, TRUE);
8380 aopOp (result, ic, FALSE, TRUE);
8382 /* if bit then unpack */
8383 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8384 genUnpackBits (result, "dptr", FPOINTER);
8387 size = AOP_SIZE (result);
8390 _startLazyDPSEvaluation ();
8397 emitcode ("movx", "a,@dptr");
8399 emitcode ("inc", "dptr");
8401 aopPut (AOP (result), "a", offset++);
8403 _endLazyDPSEvaluation ();
8406 freeAsmop (result, NULL, ic, TRUE);
8409 /*-----------------------------------------------------------------*/
8410 /* emitcodePointerGet - gget value from code space */
8411 /*-----------------------------------------------------------------*/
8413 emitcodePointerGet (operand * left,
8414 operand * result, iCode * ic)
8417 sym_link *retype = getSpec (operandType (result));
8419 aopOp (left, ic, FALSE, FALSE);
8421 /* if the operand is already in dptr
8422 then we do nothing else we move the value to dptr */
8423 if (AOP_TYPE (left) != AOP_STR)
8425 /* if this is remateriazable */
8426 if (AOP_TYPE (left) == AOP_IMMD)
8428 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8431 { /* we need to get it byte by byte */
8432 _startLazyDPSEvaluation ();
8433 if (AOP_TYPE (left) != AOP_DPTR)
8435 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8436 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8437 if (options.model == MODEL_FLAT24)
8438 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8442 /* We need to generate a load to DPTR indirect through DPTR. */
8443 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8445 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8446 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8447 if (options.model == MODEL_FLAT24)
8448 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8449 emitcode ("pop", "dph");
8450 emitcode ("pop", "dpl");
8452 _endLazyDPSEvaluation ();
8455 /* so dptr know contains the address */
8456 freeAsmop (left, NULL, ic, TRUE);
8457 aopOp (result, ic, FALSE, TRUE);
8459 /* if bit then unpack */
8460 if (IS_BITVAR (retype))
8461 genUnpackBits (result, "dptr", CPOINTER);
8464 size = AOP_SIZE (result);
8467 _startLazyDPSEvaluation ();
8473 emitcode ("clr", "a");
8474 emitcode ("movc", "a,@a+dptr");
8476 emitcode ("inc", "dptr");
8477 aopPut (AOP (result), "a", offset++);
8479 _endLazyDPSEvaluation ();
8482 freeAsmop (result, NULL, ic, TRUE);
8485 /*-----------------------------------------------------------------*/
8486 /* genGenPointerGet - gget value from generic pointer space */
8487 /*-----------------------------------------------------------------*/
8489 genGenPointerGet (operand * left,
8490 operand * result, iCode * ic)
8493 sym_link *retype = getSpec (operandType (result));
8494 sym_link *letype = getSpec (operandType (left));
8496 D (emitcode (";", "genGenPointerGet "); );
8498 aopOp (left, ic, FALSE, TRUE);
8500 /* if the operand is already in dptr
8501 then we do nothing else we move the value to dptr */
8502 if (AOP_TYPE (left) != AOP_STR)
8504 /* if this is remateriazable */
8505 if (AOP_TYPE (left) == AOP_IMMD)
8507 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8508 emitcode ("mov", "b,#%d", pointerCode (retype));
8511 { /* we need to get it byte by byte */
8512 _startLazyDPSEvaluation ();
8513 if (AOP(left)->type==AOP_DPTR2) {
8515 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8518 emitcode ("mov", "dpl,%s", l);
8519 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8522 emitcode ("mov", "dph,%s", l);
8523 if (options.model == MODEL_FLAT24) {
8524 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8527 emitcode ("mov", "dpx,%s", l);
8528 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8530 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8533 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8534 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8535 if (options.model == MODEL_FLAT24) {
8536 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8537 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8539 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8542 _endLazyDPSEvaluation ();
8545 /* so dptr know contains the address */
8546 freeAsmop (left, NULL, ic, TRUE);
8547 aopOp (result, ic, FALSE, TRUE);
8549 /* if bit then unpack */
8550 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8551 genUnpackBits (result, "dptr", GPOINTER);
8554 size = AOP_SIZE (result);
8559 emitcode ("lcall", "__gptrget");
8560 aopPut (AOP (result), "a", offset++);
8562 emitcode ("inc", "dptr");
8566 freeAsmop (result, NULL, ic, TRUE);
8569 /*-----------------------------------------------------------------*/
8570 /* genPointerGet - generate code for pointer get */
8571 /*-----------------------------------------------------------------*/
8573 genPointerGet (iCode * ic)
8575 operand *left, *result;
8576 sym_link *type, *etype;
8579 D (emitcode (";", "genPointerGet ");
8582 left = IC_LEFT (ic);
8583 result = IC_RESULT (ic);
8585 /* depending on the type of pointer we need to
8586 move it to the correct pointer register */
8587 type = operandType (left);
8588 etype = getSpec (type);
8589 /* if left is of type of pointer then it is simple */
8590 if (IS_PTR (type) && !IS_FUNC (type->next))
8591 p_type = DCL_TYPE (type);
8594 /* we have to go by the storage class */
8595 p_type = PTR_TYPE (SPEC_OCLS (etype));
8598 /* now that we have the pointer type we assign
8599 the pointer values */
8605 genNearPointerGet (left, result, ic);
8609 genPagedPointerGet (left, result, ic);
8613 genFarPointerGet (left, result, ic);
8617 emitcodePointerGet (left, result, ic);
8621 genGenPointerGet (left, result, ic);
8627 /*-----------------------------------------------------------------*/
8628 /* genPackBits - generates code for packed bit storage */
8629 /*-----------------------------------------------------------------*/
8631 genPackBits (sym_link * etype,
8633 char *rname, int p_type)
8641 blen = SPEC_BLEN (etype);
8642 bstr = SPEC_BSTR (etype);
8644 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8647 /* if the bit lenth is less than or */
8648 /* it exactly fits a byte then */
8649 if (SPEC_BLEN (etype) <= 8)
8651 shCount = SPEC_BSTR (etype);
8653 /* shift left acc */
8656 if (SPEC_BLEN (etype) < 8)
8657 { /* if smaller than a byte */
8663 emitcode ("mov", "b,a");
8664 emitcode ("mov", "a,@%s", rname);
8668 emitcode ("mov", "b,a");
8669 emitcode ("movx", "a,@dptr");
8673 emitcode ("push", "b");
8674 emitcode ("push", "acc");
8675 emitcode ("lcall", "__gptrget");
8676 emitcode ("pop", "b");
8680 emitcode ("anl", "a,#0x%02x", (unsigned char)
8681 ((unsigned char) (0xFF << (blen + bstr)) |
8682 (unsigned char) (0xFF >> (8 - bstr))));
8683 emitcode ("orl", "a,b");
8684 if (p_type == GPOINTER)
8685 emitcode ("pop", "b");
8692 emitcode ("mov", "@%s,a", rname);
8696 emitcode ("movx", "@dptr,a");
8700 emitcode ("lcall", "__gptrput");
8705 if (SPEC_BLEN (etype) <= 8)
8708 emitcode ("inc", "%s", rname);
8709 rLen = SPEC_BLEN (etype);
8711 /* now generate for lengths greater than one byte */
8715 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8727 emitcode ("mov", "@%s,a", rname);
8730 emitcode ("mov", "@%s,%s", rname, l);
8735 emitcode ("movx", "@dptr,a");
8740 emitcode ("lcall", "__gptrput");
8743 emitcode ("inc", "%s", rname);
8748 /* last last was not complete */
8751 /* save the byte & read byte */
8755 emitcode ("mov", "b,a");
8756 emitcode ("mov", "a,@%s", rname);
8760 emitcode ("mov", "b,a");
8761 emitcode ("movx", "a,@dptr");
8765 emitcode ("push", "b");
8766 emitcode ("push", "acc");
8767 emitcode ("lcall", "__gptrget");
8768 emitcode ("pop", "b");
8772 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8773 emitcode ("orl", "a,b");
8776 if (p_type == GPOINTER)
8777 emitcode ("pop", "b");
8783 emitcode ("mov", "@%s,a", rname);
8787 emitcode ("movx", "@dptr,a");
8791 emitcode ("lcall", "__gptrput");
8795 /*-----------------------------------------------------------------*/
8796 /* genDataPointerSet - remat pointer to data space */
8797 /*-----------------------------------------------------------------*/
8799 genDataPointerSet (operand * right,
8803 int size, offset = 0;
8804 char *l, buffer[256];
8806 aopOp (right, ic, FALSE, FALSE);
8808 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8809 size = AOP_SIZE (right);
8813 sprintf (buffer, "(%s + %d)", l + 1, offset);
8815 sprintf (buffer, "%s", l + 1);
8816 emitcode ("mov", "%s,%s", buffer,
8817 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8820 freeAsmop (right, NULL, ic, TRUE);
8821 freeAsmop (result, NULL, ic, TRUE);
8824 /*-----------------------------------------------------------------*/
8825 /* genNearPointerSet - emitcode for near pointer put */
8826 /*-----------------------------------------------------------------*/
8828 genNearPointerSet (operand * right,
8835 sym_link *retype, *letype;
8836 sym_link *ptype = operandType (result);
8838 retype = getSpec (operandType (right));
8839 letype = getSpec (ptype);
8841 aopOp (result, ic, FALSE, FALSE);
8843 /* if the result is rematerializable &
8844 in data space & not a bit variable */
8845 if (AOP_TYPE (result) == AOP_IMMD &&
8846 DCL_TYPE (ptype) == POINTER &&
8847 !IS_BITVAR (retype) &&
8848 !IS_BITVAR (letype))
8850 genDataPointerSet (right, result, ic);
8854 /* if the value is already in a pointer register
8855 then don't need anything more */
8856 if (!AOP_INPREG (AOP (result)))
8858 /* otherwise get a free pointer register */
8860 preg = getFreePtr (ic, &aop, FALSE);
8861 emitcode ("mov", "%s,%s",
8863 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8867 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8869 freeAsmop (result, NULL, ic, TRUE);
8870 aopOp (right, ic, FALSE, FALSE);
8872 /* if bitfield then unpack the bits */
8873 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8874 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8877 /* we have can just get the values */
8878 int size = AOP_SIZE (right);
8883 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8887 emitcode ("mov", "@%s,a", rname);
8890 emitcode ("mov", "@%s,%s", rname, l);
8892 emitcode ("inc", "%s", rname);
8897 /* now some housekeeping stuff */
8900 /* we had to allocate for this iCode */
8901 freeAsmop (NULL, aop, ic, TRUE);
8905 /* we did not allocate which means left
8906 already in a pointer register, then
8907 if size > 0 && this could be used again
8908 we have to point it back to where it
8910 if (AOP_SIZE (right) > 1 &&
8911 !OP_SYMBOL (result)->remat &&
8912 (OP_SYMBOL (result)->liveTo > ic->seq ||
8915 int size = AOP_SIZE (right) - 1;
8917 emitcode ("dec", "%s", rname);
8922 freeAsmop (right, NULL, ic, TRUE);
8927 /*-----------------------------------------------------------------*/
8928 /* genPagedPointerSet - emitcode for Paged pointer put */
8929 /*-----------------------------------------------------------------*/
8931 genPagedPointerSet (operand * right,
8938 sym_link *retype, *letype;
8940 retype = getSpec (operandType (right));
8941 letype = getSpec (operandType (result));
8943 aopOp (result, ic, FALSE, FALSE);
8945 /* if the value is already in a pointer register
8946 then don't need anything more */
8947 if (!AOP_INPREG (AOP (result)))
8949 /* otherwise get a free pointer register */
8951 preg = getFreePtr (ic, &aop, FALSE);
8952 emitcode ("mov", "%s,%s",
8954 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8958 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8960 freeAsmop (result, NULL, ic, TRUE);
8961 aopOp (right, ic, FALSE, FALSE);
8963 /* if bitfield then unpack the bits */
8964 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8965 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8968 /* we have can just get the values */
8969 int size = AOP_SIZE (right);
8974 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8977 emitcode ("movx", "@%s,a", rname);
8980 emitcode ("inc", "%s", rname);
8986 /* now some housekeeping stuff */
8989 /* we had to allocate for this iCode */
8990 freeAsmop (NULL, aop, ic, TRUE);
8994 /* we did not allocate which means left
8995 already in a pointer register, then
8996 if size > 0 && this could be used again
8997 we have to point it back to where it
8999 if (AOP_SIZE (right) > 1 &&
9000 !OP_SYMBOL (result)->remat &&
9001 (OP_SYMBOL (result)->liveTo > ic->seq ||
9004 int size = AOP_SIZE (right) - 1;
9006 emitcode ("dec", "%s", rname);
9011 freeAsmop (right, NULL, ic, TRUE);
9016 /*-----------------------------------------------------------------*/
9017 /* genFarPointerSet - set value from far space */
9018 /*-----------------------------------------------------------------*/
9020 genFarPointerSet (operand * right,
9021 operand * result, iCode * ic)
9024 sym_link *retype = getSpec (operandType (right));
9025 sym_link *letype = getSpec (operandType (result));
9027 aopOp (result, ic, FALSE, FALSE);
9029 /* if the operand is already in dptr
9030 then we do nothing else we move the value to dptr */
9031 if (AOP_TYPE (result) != AOP_STR)
9033 /* if this is remateriazable */
9034 if (AOP_TYPE (result) == AOP_IMMD)
9035 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9038 /* we need to get it byte by byte */
9039 _startLazyDPSEvaluation ();
9040 if (AOP_TYPE (result) != AOP_DPTR)
9042 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9043 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9044 if (options.model == MODEL_FLAT24)
9045 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9049 /* We need to generate a load to DPTR indirect through DPTR. */
9050 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9052 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9053 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9054 if (options.model == MODEL_FLAT24)
9055 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9056 emitcode ("pop", "dph");
9057 emitcode ("pop", "dpl");
9059 _endLazyDPSEvaluation ();
9062 /* so dptr know contains the address */
9063 freeAsmop (result, NULL, ic, TRUE);
9064 aopOp (right, ic, FALSE, TRUE);
9066 /* if bit then unpack */
9067 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9068 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9071 size = AOP_SIZE (right);
9074 _startLazyDPSEvaluation ();
9077 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9083 emitcode ("movx", "@dptr,a");
9085 emitcode ("inc", "dptr");
9087 _endLazyDPSEvaluation ();
9090 freeAsmop (right, NULL, ic, TRUE);
9093 /*-----------------------------------------------------------------*/
9094 /* genGenPointerSet - set value from generic pointer space */
9095 /*-----------------------------------------------------------------*/
9097 genGenPointerSet (operand * right,
9098 operand * result, iCode * ic)
9101 sym_link *retype = getSpec (operandType (right));
9102 sym_link *letype = getSpec (operandType (result));
9104 aopOp (result, ic, FALSE, TRUE);
9106 /* if the operand is already in dptr
9107 then we do nothing else we move the value to dptr */
9108 if (AOP_TYPE (result) != AOP_STR)
9110 _startLazyDPSEvaluation ();
9111 /* if this is remateriazable */
9112 if (AOP_TYPE (result) == AOP_IMMD)
9114 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9115 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9118 { /* we need to get it byte by byte */
9119 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9120 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9121 if (options.model == MODEL_FLAT24) {
9122 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9123 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9125 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9128 _endLazyDPSEvaluation ();
9130 /* so dptr know contains the address */
9131 freeAsmop (result, NULL, ic, TRUE);
9132 aopOp (right, ic, FALSE, TRUE);
9134 /* if bit then unpack */
9135 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9136 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9139 size = AOP_SIZE (right);
9142 _startLazyDPSEvaluation ();
9145 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9151 emitcode ("lcall", "__gptrput");
9153 emitcode ("inc", "dptr");
9155 _endLazyDPSEvaluation ();
9158 freeAsmop (right, NULL, ic, TRUE);
9161 /*-----------------------------------------------------------------*/
9162 /* genPointerSet - stores the value into a pointer location */
9163 /*-----------------------------------------------------------------*/
9165 genPointerSet (iCode * ic)
9167 operand *right, *result;
9168 sym_link *type, *etype;
9171 D (emitcode (";", "genPointerSet ");
9174 right = IC_RIGHT (ic);
9175 result = IC_RESULT (ic);
9177 /* depending on the type of pointer we need to
9178 move it to the correct pointer register */
9179 type = operandType (result);
9180 etype = getSpec (type);
9181 /* if left is of type of pointer then it is simple */
9182 if (IS_PTR (type) && !IS_FUNC (type->next))
9184 p_type = DCL_TYPE (type);
9188 /* we have to go by the storage class */
9189 p_type = PTR_TYPE (SPEC_OCLS (etype));
9192 /* now that we have the pointer type we assign
9193 the pointer values */
9199 genNearPointerSet (right, result, ic);
9203 genPagedPointerSet (right, result, ic);
9207 genFarPointerSet (right, result, ic);
9211 genGenPointerSet (right, result, ic);
9217 /*-----------------------------------------------------------------*/
9218 /* genIfx - generate code for Ifx statement */
9219 /*-----------------------------------------------------------------*/
9221 genIfx (iCode * ic, iCode * popIc)
9223 operand *cond = IC_COND (ic);
9226 D (emitcode (";", "genIfx "););
9228 aopOp (cond, ic, FALSE, FALSE);
9230 /* get the value into acc */
9231 if (AOP_TYPE (cond) != AOP_CRY)
9235 /* the result is now in the accumulator */
9236 freeAsmop (cond, NULL, ic, TRUE);
9238 /* if there was something to be popped then do it */
9242 /* if the condition is a bit variable */
9243 if (isbit && IS_ITEMP (cond) &&
9245 genIfxJump (ic, SPIL_LOC (cond)->rname);
9246 else if (isbit && !IS_ITEMP (cond))
9247 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9249 genIfxJump (ic, "a");
9254 /*-----------------------------------------------------------------*/
9255 /* genAddrOf - generates code for address of */
9256 /*-----------------------------------------------------------------*/
9258 genAddrOf (iCode * ic)
9260 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9263 D (emitcode (";", "genAddrOf ");
9266 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9268 /* if the operand is on the stack then we
9269 need to get the stack offset of this
9273 /* if it has an offset then we need to compute
9277 emitcode ("mov", "a,_bp");
9278 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9279 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9283 /* we can just move _bp */
9284 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9286 /* fill the result with zero */
9287 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9290 if (options.stack10bit && size < (FPTRSIZE - 1))
9293 "*** warning: pointer to stack var truncated.\n");
9300 if (options.stack10bit && offset == 2)
9302 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9306 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9313 /* object not on stack then we need the name */
9314 size = AOP_SIZE (IC_RESULT (ic));
9319 char s[SDCC_NAME_MAX];
9321 sprintf (s, "#(%s >> %d)",
9325 sprintf (s, "#%s", sym->rname);
9326 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9330 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9334 /*-----------------------------------------------------------------*/
9335 /* genArrayInit - generates code for address of */
9336 /*-----------------------------------------------------------------*/
9338 genArrayInit (iCode * ic)
9342 int elementSize = 0, eIndex;
9343 unsigned val, lastVal;
9345 operand *left=IC_LEFT(ic);
9347 D (emitcode (";", "genArrayInit "););
9349 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9351 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9353 // Load immediate value into DPTR.
9354 emitcode("mov", "dptr, %s",
9355 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9357 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9360 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9361 "Unexpected operand to genArrayInit.\n");
9364 // a regression because of SDCCcse.c:1.52
9365 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9366 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9367 if (options.model == MODEL_FLAT24)
9368 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9372 type = operandType(IC_LEFT(ic));
9374 if (type && type->next)
9376 elementSize = getSize(type->next);
9380 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9381 "can't determine element size in genArrayInit.\n");
9385 iLoop = IC_ARRAYILIST(ic);
9390 bool firstpass = TRUE;
9392 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9393 iLoop->count, (int)iLoop->literalValue, elementSize);
9399 symbol *tlbl = NULL;
9401 count = ix > 256 ? 256 : ix;
9405 tlbl = newiTempLabel (NULL);
9406 if (firstpass || (count & 0xff))
9408 emitcode("mov", "b, #0x%x", count & 0xff);
9411 emitcode ("", "%05d$:", tlbl->key + 100);
9416 for (eIndex = 0; eIndex < elementSize; eIndex++)
9418 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9421 emitcode("mov", "a, #0x%x", val);
9425 emitcode("movx", "@dptr, a");
9426 emitcode("inc", "dptr");
9431 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9437 iLoop = iLoop->next;
9440 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9443 /*-----------------------------------------------------------------*/
9444 /* genFarFarAssign - assignment when both are in far space */
9445 /*-----------------------------------------------------------------*/
9447 genFarFarAssign (operand * result, operand * right, iCode * ic)
9449 int size = AOP_SIZE (right);
9451 symbol *rSym = NULL;
9455 /* quick & easy case. */
9456 D(emitcode(";","genFarFarAssign (1 byte case)"););
9457 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9458 freeAsmop (right, NULL, ic, FALSE);
9459 /* now assign DPTR to result */
9461 aopOp(result, ic, FALSE, FALSE);
9463 aopPut(AOP(result), "a", 0);
9464 freeAsmop(result, NULL, ic, FALSE);
9468 /* See if we've got an underlying symbol to abuse. */
9469 if (IS_SYMOP(result) && OP_SYMBOL(result))
9471 if (IS_TRUE_SYMOP(result))
9473 rSym = OP_SYMBOL(result);
9475 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9477 rSym = OP_SYMBOL(result)->usl.spillLoc;
9481 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9483 /* We can use the '390 auto-toggle feature to good effect here. */
9485 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9486 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9487 emitcode ("mov", "dptr,#%s", rSym->rname);
9488 /* DP2 = result, DP1 = right, DP1 is current. */
9491 emitcode("movx", "a,@dptr");
9492 emitcode("movx", "@dptr,a");
9495 emitcode("inc", "dptr");
9496 emitcode("inc", "dptr");
9499 emitcode("mov", "dps, #0");
9500 freeAsmop (right, NULL, ic, FALSE);
9502 some alternative code for processors without auto-toggle
9503 no time to test now, so later well put in...kpb
9504 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9505 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9506 emitcode ("mov", "dptr,#%s", rSym->rname);
9507 /* DP2 = result, DP1 = right, DP1 is current. */
9511 emitcode("movx", "a,@dptr");
9513 emitcode("inc", "dptr");
9514 emitcode("inc", "dps");
9515 emitcode("movx", "@dptr,a");
9517 emitcode("inc", "dptr");
9518 emitcode("inc", "dps");
9520 emitcode("mov", "dps, #0");
9521 freeAsmop (right, NULL, ic, FALSE);
9526 D (emitcode (";", "genFarFarAssign"););
9527 aopOp (result, ic, TRUE, TRUE);
9529 _startLazyDPSEvaluation ();
9533 aopPut (AOP (result),
9534 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9537 _endLazyDPSEvaluation ();
9538 freeAsmop (result, NULL, ic, FALSE);
9539 freeAsmop (right, NULL, ic, FALSE);
9543 /*-----------------------------------------------------------------*/
9544 /* genAssign - generate code for assignment */
9545 /*-----------------------------------------------------------------*/
9547 genAssign (iCode * ic)
9549 operand *result, *right;
9551 unsigned long lit = 0L;
9553 D (emitcode (";", "genAssign ");
9556 result = IC_RESULT (ic);
9557 right = IC_RIGHT (ic);
9559 /* if they are the same */
9560 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9563 aopOp (right, ic, FALSE, FALSE);
9565 emitcode (";", "genAssign: resultIsFar = %s",
9566 isOperandInFarSpace (result) ?
9569 /* special case both in far space */
9570 if ((AOP_TYPE (right) == AOP_DPTR ||
9571 AOP_TYPE (right) == AOP_DPTR2) &&
9572 /* IS_TRUE_SYMOP(result) && */
9573 isOperandInFarSpace (result))
9575 genFarFarAssign (result, right, ic);
9579 aopOp (result, ic, TRUE, FALSE);
9581 /* if they are the same registers */
9582 if (sameRegs (AOP (right), AOP (result)))
9585 /* if the result is a bit */
9586 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9588 /* if the right size is a literal then
9589 we know what the value is */
9590 if (AOP_TYPE (right) == AOP_LIT)
9592 if (((int) operandLitValue (right)))
9593 aopPut (AOP (result), one, 0);
9595 aopPut (AOP (result), zero, 0);
9599 /* the right is also a bit variable */
9600 if (AOP_TYPE (right) == AOP_CRY)
9602 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9603 aopPut (AOP (result), "c", 0);
9609 aopPut (AOP (result), "a", 0);
9613 /* bit variables done */
9615 size = AOP_SIZE (result);
9617 if (AOP_TYPE (right) == AOP_LIT)
9618 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9621 (AOP_TYPE (result) != AOP_REG) &&
9622 (AOP_TYPE (right) == AOP_LIT) &&
9623 !IS_FLOAT (operandType (right)))
9625 _startLazyDPSEvaluation ();
9626 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9628 aopPut (AOP (result),
9629 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9634 /* And now fill the rest with zeros. */
9637 emitcode ("clr", "a");
9641 aopPut (AOP (result), "a", offset++);
9643 _endLazyDPSEvaluation ();
9647 _startLazyDPSEvaluation ();
9650 aopPut (AOP (result),
9651 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9655 _endLazyDPSEvaluation ();
9659 freeAsmop (right, NULL, ic, FALSE);
9660 freeAsmop (result, NULL, ic, TRUE);
9663 /*-----------------------------------------------------------------*/
9664 /* genJumpTab - generates code for jump table */
9665 /*-----------------------------------------------------------------*/
9667 genJumpTab (iCode * ic)
9672 D (emitcode (";", "genJumpTab ");
9675 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9676 /* get the condition into accumulator */
9677 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9679 /* multiply by four! */
9680 emitcode ("add", "a,acc");
9681 emitcode ("add", "a,acc");
9682 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9684 jtab = newiTempLabel (NULL);
9685 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9686 emitcode ("jmp", "@a+dptr");
9687 emitcode ("", "%05d$:", jtab->key + 100);
9688 /* now generate the jump labels */
9689 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9690 jtab = setNextItem (IC_JTLABELS (ic)))
9691 emitcode ("ljmp", "%05d$", jtab->key + 100);
9695 /*-----------------------------------------------------------------*/
9696 /* genCast - gen code for casting */
9697 /*-----------------------------------------------------------------*/
9699 genCast (iCode * ic)
9701 operand *result = IC_RESULT (ic);
9702 sym_link *ctype = operandType (IC_LEFT (ic));
9703 sym_link *rtype = operandType (IC_RIGHT (ic));
9704 operand *right = IC_RIGHT (ic);
9707 D (emitcode (";", "genCast ");
9710 /* if they are equivalent then do nothing */
9711 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9714 aopOp (right, ic, FALSE, FALSE);
9715 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9717 /* if the result is a bit */
9718 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9719 if (IS_BITVAR(OP_SYMBOL(result)->type))
9721 /* if the right size is a literal then
9722 we know what the value is */
9723 if (AOP_TYPE (right) == AOP_LIT)
9725 if (((int) operandLitValue (right)))
9726 aopPut (AOP (result), one, 0);
9728 aopPut (AOP (result), zero, 0);
9733 /* the right is also a bit variable */
9734 if (AOP_TYPE (right) == AOP_CRY)
9736 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9737 aopPut (AOP (result), "c", 0);
9743 aopPut (AOP (result), "a", 0);
9747 /* if they are the same size : or less */
9748 if (AOP_SIZE (result) <= AOP_SIZE (right))
9751 /* if they are in the same place */
9752 if (sameRegs (AOP (right), AOP (result)))
9755 /* if they in different places then copy */
9756 size = AOP_SIZE (result);
9758 _startLazyDPSEvaluation ();
9761 aopPut (AOP (result),
9762 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9766 _endLazyDPSEvaluation ();
9771 /* if the result is of type pointer */
9776 sym_link *type = operandType (right);
9778 /* pointer to generic pointer */
9779 if (IS_GENPTR (ctype))
9785 p_type = DCL_TYPE (type);
9789 #if OLD_CAST_BEHAVIOR
9790 /* KV: we are converting a non-pointer type to
9791 * a generic pointer. This (ifdef'd out) code
9792 * says that the resulting generic pointer
9793 * should have the same class as the storage
9794 * location of the non-pointer variable.
9796 * For example, converting an int (which happens
9797 * to be stored in DATA space) to a pointer results
9798 * in a DATA generic pointer; if the original int
9799 * in XDATA space, so will be the resulting pointer.
9801 * I don't like that behavior, and thus this change:
9802 * all such conversions will be forced to XDATA and
9803 * throw a warning. If you want some non-XDATA
9804 * type, or you want to suppress the warning, you
9805 * must go through an intermediate cast, like so:
9807 * char _generic *gp = (char _xdata *)(intVar);
9809 sym_link *etype = getSpec (type);
9811 /* we have to go by the storage class */
9812 if (SPEC_OCLS (etype) != generic)
9814 p_type = PTR_TYPE (SPEC_OCLS (etype));
9819 /* Converting unknown class (i.e. register variable)
9820 * to generic pointer. This is not good, but
9821 * we'll make a guess (and throw a warning).
9824 werror (W_INT_TO_GEN_PTR_CAST);
9828 /* the first two bytes are known */
9829 size = GPTRSIZE - 1;
9831 _startLazyDPSEvaluation ();
9834 aopPut (AOP (result),
9835 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9839 _endLazyDPSEvaluation ();
9841 /* the last byte depending on type */
9859 /* this should never happen */
9860 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9861 "got unknown pointer type");
9864 aopPut (AOP (result), l, GPTRSIZE - 1);
9868 /* just copy the pointers */
9869 size = AOP_SIZE (result);
9871 _startLazyDPSEvaluation ();
9874 aopPut (AOP (result),
9875 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9879 _endLazyDPSEvaluation ();
9883 /* so we now know that the size of destination is greater
9884 than the size of the source */
9885 /* we move to result for the size of source */
9886 size = AOP_SIZE (right);
9888 _startLazyDPSEvaluation ();
9891 aopPut (AOP (result),
9892 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9896 _endLazyDPSEvaluation ();
9898 /* now depending on the sign of the source && destination */
9899 size = AOP_SIZE (result) - AOP_SIZE (right);
9900 /* if unsigned or not an integral type */
9901 /* also, if the source is a bit, we don't need to sign extend, because
9902 * it can't possibly have set the sign bit.
9904 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9908 aopPut (AOP (result), zero, offset++);
9913 /* we need to extend the sign :{ */
9914 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9915 FALSE, FALSE, TRUE);
9917 emitcode ("rlc", "a");
9918 emitcode ("subb", "a,acc");
9920 aopPut (AOP (result), "a", offset++);
9923 /* we are done hurray !!!! */
9926 freeAsmop (right, NULL, ic, TRUE);
9927 freeAsmop (result, NULL, ic, TRUE);
9931 /*-----------------------------------------------------------------*/
9932 /* genDjnz - generate decrement & jump if not zero instrucion */
9933 /*-----------------------------------------------------------------*/
9935 genDjnz (iCode * ic, iCode * ifx)
9941 /* if the if condition has a false label
9942 then we cannot save */
9946 /* if the minus is not of the form
9948 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9949 !IS_OP_LITERAL (IC_RIGHT (ic)))
9952 if (operandLitValue (IC_RIGHT (ic)) != 1)
9955 /* if the size of this greater than one then no
9957 if (getSize (operandType (IC_RESULT (ic))) > 1)
9960 /* otherwise we can save BIG */
9961 D(emitcode(";", "genDjnz"););
9963 lbl = newiTempLabel (NULL);
9964 lbl1 = newiTempLabel (NULL);
9966 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9968 if (AOP_NEEDSACC(IC_RESULT(ic)))
9970 /* If the result is accessed indirectly via
9971 * the accumulator, we must explicitly write
9972 * it back after the decrement.
9974 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9976 if (strcmp(rByte, "a"))
9978 /* Something is hopelessly wrong */
9979 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9980 __FILE__, __LINE__);
9981 /* We can just give up; the generated code will be inefficient,
9984 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9987 emitcode ("dec", "%s", rByte);
9988 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9989 emitcode ("jnz", "%05d$", lbl->key + 100);
9991 else if (IS_AOP_PREG (IC_RESULT (ic)))
9993 emitcode ("dec", "%s",
9994 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9995 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9996 emitcode ("jnz", "%05d$", lbl->key + 100);
10000 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10003 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10004 emitcode ("", "%05d$:", lbl->key + 100);
10005 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10006 emitcode ("", "%05d$:", lbl1->key + 100);
10008 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10009 ifx->generated = 1;
10013 /*-----------------------------------------------------------------*/
10014 /* genReceive - generate code for a receive iCode */
10015 /*-----------------------------------------------------------------*/
10017 genReceive (iCode * ic)
10020 D (emitcode (";", "genReceive ");
10023 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10024 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10025 IS_TRUE_SYMOP (IC_RESULT (ic))))
10027 int size = getSize (operandType (IC_RESULT (ic)));
10028 int offset = fReturnSizeDS390 - size;
10031 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10032 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10035 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10036 size = AOP_SIZE (IC_RESULT (ic));
10040 emitcode ("pop", "acc");
10041 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10048 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10050 assignResultValue (IC_RESULT (ic));
10053 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10056 /*-----------------------------------------------------------------*/
10057 /* gen390Code - generate code for Dallas 390 based controllers */
10058 /*-----------------------------------------------------------------*/
10060 gen390Code (iCode * lic)
10065 lineHead = lineCurr = NULL;
10067 if (options.model == MODEL_FLAT24) {
10068 fReturnSizeDS390 = 5;
10069 fReturn = fReturn24;
10071 fReturnSizeDS390 = 4;
10072 fReturn = fReturn16;
10073 options.stack10bit=0;
10077 /* print the allocation information */
10079 printAllocInfo (currFunc, codeOutFile);
10081 /* if debug information required */
10082 if (options.debug && currFunc)
10084 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10086 if (IS_STATIC (currFunc->etype))
10087 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10089 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10092 /* stack pointer name */
10093 if (options.useXstack)
10099 for (ic = lic; ic; ic = ic->next)
10102 if (cln != ic->lineno)
10107 emitcode ("", "C$%s$%d$%d$%d ==.",
10108 FileBaseName (ic->filename), ic->lineno,
10109 ic->level, ic->block);
10112 emitcode (";", "%s %d", ic->filename, ic->lineno);
10115 /* if the result is marked as
10116 spilt and rematerializable or code for
10117 this has already been generated then
10119 if (resultRemat (ic) || ic->generated)
10122 /* depending on the operation */
10142 /* IPOP happens only when trying to restore a
10143 spilt live range, if there is an ifx statement
10144 following this pop then the if statement might
10145 be using some of the registers being popped which
10146 would destory the contents of the register so
10147 we need to check for this condition and handle it */
10149 ic->next->op == IFX &&
10150 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10151 genIfx (ic->next, ic);
10169 genEndFunction (ic);
10189 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10206 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10210 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10217 /* note these two are xlated by algebraic equivalence
10218 during parsing SDCC.y */
10219 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10220 "got '>=' or '<=' shouldn't have come here");
10224 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10236 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10240 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10244 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10268 genRightShift (ic);
10271 case GET_VALUE_AT_ADDRESS:
10272 genPointerGet (ic);
10276 if (POINTER_SET (ic))
10277 genPointerSet (ic);
10303 addSet (&_G.sendSet, ic);
10316 /* now we are ready to call the
10317 peep hole optimizer */
10318 if (!options.nopeep)
10319 peepHole (&lineHead);
10321 /* now do the actual printing */
10322 printLine (lineHead, codeOutFile);