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 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4061 /*-----------------------------------------------------------------*/
4062 static void genMultTwoByte (operand *left, operand *right,
4063 operand *result, iCode *ic)
4065 sym_link *retype = getSpec(operandType(right));
4066 sym_link *letype = getSpec(operandType(left));
4067 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4070 if (AOP_TYPE (left) == AOP_LIT) {
4075 /* load up MB with right */
4077 emitcode("clr","F0");
4078 if (AOP_TYPE(right) == AOP_LIT) {
4079 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4081 emitcode("setb","F0");
4084 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4085 emitcode ("mov","mb,#0x%02x",val & 0xff);
4087 lbl = newiTempLabel(NULL);
4088 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4089 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4090 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4091 emitcode ("xch", "a,b");
4092 emitcode ("cpl","a");
4093 emitcode ("add", "a,#1");
4094 emitcode ("xch", "a,b");
4095 emitcode ("cpl", "a"); // msb
4096 emitcode ("addc", "a,#0");
4097 emitcode ("setb","F0");
4098 emitcode ("","%05d$:",lbl->key+100);
4099 emitcode ("mov","mb,b");
4100 emitcode ("mov","mb,a");
4103 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4104 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4106 /* load up MA with left */
4108 lbl = newiTempLabel(NULL);
4109 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4110 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4111 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4112 emitcode ("xch", "a,b");
4113 emitcode ("cpl","a");
4114 emitcode ("add", "a,#1");
4115 emitcode ("xch", "a,b");
4116 emitcode ("cpl", "a"); // msb
4117 emitcode ("addc","a,#0");
4118 emitcode ("jbc","F0,%05d$",lbl->key+100);
4119 emitcode ("setb","F0");
4120 emitcode ("","%05d$:",lbl->key+100);
4121 emitcode ("mov","ma,b");
4122 emitcode ("mov","ma,a");
4124 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4125 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4127 /* wait for multiplication to finish */
4128 lbl = newiTempLabel(NULL);
4129 emitcode("","%05d$:", lbl->key+100);
4130 emitcode("mov","a,mcnt1");
4131 emitcode("anl","a,#0x80");
4132 emitcode("jnz","%05d$",lbl->key+100);
4134 freeAsmop (left, NULL, ic, TRUE);
4135 freeAsmop (right, NULL, ic,TRUE);
4136 aopOp(result, ic, TRUE, FALSE);
4138 /* if unsigned then simple */
4140 emitcode ("mov","a,ma");
4141 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4142 emitcode ("mov","a,ma");
4143 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4144 aopPut(AOP(result),"ma",1);
4145 aopPut(AOP(result),"ma",0);
4147 emitcode("push","ma");
4148 emitcode("push","ma");
4149 emitcode("push","ma");
4151 /* negate result if needed */
4152 lbl = newiTempLabel(NULL);
4153 emitcode("jnb","F0,%05d$",lbl->key+100);
4154 emitcode("cpl","a");
4155 emitcode("add","a,#1");
4156 emitcode("","%05d$:", lbl->key+100);
4157 aopPut(AOP(result),"a",0);
4158 emitcode("pop","acc");
4159 lbl = newiTempLabel(NULL);
4160 emitcode("jnb","F0,%05d$",lbl->key+100);
4161 emitcode("cpl","a");
4162 emitcode("addc","a,#0");
4163 emitcode("","%05d$:", lbl->key+100);
4164 aopPut(AOP(result),"a",1);
4165 emitcode("pop","acc");
4166 if (AOP_SIZE(result) >= 3) {
4167 lbl = newiTempLabel(NULL);
4168 emitcode("jnb","F0,%05d$",lbl->key+100);
4169 emitcode("cpl","a");
4170 emitcode("addc","a,#0");
4171 emitcode("","%05d$:", lbl->key+100);
4172 aopPut(AOP(result),"a",2);
4174 emitcode("pop","acc");
4175 if (AOP_SIZE(result) >= 4) {
4176 lbl = newiTempLabel(NULL);
4177 emitcode("jnb","F0,%05d$",lbl->key+100);
4178 emitcode("cpl","a");
4179 emitcode("addc","a,#0");
4180 emitcode("","%05d$:", lbl->key+100);
4181 aopPut(AOP(result),"a",3);
4185 freeAsmop (result, NULL, ic, TRUE);
4189 /*-----------------------------------------------------------------*/
4190 /* genMult - generates code for multiplication */
4191 /*-----------------------------------------------------------------*/
4193 genMult (iCode * ic)
4195 operand *left = IC_LEFT (ic);
4196 operand *right = IC_RIGHT (ic);
4197 operand *result = IC_RESULT (ic);
4199 D (emitcode (";", "genMult "););
4201 /* assign the amsops */
4204 /* special cases first */
4206 if (AOP_TYPE (left) == AOP_CRY &&
4207 AOP_TYPE (right) == AOP_CRY)
4209 genMultbits (left, right, result, ic);
4213 /* if both are of size == 1 */
4214 if (AOP_SIZE (left) == 1 &&
4215 AOP_SIZE (right) == 1)
4217 genMultOneByte (left, right, result, ic);
4221 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4222 /* use the ds390 ARITHMETIC accel UNIT */
4223 genMultTwoByte (left, right, result, ic);
4226 /* should have been converted to function call */
4230 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4231 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4232 freeAsmop (result, NULL, ic, TRUE);
4235 /*-----------------------------------------------------------------*/
4236 /* genDivbits :- division of bits */
4237 /*-----------------------------------------------------------------*/
4239 genDivbits (operand * left,
4247 /* the result must be bit */
4248 LOAD_AB_FOR_DIV (left, right, l);
4249 emitcode ("div", "ab");
4250 emitcode ("rrc", "a");
4251 aopOp(result, ic, TRUE, FALSE);
4253 aopPut (AOP (result), "c", 0);
4256 /*-----------------------------------------------------------------*/
4257 /* genDivOneByte : 8 bit division */
4258 /*-----------------------------------------------------------------*/
4260 genDivOneByte (operand * left,
4265 sym_link *opetype = operandType (result);
4271 /* signed or unsigned */
4272 if (SPEC_USIGN (opetype))
4274 /* unsigned is easy */
4275 LOAD_AB_FOR_DIV (left, right, l);
4276 emitcode ("div", "ab");
4279 aopOp(result, ic, TRUE, FALSE);
4280 aopPut (AOP (result), "a", 0);
4283 size = AOP_SIZE (result) - 1;
4287 aopPut (AOP (result), zero, offset++);
4292 /* signed is a little bit more difficult */
4294 /* save the signs of the operands */
4295 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4297 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4298 emitcode ("push", "acc"); /* save it on the stack */
4300 /* now sign adjust for both left & right */
4301 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4303 lbl = newiTempLabel (NULL);
4304 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4305 emitcode ("cpl", "a");
4306 emitcode ("inc", "a");
4307 emitcode ("", "%05d$:", (lbl->key + 100));
4308 emitcode ("mov", "b,a");
4310 /* sign adjust left side */
4311 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4314 lbl = newiTempLabel (NULL);
4315 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4316 emitcode ("cpl", "a");
4317 emitcode ("inc", "a");
4318 emitcode ("", "%05d$:", (lbl->key + 100));
4320 /* now the division */
4321 emitcode ("nop", "; workaround for DS80C390 div bug.");
4322 emitcode ("div", "ab");
4323 /* we are interested in the lower order
4325 emitcode ("mov", "b,a");
4326 lbl = newiTempLabel (NULL);
4327 emitcode ("pop", "acc");
4328 /* if there was an over flow we don't
4329 adjust the sign of the result */
4330 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4331 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4333 emitcode ("clr", "a");
4334 emitcode ("subb", "a,b");
4335 emitcode ("mov", "b,a");
4336 emitcode ("", "%05d$:", (lbl->key + 100));
4338 /* now we are done */
4340 aopOp(result, ic, TRUE, FALSE);
4342 aopPut (AOP (result), "b", 0);
4344 size = AOP_SIZE (result) - 1;
4348 emitcode ("mov", "c,b.7");
4349 emitcode ("subb", "a,acc");
4353 aopPut (AOP (result), "a", offset++);
4359 /*-----------------------------------------------------------------*/
4360 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4361 /*-----------------------------------------------------------------*/
4362 static void genDivTwoByte (operand *left, operand *right,
4363 operand *result, iCode *ic)
4365 sym_link *retype = getSpec(operandType(right));
4366 sym_link *letype = getSpec(operandType(left));
4367 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4370 /* load up MA with left */
4372 emitcode("clr","F0");
4373 lbl = newiTempLabel(NULL);
4374 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4375 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4376 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4377 emitcode ("xch", "a,b");
4378 emitcode ("cpl","a");
4379 emitcode ("add", "a,#1");
4380 emitcode ("xch", "a,b");
4381 emitcode ("cpl", "a"); // msb
4382 emitcode ("addc","a,#0");
4383 emitcode ("setb","F0");
4384 emitcode ("","%05d$:",lbl->key+100);
4385 emitcode ("mov","ma,b");
4386 emitcode ("mov","ma,a");
4388 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4389 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4392 /* load up MB with right */
4394 if (AOP_TYPE(right) == AOP_LIT) {
4395 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4397 lbl = newiTempLabel(NULL);
4398 emitcode ("jbc","F0,%05d$",lbl->key+100);
4399 emitcode("setb","F0");
4400 emitcode ("","%05d$:",lbl->key+100);
4403 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4404 emitcode ("mov","mb,#0x%02x",val & 0xff);
4406 lbl = newiTempLabel(NULL);
4407 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4408 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4409 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4410 emitcode ("xch", "a,b");
4411 emitcode ("cpl","a");
4412 emitcode ("add", "a,#1");
4413 emitcode ("xch", "a,b");
4414 emitcode ("cpl", "a"); // msb
4415 emitcode ("addc", "a,#0");
4416 emitcode ("jbc","F0,%05d$",lbl->key+100);
4417 emitcode ("setb","F0");
4418 emitcode ("","%05d$:",lbl->key+100);
4419 emitcode ("mov","mb,b");
4420 emitcode ("mov","mb,a");
4423 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4424 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4427 /* wait for multiplication to finish */
4428 lbl = newiTempLabel(NULL);
4429 emitcode("","%05d$:", lbl->key+100);
4430 emitcode("mov","a,mcnt1");
4431 emitcode("anl","a,#0x80");
4432 emitcode("jnz","%05d$",lbl->key+100);
4434 freeAsmop (left, NULL, ic, TRUE);
4435 freeAsmop (right, NULL, ic,TRUE);
4436 aopOp(result, ic, TRUE, FALSE);
4438 /* if unsigned then simple */
4440 aopPut(AOP(result),"ma",1);
4441 aopPut(AOP(result),"ma",0);
4443 emitcode("push","ma");
4445 /* negate result if needed */
4446 lbl = newiTempLabel(NULL);
4447 emitcode("jnb","F0,%05d$",lbl->key+100);
4448 emitcode("cpl","a");
4449 emitcode("add","a,#1");
4450 emitcode("","%05d$:", lbl->key+100);
4451 aopPut(AOP(result),"a",0);
4452 emitcode("pop","acc");
4453 lbl = newiTempLabel(NULL);
4454 emitcode("jnb","F0,%05d$",lbl->key+100);
4455 emitcode("cpl","a");
4456 emitcode("addc","a,#0");
4457 emitcode("","%05d$:", lbl->key+100);
4458 aopPut(AOP(result),"a",1);
4460 freeAsmop (result, NULL, ic, TRUE);
4464 /*-----------------------------------------------------------------*/
4465 /* genDiv - generates code for division */
4466 /*-----------------------------------------------------------------*/
4470 operand *left = IC_LEFT (ic);
4471 operand *right = IC_RIGHT (ic);
4472 operand *result = IC_RESULT (ic);
4474 D (emitcode (";", "genDiv "););
4476 /* assign the amsops */
4479 /* special cases first */
4481 if (AOP_TYPE (left) == AOP_CRY &&
4482 AOP_TYPE (right) == AOP_CRY)
4484 genDivbits (left, right, result, ic);
4488 /* if both are of size == 1 */
4489 if (AOP_SIZE (left) == 1 &&
4490 AOP_SIZE (right) == 1)
4492 genDivOneByte (left, right, result, ic);
4496 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4497 /* use the ds390 ARITHMETIC accel UNIT */
4498 genDivTwoByte (left, right, result, ic);
4501 /* should have been converted to function call */
4504 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4505 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4506 freeAsmop (result, NULL, ic, TRUE);
4509 /*-----------------------------------------------------------------*/
4510 /* genModbits :- modulus of bits */
4511 /*-----------------------------------------------------------------*/
4513 genModbits (operand * left,
4521 /* the result must be bit */
4522 LOAD_AB_FOR_DIV (left, right, l);
4523 emitcode ("div", "ab");
4524 emitcode ("mov", "a,b");
4525 emitcode ("rrc", "a");
4526 aopOp(result, ic, TRUE, FALSE);
4527 aopPut (AOP (result), "c", 0);
4530 /*-----------------------------------------------------------------*/
4531 /* genModOneByte : 8 bit modulus */
4532 /*-----------------------------------------------------------------*/
4534 genModOneByte (operand * left,
4539 sym_link *opetype = operandType (result);
4543 /* signed or unsigned */
4544 if (SPEC_USIGN (opetype))
4546 /* unsigned is easy */
4547 LOAD_AB_FOR_DIV (left, right, l);
4548 emitcode ("div", "ab");
4549 aopOp(result, ic, TRUE, FALSE);
4550 aopPut (AOP (result), "b", 0);
4554 /* signed is a little bit more difficult */
4556 /* save the signs of the operands */
4557 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4560 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4561 emitcode ("push", "acc"); /* save it on the stack */
4563 /* now sign adjust for both left & right */
4564 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4567 lbl = newiTempLabel (NULL);
4568 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4569 emitcode ("cpl", "a");
4570 emitcode ("inc", "a");
4571 emitcode ("", "%05d$:", (lbl->key + 100));
4572 emitcode ("mov", "b,a");
4574 /* sign adjust left side */
4575 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4578 lbl = newiTempLabel (NULL);
4579 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4580 emitcode ("cpl", "a");
4581 emitcode ("inc", "a");
4582 emitcode ("", "%05d$:", (lbl->key + 100));
4584 /* now the multiplication */
4585 emitcode ("nop", "; workaround for DS80C390 div bug.");
4586 emitcode ("div", "ab");
4587 /* we are interested in the lower order
4589 lbl = newiTempLabel (NULL);
4590 emitcode ("pop", "acc");
4591 /* if there was an over flow we don't
4592 adjust the sign of the result */
4593 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4594 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4596 emitcode ("clr", "a");
4597 emitcode ("subb", "a,b");
4598 emitcode ("mov", "b,a");
4599 emitcode ("", "%05d$:", (lbl->key + 100));
4601 /* now we are done */
4602 aopOp(result, ic, TRUE, FALSE);
4603 aopPut (AOP (result), "b", 0);
4607 /*-----------------------------------------------------------------*/
4608 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
4609 /*-----------------------------------------------------------------*/
4610 static void genModTwoByte (operand *left, operand *right,
4611 operand *result, iCode *ic)
4613 sym_link *retype = getSpec(operandType(right));
4614 sym_link *letype = getSpec(operandType(left));
4615 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4618 /* load up MA with left */
4620 lbl = newiTempLabel(NULL);
4621 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4622 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4623 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4624 emitcode ("xch", "a,b");
4625 emitcode ("cpl","a");
4626 emitcode ("add", "a,#1");
4627 emitcode ("xch", "a,b");
4628 emitcode ("cpl", "a"); // msb
4629 emitcode ("addc","a,#0");
4630 emitcode ("","%05d$:",lbl->key+100);
4631 emitcode ("mov","ma,b");
4632 emitcode ("mov","ma,a");
4634 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4635 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4638 /* load up MB with right */
4640 if (AOP_TYPE(right) == AOP_LIT) {
4641 int val=floatFromVal (AOP (right)->aopu.aop_lit);
4645 emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4646 emitcode ("mov","mb,#0x%02x",val & 0xff);
4648 lbl = newiTempLabel(NULL);
4649 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4650 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4651 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4652 emitcode ("xch", "a,b");
4653 emitcode ("cpl","a");
4654 emitcode ("add", "a,#1");
4655 emitcode ("xch", "a,b");
4656 emitcode ("cpl", "a"); // msb
4657 emitcode ("addc", "a,#0");
4658 emitcode ("","%05d$:",lbl->key+100);
4659 emitcode ("mov","mb,b");
4660 emitcode ("mov","mb,a");
4663 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4664 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4667 /* wait for multiplication to finish */
4668 lbl = newiTempLabel(NULL);
4669 emitcode("","%05d$:", lbl->key+100);
4670 emitcode("mov","a,mcnt1");
4671 emitcode("anl","a,#0x80");
4672 emitcode("jnz","%05d$",lbl->key+100);
4674 freeAsmop (left, NULL, ic, TRUE);
4675 freeAsmop (right, NULL, ic,TRUE);
4676 aopOp(result, ic, TRUE, FALSE);
4678 aopPut(AOP(result),"mb",1);
4679 aopPut(AOP(result),"mb",0);
4680 freeAsmop (result, NULL, ic, TRUE);
4684 /*-----------------------------------------------------------------*/
4685 /* genMod - generates code for division */
4686 /*-----------------------------------------------------------------*/
4690 operand *left = IC_LEFT (ic);
4691 operand *right = IC_RIGHT (ic);
4692 operand *result = IC_RESULT (ic);
4694 D (emitcode (";", "genMod "); );
4696 /* assign the amsops */
4699 /* special cases first */
4701 if (AOP_TYPE (left) == AOP_CRY &&
4702 AOP_TYPE (right) == AOP_CRY)
4704 genModbits (left, right, result, ic);
4708 /* if both are of size == 1 */
4709 if (AOP_SIZE (left) == 1 &&
4710 AOP_SIZE (right) == 1)
4712 genModOneByte (left, right, result, ic);
4716 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4717 /* use the ds390 ARITHMETIC accel UNIT */
4718 genModTwoByte (left, right, result, ic);
4722 /* should have been converted to function call */
4726 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4727 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4728 freeAsmop (result, NULL, ic, TRUE);
4731 /*-----------------------------------------------------------------*/
4732 /* genIfxJump :- will create a jump depending on the ifx */
4733 /*-----------------------------------------------------------------*/
4735 genIfxJump (iCode * ic, char *jval)
4738 symbol *tlbl = newiTempLabel (NULL);
4741 D (emitcode (";", "genIfxJump ");
4744 /* if true label then we jump if condition
4748 jlbl = IC_TRUE (ic);
4749 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4750 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4754 /* false label is present */
4755 jlbl = IC_FALSE (ic);
4756 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4757 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4759 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4760 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4762 emitcode (inst, "%05d$", tlbl->key + 100);
4763 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4764 emitcode ("", "%05d$:", tlbl->key + 100);
4766 /* mark the icode as generated */
4770 /*-----------------------------------------------------------------*/
4771 /* genCmp :- greater or less than comparison */
4772 /*-----------------------------------------------------------------*/
4774 genCmp (operand * left, operand * right,
4775 iCode * ic, iCode * ifx, int sign)
4777 int size, offset = 0;
4778 unsigned long lit = 0L;
4781 D (emitcode (";", "genCmp");
4784 result = IC_RESULT (ic);
4786 /* if left & right are bit variables */
4787 if (AOP_TYPE (left) == AOP_CRY &&
4788 AOP_TYPE (right) == AOP_CRY)
4790 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4791 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4795 /* subtract right from left if at the
4796 end the carry flag is set then we know that
4797 left is greater than right */
4798 size = max (AOP_SIZE (left), AOP_SIZE (right));
4800 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4801 if ((size == 1) && !sign &&
4802 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4804 symbol *lbl = newiTempLabel (NULL);
4805 emitcode ("cjne", "%s,%s,%05d$",
4806 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4807 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4809 emitcode ("", "%05d$:", lbl->key + 100);
4813 if (AOP_TYPE (right) == AOP_LIT)
4815 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4816 /* optimize if(x < 0) or if(x >= 0) */
4825 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4830 aopOp (result, ic, FALSE, FALSE);
4832 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4834 freeAsmop (result, NULL, ic, TRUE);
4835 genIfxJump (ifx, "acc.7");
4840 emitcode ("rlc", "a");
4842 goto release_freedLR;
4850 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4851 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4852 emitcode (";", "genCmp #2");
4853 if (sign && (size == 0))
4855 emitcode (";", "genCmp #3");
4856 emitcode ("xrl", "a,#0x80");
4857 if (AOP_TYPE (right) == AOP_LIT)
4859 unsigned long lit = (unsigned long)
4860 floatFromVal (AOP (right)->aopu.aop_lit);
4861 emitcode (";", "genCmp #3.1");
4862 emitcode ("subb", "a,#0x%02x",
4863 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4867 emitcode (";", "genCmp #3.2");
4868 if (AOP_NEEDSACC (right))
4870 emitcode ("push", "acc");
4872 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4873 FALSE, FALSE, FALSE));
4874 emitcode ("xrl", "b,#0x80");
4875 if (AOP_NEEDSACC (right))
4877 emitcode ("pop", "acc");
4879 emitcode ("subb", "a,b");
4886 emitcode (";", "genCmp #4");
4887 if (AOP_NEEDSACC (right))
4890 emitcode (";", "genCmp #4.1");
4891 emitcode ("xch", "a, b");
4892 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4893 emitcode ("xch", "a, b");
4898 emitcode (";", "genCmp #4.2");
4899 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4902 emitcode ("subb", "a,%s", s);
4909 /* Don't need the left & right operands any more; do need the result. */
4910 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4911 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4913 aopOp (result, ic, FALSE, FALSE);
4917 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4923 /* if the result is used in the next
4924 ifx conditional branch then generate
4925 code a little differently */
4928 genIfxJump (ifx, "c");
4934 /* leave the result in acc */
4936 freeAsmop (result, NULL, ic, TRUE);
4939 /*-----------------------------------------------------------------*/
4940 /* genCmpGt :- greater than comparison */
4941 /*-----------------------------------------------------------------*/
4943 genCmpGt (iCode * ic, iCode * ifx)
4945 operand *left, *right;
4946 sym_link *letype, *retype;
4949 D (emitcode (";", "genCmpGt ");
4952 left = IC_LEFT (ic);
4953 right = IC_RIGHT (ic);
4955 letype = getSpec (operandType (left));
4956 retype = getSpec (operandType (right));
4957 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4959 /* assign the left & right amsops */
4962 genCmp (right, left, ic, ifx, sign);
4965 /*-----------------------------------------------------------------*/
4966 /* genCmpLt - less than comparisons */
4967 /*-----------------------------------------------------------------*/
4969 genCmpLt (iCode * ic, iCode * ifx)
4971 operand *left, *right;
4972 sym_link *letype, *retype;
4975 D (emitcode (";", "genCmpLt "););
4977 left = IC_LEFT (ic);
4978 right = IC_RIGHT (ic);
4980 letype = getSpec (operandType (left));
4981 retype = getSpec (operandType (right));
4982 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4984 /* assign the left & right amsops */
4987 genCmp (left, right, ic, ifx, sign);
4990 /*-----------------------------------------------------------------*/
4991 /* gencjneshort - compare and jump if not equal */
4992 /*-----------------------------------------------------------------*/
4994 gencjneshort (operand * left, operand * right, symbol * lbl)
4996 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4998 unsigned long lit = 0L;
5000 D (emitcode (";", "gencjneshort");
5003 /* if the left side is a literal or
5004 if the right is in a pointer register and left
5006 if ((AOP_TYPE (left) == AOP_LIT) ||
5007 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5014 if (AOP_TYPE (right) == AOP_LIT)
5015 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5017 if (opIsGptr (left) || opIsGptr (right))
5019 /* We are comparing a generic pointer to something.
5020 * Exclude the generic type byte from the comparison.
5023 D (emitcode (";", "cjneshort: generic ptr special case.");
5028 /* if the right side is a literal then anything goes */
5029 if (AOP_TYPE (right) == AOP_LIT &&
5030 AOP_TYPE (left) != AOP_DIR)
5034 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5036 emitcode ("cjne", "a,%s,%05d$",
5037 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5043 /* if the right side is in a register or in direct space or
5044 if the left is a pointer register & right is not */
5045 else if (AOP_TYPE (right) == AOP_REG ||
5046 AOP_TYPE (right) == AOP_DIR ||
5047 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5048 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5052 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5053 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5054 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5055 emitcode ("jnz", "%05d$", lbl->key + 100);
5057 emitcode ("cjne", "a,%s,%05d$",
5058 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5065 /* right is a pointer reg need both a & b */
5068 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5069 if (strcmp (l, "b"))
5070 emitcode ("mov", "b,%s", l);
5071 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5072 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5078 /*-----------------------------------------------------------------*/
5079 /* gencjne - compare and jump if not equal */
5080 /*-----------------------------------------------------------------*/
5082 gencjne (operand * left, operand * right, symbol * lbl)
5084 symbol *tlbl = newiTempLabel (NULL);
5086 D (emitcode (";", "gencjne");
5089 gencjneshort (left, right, lbl);
5091 emitcode ("mov", "a,%s", one);
5092 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5093 emitcode ("", "%05d$:", lbl->key + 100);
5094 emitcode ("clr", "a");
5095 emitcode ("", "%05d$:", tlbl->key + 100);
5098 /*-----------------------------------------------------------------*/
5099 /* genCmpEq - generates code for equal to */
5100 /*-----------------------------------------------------------------*/
5102 genCmpEq (iCode * ic, iCode * ifx)
5104 operand *left, *right, *result;
5106 D (emitcode (";", "genCmpEq ");
5110 AOP_SET_LOCALS (ic);
5112 /* if literal, literal on the right or
5113 if the right is in a pointer register and left
5115 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5116 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5118 operand *t = IC_RIGHT (ic);
5119 IC_RIGHT (ic) = IC_LEFT (ic);
5123 if (ifx && /* !AOP_SIZE(result) */
5124 OP_SYMBOL (result) &&
5125 OP_SYMBOL (result)->regType == REG_CND)
5128 /* if they are both bit variables */
5129 if (AOP_TYPE (left) == AOP_CRY &&
5130 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5132 if (AOP_TYPE (right) == AOP_LIT)
5134 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5137 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5138 emitcode ("cpl", "c");
5142 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5146 emitcode ("clr", "c");
5148 /* AOP_TYPE(right) == AOP_CRY */
5152 symbol *lbl = newiTempLabel (NULL);
5153 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5154 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5155 emitcode ("cpl", "c");
5156 emitcode ("", "%05d$:", (lbl->key + 100));
5158 /* if true label then we jump if condition
5160 tlbl = newiTempLabel (NULL);
5163 emitcode ("jnc", "%05d$", tlbl->key + 100);
5164 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5168 emitcode ("jc", "%05d$", tlbl->key + 100);
5169 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5171 emitcode ("", "%05d$:", tlbl->key + 100);
5175 tlbl = newiTempLabel (NULL);
5176 gencjneshort (left, right, tlbl);
5179 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5180 emitcode ("", "%05d$:", tlbl->key + 100);
5184 symbol *lbl = newiTempLabel (NULL);
5185 emitcode ("sjmp", "%05d$", lbl->key + 100);
5186 emitcode ("", "%05d$:", tlbl->key + 100);
5187 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5188 emitcode ("", "%05d$:", lbl->key + 100);
5191 /* mark the icode as generated */
5194 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5195 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5199 /* if they are both bit variables */
5200 if (AOP_TYPE (left) == AOP_CRY &&
5201 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5203 if (AOP_TYPE (right) == AOP_LIT)
5205 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5208 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5209 emitcode ("cpl", "c");
5213 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5217 emitcode ("clr", "c");
5219 /* AOP_TYPE(right) == AOP_CRY */
5223 symbol *lbl = newiTempLabel (NULL);
5224 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5225 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5226 emitcode ("cpl", "c");
5227 emitcode ("", "%05d$:", (lbl->key + 100));
5230 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5231 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5233 aopOp (result, ic, TRUE, FALSE);
5236 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5243 genIfxJump (ifx, "c");
5246 /* if the result is used in an arithmetic operation
5247 then put the result in place */
5252 gencjne (left, right, newiTempLabel (NULL));
5254 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5255 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5257 aopOp (result, ic, TRUE, FALSE);
5259 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5261 aopPut (AOP (result), "a", 0);
5266 genIfxJump (ifx, "a");
5269 /* if the result is used in an arithmetic operation
5270 then put the result in place */
5271 if (AOP_TYPE (result) != AOP_CRY)
5273 /* leave the result in acc */
5277 freeAsmop (result, NULL, ic, TRUE);
5280 /*-----------------------------------------------------------------*/
5281 /* ifxForOp - returns the icode containing the ifx for operand */
5282 /*-----------------------------------------------------------------*/
5284 ifxForOp (operand * op, iCode * ic)
5286 /* if true symbol then needs to be assigned */
5287 if (IS_TRUE_SYMOP (op))
5290 /* if this has register type condition and
5291 the next instruction is ifx with the same operand
5292 and live to of the operand is upto the ifx only then */
5294 ic->next->op == IFX &&
5295 IC_COND (ic->next)->key == op->key &&
5296 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5301 /*-----------------------------------------------------------------*/
5302 /* genAndOp - for && operation */
5303 /*-----------------------------------------------------------------*/
5305 genAndOp (iCode * ic)
5307 operand *left, *right, *result;
5310 D (emitcode (";", "genAndOp "););
5312 /* note here that && operations that are in an
5313 if statement are taken away by backPatchLabels
5314 only those used in arthmetic operations remain */
5316 AOP_SET_LOCALS (ic);
5318 /* if both are bit variables */
5319 if (AOP_TYPE (left) == AOP_CRY &&
5320 AOP_TYPE (right) == AOP_CRY)
5322 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5323 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5324 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5325 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5327 aopOp (result,ic,FALSE, FALSE);
5332 tlbl = newiTempLabel (NULL);
5334 emitcode ("jz", "%05d$", tlbl->key + 100);
5336 emitcode ("", "%05d$:", tlbl->key + 100);
5337 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5338 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5340 aopOp (result,ic,FALSE, FALSE);
5343 freeAsmop (result, NULL, ic, TRUE);
5347 /*-----------------------------------------------------------------*/
5348 /* genOrOp - for || operation */
5349 /*-----------------------------------------------------------------*/
5351 genOrOp (iCode * ic)
5353 operand *left, *right, *result;
5356 D (emitcode (";", "genOrOp "););
5358 /* note here that || operations that are in an
5359 if statement are taken away by backPatchLabels
5360 only those used in arthmetic operations remain */
5362 AOP_SET_LOCALS (ic);
5364 /* if both are bit variables */
5365 if (AOP_TYPE (left) == AOP_CRY &&
5366 AOP_TYPE (right) == AOP_CRY)
5368 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5369 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5370 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5371 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5373 aopOp (result,ic,FALSE, FALSE);
5379 tlbl = newiTempLabel (NULL);
5381 emitcode ("jnz", "%05d$", tlbl->key + 100);
5383 emitcode ("", "%05d$:", tlbl->key + 100);
5384 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5385 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5387 aopOp (result,ic,FALSE, FALSE);
5392 freeAsmop (result, NULL, ic, TRUE);
5395 /*-----------------------------------------------------------------*/
5396 /* isLiteralBit - test if lit == 2^n */
5397 /*-----------------------------------------------------------------*/
5399 isLiteralBit (unsigned long lit)
5401 unsigned long pw[32] =
5402 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5403 0x100L, 0x200L, 0x400L, 0x800L,
5404 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5405 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5406 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5407 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5408 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5411 for (idx = 0; idx < 32; idx++)
5417 /*-----------------------------------------------------------------*/
5418 /* continueIfTrue - */
5419 /*-----------------------------------------------------------------*/
5421 continueIfTrue (iCode * ic)
5424 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5428 /*-----------------------------------------------------------------*/
5430 /*-----------------------------------------------------------------*/
5432 jumpIfTrue (iCode * ic)
5435 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5439 /*-----------------------------------------------------------------*/
5440 /* jmpTrueOrFalse - */
5441 /*-----------------------------------------------------------------*/
5443 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5445 // ugly but optimized by peephole
5448 symbol *nlbl = newiTempLabel (NULL);
5449 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5450 emitcode ("", "%05d$:", tlbl->key + 100);
5451 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5452 emitcode ("", "%05d$:", nlbl->key + 100);
5456 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5457 emitcode ("", "%05d$:", tlbl->key + 100);
5462 // Generate code to perform a bit-wise logic operation
5463 // on two operands in far space (assumed to already have been
5464 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5465 // in far space. This requires pushing the result on the stack
5466 // then popping it into the result.
5468 genFarFarLogicOp(iCode *ic, char *logicOp)
5470 int size, resultSize, compSize;
5474 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5475 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5476 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5478 _startLazyDPSEvaluation();
5479 for (size = compSize; (size--); offset++)
5481 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5482 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5483 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5485 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5486 emitcode ("push", "acc");
5488 _endLazyDPSEvaluation();
5490 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5491 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5492 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5494 resultSize = AOP_SIZE(IC_RESULT(ic));
5496 ADJUST_PUSHED_RESULT(compSize, resultSize);
5498 _startLazyDPSEvaluation();
5501 emitcode ("pop", "acc");
5502 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5504 _endLazyDPSEvaluation();
5505 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5509 /*-----------------------------------------------------------------*/
5510 /* genAnd - code for and */
5511 /*-----------------------------------------------------------------*/
5513 genAnd (iCode * ic, iCode * ifx)
5515 operand *left, *right, *result;
5516 int size, offset = 0;
5517 unsigned long lit = 0L;
5522 D (emitcode (";", "genAnd "););
5524 AOP_OP_3_NOFATAL (ic, pushResult);
5525 AOP_SET_LOCALS (ic);
5529 genFarFarLogicOp(ic, "anl");
5534 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5536 AOP_TYPE (left), AOP_TYPE (right));
5537 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5539 AOP_SIZE (left), AOP_SIZE (right));
5542 /* if left is a literal & right is not then exchange them */
5543 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5544 #ifdef LOGIC_OPS_BROKEN
5545 || AOP_NEEDSACC (left)
5549 operand *tmp = right;
5554 /* if result = right then exchange them */
5555 if (sameRegs (AOP (result), AOP (right)))
5557 operand *tmp = right;
5562 /* if right is bit then exchange them */
5563 if (AOP_TYPE (right) == AOP_CRY &&
5564 AOP_TYPE (left) != AOP_CRY)
5566 operand *tmp = right;
5570 if (AOP_TYPE (right) == AOP_LIT)
5571 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5573 size = AOP_SIZE (result);
5576 // result = bit & yy;
5577 if (AOP_TYPE (left) == AOP_CRY)
5579 // c = bit & literal;
5580 if (AOP_TYPE (right) == AOP_LIT)
5584 if (size && sameRegs (AOP (result), AOP (left)))
5587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5592 if (size && (AOP_TYPE (result) == AOP_CRY))
5594 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5597 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5602 emitcode ("clr", "c");
5607 if (AOP_TYPE (right) == AOP_CRY)
5610 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5611 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5616 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5618 emitcode ("rrc", "a");
5619 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5627 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5628 genIfxJump (ifx, "c");
5632 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5633 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5634 if ((AOP_TYPE (right) == AOP_LIT) &&
5635 (AOP_TYPE (result) == AOP_CRY) &&
5636 (AOP_TYPE (left) != AOP_CRY))
5638 int posbit = isLiteralBit (lit);
5643 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5646 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5652 sprintf (buffer, "acc.%d", posbit & 0x07);
5653 genIfxJump (ifx, buffer);
5660 symbol *tlbl = newiTempLabel (NULL);
5661 int sizel = AOP_SIZE (left);
5663 emitcode ("setb", "c");
5666 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5668 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5670 if ((posbit = isLiteralBit (bytelit)) != 0)
5671 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5674 if (bytelit != 0x0FFL)
5675 emitcode ("anl", "a,%s",
5676 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5677 emitcode ("jnz", "%05d$", tlbl->key + 100);
5682 // bit = left & literal
5685 emitcode ("clr", "c");
5686 emitcode ("", "%05d$:", tlbl->key + 100);
5688 // if(left & literal)
5692 jmpTrueOrFalse (ifx, tlbl);
5700 /* if left is same as result */
5701 if (sameRegs (AOP (result), AOP (left)))
5703 for (; size--; offset++)
5705 if (AOP_TYPE (right) == AOP_LIT)
5707 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5709 else if (bytelit == 0)
5710 aopPut (AOP (result), zero, offset);
5711 else if (IS_AOP_PREG (result))
5713 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5714 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5715 aopPut (AOP (result), "a", offset);
5718 emitcode ("anl", "%s,%s",
5719 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5720 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5724 if (AOP_TYPE (left) == AOP_ACC)
5725 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5728 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5729 if (IS_AOP_PREG (result))
5731 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5732 aopPut (AOP (result), "a", offset);
5736 emitcode ("anl", "%s,a",
5737 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5744 // left & result in different registers
5745 if (AOP_TYPE (result) == AOP_CRY)
5748 // if(size), result in bit
5749 // if(!size && ifx), conditional oper: if(left & right)
5750 symbol *tlbl = newiTempLabel (NULL);
5751 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5753 emitcode ("setb", "c");
5756 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5757 emitcode ("anl", "a,%s",
5758 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5760 if (AOP_TYPE(left)==AOP_ACC) {
5761 emitcode("mov", "b,a");
5762 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5763 emitcode("anl", "a,b");
5765 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5766 emitcode ("anl", "a,%s",
5767 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5770 emitcode ("jnz", "%05d$", tlbl->key + 100);
5776 emitcode ("", "%05d$:", tlbl->key + 100);
5780 jmpTrueOrFalse (ifx, tlbl);
5784 for (; (size--); offset++)
5787 // result = left & right
5788 if (AOP_TYPE (right) == AOP_LIT)
5790 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5792 aopPut (AOP (result),
5793 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5797 else if (bytelit == 0)
5799 aopPut (AOP (result), zero, offset);
5802 D (emitcode (";", "better literal AND."););
5803 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5804 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5805 FALSE, FALSE, FALSE));
5810 // faster than result <- left, anl result,right
5811 // and better if result is SFR
5812 if (AOP_TYPE (left) == AOP_ACC)
5814 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5815 FALSE, FALSE, FALSE));
5819 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5820 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5822 emitcode("mov", "b,a");
5826 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5827 emitcode ("anl", "a,%s", rOp);
5830 aopPut (AOP (result), "a", offset);
5836 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5837 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5838 freeAsmop (result, NULL, ic, TRUE);
5842 /*-----------------------------------------------------------------*/
5843 /* genOr - code for or */
5844 /*-----------------------------------------------------------------*/
5846 genOr (iCode * ic, iCode * ifx)
5848 operand *left, *right, *result;
5849 int size, offset = 0;
5850 unsigned long lit = 0L;
5853 D (emitcode (";", "genOr "););
5855 AOP_OP_3_NOFATAL (ic, pushResult);
5856 AOP_SET_LOCALS (ic);
5860 genFarFarLogicOp(ic, "orl");
5866 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5868 AOP_TYPE (left), AOP_TYPE (right));
5869 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5871 AOP_SIZE (left), AOP_SIZE (right));
5874 /* if left is a literal & right is not then exchange them */
5875 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5876 #ifdef LOGIC_OPS_BROKEN
5877 || AOP_NEEDSACC (left) // I think this is a net loss now.
5881 operand *tmp = right;
5886 /* if result = right then exchange them */
5887 if (sameRegs (AOP (result), AOP (right)))
5889 operand *tmp = right;
5894 /* if right is bit then exchange them */
5895 if (AOP_TYPE (right) == AOP_CRY &&
5896 AOP_TYPE (left) != AOP_CRY)
5898 operand *tmp = right;
5902 if (AOP_TYPE (right) == AOP_LIT)
5903 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5905 size = AOP_SIZE (result);
5909 if (AOP_TYPE (left) == AOP_CRY)
5911 if (AOP_TYPE (right) == AOP_LIT)
5913 // c = bit & literal;
5916 // lit != 0 => result = 1
5917 if (AOP_TYPE (result) == AOP_CRY)
5920 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5922 continueIfTrue (ifx);
5925 emitcode ("setb", "c");
5929 // lit == 0 => result = left
5930 if (size && sameRegs (AOP (result), AOP (left)))
5932 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5937 if (AOP_TYPE (right) == AOP_CRY)
5940 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5941 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5946 symbol *tlbl = newiTempLabel (NULL);
5947 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5948 emitcode ("setb", "c");
5949 emitcode ("jb", "%s,%05d$",
5950 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5952 emitcode ("jnz", "%05d$", tlbl->key + 100);
5953 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5955 jmpTrueOrFalse (ifx, tlbl);
5961 emitcode ("", "%05d$:", tlbl->key + 100);
5970 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5971 genIfxJump (ifx, "c");
5975 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5976 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5977 if ((AOP_TYPE (right) == AOP_LIT) &&
5978 (AOP_TYPE (result) == AOP_CRY) &&
5979 (AOP_TYPE (left) != AOP_CRY))
5985 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5987 continueIfTrue (ifx);
5992 // lit = 0, result = boolean(left)
5994 emitcode ("setb", "c");
5998 symbol *tlbl = newiTempLabel (NULL);
5999 emitcode ("jnz", "%05d$", tlbl->key + 100);
6001 emitcode ("", "%05d$:", tlbl->key + 100);
6005 genIfxJump (ifx, "a");
6013 /* if left is same as result */
6014 if (sameRegs (AOP (result), AOP (left)))
6016 for (; size--; offset++)
6018 if (AOP_TYPE (right) == AOP_LIT)
6020 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6026 if (IS_AOP_PREG (left))
6028 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6029 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6030 aopPut (AOP (result), "a", offset);
6034 emitcode ("orl", "%s,%s",
6035 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6036 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6042 if (AOP_TYPE (left) == AOP_ACC)
6044 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6048 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6049 if (IS_AOP_PREG (left))
6051 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6052 aopPut (AOP (result), "a", offset);
6056 emitcode ("orl", "%s,a",
6057 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6065 // left & result in different registers
6066 if (AOP_TYPE (result) == AOP_CRY)
6069 // if(size), result in bit
6070 // if(!size && ifx), conditional oper: if(left | right)
6071 symbol *tlbl = newiTempLabel (NULL);
6072 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6074 emitcode ("setb", "c");
6077 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6078 emitcode ("orl", "a,%s",
6079 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6081 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6082 emitcode ("orl", "a,%s",
6083 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6085 emitcode ("jnz", "%05d$", tlbl->key + 100);
6091 emitcode ("", "%05d$:", tlbl->key + 100);
6095 jmpTrueOrFalse (ifx, tlbl);
6099 _startLazyDPSEvaluation();
6100 for (; (size--); offset++)
6103 // result = left & right
6104 if (AOP_TYPE (right) == AOP_LIT)
6106 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6108 aopPut (AOP (result),
6109 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6113 D (emitcode (";", "better literal OR."););
6114 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6115 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6116 FALSE, FALSE, FALSE));
6121 // faster than result <- left, anl result,right
6122 // and better if result is SFR
6123 if (AOP_TYPE (left) == AOP_ACC)
6125 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6126 FALSE, FALSE, FALSE));
6130 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6132 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6134 emitcode("mov", "b,a");
6138 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6139 emitcode ("orl", "a,%s", rOp);
6142 aopPut (AOP (result), "a", offset);
6144 _endLazyDPSEvaluation();
6149 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6150 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6151 freeAsmop (result, NULL, ic, TRUE);
6154 /*-----------------------------------------------------------------*/
6155 /* genXor - code for xclusive or */
6156 /*-----------------------------------------------------------------*/
6158 genXor (iCode * ic, iCode * ifx)
6160 operand *left, *right, *result;
6161 int size, offset = 0;
6162 unsigned long lit = 0L;
6165 D (emitcode (";", "genXor "););
6167 AOP_OP_3_NOFATAL (ic, pushResult);
6168 AOP_SET_LOCALS (ic);
6172 genFarFarLogicOp(ic, "xrl");
6177 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6179 AOP_TYPE (left), AOP_TYPE (right));
6180 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6182 AOP_SIZE (left), AOP_SIZE (right));
6185 /* if left is a literal & right is not ||
6186 if left needs acc & right does not */
6187 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6188 #ifdef LOGIC_OPS_BROKEN
6189 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6193 operand *tmp = right;
6198 /* if result = right then exchange them */
6199 if (sameRegs (AOP (result), AOP (right)))
6201 operand *tmp = right;
6206 /* if right is bit then exchange them */
6207 if (AOP_TYPE (right) == AOP_CRY &&
6208 AOP_TYPE (left) != AOP_CRY)
6210 operand *tmp = right;
6214 if (AOP_TYPE (right) == AOP_LIT)
6215 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6217 size = AOP_SIZE (result);
6221 if (AOP_TYPE (left) == AOP_CRY)
6223 if (AOP_TYPE (right) == AOP_LIT)
6225 // c = bit & literal;
6228 // lit>>1 != 0 => result = 1
6229 if (AOP_TYPE (result) == AOP_CRY)
6232 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6234 continueIfTrue (ifx);
6237 emitcode ("setb", "c");
6244 // lit == 0, result = left
6245 if (size && sameRegs (AOP (result), AOP (left)))
6247 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6251 // lit == 1, result = not(left)
6252 if (size && sameRegs (AOP (result), AOP (left)))
6254 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6259 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6260 emitcode ("cpl", "c");
6269 symbol *tlbl = newiTempLabel (NULL);
6270 if (AOP_TYPE (right) == AOP_CRY)
6273 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6277 int sizer = AOP_SIZE (right);
6279 // if val>>1 != 0, result = 1
6280 emitcode ("setb", "c");
6283 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6285 // test the msb of the lsb
6286 emitcode ("anl", "a,#0xfe");
6287 emitcode ("jnz", "%05d$", tlbl->key + 100);
6291 emitcode ("rrc", "a");
6293 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6294 emitcode ("cpl", "c");
6295 emitcode ("", "%05d$:", (tlbl->key + 100));
6302 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6303 genIfxJump (ifx, "c");
6307 if (sameRegs (AOP (result), AOP (left)))
6309 /* if left is same as result */
6310 for (; size--; offset++)
6312 if (AOP_TYPE (right) == AOP_LIT)
6314 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6316 else if (IS_AOP_PREG (left))
6318 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6319 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6320 aopPut (AOP (result), "a", offset);
6323 emitcode ("xrl", "%s,%s",
6324 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6325 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6329 if (AOP_TYPE (left) == AOP_ACC)
6330 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6334 if (IS_AOP_PREG (left))
6336 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6337 aopPut (AOP (result), "a", offset);
6340 emitcode ("xrl", "%s,a",
6341 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6348 // left & result in different registers
6349 if (AOP_TYPE (result) == AOP_CRY)
6352 // if(size), result in bit
6353 // if(!size && ifx), conditional oper: if(left ^ right)
6354 symbol *tlbl = newiTempLabel (NULL);
6355 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6357 emitcode ("setb", "c");
6360 if ((AOP_TYPE (right) == AOP_LIT) &&
6361 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6363 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6367 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6368 emitcode ("xrl", "a,%s",
6369 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6371 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6372 emitcode ("xrl", "a,%s",
6373 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6376 emitcode ("jnz", "%05d$", tlbl->key + 100);
6382 emitcode ("", "%05d$:", tlbl->key + 100);
6386 jmpTrueOrFalse (ifx, tlbl);
6389 for (; (size--); offset++)
6392 // result = left & right
6393 if (AOP_TYPE (right) == AOP_LIT)
6395 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6397 aopPut (AOP (result),
6398 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6402 D (emitcode (";", "better literal XOR.");
6404 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6405 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6406 FALSE, FALSE, FALSE));
6410 // faster than result <- left, anl result,right
6411 // and better if result is SFR
6412 if (AOP_TYPE (left) == AOP_ACC)
6414 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6415 FALSE, FALSE, FALSE));
6419 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6420 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6422 emitcode("mov", "b,a");
6426 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6427 emitcode ("xrl", "a,%s", rOp);
6430 aopPut (AOP (result), "a", offset);
6435 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6436 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6437 freeAsmop (result, NULL, ic, TRUE);
6440 /*-----------------------------------------------------------------*/
6441 /* genInline - write the inline code out */
6442 /*-----------------------------------------------------------------*/
6444 genInline (iCode * ic)
6446 char *buffer, *bp, *bp1;
6448 D (emitcode (";", "genInline ");
6451 _G.inLine += (!options.asmpeep);
6453 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6454 strcpy (buffer, IC_INLINE (ic));
6456 /* emit each line as a code */
6481 /* emitcode("",buffer); */
6482 _G.inLine -= (!options.asmpeep);
6485 /*-----------------------------------------------------------------*/
6486 /* genRRC - rotate right with carry */
6487 /*-----------------------------------------------------------------*/
6491 operand *left, *result;
6492 int size, offset = 0;
6495 D (emitcode (";", "genRRC ");
6498 /* rotate right with carry */
6499 left = IC_LEFT (ic);
6500 result = IC_RESULT (ic);
6501 aopOp (left, ic, FALSE, FALSE);
6502 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6504 /* move it to the result */
6505 size = AOP_SIZE (result);
6509 _startLazyDPSEvaluation ();
6512 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6514 emitcode ("rrc", "a");
6515 if (AOP_SIZE (result) > 1)
6516 aopPut (AOP (result), "a", offset--);
6518 _endLazyDPSEvaluation ();
6520 /* now we need to put the carry into the
6521 highest order byte of the result */
6522 if (AOP_SIZE (result) > 1)
6524 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6527 emitcode ("mov", "acc.7,c");
6528 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6529 freeAsmop (left, NULL, ic, TRUE);
6530 freeAsmop (result, NULL, ic, TRUE);
6533 /*-----------------------------------------------------------------*/
6534 /* genRLC - generate code for rotate left with carry */
6535 /*-----------------------------------------------------------------*/
6539 operand *left, *result;
6540 int size, offset = 0;
6543 D (emitcode (";", "genRLC ");
6546 /* rotate right with carry */
6547 left = IC_LEFT (ic);
6548 result = IC_RESULT (ic);
6549 aopOp (left, ic, FALSE, FALSE);
6550 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6552 /* move it to the result */
6553 size = AOP_SIZE (result);
6557 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6559 emitcode ("add", "a,acc");
6560 if (AOP_SIZE (result) > 1)
6562 aopPut (AOP (result), "a", offset++);
6565 _startLazyDPSEvaluation ();
6568 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6570 emitcode ("rlc", "a");
6571 if (AOP_SIZE (result) > 1)
6572 aopPut (AOP (result), "a", offset++);
6574 _endLazyDPSEvaluation ();
6576 /* now we need to put the carry into the
6577 highest order byte of the result */
6578 if (AOP_SIZE (result) > 1)
6580 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6583 emitcode ("mov", "acc.0,c");
6584 aopPut (AOP (result), "a", 0);
6585 freeAsmop (left, NULL, ic, TRUE);
6586 freeAsmop (result, NULL, ic, TRUE);
6589 /*-----------------------------------------------------------------*/
6590 /* genGetHbit - generates code get highest order bit */
6591 /*-----------------------------------------------------------------*/
6593 genGetHbit (iCode * ic)
6595 operand *left, *result;
6596 left = IC_LEFT (ic);
6597 result = IC_RESULT (ic);
6598 aopOp (left, ic, FALSE, FALSE);
6599 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6601 D (emitcode (";", "genGetHbit ");
6604 /* get the highest order byte into a */
6605 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6606 if (AOP_TYPE (result) == AOP_CRY)
6608 emitcode ("rlc", "a");
6613 emitcode ("rl", "a");
6614 emitcode ("anl", "a,#0x01");
6619 freeAsmop (left, NULL, ic, TRUE);
6620 freeAsmop (result, NULL, ic, TRUE);
6623 /*-----------------------------------------------------------------*/
6624 /* AccRol - rotate left accumulator by known count */
6625 /*-----------------------------------------------------------------*/
6627 AccRol (int shCount)
6629 shCount &= 0x0007; // shCount : 0..7
6636 emitcode ("rl", "a");
6639 emitcode ("rl", "a");
6640 emitcode ("rl", "a");
6643 emitcode ("swap", "a");
6644 emitcode ("rr", "a");
6647 emitcode ("swap", "a");
6650 emitcode ("swap", "a");
6651 emitcode ("rl", "a");
6654 emitcode ("rr", "a");
6655 emitcode ("rr", "a");
6658 emitcode ("rr", "a");
6663 /*-----------------------------------------------------------------*/
6664 /* AccLsh - left shift accumulator by known count */
6665 /*-----------------------------------------------------------------*/
6667 AccLsh (int shCount)
6672 emitcode ("add", "a,acc");
6673 else if (shCount == 2)
6675 emitcode ("add", "a,acc");
6676 emitcode ("add", "a,acc");
6680 /* rotate left accumulator */
6682 /* and kill the lower order bits */
6683 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6688 /*-----------------------------------------------------------------*/
6689 /* AccRsh - right shift accumulator by known count */
6690 /*-----------------------------------------------------------------*/
6692 AccRsh (int shCount)
6699 emitcode ("rrc", "a");
6703 /* rotate right accumulator */
6704 AccRol (8 - shCount);
6705 /* and kill the higher order bits */
6706 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6711 #ifdef BETTER_LITERAL_SHIFT
6712 /*-----------------------------------------------------------------*/
6713 /* AccSRsh - signed right shift accumulator by known count */
6714 /*-----------------------------------------------------------------*/
6716 AccSRsh (int shCount)
6723 emitcode ("mov", "c,acc.7");
6724 emitcode ("rrc", "a");
6726 else if (shCount == 2)
6728 emitcode ("mov", "c,acc.7");
6729 emitcode ("rrc", "a");
6730 emitcode ("mov", "c,acc.7");
6731 emitcode ("rrc", "a");
6735 tlbl = newiTempLabel (NULL);
6736 /* rotate right accumulator */
6737 AccRol (8 - shCount);
6738 /* and kill the higher order bits */
6739 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6740 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6741 emitcode ("orl", "a,#0x%02x",
6742 (unsigned char) ~SRMask[shCount]);
6743 emitcode ("", "%05d$:", tlbl->key + 100);
6749 #ifdef BETTER_LITERAL_SHIFT
6750 /*-----------------------------------------------------------------*/
6751 /* shiftR1Left2Result - shift right one byte from left to result */
6752 /*-----------------------------------------------------------------*/
6754 shiftR1Left2Result (operand * left, int offl,
6755 operand * result, int offr,
6756 int shCount, int sign)
6758 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6759 /* shift right accumulator */
6764 aopPut (AOP (result), "a", offr);
6768 #ifdef BETTER_LITERAL_SHIFT
6769 /*-----------------------------------------------------------------*/
6770 /* shiftL1Left2Result - shift left one byte from left to result */
6771 /*-----------------------------------------------------------------*/
6773 shiftL1Left2Result (operand * left, int offl,
6774 operand * result, int offr, int shCount)
6776 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6777 /* shift left accumulator */
6779 aopPut (AOP (result), "a", offr);
6783 #ifdef BETTER_LITERAL_SHIFT
6784 /*-----------------------------------------------------------------*/
6785 /* movLeft2Result - move byte from left to result */
6786 /*-----------------------------------------------------------------*/
6788 movLeft2Result (operand * left, int offl,
6789 operand * result, int offr, int sign)
6792 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6794 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6796 if (*l == '@' && (IS_AOP_PREG (result)))
6798 emitcode ("mov", "a,%s", l);
6799 aopPut (AOP (result), "a", offr);
6805 aopPut (AOP (result), l, offr);
6809 /* MSB sign in acc.7 ! */
6810 if (getDataSize (left) == offl + 1)
6812 emitcode ("mov", "a,%s", l);
6813 aopPut (AOP (result), "a", offr);
6821 #ifdef BETTER_LITERAL_SHIFT
6822 /*-----------------------------------------------------------------*/
6823 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6824 /*-----------------------------------------------------------------*/
6828 emitcode ("rrc", "a");
6829 emitcode ("xch", "a,%s", x);
6830 emitcode ("rrc", "a");
6831 emitcode ("xch", "a,%s", x);
6835 #ifdef BETTER_LITERAL_SHIFT
6837 /*-----------------------------------------------------------------*/
6838 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6839 /*-----------------------------------------------------------------*/
6843 emitcode ("xch", "a,%s", x);
6844 emitcode ("rlc", "a");
6845 emitcode ("xch", "a,%s", x);
6846 emitcode ("rlc", "a");
6850 #ifdef BETTER_LITERAL_SHIFT
6851 /*-----------------------------------------------------------------*/
6852 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6853 /*-----------------------------------------------------------------*/
6857 emitcode ("xch", "a,%s", x);
6858 emitcode ("add", "a,acc");
6859 emitcode ("xch", "a,%s", x);
6860 emitcode ("rlc", "a");
6864 #ifdef BETTER_LITERAL_SHIFT
6865 /*-----------------------------------------------------------------*/
6866 /* AccAXLsh - left shift a:x by known count (0..7) */
6867 /*-----------------------------------------------------------------*/
6869 AccAXLsh (char *x, int shCount)
6884 case 5: // AAAAABBB:CCCCCDDD
6886 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6888 emitcode ("anl", "a,#0x%02x",
6889 SLMask[shCount]); // BBB00000:CCCCCDDD
6891 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6893 AccRol (shCount); // DDDCCCCC:BBB00000
6895 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6897 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6899 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6901 emitcode ("anl", "a,#0x%02x",
6902 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6904 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6906 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6909 case 6: // AAAAAABB:CCCCCCDD
6910 emitcode ("anl", "a,#0x%02x",
6911 SRMask[shCount]); // 000000BB:CCCCCCDD
6912 emitcode ("mov", "c,acc.0"); // c = B
6913 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6915 AccAXRrl1 (x); // BCCCCCCD:D000000B
6916 AccAXRrl1 (x); // BBCCCCCC:DD000000
6918 emitcode("rrc","a");
6919 emitcode("xch","a,%s", x);
6920 emitcode("rrc","a");
6921 emitcode("mov","c,acc.0"); //<< get correct bit
6922 emitcode("xch","a,%s", x);
6924 emitcode("rrc","a");
6925 emitcode("xch","a,%s", x);
6926 emitcode("rrc","a");
6927 emitcode("xch","a,%s", x);
6930 case 7: // a:x <<= 7
6932 emitcode ("anl", "a,#0x%02x",
6933 SRMask[shCount]); // 0000000B:CCCCCCCD
6935 emitcode ("mov", "c,acc.0"); // c = B
6937 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6939 AccAXRrl1 (x); // BCCCCCCC:D0000000
6948 #ifdef BETTER_LITERAL_SHIFT
6950 /*-----------------------------------------------------------------*/
6951 /* AccAXRsh - right shift a:x known count (0..7) */
6952 /*-----------------------------------------------------------------*/
6954 AccAXRsh (char *x, int shCount)
6962 AccAXRrl1 (x); // 0->a:x
6967 AccAXRrl1 (x); // 0->a:x
6970 AccAXRrl1 (x); // 0->a:x
6975 case 5: // AAAAABBB:CCCCCDDD = a:x
6977 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6979 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6981 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6983 emitcode ("anl", "a,#0x%02x",
6984 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6986 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6988 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6990 emitcode ("anl", "a,#0x%02x",
6991 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6993 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6995 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6997 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7000 case 6: // AABBBBBB:CCDDDDDD
7002 emitcode ("mov", "c,acc.7");
7003 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7005 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7007 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7009 emitcode ("anl", "a,#0x%02x",
7010 SRMask[shCount]); // 000000AA:BBBBBBCC
7013 case 7: // ABBBBBBB:CDDDDDDD
7015 emitcode ("mov", "c,acc.7"); // c = A
7017 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7019 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7021 emitcode ("anl", "a,#0x%02x",
7022 SRMask[shCount]); // 0000000A:BBBBBBBC
7031 #ifdef BETTER_LITERAL_SHIFT
7032 /*-----------------------------------------------------------------*/
7033 /* AccAXRshS - right shift signed a:x known count (0..7) */
7034 /*-----------------------------------------------------------------*/
7036 AccAXRshS (char *x, int shCount)
7044 emitcode ("mov", "c,acc.7");
7045 AccAXRrl1 (x); // s->a:x
7049 emitcode ("mov", "c,acc.7");
7050 AccAXRrl1 (x); // s->a:x
7052 emitcode ("mov", "c,acc.7");
7053 AccAXRrl1 (x); // s->a:x
7058 case 5: // AAAAABBB:CCCCCDDD = a:x
7060 tlbl = newiTempLabel (NULL);
7061 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7063 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7065 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7067 emitcode ("anl", "a,#0x%02x",
7068 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7070 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7072 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7074 emitcode ("anl", "a,#0x%02x",
7075 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7077 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7079 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7081 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7083 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7084 emitcode ("orl", "a,#0x%02x",
7085 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7087 emitcode ("", "%05d$:", tlbl->key + 100);
7088 break; // SSSSAAAA:BBBCCCCC
7090 case 6: // AABBBBBB:CCDDDDDD
7092 tlbl = newiTempLabel (NULL);
7093 emitcode ("mov", "c,acc.7");
7094 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7096 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7098 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7100 emitcode ("anl", "a,#0x%02x",
7101 SRMask[shCount]); // 000000AA:BBBBBBCC
7103 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7104 emitcode ("orl", "a,#0x%02x",
7105 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7107 emitcode ("", "%05d$:", tlbl->key + 100);
7109 case 7: // ABBBBBBB:CDDDDDDD
7111 tlbl = newiTempLabel (NULL);
7112 emitcode ("mov", "c,acc.7"); // c = A
7114 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7116 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7118 emitcode ("anl", "a,#0x%02x",
7119 SRMask[shCount]); // 0000000A:BBBBBBBC
7121 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7122 emitcode ("orl", "a,#0x%02x",
7123 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7125 emitcode ("", "%05d$:", tlbl->key + 100);
7133 #ifdef BETTER_LITERAL_SHIFT
7135 _loadLeftIntoAx(char **lsb,
7141 // Get the initial value from left into a pair of registers.
7142 // MSB must be in A, LSB can be any register.
7144 // If the result is held in registers, it is an optimization
7145 // if the LSB can be held in the register which will hold the,
7146 // result LSB since this saves us from having to copy it into
7147 // the result following AccAXLsh.
7149 // If the result is addressed indirectly, this is not a gain.
7150 if (AOP_NEEDSACC(result))
7154 _startLazyDPSEvaluation();
7155 if (AOP_TYPE(left) == AOP_DPTR2)
7158 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7159 // get LSB in DP2_RESULT_REG.
7160 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7161 assert(!strcmp(leftByte, DP2_RESULT_REG));
7165 // get LSB into DP2_RESULT_REG
7166 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7167 if (strcmp(leftByte, DP2_RESULT_REG))
7170 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7173 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7174 assert(strcmp(leftByte, DP2_RESULT_REG));
7177 _endLazyDPSEvaluation();
7178 *lsb = DP2_RESULT_REG;
7182 if (sameRegs (AOP (result), AOP (left)) &&
7183 ((offl + MSB16) == offr))
7185 /* don't crash result[offr] */
7186 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7187 emitcode ("xch", "a,%s",
7188 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7192 movLeft2Result (left, offl, result, offr, 0);
7193 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7195 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7196 assert(strcmp(*lsb,"a"));
7201 _storeAxResults(char *lsb,
7205 _startLazyDPSEvaluation();
7206 if (AOP_NEEDSACC(result))
7208 /* We have to explicitly update the result LSB.
7210 emitcode("xch","a,%s", lsb);
7211 aopPut(AOP(result), "a", offr);
7212 emitcode("mov","a,%s", lsb);
7214 if (getDataSize (result) > 1)
7216 aopPut (AOP (result), "a", offr + MSB16);
7218 _endLazyDPSEvaluation();
7221 /*-----------------------------------------------------------------*/
7222 /* shiftL2Left2Result - shift left two bytes from left to result */
7223 /*-----------------------------------------------------------------*/
7225 shiftL2Left2Result (operand * left, int offl,
7226 operand * result, int offr, int shCount)
7230 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7232 AccAXLsh (lsb, shCount);
7234 _storeAxResults(lsb, result, offr);
7238 #ifdef BETTER_LITERAL_SHIFT
7239 /*-----------------------------------------------------------------*/
7240 /* shiftR2Left2Result - shift right two bytes from left to result */
7241 /*-----------------------------------------------------------------*/
7243 shiftR2Left2Result (operand * left, int offl,
7244 operand * result, int offr,
7245 int shCount, int sign)
7249 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7251 /* a:x >> shCount (x = lsb(result)) */
7254 AccAXRshS(lsb, shCount);
7258 AccAXRsh(lsb, shCount);
7261 _storeAxResults(lsb, result, offr);
7267 /*-----------------------------------------------------------------*/
7268 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7269 /*-----------------------------------------------------------------*/
7271 shiftLLeftOrResult (operand * left, int offl,
7272 operand * result, int offr, int shCount)
7274 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7275 /* shift left accumulator */
7277 /* or with result */
7278 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7279 /* back to result */
7280 aopPut (AOP (result), "a", offr);
7286 /*-----------------------------------------------------------------*/
7287 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7288 /*-----------------------------------------------------------------*/
7290 shiftRLeftOrResult (operand * left, int offl,
7291 operand * result, int offr, int shCount)
7293 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7294 /* shift right accumulator */
7296 /* or with result */
7297 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7298 /* back to result */
7299 aopPut (AOP (result), "a", offr);
7303 #ifdef BETTER_LITERAL_SHIFT
7304 /*-----------------------------------------------------------------*/
7305 /* genlshOne - left shift a one byte quantity by known count */
7306 /*-----------------------------------------------------------------*/
7308 genlshOne (operand * result, operand * left, int shCount)
7310 D (emitcode (";", "genlshOne "););
7311 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7315 #ifdef BETTER_LITERAL_SHIFT
7316 /*-----------------------------------------------------------------*/
7317 /* genlshTwo - left shift two bytes by known amount != 0 */
7318 /*-----------------------------------------------------------------*/
7320 genlshTwo (operand * result, operand * left, int shCount)
7324 D (emitcode (";", "genlshTwo "););
7326 size = getDataSize (result);
7328 /* if shCount >= 8 */
7333 _startLazyDPSEvaluation();
7339 _endLazyDPSEvaluation();
7340 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7341 aopPut (AOP (result), zero, LSB);
7345 movLeft2Result (left, LSB, result, MSB16, 0);
7346 aopPut (AOP (result), zero, LSB);
7347 _endLazyDPSEvaluation();
7352 aopPut (AOP (result), zero, LSB);
7353 _endLazyDPSEvaluation();
7357 /* 1 <= shCount <= 7 */
7362 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7366 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7374 /*-----------------------------------------------------------------*/
7375 /* shiftLLong - shift left one long from left to result */
7376 /* offl = LSB or MSB16 */
7377 /*-----------------------------------------------------------------*/
7379 shiftLLong (operand * left, operand * result, int offr)
7382 int size = AOP_SIZE (result);
7384 if (size >= LSB + offr)
7386 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7388 emitcode ("add", "a,acc");
7389 if (sameRegs (AOP (left), AOP (result)) &&
7390 size >= MSB16 + offr && offr != LSB)
7391 emitcode ("xch", "a,%s",
7392 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7394 aopPut (AOP (result), "a", LSB + offr);
7397 if (size >= MSB16 + offr)
7399 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7401 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7404 emitcode ("rlc", "a");
7405 if (sameRegs (AOP (left), AOP (result)) &&
7406 size >= MSB24 + offr && offr != LSB)
7407 emitcode ("xch", "a,%s",
7408 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7410 aopPut (AOP (result), "a", MSB16 + offr);
7413 if (size >= MSB24 + offr)
7415 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7417 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7420 emitcode ("rlc", "a");
7421 if (sameRegs (AOP (left), AOP (result)) &&
7422 size >= MSB32 + offr && offr != LSB)
7423 emitcode ("xch", "a,%s",
7424 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7426 aopPut (AOP (result), "a", MSB24 + offr);
7429 if (size > MSB32 + offr)
7431 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7433 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7436 emitcode ("rlc", "a");
7437 aopPut (AOP (result), "a", MSB32 + offr);
7440 aopPut (AOP (result), zero, LSB);
7446 /*-----------------------------------------------------------------*/
7447 /* genlshFour - shift four byte by a known amount != 0 */
7448 /*-----------------------------------------------------------------*/
7450 genlshFour (operand * result, operand * left, int shCount)
7454 D (emitcode (";", "genlshFour ");
7457 size = AOP_SIZE (result);
7459 /* if shifting more that 3 bytes */
7464 /* lowest order of left goes to the highest
7465 order of the destination */
7466 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7468 movLeft2Result (left, LSB, result, MSB32, 0);
7469 aopPut (AOP (result), zero, LSB);
7470 aopPut (AOP (result), zero, MSB16);
7471 aopPut (AOP (result), zero, MSB24);
7475 /* more than two bytes */
7476 else if (shCount >= 16)
7478 /* lower order two bytes goes to higher order two bytes */
7480 /* if some more remaining */
7482 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7485 movLeft2Result (left, MSB16, result, MSB32, 0);
7486 movLeft2Result (left, LSB, result, MSB24, 0);
7488 aopPut (AOP (result), zero, MSB16);
7489 aopPut (AOP (result), zero, LSB);
7493 /* if more than 1 byte */
7494 else if (shCount >= 8)
7496 /* lower order three bytes goes to higher order three bytes */
7501 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7503 movLeft2Result (left, LSB, result, MSB16, 0);
7509 movLeft2Result (left, MSB24, result, MSB32, 0);
7510 movLeft2Result (left, MSB16, result, MSB24, 0);
7511 movLeft2Result (left, LSB, result, MSB16, 0);
7512 aopPut (AOP (result), zero, LSB);
7514 else if (shCount == 1)
7515 shiftLLong (left, result, MSB16);
7518 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7519 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7520 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7521 aopPut (AOP (result), zero, LSB);
7526 /* 1 <= shCount <= 7 */
7527 else if (shCount <= 2)
7529 shiftLLong (left, result, LSB);
7531 shiftLLong (result, result, LSB);
7533 /* 3 <= shCount <= 7, optimize */
7536 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7537 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7538 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7543 #ifdef BETTER_LITERAL_SHIFT
7544 /*-----------------------------------------------------------------*/
7545 /* genLeftShiftLiteral - left shifting by known count */
7546 /*-----------------------------------------------------------------*/
7548 genLeftShiftLiteral (operand * left,
7553 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7556 size = getSize (operandType (result));
7558 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7560 /* We only handle certain easy cases so far. */
7562 && (shCount < (size * 8))
7566 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7570 freeAsmop (right, NULL, ic, TRUE);
7572 aopOp(left, ic, FALSE, FALSE);
7573 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7576 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7578 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7579 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7581 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7584 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7586 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7587 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7589 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7595 emitcode ("; shift left ", "result %d, left %d", size,
7599 /* I suppose that the left size >= result size */
7602 _startLazyDPSEvaluation();
7605 movLeft2Result (left, size, result, size, 0);
7607 _endLazyDPSEvaluation();
7609 else if (shCount >= (size * 8))
7611 _startLazyDPSEvaluation();
7614 aopPut (AOP (result), zero, size);
7616 _endLazyDPSEvaluation();
7623 genlshOne (result, left, shCount);
7627 genlshTwo (result, left, shCount);
7631 genlshFour (result, left, shCount);
7635 fprintf(stderr, "*** ack! mystery literal shift!\n");
7639 freeAsmop (left, NULL, ic, TRUE);
7640 freeAsmop (result, NULL, ic, TRUE);
7645 /*-----------------------------------------------------------------*/
7646 /* genLeftShift - generates code for left shifting */
7647 /*-----------------------------------------------------------------*/
7649 genLeftShift (iCode * ic)
7651 operand *left, *right, *result;
7654 symbol *tlbl, *tlbl1;
7656 D (emitcode (";", "genLeftShift "););
7658 right = IC_RIGHT (ic);
7659 left = IC_LEFT (ic);
7660 result = IC_RESULT (ic);
7662 aopOp (right, ic, FALSE, FALSE);
7665 #ifdef BETTER_LITERAL_SHIFT
7666 /* if the shift count is known then do it
7667 as efficiently as possible */
7668 if (AOP_TYPE (right) == AOP_LIT)
7670 if (genLeftShiftLiteral (left, right, result, ic))
7677 /* shift count is unknown then we have to form
7678 a loop get the loop count in B : Note: we take
7679 only the lower order byte since shifting
7680 more that 32 bits make no sense anyway, ( the
7681 largest size of an object can be only 32 bits ) */
7683 if (AOP_TYPE (right) == AOP_LIT)
7685 /* Really should be handled by genLeftShiftLiteral,
7686 * but since I'm too lazy to fix that today, at least we can make
7687 * some small improvement.
7689 emitcode("mov", "b,#0x%02x",
7690 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7694 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7695 emitcode ("inc", "b");
7697 freeAsmop (right, NULL, ic, TRUE);
7698 aopOp (left, ic, FALSE, FALSE);
7699 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7701 /* now move the left to the result if they are not the
7703 if (!sameRegs (AOP (left), AOP (result)) &&
7704 AOP_SIZE (result) > 1)
7707 size = AOP_SIZE (result);
7709 _startLazyDPSEvaluation ();
7712 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7713 if (*l == '@' && (IS_AOP_PREG (result)))
7716 emitcode ("mov", "a,%s", l);
7717 aopPut (AOP (result), "a", offset);
7720 aopPut (AOP (result), l, offset);
7723 _endLazyDPSEvaluation ();
7726 tlbl = newiTempLabel (NULL);
7727 size = AOP_SIZE (result);
7729 tlbl1 = newiTempLabel (NULL);
7731 /* if it is only one byte then */
7734 symbol *tlbl1 = newiTempLabel (NULL);
7736 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7738 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7739 emitcode ("", "%05d$:", tlbl->key + 100);
7740 emitcode ("add", "a,acc");
7741 emitcode ("", "%05d$:", tlbl1->key + 100);
7742 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7743 aopPut (AOP (result), "a", 0);
7747 reAdjustPreg (AOP (result));
7749 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7750 emitcode ("", "%05d$:", tlbl->key + 100);
7751 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7753 emitcode ("add", "a,acc");
7754 aopPut (AOP (result), "a", offset++);
7755 _startLazyDPSEvaluation ();
7758 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7760 emitcode ("rlc", "a");
7761 aopPut (AOP (result), "a", offset++);
7763 _endLazyDPSEvaluation ();
7764 reAdjustPreg (AOP (result));
7766 emitcode ("", "%05d$:", tlbl1->key + 100);
7767 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7769 freeAsmop (left, NULL, ic, TRUE);
7770 freeAsmop (result, NULL, ic, TRUE);
7773 #ifdef BETTER_LITERAL_SHIFT
7774 /*-----------------------------------------------------------------*/
7775 /* genrshOne - right shift a one byte quantity by known count */
7776 /*-----------------------------------------------------------------*/
7778 genrshOne (operand * result, operand * left,
7779 int shCount, int sign)
7781 D (emitcode (";", "genrshOne"););
7782 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7786 #ifdef BETTER_LITERAL_SHIFT
7787 /*-----------------------------------------------------------------*/
7788 /* genrshTwo - right shift two bytes by known amount != 0 */
7789 /*-----------------------------------------------------------------*/
7791 genrshTwo (operand * result, operand * left,
7792 int shCount, int sign)
7794 D (emitcode (";", "genrshTwo"););
7796 /* if shCount >= 8 */
7800 _startLazyDPSEvaluation();
7803 shiftR1Left2Result (left, MSB16, result, LSB,
7808 movLeft2Result (left, MSB16, result, LSB, sign);
7810 addSign (result, MSB16, sign);
7811 _endLazyDPSEvaluation();
7814 /* 1 <= shCount <= 7 */
7817 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7824 /*-----------------------------------------------------------------*/
7825 /* shiftRLong - shift right one long from left to result */
7826 /* offl = LSB or MSB16 */
7827 /*-----------------------------------------------------------------*/
7829 shiftRLong (operand * left, int offl,
7830 operand * result, int sign)
7832 int isSameRegs=sameRegs(AOP(left),AOP(result));
7834 if (isSameRegs && offl>1) {
7835 // we are in big trouble, but this shouldn't happen
7836 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7839 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7844 emitcode ("rlc", "a");
7845 emitcode ("subb", "a,acc");
7846 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7848 aopPut (AOP(result), zero, MSB32);
7853 emitcode ("clr", "c");
7855 emitcode ("mov", "c,acc.7");
7858 emitcode ("rrc", "a");
7860 if (isSameRegs && offl==MSB16) {
7861 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7863 aopPut (AOP (result), "a", MSB32);
7864 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7867 emitcode ("rrc", "a");
7868 if (isSameRegs && offl==1) {
7869 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7871 aopPut (AOP (result), "a", MSB24);
7872 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7874 emitcode ("rrc", "a");
7875 aopPut (AOP (result), "a", MSB16 - offl);
7879 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7880 emitcode ("rrc", "a");
7881 aopPut (AOP (result), "a", LSB);
7888 /*-----------------------------------------------------------------*/
7889 /* genrshFour - shift four byte by a known amount != 0 */
7890 /*-----------------------------------------------------------------*/
7892 genrshFour (operand * result, operand * left,
7893 int shCount, int sign)
7895 D (emitcode (";", "genrshFour");
7898 /* if shifting more that 3 bytes */
7903 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7905 movLeft2Result (left, MSB32, result, LSB, sign);
7906 addSign (result, MSB16, sign);
7908 else if (shCount >= 16)
7912 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7915 movLeft2Result (left, MSB24, result, LSB, 0);
7916 movLeft2Result (left, MSB32, result, MSB16, sign);
7918 addSign (result, MSB24, sign);
7920 else if (shCount >= 8)
7924 shiftRLong (left, MSB16, result, sign);
7925 else if (shCount == 0)
7927 movLeft2Result (left, MSB16, result, LSB, 0);
7928 movLeft2Result (left, MSB24, result, MSB16, 0);
7929 movLeft2Result (left, MSB32, result, MSB24, sign);
7930 addSign (result, MSB32, sign);
7934 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7935 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7936 /* the last shift is signed */
7937 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7938 addSign (result, MSB32, sign);
7942 { /* 1 <= shCount <= 7 */
7945 shiftRLong (left, LSB, result, sign);
7947 shiftRLong (result, LSB, result, sign);
7951 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7952 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7953 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7959 #ifdef BETTER_LITERAL_SHIFT
7960 /*-----------------------------------------------------------------*/
7961 /* genRightShiftLiteral - right shifting by known count */
7962 /*-----------------------------------------------------------------*/
7964 genRightShiftLiteral (operand * left,
7970 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7973 size = getSize (operandType (result));
7975 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7977 /* We only handle certain easy cases so far. */
7979 && (shCount < (size * 8))
7983 D(emitcode (";", "genRightShiftLiteral wimping out"););
7987 freeAsmop (right, NULL, ic, TRUE);
7989 aopOp (left, ic, FALSE, FALSE);
7990 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7993 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7997 /* test the LEFT size !!! */
7999 /* I suppose that the left size >= result size */
8002 size = getDataSize (result);
8003 _startLazyDPSEvaluation();
8006 movLeft2Result (left, size, result, size, 0);
8008 _endLazyDPSEvaluation();
8010 else if (shCount >= (size * 8))
8014 /* get sign in acc.7 */
8015 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8017 addSign (result, LSB, sign);
8024 genrshOne (result, left, shCount, sign);
8028 genrshTwo (result, left, shCount, sign);
8032 genrshFour (result, left, shCount, sign);
8039 freeAsmop (left, NULL, ic, TRUE);
8040 freeAsmop (result, NULL, ic, TRUE);
8046 /*-----------------------------------------------------------------*/
8047 /* genSignedRightShift - right shift of signed number */
8048 /*-----------------------------------------------------------------*/
8050 genSignedRightShift (iCode * ic)
8052 operand *right, *left, *result;
8055 symbol *tlbl, *tlbl1;
8057 D (emitcode (";", "genSignedRightShift "););
8059 /* we do it the hard way put the shift count in b
8060 and loop thru preserving the sign */
8062 right = IC_RIGHT (ic);
8063 left = IC_LEFT (ic);
8064 result = IC_RESULT (ic);
8066 aopOp (right, ic, FALSE, FALSE);
8068 #ifdef BETTER_LITERAL_SHIFT
8069 if (AOP_TYPE (right) == AOP_LIT)
8071 if (genRightShiftLiteral (left, right, result, ic, 1))
8077 /* shift count is unknown then we have to form
8078 a loop get the loop count in B : Note: we take
8079 only the lower order byte since shifting
8080 more that 32 bits make no sense anyway, ( the
8081 largest size of an object can be only 32 bits ) */
8083 if (AOP_TYPE (right) == AOP_LIT)
8085 /* Really should be handled by genRightShiftLiteral,
8086 * but since I'm too lazy to fix that today, at least we can make
8087 * some small improvement.
8089 emitcode("mov", "b,#0x%02x",
8090 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8094 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8095 emitcode ("inc", "b");
8097 freeAsmop (right, NULL, ic, TRUE);
8098 aopOp (left, ic, FALSE, FALSE);
8099 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8101 /* now move the left to the result if they are not the
8103 if (!sameRegs (AOP (left), AOP (result)) &&
8104 AOP_SIZE (result) > 1)
8107 size = AOP_SIZE (result);
8109 _startLazyDPSEvaluation ();
8112 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8113 if (*l == '@' && IS_AOP_PREG (result))
8116 emitcode ("mov", "a,%s", l);
8117 aopPut (AOP (result), "a", offset);
8120 aopPut (AOP (result), l, offset);
8123 _endLazyDPSEvaluation ();
8126 /* mov the highest order bit to OVR */
8127 tlbl = newiTempLabel (NULL);
8128 tlbl1 = newiTempLabel (NULL);
8130 size = AOP_SIZE (result);
8132 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8133 emitcode ("rlc", "a");
8134 emitcode ("mov", "ov,c");
8135 /* if it is only one byte then */
8138 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8140 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8141 emitcode ("", "%05d$:", tlbl->key + 100);
8142 emitcode ("mov", "c,ov");
8143 emitcode ("rrc", "a");
8144 emitcode ("", "%05d$:", tlbl1->key + 100);
8145 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8146 aopPut (AOP (result), "a", 0);
8150 reAdjustPreg (AOP (result));
8151 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8152 emitcode ("", "%05d$:", tlbl->key + 100);
8153 emitcode ("mov", "c,ov");
8154 _startLazyDPSEvaluation ();
8157 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8159 emitcode ("rrc", "a");
8160 aopPut (AOP (result), "a", offset--);
8162 _endLazyDPSEvaluation ();
8163 reAdjustPreg (AOP (result));
8164 emitcode ("", "%05d$:", tlbl1->key + 100);
8165 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8168 freeAsmop (left, NULL, ic, TRUE);
8169 freeAsmop (result, NULL, ic, TRUE);
8172 /*-----------------------------------------------------------------*/
8173 /* genRightShift - generate code for right shifting */
8174 /*-----------------------------------------------------------------*/
8176 genRightShift (iCode * ic)
8178 operand *right, *left, *result;
8182 symbol *tlbl, *tlbl1;
8184 D (emitcode (";", "genRightShift "););
8186 /* if signed then we do it the hard way preserve the
8187 sign bit moving it inwards */
8188 retype = getSpec (operandType (IC_RESULT (ic)));
8190 if (!SPEC_USIGN (retype))
8192 genSignedRightShift (ic);
8196 /* signed & unsigned types are treated the same : i.e. the
8197 signed is NOT propagated inwards : quoting from the
8198 ANSI - standard : "for E1 >> E2, is equivalent to division
8199 by 2**E2 if unsigned or if it has a non-negative value,
8200 otherwise the result is implementation defined ", MY definition
8201 is that the sign does not get propagated */
8203 right = IC_RIGHT (ic);
8204 left = IC_LEFT (ic);
8205 result = IC_RESULT (ic);
8207 aopOp (right, ic, FALSE, FALSE);
8209 #ifdef BETTER_LITERAL_SHIFT
8210 /* if the shift count is known then do it
8211 as efficiently as possible */
8212 if (AOP_TYPE (right) == AOP_LIT)
8214 if (genRightShiftLiteral (left, right, result, ic, 0))
8221 /* shift count is unknown then we have to form
8222 a loop get the loop count in B : Note: we take
8223 only the lower order byte since shifting
8224 more that 32 bits make no sense anyway, ( the
8225 largest size of an object can be only 32 bits ) */
8227 if (AOP_TYPE (right) == AOP_LIT)
8229 /* Really should be handled by genRightShiftLiteral,
8230 * but since I'm too lazy to fix that today, at least we can make
8231 * some small improvement.
8233 emitcode("mov", "b,#0x%02x",
8234 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8238 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8239 emitcode ("inc", "b");
8241 freeAsmop (right, NULL, ic, TRUE);
8242 aopOp (left, ic, FALSE, FALSE);
8243 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8245 /* now move the left to the result if they are not the
8247 if (!sameRegs (AOP (left), AOP (result)) &&
8248 AOP_SIZE (result) > 1)
8251 size = AOP_SIZE (result);
8253 _startLazyDPSEvaluation ();
8256 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8257 if (*l == '@' && IS_AOP_PREG (result))
8260 emitcode ("mov", "a,%s", l);
8261 aopPut (AOP (result), "a", offset);
8264 aopPut (AOP (result), l, offset);
8267 _endLazyDPSEvaluation ();
8270 tlbl = newiTempLabel (NULL);
8271 tlbl1 = newiTempLabel (NULL);
8272 size = AOP_SIZE (result);
8275 /* if it is only one byte then */
8278 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8280 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8281 emitcode ("", "%05d$:", tlbl->key + 100);
8283 emitcode ("rrc", "a");
8284 emitcode ("", "%05d$:", tlbl1->key + 100);
8285 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8286 aopPut (AOP (result), "a", 0);
8290 reAdjustPreg (AOP (result));
8291 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8292 emitcode ("", "%05d$:", tlbl->key + 100);
8294 _startLazyDPSEvaluation ();
8297 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8299 emitcode ("rrc", "a");
8300 aopPut (AOP (result), "a", offset--);
8302 _endLazyDPSEvaluation ();
8303 reAdjustPreg (AOP (result));
8305 emitcode ("", "%05d$:", tlbl1->key + 100);
8306 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8309 freeAsmop (left, NULL, ic, TRUE);
8310 freeAsmop (result, NULL, ic, TRUE);
8313 /*-----------------------------------------------------------------*/
8314 /* genUnpackBits - generates code for unpacking bits */
8315 /*-----------------------------------------------------------------*/
8317 genUnpackBits (operand * result, char *rname, int ptype)
8324 D (emitcode (";", "genUnpackBits ");
8327 etype = getSpec (operandType (result));
8329 /* read the first byte */
8335 emitcode ("mov", "a,@%s", rname);
8339 emitcode ("movx", "a,@%s", rname);
8343 emitcode ("movx", "a,@dptr");
8347 emitcode ("clr", "a");
8348 emitcode ("movc", "a,@a+dptr");
8352 emitcode ("lcall", "__gptrget");
8356 /* if we have bitdisplacement then it fits */
8357 /* into this byte completely or if length is */
8358 /* less than a byte */
8359 if ((shCnt = SPEC_BSTR (etype)) ||
8360 (SPEC_BLEN (etype) <= 8))
8363 /* shift right acc */
8366 emitcode ("anl", "a,#0x%02x",
8367 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8368 aopPut (AOP (result), "a", offset);
8372 /* bit field did not fit in a byte */
8373 rlen = SPEC_BLEN (etype) - 8;
8374 aopPut (AOP (result), "a", offset++);
8383 emitcode ("inc", "%s", rname);
8384 emitcode ("mov", "a,@%s", rname);
8388 emitcode ("inc", "%s", rname);
8389 emitcode ("movx", "a,@%s", rname);
8393 emitcode ("inc", "dptr");
8394 emitcode ("movx", "a,@dptr");
8398 emitcode ("clr", "a");
8399 emitcode ("inc", "dptr");
8400 emitcode ("movc", "a,@a+dptr");
8404 emitcode ("inc", "dptr");
8405 emitcode ("lcall", "__gptrget");
8410 /* if we are done */
8414 aopPut (AOP (result), "a", offset++);
8420 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8421 aopPut (AOP (result), "a", offset);
8428 /*-----------------------------------------------------------------*/
8429 /* genDataPointerGet - generates code when ptr offset is known */
8430 /*-----------------------------------------------------------------*/
8432 genDataPointerGet (operand * left,
8438 int size, offset = 0;
8439 aopOp (result, ic, TRUE, FALSE);
8441 /* get the string representation of the name */
8442 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8443 size = AOP_SIZE (result);
8444 _startLazyDPSEvaluation ();
8448 sprintf (buffer, "(%s + %d)", l + 1, offset);
8450 sprintf (buffer, "%s", l + 1);
8451 aopPut (AOP (result), buffer, offset++);
8453 _endLazyDPSEvaluation ();
8455 freeAsmop (left, NULL, ic, TRUE);
8456 freeAsmop (result, NULL, ic, TRUE);
8459 /*-----------------------------------------------------------------*/
8460 /* genNearPointerGet - emitcode for near pointer fetch */
8461 /*-----------------------------------------------------------------*/
8463 genNearPointerGet (operand * left,
8470 sym_link *rtype, *retype, *letype;
8471 sym_link *ltype = operandType (left);
8474 rtype = operandType (result);
8475 retype = getSpec (rtype);
8476 letype = getSpec (ltype);
8478 aopOp (left, ic, FALSE, FALSE);
8480 /* if left is rematerialisable and
8481 result is not bit variable type and
8482 the left is pointer to data space i.e
8483 lower 128 bytes of space */
8484 if (AOP_TYPE (left) == AOP_IMMD &&
8485 !IS_BITVAR (retype) &&
8486 !IS_BITVAR (letype) &&
8487 DCL_TYPE (ltype) == POINTER)
8489 genDataPointerGet (left, result, ic);
8493 /* if the value is already in a pointer register
8494 then don't need anything more */
8495 if (!AOP_INPREG (AOP (left)))
8497 /* otherwise get a free pointer register */
8499 preg = getFreePtr (ic, &aop, FALSE);
8500 emitcode ("mov", "%s,%s",
8502 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8506 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8508 freeAsmop (left, NULL, ic, TRUE);
8509 aopOp (result, ic, FALSE, FALSE);
8511 /* if bitfield then unpack the bits */
8512 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8513 genUnpackBits (result, rname, POINTER);
8516 /* we have can just get the values */
8517 int size = AOP_SIZE (result);
8522 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8525 emitcode ("mov", "a,@%s", rname);
8526 aopPut (AOP (result), "a", offset);
8530 sprintf (buffer, "@%s", rname);
8531 aopPut (AOP (result), buffer, offset);
8535 emitcode ("inc", "%s", rname);
8539 /* now some housekeeping stuff */
8542 /* we had to allocate for this iCode */
8543 freeAsmop (NULL, aop, ic, TRUE);
8547 /* we did not allocate which means left
8548 already in a pointer register, then
8549 if size > 0 && this could be used again
8550 we have to point it back to where it
8552 if (AOP_SIZE (result) > 1 &&
8553 !OP_SYMBOL (left)->remat &&
8554 (OP_SYMBOL (left)->liveTo > ic->seq ||
8557 int size = AOP_SIZE (result) - 1;
8559 emitcode ("dec", "%s", rname);
8564 freeAsmop (result, NULL, ic, TRUE);
8568 /*-----------------------------------------------------------------*/
8569 /* genPagedPointerGet - emitcode for paged pointer fetch */
8570 /*-----------------------------------------------------------------*/
8572 genPagedPointerGet (operand * left,
8579 sym_link *rtype, *retype, *letype;
8581 rtype = operandType (result);
8582 retype = getSpec (rtype);
8583 letype = getSpec (operandType (left));
8584 aopOp (left, ic, FALSE, FALSE);
8586 /* if the value is already in a pointer register
8587 then don't need anything more */
8588 if (!AOP_INPREG (AOP (left)))
8590 /* otherwise get a free pointer register */
8592 preg = getFreePtr (ic, &aop, FALSE);
8593 emitcode ("mov", "%s,%s",
8595 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8599 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8601 freeAsmop (left, NULL, ic, TRUE);
8602 aopOp (result, ic, FALSE, FALSE);
8604 /* if bitfield then unpack the bits */
8605 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8606 genUnpackBits (result, rname, PPOINTER);
8609 /* we have can just get the values */
8610 int size = AOP_SIZE (result);
8616 emitcode ("movx", "a,@%s", rname);
8617 aopPut (AOP (result), "a", offset);
8622 emitcode ("inc", "%s", rname);
8626 /* now some housekeeping stuff */
8629 /* we had to allocate for this iCode */
8630 freeAsmop (NULL, aop, ic, TRUE);
8634 /* we did not allocate which means left
8635 already in a pointer register, then
8636 if size > 0 && this could be used again
8637 we have to point it back to where it
8639 if (AOP_SIZE (result) > 1 &&
8640 !OP_SYMBOL (left)->remat &&
8641 (OP_SYMBOL (left)->liveTo > ic->seq ||
8644 int size = AOP_SIZE (result) - 1;
8646 emitcode ("dec", "%s", rname);
8651 freeAsmop (result, NULL, ic, TRUE);
8656 /*-----------------------------------------------------------------*/
8657 /* genFarPointerGet - gget value from far space */
8658 /*-----------------------------------------------------------------*/
8660 genFarPointerGet (operand * left,
8661 operand * result, iCode * ic)
8664 sym_link *retype = getSpec (operandType (result));
8665 sym_link *letype = getSpec (operandType (left));
8666 D (emitcode (";", "genFarPointerGet");
8669 aopOp (left, ic, FALSE, FALSE);
8671 /* if the operand is already in dptr
8672 then we do nothing else we move the value to dptr */
8673 if (AOP_TYPE (left) != AOP_STR)
8675 /* if this is remateriazable */
8676 if (AOP_TYPE (left) == AOP_IMMD)
8678 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8682 /* we need to get it byte by byte */
8683 _startLazyDPSEvaluation ();
8684 if (AOP_TYPE (left) != AOP_DPTR)
8686 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8687 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8688 if (options.model == MODEL_FLAT24)
8689 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8693 /* We need to generate a load to DPTR indirect through DPTR. */
8694 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8696 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8697 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8698 if (options.model == MODEL_FLAT24)
8699 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8700 emitcode ("pop", "dph");
8701 emitcode ("pop", "dpl");
8703 _endLazyDPSEvaluation ();
8706 /* so dptr know contains the address */
8707 freeAsmop (left, NULL, ic, TRUE);
8708 aopOp (result, ic, FALSE, TRUE);
8710 /* if bit then unpack */
8711 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8712 genUnpackBits (result, "dptr", FPOINTER);
8715 size = AOP_SIZE (result);
8718 _startLazyDPSEvaluation ();
8725 emitcode ("movx", "a,@dptr");
8727 emitcode ("inc", "dptr");
8729 aopPut (AOP (result), "a", offset++);
8731 _endLazyDPSEvaluation ();
8734 freeAsmop (result, NULL, ic, TRUE);
8737 /*-----------------------------------------------------------------*/
8738 /* emitcodePointerGet - gget value from code space */
8739 /*-----------------------------------------------------------------*/
8741 emitcodePointerGet (operand * left,
8742 operand * result, iCode * ic)
8745 sym_link *retype = getSpec (operandType (result));
8747 aopOp (left, ic, FALSE, FALSE);
8749 /* if the operand is already in dptr
8750 then we do nothing else we move the value to dptr */
8751 if (AOP_TYPE (left) != AOP_STR)
8753 /* if this is remateriazable */
8754 if (AOP_TYPE (left) == AOP_IMMD)
8756 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8759 { /* we need to get it byte by byte */
8760 _startLazyDPSEvaluation ();
8761 if (AOP_TYPE (left) != AOP_DPTR)
8763 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8764 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8765 if (options.model == MODEL_FLAT24)
8766 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8770 /* We need to generate a load to DPTR indirect through DPTR. */
8771 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8773 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8774 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8775 if (options.model == MODEL_FLAT24)
8776 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8777 emitcode ("pop", "dph");
8778 emitcode ("pop", "dpl");
8780 _endLazyDPSEvaluation ();
8783 /* so dptr know contains the address */
8784 freeAsmop (left, NULL, ic, TRUE);
8785 aopOp (result, ic, FALSE, TRUE);
8787 /* if bit then unpack */
8788 if (IS_BITVAR (retype))
8789 genUnpackBits (result, "dptr", CPOINTER);
8792 size = AOP_SIZE (result);
8795 _startLazyDPSEvaluation ();
8801 emitcode ("clr", "a");
8802 emitcode ("movc", "a,@a+dptr");
8804 emitcode ("inc", "dptr");
8805 aopPut (AOP (result), "a", offset++);
8807 _endLazyDPSEvaluation ();
8810 freeAsmop (result, NULL, ic, TRUE);
8813 /*-----------------------------------------------------------------*/
8814 /* genGenPointerGet - gget value from generic pointer space */
8815 /*-----------------------------------------------------------------*/
8817 genGenPointerGet (operand * left,
8818 operand * result, iCode * ic)
8821 sym_link *retype = getSpec (operandType (result));
8822 sym_link *letype = getSpec (operandType (left));
8824 D (emitcode (";", "genGenPointerGet "); );
8826 aopOp (left, ic, FALSE, TRUE);
8828 /* if the operand is already in dptr
8829 then we do nothing else we move the value to dptr */
8830 if (AOP_TYPE (left) != AOP_STR)
8832 /* if this is remateriazable */
8833 if (AOP_TYPE (left) == AOP_IMMD)
8835 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8836 emitcode ("mov", "b,#%d", pointerCode (retype));
8839 { /* we need to get it byte by byte */
8840 _startLazyDPSEvaluation ();
8841 if (AOP(left)->type==AOP_DPTR2) {
8843 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8846 emitcode ("mov", "dpl,%s", l);
8847 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8850 emitcode ("mov", "dph,%s", l);
8851 if (options.model == MODEL_FLAT24) {
8852 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8855 emitcode ("mov", "dpx,%s", l);
8856 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8858 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8861 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8862 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8863 if (options.model == MODEL_FLAT24) {
8864 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8865 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8867 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8870 _endLazyDPSEvaluation ();
8873 /* so dptr know contains the address */
8874 freeAsmop (left, NULL, ic, TRUE);
8875 aopOp (result, ic, FALSE, TRUE);
8877 /* if bit then unpack */
8878 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8879 genUnpackBits (result, "dptr", GPOINTER);
8882 size = AOP_SIZE (result);
8887 emitcode ("lcall", "__gptrget");
8888 aopPut (AOP (result), "a", offset++);
8890 emitcode ("inc", "dptr");
8894 freeAsmop (result, NULL, ic, TRUE);
8897 /*-----------------------------------------------------------------*/
8898 /* genPointerGet - generate code for pointer get */
8899 /*-----------------------------------------------------------------*/
8901 genPointerGet (iCode * ic)
8903 operand *left, *result;
8904 sym_link *type, *etype;
8907 D (emitcode (";", "genPointerGet ");
8910 left = IC_LEFT (ic);
8911 result = IC_RESULT (ic);
8913 /* depending on the type of pointer we need to
8914 move it to the correct pointer register */
8915 type = operandType (left);
8916 etype = getSpec (type);
8917 /* if left is of type of pointer then it is simple */
8918 if (IS_PTR (type) && !IS_FUNC (type->next))
8919 p_type = DCL_TYPE (type);
8922 /* we have to go by the storage class */
8923 p_type = PTR_TYPE (SPEC_OCLS (etype));
8926 /* now that we have the pointer type we assign
8927 the pointer values */
8933 genNearPointerGet (left, result, ic);
8937 genPagedPointerGet (left, result, ic);
8941 genFarPointerGet (left, result, ic);
8945 emitcodePointerGet (left, result, ic);
8949 genGenPointerGet (left, result, ic);
8955 /*-----------------------------------------------------------------*/
8956 /* genPackBits - generates code for packed bit storage */
8957 /*-----------------------------------------------------------------*/
8959 genPackBits (sym_link * etype,
8961 char *rname, int p_type)
8969 blen = SPEC_BLEN (etype);
8970 bstr = SPEC_BSTR (etype);
8972 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8975 /* if the bit lenth is less than or */
8976 /* it exactly fits a byte then */
8977 if (SPEC_BLEN (etype) <= 8)
8979 shCount = SPEC_BSTR (etype);
8981 /* shift left acc */
8984 if (SPEC_BLEN (etype) < 8)
8985 { /* if smaller than a byte */
8991 emitcode ("mov", "b,a");
8992 emitcode ("mov", "a,@%s", rname);
8996 emitcode ("mov", "b,a");
8997 emitcode ("movx", "a,@dptr");
9001 emitcode ("push", "b");
9002 emitcode ("push", "acc");
9003 emitcode ("lcall", "__gptrget");
9004 emitcode ("pop", "b");
9008 emitcode ("anl", "a,#0x%02x", (unsigned char)
9009 ((unsigned char) (0xFF << (blen + bstr)) |
9010 (unsigned char) (0xFF >> (8 - bstr))));
9011 emitcode ("orl", "a,b");
9012 if (p_type == GPOINTER)
9013 emitcode ("pop", "b");
9020 emitcode ("mov", "@%s,a", rname);
9024 emitcode ("movx", "@dptr,a");
9028 emitcode ("lcall", "__gptrput");
9033 if (SPEC_BLEN (etype) <= 8)
9036 emitcode ("inc", "%s", rname);
9037 rLen = SPEC_BLEN (etype);
9039 /* now generate for lengths greater than one byte */
9043 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9055 emitcode ("mov", "@%s,a", rname);
9058 emitcode ("mov", "@%s,%s", rname, l);
9063 emitcode ("movx", "@dptr,a");
9068 emitcode ("lcall", "__gptrput");
9071 emitcode ("inc", "%s", rname);
9076 /* last last was not complete */
9079 /* save the byte & read byte */
9083 emitcode ("mov", "b,a");
9084 emitcode ("mov", "a,@%s", rname);
9088 emitcode ("mov", "b,a");
9089 emitcode ("movx", "a,@dptr");
9093 emitcode ("push", "b");
9094 emitcode ("push", "acc");
9095 emitcode ("lcall", "__gptrget");
9096 emitcode ("pop", "b");
9100 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9101 emitcode ("orl", "a,b");
9104 if (p_type == GPOINTER)
9105 emitcode ("pop", "b");
9111 emitcode ("mov", "@%s,a", rname);
9115 emitcode ("movx", "@dptr,a");
9119 emitcode ("lcall", "__gptrput");
9123 /*-----------------------------------------------------------------*/
9124 /* genDataPointerSet - remat pointer to data space */
9125 /*-----------------------------------------------------------------*/
9127 genDataPointerSet (operand * right,
9131 int size, offset = 0;
9132 char *l, buffer[256];
9134 aopOp (right, ic, FALSE, FALSE);
9136 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9137 size = AOP_SIZE (right);
9141 sprintf (buffer, "(%s + %d)", l + 1, offset);
9143 sprintf (buffer, "%s", l + 1);
9144 emitcode ("mov", "%s,%s", buffer,
9145 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9148 freeAsmop (right, NULL, ic, TRUE);
9149 freeAsmop (result, NULL, ic, TRUE);
9152 /*-----------------------------------------------------------------*/
9153 /* genNearPointerSet - emitcode for near pointer put */
9154 /*-----------------------------------------------------------------*/
9156 genNearPointerSet (operand * right,
9163 sym_link *retype, *letype;
9164 sym_link *ptype = operandType (result);
9166 retype = getSpec (operandType (right));
9167 letype = getSpec (ptype);
9169 aopOp (result, ic, FALSE, FALSE);
9171 /* if the result is rematerializable &
9172 in data space & not a bit variable */
9173 if (AOP_TYPE (result) == AOP_IMMD &&
9174 DCL_TYPE (ptype) == POINTER &&
9175 !IS_BITVAR (retype) &&
9176 !IS_BITVAR (letype))
9178 genDataPointerSet (right, result, ic);
9182 /* if the value is already in a pointer register
9183 then don't need anything more */
9184 if (!AOP_INPREG (AOP (result)))
9186 /* otherwise get a free pointer register */
9188 preg = getFreePtr (ic, &aop, FALSE);
9189 emitcode ("mov", "%s,%s",
9191 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9195 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9197 freeAsmop (result, NULL, ic, TRUE);
9198 aopOp (right, ic, FALSE, FALSE);
9200 /* if bitfield then unpack the bits */
9201 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9202 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9205 /* we have can just get the values */
9206 int size = AOP_SIZE (right);
9211 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9215 emitcode ("mov", "@%s,a", rname);
9218 emitcode ("mov", "@%s,%s", rname, l);
9220 emitcode ("inc", "%s", rname);
9225 /* now some housekeeping stuff */
9228 /* we had to allocate for this iCode */
9229 freeAsmop (NULL, aop, ic, TRUE);
9233 /* we did not allocate which means left
9234 already in a pointer register, then
9235 if size > 0 && this could be used again
9236 we have to point it back to where it
9238 if (AOP_SIZE (right) > 1 &&
9239 !OP_SYMBOL (result)->remat &&
9240 (OP_SYMBOL (result)->liveTo > ic->seq ||
9243 int size = AOP_SIZE (right) - 1;
9245 emitcode ("dec", "%s", rname);
9250 freeAsmop (right, NULL, ic, TRUE);
9255 /*-----------------------------------------------------------------*/
9256 /* genPagedPointerSet - emitcode for Paged pointer put */
9257 /*-----------------------------------------------------------------*/
9259 genPagedPointerSet (operand * right,
9266 sym_link *retype, *letype;
9268 retype = getSpec (operandType (right));
9269 letype = getSpec (operandType (result));
9271 aopOp (result, ic, FALSE, FALSE);
9273 /* if the value is already in a pointer register
9274 then don't need anything more */
9275 if (!AOP_INPREG (AOP (result)))
9277 /* otherwise get a free pointer register */
9279 preg = getFreePtr (ic, &aop, FALSE);
9280 emitcode ("mov", "%s,%s",
9282 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9286 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9288 freeAsmop (result, NULL, ic, TRUE);
9289 aopOp (right, ic, FALSE, FALSE);
9291 /* if bitfield then unpack the bits */
9292 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9293 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9296 /* we have can just get the values */
9297 int size = AOP_SIZE (right);
9302 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9305 emitcode ("movx", "@%s,a", rname);
9308 emitcode ("inc", "%s", rname);
9314 /* now some housekeeping stuff */
9317 /* we had to allocate for this iCode */
9318 freeAsmop (NULL, aop, ic, TRUE);
9322 /* we did not allocate which means left
9323 already in a pointer register, then
9324 if size > 0 && this could be used again
9325 we have to point it back to where it
9327 if (AOP_SIZE (right) > 1 &&
9328 !OP_SYMBOL (result)->remat &&
9329 (OP_SYMBOL (result)->liveTo > ic->seq ||
9332 int size = AOP_SIZE (right) - 1;
9334 emitcode ("dec", "%s", rname);
9339 freeAsmop (right, NULL, ic, TRUE);
9344 /*-----------------------------------------------------------------*/
9345 /* genFarPointerSet - set value from far space */
9346 /*-----------------------------------------------------------------*/
9348 genFarPointerSet (operand * right,
9349 operand * result, iCode * ic)
9352 sym_link *retype = getSpec (operandType (right));
9353 sym_link *letype = getSpec (operandType (result));
9355 aopOp (result, ic, FALSE, FALSE);
9357 /* if the operand is already in dptr
9358 then we do nothing else we move the value to dptr */
9359 if (AOP_TYPE (result) != AOP_STR)
9361 /* if this is remateriazable */
9362 if (AOP_TYPE (result) == AOP_IMMD)
9363 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9366 /* we need to get it byte by byte */
9367 _startLazyDPSEvaluation ();
9368 if (AOP_TYPE (result) != AOP_DPTR)
9370 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9371 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9372 if (options.model == MODEL_FLAT24)
9373 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9377 /* We need to generate a load to DPTR indirect through DPTR. */
9378 D (emitcode (";", "genFarPointerSet -- indirection special case.");
9380 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9381 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9382 if (options.model == MODEL_FLAT24)
9383 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9384 emitcode ("pop", "dph");
9385 emitcode ("pop", "dpl");
9387 _endLazyDPSEvaluation ();
9390 /* so dptr know contains the address */
9391 freeAsmop (result, NULL, ic, TRUE);
9392 aopOp (right, ic, FALSE, TRUE);
9394 /* if bit then unpack */
9395 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9396 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9399 size = AOP_SIZE (right);
9402 _startLazyDPSEvaluation ();
9405 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9411 emitcode ("movx", "@dptr,a");
9413 emitcode ("inc", "dptr");
9415 _endLazyDPSEvaluation ();
9418 freeAsmop (right, NULL, ic, TRUE);
9421 /*-----------------------------------------------------------------*/
9422 /* genGenPointerSet - set value from generic pointer space */
9423 /*-----------------------------------------------------------------*/
9425 genGenPointerSet (operand * right,
9426 operand * result, iCode * ic)
9429 sym_link *retype = getSpec (operandType (right));
9430 sym_link *letype = getSpec (operandType (result));
9432 aopOp (result, ic, FALSE, TRUE);
9434 /* if the operand is already in dptr
9435 then we do nothing else we move the value to dptr */
9436 if (AOP_TYPE (result) != AOP_STR)
9438 _startLazyDPSEvaluation ();
9439 /* if this is remateriazable */
9440 if (AOP_TYPE (result) == AOP_IMMD)
9442 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9443 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9446 { /* we need to get it byte by byte */
9447 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9448 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9449 if (options.model == MODEL_FLAT24) {
9450 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9451 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9453 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9456 _endLazyDPSEvaluation ();
9458 /* so dptr know contains the address */
9459 freeAsmop (result, NULL, ic, TRUE);
9460 aopOp (right, ic, FALSE, TRUE);
9462 /* if bit then unpack */
9463 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9464 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9467 size = AOP_SIZE (right);
9470 _startLazyDPSEvaluation ();
9473 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9479 emitcode ("lcall", "__gptrput");
9481 emitcode ("inc", "dptr");
9483 _endLazyDPSEvaluation ();
9486 freeAsmop (right, NULL, ic, TRUE);
9489 /*-----------------------------------------------------------------*/
9490 /* genPointerSet - stores the value into a pointer location */
9491 /*-----------------------------------------------------------------*/
9493 genPointerSet (iCode * ic)
9495 operand *right, *result;
9496 sym_link *type, *etype;
9499 D (emitcode (";", "genPointerSet ");
9502 right = IC_RIGHT (ic);
9503 result = IC_RESULT (ic);
9505 /* depending on the type of pointer we need to
9506 move it to the correct pointer register */
9507 type = operandType (result);
9508 etype = getSpec (type);
9509 /* if left is of type of pointer then it is simple */
9510 if (IS_PTR (type) && !IS_FUNC (type->next))
9512 p_type = DCL_TYPE (type);
9516 /* we have to go by the storage class */
9517 p_type = PTR_TYPE (SPEC_OCLS (etype));
9520 /* now that we have the pointer type we assign
9521 the pointer values */
9527 genNearPointerSet (right, result, ic);
9531 genPagedPointerSet (right, result, ic);
9535 genFarPointerSet (right, result, ic);
9539 genGenPointerSet (right, result, ic);
9545 /*-----------------------------------------------------------------*/
9546 /* genIfx - generate code for Ifx statement */
9547 /*-----------------------------------------------------------------*/
9549 genIfx (iCode * ic, iCode * popIc)
9551 operand *cond = IC_COND (ic);
9554 D (emitcode (";", "genIfx "););
9556 aopOp (cond, ic, FALSE, FALSE);
9558 /* get the value into acc */
9559 if (AOP_TYPE (cond) != AOP_CRY)
9563 /* the result is now in the accumulator */
9564 freeAsmop (cond, NULL, ic, TRUE);
9566 /* if there was something to be popped then do it */
9570 /* if the condition is a bit variable */
9571 if (isbit && IS_ITEMP (cond) &&
9573 genIfxJump (ic, SPIL_LOC (cond)->rname);
9574 else if (isbit && !IS_ITEMP (cond))
9575 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9577 genIfxJump (ic, "a");
9582 /*-----------------------------------------------------------------*/
9583 /* genAddrOf - generates code for address of */
9584 /*-----------------------------------------------------------------*/
9586 genAddrOf (iCode * ic)
9588 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9591 D (emitcode (";", "genAddrOf ");
9594 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9596 /* if the operand is on the stack then we
9597 need to get the stack offset of this
9601 /* if it has an offset then we need to compute
9605 emitcode ("mov", "a,_bp");
9606 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9607 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9611 /* we can just move _bp */
9612 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9614 /* fill the result with zero */
9615 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9618 if (options.stack10bit && size < (FPTRSIZE - 1))
9621 "*** warning: pointer to stack var truncated.\n");
9628 if (options.stack10bit && offset == 2)
9630 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9634 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9641 /* object not on stack then we need the name */
9642 size = AOP_SIZE (IC_RESULT (ic));
9647 char s[SDCC_NAME_MAX];
9649 sprintf (s, "#(%s >> %d)",
9653 sprintf (s, "#%s", sym->rname);
9654 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9662 /*-----------------------------------------------------------------*/
9663 /* genArrayInit - generates code for address of */
9664 /*-----------------------------------------------------------------*/
9666 genArrayInit (iCode * ic)
9670 int elementSize = 0, eIndex;
9671 unsigned val, lastVal;
9673 operand *left=IC_LEFT(ic);
9675 D (emitcode (";", "genArrayInit "););
9677 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9679 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9681 // Load immediate value into DPTR.
9682 emitcode("mov", "dptr, %s",
9683 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9685 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9688 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9689 "Unexpected operand to genArrayInit.\n");
9692 // a regression because of SDCCcse.c:1.52
9693 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9694 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9695 if (options.model == MODEL_FLAT24)
9696 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9700 type = operandType(IC_LEFT(ic));
9702 if (type && type->next)
9704 elementSize = getSize(type->next);
9708 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9709 "can't determine element size in genArrayInit.\n");
9713 iLoop = IC_ARRAYILIST(ic);
9718 bool firstpass = TRUE;
9720 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9721 iLoop->count, (int)iLoop->literalValue, elementSize);
9727 symbol *tlbl = NULL;
9729 count = ix > 256 ? 256 : ix;
9733 tlbl = newiTempLabel (NULL);
9734 if (firstpass || (count & 0xff))
9736 emitcode("mov", "b, #0x%x", count & 0xff);
9739 emitcode ("", "%05d$:", tlbl->key + 100);
9744 for (eIndex = 0; eIndex < elementSize; eIndex++)
9746 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9749 emitcode("mov", "a, #0x%x", val);
9753 emitcode("movx", "@dptr, a");
9754 emitcode("inc", "dptr");
9759 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9765 iLoop = iLoop->next;
9768 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9771 /*-----------------------------------------------------------------*/
9772 /* genFarFarAssign - assignment when both are in far space */
9773 /*-----------------------------------------------------------------*/
9775 genFarFarAssign (operand * result, operand * right, iCode * ic)
9777 int size = AOP_SIZE (right);
9779 symbol *rSym = NULL;
9783 /* quick & easy case. */
9784 D(emitcode(";","genFarFarAssign (1 byte case)"););
9785 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9786 freeAsmop (right, NULL, ic, FALSE);
9787 /* now assign DPTR to result */
9789 aopOp(result, ic, FALSE, FALSE);
9791 aopPut(AOP(result), "a", 0);
9792 freeAsmop(result, NULL, ic, FALSE);
9796 /* See if we've got an underlying symbol to abuse. */
9797 if (IS_SYMOP(result) && OP_SYMBOL(result))
9799 if (IS_TRUE_SYMOP(result))
9801 rSym = OP_SYMBOL(result);
9803 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9805 rSym = OP_SYMBOL(result)->usl.spillLoc;
9809 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9811 /* We can use the '390 auto-toggle feature to good effect here. */
9813 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9814 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9815 emitcode ("mov", "dptr,#%s", rSym->rname);
9816 /* DP2 = result, DP1 = right, DP1 is current. */
9819 emitcode("movx", "a,@dptr");
9820 emitcode("movx", "@dptr,a");
9823 emitcode("inc", "dptr");
9824 emitcode("inc", "dptr");
9827 emitcode("mov", "dps, #0");
9828 freeAsmop (right, NULL, ic, FALSE);
9830 some alternative code for processors without auto-toggle
9831 no time to test now, so later well put in...kpb
9832 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9833 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9834 emitcode ("mov", "dptr,#%s", rSym->rname);
9835 /* DP2 = result, DP1 = right, DP1 is current. */
9839 emitcode("movx", "a,@dptr");
9841 emitcode("inc", "dptr");
9842 emitcode("inc", "dps");
9843 emitcode("movx", "@dptr,a");
9845 emitcode("inc", "dptr");
9846 emitcode("inc", "dps");
9848 emitcode("mov", "dps, #0");
9849 freeAsmop (right, NULL, ic, FALSE);
9854 D (emitcode (";", "genFarFarAssign"););
9855 aopOp (result, ic, TRUE, TRUE);
9857 _startLazyDPSEvaluation ();
9861 aopPut (AOP (result),
9862 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9865 _endLazyDPSEvaluation ();
9866 freeAsmop (result, NULL, ic, FALSE);
9867 freeAsmop (right, NULL, ic, FALSE);
9871 /*-----------------------------------------------------------------*/
9872 /* genAssign - generate code for assignment */
9873 /*-----------------------------------------------------------------*/
9875 genAssign (iCode * ic)
9877 operand *result, *right;
9879 unsigned long lit = 0L;
9881 D (emitcode (";", "genAssign ");
9884 result = IC_RESULT (ic);
9885 right = IC_RIGHT (ic);
9887 /* if they are the same */
9888 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9891 aopOp (right, ic, FALSE, FALSE);
9893 emitcode (";", "genAssign: resultIsFar = %s",
9894 isOperandInFarSpace (result) ?
9897 /* special case both in far space */
9898 if ((AOP_TYPE (right) == AOP_DPTR ||
9899 AOP_TYPE (right) == AOP_DPTR2) &&
9900 /* IS_TRUE_SYMOP(result) && */
9901 isOperandInFarSpace (result))
9903 genFarFarAssign (result, right, ic);
9907 aopOp (result, ic, TRUE, FALSE);
9909 /* if they are the same registers */
9910 if (sameRegs (AOP (right), AOP (result)))
9913 /* if the result is a bit */
9914 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9916 /* if the right size is a literal then
9917 we know what the value is */
9918 if (AOP_TYPE (right) == AOP_LIT)
9920 if (((int) operandLitValue (right)))
9921 aopPut (AOP (result), one, 0);
9923 aopPut (AOP (result), zero, 0);
9927 /* the right is also a bit variable */
9928 if (AOP_TYPE (right) == AOP_CRY)
9930 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9931 aopPut (AOP (result), "c", 0);
9937 aopPut (AOP (result), "a", 0);
9941 /* bit variables done */
9943 size = AOP_SIZE (result);
9945 if (AOP_TYPE (right) == AOP_LIT)
9946 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9949 (AOP_TYPE (result) != AOP_REG) &&
9950 (AOP_TYPE (right) == AOP_LIT) &&
9951 !IS_FLOAT (operandType (right)))
9953 _startLazyDPSEvaluation ();
9954 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9956 aopPut (AOP (result),
9957 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9962 /* And now fill the rest with zeros. */
9965 emitcode ("clr", "a");
9969 aopPut (AOP (result), "a", offset++);
9971 _endLazyDPSEvaluation ();
9975 _startLazyDPSEvaluation ();
9978 aopPut (AOP (result),
9979 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9983 _endLazyDPSEvaluation ();
9987 freeAsmop (right, NULL, ic, FALSE);
9988 freeAsmop (result, NULL, ic, TRUE);
9991 /*-----------------------------------------------------------------*/
9992 /* genJumpTab - generates code for jump table */
9993 /*-----------------------------------------------------------------*/
9995 genJumpTab (iCode * ic)
10000 D (emitcode (";", "genJumpTab ");
10003 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10004 /* get the condition into accumulator */
10005 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10007 /* multiply by four! */
10008 emitcode ("add", "a,acc");
10009 emitcode ("add", "a,acc");
10010 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10012 jtab = newiTempLabel (NULL);
10013 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10014 emitcode ("jmp", "@a+dptr");
10015 emitcode ("", "%05d$:", jtab->key + 100);
10016 /* now generate the jump labels */
10017 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10018 jtab = setNextItem (IC_JTLABELS (ic)))
10019 emitcode ("ljmp", "%05d$", jtab->key + 100);
10023 /*-----------------------------------------------------------------*/
10024 /* genCast - gen code for casting */
10025 /*-----------------------------------------------------------------*/
10027 genCast (iCode * ic)
10029 operand *result = IC_RESULT (ic);
10030 sym_link *ctype = operandType (IC_LEFT (ic));
10031 sym_link *rtype = operandType (IC_RIGHT (ic));
10032 operand *right = IC_RIGHT (ic);
10035 D (emitcode (";", "genCast ");
10038 /* if they are equivalent then do nothing */
10039 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10042 aopOp (right, ic, FALSE, FALSE);
10043 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10045 /* if the result is a bit */
10046 // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10047 if (IS_BITVAR(OP_SYMBOL(result)->type))
10049 /* if the right size is a literal then
10050 we know what the value is */
10051 if (AOP_TYPE (right) == AOP_LIT)
10053 if (((int) operandLitValue (right)))
10054 aopPut (AOP (result), one, 0);
10056 aopPut (AOP (result), zero, 0);
10061 /* the right is also a bit variable */
10062 if (AOP_TYPE (right) == AOP_CRY)
10064 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10065 aopPut (AOP (result), "c", 0);
10069 /* we need to or */
10071 aopPut (AOP (result), "a", 0);
10075 /* if they are the same size : or less */
10076 if (AOP_SIZE (result) <= AOP_SIZE (right))
10079 /* if they are in the same place */
10080 if (sameRegs (AOP (right), AOP (result)))
10083 /* if they in different places then copy */
10084 size = AOP_SIZE (result);
10086 _startLazyDPSEvaluation ();
10089 aopPut (AOP (result),
10090 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10094 _endLazyDPSEvaluation ();
10099 /* if the result is of type pointer */
10100 if (IS_PTR (ctype))
10104 sym_link *type = operandType (right);
10106 /* pointer to generic pointer */
10107 if (IS_GENPTR (ctype))
10113 p_type = DCL_TYPE (type);
10117 #if OLD_CAST_BEHAVIOR
10118 /* KV: we are converting a non-pointer type to
10119 * a generic pointer. This (ifdef'd out) code
10120 * says that the resulting generic pointer
10121 * should have the same class as the storage
10122 * location of the non-pointer variable.
10124 * For example, converting an int (which happens
10125 * to be stored in DATA space) to a pointer results
10126 * in a DATA generic pointer; if the original int
10127 * in XDATA space, so will be the resulting pointer.
10129 * I don't like that behavior, and thus this change:
10130 * all such conversions will be forced to XDATA and
10131 * throw a warning. If you want some non-XDATA
10132 * type, or you want to suppress the warning, you
10133 * must go through an intermediate cast, like so:
10135 * char _generic *gp = (char _xdata *)(intVar);
10137 sym_link *etype = getSpec (type);
10139 /* we have to go by the storage class */
10140 if (SPEC_OCLS (etype) != generic)
10142 p_type = PTR_TYPE (SPEC_OCLS (etype));
10147 /* Converting unknown class (i.e. register variable)
10148 * to generic pointer. This is not good, but
10149 * we'll make a guess (and throw a warning).
10152 werror (W_INT_TO_GEN_PTR_CAST);
10156 /* the first two bytes are known */
10157 size = GPTRSIZE - 1;
10159 _startLazyDPSEvaluation ();
10162 aopPut (AOP (result),
10163 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10167 _endLazyDPSEvaluation ();
10169 /* the last byte depending on type */
10187 /* this should never happen */
10188 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10189 "got unknown pointer type");
10192 aopPut (AOP (result), l, GPTRSIZE - 1);
10196 /* just copy the pointers */
10197 size = AOP_SIZE (result);
10199 _startLazyDPSEvaluation ();
10202 aopPut (AOP (result),
10203 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10207 _endLazyDPSEvaluation ();
10211 /* so we now know that the size of destination is greater
10212 than the size of the source */
10213 /* we move to result for the size of source */
10214 size = AOP_SIZE (right);
10216 _startLazyDPSEvaluation ();
10219 aopPut (AOP (result),
10220 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10224 _endLazyDPSEvaluation ();
10226 /* now depending on the sign of the source && destination */
10227 size = AOP_SIZE (result) - AOP_SIZE (right);
10228 /* if unsigned or not an integral type */
10229 /* also, if the source is a bit, we don't need to sign extend, because
10230 * it can't possibly have set the sign bit.
10232 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10236 aopPut (AOP (result), zero, offset++);
10241 /* we need to extend the sign :{ */
10242 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10243 FALSE, FALSE, TRUE);
10245 emitcode ("rlc", "a");
10246 emitcode ("subb", "a,acc");
10248 aopPut (AOP (result), "a", offset++);
10251 /* we are done hurray !!!! */
10254 freeAsmop (right, NULL, ic, TRUE);
10255 freeAsmop (result, NULL, ic, TRUE);
10259 /*-----------------------------------------------------------------*/
10260 /* genDjnz - generate decrement & jump if not zero instrucion */
10261 /*-----------------------------------------------------------------*/
10263 genDjnz (iCode * ic, iCode * ifx)
10265 symbol *lbl, *lbl1;
10269 /* if the if condition has a false label
10270 then we cannot save */
10271 if (IC_FALSE (ifx))
10274 /* if the minus is not of the form
10276 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10277 !IS_OP_LITERAL (IC_RIGHT (ic)))
10280 if (operandLitValue (IC_RIGHT (ic)) != 1)
10283 /* if the size of this greater than one then no
10285 if (getSize (operandType (IC_RESULT (ic))) > 1)
10288 /* otherwise we can save BIG */
10289 D(emitcode(";", "genDjnz"););
10291 lbl = newiTempLabel (NULL);
10292 lbl1 = newiTempLabel (NULL);
10294 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10296 if (AOP_NEEDSACC(IC_RESULT(ic)))
10298 /* If the result is accessed indirectly via
10299 * the accumulator, we must explicitly write
10300 * it back after the decrement.
10302 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10304 if (strcmp(rByte, "a"))
10306 /* Something is hopelessly wrong */
10307 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10308 __FILE__, __LINE__);
10309 /* We can just give up; the generated code will be inefficient,
10310 * but what the hey.
10312 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10315 emitcode ("dec", "%s", rByte);
10316 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10317 emitcode ("jnz", "%05d$", lbl->key + 100);
10319 else if (IS_AOP_PREG (IC_RESULT (ic)))
10321 emitcode ("dec", "%s",
10322 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10323 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10324 emitcode ("jnz", "%05d$", lbl->key + 100);
10328 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10331 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10332 emitcode ("", "%05d$:", lbl->key + 100);
10333 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10334 emitcode ("", "%05d$:", lbl1->key + 100);
10336 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10337 ifx->generated = 1;
10341 /*-----------------------------------------------------------------*/
10342 /* genReceive - generate code for a receive iCode */
10343 /*-----------------------------------------------------------------*/
10345 genReceive (iCode * ic)
10348 D (emitcode (";", "genReceive ");
10351 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10352 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10353 IS_TRUE_SYMOP (IC_RESULT (ic))))
10355 int size = getSize (operandType (IC_RESULT (ic)));
10356 int offset = fReturnSizeDS390 - size;
10359 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10360 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10363 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10364 size = AOP_SIZE (IC_RESULT (ic));
10368 emitcode ("pop", "acc");
10369 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10376 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10378 assignResultValue (IC_RESULT (ic));
10381 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10384 /*-----------------------------------------------------------------*/
10385 /* gen390Code - generate code for Dallas 390 based controllers */
10386 /*-----------------------------------------------------------------*/
10388 gen390Code (iCode * lic)
10393 lineHead = lineCurr = NULL;
10395 if (options.model == MODEL_FLAT24) {
10396 fReturnSizeDS390 = 5;
10397 fReturn = fReturn24;
10399 fReturnSizeDS390 = 4;
10400 fReturn = fReturn16;
10401 options.stack10bit=0;
10405 /* print the allocation information */
10407 printAllocInfo (currFunc, codeOutFile);
10409 /* if debug information required */
10410 if (options.debug && currFunc)
10412 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10414 if (IS_STATIC (currFunc->etype))
10415 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10417 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10420 /* stack pointer name */
10421 if (options.useXstack)
10427 for (ic = lic; ic; ic = ic->next)
10430 if (cln != ic->lineno)
10435 emitcode ("", "C$%s$%d$%d$%d ==.",
10436 FileBaseName (ic->filename), ic->lineno,
10437 ic->level, ic->block);
10440 emitcode (";", "%s %d", ic->filename, ic->lineno);
10443 /* if the result is marked as
10444 spilt and rematerializable or code for
10445 this has already been generated then
10447 if (resultRemat (ic) || ic->generated)
10450 /* depending on the operation */
10470 /* IPOP happens only when trying to restore a
10471 spilt live range, if there is an ifx statement
10472 following this pop then the if statement might
10473 be using some of the registers being popped which
10474 would destory the contents of the register so
10475 we need to check for this condition and handle it */
10477 ic->next->op == IFX &&
10478 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10479 genIfx (ic->next, ic);
10497 genEndFunction (ic);
10517 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10534 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10538 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10545 /* note these two are xlated by algebraic equivalence
10546 during parsing SDCC.y */
10547 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10548 "got '>=' or '<=' shouldn't have come here");
10552 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10564 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10568 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10572 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10596 genRightShift (ic);
10599 case GET_VALUE_AT_ADDRESS:
10600 genPointerGet (ic);
10604 if (POINTER_SET (ic))
10605 genPointerSet (ic);
10631 addSet (&_G.sendSet, ic);
10644 /* now we are ready to call the
10645 peep hole optimizer */
10646 if (!options.nopeep)
10647 peepHole (&lineHead);
10649 /* now do the actual printing */
10650 printLine (lineHead, codeOutFile);