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>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #define BETTER_LITERAL_SHIFT
53 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
66 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
67 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
69 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
70 static char *fReturn24[] =
71 {"dpl", "dph", "dpx", "b", "a"};
72 static char *fReturn16[] =
73 {"dpl", "dph", "b", "a"};
74 static char **fReturn = fReturn24;
75 static char *accUse[] =
78 static short rbank = -1;
92 static void saveRBank (int, iCode *, bool);
94 #define RESULTONSTACK(x) \
95 (IC_RESULT(x) && IC_RESULT(x)->aop && \
96 IC_RESULT(x)->aop->type == AOP_STK )
98 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
99 #define MOVA(x) { char *_mova_tmp = strdup(x); \
100 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
102 emitcode("mov","a,%s",_mova_tmp); \
106 #define CLRC emitcode("clr","c")
107 #define SETC emitcode("setb","c")
109 // A scratch register which will be used to hold
110 // result bytes from operands in far space via DPTR2.
111 #define DP2_RESULT_REG "ap"
113 static lineNode *lineHead = NULL;
114 static lineNode *lineCurr = NULL;
116 static unsigned char SLMask[] =
117 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
118 0xE0, 0xC0, 0x80, 0x00};
119 static unsigned char SRMask[] =
120 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
121 0x07, 0x03, 0x01, 0x00};
128 /*-----------------------------------------------------------------*/
129 /* emitcode - writes the code into a file : for now it is simple */
130 /*-----------------------------------------------------------------*/
132 emitcode (char *inst, char *fmt,...)
135 char lb[INITIAL_INLINEASM];
143 sprintf (lb, "%s\t", inst);
145 sprintf (lb, "%s", inst);
146 vsprintf (lb + (strlen (lb)), fmt, ap);
149 vsprintf (lb, fmt, ap);
151 while (isspace (*lbp))
155 lineCurr = (lineCurr ?
156 connectLine (lineCurr, newLineNode (lb)) :
157 (lineHead = newLineNode (lb)));
158 lineCurr->isInline = _G.inLine;
159 lineCurr->isDebug = _G.debugLine;
163 /*-----------------------------------------------------------------*/
164 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
165 /*-----------------------------------------------------------------*/
167 getFreePtr (iCode * ic, asmop ** aopp, bool result)
169 bool r0iu = FALSE, r1iu = FALSE;
170 bool r0ou = FALSE, r1ou = FALSE;
172 /* the logic: if r0 & r1 used in the instruction
173 then we are in trouble otherwise */
175 /* first check if r0 & r1 are used by this
176 instruction, in which case we are in trouble */
177 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
178 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
183 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
184 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
186 /* if no usage of r0 then return it */
189 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
190 (*aopp)->type = AOP_R0;
192 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
195 /* if no usage of r1 then return it */
198 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
199 (*aopp)->type = AOP_R1;
201 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
204 /* now we know they both have usage */
205 /* if r0 not used in this instruction */
208 /* push it if not already pushed */
211 emitcode ("push", "%s",
212 ds390_regWithIdx (R0_IDX)->dname);
216 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
217 (*aopp)->type = AOP_R0;
219 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
222 /* if r1 not used then */
226 /* push it if not already pushed */
229 emitcode ("push", "%s",
230 ds390_regWithIdx (R1_IDX)->dname);
234 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
235 (*aopp)->type = AOP_R1;
236 return ds390_regWithIdx (R1_IDX);
240 /* I said end of world but not quite end of world yet */
241 /* if this is a result then we can push it on the stack */
244 (*aopp)->type = AOP_STK;
248 /* other wise this is true end of the world */
249 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
250 "getFreePtr should never reach here");
254 /*-----------------------------------------------------------------*/
255 /* newAsmop - creates a new asmOp */
256 /*-----------------------------------------------------------------*/
258 newAsmop (short type)
262 aop = Safe_calloc (1, sizeof (asmop));
267 static int _currentDPS; /* Current processor DPS. */
268 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
269 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
271 /*-----------------------------------------------------------------*/
272 /* genSetDPTR: generate code to select which DPTR is in use (zero */
273 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
274 /* alternate DPTR (DPL1/DPH1/DPX1). */
275 /*-----------------------------------------------------------------*/
280 /* If we are doing lazy evaluation, simply note the desired
281 * change, but don't emit any code yet.
291 emitcode ("mov", "dps, #0x00");
296 emitcode ("mov", "dps, #0x01");
300 /*-----------------------------------------------------------------*/
301 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
303 /* Any code that operates on DPTR (NB: not on the individual */
304 /* components, like DPH) *must* call _flushLazyDPS() before using */
305 /* DPTR within a lazy DPS evaluation block. */
307 /* Note that aopPut and aopGet already contain the proper calls to */
308 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
309 /* DPS evaluation block. */
311 /* Also, _flushLazyDPS must be called before any flow control */
312 /* operations that could potentially branch out of the block. */
314 /* Lazy DPS evaluation is simply an optimization (though an */
315 /* important one), so if in doubt, leave it out. */
316 /*-----------------------------------------------------------------*/
318 _startLazyDPSEvaluation (void)
322 #ifdef BETTER_LITERAL_SHIFT
329 /*-----------------------------------------------------------------*/
330 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
331 /* desired one. Call before using DPTR within a lazy DPS evaluation */
333 /*-----------------------------------------------------------------*/
343 if (_desiredDPS != _currentDPS)
347 emitcode ("inc", "dps");
351 emitcode ("dec", "dps");
353 _currentDPS = _desiredDPS;
357 /*-----------------------------------------------------------------*/
358 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
360 /* Forces us back to the safe state (standard DPTR selected). */
361 /*-----------------------------------------------------------------*/
363 _endLazyDPSEvaluation (void)
365 #ifdef BETTER_LITERAL_SHIFT
384 /*-----------------------------------------------------------------*/
385 /* pointerCode - returns the code for a pointer type */
386 /*-----------------------------------------------------------------*/
388 pointerCode (sym_link * etype)
391 return PTR_TYPE (SPEC_OCLS (etype));
395 /*-----------------------------------------------------------------*/
396 /* aopForSym - for a true symbol */
397 /*-----------------------------------------------------------------*/
399 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
402 memmap *space = SPEC_OCLS (sym->etype);
404 /* if already has one */
408 /* assign depending on the storage class */
409 /* if it is on the stack or indirectly addressable */
410 /* space we need to assign either r0 or r1 to it */
411 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
413 sym->aop = aop = newAsmop (0);
414 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
415 aop->size = getSize (sym->type);
417 /* now assign the address of the variable to
418 the pointer register */
419 if (aop->type != AOP_STK)
425 emitcode ("push", "acc");
427 emitcode ("mov", "a,_bp");
428 emitcode ("add", "a,#0x%02x",
430 ((char) (sym->stack - _G.nRegsSaved)) :
431 ((char) sym->stack)) & 0xff);
432 emitcode ("mov", "%s,a",
433 aop->aopu.aop_ptr->name);
436 emitcode ("pop", "acc");
439 emitcode ("mov", "%s,#%s",
440 aop->aopu.aop_ptr->name,
442 aop->paged = space->paged;
445 aop->aopu.aop_stk = sym->stack;
449 if (sym->onStack && options.stack10bit)
451 /* It's on the 10 bit stack, which is located in
456 emitcode ("push", "acc");
458 emitcode ("mov", "a,_bp");
459 emitcode ("add", "a,#0x%02x",
461 ((char) (sym->stack - _G.nRegsSaved)) :
462 ((char) sym->stack)) & 0xff);
466 if (options.model == MODEL_FLAT24)
467 emitcode ("mov", "dpx1,#0x40");
469 emitcode ("mov", "dph1,#0x00");
470 emitcode ("mov", "dpl1, a");
474 if (options.model == MODEL_FLAT24)
475 emitcode ("mov", "dpx,#0x40");
476 emitcode ("mov", "dph,#0x00");
477 emitcode ("mov", "dpl, a");
481 emitcode ("pop", "acc");
483 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
484 aop->size = getSize (sym->type);
488 /* if in bit space */
489 if (IN_BITSPACE (space))
491 sym->aop = aop = newAsmop (AOP_CRY);
492 aop->aopu.aop_dir = sym->rname;
493 aop->size = getSize (sym->type);
496 /* if it is in direct space */
497 if (IN_DIRSPACE (space))
499 sym->aop = aop = newAsmop (AOP_DIR);
500 aop->aopu.aop_dir = sym->rname;
501 aop->size = getSize (sym->type);
505 /* special case for a function */
506 if (IS_FUNC (sym->type))
508 sym->aop = aop = newAsmop (AOP_IMMD);
509 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
510 strcpy (aop->aopu.aop_immd, sym->rname);
511 aop->size = FPTRSIZE;
515 /* only remaining is far space */
516 /* in which case DPTR gets the address */
517 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
522 emitcode ("mov", "dptr,#%s", sym->rname);
527 emitcode ("mov", "dptr,#%s", sym->rname);
529 aop->size = getSize (sym->type);
531 /* if it is in code space */
532 if (IN_CODESPACE (space))
538 /*-----------------------------------------------------------------*/
539 /* aopForRemat - rematerialzes an object */
540 /*-----------------------------------------------------------------*/
542 aopForRemat (symbol * sym)
544 iCode *ic = sym->rematiCode;
545 asmop *aop = newAsmop (AOP_IMMD);
552 val += (int) operandLitValue (IC_RIGHT (ic));
553 else if (ic->op == '-')
554 val -= (int) operandLitValue (IC_RIGHT (ic));
558 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
562 sprintf (buffer, "(%s %c 0x%04x)",
563 OP_SYMBOL (IC_LEFT (ic))->rname,
564 val >= 0 ? '+' : '-',
567 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
569 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
570 strcpy (aop->aopu.aop_immd, buffer);
574 /*-----------------------------------------------------------------*/
575 /* regsInCommon - two operands have some registers in common */
576 /*-----------------------------------------------------------------*/
578 regsInCommon (operand * op1, operand * op2)
583 /* if they have registers in common */
584 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
587 sym1 = OP_SYMBOL (op1);
588 sym2 = OP_SYMBOL (op2);
590 if (sym1->nRegs == 0 || sym2->nRegs == 0)
593 for (i = 0; i < sym1->nRegs; i++)
599 for (j = 0; j < sym2->nRegs; j++)
604 if (sym2->regs[j] == sym1->regs[i])
612 /*-----------------------------------------------------------------*/
613 /* operandsEqu - equivalent */
614 /*-----------------------------------------------------------------*/
616 operandsEqu (operand * op1, operand * op2)
620 /* if they not symbols */
621 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
624 sym1 = OP_SYMBOL (op1);
625 sym2 = OP_SYMBOL (op2);
627 /* if both are itemps & one is spilt
628 and the other is not then false */
629 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
630 sym1->isspilt != sym2->isspilt)
633 /* if they are the same */
637 if (strcmp (sym1->rname, sym2->rname) == 0)
641 /* if left is a tmp & right is not */
642 if (IS_ITEMP (op1) &&
645 (sym1->usl.spillLoc == sym2))
648 if (IS_ITEMP (op2) &&
652 (sym2->usl.spillLoc == sym1))
658 /*-----------------------------------------------------------------*/
659 /* sameRegs - two asmops have the same registers */
660 /*-----------------------------------------------------------------*/
662 sameRegs (asmop * aop1, asmop * aop2)
668 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
675 if (aop1->type != AOP_REG ||
676 aop2->type != AOP_REG)
679 if (aop1->size != aop2->size)
682 for (i = 0; i < aop1->size; i++)
683 if (aop1->aopu.aop_reg[i] !=
684 aop2->aopu.aop_reg[i])
690 /*-----------------------------------------------------------------*/
691 /* aopOp - allocates an asmop for an operand : */
692 /*-----------------------------------------------------------------*/
694 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
703 /* if this a literal */
704 if (IS_OP_LITERAL (op))
706 op->aop = aop = newAsmop (AOP_LIT);
707 aop->aopu.aop_lit = op->operand.valOperand;
708 aop->size = getSize (operandType (op));
712 /* if already has a asmop then continue */
716 /* if the underlying symbol has a aop */
717 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
719 op->aop = OP_SYMBOL (op)->aop;
723 /* if this is a true symbol */
724 if (IS_TRUE_SYMOP (op))
726 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
730 /* this is a temporary : this has
736 e) can be a return use only */
738 sym = OP_SYMBOL (op);
741 /* if the type is a conditional */
742 if (sym->regType == REG_CND)
744 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
749 /* if it is spilt then two situations
751 b) has a spill location */
752 if (sym->isspilt || sym->nRegs == 0)
755 /* rematerialize it NOW */
758 sym->aop = op->aop = aop =
760 aop->size = getSize (sym->type);
767 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
768 aop->size = getSize (sym->type);
769 for (i = 0; i < 2; i++)
770 aop->aopu.aop_str[i] = accUse[i];
780 /* a AOP_STR uses DPTR, but DPTR is already in use;
783 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
786 aop = op->aop = sym->aop = newAsmop (AOP_STR);
787 aop->size = getSize (sym->type);
788 for (i = 0; i < (int) fReturnSizeDS390; i++)
789 aop->aopu.aop_str[i] = fReturn[i];
793 /* else spill location */
794 sym->aop = op->aop = aop =
795 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
796 aop->size = getSize (sym->type);
800 /* must be in a register */
801 sym->aop = op->aop = aop = newAsmop (AOP_REG);
802 aop->size = sym->nRegs;
803 for (i = 0; i < sym->nRegs; i++)
804 aop->aopu.aop_reg[i] = sym->regs[i];
807 /*-----------------------------------------------------------------*/
808 /* freeAsmop - free up the asmop given to an operand */
809 /*----------------------------------------------------------------*/
811 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
828 /* depending on the asmop type only three cases need work AOP_RO
829 , AOP_R1 && AOP_STK */
837 emitcode ("pop", "ar0");
841 bitVectUnSetBit (ic->rUsed, R0_IDX);
849 emitcode ("pop", "ar1");
853 bitVectUnSetBit (ic->rUsed, R1_IDX);
859 int stk = aop->aopu.aop_stk + aop->size;
860 bitVectUnSetBit (ic->rUsed, R0_IDX);
861 bitVectUnSetBit (ic->rUsed, R1_IDX);
863 getFreePtr (ic, &aop, FALSE);
865 if (options.stack10bit)
867 /* I'm not sure what to do here yet... */
870 "*** Warning: probably generating bad code for "
871 "10 bit stack mode.\n");
876 emitcode ("mov", "a,_bp");
877 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
878 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
882 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
887 emitcode ("pop", "acc");
888 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
891 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
894 freeAsmop (op, NULL, ic, TRUE);
897 emitcode ("pop", "ar0");
903 emitcode ("pop", "ar1");
910 /* all other cases just dealloc */
916 OP_SYMBOL (op)->aop = NULL;
917 /* if the symbol has a spill */
919 SPIL_LOC (op)->aop = NULL;
924 /*------------------------------------------------------------------*/
925 /* aopGet - for fetching value of the aop */
927 /* Set canClobberACC if you are sure it is OK to clobber the value */
928 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
929 /* just less efficient. */
930 /*------------------------------------------------------------------*/
942 /* offset is greater than
944 if (offset > (aop->size - 1) &&
945 aop->type != AOP_LIT)
948 /* depending on type */
954 /* if we need to increment it */
955 while (offset > aop->coff)
957 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
961 while (offset < aop->coff)
963 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
970 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
971 return (dname ? "acc" : "a");
973 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
974 rs = Safe_calloc (1, strlen (s) + 1);
981 if (aop->type == AOP_DPTR2)
987 emitcode ("xch", "a, %s", DP2_RESULT_REG);
993 while (offset > aop->coff)
995 emitcode ("inc", "dptr");
999 while (offset < aop->coff)
1001 emitcode ("lcall", "__decdptr");
1008 emitcode ("clr", "a");
1009 emitcode ("movc", "a,@a+dptr");
1013 emitcode ("movx", "a,@dptr");
1016 if (aop->type == AOP_DPTR2)
1022 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1023 return DP2_RESULT_REG;
1026 return (dname ? "acc" : "a");
1030 sprintf (s, "#%s", aop->aopu.aop_immd);
1032 sprintf (s, "#(%s >> %d)",
1037 aop->aopu.aop_immd);
1038 rs = Safe_calloc (1, strlen (s) + 1);
1044 sprintf (s, "(%s + %d)",
1048 sprintf (s, "%s", aop->aopu.aop_dir);
1049 rs = Safe_calloc (1, strlen (s) + 1);
1055 return aop->aopu.aop_reg[offset]->dname;
1057 return aop->aopu.aop_reg[offset]->name;
1060 emitcode ("clr", "a");
1061 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1062 emitcode ("rlc", "a");
1063 return (dname ? "acc" : "a");
1066 if (!offset && dname)
1068 return aop->aopu.aop_str[offset];
1071 return aopLiteral (aop->aopu.aop_lit, offset);
1075 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1079 return aop->aopu.aop_str[offset];
1083 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1084 "aopget got unsupported aop->type");
1087 /*-----------------------------------------------------------------*/
1088 /* aopPut - puts a string for a aop */
1089 /*-----------------------------------------------------------------*/
1091 aopPut (asmop * aop, char *s, int offset)
1095 if (aop->size && offset > (aop->size - 1))
1097 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1098 "aopPut got offset > aop->size");
1102 /* will assign value to value */
1103 /* depending on where it is ofcourse */
1108 sprintf (d, "(%s + %d)",
1109 aop->aopu.aop_dir, offset);
1111 sprintf (d, "%s", aop->aopu.aop_dir);
1114 emitcode ("mov", "%s,%s", d, s);
1119 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1120 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1123 strcmp (s, "r0") == 0 ||
1124 strcmp (s, "r1") == 0 ||
1125 strcmp (s, "r2") == 0 ||
1126 strcmp (s, "r3") == 0 ||
1127 strcmp (s, "r4") == 0 ||
1128 strcmp (s, "r5") == 0 ||
1129 strcmp (s, "r6") == 0 ||
1130 strcmp (s, "r7") == 0)
1131 emitcode ("mov", "%s,%s",
1132 aop->aopu.aop_reg[offset]->dname, s);
1134 emitcode ("mov", "%s,%s",
1135 aop->aopu.aop_reg[offset]->name, s);
1142 if (aop->type == AOP_DPTR2)
1150 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1151 "aopPut writting to code space");
1155 while (offset > aop->coff)
1158 emitcode ("inc", "dptr");
1161 while (offset < aop->coff)
1164 emitcode ("lcall", "__decdptr");
1169 /* if not in accumulater */
1172 emitcode ("movx", "@dptr,a");
1174 if (aop->type == AOP_DPTR2)
1182 while (offset > aop->coff)
1185 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1187 while (offset < aop->coff)
1190 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1197 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1203 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1205 else if (strcmp (s, "r0") == 0 ||
1206 strcmp (s, "r1") == 0 ||
1207 strcmp (s, "r2") == 0 ||
1208 strcmp (s, "r3") == 0 ||
1209 strcmp (s, "r4") == 0 ||
1210 strcmp (s, "r5") == 0 ||
1211 strcmp (s, "r6") == 0 ||
1212 strcmp (s, "r7") == 0)
1215 sprintf (buffer, "a%s", s);
1216 emitcode ("mov", "@%s,%s",
1217 aop->aopu.aop_ptr->name, buffer);
1220 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1225 if (strcmp (s, "a") == 0)
1226 emitcode ("push", "acc");
1228 emitcode ("push", "%s", s);
1233 /* if bit variable */
1234 if (!aop->aopu.aop_dir)
1236 emitcode ("clr", "a");
1237 emitcode ("rlc", "a");
1242 emitcode ("clr", "%s", aop->aopu.aop_dir);
1244 emitcode ("setb", "%s", aop->aopu.aop_dir);
1245 else if (!strcmp (s, "c"))
1246 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1249 if (strcmp (s, "a"))
1254 symbol *lbl = newiTempLabel (NULL);
1255 emitcode ("clr", "c");
1256 emitcode ("jz", "%05d$", lbl->key + 100);
1257 emitcode ("cpl", "c");
1258 emitcode ("", "%05d$:", lbl->key + 100);
1259 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1267 if (strcmp (aop->aopu.aop_str[offset], s))
1268 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1273 if (!offset && (strcmp (s, "acc") == 0))
1276 if (strcmp (aop->aopu.aop_str[offset], s))
1277 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1281 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1282 "aopPut got unsupported aop->type");
1289 /*--------------------------------------------------------------------*/
1290 /* reAdjustPreg - points a register back to where it should (coff==0) */
1291 /*--------------------------------------------------------------------*/
1293 reAdjustPreg (asmop * aop)
1295 if ((aop->coff==0) || (aop->size <= 1)) {
1304 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1308 if (aop->type == AOP_DPTR2)
1315 emitcode ("lcall", "__decdptr");
1318 if (aop->type == AOP_DPTR2)
1328 #define AOP(op) op->aop
1329 #define AOP_TYPE(op) AOP(op)->type
1330 #define AOP_SIZE(op) AOP(op)->size
1331 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1332 AOP_TYPE(x) == AOP_R0))
1334 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1335 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1338 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1339 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1340 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1342 /* Workaround for DS80C390 bug: div ab may return bogus results
1343 * if A is accessed in instruction immediately before the div.
1345 * Will be fixed in B4 rev of processor, Dallas claims.
1348 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1349 if (!AOP_NEEDSACC(RIGHT)) \
1351 /* We can load A first, then B, since \
1352 * B (the RIGHT operand) won't clobber A, \
1353 * thus avoiding touching A right before the div. \
1355 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1356 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1358 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1362 /* Just stuff in a nop after loading A. */ \
1363 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1364 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1366 emitcode("nop", "; workaround for DS80C390 div bug."); \
1369 /*-----------------------------------------------------------------*/
1370 /* genNotFloat - generates not for float operations */
1371 /*-----------------------------------------------------------------*/
1373 genNotFloat (operand * op, operand * res)
1379 D (emitcode (";", "genNotFloat ");
1382 /* we will put 127 in the first byte of
1384 aopPut (AOP (res), "#127", 0);
1385 size = AOP_SIZE (op) - 1;
1388 _startLazyDPSEvaluation ();
1389 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1394 emitcode ("orl", "a,%s",
1396 offset++, FALSE, FALSE, FALSE));
1398 _endLazyDPSEvaluation ();
1400 tlbl = newiTempLabel (NULL);
1401 aopPut (res->aop, one, 1);
1402 emitcode ("jz", "%05d$", (tlbl->key + 100));
1403 aopPut (res->aop, zero, 1);
1404 emitcode ("", "%05d$:", (tlbl->key + 100));
1406 size = res->aop->size - 2;
1408 /* put zeros in the rest */
1410 aopPut (res->aop, zero, offset++);
1413 /*-----------------------------------------------------------------*/
1414 /* opIsGptr: returns non-zero if the passed operand is */
1415 /* a generic pointer type. */
1416 /*-----------------------------------------------------------------*/
1418 opIsGptr (operand * op)
1420 sym_link *type = operandType (op);
1422 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1429 /*-----------------------------------------------------------------*/
1430 /* getDataSize - get the operand data size */
1431 /*-----------------------------------------------------------------*/
1433 getDataSize (operand * op)
1436 size = AOP_SIZE (op);
1437 if (size == GPTRSIZE)
1439 sym_link *type = operandType (op);
1440 if (IS_GENPTR (type))
1442 /* generic pointer; arithmetic operations
1443 * should ignore the high byte (pointer type).
1451 /*-----------------------------------------------------------------*/
1452 /* outAcc - output Acc */
1453 /*-----------------------------------------------------------------*/
1455 outAcc (operand * result)
1458 size = getDataSize (result);
1461 aopPut (AOP (result), "a", 0);
1464 /* unsigned or positive */
1467 aopPut (AOP (result), zero, offset++);
1472 /*-----------------------------------------------------------------*/
1473 /* outBitC - output a bit C */
1474 /*-----------------------------------------------------------------*/
1476 outBitC (operand * result)
1478 /* if the result is bit */
1479 if (AOP_TYPE (result) == AOP_CRY)
1481 aopPut (AOP (result), "c", 0);
1485 emitcode ("clr", "a");
1486 emitcode ("rlc", "a");
1491 /*-----------------------------------------------------------------*/
1492 /* toBoolean - emit code for orl a,operator(sizeop) */
1493 /*-----------------------------------------------------------------*/
1495 toBoolean (operand * oper)
1497 int size = AOP_SIZE (oper) - 1;
1501 /* The generic part of a generic pointer should
1502 * not participate in it's truth value.
1504 * i.e. 0x10000000 is zero.
1506 if (opIsGptr (oper))
1508 D (emitcode (";", "toBoolean: generic ptr special case.");
1513 _startLazyDPSEvaluation ();
1514 if (AOP_NEEDSACC (oper) && size)
1517 emitcode ("push", "b");
1518 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1522 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1528 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1532 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1535 _endLazyDPSEvaluation ();
1539 emitcode ("mov", "a,b");
1540 emitcode ("pop", "b");
1545 /*-----------------------------------------------------------------*/
1546 /* genNot - generate code for ! operation */
1547 /*-----------------------------------------------------------------*/
1552 sym_link *optype = operandType (IC_LEFT (ic));
1554 D (emitcode (";", "genNot ");
1557 /* assign asmOps to operand & result */
1558 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1559 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1561 /* if in bit space then a special case */
1562 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1564 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1565 emitcode ("cpl", "c");
1566 outBitC (IC_RESULT (ic));
1570 /* if type float then do float */
1571 if (IS_FLOAT (optype))
1573 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1577 toBoolean (IC_LEFT (ic));
1579 tlbl = newiTempLabel (NULL);
1580 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1581 emitcode ("", "%05d$:", tlbl->key + 100);
1582 outBitC (IC_RESULT (ic));
1585 /* release the aops */
1586 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1587 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1591 /*-----------------------------------------------------------------*/
1592 /* genCpl - generate code for complement */
1593 /*-----------------------------------------------------------------*/
1600 D (emitcode (";", "genCpl ");
1604 /* assign asmOps to operand & result */
1605 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1606 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1608 /* if both are in bit space then
1610 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1611 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1614 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1615 emitcode ("cpl", "c");
1616 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1620 size = AOP_SIZE (IC_RESULT (ic));
1621 _startLazyDPSEvaluation ();
1624 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1626 emitcode ("cpl", "a");
1627 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1629 _endLazyDPSEvaluation ();
1633 /* release the aops */
1634 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1635 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1638 /*-----------------------------------------------------------------*/
1639 /* genUminusFloat - unary minus for floating points */
1640 /*-----------------------------------------------------------------*/
1642 genUminusFloat (operand * op, operand * result)
1644 int size, offset = 0;
1646 /* for this we just need to flip the
1647 first it then copy the rest in place */
1648 D (emitcode (";", "genUminusFloat");
1651 _startLazyDPSEvaluation ();
1652 size = AOP_SIZE (op) - 1;
1653 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1656 emitcode ("cpl", "acc.7");
1657 aopPut (AOP (result), "a", 3);
1661 aopPut (AOP (result),
1662 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1666 _endLazyDPSEvaluation ();
1669 /*-----------------------------------------------------------------*/
1670 /* genUminus - unary minus code generation */
1671 /*-----------------------------------------------------------------*/
1673 genUminus (iCode * ic)
1676 sym_link *optype, *rtype;
1678 D (emitcode (";", "genUminus ");
1683 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1684 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1686 /* if both in bit space then special
1688 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1689 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1692 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1693 emitcode ("cpl", "c");
1694 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1698 optype = operandType (IC_LEFT (ic));
1699 rtype = operandType (IC_RESULT (ic));
1701 /* if float then do float stuff */
1702 if (IS_FLOAT (optype))
1704 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1708 /* otherwise subtract from zero */
1709 size = AOP_SIZE (IC_LEFT (ic));
1711 _startLazyDPSEvaluation ();
1714 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1715 if (!strcmp (l, "a"))
1719 emitcode ("cpl", "a");
1720 emitcode ("addc", "a,#0");
1726 emitcode ("clr", "a");
1727 emitcode ("subb", "a,%s", l);
1729 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1731 _endLazyDPSEvaluation ();
1733 /* if any remaining bytes in the result */
1734 /* we just need to propagate the sign */
1735 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1737 emitcode ("rlc", "a");
1738 emitcode ("subb", "a,acc");
1740 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1744 /* release the aops */
1745 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1746 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1749 /*-----------------------------------------------------------------*/
1750 /* saveRegisters - will look for a call and save the registers */
1751 /*-----------------------------------------------------------------*/
1753 saveRegisters (iCode * lic)
1761 for (ic = lic; ic; ic = ic->next)
1762 if (ic->op == CALL || ic->op == PCALL)
1767 fprintf (stderr, "found parameter push with no function call\n");
1771 /* if the registers have been saved already then
1773 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1774 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
1777 /* find the registers in use at this time
1778 and push them away to safety */
1779 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1783 if (options.useXstack)
1785 if (bitVectBitValue (rsave, R0_IDX))
1786 emitcode ("mov", "b,r0");
1787 emitcode ("mov", "r0,%s", spname);
1788 for (i = 0; i < ds390_nRegs; i++)
1790 if (bitVectBitValue (rsave, i))
1793 emitcode ("mov", "a,b");
1795 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1796 emitcode ("movx", "@r0,a");
1797 emitcode ("inc", "r0");
1800 emitcode ("mov", "%s,r0", spname);
1801 if (bitVectBitValue (rsave, R0_IDX))
1802 emitcode ("mov", "r0,b");
1805 for (i = 0; i < ds390_nRegs; i++)
1807 if (bitVectBitValue (rsave, i))
1808 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1811 detype = getSpec (operandType (IC_LEFT (ic)));
1814 /*-----------------------------------------------------------------*/
1815 /* unsaveRegisters - pop the pushed registers */
1816 /*-----------------------------------------------------------------*/
1818 unsaveRegisters (iCode * ic)
1822 /* find the registers in use at this time
1823 and push them away to safety */
1824 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1827 if (options.useXstack)
1829 emitcode ("mov", "r0,%s", spname);
1830 for (i = ds390_nRegs; i >= 0; i--)
1832 if (bitVectBitValue (rsave, i))
1834 emitcode ("dec", "r0");
1835 emitcode ("movx", "a,@r0");
1837 emitcode ("mov", "b,a");
1839 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1843 emitcode ("mov", "%s,r0", spname);
1844 if (bitVectBitValue (rsave, R0_IDX))
1845 emitcode ("mov", "r0,b");
1848 for (i = ds390_nRegs; i >= 0; i--)
1850 if (bitVectBitValue (rsave, i))
1851 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1857 /*-----------------------------------------------------------------*/
1859 /*-----------------------------------------------------------------*/
1861 pushSide (operand * oper, int size)
1864 _startLazyDPSEvaluation ();
1867 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1868 if (AOP_TYPE (oper) != AOP_REG &&
1869 AOP_TYPE (oper) != AOP_DIR &&
1872 emitcode ("mov", "a,%s", l);
1873 emitcode ("push", "acc");
1876 emitcode ("push", "%s", l);
1878 _endLazyDPSEvaluation ();
1881 /*-----------------------------------------------------------------*/
1882 /* assignResultValue - */
1883 /*-----------------------------------------------------------------*/
1885 assignResultValue (operand * oper)
1888 int size = AOP_SIZE (oper);
1890 _startLazyDPSEvaluation ();
1893 aopPut (AOP (oper), fReturn[offset], offset);
1896 _endLazyDPSEvaluation ();
1900 /*-----------------------------------------------------------------*/
1901 /* genXpush - pushes onto the external stack */
1902 /*-----------------------------------------------------------------*/
1904 genXpush (iCode * ic)
1906 asmop *aop = newAsmop (0);
1908 int size, offset = 0;
1910 D (emitcode (";", "genXpush ");
1913 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1914 r = getFreePtr (ic, &aop, FALSE);
1917 emitcode ("mov", "%s,_spx", r->name);
1919 size = AOP_SIZE (IC_LEFT (ic));
1920 _startLazyDPSEvaluation ();
1924 char *l = aopGet (AOP (IC_LEFT (ic)),
1925 offset++, FALSE, FALSE, TRUE);
1927 emitcode ("movx", "@%s,a", r->name);
1928 emitcode ("inc", "%s", r->name);
1931 _endLazyDPSEvaluation ();
1934 emitcode ("mov", "_spx,%s", r->name);
1936 freeAsmop (NULL, aop, ic, TRUE);
1937 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1940 /*-----------------------------------------------------------------*/
1941 /* genIpush - genrate code for pushing this gets a little complex */
1942 /*-----------------------------------------------------------------*/
1944 genIpush (iCode * ic)
1946 int size, offset = 0;
1949 D (emitcode (";", "genIpush ");
1952 /* if this is not a parm push : ie. it is spill push
1953 and spill push is always done on the local stack */
1957 /* and the item is spilt then do nothing */
1958 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1961 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1962 size = AOP_SIZE (IC_LEFT (ic));
1963 /* push it on the stack */
1964 _startLazyDPSEvaluation ();
1967 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1973 emitcode ("push", "%s", l);
1975 _endLazyDPSEvaluation ();
1979 /* this is a paramter push: in this case we call
1980 the routine to find the call and save those
1981 registers that need to be saved */
1984 /* if use external stack then call the external
1985 stack pushing routine */
1986 if (options.useXstack)
1992 /* then do the push */
1993 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1995 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1996 size = AOP_SIZE (IC_LEFT (ic));
1998 _startLazyDPSEvaluation ();
2001 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2002 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2003 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2006 emitcode ("mov", "a,%s", l);
2007 emitcode ("push", "acc");
2010 emitcode ("push", "%s", l);
2012 _endLazyDPSEvaluation ();
2014 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2017 /*-----------------------------------------------------------------*/
2018 /* genIpop - recover the registers: can happen only for spilling */
2019 /*-----------------------------------------------------------------*/
2021 genIpop (iCode * ic)
2025 D (emitcode (";", "genIpop ");
2029 /* if the temp was not pushed then */
2030 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2033 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2034 size = AOP_SIZE (IC_LEFT (ic));
2035 offset = (size - 1);
2036 _startLazyDPSEvaluation ();
2039 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2040 FALSE, TRUE, TRUE));
2042 _endLazyDPSEvaluation ();
2044 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2047 /*-----------------------------------------------------------------*/
2048 /* unsaveRBank - restores the resgister bank from stack */
2049 /*-----------------------------------------------------------------*/
2051 unsaveRBank (int bank, iCode * ic, bool popPsw)
2057 if (options.useXstack)
2061 /* Assume r0 is available for use. */
2062 r = ds390_regWithIdx (R0_IDX);;
2067 r = getFreePtr (ic, &aop, FALSE);
2069 emitcode ("mov", "%s,_spx", r->name);
2074 if (options.useXstack)
2076 emitcode ("movx", "a,@%s", r->name);
2077 emitcode ("mov", "psw,a");
2078 emitcode ("dec", "%s", r->name);
2082 emitcode ("pop", "psw");
2086 for (i = (ds390_nRegs - 1); i >= 0; i--)
2088 if (options.useXstack)
2090 emitcode ("movx", "a,@%s", r->name);
2091 emitcode ("mov", "(%s+%d),a",
2092 regs390[i].base, 8 * bank + regs390[i].offset);
2093 emitcode ("dec", "%s", r->name);
2097 emitcode ("pop", "(%s+%d)",
2098 regs390[i].base, 8 * bank + regs390[i].offset);
2101 if (options.useXstack)
2103 emitcode ("mov", "_spx,%s", r->name);
2108 freeAsmop (NULL, aop, ic, TRUE);
2112 /*-----------------------------------------------------------------*/
2113 /* saveRBank - saves an entire register bank on the stack */
2114 /*-----------------------------------------------------------------*/
2116 saveRBank (int bank, iCode * ic, bool pushPsw)
2122 if (options.useXstack)
2126 /* Assume r0 is available for use. */
2127 r = ds390_regWithIdx (R0_IDX);;
2132 r = getFreePtr (ic, &aop, FALSE);
2134 emitcode ("mov", "%s,_spx", r->name);
2137 for (i = 0; i < ds390_nRegs; i++)
2139 if (options.useXstack)
2141 emitcode ("inc", "%s", r->name);
2142 emitcode ("mov", "a,(%s+%d)",
2143 regs390[i].base, 8 * bank + regs390[i].offset);
2144 emitcode ("movx", "@%s,a", r->name);
2147 emitcode ("push", "(%s+%d)",
2148 regs390[i].base, 8 * bank + regs390[i].offset);
2153 if (options.useXstack)
2155 emitcode ("mov", "a,psw");
2156 emitcode ("movx", "@%s,a", r->name);
2157 emitcode ("inc", "%s", r->name);
2158 emitcode ("mov", "_spx,%s", r->name);
2162 emitcode ("push", "psw");
2165 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2170 freeAsmop (NULL, aop, ic, TRUE);
2179 /*-----------------------------------------------------------------*/
2180 /* genCall - generates a call statement */
2181 /*-----------------------------------------------------------------*/
2183 genCall (iCode * ic)
2186 bool restoreBank = FALSE;
2187 bool swapBanks = FALSE;
2189 D (emitcode (";", "genCall "););
2191 /* if we are calling a not _naked function that is not using
2192 the same register bank then we need to save the
2193 destination registers on the stack */
2194 detype = getSpec (operandType (IC_LEFT (ic)));
2195 if (detype && !SPEC_NAKED(detype) &&
2196 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2197 IS_ISR (currFunc->etype))
2201 /* This is unexpected; the bank should have been saved in
2204 saveRBank (SPEC_BANK (detype), ic, FALSE);
2210 /* if caller saves & we have not saved then */
2214 /* if send set is not empty the assign */
2215 /* We've saved all the registers we care about;
2216 * therefore, we may clobber any register not used
2217 * in the calling convention (i.e. anything not in
2224 for (sic = setFirstItem (_G.sendSet); sic;
2225 sic = setNextItem (_G.sendSet))
2227 int size, offset = 0;
2229 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2230 size = AOP_SIZE (IC_LEFT (sic));
2232 _startLazyDPSEvaluation ();
2235 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2236 FALSE, FALSE, TRUE);
2237 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2239 emitcode("mov", "%s,%s", regs390[offset].name, l);
2241 else if (strcmp (l, fReturn[offset]))
2243 emitcode ("mov", "%s,%s",
2249 _endLazyDPSEvaluation ();
2250 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2252 size = AOP_SIZE (IC_LEFT (sic));
2260 emitcode("mov", "%s,%s",
2261 fReturn[size], regs390[size].name);
2264 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2271 emitcode ("mov", "psw,#0x%02x",
2272 ((SPEC_BANK(detype)) << 3) & 0xff);
2276 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2277 OP_SYMBOL (IC_LEFT (ic))->rname :
2278 OP_SYMBOL (IC_LEFT (ic))->name));
2282 emitcode ("mov", "psw,#0x%02x",
2283 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
2286 /* if we need assign a result value */
2287 if ((IS_ITEMP (IC_RESULT (ic)) &&
2288 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2289 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2290 IS_TRUE_SYMOP (IC_RESULT (ic)))
2292 if (isOperandInFarSpace (IC_RESULT (ic))
2293 && getSize (operandType (IC_RESULT (ic))) <= 2)
2295 int size = getSize (operandType (IC_RESULT (ic)));
2297 /* Special case for 1 or 2 byte return in far space. */
2301 emitcode ("mov", "b,%s", fReturn[1]);
2304 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2305 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2309 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2311 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2316 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2319 assignResultValue (IC_RESULT (ic));
2321 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2325 /* adjust the stack for parameters if
2330 if (ic->parmBytes > 3)
2332 emitcode ("mov", "a,%s", spname);
2333 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2334 emitcode ("mov", "%s,a", spname);
2337 for (i = 0; i < ic->parmBytes; i++)
2338 emitcode ("dec", "%s", spname);
2341 /* if we hade saved some registers then unsave them */
2342 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2343 unsaveRegisters (ic);
2345 /* if register bank was saved then pop them */
2347 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
2350 /*-----------------------------------------------------------------*/
2351 /* genPcall - generates a call by pointer statement */
2352 /*-----------------------------------------------------------------*/
2354 genPcall (iCode * ic)
2357 symbol *rlbl = newiTempLabel (NULL);
2359 D (emitcode (";", "genPcall ");
2363 /* if caller saves & we have not saved then */
2367 /* if we are calling a function that is not using
2368 the same register bank then we need to save the
2369 destination registers on the stack */
2370 detype = getSpec (operandType (IC_LEFT (ic)));
2372 IS_ISR (currFunc->etype) &&
2373 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2374 saveRBank (SPEC_BANK (detype), ic, TRUE);
2377 /* push the return address on to the stack */
2378 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2379 emitcode ("push", "acc");
2380 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2381 emitcode ("push", "acc");
2383 if (options.model == MODEL_FLAT24)
2385 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2386 emitcode ("push", "acc");
2389 /* now push the calling address */
2390 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2392 pushSide (IC_LEFT (ic), FPTRSIZE);
2394 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2396 /* if send set is not empty the assign */
2401 for (sic = setFirstItem (_G.sendSet); sic;
2402 sic = setNextItem (_G.sendSet))
2404 int size, offset = 0;
2406 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2407 size = AOP_SIZE (IC_LEFT (sic));
2408 _startLazyDPSEvaluation ();
2411 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2412 FALSE, FALSE, TRUE);
2413 if (strcmp (l, fReturn[offset]))
2415 emitcode ("mov", "%s,%s",
2421 _endLazyDPSEvaluation ();
2422 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2427 emitcode ("ret", "");
2428 emitcode ("", "%05d$:", (rlbl->key + 100));
2431 /* if we need assign a result value */
2432 if ((IS_ITEMP (IC_RESULT (ic)) &&
2433 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2434 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2435 IS_TRUE_SYMOP (IC_RESULT (ic)))
2439 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2442 assignResultValue (IC_RESULT (ic));
2444 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2447 /* adjust the stack for parameters if
2452 if (ic->parmBytes > 3)
2454 emitcode ("mov", "a,%s", spname);
2455 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2456 emitcode ("mov", "%s,a", spname);
2459 for (i = 0; i < ic->parmBytes; i++)
2460 emitcode ("dec", "%s", spname);
2464 /* if register bank was saved then unsave them */
2466 (SPEC_BANK (currFunc->etype) !=
2467 SPEC_BANK (detype)))
2468 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2470 /* if we hade saved some registers then
2473 unsaveRegisters (ic);
2477 /*-----------------------------------------------------------------*/
2478 /* resultRemat - result is rematerializable */
2479 /*-----------------------------------------------------------------*/
2481 resultRemat (iCode * ic)
2483 if (SKIP_IC (ic) || ic->op == IFX)
2486 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2488 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2489 if (sym->remat && !POINTER_SET (ic))
2496 #if defined(__BORLANDC__) || defined(_MSC_VER)
2497 #define STRCASECMP stricmp
2499 #define STRCASECMP strcasecmp
2502 /*-----------------------------------------------------------------*/
2503 /* inExcludeList - return 1 if the string is in exclude Reg list */
2504 /*-----------------------------------------------------------------*/
2506 inExcludeList (char *s)
2510 if (options.excludeRegs[i] &&
2511 STRCASECMP (options.excludeRegs[i], "none") == 0)
2514 for (i = 0; options.excludeRegs[i]; i++)
2516 if (options.excludeRegs[i] &&
2517 STRCASECMP (s, options.excludeRegs[i]) == 0)
2523 /*-----------------------------------------------------------------*/
2524 /* genFunction - generated code for function entry */
2525 /*-----------------------------------------------------------------*/
2527 genFunction (iCode * ic)
2531 bool switchedPSW = FALSE;
2533 D (emitcode (";", "genFunction "););
2536 /* create the function header */
2537 emitcode (";", "-----------------------------------------");
2538 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2539 emitcode (";", "-----------------------------------------");
2541 emitcode ("", "%s:", sym->rname);
2542 fetype = getSpec (operandType (IC_LEFT (ic)));
2544 if (SPEC_NAKED(fetype))
2546 emitcode(";", "naked function: no prologue.");
2550 /* if critical function then turn interrupts off */
2551 if (SPEC_CRTCL (fetype))
2552 emitcode ("clr", "ea");
2554 /* here we need to generate the equates for the
2555 register bank if required */
2556 if (SPEC_BANK (fetype) != rbank)
2560 rbank = SPEC_BANK (fetype);
2561 for (i = 0; i < ds390_nRegs; i++)
2563 if (strcmp (regs390[i].base, "0") == 0)
2564 emitcode ("", "%s = 0x%02x",
2566 8 * rbank + regs390[i].offset);
2568 emitcode ("", "%s = %s + 0x%02x",
2571 8 * rbank + regs390[i].offset);
2575 /* if this is an interrupt service routine then
2576 save acc, b, dpl, dph */
2577 if (IS_ISR (sym->etype))
2580 if (!inExcludeList ("acc"))
2581 emitcode ("push", "acc");
2582 if (!inExcludeList ("b"))
2583 emitcode ("push", "b");
2584 if (!inExcludeList ("dpl"))
2585 emitcode ("push", "dpl");
2586 if (!inExcludeList ("dph"))
2587 emitcode ("push", "dph");
2588 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2590 emitcode ("push", "dpx");
2591 /* Make sure we're using standard DPTR */
2592 emitcode ("push", "dps");
2593 emitcode ("mov", "dps, #0x00");
2594 if (options.stack10bit)
2596 /* This ISR could conceivably use DPTR2. Better save it. */
2597 emitcode ("push", "dpl1");
2598 emitcode ("push", "dph1");
2599 emitcode ("push", "dpx1");
2600 emitcode ("push", DP2_RESULT_REG);
2603 /* if this isr has no bank i.e. is going to
2604 run with bank 0 , then we need to save more
2606 if (!SPEC_BANK (sym->etype))
2609 /* if this function does not call any other
2610 function then we can be economical and
2611 save only those registers that are used */
2616 /* if any registers used */
2619 /* save the registers used */
2620 for (i = 0; i < sym->regsUsed->size; i++)
2622 if (bitVectBitValue (sym->regsUsed, i) ||
2623 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2624 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2631 /* this function has a function call cannot
2632 determines register usage so we will have to push the
2634 saveRBank (0, ic, FALSE);
2639 /* This ISR uses a non-zero bank.
2641 * We assume that the bank is available for our
2644 * However, if this ISR calls a function which uses some
2645 * other bank, we must save that bank entirely.
2647 unsigned long banksToSave = 0;
2652 #define MAX_REGISTER_BANKS 4
2657 for (i = ic; i; i = i->next)
2659 if (i->op == ENDFUNCTION)
2661 /* we got to the end OK. */
2669 detype = getSpec(operandType (IC_LEFT(i)));
2671 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2673 /* Mark this bank for saving. */
2674 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2676 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2680 banksToSave |= (1 << SPEC_BANK(detype));
2683 /* And note that we don't need to do it in
2691 /* This is a mess; we have no idea what
2692 * register bank the called function might
2695 * The only thing I can think of to do is
2696 * throw a warning and hope.
2698 werror(W_FUNCPTR_IN_USING_ISR);
2702 if (banksToSave && options.useXstack)
2704 /* Since we aren't passing it an ic,
2705 * saveRBank will assume r0 is available to abuse.
2707 * So switch to our (trashable) bank now, so
2708 * the caller's R0 isn't trashed.
2710 emitcode ("push", "psw");
2711 emitcode ("mov", "psw,#0x%02x",
2712 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2716 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2718 if (banksToSave & (1 << ix))
2720 saveRBank(ix, NULL, FALSE);
2724 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2729 /* if callee-save to be used for this function
2730 then save the registers being used in this function */
2731 if (sym->calleeSave)
2735 /* if any registers used */
2738 /* save the registers used */
2739 for (i = 0; i < sym->regsUsed->size; i++)
2741 if (bitVectBitValue (sym->regsUsed, i) ||
2742 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2744 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2752 /* set the register bank to the desired value */
2753 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2756 emitcode ("push", "psw");
2757 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2760 if (IS_RENT (sym->etype) || options.stackAuto)
2763 if (options.useXstack)
2765 emitcode ("mov", "r0,%s", spname);
2766 emitcode ("mov", "a,_bp");
2767 emitcode ("movx", "@r0,a");
2768 emitcode ("inc", "%s", spname);
2772 /* set up the stack */
2773 emitcode ("push", "_bp"); /* save the callers stack */
2775 emitcode ("mov", "_bp,%s", spname);
2778 /* adjust the stack for the function */
2784 werror (W_STACK_OVERFLOW, sym->name);
2786 if (i > 3 && sym->recvSize < 4)
2789 emitcode ("mov", "a,sp");
2790 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2791 emitcode ("mov", "sp,a");
2796 emitcode ("inc", "sp");
2802 emitcode ("mov", "a,_spx");
2803 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2804 emitcode ("mov", "_spx,a");
2809 /*-----------------------------------------------------------------*/
2810 /* genEndFunction - generates epilogue for functions */
2811 /*-----------------------------------------------------------------*/
2813 genEndFunction (iCode * ic)
2815 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2817 D (emitcode (";", "genEndFunction "););
2819 if (SPEC_NAKED(sym->etype))
2821 emitcode(";", "naked function: no epilogue.");
2825 if (IS_RENT (sym->etype) || options.stackAuto)
2827 emitcode ("mov", "%s,_bp", spname);
2830 /* if use external stack but some variables were
2831 added to the local stack then decrement the
2833 if (options.useXstack && sym->stack)
2835 emitcode ("mov", "a,sp");
2836 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2837 emitcode ("mov", "sp,a");
2841 if ((IS_RENT (sym->etype) || options.stackAuto))
2843 if (options.useXstack)
2845 emitcode ("mov", "r0,%s", spname);
2846 emitcode ("movx", "a,@r0");
2847 emitcode ("mov", "_bp,a");
2848 emitcode ("dec", "%s", spname);
2852 emitcode ("pop", "_bp");
2856 /* restore the register bank */
2857 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2859 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2860 || !options.useXstack)
2862 /* Special case of ISR using non-zero bank with useXstack
2865 emitcode ("pop", "psw");
2869 if (IS_ISR (sym->etype))
2872 /* now we need to restore the registers */
2873 /* if this isr has no bank i.e. is going to
2874 run with bank 0 , then we need to save more
2876 if (!SPEC_BANK (sym->etype))
2878 /* if this function does not call any other
2879 function then we can be economical and
2880 save only those registers that are used */
2885 /* if any registers used */
2888 /* save the registers used */
2889 for (i = sym->regsUsed->size; i >= 0; i--)
2891 if (bitVectBitValue (sym->regsUsed, i) ||
2892 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2893 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2900 /* this function has a function call cannot
2901 determines register usage so we will have to pop the
2903 unsaveRBank (0, ic, FALSE);
2908 /* This ISR uses a non-zero bank.
2910 * Restore any register banks saved by genFunction
2913 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2916 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2918 if (savedBanks & (1 << ix))
2920 unsaveRBank(ix, NULL, FALSE);
2924 if (options.useXstack)
2926 /* Restore bank AFTER calling unsaveRBank,
2927 * since it can trash r0.
2929 emitcode ("pop", "psw");
2933 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2935 if (options.stack10bit)
2937 emitcode ("pop", DP2_RESULT_REG);
2938 emitcode ("pop", "dpx1");
2939 emitcode ("pop", "dph1");
2940 emitcode ("pop", "dpl1");
2942 emitcode ("pop", "dps");
2943 emitcode ("pop", "dpx");
2945 if (!inExcludeList ("dph"))
2946 emitcode ("pop", "dph");
2947 if (!inExcludeList ("dpl"))
2948 emitcode ("pop", "dpl");
2949 if (!inExcludeList ("b"))
2950 emitcode ("pop", "b");
2951 if (!inExcludeList ("acc"))
2952 emitcode ("pop", "acc");
2954 if (SPEC_CRTCL (sym->etype))
2955 emitcode ("setb", "ea");
2957 /* if debug then send end of function */
2958 if (options.debug && currFunc) {
2960 emitcode ("", "C$%s$%d$%d$%d ==.",
2961 FileBaseName (ic->filename), currFunc->lastLine,
2962 ic->level, ic->block);
2963 if (IS_STATIC (currFunc->etype))
2964 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2966 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2970 emitcode ("reti", "");
2974 if (SPEC_CRTCL (sym->etype))
2975 emitcode ("setb", "ea");
2977 if (sym->calleeSave)
2981 /* if any registers used */
2984 /* save the registers used */
2985 for (i = sym->regsUsed->size; i >= 0; i--)
2987 if (bitVectBitValue (sym->regsUsed, i) ||
2988 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2989 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2995 /* if debug then send end of function */
2996 if (options.debug && currFunc)
2999 emitcode ("", "C$%s$%d$%d$%d ==.",
3000 FileBaseName (ic->filename), currFunc->lastLine,
3001 ic->level, ic->block);
3002 if (IS_STATIC (currFunc->etype))
3003 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3005 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3009 emitcode ("ret", "");
3014 /*-----------------------------------------------------------------*/
3015 /* genRet - generate code for return statement */
3016 /*-----------------------------------------------------------------*/
3020 int size, offset = 0, pushed = 0;
3022 D (emitcode (";", "genRet ");
3025 /* if we have no return value then
3026 just generate the "ret" */
3030 /* we have something to return then
3031 move the return value into place */
3032 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3033 size = AOP_SIZE (IC_LEFT (ic));
3035 _startLazyDPSEvaluation ();
3039 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3041 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3042 FALSE, TRUE, FALSE);
3043 emitcode ("push", "%s", l);
3048 /* Since A is the last element of fReturn,
3049 * is is OK to clobber it in the aopGet.
3051 l = aopGet (AOP (IC_LEFT (ic)), offset,
3052 FALSE, FALSE, TRUE);
3053 if (strcmp (fReturn[offset], l))
3054 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3057 _endLazyDPSEvaluation ();
3064 if (strcmp (fReturn[pushed], "a"))
3065 emitcode ("pop", fReturn[pushed]);
3067 emitcode ("pop", "acc");
3070 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3073 /* generate a jump to the return label
3074 if the next is not the return statement */
3075 if (!(ic->next && ic->next->op == LABEL &&
3076 IC_LABEL (ic->next) == returnLabel))
3078 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3082 /*-----------------------------------------------------------------*/
3083 /* genLabel - generates a label */
3084 /*-----------------------------------------------------------------*/
3086 genLabel (iCode * ic)
3088 /* special case never generate */
3089 if (IC_LABEL (ic) == entryLabel)
3092 D (emitcode (";", "genLabel ");
3095 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3098 /*-----------------------------------------------------------------*/
3099 /* genGoto - generates a ljmp */
3100 /*-----------------------------------------------------------------*/
3102 genGoto (iCode * ic)
3104 D (emitcode (";", "genGoto ");
3106 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3109 /*-----------------------------------------------------------------*/
3110 /* findLabelBackwards: walks back through the iCode chain looking */
3111 /* for the given label. Returns number of iCode instructions */
3112 /* between that label and given ic. */
3113 /* Returns zero if label not found. */
3114 /*-----------------------------------------------------------------*/
3116 findLabelBackwards (iCode * ic, int key)
3125 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3127 /* printf("findLabelBackwards = %d\n", count); */
3135 /*-----------------------------------------------------------------*/
3136 /* genPlusIncr :- does addition with increment if possible */
3137 /*-----------------------------------------------------------------*/
3139 genPlusIncr (iCode * ic)
3141 unsigned int icount;
3142 unsigned int size = getDataSize (IC_RESULT (ic));
3144 /* will try to generate an increment */
3145 /* if the right side is not a literal
3147 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3150 /* if the literal value of the right hand side
3151 is greater than 4 then it is not worth it */
3152 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3155 /* if increment 16 bits in register */
3157 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3158 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3159 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3167 /* If the next instruction is a goto and the goto target
3168 * is <= 5 instructions previous to this, we can generate
3169 * jumps straight to that target.
3171 if (ic->next && ic->next->op == GOTO
3172 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3175 emitcode (";", "tail increment optimized (range %d)", labelRange);
3176 tlbl = IC_LABEL (ic->next);
3181 tlbl = newiTempLabel (NULL);
3184 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3185 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3186 IS_AOP_PREG (IC_RESULT (ic)))
3187 emitcode ("cjne", "%s,#0x00,%05d$"
3188 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3192 emitcode ("clr", "a");
3193 emitcode ("cjne", "a,%s,%05d$"
3194 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3198 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3201 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3202 IS_AOP_PREG (IC_RESULT (ic)))
3203 emitcode ("cjne", "%s,#0x00,%05d$"
3204 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3207 emitcode ("cjne", "a,%s,%05d$"
3208 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3211 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3215 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3216 IS_AOP_PREG (IC_RESULT (ic)))
3217 emitcode ("cjne", "%s,#0x00,%05d$"
3218 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3222 emitcode ("cjne", "a,%s,%05d$"
3223 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3226 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3231 emitcode ("", "%05d$:", tlbl->key + 100);
3236 /* if the sizes are greater than 1 then we cannot */
3237 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3238 AOP_SIZE (IC_LEFT (ic)) > 1)
3241 /* we can if the aops of the left & result match or
3242 if they are in registers and the registers are the
3245 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3246 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3247 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3252 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3253 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3254 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3259 _startLazyDPSEvaluation ();
3262 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3264 _endLazyDPSEvaluation ();
3273 /*-----------------------------------------------------------------*/
3274 /* outBitAcc - output a bit in acc */
3275 /*-----------------------------------------------------------------*/
3277 outBitAcc (operand * result)
3279 symbol *tlbl = newiTempLabel (NULL);
3280 /* if the result is a bit */
3281 if (AOP_TYPE (result) == AOP_CRY)
3283 aopPut (AOP (result), "a", 0);
3287 emitcode ("jz", "%05d$", tlbl->key + 100);
3288 emitcode ("mov", "a,%s", one);
3289 emitcode ("", "%05d$:", tlbl->key + 100);
3294 /*-----------------------------------------------------------------*/
3295 /* genPlusBits - generates code for addition of two bits */
3296 /*-----------------------------------------------------------------*/
3298 genPlusBits (iCode * ic)
3300 D (emitcode (";", "genPlusBits ");
3302 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3304 symbol *lbl = newiTempLabel (NULL);
3305 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3306 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3307 emitcode ("cpl", "c");
3308 emitcode ("", "%05d$:", (lbl->key + 100));
3309 outBitC (IC_RESULT (ic));
3313 emitcode ("clr", "a");
3314 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3315 emitcode ("rlc", "a");
3316 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3317 emitcode ("addc", "a,#0x00");
3318 outAcc (IC_RESULT (ic));
3323 adjustArithmeticResult (iCode * ic)
3325 if (opIsGptr (IC_RESULT (ic)) &&
3326 opIsGptr (IC_LEFT (ic)) &&
3327 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3329 aopPut (AOP (IC_RESULT (ic)),
3330 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3334 if (opIsGptr (IC_RESULT (ic)) &&
3335 opIsGptr (IC_RIGHT (ic)) &&
3336 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3338 aopPut (AOP (IC_RESULT (ic)),
3339 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3343 if (opIsGptr (IC_RESULT (ic)) &&
3344 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3345 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3346 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3347 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3350 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3351 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3355 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3356 // (because all three operands are in far space).
3357 #define AOP_OP_3(ic) \
3358 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3359 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3360 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3361 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3362 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3363 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3365 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3367 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3370 // Macro to aopOp all three operands of an ic. If this cannot be done,
3371 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3372 // will be set TRUE. The caller must then handle the case specially, noting
3373 // that the IC_RESULT operand is not aopOp'd.
3374 #define AOP_OP_3_NOFATAL(ic, rc) \
3375 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3376 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3377 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3378 isOperandInFarSpace(IC_RESULT(ic))) \
3380 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3385 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3386 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3388 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3389 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3391 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3393 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3397 // aopOp the left & right operands of an ic.
3398 #define AOP_OP_2(ic) \
3399 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3400 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3402 // convienience macro.
3403 #define AOP_SET_LOCALS(ic) \
3404 left = IC_LEFT(ic); \
3405 right = IC_RIGHT(ic); \
3406 result = IC_RESULT(ic);
3409 // Given an integer value of pushedSize bytes on the stack,
3410 // adjust it to be resultSize bytes, either by discarding
3411 // the most significant bytes or by zero-padding.
3413 // On exit from this macro, pushedSize will have been adjusted to
3414 // equal resultSize, and ACC may be trashed.
3415 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3416 /* If the pushed data is bigger than the result, \
3417 * simply discard unused bytes. Icky, but works. \
3419 while (pushedSize > resultSize) \
3421 D (emitcode (";", "discarding unused result byte."););\
3422 emitcode ("pop", "acc"); \
3425 if (pushedSize < resultSize) \
3427 emitcode ("clr", "a"); \
3428 /* Conversly, we haven't pushed enough here. \
3429 * just zero-pad, and all is well. \
3431 while (pushedSize < resultSize) \
3433 emitcode("push", "acc"); \
3437 assert(pushedSize == resultSize);
3439 /*-----------------------------------------------------------------*/
3440 /* genPlus - generates code for addition */
3441 /*-----------------------------------------------------------------*/
3443 genPlus (iCode * ic)
3445 int size, offset = 0;
3446 bool pushResult = FALSE;
3449 D (emitcode (";", "genPlus "););
3451 /* special cases :- */
3453 AOP_OP_3_NOFATAL (ic, pushResult);
3456 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3461 /* if literal, literal on the right or
3462 if left requires ACC or right is already
3464 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3465 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3466 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3468 operand *t = IC_RIGHT (ic);
3469 IC_RIGHT (ic) = IC_LEFT (ic);
3471 emitcode (";", "Swapped plus args.");
3474 /* if both left & right are in bit
3476 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3477 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3483 /* if left in bit space & right literal */
3484 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3485 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3487 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3488 /* if result in bit space */
3489 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3491 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3492 emitcode ("cpl", "c");
3493 outBitC (IC_RESULT (ic));
3497 size = getDataSize (IC_RESULT (ic));
3498 _startLazyDPSEvaluation ();
3501 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3502 emitcode ("addc", "a,#00");
3503 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3505 _endLazyDPSEvaluation ();
3510 /* if I can do an increment instead
3511 of add then GOOD for ME */
3512 if (genPlusIncr (ic) == TRUE)
3514 emitcode (";", "did genPlusIncr");
3519 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3521 _startLazyDPSEvaluation ();
3524 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3526 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3528 emitcode ("add", "a,%s",
3529 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3531 emitcode ("addc", "a,%s",
3532 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3536 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3538 /* right is going to use ACC or we would have taken the
3541 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3543 D(emitcode(";", "+ AOP_ACC special case."););
3544 emitcode("xch", "a, %s", DP2_RESULT_REG);
3546 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3549 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3552 emitcode("add", "a, %s", DP2_RESULT_REG);
3556 emitcode ("add", "a,%s",
3557 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3562 emitcode ("addc", "a,%s",
3563 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3568 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3572 emitcode ("push", "acc");
3576 _endLazyDPSEvaluation ();
3580 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3582 size = getDataSize (IC_LEFT (ic));
3583 rSize = getDataSize (IC_RESULT (ic));
3585 ADJUST_PUSHED_RESULT(size, rSize);
3587 _startLazyDPSEvaluation ();
3590 emitcode ("pop", "acc");
3591 aopPut (AOP (IC_RESULT (ic)), "a", size);
3593 _endLazyDPSEvaluation ();
3596 adjustArithmeticResult (ic);
3599 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3600 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3601 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3604 /*-----------------------------------------------------------------*/
3605 /* genMinusDec :- does subtraction with deccrement if possible */
3606 /*-----------------------------------------------------------------*/
3608 genMinusDec (iCode * ic)
3610 unsigned int icount;
3611 unsigned int size = getDataSize (IC_RESULT (ic));
3613 /* will try to generate an increment */
3614 /* if the right side is not a literal
3616 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3619 /* if the literal value of the right hand side
3620 is greater than 4 then it is not worth it */
3621 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3624 /* if decrement 16 bits in register */
3625 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3626 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3627 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3635 /* If the next instruction is a goto and the goto target
3636 * is <= 5 instructions previous to this, we can generate
3637 * jumps straight to that target.
3639 if (ic->next && ic->next->op == GOTO
3640 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3643 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3644 tlbl = IC_LABEL (ic->next);
3649 tlbl = newiTempLabel (NULL);
3653 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3654 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3655 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3656 IS_AOP_PREG (IC_RESULT (ic)))
3657 emitcode ("cjne", "%s,#0xff,%05d$"
3658 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3662 emitcode ("mov", "a,#0xff");
3663 emitcode ("cjne", "a,%s,%05d$"
3664 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3667 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3670 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3671 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3672 IS_AOP_PREG (IC_RESULT (ic)))
3673 emitcode ("cjne", "%s,#0xff,%05d$"
3674 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3678 emitcode ("cjne", "a,%s,%05d$"
3679 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3682 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3686 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3687 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3688 IS_AOP_PREG (IC_RESULT (ic)))
3689 emitcode ("cjne", "%s,#0xff,%05d$"
3690 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3694 emitcode ("cjne", "a,%s,%05d$"
3695 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3698 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3702 emitcode ("", "%05d$:", tlbl->key + 100);
3707 /* if the sizes are greater than 1 then we cannot */
3708 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3709 AOP_SIZE (IC_LEFT (ic)) > 1)
3712 /* we can if the aops of the left & result match or
3713 if they are in registers and the registers are the
3716 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3717 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3718 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3721 _startLazyDPSEvaluation ();
3724 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3726 _endLazyDPSEvaluation ();
3734 /*-----------------------------------------------------------------*/
3735 /* addSign - complete with sign */
3736 /*-----------------------------------------------------------------*/
3738 addSign (operand * result, int offset, int sign)
3740 int size = (getDataSize (result) - offset);
3743 _startLazyDPSEvaluation();
3746 emitcode ("rlc", "a");
3747 emitcode ("subb", "a,acc");
3750 aopPut (AOP (result), "a", offset++);
3757 aopPut (AOP (result), zero, offset++);
3760 _endLazyDPSEvaluation();
3764 /*-----------------------------------------------------------------*/
3765 /* genMinusBits - generates code for subtraction of two bits */
3766 /*-----------------------------------------------------------------*/
3768 genMinusBits (iCode * ic)
3770 symbol *lbl = newiTempLabel (NULL);
3772 D (emitcode (";", "genMinusBits "););
3774 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3776 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3777 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3778 emitcode ("cpl", "c");
3779 emitcode ("", "%05d$:", (lbl->key + 100));
3780 outBitC (IC_RESULT (ic));
3784 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3785 emitcode ("subb", "a,acc");
3786 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3787 emitcode ("inc", "a");
3788 emitcode ("", "%05d$:", (lbl->key + 100));
3789 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3790 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3794 /*-----------------------------------------------------------------*/
3795 /* genMinus - generates code for subtraction */
3796 /*-----------------------------------------------------------------*/
3798 genMinus (iCode * ic)
3800 int size, offset = 0;
3802 unsigned long lit = 0L;
3803 bool pushResult = FALSE;
3805 D (emitcode (";", "genMinus "););
3807 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3808 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3809 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3810 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3816 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3818 /* special cases :- */
3819 /* if both left & right are in bit space */
3820 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3821 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3827 /* if I can do an decrement instead
3828 of subtract then GOOD for ME */
3829 if (genMinusDec (ic) == TRUE)
3834 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3836 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3842 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3847 /* if literal, add a,#-lit, else normal subb */
3848 _startLazyDPSEvaluation ();
3851 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3852 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3853 emitcode ("subb", "a,%s",
3854 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3857 /* first add without previous c */
3859 if (!size && lit==-1) {
3860 emitcode ("dec", "a");
3862 emitcode ("add", "a,#0x%02x",
3863 (unsigned int) (lit & 0x0FFL));
3866 emitcode ("addc", "a,#0x%02x",
3867 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3873 emitcode ("push", "acc");
3877 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3881 _endLazyDPSEvaluation ();
3885 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3887 size = getDataSize (IC_LEFT (ic));
3888 rSize = getDataSize (IC_RESULT (ic));
3890 ADJUST_PUSHED_RESULT(size, rSize);
3892 _startLazyDPSEvaluation ();
3895 emitcode ("pop", "acc");
3896 aopPut (AOP (IC_RESULT (ic)), "a", size);
3898 _endLazyDPSEvaluation ();
3901 adjustArithmeticResult (ic);
3904 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3905 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3906 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3910 /*-----------------------------------------------------------------*/
3911 /* genMultbits :- multiplication of bits */
3912 /*-----------------------------------------------------------------*/
3914 genMultbits (operand * left,
3918 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3919 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3924 /*-----------------------------------------------------------------*/
3925 /* genMultOneByte : 8*8=8/16 bit multiplication */
3926 /*-----------------------------------------------------------------*/
3928 genMultOneByte (operand * left,
3932 sym_link *opetype = operandType (result);
3934 int size=AOP_SIZE(result);
3936 if (size<1 || size>2) {
3937 // this should never happen
3938 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3939 AOP_SIZE(result), __FILE__, lineno);
3943 /* (if two literals: the value is computed before) */
3944 /* if one literal, literal on the right */
3945 if (AOP_TYPE (left) == AOP_LIT)
3950 emitcode (";", "swapped left and right");
3953 if (SPEC_USIGN(opetype)
3954 // ignore the sign of left and right, what else can we do?
3955 || (SPEC_USIGN(operandType(left)) &&
3956 SPEC_USIGN(operandType(right)))) {
3957 // just an unsigned 8*8=8/16 multiply
3958 //emitcode (";","unsigned");
3959 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3960 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3961 emitcode ("mul", "ab");
3962 aopPut (AOP (result), "a", 0);
3964 aopPut (AOP (result), "b", 1);
3969 // we have to do a signed multiply
3971 emitcode (";", "signed");
3972 emitcode ("clr", "F0"); // reset sign flag
3973 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3975 lbl=newiTempLabel(NULL);
3976 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3977 // left side is negative, 8-bit two's complement, this fails for -128
3978 emitcode ("setb", "F0"); // set sign flag
3979 emitcode ("cpl", "a");
3980 emitcode ("inc", "a");
3982 emitcode ("", "%05d$:", lbl->key+100);
3985 if (AOP_TYPE(right)==AOP_LIT) {
3986 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3987 /* AND literal negative */
3988 if ((int) val < 0) {
3989 emitcode ("cpl", "F0"); // complement sign flag
3990 emitcode ("mov", "b,#0x%02x", -val);
3992 emitcode ("mov", "b,#0x%02x", val);
3995 lbl=newiTempLabel(NULL);
3996 emitcode ("mov", "b,a");
3997 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3998 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3999 // right side is negative, 8-bit two's complement
4000 emitcode ("cpl", "F0"); // complement sign flag
4001 emitcode ("cpl", "a");
4002 emitcode ("inc", "a");
4003 emitcode ("", "%05d$:", lbl->key+100);
4005 emitcode ("mul", "ab");
4007 lbl=newiTempLabel(NULL);
4008 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4009 // only ONE op was negative, we have to do a 8/16-bit two's complement
4010 emitcode ("cpl", "a"); // lsb
4012 emitcode ("inc", "a");
4014 emitcode ("add", "a,#1");
4015 emitcode ("xch", "a,b");
4016 emitcode ("cpl", "a"); // msb
4017 emitcode ("addc", "a,#0");
4018 emitcode ("xch", "a,b");
4021 emitcode ("", "%05d$:", lbl->key+100);
4022 aopPut (AOP (result), "a", 0);
4024 aopPut (AOP (result), "b", 1);
4028 /*-----------------------------------------------------------------*/
4029 /* genMult - generates code for multiplication */
4030 /*-----------------------------------------------------------------*/
4032 genMult (iCode * ic)
4034 operand *left = IC_LEFT (ic);
4035 operand *right = IC_RIGHT (ic);
4036 operand *result = IC_RESULT (ic);
4038 D (emitcode (";", "genMult "););
4040 /* assign the amsops */
4043 /* special cases first */
4045 if (AOP_TYPE (left) == AOP_CRY &&
4046 AOP_TYPE (right) == AOP_CRY)
4048 genMultbits (left, right, result);
4052 /* if both are of size == 1 */
4053 if (AOP_SIZE (left) == 1 &&
4054 AOP_SIZE (right) == 1)
4056 genMultOneByte (left, right, result);
4060 /* should have been converted to function call */
4064 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4065 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4066 freeAsmop (result, NULL, ic, TRUE);
4069 /*-----------------------------------------------------------------*/
4070 /* genDivbits :- division of bits */
4071 /*-----------------------------------------------------------------*/
4073 genDivbits (operand * left,
4080 /* the result must be bit */
4081 LOAD_AB_FOR_DIV (left, right, l);
4082 emitcode ("div", "ab");
4083 emitcode ("rrc", "a");
4084 aopPut (AOP (result), "c", 0);
4087 /*-----------------------------------------------------------------*/
4088 /* genDivOneByte : 8 bit division */
4089 /*-----------------------------------------------------------------*/
4091 genDivOneByte (operand * left,
4095 sym_link *opetype = operandType (result);
4100 size = AOP_SIZE (result) - 1;
4102 /* signed or unsigned */
4103 if (SPEC_USIGN (opetype))
4105 /* unsigned is easy */
4106 LOAD_AB_FOR_DIV (left, right, l);
4107 emitcode ("div", "ab");
4108 aopPut (AOP (result), "a", 0);
4110 aopPut (AOP (result), zero, offset++);
4114 /* signed is a little bit more difficult */
4116 /* save the signs of the operands */
4117 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4119 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4120 emitcode ("push", "acc"); /* save it on the stack */
4122 /* now sign adjust for both left & right */
4123 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4125 lbl = newiTempLabel (NULL);
4126 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4127 emitcode ("cpl", "a");
4128 emitcode ("inc", "a");
4129 emitcode ("", "%05d$:", (lbl->key + 100));
4130 emitcode ("mov", "b,a");
4132 /* sign adjust left side */
4133 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4136 lbl = newiTempLabel (NULL);
4137 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4138 emitcode ("cpl", "a");
4139 emitcode ("inc", "a");
4140 emitcode ("", "%05d$:", (lbl->key + 100));
4142 /* now the division */
4143 emitcode ("nop", "; workaround for DS80C390 div bug.");
4144 emitcode ("div", "ab");
4145 /* we are interested in the lower order
4147 emitcode ("mov", "b,a");
4148 lbl = newiTempLabel (NULL);
4149 emitcode ("pop", "acc");
4150 /* if there was an over flow we don't
4151 adjust the sign of the result */
4152 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4153 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4155 emitcode ("clr", "a");
4156 emitcode ("subb", "a,b");
4157 emitcode ("mov", "b,a");
4158 emitcode ("", "%05d$:", (lbl->key + 100));
4160 /* now we are done */
4161 aopPut (AOP (result), "b", 0);
4164 emitcode ("mov", "c,b.7");
4165 emitcode ("subb", "a,acc");
4168 aopPut (AOP (result), "a", offset++);
4172 /*-----------------------------------------------------------------*/
4173 /* genDiv - generates code for division */
4174 /*-----------------------------------------------------------------*/
4178 operand *left = IC_LEFT (ic);
4179 operand *right = IC_RIGHT (ic);
4180 operand *result = IC_RESULT (ic);
4182 D (emitcode (";", "genDiv ");
4185 /* assign the amsops */
4188 /* special cases first */
4190 if (AOP_TYPE (left) == AOP_CRY &&
4191 AOP_TYPE (right) == AOP_CRY)
4193 genDivbits (left, right, result);
4197 /* if both are of size == 1 */
4198 if (AOP_SIZE (left) == 1 &&
4199 AOP_SIZE (right) == 1)
4201 genDivOneByte (left, right, result);
4205 /* should have been converted to function call */
4208 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4209 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4210 freeAsmop (result, NULL, ic, TRUE);
4213 /*-----------------------------------------------------------------*/
4214 /* genModbits :- modulus of bits */
4215 /*-----------------------------------------------------------------*/
4217 genModbits (operand * left,
4224 /* the result must be bit */
4225 LOAD_AB_FOR_DIV (left, right, l);
4226 emitcode ("div", "ab");
4227 emitcode ("mov", "a,b");
4228 emitcode ("rrc", "a");
4229 aopPut (AOP (result), "c", 0);
4232 /*-----------------------------------------------------------------*/
4233 /* genModOneByte : 8 bit modulus */
4234 /*-----------------------------------------------------------------*/
4236 genModOneByte (operand * left,
4240 sym_link *opetype = operandType (result);
4244 /* signed or unsigned */
4245 if (SPEC_USIGN (opetype))
4247 /* unsigned is easy */
4248 LOAD_AB_FOR_DIV (left, right, l);
4249 emitcode ("div", "ab");
4250 aopPut (AOP (result), "b", 0);
4254 /* signed is a little bit more difficult */
4256 /* save the signs of the operands */
4257 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4260 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4261 emitcode ("push", "acc"); /* save it on the stack */
4263 /* now sign adjust for both left & right */
4264 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4267 lbl = newiTempLabel (NULL);
4268 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4269 emitcode ("cpl", "a");
4270 emitcode ("inc", "a");
4271 emitcode ("", "%05d$:", (lbl->key + 100));
4272 emitcode ("mov", "b,a");
4274 /* sign adjust left side */
4275 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4278 lbl = newiTempLabel (NULL);
4279 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4280 emitcode ("cpl", "a");
4281 emitcode ("inc", "a");
4282 emitcode ("", "%05d$:", (lbl->key + 100));
4284 /* now the multiplication */
4285 emitcode ("nop", "; workaround for DS80C390 div bug.");
4286 emitcode ("div", "ab");
4287 /* we are interested in the lower order
4289 lbl = newiTempLabel (NULL);
4290 emitcode ("pop", "acc");
4291 /* if there was an over flow we don't
4292 adjust the sign of the result */
4293 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4294 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4296 emitcode ("clr", "a");
4297 emitcode ("subb", "a,b");
4298 emitcode ("mov", "b,a");
4299 emitcode ("", "%05d$:", (lbl->key + 100));
4301 /* now we are done */
4302 aopPut (AOP (result), "b", 0);
4306 /*-----------------------------------------------------------------*/
4307 /* genMod - generates code for division */
4308 /*-----------------------------------------------------------------*/
4312 operand *left = IC_LEFT (ic);
4313 operand *right = IC_RIGHT (ic);
4314 operand *result = IC_RESULT (ic);
4316 D (emitcode (";", "genMod ");
4319 /* assign the amsops */
4322 /* special cases first */
4324 if (AOP_TYPE (left) == AOP_CRY &&
4325 AOP_TYPE (right) == AOP_CRY)
4327 genModbits (left, right, result);
4331 /* if both are of size == 1 */
4332 if (AOP_SIZE (left) == 1 &&
4333 AOP_SIZE (right) == 1)
4335 genModOneByte (left, right, result);
4339 /* should have been converted to function call */
4343 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4344 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4345 freeAsmop (result, NULL, ic, TRUE);
4348 /*-----------------------------------------------------------------*/
4349 /* genIfxJump :- will create a jump depending on the ifx */
4350 /*-----------------------------------------------------------------*/
4352 genIfxJump (iCode * ic, char *jval)
4355 symbol *tlbl = newiTempLabel (NULL);
4358 D (emitcode (";", "genIfxJump ");
4361 /* if true label then we jump if condition
4365 jlbl = IC_TRUE (ic);
4366 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4367 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4371 /* false label is present */
4372 jlbl = IC_FALSE (ic);
4373 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4374 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4376 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4377 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4379 emitcode (inst, "%05d$", tlbl->key + 100);
4380 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4381 emitcode ("", "%05d$:", tlbl->key + 100);
4383 /* mark the icode as generated */
4387 /*-----------------------------------------------------------------*/
4388 /* genCmp :- greater or less than comparison */
4389 /*-----------------------------------------------------------------*/
4391 genCmp (operand * left, operand * right,
4392 iCode * ic, iCode * ifx, int sign)
4394 int size, offset = 0;
4395 unsigned long lit = 0L;
4398 D (emitcode (";", "genCmp");
4401 result = IC_RESULT (ic);
4403 /* if left & right are bit variables */
4404 if (AOP_TYPE (left) == AOP_CRY &&
4405 AOP_TYPE (right) == AOP_CRY)
4407 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4408 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4412 /* subtract right from left if at the
4413 end the carry flag is set then we know that
4414 left is greater than right */
4415 size = max (AOP_SIZE (left), AOP_SIZE (right));
4417 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4418 if ((size == 1) && !sign &&
4419 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4421 symbol *lbl = newiTempLabel (NULL);
4422 emitcode ("cjne", "%s,%s,%05d$",
4423 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4424 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4426 emitcode ("", "%05d$:", lbl->key + 100);
4430 if (AOP_TYPE (right) == AOP_LIT)
4432 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4433 /* optimize if(x < 0) or if(x >= 0) */
4442 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4444 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4445 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4447 aopOp (result, ic, FALSE, FALSE);
4449 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4451 freeAsmop (result, NULL, ic, TRUE);
4452 genIfxJump (ifx, "acc.7");
4457 emitcode ("rlc", "a");
4459 goto release_freedLR;
4467 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4468 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4469 emitcode (";", "genCmp #2");
4470 if (sign && (size == 0))
4472 emitcode (";", "genCmp #3");
4473 emitcode ("xrl", "a,#0x80");
4474 if (AOP_TYPE (right) == AOP_LIT)
4476 unsigned long lit = (unsigned long)
4477 floatFromVal (AOP (right)->aopu.aop_lit);
4478 emitcode (";", "genCmp #3.1");
4479 emitcode ("subb", "a,#0x%02x",
4480 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4484 emitcode (";", "genCmp #3.2");
4485 if (AOP_NEEDSACC (right))
4487 emitcode ("push", "acc");
4489 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4490 FALSE, FALSE, FALSE));
4491 emitcode ("xrl", "b,#0x80");
4492 if (AOP_NEEDSACC (right))
4494 emitcode ("pop", "acc");
4496 emitcode ("subb", "a,b");
4503 emitcode (";", "genCmp #4");
4504 if (AOP_NEEDSACC (right))
4507 emitcode (";", "genCmp #4.1");
4508 emitcode ("xch", "a, b");
4509 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4510 emitcode ("xch", "a, b");
4515 emitcode (";", "genCmp #4.2");
4516 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4519 emitcode ("subb", "a,%s", s);
4526 /* Don't need the left & right operands any more; do need the result. */
4527 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4528 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4530 aopOp (result, ic, FALSE, FALSE);
4534 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4540 /* if the result is used in the next
4541 ifx conditional branch then generate
4542 code a little differently */
4545 genIfxJump (ifx, "c");
4551 /* leave the result in acc */
4553 freeAsmop (result, NULL, ic, TRUE);
4556 /*-----------------------------------------------------------------*/
4557 /* genCmpGt :- greater than comparison */
4558 /*-----------------------------------------------------------------*/
4560 genCmpGt (iCode * ic, iCode * ifx)
4562 operand *left, *right;
4563 sym_link *letype, *retype;
4566 D (emitcode (";", "genCmpGt ");
4569 left = IC_LEFT (ic);
4570 right = IC_RIGHT (ic);
4572 letype = getSpec (operandType (left));
4573 retype = getSpec (operandType (right));
4574 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4576 /* assign the left & right amsops */
4579 genCmp (right, left, ic, ifx, sign);
4582 /*-----------------------------------------------------------------*/
4583 /* genCmpLt - less than comparisons */
4584 /*-----------------------------------------------------------------*/
4586 genCmpLt (iCode * ic, iCode * ifx)
4588 operand *left, *right;
4589 sym_link *letype, *retype;
4592 D (emitcode (";", "genCmpLt "););
4594 left = IC_LEFT (ic);
4595 right = IC_RIGHT (ic);
4597 letype = getSpec (operandType (left));
4598 retype = getSpec (operandType (right));
4599 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4601 /* assign the left & right amsops */
4604 genCmp (left, right, ic, ifx, sign);
4607 /*-----------------------------------------------------------------*/
4608 /* gencjneshort - compare and jump if not equal */
4609 /*-----------------------------------------------------------------*/
4611 gencjneshort (operand * left, operand * right, symbol * lbl)
4613 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4615 unsigned long lit = 0L;
4617 D (emitcode (";", "gencjneshort");
4620 /* if the left side is a literal or
4621 if the right is in a pointer register and left
4623 if ((AOP_TYPE (left) == AOP_LIT) ||
4624 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4631 if (AOP_TYPE (right) == AOP_LIT)
4632 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4634 if (opIsGptr (left) || opIsGptr (right))
4636 /* We are comparing a generic pointer to something.
4637 * Exclude the generic type byte from the comparison.
4640 D (emitcode (";", "cjneshort: generic ptr special case.");
4645 /* if the right side is a literal then anything goes */
4646 if (AOP_TYPE (right) == AOP_LIT &&
4647 AOP_TYPE (left) != AOP_DIR)
4651 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4653 emitcode ("cjne", "a,%s,%05d$",
4654 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4660 /* if the right side is in a register or in direct space or
4661 if the left is a pointer register & right is not */
4662 else if (AOP_TYPE (right) == AOP_REG ||
4663 AOP_TYPE (right) == AOP_DIR ||
4664 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4665 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4669 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4670 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4671 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4672 emitcode ("jnz", "%05d$", lbl->key + 100);
4674 emitcode ("cjne", "a,%s,%05d$",
4675 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4682 /* right is a pointer reg need both a & b */
4685 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4686 if (strcmp (l, "b"))
4687 emitcode ("mov", "b,%s", l);
4688 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4689 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4695 /*-----------------------------------------------------------------*/
4696 /* gencjne - compare and jump if not equal */
4697 /*-----------------------------------------------------------------*/
4699 gencjne (operand * left, operand * right, symbol * lbl)
4701 symbol *tlbl = newiTempLabel (NULL);
4703 D (emitcode (";", "gencjne");
4706 gencjneshort (left, right, lbl);
4708 emitcode ("mov", "a,%s", one);
4709 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4710 emitcode ("", "%05d$:", lbl->key + 100);
4711 emitcode ("clr", "a");
4712 emitcode ("", "%05d$:", tlbl->key + 100);
4715 /*-----------------------------------------------------------------*/
4716 /* genCmpEq - generates code for equal to */
4717 /*-----------------------------------------------------------------*/
4719 genCmpEq (iCode * ic, iCode * ifx)
4721 operand *left, *right, *result;
4723 D (emitcode (";", "genCmpEq ");
4727 AOP_SET_LOCALS (ic);
4729 /* if literal, literal on the right or
4730 if the right is in a pointer register and left
4732 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4733 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4735 operand *t = IC_RIGHT (ic);
4736 IC_RIGHT (ic) = IC_LEFT (ic);
4740 if (ifx && /* !AOP_SIZE(result) */
4741 OP_SYMBOL (result) &&
4742 OP_SYMBOL (result)->regType == REG_CND)
4745 /* if they are both bit variables */
4746 if (AOP_TYPE (left) == AOP_CRY &&
4747 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4749 if (AOP_TYPE (right) == AOP_LIT)
4751 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4754 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4755 emitcode ("cpl", "c");
4759 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4763 emitcode ("clr", "c");
4765 /* AOP_TYPE(right) == AOP_CRY */
4769 symbol *lbl = newiTempLabel (NULL);
4770 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4771 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4772 emitcode ("cpl", "c");
4773 emitcode ("", "%05d$:", (lbl->key + 100));
4775 /* if true label then we jump if condition
4777 tlbl = newiTempLabel (NULL);
4780 emitcode ("jnc", "%05d$", tlbl->key + 100);
4781 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4785 emitcode ("jc", "%05d$", tlbl->key + 100);
4786 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4788 emitcode ("", "%05d$:", tlbl->key + 100);
4792 tlbl = newiTempLabel (NULL);
4793 gencjneshort (left, right, tlbl);
4796 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4797 emitcode ("", "%05d$:", tlbl->key + 100);
4801 symbol *lbl = newiTempLabel (NULL);
4802 emitcode ("sjmp", "%05d$", lbl->key + 100);
4803 emitcode ("", "%05d$:", tlbl->key + 100);
4804 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4805 emitcode ("", "%05d$:", lbl->key + 100);
4808 /* mark the icode as generated */
4811 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4812 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4816 /* if they are both bit variables */
4817 if (AOP_TYPE (left) == AOP_CRY &&
4818 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4820 if (AOP_TYPE (right) == AOP_LIT)
4822 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4825 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4826 emitcode ("cpl", "c");
4830 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4834 emitcode ("clr", "c");
4836 /* AOP_TYPE(right) == AOP_CRY */
4840 symbol *lbl = newiTempLabel (NULL);
4841 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4842 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4843 emitcode ("cpl", "c");
4844 emitcode ("", "%05d$:", (lbl->key + 100));
4847 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4850 aopOp (result, ic, TRUE, FALSE);
4853 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4860 genIfxJump (ifx, "c");
4863 /* if the result is used in an arithmetic operation
4864 then put the result in place */
4869 gencjne (left, right, newiTempLabel (NULL));
4871 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4872 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4874 aopOp (result, ic, TRUE, FALSE);
4876 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4878 aopPut (AOP (result), "a", 0);
4883 genIfxJump (ifx, "a");
4886 /* if the result is used in an arithmetic operation
4887 then put the result in place */
4888 if (AOP_TYPE (result) != AOP_CRY)
4890 /* leave the result in acc */
4894 freeAsmop (result, NULL, ic, TRUE);
4897 /*-----------------------------------------------------------------*/
4898 /* ifxForOp - returns the icode containing the ifx for operand */
4899 /*-----------------------------------------------------------------*/
4901 ifxForOp (operand * op, iCode * ic)
4903 /* if true symbol then needs to be assigned */
4904 if (IS_TRUE_SYMOP (op))
4907 /* if this has register type condition and
4908 the next instruction is ifx with the same operand
4909 and live to of the operand is upto the ifx only then */
4911 ic->next->op == IFX &&
4912 IC_COND (ic->next)->key == op->key &&
4913 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4918 /*-----------------------------------------------------------------*/
4919 /* genAndOp - for && operation */
4920 /*-----------------------------------------------------------------*/
4922 genAndOp (iCode * ic)
4924 operand *left, *right, *result;
4927 D (emitcode (";", "genAndOp "););
4929 /* note here that && operations that are in an
4930 if statement are taken away by backPatchLabels
4931 only those used in arthmetic operations remain */
4933 AOP_SET_LOCALS (ic);
4935 /* if both are bit variables */
4936 if (AOP_TYPE (left) == AOP_CRY &&
4937 AOP_TYPE (right) == AOP_CRY)
4939 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4940 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4941 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4942 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 aopOp (result,ic,FALSE, FALSE);
4949 tlbl = newiTempLabel (NULL);
4951 emitcode ("jz", "%05d$", tlbl->key + 100);
4953 emitcode ("", "%05d$:", tlbl->key + 100);
4954 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4955 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4957 aopOp (result,ic,FALSE, FALSE);
4960 freeAsmop (result, NULL, ic, TRUE);
4964 /*-----------------------------------------------------------------*/
4965 /* genOrOp - for || operation */
4966 /*-----------------------------------------------------------------*/
4968 genOrOp (iCode * ic)
4970 operand *left, *right, *result;
4973 D (emitcode (";", "genOrOp "););
4975 /* note here that || operations that are in an
4976 if statement are taken away by backPatchLabels
4977 only those used in arthmetic operations remain */
4979 AOP_SET_LOCALS (ic);
4981 /* if both are bit variables */
4982 if (AOP_TYPE (left) == AOP_CRY &&
4983 AOP_TYPE (right) == AOP_CRY)
4985 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4986 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4987 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4988 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4990 aopOp (result,ic,FALSE, FALSE);
4996 tlbl = newiTempLabel (NULL);
4998 emitcode ("jnz", "%05d$", tlbl->key + 100);
5000 emitcode ("", "%05d$:", tlbl->key + 100);
5001 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5002 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5004 aopOp (result,ic,FALSE, FALSE);
5009 freeAsmop (result, NULL, ic, TRUE);
5012 /*-----------------------------------------------------------------*/
5013 /* isLiteralBit - test if lit == 2^n */
5014 /*-----------------------------------------------------------------*/
5016 isLiteralBit (unsigned long lit)
5018 unsigned long pw[32] =
5019 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5020 0x100L, 0x200L, 0x400L, 0x800L,
5021 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5022 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5023 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5024 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5025 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5028 for (idx = 0; idx < 32; idx++)
5034 /*-----------------------------------------------------------------*/
5035 /* continueIfTrue - */
5036 /*-----------------------------------------------------------------*/
5038 continueIfTrue (iCode * ic)
5041 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5045 /*-----------------------------------------------------------------*/
5047 /*-----------------------------------------------------------------*/
5049 jumpIfTrue (iCode * ic)
5052 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5056 /*-----------------------------------------------------------------*/
5057 /* jmpTrueOrFalse - */
5058 /*-----------------------------------------------------------------*/
5060 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5062 // ugly but optimized by peephole
5065 symbol *nlbl = newiTempLabel (NULL);
5066 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5067 emitcode ("", "%05d$:", tlbl->key + 100);
5068 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5069 emitcode ("", "%05d$:", nlbl->key + 100);
5073 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5074 emitcode ("", "%05d$:", tlbl->key + 100);
5079 // Generate code to perform a bit-wise logic operation
5080 // on two operands in far space (assumed to already have been
5081 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5082 // in far space. This requires pushing the result on the stack
5083 // then popping it into the result.
5085 genFarFarLogicOp(iCode *ic, char *logicOp)
5087 int size, resultSize, compSize;
5091 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5092 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5093 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5095 _startLazyDPSEvaluation();
5096 for (size = compSize; (size--); offset++)
5098 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5099 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5100 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5102 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5103 emitcode ("push", "acc");
5105 _endLazyDPSEvaluation();
5107 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5108 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5109 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5111 resultSize = AOP_SIZE(IC_RESULT(ic));
5113 ADJUST_PUSHED_RESULT(compSize, resultSize);
5115 _startLazyDPSEvaluation();
5118 emitcode ("pop", "acc");
5119 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5121 _endLazyDPSEvaluation();
5122 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5126 /*-----------------------------------------------------------------*/
5127 /* genAnd - code for and */
5128 /*-----------------------------------------------------------------*/
5130 genAnd (iCode * ic, iCode * ifx)
5132 operand *left, *right, *result;
5133 int size, offset = 0;
5134 unsigned long lit = 0L;
5139 D (emitcode (";", "genAnd "););
5141 AOP_OP_3_NOFATAL (ic, pushResult);
5142 AOP_SET_LOCALS (ic);
5146 genFarFarLogicOp(ic, "anl");
5151 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5153 AOP_TYPE (left), AOP_TYPE (right));
5154 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5156 AOP_SIZE (left), AOP_SIZE (right));
5159 /* if left is a literal & right is not then exchange them */
5160 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5161 AOP_NEEDSACC (left))
5163 operand *tmp = right;
5168 /* if result = right then exchange them */
5169 if (sameRegs (AOP (result), AOP (right)))
5171 operand *tmp = right;
5176 /* if right is bit then exchange them */
5177 if (AOP_TYPE (right) == AOP_CRY &&
5178 AOP_TYPE (left) != AOP_CRY)
5180 operand *tmp = right;
5184 if (AOP_TYPE (right) == AOP_LIT)
5185 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5187 size = AOP_SIZE (result);
5190 // result = bit & yy;
5191 if (AOP_TYPE (left) == AOP_CRY)
5193 // c = bit & literal;
5194 if (AOP_TYPE (right) == AOP_LIT)
5198 if (size && sameRegs (AOP (result), AOP (left)))
5201 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5206 if (size && (AOP_TYPE (result) == AOP_CRY))
5208 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5211 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5216 emitcode ("clr", "c");
5221 if (AOP_TYPE (right) == AOP_CRY)
5224 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5225 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5230 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5232 emitcode ("rrc", "a");
5233 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5241 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5242 genIfxJump (ifx, "c");
5246 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5247 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5248 if ((AOP_TYPE (right) == AOP_LIT) &&
5249 (AOP_TYPE (result) == AOP_CRY) &&
5250 (AOP_TYPE (left) != AOP_CRY))
5252 int posbit = isLiteralBit (lit);
5257 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5260 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5266 sprintf (buffer, "acc.%d", posbit & 0x07);
5267 genIfxJump (ifx, buffer);
5274 symbol *tlbl = newiTempLabel (NULL);
5275 int sizel = AOP_SIZE (left);
5277 emitcode ("setb", "c");
5280 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5282 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5284 if ((posbit = isLiteralBit (bytelit)) != 0)
5285 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5288 if (bytelit != 0x0FFL)
5289 emitcode ("anl", "a,%s",
5290 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5291 emitcode ("jnz", "%05d$", tlbl->key + 100);
5296 // bit = left & literal
5299 emitcode ("clr", "c");
5300 emitcode ("", "%05d$:", tlbl->key + 100);
5302 // if(left & literal)
5306 jmpTrueOrFalse (ifx, tlbl);
5314 /* if left is same as result */
5315 if (sameRegs (AOP (result), AOP (left)))
5317 for (; size--; offset++)
5319 if (AOP_TYPE (right) == AOP_LIT)
5321 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5323 else if (bytelit == 0)
5324 aopPut (AOP (result), zero, offset);
5325 else if (IS_AOP_PREG (result))
5327 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5328 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5329 aopPut (AOP (result), "a", offset);
5332 emitcode ("anl", "%s,%s",
5333 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5334 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5338 if (AOP_TYPE (left) == AOP_ACC)
5339 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5342 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5343 if (IS_AOP_PREG (result))
5345 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5346 aopPut (AOP (result), "a", offset);
5350 emitcode ("anl", "%s,a",
5351 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5358 // left & result in different registers
5359 if (AOP_TYPE (result) == AOP_CRY)
5362 // if(size), result in bit
5363 // if(!size && ifx), conditional oper: if(left & right)
5364 symbol *tlbl = newiTempLabel (NULL);
5365 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5367 emitcode ("setb", "c");
5370 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5371 emitcode ("anl", "a,%s",
5372 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5374 if (AOP_TYPE(left)==AOP_ACC) {
5375 emitcode("mov", "b,a");
5376 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5377 emitcode("anl", "a,b");
5379 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5380 emitcode ("anl", "a,%s",
5381 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5384 emitcode ("jnz", "%05d$", tlbl->key + 100);
5390 emitcode ("", "%05d$:", tlbl->key + 100);
5394 jmpTrueOrFalse (ifx, tlbl);
5398 for (; (size--); offset++)
5401 // result = left & right
5402 if (AOP_TYPE (right) == AOP_LIT)
5404 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5406 aopPut (AOP (result),
5407 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5411 else if (bytelit == 0)
5413 aopPut (AOP (result), zero, offset);
5416 D (emitcode (";", "better literal AND.");
5418 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5419 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5420 FALSE, FALSE, FALSE));
5425 // faster than result <- left, anl result,right
5426 // and better if result is SFR
5427 if (AOP_TYPE (left) == AOP_ACC)
5429 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5430 FALSE, FALSE, FALSE));
5434 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5435 emitcode ("anl", "a,%s",
5436 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5439 aopPut (AOP (result), "a", offset);
5445 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5446 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5447 freeAsmop (result, NULL, ic, TRUE);
5451 /*-----------------------------------------------------------------*/
5452 /* genOr - code for or */
5453 /*-----------------------------------------------------------------*/
5455 genOr (iCode * ic, iCode * ifx)
5457 operand *left, *right, *result;
5458 int size, offset = 0;
5459 unsigned long lit = 0L;
5462 D (emitcode (";", "genOr "););
5464 AOP_OP_3_NOFATAL (ic, pushResult);
5465 AOP_SET_LOCALS (ic);
5469 genFarFarLogicOp(ic, "orl");
5475 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5477 AOP_TYPE (left), AOP_TYPE (right));
5478 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5480 AOP_SIZE (left), AOP_SIZE (right));
5483 /* if left is a literal & right is not then exchange them */
5484 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5485 AOP_NEEDSACC (left))
5487 operand *tmp = right;
5492 /* if result = right then exchange them */
5493 if (sameRegs (AOP (result), AOP (right)))
5495 operand *tmp = right;
5500 /* if right is bit then exchange them */
5501 if (AOP_TYPE (right) == AOP_CRY &&
5502 AOP_TYPE (left) != AOP_CRY)
5504 operand *tmp = right;
5508 if (AOP_TYPE (right) == AOP_LIT)
5509 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5511 size = AOP_SIZE (result);
5515 if (AOP_TYPE (left) == AOP_CRY)
5517 if (AOP_TYPE (right) == AOP_LIT)
5519 // c = bit & literal;
5522 // lit != 0 => result = 1
5523 if (AOP_TYPE (result) == AOP_CRY)
5526 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5528 continueIfTrue (ifx);
5531 emitcode ("setb", "c");
5535 // lit == 0 => result = left
5536 if (size && sameRegs (AOP (result), AOP (left)))
5538 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5543 if (AOP_TYPE (right) == AOP_CRY)
5546 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5547 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5552 symbol *tlbl = newiTempLabel (NULL);
5553 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5554 emitcode ("setb", "c");
5555 emitcode ("jb", "%s,%05d$",
5556 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5558 emitcode ("jnz", "%05d$", tlbl->key + 100);
5559 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5561 jmpTrueOrFalse (ifx, tlbl);
5567 emitcode ("", "%05d$:", tlbl->key + 100);
5576 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5577 genIfxJump (ifx, "c");
5581 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5582 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5583 if ((AOP_TYPE (right) == AOP_LIT) &&
5584 (AOP_TYPE (result) == AOP_CRY) &&
5585 (AOP_TYPE (left) != AOP_CRY))
5591 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5593 continueIfTrue (ifx);
5598 // lit = 0, result = boolean(left)
5600 emitcode ("setb", "c");
5604 symbol *tlbl = newiTempLabel (NULL);
5605 emitcode ("jnz", "%05d$", tlbl->key + 100);
5607 emitcode ("", "%05d$:", tlbl->key + 100);
5611 genIfxJump (ifx, "a");
5619 /* if left is same as result */
5620 if (sameRegs (AOP (result), AOP (left)))
5622 for (; size--; offset++)
5624 if (AOP_TYPE (right) == AOP_LIT)
5626 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5632 if (IS_AOP_PREG (left))
5634 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5635 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5636 aopPut (AOP (result), "a", offset);
5640 emitcode ("orl", "%s,%s",
5641 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5642 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5648 if (AOP_TYPE (left) == AOP_ACC)
5650 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5654 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5655 if (IS_AOP_PREG (left))
5657 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5658 aopPut (AOP (result), "a", offset);
5662 emitcode ("orl", "%s,a",
5663 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5671 // left & result in different registers
5672 if (AOP_TYPE (result) == AOP_CRY)
5675 // if(size), result in bit
5676 // if(!size && ifx), conditional oper: if(left | right)
5677 symbol *tlbl = newiTempLabel (NULL);
5678 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5680 emitcode ("setb", "c");
5683 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5684 emitcode ("orl", "a,%s",
5685 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5687 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5688 emitcode ("orl", "a,%s",
5689 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5691 emitcode ("jnz", "%05d$", tlbl->key + 100);
5697 emitcode ("", "%05d$:", tlbl->key + 100);
5701 jmpTrueOrFalse (ifx, tlbl);
5705 for (; (size--); offset++)
5708 // result = left & right
5709 if (AOP_TYPE (right) == AOP_LIT)
5711 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5713 aopPut (AOP (result),
5714 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5718 D (emitcode (";", "better literal OR.");
5720 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5721 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5722 FALSE, FALSE, FALSE));
5727 // faster than result <- left, anl result,right
5728 // and better if result is SFR
5729 if (AOP_TYPE (left) == AOP_ACC)
5731 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5732 FALSE, FALSE, FALSE));
5736 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5737 emitcode ("orl", "a,%s",
5738 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5741 aopPut (AOP (result), "a", offset);
5747 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5748 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5749 freeAsmop (result, NULL, ic, TRUE);
5752 /*-----------------------------------------------------------------*/
5753 /* genXor - code for xclusive or */
5754 /*-----------------------------------------------------------------*/
5756 genXor (iCode * ic, iCode * ifx)
5758 operand *left, *right, *result;
5759 int size, offset = 0;
5760 unsigned long lit = 0L;
5763 D (emitcode (";", "genXor "););
5765 AOP_OP_3_NOFATAL (ic, pushResult);
5766 AOP_SET_LOCALS (ic);
5770 genFarFarLogicOp(ic, "xrl");
5775 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5777 AOP_TYPE (left), AOP_TYPE (right));
5778 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5780 AOP_SIZE (left), AOP_SIZE (right));
5783 /* if left is a literal & right is not ||
5784 if left needs acc & right does not */
5785 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5786 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5788 operand *tmp = right;
5793 /* if result = right then exchange them */
5794 if (sameRegs (AOP (result), AOP (right)))
5796 operand *tmp = right;
5801 /* if right is bit then exchange them */
5802 if (AOP_TYPE (right) == AOP_CRY &&
5803 AOP_TYPE (left) != AOP_CRY)
5805 operand *tmp = right;
5809 if (AOP_TYPE (right) == AOP_LIT)
5810 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5812 size = AOP_SIZE (result);
5816 if (AOP_TYPE (left) == AOP_CRY)
5818 if (AOP_TYPE (right) == AOP_LIT)
5820 // c = bit & literal;
5823 // lit>>1 != 0 => result = 1
5824 if (AOP_TYPE (result) == AOP_CRY)
5827 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5829 continueIfTrue (ifx);
5832 emitcode ("setb", "c");
5839 // lit == 0, result = left
5840 if (size && sameRegs (AOP (result), AOP (left)))
5842 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5846 // lit == 1, result = not(left)
5847 if (size && sameRegs (AOP (result), AOP (left)))
5849 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5854 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5855 emitcode ("cpl", "c");
5864 symbol *tlbl = newiTempLabel (NULL);
5865 if (AOP_TYPE (right) == AOP_CRY)
5868 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5872 int sizer = AOP_SIZE (right);
5874 // if val>>1 != 0, result = 1
5875 emitcode ("setb", "c");
5878 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5880 // test the msb of the lsb
5881 emitcode ("anl", "a,#0xfe");
5882 emitcode ("jnz", "%05d$", tlbl->key + 100);
5886 emitcode ("rrc", "a");
5888 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5889 emitcode ("cpl", "c");
5890 emitcode ("", "%05d$:", (tlbl->key + 100));
5897 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5898 genIfxJump (ifx, "c");
5902 if (sameRegs (AOP (result), AOP (left)))
5904 /* if left is same as result */
5905 for (; size--; offset++)
5907 if (AOP_TYPE (right) == AOP_LIT)
5909 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5911 else if (IS_AOP_PREG (left))
5913 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5914 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5915 aopPut (AOP (result), "a", offset);
5918 emitcode ("xrl", "%s,%s",
5919 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5920 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5924 if (AOP_TYPE (left) == AOP_ACC)
5925 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5928 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5929 if (IS_AOP_PREG (left))
5931 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5932 aopPut (AOP (result), "a", offset);
5935 emitcode ("xrl", "%s,a",
5936 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5943 // left & result in different registers
5944 if (AOP_TYPE (result) == AOP_CRY)
5947 // if(size), result in bit
5948 // if(!size && ifx), conditional oper: if(left ^ right)
5949 symbol *tlbl = newiTempLabel (NULL);
5950 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5952 emitcode ("setb", "c");
5955 if ((AOP_TYPE (right) == AOP_LIT) &&
5956 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5958 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5962 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5963 emitcode ("xrl", "a,%s",
5964 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5966 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5967 emitcode ("xrl", "a,%s",
5968 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5971 emitcode ("jnz", "%05d$", tlbl->key + 100);
5977 emitcode ("", "%05d$:", tlbl->key + 100);
5981 jmpTrueOrFalse (ifx, tlbl);
5984 for (; (size--); offset++)
5987 // result = left & right
5988 if (AOP_TYPE (right) == AOP_LIT)
5990 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5992 aopPut (AOP (result),
5993 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5997 D (emitcode (";", "better literal XOR.");
5999 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6000 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6001 FALSE, FALSE, FALSE));
6005 // faster than result <- left, anl result,right
6006 // and better if result is SFR
6007 if (AOP_TYPE (left) == AOP_ACC)
6009 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6010 FALSE, FALSE, FALSE));
6014 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6015 emitcode ("xrl", "a,%s",
6016 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6019 aopPut (AOP (result), "a", offset);
6024 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6025 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6026 freeAsmop (result, NULL, ic, TRUE);
6029 /*-----------------------------------------------------------------*/
6030 /* genInline - write the inline code out */
6031 /*-----------------------------------------------------------------*/
6033 genInline (iCode * ic)
6035 char *buffer, *bp, *bp1;
6037 D (emitcode (";", "genInline ");
6040 _G.inLine += (!options.asmpeep);
6042 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6043 strcpy (buffer, IC_INLINE (ic));
6045 /* emit each line as a code */
6070 /* emitcode("",buffer); */
6071 _G.inLine -= (!options.asmpeep);
6074 /*-----------------------------------------------------------------*/
6075 /* genRRC - rotate right with carry */
6076 /*-----------------------------------------------------------------*/
6080 operand *left, *result;
6081 int size, offset = 0;
6084 D (emitcode (";", "genRRC ");
6087 /* rotate right with carry */
6088 left = IC_LEFT (ic);
6089 result = IC_RESULT (ic);
6090 aopOp (left, ic, FALSE, FALSE);
6091 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6093 /* move it to the result */
6094 size = AOP_SIZE (result);
6098 _startLazyDPSEvaluation ();
6101 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6103 emitcode ("rrc", "a");
6104 if (AOP_SIZE (result) > 1)
6105 aopPut (AOP (result), "a", offset--);
6107 _endLazyDPSEvaluation ();
6109 /* now we need to put the carry into the
6110 highest order byte of the result */
6111 if (AOP_SIZE (result) > 1)
6113 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6116 emitcode ("mov", "acc.7,c");
6117 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6118 freeAsmop (left, NULL, ic, TRUE);
6119 freeAsmop (result, NULL, ic, TRUE);
6122 /*-----------------------------------------------------------------*/
6123 /* genRLC - generate code for rotate left with carry */
6124 /*-----------------------------------------------------------------*/
6128 operand *left, *result;
6129 int size, offset = 0;
6132 D (emitcode (";", "genRLC ");
6135 /* rotate right with carry */
6136 left = IC_LEFT (ic);
6137 result = IC_RESULT (ic);
6138 aopOp (left, ic, FALSE, FALSE);
6139 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6141 /* move it to the result */
6142 size = AOP_SIZE (result);
6146 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6148 emitcode ("add", "a,acc");
6149 if (AOP_SIZE (result) > 1)
6151 aopPut (AOP (result), "a", offset++);
6154 _startLazyDPSEvaluation ();
6157 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6159 emitcode ("rlc", "a");
6160 if (AOP_SIZE (result) > 1)
6161 aopPut (AOP (result), "a", offset++);
6163 _endLazyDPSEvaluation ();
6165 /* now we need to put the carry into the
6166 highest order byte of the result */
6167 if (AOP_SIZE (result) > 1)
6169 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6172 emitcode ("mov", "acc.0,c");
6173 aopPut (AOP (result), "a", 0);
6174 freeAsmop (left, NULL, ic, TRUE);
6175 freeAsmop (result, NULL, ic, TRUE);
6178 /*-----------------------------------------------------------------*/
6179 /* genGetHbit - generates code get highest order bit */
6180 /*-----------------------------------------------------------------*/
6182 genGetHbit (iCode * ic)
6184 operand *left, *result;
6185 left = IC_LEFT (ic);
6186 result = IC_RESULT (ic);
6187 aopOp (left, ic, FALSE, FALSE);
6188 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6190 D (emitcode (";", "genGetHbit ");
6193 /* get the highest order byte into a */
6194 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6195 if (AOP_TYPE (result) == AOP_CRY)
6197 emitcode ("rlc", "a");
6202 emitcode ("rl", "a");
6203 emitcode ("anl", "a,#0x01");
6208 freeAsmop (left, NULL, ic, TRUE);
6209 freeAsmop (result, NULL, ic, TRUE);
6212 /*-----------------------------------------------------------------*/
6213 /* AccRol - rotate left accumulator by known count */
6214 /*-----------------------------------------------------------------*/
6216 AccRol (int shCount)
6218 shCount &= 0x0007; // shCount : 0..7
6225 emitcode ("rl", "a");
6228 emitcode ("rl", "a");
6229 emitcode ("rl", "a");
6232 emitcode ("swap", "a");
6233 emitcode ("rr", "a");
6236 emitcode ("swap", "a");
6239 emitcode ("swap", "a");
6240 emitcode ("rl", "a");
6243 emitcode ("rr", "a");
6244 emitcode ("rr", "a");
6247 emitcode ("rr", "a");
6252 /*-----------------------------------------------------------------*/
6253 /* AccLsh - left shift accumulator by known count */
6254 /*-----------------------------------------------------------------*/
6256 AccLsh (int shCount)
6261 emitcode ("add", "a,acc");
6262 else if (shCount == 2)
6264 emitcode ("add", "a,acc");
6265 emitcode ("add", "a,acc");
6269 /* rotate left accumulator */
6271 /* and kill the lower order bits */
6272 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6277 /*-----------------------------------------------------------------*/
6278 /* AccRsh - right shift accumulator by known count */
6279 /*-----------------------------------------------------------------*/
6281 AccRsh (int shCount)
6288 emitcode ("rrc", "a");
6292 /* rotate right accumulator */
6293 AccRol (8 - shCount);
6294 /* and kill the higher order bits */
6295 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6300 #ifdef BETTER_LITERAL_SHIFT
6301 /*-----------------------------------------------------------------*/
6302 /* AccSRsh - signed right shift accumulator by known count */
6303 /*-----------------------------------------------------------------*/
6305 AccSRsh (int shCount)
6312 emitcode ("mov", "c,acc.7");
6313 emitcode ("rrc", "a");
6315 else if (shCount == 2)
6317 emitcode ("mov", "c,acc.7");
6318 emitcode ("rrc", "a");
6319 emitcode ("mov", "c,acc.7");
6320 emitcode ("rrc", "a");
6324 tlbl = newiTempLabel (NULL);
6325 /* rotate right accumulator */
6326 AccRol (8 - shCount);
6327 /* and kill the higher order bits */
6328 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6329 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6330 emitcode ("orl", "a,#0x%02x",
6331 (unsigned char) ~SRMask[shCount]);
6332 emitcode ("", "%05d$:", tlbl->key + 100);
6338 #ifdef BETTER_LITERAL_SHIFT
6339 /*-----------------------------------------------------------------*/
6340 /* shiftR1Left2Result - shift right one byte from left to result */
6341 /*-----------------------------------------------------------------*/
6343 shiftR1Left2Result (operand * left, int offl,
6344 operand * result, int offr,
6345 int shCount, int sign)
6347 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6348 /* shift right accumulator */
6353 aopPut (AOP (result), "a", offr);
6357 #ifdef BETTER_LITERAL_SHIFT
6358 /*-----------------------------------------------------------------*/
6359 /* shiftL1Left2Result - shift left one byte from left to result */
6360 /*-----------------------------------------------------------------*/
6362 shiftL1Left2Result (operand * left, int offl,
6363 operand * result, int offr, int shCount)
6365 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6366 /* shift left accumulator */
6368 aopPut (AOP (result), "a", offr);
6372 #ifdef BETTER_LITERAL_SHIFT
6373 /*-----------------------------------------------------------------*/
6374 /* movLeft2Result - move byte from left to result */
6375 /*-----------------------------------------------------------------*/
6377 movLeft2Result (operand * left, int offl,
6378 operand * result, int offr, int sign)
6381 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6383 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6385 if (*l == '@' && (IS_AOP_PREG (result)))
6387 emitcode ("mov", "a,%s", l);
6388 aopPut (AOP (result), "a", offr);
6394 aopPut (AOP (result), l, offr);
6398 /* MSB sign in acc.7 ! */
6399 if (getDataSize (left) == offl + 1)
6401 emitcode ("mov", "a,%s", l);
6402 aopPut (AOP (result), "a", offr);
6410 #ifdef BETTER_LITERAL_SHIFT
6411 /*-----------------------------------------------------------------*/
6412 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6413 /*-----------------------------------------------------------------*/
6417 emitcode ("rrc", "a");
6418 emitcode ("xch", "a,%s", x);
6419 emitcode ("rrc", "a");
6420 emitcode ("xch", "a,%s", x);
6424 #ifdef BETTER_LITERAL_SHIFT
6426 /*-----------------------------------------------------------------*/
6427 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6428 /*-----------------------------------------------------------------*/
6432 emitcode ("xch", "a,%s", x);
6433 emitcode ("rlc", "a");
6434 emitcode ("xch", "a,%s", x);
6435 emitcode ("rlc", "a");
6439 #ifdef BETTER_LITERAL_SHIFT
6440 /*-----------------------------------------------------------------*/
6441 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6442 /*-----------------------------------------------------------------*/
6446 emitcode ("xch", "a,%s", x);
6447 emitcode ("add", "a,acc");
6448 emitcode ("xch", "a,%s", x);
6449 emitcode ("rlc", "a");
6453 #ifdef BETTER_LITERAL_SHIFT
6454 /*-----------------------------------------------------------------*/
6455 /* AccAXLsh - left shift a:x by known count (0..7) */
6456 /*-----------------------------------------------------------------*/
6458 AccAXLsh (char *x, int shCount)
6473 case 5: // AAAAABBB:CCCCCDDD
6475 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6477 emitcode ("anl", "a,#0x%02x",
6478 SLMask[shCount]); // BBB00000:CCCCCDDD
6480 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6482 AccRol (shCount); // DDDCCCCC:BBB00000
6484 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6486 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6488 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6490 emitcode ("anl", "a,#0x%02x",
6491 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6493 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6495 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6498 case 6: // AAAAAABB:CCCCCCDD
6499 emitcode ("anl", "a,#0x%02x",
6500 SRMask[shCount]); // 000000BB:CCCCCCDD
6501 emitcode ("mov", "c,acc.0"); // c = B
6502 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6504 AccAXRrl1 (x); // BCCCCCCD:D000000B
6505 AccAXRrl1 (x); // BBCCCCCC:DD000000
6507 emitcode("rrc","a");
6508 emitcode("xch","a,%s", x);
6509 emitcode("rrc","a");
6510 emitcode("mov","c,acc.0"); //<< get correct bit
6511 emitcode("xch","a,%s", x);
6513 emitcode("rrc","a");
6514 emitcode("xch","a,%s", x);
6515 emitcode("rrc","a");
6516 emitcode("xch","a,%s", x);
6519 case 7: // a:x <<= 7
6521 emitcode ("anl", "a,#0x%02x",
6522 SRMask[shCount]); // 0000000B:CCCCCCCD
6524 emitcode ("mov", "c,acc.0"); // c = B
6526 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6528 AccAXRrl1 (x); // BCCCCCCC:D0000000
6537 #ifdef BETTER_LITERAL_SHIFT
6539 /*-----------------------------------------------------------------*/
6540 /* AccAXRsh - right shift a:x known count (0..7) */
6541 /*-----------------------------------------------------------------*/
6543 AccAXRsh (char *x, int shCount)
6551 AccAXRrl1 (x); // 0->a:x
6556 AccAXRrl1 (x); // 0->a:x
6559 AccAXRrl1 (x); // 0->a:x
6564 case 5: // AAAAABBB:CCCCCDDD = a:x
6566 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6568 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6570 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6572 emitcode ("anl", "a,#0x%02x",
6573 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6575 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6577 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6579 emitcode ("anl", "a,#0x%02x",
6580 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6582 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6584 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6586 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6589 case 6: // AABBBBBB:CCDDDDDD
6591 emitcode ("mov", "c,acc.7");
6592 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6594 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6596 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6598 emitcode ("anl", "a,#0x%02x",
6599 SRMask[shCount]); // 000000AA:BBBBBBCC
6602 case 7: // ABBBBBBB:CDDDDDDD
6604 emitcode ("mov", "c,acc.7"); // c = A
6606 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6608 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6610 emitcode ("anl", "a,#0x%02x",
6611 SRMask[shCount]); // 0000000A:BBBBBBBC
6620 #ifdef BETTER_LITERAL_SHIFT
6621 /*-----------------------------------------------------------------*/
6622 /* AccAXRshS - right shift signed a:x known count (0..7) */
6623 /*-----------------------------------------------------------------*/
6625 AccAXRshS (char *x, int shCount)
6633 emitcode ("mov", "c,acc.7");
6634 AccAXRrl1 (x); // s->a:x
6638 emitcode ("mov", "c,acc.7");
6639 AccAXRrl1 (x); // s->a:x
6641 emitcode ("mov", "c,acc.7");
6642 AccAXRrl1 (x); // s->a:x
6647 case 5: // AAAAABBB:CCCCCDDD = a:x
6649 tlbl = newiTempLabel (NULL);
6650 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6652 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6654 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6656 emitcode ("anl", "a,#0x%02x",
6657 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6659 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6661 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6663 emitcode ("anl", "a,#0x%02x",
6664 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6666 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6668 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6670 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6672 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6673 emitcode ("orl", "a,#0x%02x",
6674 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6676 emitcode ("", "%05d$:", tlbl->key + 100);
6677 break; // SSSSAAAA:BBBCCCCC
6679 case 6: // AABBBBBB:CCDDDDDD
6681 tlbl = newiTempLabel (NULL);
6682 emitcode ("mov", "c,acc.7");
6683 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6685 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6687 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6689 emitcode ("anl", "a,#0x%02x",
6690 SRMask[shCount]); // 000000AA:BBBBBBCC
6692 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6693 emitcode ("orl", "a,#0x%02x",
6694 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6696 emitcode ("", "%05d$:", tlbl->key + 100);
6698 case 7: // ABBBBBBB:CDDDDDDD
6700 tlbl = newiTempLabel (NULL);
6701 emitcode ("mov", "c,acc.7"); // c = A
6703 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6705 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6707 emitcode ("anl", "a,#0x%02x",
6708 SRMask[shCount]); // 0000000A:BBBBBBBC
6710 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6711 emitcode ("orl", "a,#0x%02x",
6712 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6714 emitcode ("", "%05d$:", tlbl->key + 100);
6722 #ifdef BETTER_LITERAL_SHIFT
6724 _loadLeftIntoAx(char **lsb,
6730 // Get the initial value from left into a pair of registers.
6731 // MSB must be in A, LSB can be any register.
6733 // If the result is held in registers, it is an optimization
6734 // if the LSB can be held in the register which will hold the,
6735 // result LSB since this saves us from having to copy it into
6736 // the result following AccAXLsh.
6738 // If the result is addressed indirectly, this is not a gain.
6739 if (AOP_NEEDSACC(result))
6743 _startLazyDPSEvaluation();
6744 if (AOP_TYPE(left) == AOP_DPTR2)
6747 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6748 // get LSB in DP2_RESULT_REG.
6749 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6750 assert(!strcmp(leftByte, DP2_RESULT_REG));
6754 // get LSB into DP2_RESULT_REG
6755 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6756 if (strcmp(leftByte, DP2_RESULT_REG))
6759 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6762 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6763 assert(strcmp(leftByte, DP2_RESULT_REG));
6766 _endLazyDPSEvaluation();
6767 *lsb = DP2_RESULT_REG;
6771 if (sameRegs (AOP (result), AOP (left)) &&
6772 ((offl + MSB16) == offr))
6774 /* don't crash result[offr] */
6775 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6776 emitcode ("xch", "a,%s",
6777 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6781 movLeft2Result (left, offl, result, offr, 0);
6782 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6784 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6785 assert(strcmp(*lsb,"a"));
6790 _storeAxResults(char *lsb,
6794 _startLazyDPSEvaluation();
6795 if (AOP_NEEDSACC(result))
6797 /* We have to explicitly update the result LSB.
6799 emitcode("xch","a,%s", lsb);
6800 aopPut(AOP(result), "a", offr);
6801 emitcode("mov","a,%s", lsb);
6803 if (getDataSize (result) > 1)
6805 aopPut (AOP (result), "a", offr + MSB16);
6807 _endLazyDPSEvaluation();
6810 /*-----------------------------------------------------------------*/
6811 /* shiftL2Left2Result - shift left two bytes from left to result */
6812 /*-----------------------------------------------------------------*/
6814 shiftL2Left2Result (operand * left, int offl,
6815 operand * result, int offr, int shCount)
6819 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6821 AccAXLsh (lsb, shCount);
6823 _storeAxResults(lsb, result, offr);
6827 #ifdef BETTER_LITERAL_SHIFT
6828 /*-----------------------------------------------------------------*/
6829 /* shiftR2Left2Result - shift right two bytes from left to result */
6830 /*-----------------------------------------------------------------*/
6832 shiftR2Left2Result (operand * left, int offl,
6833 operand * result, int offr,
6834 int shCount, int sign)
6838 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6840 /* a:x >> shCount (x = lsb(result)) */
6843 AccAXRshS(lsb, shCount);
6847 AccAXRsh(lsb, shCount);
6850 _storeAxResults(lsb, result, offr);
6856 /*-----------------------------------------------------------------*/
6857 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6858 /*-----------------------------------------------------------------*/
6860 shiftLLeftOrResult (operand * left, int offl,
6861 operand * result, int offr, int shCount)
6863 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6864 /* shift left accumulator */
6866 /* or with result */
6867 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6868 /* back to result */
6869 aopPut (AOP (result), "a", offr);
6875 /*-----------------------------------------------------------------*/
6876 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6877 /*-----------------------------------------------------------------*/
6879 shiftRLeftOrResult (operand * left, int offl,
6880 operand * result, int offr, int shCount)
6882 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6883 /* shift right accumulator */
6885 /* or with result */
6886 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6887 /* back to result */
6888 aopPut (AOP (result), "a", offr);
6892 #ifdef BETTER_LITERAL_SHIFT
6893 /*-----------------------------------------------------------------*/
6894 /* genlshOne - left shift a one byte quantity by known count */
6895 /*-----------------------------------------------------------------*/
6897 genlshOne (operand * result, operand * left, int shCount)
6899 D (emitcode (";", "genlshOne "););
6900 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6904 #ifdef BETTER_LITERAL_SHIFT
6905 /*-----------------------------------------------------------------*/
6906 /* genlshTwo - left shift two bytes by known amount != 0 */
6907 /*-----------------------------------------------------------------*/
6909 genlshTwo (operand * result, operand * left, int shCount)
6913 D (emitcode (";", "genlshTwo "););
6915 size = getDataSize (result);
6917 /* if shCount >= 8 */
6922 _startLazyDPSEvaluation();
6928 _endLazyDPSEvaluation();
6929 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6930 aopPut (AOP (result), zero, LSB);
6934 movLeft2Result (left, LSB, result, MSB16, 0);
6935 aopPut (AOP (result), zero, LSB);
6936 _endLazyDPSEvaluation();
6941 aopPut (AOP (result), zero, LSB);
6942 _endLazyDPSEvaluation();
6946 /* 1 <= shCount <= 7 */
6951 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6955 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6963 /*-----------------------------------------------------------------*/
6964 /* shiftLLong - shift left one long from left to result */
6965 /* offl = LSB or MSB16 */
6966 /*-----------------------------------------------------------------*/
6968 shiftLLong (operand * left, operand * result, int offr)
6971 int size = AOP_SIZE (result);
6973 if (size >= LSB + offr)
6975 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6977 emitcode ("add", "a,acc");
6978 if (sameRegs (AOP (left), AOP (result)) &&
6979 size >= MSB16 + offr && offr != LSB)
6980 emitcode ("xch", "a,%s",
6981 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6983 aopPut (AOP (result), "a", LSB + offr);
6986 if (size >= MSB16 + offr)
6988 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6990 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6993 emitcode ("rlc", "a");
6994 if (sameRegs (AOP (left), AOP (result)) &&
6995 size >= MSB24 + offr && offr != LSB)
6996 emitcode ("xch", "a,%s",
6997 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6999 aopPut (AOP (result), "a", MSB16 + offr);
7002 if (size >= MSB24 + offr)
7004 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7006 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7009 emitcode ("rlc", "a");
7010 if (sameRegs (AOP (left), AOP (result)) &&
7011 size >= MSB32 + offr && offr != LSB)
7012 emitcode ("xch", "a,%s",
7013 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7015 aopPut (AOP (result), "a", MSB24 + offr);
7018 if (size > MSB32 + offr)
7020 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7022 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7025 emitcode ("rlc", "a");
7026 aopPut (AOP (result), "a", MSB32 + offr);
7029 aopPut (AOP (result), zero, LSB);
7035 /*-----------------------------------------------------------------*/
7036 /* genlshFour - shift four byte by a known amount != 0 */
7037 /*-----------------------------------------------------------------*/
7039 genlshFour (operand * result, operand * left, int shCount)
7043 D (emitcode (";", "genlshFour ");
7046 size = AOP_SIZE (result);
7048 /* if shifting more that 3 bytes */
7053 /* lowest order of left goes to the highest
7054 order of the destination */
7055 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7057 movLeft2Result (left, LSB, result, MSB32, 0);
7058 aopPut (AOP (result), zero, LSB);
7059 aopPut (AOP (result), zero, MSB16);
7060 aopPut (AOP (result), zero, MSB24);
7064 /* more than two bytes */
7065 else if (shCount >= 16)
7067 /* lower order two bytes goes to higher order two bytes */
7069 /* if some more remaining */
7071 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7074 movLeft2Result (left, MSB16, result, MSB32, 0);
7075 movLeft2Result (left, LSB, result, MSB24, 0);
7077 aopPut (AOP (result), zero, MSB16);
7078 aopPut (AOP (result), zero, LSB);
7082 /* if more than 1 byte */
7083 else if (shCount >= 8)
7085 /* lower order three bytes goes to higher order three bytes */
7090 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7092 movLeft2Result (left, LSB, result, MSB16, 0);
7098 movLeft2Result (left, MSB24, result, MSB32, 0);
7099 movLeft2Result (left, MSB16, result, MSB24, 0);
7100 movLeft2Result (left, LSB, result, MSB16, 0);
7101 aopPut (AOP (result), zero, LSB);
7103 else if (shCount == 1)
7104 shiftLLong (left, result, MSB16);
7107 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7108 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7109 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7110 aopPut (AOP (result), zero, LSB);
7115 /* 1 <= shCount <= 7 */
7116 else if (shCount <= 2)
7118 shiftLLong (left, result, LSB);
7120 shiftLLong (result, result, LSB);
7122 /* 3 <= shCount <= 7, optimize */
7125 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7126 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7127 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7132 #ifdef BETTER_LITERAL_SHIFT
7133 /*-----------------------------------------------------------------*/
7134 /* genLeftShiftLiteral - left shifting by known count */
7135 /*-----------------------------------------------------------------*/
7137 genLeftShiftLiteral (operand * left,
7142 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7145 size = getSize (operandType (result));
7147 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7149 /* We only handle certain easy cases so far. */
7151 && (shCount < (size * 8))
7155 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7159 freeAsmop (right, NULL, ic, TRUE);
7161 aopOp(left, ic, FALSE, FALSE);
7162 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7165 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7167 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7168 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7170 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7173 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7175 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7176 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7178 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7184 emitcode ("; shift left ", "result %d, left %d", size,
7188 /* I suppose that the left size >= result size */
7191 _startLazyDPSEvaluation();
7194 movLeft2Result (left, size, result, size, 0);
7196 _endLazyDPSEvaluation();
7198 else if (shCount >= (size * 8))
7200 _startLazyDPSEvaluation();
7203 aopPut (AOP (result), zero, size);
7205 _endLazyDPSEvaluation();
7212 genlshOne (result, left, shCount);
7216 genlshTwo (result, left, shCount);
7220 genlshFour (result, left, shCount);
7224 fprintf(stderr, "*** ack! mystery literal shift!\n");
7228 freeAsmop (left, NULL, ic, TRUE);
7229 freeAsmop (result, NULL, ic, TRUE);
7234 /*-----------------------------------------------------------------*/
7235 /* genLeftShift - generates code for left shifting */
7236 /*-----------------------------------------------------------------*/
7238 genLeftShift (iCode * ic)
7240 operand *left, *right, *result;
7243 symbol *tlbl, *tlbl1;
7245 D (emitcode (";", "genLeftShift "););
7247 right = IC_RIGHT (ic);
7248 left = IC_LEFT (ic);
7249 result = IC_RESULT (ic);
7251 aopOp (right, ic, FALSE, FALSE);
7254 #ifdef BETTER_LITERAL_SHIFT
7255 /* if the shift count is known then do it
7256 as efficiently as possible */
7257 if (AOP_TYPE (right) == AOP_LIT)
7259 if (genLeftShiftLiteral (left, right, result, ic))
7266 /* shift count is unknown then we have to form
7267 a loop get the loop count in B : Note: we take
7268 only the lower order byte since shifting
7269 more that 32 bits make no sense anyway, ( the
7270 largest size of an object can be only 32 bits ) */
7272 if (AOP_TYPE (right) == AOP_LIT)
7274 /* Really should be handled by genLeftShiftLiteral,
7275 * but since I'm too lazy to fix that today, at least we can make
7276 * some small improvement.
7278 emitcode("mov", "b,#0x%02x",
7279 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7283 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7284 emitcode ("inc", "b");
7286 freeAsmop (right, NULL, ic, TRUE);
7287 aopOp (left, ic, FALSE, FALSE);
7288 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7290 /* now move the left to the result if they are not the
7292 if (!sameRegs (AOP (left), AOP (result)) &&
7293 AOP_SIZE (result) > 1)
7296 size = AOP_SIZE (result);
7298 _startLazyDPSEvaluation ();
7301 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7302 if (*l == '@' && (IS_AOP_PREG (result)))
7305 emitcode ("mov", "a,%s", l);
7306 aopPut (AOP (result), "a", offset);
7309 aopPut (AOP (result), l, offset);
7312 _endLazyDPSEvaluation ();
7315 tlbl = newiTempLabel (NULL);
7316 size = AOP_SIZE (result);
7318 tlbl1 = newiTempLabel (NULL);
7320 /* if it is only one byte then */
7323 symbol *tlbl1 = newiTempLabel (NULL);
7325 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7327 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7328 emitcode ("", "%05d$:", tlbl->key + 100);
7329 emitcode ("add", "a,acc");
7330 emitcode ("", "%05d$:", tlbl1->key + 100);
7331 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7332 aopPut (AOP (result), "a", 0);
7336 reAdjustPreg (AOP (result));
7338 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7339 emitcode ("", "%05d$:", tlbl->key + 100);
7340 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7342 emitcode ("add", "a,acc");
7343 aopPut (AOP (result), "a", offset++);
7344 _startLazyDPSEvaluation ();
7347 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7349 emitcode ("rlc", "a");
7350 aopPut (AOP (result), "a", offset++);
7352 _endLazyDPSEvaluation ();
7353 reAdjustPreg (AOP (result));
7355 emitcode ("", "%05d$:", tlbl1->key + 100);
7356 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7358 freeAsmop (left, NULL, ic, TRUE);
7359 freeAsmop (result, NULL, ic, TRUE);
7362 #ifdef BETTER_LITERAL_SHIFT
7363 /*-----------------------------------------------------------------*/
7364 /* genrshOne - right shift a one byte quantity by known count */
7365 /*-----------------------------------------------------------------*/
7367 genrshOne (operand * result, operand * left,
7368 int shCount, int sign)
7370 D (emitcode (";", "genrshOne"););
7371 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7375 #ifdef BETTER_LITERAL_SHIFT
7376 /*-----------------------------------------------------------------*/
7377 /* genrshTwo - right shift two bytes by known amount != 0 */
7378 /*-----------------------------------------------------------------*/
7380 genrshTwo (operand * result, operand * left,
7381 int shCount, int sign)
7383 D (emitcode (";", "genrshTwo"););
7385 /* if shCount >= 8 */
7389 _startLazyDPSEvaluation();
7392 shiftR1Left2Result (left, MSB16, result, LSB,
7397 movLeft2Result (left, MSB16, result, LSB, sign);
7399 addSign (result, MSB16, sign);
7400 _endLazyDPSEvaluation();
7403 /* 1 <= shCount <= 7 */
7406 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7413 /*-----------------------------------------------------------------*/
7414 /* shiftRLong - shift right one long from left to result */
7415 /* offl = LSB or MSB16 */
7416 /*-----------------------------------------------------------------*/
7418 shiftRLong (operand * left, int offl,
7419 operand * result, int sign)
7421 int isSameRegs=sameRegs(AOP(left),AOP(result));
7423 if (isSameRegs && offl>1) {
7424 // we are in big trouble, but this shouldn't happen
7425 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7428 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7433 emitcode ("rlc", "a");
7434 emitcode ("subb", "a,acc");
7435 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7437 aopPut (AOP(result), zero, MSB32);
7442 emitcode ("clr", "c");
7444 emitcode ("mov", "c,acc.7");
7447 emitcode ("rrc", "a");
7449 if (isSameRegs && offl==MSB16) {
7450 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7452 aopPut (AOP (result), "a", MSB32);
7453 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7456 emitcode ("rrc", "a");
7457 if (isSameRegs && offl==1) {
7458 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7460 aopPut (AOP (result), "a", MSB24);
7461 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7463 emitcode ("rrc", "a");
7464 aopPut (AOP (result), "a", MSB16 - offl);
7468 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7469 emitcode ("rrc", "a");
7470 aopPut (AOP (result), "a", LSB);
7477 /*-----------------------------------------------------------------*/
7478 /* genrshFour - shift four byte by a known amount != 0 */
7479 /*-----------------------------------------------------------------*/
7481 genrshFour (operand * result, operand * left,
7482 int shCount, int sign)
7484 D (emitcode (";", "genrshFour");
7487 /* if shifting more that 3 bytes */
7492 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7494 movLeft2Result (left, MSB32, result, LSB, sign);
7495 addSign (result, MSB16, sign);
7497 else if (shCount >= 16)
7501 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7504 movLeft2Result (left, MSB24, result, LSB, 0);
7505 movLeft2Result (left, MSB32, result, MSB16, sign);
7507 addSign (result, MSB24, sign);
7509 else if (shCount >= 8)
7513 shiftRLong (left, MSB16, result, sign);
7514 else if (shCount == 0)
7516 movLeft2Result (left, MSB16, result, LSB, 0);
7517 movLeft2Result (left, MSB24, result, MSB16, 0);
7518 movLeft2Result (left, MSB32, result, MSB24, sign);
7519 addSign (result, MSB32, sign);
7523 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7524 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7525 /* the last shift is signed */
7526 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7527 addSign (result, MSB32, sign);
7531 { /* 1 <= shCount <= 7 */
7534 shiftRLong (left, LSB, result, sign);
7536 shiftRLong (result, LSB, result, sign);
7540 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7541 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7542 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7548 #ifdef BETTER_LITERAL_SHIFT
7549 /*-----------------------------------------------------------------*/
7550 /* genRightShiftLiteral - right shifting by known count */
7551 /*-----------------------------------------------------------------*/
7553 genRightShiftLiteral (operand * left,
7559 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7562 size = getSize (operandType (result));
7564 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7566 /* We only handle certain easy cases so far. */
7568 && (shCount < (size * 8))
7572 D(emitcode (";", "genRightShiftLiteral wimping out"););
7576 freeAsmop (right, NULL, ic, TRUE);
7578 aopOp (left, ic, FALSE, FALSE);
7579 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7582 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7586 /* test the LEFT size !!! */
7588 /* I suppose that the left size >= result size */
7591 size = getDataSize (result);
7592 _startLazyDPSEvaluation();
7595 movLeft2Result (left, size, result, size, 0);
7597 _endLazyDPSEvaluation();
7599 else if (shCount >= (size * 8))
7603 /* get sign in acc.7 */
7604 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7606 addSign (result, LSB, sign);
7613 genrshOne (result, left, shCount, sign);
7617 genrshTwo (result, left, shCount, sign);
7621 genrshFour (result, left, shCount, sign);
7628 freeAsmop (left, NULL, ic, TRUE);
7629 freeAsmop (result, NULL, ic, TRUE);
7635 /*-----------------------------------------------------------------*/
7636 /* genSignedRightShift - right shift of signed number */
7637 /*-----------------------------------------------------------------*/
7639 genSignedRightShift (iCode * ic)
7641 operand *right, *left, *result;
7644 symbol *tlbl, *tlbl1;
7646 D (emitcode (";", "genSignedRightShift "););
7648 /* we do it the hard way put the shift count in b
7649 and loop thru preserving the sign */
7651 right = IC_RIGHT (ic);
7652 left = IC_LEFT (ic);
7653 result = IC_RESULT (ic);
7655 aopOp (right, ic, FALSE, FALSE);
7657 #ifdef BETTER_LITERAL_SHIFT
7658 if (AOP_TYPE (right) == AOP_LIT)
7660 if (genRightShiftLiteral (left, right, result, ic, 1))
7666 /* shift count is unknown then we have to form
7667 a loop get the loop count in B : Note: we take
7668 only the lower order byte since shifting
7669 more that 32 bits make no sense anyway, ( the
7670 largest size of an object can be only 32 bits ) */
7672 if (AOP_TYPE (right) == AOP_LIT)
7674 /* Really should be handled by genRightShiftLiteral,
7675 * but since I'm too lazy to fix that today, at least we can make
7676 * some small improvement.
7678 emitcode("mov", "b,#0x%02x",
7679 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7683 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7684 emitcode ("inc", "b");
7686 freeAsmop (right, NULL, ic, TRUE);
7687 aopOp (left, ic, FALSE, FALSE);
7688 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7690 /* now move the left to the result if they are not the
7692 if (!sameRegs (AOP (left), AOP (result)) &&
7693 AOP_SIZE (result) > 1)
7696 size = AOP_SIZE (result);
7698 _startLazyDPSEvaluation ();
7701 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7702 if (*l == '@' && IS_AOP_PREG (result))
7705 emitcode ("mov", "a,%s", l);
7706 aopPut (AOP (result), "a", offset);
7709 aopPut (AOP (result), l, offset);
7712 _endLazyDPSEvaluation ();
7715 /* mov the highest order bit to OVR */
7716 tlbl = newiTempLabel (NULL);
7717 tlbl1 = newiTempLabel (NULL);
7719 size = AOP_SIZE (result);
7721 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7722 emitcode ("rlc", "a");
7723 emitcode ("mov", "ov,c");
7724 /* if it is only one byte then */
7727 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7729 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7730 emitcode ("", "%05d$:", tlbl->key + 100);
7731 emitcode ("mov", "c,ov");
7732 emitcode ("rrc", "a");
7733 emitcode ("", "%05d$:", tlbl1->key + 100);
7734 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7735 aopPut (AOP (result), "a", 0);
7739 reAdjustPreg (AOP (result));
7740 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7741 emitcode ("", "%05d$:", tlbl->key + 100);
7742 emitcode ("mov", "c,ov");
7743 _startLazyDPSEvaluation ();
7746 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7748 emitcode ("rrc", "a");
7749 aopPut (AOP (result), "a", offset--);
7751 _endLazyDPSEvaluation ();
7752 reAdjustPreg (AOP (result));
7753 emitcode ("", "%05d$:", tlbl1->key + 100);
7754 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7757 freeAsmop (left, NULL, ic, TRUE);
7758 freeAsmop (result, NULL, ic, TRUE);
7761 /*-----------------------------------------------------------------*/
7762 /* genRightShift - generate code for right shifting */
7763 /*-----------------------------------------------------------------*/
7765 genRightShift (iCode * ic)
7767 operand *right, *left, *result;
7771 symbol *tlbl, *tlbl1;
7773 D (emitcode (";", "genRightShift "););
7775 /* if signed then we do it the hard way preserve the
7776 sign bit moving it inwards */
7777 retype = getSpec (operandType (IC_RESULT (ic)));
7779 if (!SPEC_USIGN (retype))
7781 genSignedRightShift (ic);
7785 /* signed & unsigned types are treated the same : i.e. the
7786 signed is NOT propagated inwards : quoting from the
7787 ANSI - standard : "for E1 >> E2, is equivalent to division
7788 by 2**E2 if unsigned or if it has a non-negative value,
7789 otherwise the result is implementation defined ", MY definition
7790 is that the sign does not get propagated */
7792 right = IC_RIGHT (ic);
7793 left = IC_LEFT (ic);
7794 result = IC_RESULT (ic);
7796 aopOp (right, ic, FALSE, FALSE);
7798 #ifdef BETTER_LITERAL_SHIFT
7799 /* if the shift count is known then do it
7800 as efficiently as possible */
7801 if (AOP_TYPE (right) == AOP_LIT)
7803 if (genRightShiftLiteral (left, right, result, ic, 0))
7810 /* shift count is unknown then we have to form
7811 a loop get the loop count in B : Note: we take
7812 only the lower order byte since shifting
7813 more that 32 bits make no sense anyway, ( the
7814 largest size of an object can be only 32 bits ) */
7816 if (AOP_TYPE (right) == AOP_LIT)
7818 /* Really should be handled by genRightShiftLiteral,
7819 * but since I'm too lazy to fix that today, at least we can make
7820 * some small improvement.
7822 emitcode("mov", "b,#0x%02x",
7823 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7827 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7828 emitcode ("inc", "b");
7830 freeAsmop (right, NULL, ic, TRUE);
7831 aopOp (left, ic, FALSE, FALSE);
7832 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7834 /* now move the left to the result if they are not the
7836 if (!sameRegs (AOP (left), AOP (result)) &&
7837 AOP_SIZE (result) > 1)
7840 size = AOP_SIZE (result);
7842 _startLazyDPSEvaluation ();
7845 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7846 if (*l == '@' && IS_AOP_PREG (result))
7849 emitcode ("mov", "a,%s", l);
7850 aopPut (AOP (result), "a", offset);
7853 aopPut (AOP (result), l, offset);
7856 _endLazyDPSEvaluation ();
7859 tlbl = newiTempLabel (NULL);
7860 tlbl1 = newiTempLabel (NULL);
7861 size = AOP_SIZE (result);
7864 /* if it is only one byte then */
7867 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7869 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7870 emitcode ("", "%05d$:", tlbl->key + 100);
7872 emitcode ("rrc", "a");
7873 emitcode ("", "%05d$:", tlbl1->key + 100);
7874 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7875 aopPut (AOP (result), "a", 0);
7879 reAdjustPreg (AOP (result));
7880 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7881 emitcode ("", "%05d$:", tlbl->key + 100);
7883 _startLazyDPSEvaluation ();
7886 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7888 emitcode ("rrc", "a");
7889 aopPut (AOP (result), "a", offset--);
7891 _endLazyDPSEvaluation ();
7892 reAdjustPreg (AOP (result));
7894 emitcode ("", "%05d$:", tlbl1->key + 100);
7895 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7898 freeAsmop (left, NULL, ic, TRUE);
7899 freeAsmop (result, NULL, ic, TRUE);
7902 /*-----------------------------------------------------------------*/
7903 /* genUnpackBits - generates code for unpacking bits */
7904 /*-----------------------------------------------------------------*/
7906 genUnpackBits (operand * result, char *rname, int ptype)
7913 D (emitcode (";", "genUnpackBits ");
7916 etype = getSpec (operandType (result));
7918 /* read the first byte */
7924 emitcode ("mov", "a,@%s", rname);
7928 emitcode ("movx", "a,@%s", rname);
7932 emitcode ("movx", "a,@dptr");
7936 emitcode ("clr", "a");
7937 emitcode ("movc", "a", "@a+dptr");
7941 emitcode ("lcall", "__gptrget");
7945 /* if we have bitdisplacement then it fits */
7946 /* into this byte completely or if length is */
7947 /* less than a byte */
7948 if ((shCnt = SPEC_BSTR (etype)) ||
7949 (SPEC_BLEN (etype) <= 8))
7952 /* shift right acc */
7955 emitcode ("anl", "a,#0x%02x",
7956 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7957 aopPut (AOP (result), "a", offset);
7961 /* bit field did not fit in a byte */
7962 rlen = SPEC_BLEN (etype) - 8;
7963 aopPut (AOP (result), "a", offset++);
7972 emitcode ("inc", "%s", rname);
7973 emitcode ("mov", "a,@%s", rname);
7977 emitcode ("inc", "%s", rname);
7978 emitcode ("movx", "a,@%s", rname);
7982 emitcode ("inc", "dptr");
7983 emitcode ("movx", "a,@dptr");
7987 emitcode ("clr", "a");
7988 emitcode ("inc", "dptr");
7989 emitcode ("movc", "a", "@a+dptr");
7993 emitcode ("inc", "dptr");
7994 emitcode ("lcall", "__gptrget");
7999 /* if we are done */
8003 aopPut (AOP (result), "a", offset++);
8009 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8010 aopPut (AOP (result), "a", offset);
8017 /*-----------------------------------------------------------------*/
8018 /* genDataPointerGet - generates code when ptr offset is known */
8019 /*-----------------------------------------------------------------*/
8021 genDataPointerGet (operand * left,
8027 int size, offset = 0;
8028 aopOp (result, ic, TRUE, FALSE);
8030 /* get the string representation of the name */
8031 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8032 size = AOP_SIZE (result);
8033 _startLazyDPSEvaluation ();
8037 sprintf (buffer, "(%s + %d)", l + 1, offset);
8039 sprintf (buffer, "%s", l + 1);
8040 aopPut (AOP (result), buffer, offset++);
8042 _endLazyDPSEvaluation ();
8044 freeAsmop (left, NULL, ic, TRUE);
8045 freeAsmop (result, NULL, ic, TRUE);
8048 /*-----------------------------------------------------------------*/
8049 /* genNearPointerGet - emitcode for near pointer fetch */
8050 /*-----------------------------------------------------------------*/
8052 genNearPointerGet (operand * left,
8059 sym_link *rtype, *retype, *letype;
8060 sym_link *ltype = operandType (left);
8063 rtype = operandType (result);
8064 retype = getSpec (rtype);
8065 letype = getSpec (ltype);
8067 aopOp (left, ic, FALSE, FALSE);
8069 /* if left is rematerialisable and
8070 result is not bit variable type and
8071 the left is pointer to data space i.e
8072 lower 128 bytes of space */
8073 if (AOP_TYPE (left) == AOP_IMMD &&
8074 !IS_BITVAR (retype) &&
8075 !IS_BITVAR (letype) &&
8076 DCL_TYPE (ltype) == POINTER)
8078 genDataPointerGet (left, result, ic);
8082 /* if the value is already in a pointer register
8083 then don't need anything more */
8084 if (!AOP_INPREG (AOP (left)))
8086 /* otherwise get a free pointer register */
8088 preg = getFreePtr (ic, &aop, FALSE);
8089 emitcode ("mov", "%s,%s",
8091 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8095 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8097 freeAsmop (left, NULL, ic, TRUE);
8098 aopOp (result, ic, FALSE, FALSE);
8100 /* if bitfield then unpack the bits */
8101 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8102 genUnpackBits (result, rname, POINTER);
8105 /* we have can just get the values */
8106 int size = AOP_SIZE (result);
8111 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8114 emitcode ("mov", "a,@%s", rname);
8115 aopPut (AOP (result), "a", offset);
8119 sprintf (buffer, "@%s", rname);
8120 aopPut (AOP (result), buffer, offset);
8124 emitcode ("inc", "%s", rname);
8128 /* now some housekeeping stuff */
8131 /* we had to allocate for this iCode */
8132 freeAsmop (NULL, aop, ic, TRUE);
8136 /* we did not allocate which means left
8137 already in a pointer register, then
8138 if size > 0 && this could be used again
8139 we have to point it back to where it
8141 if (AOP_SIZE (result) > 1 &&
8142 !OP_SYMBOL (left)->remat &&
8143 (OP_SYMBOL (left)->liveTo > ic->seq ||
8146 int size = AOP_SIZE (result) - 1;
8148 emitcode ("dec", "%s", rname);
8153 freeAsmop (result, NULL, ic, TRUE);
8157 /*-----------------------------------------------------------------*/
8158 /* genPagedPointerGet - emitcode for paged pointer fetch */
8159 /*-----------------------------------------------------------------*/
8161 genPagedPointerGet (operand * left,
8168 sym_link *rtype, *retype, *letype;
8170 rtype = operandType (result);
8171 retype = getSpec (rtype);
8172 letype = getSpec (operandType (left));
8173 aopOp (left, ic, FALSE, FALSE);
8175 /* if the value is already in a pointer register
8176 then don't need anything more */
8177 if (!AOP_INPREG (AOP (left)))
8179 /* otherwise get a free pointer register */
8181 preg = getFreePtr (ic, &aop, FALSE);
8182 emitcode ("mov", "%s,%s",
8184 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8188 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8190 freeAsmop (left, NULL, ic, TRUE);
8191 aopOp (result, ic, FALSE, FALSE);
8193 /* if bitfield then unpack the bits */
8194 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8195 genUnpackBits (result, rname, PPOINTER);
8198 /* we have can just get the values */
8199 int size = AOP_SIZE (result);
8205 emitcode ("movx", "a,@%s", rname);
8206 aopPut (AOP (result), "a", offset);
8211 emitcode ("inc", "%s", rname);
8215 /* now some housekeeping stuff */
8218 /* we had to allocate for this iCode */
8219 freeAsmop (NULL, aop, ic, TRUE);
8223 /* we did not allocate which means left
8224 already in a pointer register, then
8225 if size > 0 && this could be used again
8226 we have to point it back to where it
8228 if (AOP_SIZE (result) > 1 &&
8229 !OP_SYMBOL (left)->remat &&
8230 (OP_SYMBOL (left)->liveTo > ic->seq ||
8233 int size = AOP_SIZE (result) - 1;
8235 emitcode ("dec", "%s", rname);
8240 freeAsmop (result, NULL, ic, TRUE);
8245 /*-----------------------------------------------------------------*/
8246 /* genFarPointerGet - gget value from far space */
8247 /*-----------------------------------------------------------------*/
8249 genFarPointerGet (operand * left,
8250 operand * result, iCode * ic)
8253 sym_link *retype = getSpec (operandType (result));
8254 sym_link *letype = getSpec (operandType (left));
8255 D (emitcode (";", "genFarPointerGet");
8258 aopOp (left, ic, FALSE, FALSE);
8260 /* if the operand is already in dptr
8261 then we do nothing else we move the value to dptr */
8262 if (AOP_TYPE (left) != AOP_STR)
8264 /* if this is remateriazable */
8265 if (AOP_TYPE (left) == AOP_IMMD)
8267 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8271 /* we need to get it byte by byte */
8272 _startLazyDPSEvaluation ();
8273 if (AOP_TYPE (left) != AOP_DPTR)
8275 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8276 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8277 if (options.model == MODEL_FLAT24)
8278 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8282 /* We need to generate a load to DPTR indirect through DPTR. */
8283 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8285 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8286 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8287 if (options.model == MODEL_FLAT24)
8288 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8289 emitcode ("pop", "dph");
8290 emitcode ("pop", "dpl");
8292 _endLazyDPSEvaluation ();
8295 /* so dptr know contains the address */
8296 freeAsmop (left, NULL, ic, TRUE);
8297 aopOp (result, ic, FALSE, TRUE);
8299 /* if bit then unpack */
8300 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8301 genUnpackBits (result, "dptr", FPOINTER);
8304 size = AOP_SIZE (result);
8307 _startLazyDPSEvaluation ();
8314 emitcode ("movx", "a,@dptr");
8316 emitcode ("inc", "dptr");
8318 aopPut (AOP (result), "a", offset++);
8320 _endLazyDPSEvaluation ();
8323 freeAsmop (result, NULL, ic, TRUE);
8326 /*-----------------------------------------------------------------*/
8327 /* emitcodePointerGet - gget value from code space */
8328 /*-----------------------------------------------------------------*/
8330 emitcodePointerGet (operand * left,
8331 operand * result, iCode * ic)
8334 sym_link *retype = getSpec (operandType (result));
8336 aopOp (left, ic, FALSE, FALSE);
8338 /* if the operand is already in dptr
8339 then we do nothing else we move the value to dptr */
8340 if (AOP_TYPE (left) != AOP_STR)
8342 /* if this is remateriazable */
8343 if (AOP_TYPE (left) == AOP_IMMD)
8345 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8348 { /* we need to get it byte by byte */
8349 _startLazyDPSEvaluation ();
8350 if (AOP_TYPE (left) != AOP_DPTR)
8352 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8353 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8354 if (options.model == MODEL_FLAT24)
8355 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8359 /* We need to generate a load to DPTR indirect through DPTR. */
8360 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8362 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8363 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8364 if (options.model == MODEL_FLAT24)
8365 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8366 emitcode ("pop", "dph");
8367 emitcode ("pop", "dpl");
8369 _endLazyDPSEvaluation ();
8372 /* so dptr know contains the address */
8373 freeAsmop (left, NULL, ic, TRUE);
8374 aopOp (result, ic, FALSE, TRUE);
8376 /* if bit then unpack */
8377 if (IS_BITVAR (retype))
8378 genUnpackBits (result, "dptr", CPOINTER);
8381 size = AOP_SIZE (result);
8384 _startLazyDPSEvaluation ();
8390 emitcode ("clr", "a");
8391 emitcode ("movc", "a,@a+dptr");
8393 emitcode ("inc", "dptr");
8394 aopPut (AOP (result), "a", offset++);
8396 _endLazyDPSEvaluation ();
8399 freeAsmop (result, NULL, ic, TRUE);
8402 /*-----------------------------------------------------------------*/
8403 /* genGenPointerGet - gget value from generic pointer space */
8404 /*-----------------------------------------------------------------*/
8406 genGenPointerGet (operand * left,
8407 operand * result, iCode * ic)
8410 sym_link *retype = getSpec (operandType (result));
8411 sym_link *letype = getSpec (operandType (left));
8413 D (emitcode (";", "genGenPointerGet "); );
8415 aopOp (left, ic, FALSE, TRUE);
8417 /* if the operand is already in dptr
8418 then we do nothing else we move the value to dptr */
8419 if (AOP_TYPE (left) != AOP_STR)
8421 /* if this is remateriazable */
8422 if (AOP_TYPE (left) == AOP_IMMD)
8424 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8425 emitcode ("mov", "b,#%d", pointerCode (retype));
8428 { /* we need to get it byte by byte */
8429 _startLazyDPSEvaluation ();
8430 if (AOP(left)->type==AOP_DPTR2) {
8432 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8435 emitcode ("mov", "dpl,%s", l);
8436 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8439 emitcode ("mov", "dph,%s", l);
8440 if (options.model == MODEL_FLAT24) {
8441 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8444 emitcode ("mov", "dpx,%s", l);
8445 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8447 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8450 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8451 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8452 if (options.model == MODEL_FLAT24) {
8453 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8454 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8456 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8459 _endLazyDPSEvaluation ();
8462 /* so dptr know contains the address */
8463 freeAsmop (left, NULL, ic, TRUE);
8464 aopOp (result, ic, FALSE, TRUE);
8466 /* if bit then unpack */
8467 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8468 genUnpackBits (result, "dptr", GPOINTER);
8471 size = AOP_SIZE (result);
8476 emitcode ("lcall", "__gptrget");
8477 aopPut (AOP (result), "a", offset++);
8479 emitcode ("inc", "dptr");
8483 freeAsmop (result, NULL, ic, TRUE);
8486 /*-----------------------------------------------------------------*/
8487 /* genPointerGet - generate code for pointer get */
8488 /*-----------------------------------------------------------------*/
8490 genPointerGet (iCode * ic)
8492 operand *left, *result;
8493 sym_link *type, *etype;
8496 D (emitcode (";", "genPointerGet ");
8499 left = IC_LEFT (ic);
8500 result = IC_RESULT (ic);
8502 /* depending on the type of pointer we need to
8503 move it to the correct pointer register */
8504 type = operandType (left);
8505 etype = getSpec (type);
8506 /* if left is of type of pointer then it is simple */
8507 if (IS_PTR (type) && !IS_FUNC (type->next))
8508 p_type = DCL_TYPE (type);
8511 /* we have to go by the storage class */
8512 p_type = PTR_TYPE (SPEC_OCLS (etype));
8515 /* now that we have the pointer type we assign
8516 the pointer values */
8522 genNearPointerGet (left, result, ic);
8526 genPagedPointerGet (left, result, ic);
8530 genFarPointerGet (left, result, ic);
8534 emitcodePointerGet (left, result, ic);
8538 genGenPointerGet (left, result, ic);
8544 /*-----------------------------------------------------------------*/
8545 /* genPackBits - generates code for packed bit storage */
8546 /*-----------------------------------------------------------------*/
8548 genPackBits (sym_link * etype,
8550 char *rname, int p_type)
8558 blen = SPEC_BLEN (etype);
8559 bstr = SPEC_BSTR (etype);
8561 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8564 /* if the bit lenth is less than or */
8565 /* it exactly fits a byte then */
8566 if (SPEC_BLEN (etype) <= 8)
8568 shCount = SPEC_BSTR (etype);
8570 /* shift left acc */
8573 if (SPEC_BLEN (etype) < 8)
8574 { /* if smaller than a byte */
8580 emitcode ("mov", "b,a");
8581 emitcode ("mov", "a,@%s", rname);
8585 emitcode ("mov", "b,a");
8586 emitcode ("movx", "a,@dptr");
8590 emitcode ("push", "b");
8591 emitcode ("push", "acc");
8592 emitcode ("lcall", "__gptrget");
8593 emitcode ("pop", "b");
8597 emitcode ("anl", "a,#0x%02x", (unsigned char)
8598 ((unsigned char) (0xFF << (blen + bstr)) |
8599 (unsigned char) (0xFF >> (8 - bstr))));
8600 emitcode ("orl", "a,b");
8601 if (p_type == GPOINTER)
8602 emitcode ("pop", "b");
8609 emitcode ("mov", "@%s,a", rname);
8613 emitcode ("movx", "@dptr,a");
8617 emitcode ("lcall", "__gptrput");
8622 if (SPEC_BLEN (etype) <= 8)
8625 emitcode ("inc", "%s", rname);
8626 rLen = SPEC_BLEN (etype);
8628 /* now generate for lengths greater than one byte */
8632 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8644 emitcode ("mov", "@%s,a", rname);
8647 emitcode ("mov", "@%s,%s", rname, l);
8652 emitcode ("movx", "@dptr,a");
8657 emitcode ("lcall", "__gptrput");
8660 emitcode ("inc", "%s", rname);
8665 /* last last was not complete */
8668 /* save the byte & read byte */
8672 emitcode ("mov", "b,a");
8673 emitcode ("mov", "a,@%s", rname);
8677 emitcode ("mov", "b,a");
8678 emitcode ("movx", "a,@dptr");
8682 emitcode ("push", "b");
8683 emitcode ("push", "acc");
8684 emitcode ("lcall", "__gptrget");
8685 emitcode ("pop", "b");
8689 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8690 emitcode ("orl", "a,b");
8693 if (p_type == GPOINTER)
8694 emitcode ("pop", "b");
8700 emitcode ("mov", "@%s,a", rname);
8704 emitcode ("movx", "@dptr,a");
8708 emitcode ("lcall", "__gptrput");
8712 /*-----------------------------------------------------------------*/
8713 /* genDataPointerSet - remat pointer to data space */
8714 /*-----------------------------------------------------------------*/
8716 genDataPointerSet (operand * right,
8720 int size, offset = 0;
8721 char *l, buffer[256];
8723 aopOp (right, ic, FALSE, FALSE);
8725 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8726 size = AOP_SIZE (right);
8730 sprintf (buffer, "(%s + %d)", l + 1, offset);
8732 sprintf (buffer, "%s", l + 1);
8733 emitcode ("mov", "%s,%s", buffer,
8734 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8737 freeAsmop (right, NULL, ic, TRUE);
8738 freeAsmop (result, NULL, ic, TRUE);
8741 /*-----------------------------------------------------------------*/
8742 /* genNearPointerSet - emitcode for near pointer put */
8743 /*-----------------------------------------------------------------*/
8745 genNearPointerSet (operand * right,
8752 sym_link *retype, *letype;
8753 sym_link *ptype = operandType (result);
8755 retype = getSpec (operandType (right));
8756 letype = getSpec (ptype);
8758 aopOp (result, ic, FALSE, FALSE);
8760 /* if the result is rematerializable &
8761 in data space & not a bit variable */
8762 if (AOP_TYPE (result) == AOP_IMMD &&
8763 DCL_TYPE (ptype) == POINTER &&
8764 !IS_BITVAR (retype) &&
8765 !IS_BITVAR (letype))
8767 genDataPointerSet (right, result, ic);
8771 /* if the value is already in a pointer register
8772 then don't need anything more */
8773 if (!AOP_INPREG (AOP (result)))
8775 /* otherwise get a free pointer register */
8777 preg = getFreePtr (ic, &aop, FALSE);
8778 emitcode ("mov", "%s,%s",
8780 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8784 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8786 freeAsmop (result, NULL, ic, TRUE);
8787 aopOp (right, ic, FALSE, FALSE);
8789 /* if bitfield then unpack the bits */
8790 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8791 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8794 /* we have can just get the values */
8795 int size = AOP_SIZE (right);
8800 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8804 emitcode ("mov", "@%s,a", rname);
8807 emitcode ("mov", "@%s,%s", rname, l);
8809 emitcode ("inc", "%s", rname);
8814 /* now some housekeeping stuff */
8817 /* we had to allocate for this iCode */
8818 freeAsmop (NULL, aop, ic, TRUE);
8822 /* we did not allocate which means left
8823 already in a pointer register, then
8824 if size > 0 && this could be used again
8825 we have to point it back to where it
8827 if (AOP_SIZE (right) > 1 &&
8828 !OP_SYMBOL (result)->remat &&
8829 (OP_SYMBOL (result)->liveTo > ic->seq ||
8832 int size = AOP_SIZE (right) - 1;
8834 emitcode ("dec", "%s", rname);
8839 freeAsmop (right, NULL, ic, TRUE);
8844 /*-----------------------------------------------------------------*/
8845 /* genPagedPointerSet - emitcode for Paged pointer put */
8846 /*-----------------------------------------------------------------*/
8848 genPagedPointerSet (operand * right,
8855 sym_link *retype, *letype;
8857 retype = getSpec (operandType (right));
8858 letype = getSpec (operandType (result));
8860 aopOp (result, ic, FALSE, FALSE);
8862 /* if the value is already in a pointer register
8863 then don't need anything more */
8864 if (!AOP_INPREG (AOP (result)))
8866 /* otherwise get a free pointer register */
8868 preg = getFreePtr (ic, &aop, FALSE);
8869 emitcode ("mov", "%s,%s",
8871 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8875 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8877 freeAsmop (result, NULL, ic, TRUE);
8878 aopOp (right, ic, FALSE, FALSE);
8880 /* if bitfield then unpack the bits */
8881 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8882 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8885 /* we have can just get the values */
8886 int size = AOP_SIZE (right);
8891 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8894 emitcode ("movx", "@%s,a", rname);
8897 emitcode ("inc", "%s", rname);
8903 /* now some housekeeping stuff */
8906 /* we had to allocate for this iCode */
8907 freeAsmop (NULL, aop, ic, TRUE);
8911 /* we did not allocate which means left
8912 already in a pointer register, then
8913 if size > 0 && this could be used again
8914 we have to point it back to where it
8916 if (AOP_SIZE (right) > 1 &&
8917 !OP_SYMBOL (result)->remat &&
8918 (OP_SYMBOL (result)->liveTo > ic->seq ||
8921 int size = AOP_SIZE (right) - 1;
8923 emitcode ("dec", "%s", rname);
8928 freeAsmop (right, NULL, ic, TRUE);
8933 /*-----------------------------------------------------------------*/
8934 /* genFarPointerSet - set value from far space */
8935 /*-----------------------------------------------------------------*/
8937 genFarPointerSet (operand * right,
8938 operand * result, iCode * ic)
8941 sym_link *retype = getSpec (operandType (right));
8942 sym_link *letype = getSpec (operandType (result));
8944 aopOp (result, ic, FALSE, FALSE);
8946 /* if the operand is already in dptr
8947 then we do nothing else we move the value to dptr */
8948 if (AOP_TYPE (result) != AOP_STR)
8950 /* if this is remateriazable */
8951 if (AOP_TYPE (result) == AOP_IMMD)
8952 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8955 /* we need to get it byte by byte */
8956 _startLazyDPSEvaluation ();
8957 if (AOP_TYPE (result) != AOP_DPTR)
8959 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8960 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8961 if (options.model == MODEL_FLAT24)
8962 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8966 /* We need to generate a load to DPTR indirect through DPTR. */
8967 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8969 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8970 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8971 if (options.model == MODEL_FLAT24)
8972 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8973 emitcode ("pop", "dph");
8974 emitcode ("pop", "dpl");
8976 _endLazyDPSEvaluation ();
8979 /* so dptr know contains the address */
8980 freeAsmop (result, NULL, ic, TRUE);
8981 aopOp (right, ic, FALSE, TRUE);
8983 /* if bit then unpack */
8984 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8985 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8988 size = AOP_SIZE (right);
8991 _startLazyDPSEvaluation ();
8994 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9000 emitcode ("movx", "@dptr,a");
9002 emitcode ("inc", "dptr");
9004 _endLazyDPSEvaluation ();
9007 freeAsmop (right, NULL, ic, TRUE);
9010 /*-----------------------------------------------------------------*/
9011 /* genGenPointerSet - set value from generic pointer space */
9012 /*-----------------------------------------------------------------*/
9014 genGenPointerSet (operand * right,
9015 operand * result, iCode * ic)
9018 sym_link *retype = getSpec (operandType (right));
9019 sym_link *letype = getSpec (operandType (result));
9021 aopOp (result, ic, FALSE, TRUE);
9023 /* if the operand is already in dptr
9024 then we do nothing else we move the value to dptr */
9025 if (AOP_TYPE (result) != AOP_STR)
9027 _startLazyDPSEvaluation ();
9028 /* if this is remateriazable */
9029 if (AOP_TYPE (result) == AOP_IMMD)
9031 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9032 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9035 { /* we need to get it byte by byte */
9036 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9037 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9038 if (options.model == MODEL_FLAT24) {
9039 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9040 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9042 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9045 _endLazyDPSEvaluation ();
9047 /* so dptr know contains the address */
9048 freeAsmop (result, NULL, ic, TRUE);
9049 aopOp (right, ic, FALSE, TRUE);
9051 /* if bit then unpack */
9052 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9053 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9056 size = AOP_SIZE (right);
9059 _startLazyDPSEvaluation ();
9062 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9068 emitcode ("lcall", "__gptrput");
9070 emitcode ("inc", "dptr");
9072 _endLazyDPSEvaluation ();
9075 freeAsmop (right, NULL, ic, TRUE);
9078 /*-----------------------------------------------------------------*/
9079 /* genPointerSet - stores the value into a pointer location */
9080 /*-----------------------------------------------------------------*/
9082 genPointerSet (iCode * ic)
9084 operand *right, *result;
9085 sym_link *type, *etype;
9088 D (emitcode (";", "genPointerSet ");
9091 right = IC_RIGHT (ic);
9092 result = IC_RESULT (ic);
9094 /* depending on the type of pointer we need to
9095 move it to the correct pointer register */
9096 type = operandType (result);
9097 etype = getSpec (type);
9098 /* if left is of type of pointer then it is simple */
9099 if (IS_PTR (type) && !IS_FUNC (type->next))
9101 p_type = DCL_TYPE (type);
9105 /* we have to go by the storage class */
9106 p_type = PTR_TYPE (SPEC_OCLS (etype));
9109 /* now that we have the pointer type we assign
9110 the pointer values */
9116 genNearPointerSet (right, result, ic);
9120 genPagedPointerSet (right, result, ic);
9124 genFarPointerSet (right, result, ic);
9128 genGenPointerSet (right, result, ic);
9134 /*-----------------------------------------------------------------*/
9135 /* genIfx - generate code for Ifx statement */
9136 /*-----------------------------------------------------------------*/
9138 genIfx (iCode * ic, iCode * popIc)
9140 operand *cond = IC_COND (ic);
9143 D (emitcode (";", "genIfx "););
9145 aopOp (cond, ic, FALSE, FALSE);
9147 /* get the value into acc */
9148 if (AOP_TYPE (cond) != AOP_CRY)
9152 /* the result is now in the accumulator */
9153 freeAsmop (cond, NULL, ic, TRUE);
9155 /* if there was something to be popped then do it */
9159 /* if the condition is a bit variable */
9160 if (isbit && IS_ITEMP (cond) &&
9162 genIfxJump (ic, SPIL_LOC (cond)->rname);
9163 else if (isbit && !IS_ITEMP (cond))
9164 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9166 genIfxJump (ic, "a");
9171 /*-----------------------------------------------------------------*/
9172 /* genAddrOf - generates code for address of */
9173 /*-----------------------------------------------------------------*/
9175 genAddrOf (iCode * ic)
9177 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9180 D (emitcode (";", "genAddrOf ");
9183 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9185 /* if the operand is on the stack then we
9186 need to get the stack offset of this
9190 /* if it has an offset then we need to compute
9194 emitcode ("mov", "a,_bp");
9195 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9196 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9200 /* we can just move _bp */
9201 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9203 /* fill the result with zero */
9204 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9207 if (options.stack10bit && size < (FPTRSIZE - 1))
9210 "*** warning: pointer to stack var truncated.\n");
9217 if (options.stack10bit && offset == 2)
9219 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9223 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9230 /* object not on stack then we need the name */
9231 size = AOP_SIZE (IC_RESULT (ic));
9236 char s[SDCC_NAME_MAX];
9238 sprintf (s, "#(%s >> %d)",
9242 sprintf (s, "#%s", sym->rname);
9243 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9247 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9251 /*-----------------------------------------------------------------*/
9252 /* genArrayInit - generates code for address of */
9253 /*-----------------------------------------------------------------*/
9255 genArrayInit (iCode * ic)
9259 int elementSize = 0, eIndex;
9260 unsigned val, lastVal;
9263 D (emitcode (";", "genArrayInit "););
9265 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9267 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9269 // Load immediate value into DPTR.
9270 emitcode("mov", "dptr, %s",
9271 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9273 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9275 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9276 "Unexpected operand to genArrayInit.\n");
9280 type = operandType(IC_LEFT(ic));
9282 if (type && type->next)
9284 elementSize = getSize(type->next);
9288 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9289 "can't determine element size in genArrayInit.\n");
9293 iLoop = IC_ARRAYILIST(ic);
9298 bool firstpass = TRUE;
9300 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9301 iLoop->count, (int)iLoop->literalValue, elementSize);
9307 symbol *tlbl = NULL;
9309 count = ix > 256 ? 256 : ix;
9313 tlbl = newiTempLabel (NULL);
9314 if (firstpass || (count & 0xff))
9316 emitcode("mov", "b, #0x%x", count & 0xff);
9319 emitcode ("", "%05d$:", tlbl->key + 100);
9324 for (eIndex = 0; eIndex < elementSize; eIndex++)
9326 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9329 emitcode("mov", "a, #0x%x", val);
9333 emitcode("movx", "@dptr, a");
9334 emitcode("inc", "dptr");
9339 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9345 iLoop = iLoop->next;
9348 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9351 /*-----------------------------------------------------------------*/
9352 /* genFarFarAssign - assignment when both are in far space */
9353 /*-----------------------------------------------------------------*/
9355 genFarFarAssign (operand * result, operand * right, iCode * ic)
9357 int size = AOP_SIZE (right);
9359 symbol *rSym = NULL;
9363 /* quick & easy case. */
9364 D(emitcode(";","genFarFarAssign (1 byte case)"););
9365 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9366 freeAsmop (right, NULL, ic, FALSE);
9367 /* now assign DPTR to result */
9369 aopOp(result, ic, FALSE, FALSE);
9371 aopPut(AOP(result), "a", 0);
9372 freeAsmop(result, NULL, ic, FALSE);
9376 /* See if we've got an underlying symbol to abuse. */
9377 if (IS_SYMOP(result) && OP_SYMBOL(result))
9379 if (IS_TRUE_SYMOP(result))
9381 rSym = OP_SYMBOL(result);
9383 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9385 rSym = OP_SYMBOL(result)->usl.spillLoc;
9389 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9391 /* We can use the '390 auto-toggle feature to good effect here. */
9393 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9394 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9395 emitcode ("mov", "dptr,#%s", rSym->rname);
9396 /* DP2 = result, DP1 = right, DP1 is current. */
9399 emitcode("movx", "a,@dptr");
9400 emitcode("movx", "@dptr,a");
9403 emitcode("inc", "dptr");
9404 emitcode("inc", "dptr");
9407 emitcode("mov", "dps, #0");
9408 freeAsmop (right, NULL, ic, FALSE);
9410 some alternative code for processors without auto-toggle
9411 no time to test now, so later well put in...kpb
9412 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9413 emitcode("mov", "dps, #0x01"); /* Select DPTR2. */
9414 emitcode ("mov", "dptr,#%s", rSym->rname);
9415 /* DP2 = result, DP1 = right, DP1 is current. */
9419 emitcode("movx", "a,@dptr");
9421 emitcode("inc", "dptr");
9422 emitcode("inc", "dps");
9423 emitcode("movx", "@dptr,a");
9425 emitcode("inc", "dptr");
9426 emitcode("inc", "dps");
9428 emitcode("mov", "dps, #0");
9429 freeAsmop (right, NULL, ic, FALSE);
9434 D (emitcode (";", "genFarFarAssign"););
9435 aopOp (result, ic, TRUE, TRUE);
9437 _startLazyDPSEvaluation ();
9441 aopPut (AOP (result),
9442 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9445 _endLazyDPSEvaluation ();
9446 freeAsmop (result, NULL, ic, FALSE);
9447 freeAsmop (right, NULL, ic, FALSE);
9451 /*-----------------------------------------------------------------*/
9452 /* genAssign - generate code for assignment */
9453 /*-----------------------------------------------------------------*/
9455 genAssign (iCode * ic)
9457 operand *result, *right;
9459 unsigned long lit = 0L;
9461 D (emitcode (";", "genAssign ");
9464 result = IC_RESULT (ic);
9465 right = IC_RIGHT (ic);
9467 /* if they are the same */
9468 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9471 aopOp (right, ic, FALSE, FALSE);
9473 emitcode (";", "genAssign: resultIsFar = %s",
9474 isOperandInFarSpace (result) ?
9477 /* special case both in far space */
9478 if ((AOP_TYPE (right) == AOP_DPTR ||
9479 AOP_TYPE (right) == AOP_DPTR2) &&
9480 /* IS_TRUE_SYMOP(result) && */
9481 isOperandInFarSpace (result))
9483 genFarFarAssign (result, right, ic);
9487 aopOp (result, ic, TRUE, FALSE);
9489 /* if they are the same registers */
9490 if (sameRegs (AOP (right), AOP (result)))
9493 /* if the result is a bit */
9494 if (AOP_TYPE (result) == AOP_CRY)
9497 /* if the right size is a literal then
9498 we know what the value is */
9499 if (AOP_TYPE (right) == AOP_LIT)
9501 if (((int) operandLitValue (right)))
9502 aopPut (AOP (result), one, 0);
9504 aopPut (AOP (result), zero, 0);
9508 /* the right is also a bit variable */
9509 if (AOP_TYPE (right) == AOP_CRY)
9511 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9512 aopPut (AOP (result), "c", 0);
9518 aopPut (AOP (result), "a", 0);
9522 /* bit variables done */
9524 size = AOP_SIZE (result);
9526 if (AOP_TYPE (right) == AOP_LIT)
9527 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9530 (AOP_TYPE (result) != AOP_REG) &&
9531 (AOP_TYPE (right) == AOP_LIT) &&
9532 !IS_FLOAT (operandType (right)))
9534 _startLazyDPSEvaluation ();
9535 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9537 aopPut (AOP (result),
9538 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9543 /* And now fill the rest with zeros. */
9546 emitcode ("clr", "a");
9550 aopPut (AOP (result), "a", offset++);
9552 _endLazyDPSEvaluation ();
9556 _startLazyDPSEvaluation ();
9559 aopPut (AOP (result),
9560 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9564 _endLazyDPSEvaluation ();
9568 freeAsmop (right, NULL, ic, FALSE);
9569 freeAsmop (result, NULL, ic, TRUE);
9572 /*-----------------------------------------------------------------*/
9573 /* genJumpTab - generates code for jump table */
9574 /*-----------------------------------------------------------------*/
9576 genJumpTab (iCode * ic)
9581 D (emitcode (";", "genJumpTab ");
9584 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9585 /* get the condition into accumulator */
9586 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9588 /* multiply by four! */
9589 emitcode ("add", "a,acc");
9590 emitcode ("add", "a,acc");
9591 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9593 jtab = newiTempLabel (NULL);
9594 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9595 emitcode ("jmp", "@a+dptr");
9596 emitcode ("", "%05d$:", jtab->key + 100);
9597 /* now generate the jump labels */
9598 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9599 jtab = setNextItem (IC_JTLABELS (ic)))
9600 emitcode ("ljmp", "%05d$", jtab->key + 100);
9604 /*-----------------------------------------------------------------*/
9605 /* genCast - gen code for casting */
9606 /*-----------------------------------------------------------------*/
9608 genCast (iCode * ic)
9610 operand *result = IC_RESULT (ic);
9611 sym_link *ctype = operandType (IC_LEFT (ic));
9612 sym_link *rtype = operandType (IC_RIGHT (ic));
9613 operand *right = IC_RIGHT (ic);
9616 D (emitcode (";", "genCast ");
9619 /* if they are equivalent then do nothing */
9620 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9623 aopOp (right, ic, FALSE, FALSE);
9624 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9626 /* if the result is a bit */
9627 if (AOP_TYPE (result) == AOP_CRY)
9629 /* if the right size is a literal then
9630 we know what the value is */
9631 if (AOP_TYPE (right) == AOP_LIT)
9633 if (((int) operandLitValue (right)))
9634 aopPut (AOP (result), one, 0);
9636 aopPut (AOP (result), zero, 0);
9641 /* the right is also a bit variable */
9642 if (AOP_TYPE (right) == AOP_CRY)
9644 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9645 aopPut (AOP (result), "c", 0);
9651 aopPut (AOP (result), "a", 0);
9655 /* if they are the same size : or less */
9656 if (AOP_SIZE (result) <= AOP_SIZE (right))
9659 /* if they are in the same place */
9660 if (sameRegs (AOP (right), AOP (result)))
9663 /* if they in different places then copy */
9664 size = AOP_SIZE (result);
9666 _startLazyDPSEvaluation ();
9669 aopPut (AOP (result),
9670 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9674 _endLazyDPSEvaluation ();
9679 /* if the result is of type pointer */
9684 sym_link *type = operandType (right);
9686 /* pointer to generic pointer */
9687 if (IS_GENPTR (ctype))
9693 p_type = DCL_TYPE (type);
9697 #if OLD_CAST_BEHAVIOR
9698 /* KV: we are converting a non-pointer type to
9699 * a generic pointer. This (ifdef'd out) code
9700 * says that the resulting generic pointer
9701 * should have the same class as the storage
9702 * location of the non-pointer variable.
9704 * For example, converting an int (which happens
9705 * to be stored in DATA space) to a pointer results
9706 * in a DATA generic pointer; if the original int
9707 * in XDATA space, so will be the resulting pointer.
9709 * I don't like that behavior, and thus this change:
9710 * all such conversions will be forced to XDATA and
9711 * throw a warning. If you want some non-XDATA
9712 * type, or you want to suppress the warning, you
9713 * must go through an intermediate cast, like so:
9715 * char _generic *gp = (char _xdata *)(intVar);
9717 sym_link *etype = getSpec (type);
9719 /* we have to go by the storage class */
9720 if (SPEC_OCLS (etype) != generic)
9722 p_type = PTR_TYPE (SPEC_OCLS (etype));
9727 /* Converting unknown class (i.e. register variable)
9728 * to generic pointer. This is not good, but
9729 * we'll make a guess (and throw a warning).
9732 werror (W_INT_TO_GEN_PTR_CAST);
9736 /* the first two bytes are known */
9737 size = GPTRSIZE - 1;
9739 _startLazyDPSEvaluation ();
9742 aopPut (AOP (result),
9743 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9747 _endLazyDPSEvaluation ();
9749 /* the last byte depending on type */
9767 /* this should never happen */
9768 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9769 "got unknown pointer type");
9772 aopPut (AOP (result), l, GPTRSIZE - 1);
9776 /* just copy the pointers */
9777 size = AOP_SIZE (result);
9779 _startLazyDPSEvaluation ();
9782 aopPut (AOP (result),
9783 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9787 _endLazyDPSEvaluation ();
9791 /* so we now know that the size of destination is greater
9792 than the size of the source */
9793 /* we move to result for the size of source */
9794 size = AOP_SIZE (right);
9796 _startLazyDPSEvaluation ();
9799 aopPut (AOP (result),
9800 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9804 _endLazyDPSEvaluation ();
9806 /* now depending on the sign of the source && destination */
9807 size = AOP_SIZE (result) - AOP_SIZE (right);
9808 /* if unsigned or not an integral type */
9809 /* also, if the source is a bit, we don't need to sign extend, because
9810 * it can't possibly have set the sign bit.
9812 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9816 aopPut (AOP (result), zero, offset++);
9821 /* we need to extend the sign :{ */
9822 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9823 FALSE, FALSE, TRUE);
9825 emitcode ("rlc", "a");
9826 emitcode ("subb", "a,acc");
9828 aopPut (AOP (result), "a", offset++);
9831 /* we are done hurray !!!! */
9834 freeAsmop (right, NULL, ic, TRUE);
9835 freeAsmop (result, NULL, ic, TRUE);
9839 /*-----------------------------------------------------------------*/
9840 /* genDjnz - generate decrement & jump if not zero instrucion */
9841 /*-----------------------------------------------------------------*/
9843 genDjnz (iCode * ic, iCode * ifx)
9849 /* if the if condition has a false label
9850 then we cannot save */
9854 /* if the minus is not of the form
9856 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9857 !IS_OP_LITERAL (IC_RIGHT (ic)))
9860 if (operandLitValue (IC_RIGHT (ic)) != 1)
9863 /* if the size of this greater than one then no
9865 if (getSize (operandType (IC_RESULT (ic))) > 1)
9868 /* otherwise we can save BIG */
9869 D(emitcode(";", "genDjnz"););
9871 lbl = newiTempLabel (NULL);
9872 lbl1 = newiTempLabel (NULL);
9874 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9876 if (AOP_NEEDSACC(IC_RESULT(ic)))
9878 /* If the result is accessed indirectly via
9879 * the accumulator, we must explicitly write
9880 * it back after the decrement.
9882 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9884 if (strcmp(rByte, "a"))
9886 /* Something is hopelessly wrong */
9887 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9888 __FILE__, __LINE__);
9889 /* We can just give up; the generated code will be inefficient,
9892 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9895 emitcode ("dec", "%s", rByte);
9896 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9897 emitcode ("jnz", "%05d$", lbl->key + 100);
9899 else if (IS_AOP_PREG (IC_RESULT (ic)))
9901 emitcode ("dec", "%s",
9902 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9903 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9904 emitcode ("jnz", "%05d$", lbl->key + 100);
9908 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9911 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9912 emitcode ("", "%05d$:", lbl->key + 100);
9913 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9914 emitcode ("", "%05d$:", lbl1->key + 100);
9916 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9921 /*-----------------------------------------------------------------*/
9922 /* genReceive - generate code for a receive iCode */
9923 /*-----------------------------------------------------------------*/
9925 genReceive (iCode * ic)
9928 D (emitcode (";", "genReceive ");
9931 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9932 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9933 IS_TRUE_SYMOP (IC_RESULT (ic))))
9935 int size = getSize (operandType (IC_RESULT (ic)));
9936 int offset = fReturnSizeDS390 - size;
9939 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9940 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9943 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9944 size = AOP_SIZE (IC_RESULT (ic));
9948 emitcode ("pop", "acc");
9949 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9956 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9958 assignResultValue (IC_RESULT (ic));
9961 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9964 /*-----------------------------------------------------------------*/
9965 /* gen390Code - generate code for Dallas 390 based controllers */
9966 /*-----------------------------------------------------------------*/
9968 gen390Code (iCode * lic)
9973 lineHead = lineCurr = NULL;
9975 if (options.model == MODEL_FLAT24) {
9976 fReturnSizeDS390 = 5;
9977 fReturn = fReturn24;
9979 fReturnSizeDS390 = 4;
9980 fReturn = fReturn16;
9981 options.stack10bit=0;
9985 /* print the allocation information */
9987 printAllocInfo (currFunc, codeOutFile);
9989 /* if debug information required */
9990 if (options.debug && currFunc)
9992 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9994 if (IS_STATIC (currFunc->etype))
9995 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9997 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10000 /* stack pointer name */
10001 if (options.useXstack)
10007 for (ic = lic; ic; ic = ic->next)
10010 if (cln != ic->lineno)
10015 emitcode ("", "C$%s$%d$%d$%d ==.",
10016 FileBaseName (ic->filename), ic->lineno,
10017 ic->level, ic->block);
10020 emitcode (";", "%s %d", ic->filename, ic->lineno);
10023 /* if the result is marked as
10024 spilt and rematerializable or code for
10025 this has already been generated then
10027 if (resultRemat (ic) || ic->generated)
10030 /* depending on the operation */
10050 /* IPOP happens only when trying to restore a
10051 spilt live range, if there is an ifx statement
10052 following this pop then the if statement might
10053 be using some of the registers being popped which
10054 would destory the contents of the register so
10055 we need to check for this condition and handle it */
10057 ic->next->op == IFX &&
10058 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10059 genIfx (ic->next, ic);
10077 genEndFunction (ic);
10097 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10114 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10118 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10125 /* note these two are xlated by algebraic equivalence
10126 during parsing SDCC.y */
10127 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10128 "got '>=' or '<=' shouldn't have come here");
10132 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10144 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10148 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10152 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10176 genRightShift (ic);
10179 case GET_VALUE_AT_ADDRESS:
10180 genPointerGet (ic);
10184 if (POINTER_SET (ic))
10185 genPointerSet (ic);
10211 addSet (&_G.sendSet, ic);
10224 /* now we are ready to call the
10225 peep hole optimizer */
10226 if (!options.nopeep)
10227 peepHole (&lineHead);
10229 /* now do the actual printing */
10230 printLine (lineHead, codeOutFile);