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 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
67 static char *fReturn24[] =
68 {"dpl", "dph", "dpx", "b", "a"};
69 static char *fReturn16[] =
70 {"dpl", "dph", "b", "a"};
71 static char **fReturn = fReturn24;
72 static char *accUse[] =
75 static short rbank = -1;
89 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
96 #define MOVA(x) { char *_mova_tmp = strdup(x); \
97 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
99 emitcode("mov","a,%s",_mova_tmp); \
103 #define CLRC emitcode("clr","c")
104 #define SETC emitcode("setb","c")
106 // A scratch register which will be used to hold
107 // result bytes from operands in far space via DPTR2.
108 #define DP2_RESULT_REG "ap"
110 static lineNode *lineHead = NULL;
111 static lineNode *lineCurr = NULL;
113 static unsigned char SLMask[] =
114 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
115 0xE0, 0xC0, 0x80, 0x00};
116 static unsigned char SRMask[] =
117 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
118 0x07, 0x03, 0x01, 0x00};
125 /*-----------------------------------------------------------------*/
126 /* emitcode - writes the code into a file : for now it is simple */
127 /*-----------------------------------------------------------------*/
129 emitcode (char *inst, char *fmt,...)
132 char lb[INITIAL_INLINEASM];
140 sprintf (lb, "%s\t", inst);
142 sprintf (lb, "%s", inst);
143 vsprintf (lb + (strlen (lb)), fmt, ap);
146 vsprintf (lb, fmt, ap);
148 while (isspace (*lbp))
152 lineCurr = (lineCurr ?
153 connectLine (lineCurr, newLineNode (lb)) :
154 (lineHead = newLineNode (lb)));
155 lineCurr->isInline = _G.inLine;
156 lineCurr->isDebug = _G.debugLine;
160 /*-----------------------------------------------------------------*/
161 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
162 /*-----------------------------------------------------------------*/
164 getFreePtr (iCode * ic, asmop ** aopp, bool result)
166 bool r0iu = FALSE, r1iu = FALSE;
167 bool r0ou = FALSE, r1ou = FALSE;
169 /* the logic: if r0 & r1 used in the instruction
170 then we are in trouble otherwise */
172 /* first check if r0 & r1 are used by this
173 instruction, in which case we are in trouble */
174 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
175 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
180 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
181 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
183 /* if no usage of r0 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
187 (*aopp)->type = AOP_R0;
189 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
192 /* if no usage of r1 then return it */
195 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
196 (*aopp)->type = AOP_R1;
198 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
201 /* now we know they both have usage */
202 /* if r0 not used in this instruction */
205 /* push it if not already pushed */
208 emitcode ("push", "%s",
209 ds390_regWithIdx (R0_IDX)->dname);
213 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
214 (*aopp)->type = AOP_R0;
216 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
219 /* if r1 not used then */
223 /* push it if not already pushed */
226 emitcode ("push", "%s",
227 ds390_regWithIdx (R1_IDX)->dname);
231 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
232 (*aopp)->type = AOP_R1;
233 return ds390_regWithIdx (R1_IDX);
237 /* I said end of world but not quite end of world yet */
238 /* if this is a result then we can push it on the stack */
241 (*aopp)->type = AOP_STK;
245 /* other wise this is true end of the world */
246 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
247 "getFreePtr should never reach here");
251 /*-----------------------------------------------------------------*/
252 /* newAsmop - creates a new asmOp */
253 /*-----------------------------------------------------------------*/
255 newAsmop (short type)
259 aop = Safe_calloc (1, sizeof (asmop));
264 static int _currentDPS; /* Current processor DPS. */
265 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
266 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
268 /*-----------------------------------------------------------------*/
269 /* genSetDPTR: generate code to select which DPTR is in use (zero */
270 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
271 /* alternate DPTR (DPL1/DPH1/DPX1). */
272 /*-----------------------------------------------------------------*/
277 /* If we are doing lazy evaluation, simply note the desired
278 * change, but don't emit any code yet.
288 emitcode ("mov", "dps, #0x00");
292 emitcode ("mov", "dps, #0x01");
296 /*-----------------------------------------------------------------*/
297 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
299 /* Any code that operates on DPTR (NB: not on the individual */
300 /* components, like DPH) *must* call _flushLazyDPS() before using */
301 /* DPTR within a lazy DPS evaluation block. */
303 /* Note that aopPut and aopGet already contain the proper calls to */
304 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
305 /* DPS evaluation block. */
307 /* Also, _flushLazyDPS must be called before any flow control */
308 /* operations that could potentially branch out of the block. */
310 /* Lazy DPS evaluation is simply an optimization (though an */
311 /* important one), so if in doubt, leave it out. */
312 /*-----------------------------------------------------------------*/
314 _startLazyDPSEvaluation (void)
318 #ifdef BETTER_LITERAL_SHIFT
325 /*-----------------------------------------------------------------*/
326 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
327 /* desired one. Call before using DPTR within a lazy DPS evaluation */
329 /*-----------------------------------------------------------------*/
339 if (_desiredDPS != _currentDPS)
343 emitcode ("inc", "dps");
347 emitcode ("dec", "dps");
349 _currentDPS = _desiredDPS;
353 /*-----------------------------------------------------------------*/
354 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
356 /* Forces us back to the safe state (standard DPTR selected). */
357 /*-----------------------------------------------------------------*/
359 _endLazyDPSEvaluation (void)
361 #ifdef BETTER_LITERAL_SHIFT
380 /*-----------------------------------------------------------------*/
381 /* pointerCode - returns the code for a pointer type */
382 /*-----------------------------------------------------------------*/
384 pointerCode (sym_link * etype)
387 return PTR_TYPE (SPEC_OCLS (etype));
391 /*-----------------------------------------------------------------*/
392 /* aopForSym - for a true symbol */
393 /*-----------------------------------------------------------------*/
395 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
398 memmap *space = SPEC_OCLS (sym->etype);
400 /* if already has one */
404 /* assign depending on the storage class */
405 /* if it is on the stack or indirectly addressable */
406 /* space we need to assign either r0 or r1 to it */
407 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
409 sym->aop = aop = newAsmop (0);
410 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
411 aop->size = getSize (sym->type);
413 /* now assign the address of the variable to
414 the pointer register */
415 if (aop->type != AOP_STK)
421 emitcode ("push", "acc");
423 emitcode ("mov", "a,_bp");
424 emitcode ("add", "a,#0x%02x",
426 ((char) (sym->stack - _G.nRegsSaved)) :
427 ((char) sym->stack)) & 0xff);
428 emitcode ("mov", "%s,a",
429 aop->aopu.aop_ptr->name);
432 emitcode ("pop", "acc");
435 emitcode ("mov", "%s,#%s",
436 aop->aopu.aop_ptr->name,
438 aop->paged = space->paged;
441 aop->aopu.aop_stk = sym->stack;
445 if (sym->onStack && options.stack10bit)
447 /* It's on the 10 bit stack, which is located in
452 emitcode ("push", "acc");
454 emitcode ("mov", "a,_bp");
455 emitcode ("add", "a,#0x%02x",
457 ((char) (sym->stack - _G.nRegsSaved)) :
458 ((char) sym->stack)) & 0xff);
462 if (options.model == MODEL_FLAT24)
463 emitcode ("mov", "dpx1,#0x40");
464 emitcode ("mov", "dph1,#0x00");
465 emitcode ("mov", "dpl1, a");
469 if (options.model == MODEL_FLAT24)
470 emitcode ("mov", "dpx,#0x40");
471 emitcode ("mov", "dph,#0x00");
472 emitcode ("mov", "dpl, a");
476 emitcode ("pop", "acc");
478 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
479 aop->size = getSize (sym->type);
483 /* if in bit space */
484 if (IN_BITSPACE (space))
486 sym->aop = aop = newAsmop (AOP_CRY);
487 aop->aopu.aop_dir = sym->rname;
488 aop->size = getSize (sym->type);
491 /* if it is in direct space */
492 if (IN_DIRSPACE (space))
494 sym->aop = aop = newAsmop (AOP_DIR);
495 aop->aopu.aop_dir = sym->rname;
496 aop->size = getSize (sym->type);
500 /* special case for a function */
501 if (IS_FUNC (sym->type))
503 sym->aop = aop = newAsmop (AOP_IMMD);
504 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
505 strcpy (aop->aopu.aop_immd, sym->rname);
506 aop->size = FPTRSIZE;
510 /* only remaining is far space */
511 /* in which case DPTR gets the address */
512 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
517 emitcode ("mov", "dptr,#%s", sym->rname);
522 emitcode ("mov", "dptr,#%s", sym->rname);
524 aop->size = getSize (sym->type);
526 /* if it is in code space */
527 if (IN_CODESPACE (space))
533 /*-----------------------------------------------------------------*/
534 /* aopForRemat - rematerialzes an object */
535 /*-----------------------------------------------------------------*/
537 aopForRemat (symbol * sym)
539 iCode *ic = sym->rematiCode;
540 asmop *aop = newAsmop (AOP_IMMD);
547 val += (int) operandLitValue (IC_RIGHT (ic));
548 else if (ic->op == '-')
549 val -= (int) operandLitValue (IC_RIGHT (ic));
553 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
557 sprintf (buffer, "(%s %c 0x%04x)",
558 OP_SYMBOL (IC_LEFT (ic))->rname,
559 val >= 0 ? '+' : '-',
562 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
564 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
565 strcpy (aop->aopu.aop_immd, buffer);
569 /*-----------------------------------------------------------------*/
570 /* regsInCommon - two operands have some registers in common */
571 /*-----------------------------------------------------------------*/
573 regsInCommon (operand * op1, operand * op2)
578 /* if they have registers in common */
579 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
582 sym1 = OP_SYMBOL (op1);
583 sym2 = OP_SYMBOL (op2);
585 if (sym1->nRegs == 0 || sym2->nRegs == 0)
588 for (i = 0; i < sym1->nRegs; i++)
594 for (j = 0; j < sym2->nRegs; j++)
599 if (sym2->regs[j] == sym1->regs[i])
607 /*-----------------------------------------------------------------*/
608 /* operandsEqu - equivalent */
609 /*-----------------------------------------------------------------*/
611 operandsEqu (operand * op1, operand * op2)
615 /* if they not symbols */
616 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
619 sym1 = OP_SYMBOL (op1);
620 sym2 = OP_SYMBOL (op2);
622 /* if both are itemps & one is spilt
623 and the other is not then false */
624 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
625 sym1->isspilt != sym2->isspilt)
628 /* if they are the same */
632 if (strcmp (sym1->rname, sym2->rname) == 0)
636 /* if left is a tmp & right is not */
637 if (IS_ITEMP (op1) &&
640 (sym1->usl.spillLoc == sym2))
643 if (IS_ITEMP (op2) &&
647 (sym2->usl.spillLoc == sym1))
653 /*-----------------------------------------------------------------*/
654 /* sameRegs - two asmops have the same registers */
655 /*-----------------------------------------------------------------*/
657 sameRegs (asmop * aop1, asmop * aop2)
663 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
670 if (aop1->type != AOP_REG ||
671 aop2->type != AOP_REG)
674 if (aop1->size != aop2->size)
677 for (i = 0; i < aop1->size; i++)
678 if (aop1->aopu.aop_reg[i] !=
679 aop2->aopu.aop_reg[i])
685 /*-----------------------------------------------------------------*/
686 /* aopOp - allocates an asmop for an operand : */
687 /*-----------------------------------------------------------------*/
689 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
698 /* if this a literal */
699 if (IS_OP_LITERAL (op))
701 op->aop = aop = newAsmop (AOP_LIT);
702 aop->aopu.aop_lit = op->operand.valOperand;
703 aop->size = getSize (operandType (op));
707 /* if already has a asmop then continue */
711 /* if the underlying symbol has a aop */
712 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
714 op->aop = OP_SYMBOL (op)->aop;
718 /* if this is a true symbol */
719 if (IS_TRUE_SYMOP (op))
721 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
725 /* this is a temporary : this has
731 e) can be a return use only */
733 sym = OP_SYMBOL (op);
736 /* if the type is a conditional */
737 if (sym->regType == REG_CND)
739 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
744 /* if it is spilt then two situations
746 b) has a spill location */
747 if (sym->isspilt || sym->nRegs == 0)
750 /* rematerialize it NOW */
753 sym->aop = op->aop = aop =
755 aop->size = getSize (sym->type);
762 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
763 aop->size = getSize (sym->type);
764 for (i = 0; i < 2; i++)
765 aop->aopu.aop_str[i] = accUse[i];
775 /* a AOP_STR uses DPTR, but DPTR is already in use;
778 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
781 aop = op->aop = sym->aop = newAsmop (AOP_STR);
782 aop->size = getSize (sym->type);
783 for (i = 0; i < (int) fReturnSizeDS390; i++)
784 aop->aopu.aop_str[i] = fReturn[i];
788 /* else spill location */
789 sym->aop = op->aop = aop =
790 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
791 aop->size = getSize (sym->type);
795 /* must be in a register */
796 sym->aop = op->aop = aop = newAsmop (AOP_REG);
797 aop->size = sym->nRegs;
798 for (i = 0; i < sym->nRegs; i++)
799 aop->aopu.aop_reg[i] = sym->regs[i];
802 /*-----------------------------------------------------------------*/
803 /* freeAsmop - free up the asmop given to an operand */
804 /*----------------------------------------------------------------*/
806 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
823 /* depending on the asmop type only three cases need work AOP_RO
824 , AOP_R1 && AOP_STK */
832 emitcode ("pop", "ar0");
836 bitVectUnSetBit (ic->rUsed, R0_IDX);
844 emitcode ("pop", "ar1");
848 bitVectUnSetBit (ic->rUsed, R1_IDX);
854 int stk = aop->aopu.aop_stk + aop->size;
855 bitVectUnSetBit (ic->rUsed, R0_IDX);
856 bitVectUnSetBit (ic->rUsed, R1_IDX);
858 getFreePtr (ic, &aop, FALSE);
860 if (options.stack10bit)
862 /* I'm not sure what to do here yet... */
865 "*** Warning: probably generating bad code for "
866 "10 bit stack mode.\n");
871 emitcode ("mov", "a,_bp");
872 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
873 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
877 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
882 emitcode ("pop", "acc");
883 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
886 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
889 freeAsmop (op, NULL, ic, TRUE);
892 emitcode ("pop", "ar0");
898 emitcode ("pop", "ar1");
905 /* all other cases just dealloc */
911 OP_SYMBOL (op)->aop = NULL;
912 /* if the symbol has a spill */
914 SPIL_LOC (op)->aop = NULL;
919 /*------------------------------------------------------------------*/
920 /* aopGet - for fetching value of the aop */
922 /* Set canClobberACC if you are sure it is OK to clobber the value */
923 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
924 /* just less efficient. */
925 /*------------------------------------------------------------------*/
937 /* offset is greater than
939 if (offset > (aop->size - 1) &&
940 aop->type != AOP_LIT)
943 /* depending on type */
949 /* if we need to increment it */
950 while (offset > aop->coff)
952 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
956 while (offset < aop->coff)
958 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
965 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
966 return (dname ? "acc" : "a");
968 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
969 rs = Safe_calloc (1, strlen (s) + 1);
976 if (aop->type == AOP_DPTR2)
981 emitcode ("xch", "a, %s", DP2_RESULT_REG);
987 while (offset > aop->coff)
989 emitcode ("inc", "dptr");
993 while (offset < aop->coff)
995 emitcode ("lcall", "__decdptr");
1002 emitcode ("clr", "a");
1003 emitcode ("movc", "a,@a+dptr");
1007 emitcode ("movx", "a,@dptr");
1010 if (aop->type == AOP_DPTR2)
1015 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1016 return DP2_RESULT_REG;
1019 return (dname ? "acc" : "a");
1023 sprintf (s, "#%s", aop->aopu.aop_immd);
1025 sprintf (s, "#(%s >> %d)",
1030 aop->aopu.aop_immd);
1031 rs = Safe_calloc (1, strlen (s) + 1);
1037 sprintf (s, "(%s + %d)",
1041 sprintf (s, "%s", aop->aopu.aop_dir);
1042 rs = Safe_calloc (1, strlen (s) + 1);
1048 return aop->aopu.aop_reg[offset]->dname;
1050 return aop->aopu.aop_reg[offset]->name;
1053 emitcode ("clr", "a");
1054 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1055 emitcode ("rlc", "a");
1056 return (dname ? "acc" : "a");
1059 if (!offset && dname)
1061 return aop->aopu.aop_str[offset];
1064 return aopLiteral (aop->aopu.aop_lit, offset);
1068 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1072 return aop->aopu.aop_str[offset];
1076 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1077 "aopget got unsupported aop->type");
1080 /*-----------------------------------------------------------------*/
1081 /* aopPut - puts a string for a aop */
1082 /*-----------------------------------------------------------------*/
1084 aopPut (asmop * aop, char *s, int offset)
1088 if (aop->size && offset > (aop->size - 1))
1090 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1091 "aopPut got offset > aop->size");
1095 /* will assign value to value */
1096 /* depending on where it is ofcourse */
1101 sprintf (d, "(%s + %d)",
1102 aop->aopu.aop_dir, offset);
1104 sprintf (d, "%s", aop->aopu.aop_dir);
1107 emitcode ("mov", "%s,%s", d, s);
1112 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1113 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1116 strcmp (s, "r0") == 0 ||
1117 strcmp (s, "r1") == 0 ||
1118 strcmp (s, "r2") == 0 ||
1119 strcmp (s, "r3") == 0 ||
1120 strcmp (s, "r4") == 0 ||
1121 strcmp (s, "r5") == 0 ||
1122 strcmp (s, "r6") == 0 ||
1123 strcmp (s, "r7") == 0)
1124 emitcode ("mov", "%s,%s",
1125 aop->aopu.aop_reg[offset]->dname, s);
1127 emitcode ("mov", "%s,%s",
1128 aop->aopu.aop_reg[offset]->name, s);
1135 if (aop->type == AOP_DPTR2)
1143 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1144 "aopPut writting to code space");
1148 while (offset > aop->coff)
1151 emitcode ("inc", "dptr");
1154 while (offset < aop->coff)
1157 emitcode ("lcall", "__decdptr");
1162 /* if not in accumulater */
1165 emitcode ("movx", "@dptr,a");
1167 if (aop->type == AOP_DPTR2)
1175 while (offset > aop->coff)
1178 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1180 while (offset < aop->coff)
1183 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1190 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1196 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1198 else if (strcmp (s, "r0") == 0 ||
1199 strcmp (s, "r1") == 0 ||
1200 strcmp (s, "r2") == 0 ||
1201 strcmp (s, "r3") == 0 ||
1202 strcmp (s, "r4") == 0 ||
1203 strcmp (s, "r5") == 0 ||
1204 strcmp (s, "r6") == 0 ||
1205 strcmp (s, "r7") == 0)
1208 sprintf (buffer, "a%s", s);
1209 emitcode ("mov", "@%s,%s",
1210 aop->aopu.aop_ptr->name, buffer);
1213 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1218 if (strcmp (s, "a") == 0)
1219 emitcode ("push", "acc");
1221 emitcode ("push", "%s", s);
1226 /* if bit variable */
1227 if (!aop->aopu.aop_dir)
1229 emitcode ("clr", "a");
1230 emitcode ("rlc", "a");
1235 emitcode ("clr", "%s", aop->aopu.aop_dir);
1237 emitcode ("setb", "%s", aop->aopu.aop_dir);
1238 else if (!strcmp (s, "c"))
1239 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1242 if (strcmp (s, "a"))
1247 symbol *lbl = newiTempLabel (NULL);
1248 emitcode ("clr", "c");
1249 emitcode ("jz", "%05d$", lbl->key + 100);
1250 emitcode ("cpl", "c");
1251 emitcode ("", "%05d$:", lbl->key + 100);
1252 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1260 if (strcmp (aop->aopu.aop_str[offset], s))
1261 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1266 if (!offset && (strcmp (s, "acc") == 0))
1269 if (strcmp (aop->aopu.aop_str[offset], s))
1270 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1274 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1275 "aopPut got unsupported aop->type");
1282 /*--------------------------------------------------------------------*/
1283 /* reAdjustPreg - points a register back to where it should (coff==0) */
1284 /*--------------------------------------------------------------------*/
1286 reAdjustPreg (asmop * aop)
1288 if ((aop->coff==0) || (aop->size <= 1)) {
1297 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1301 if (aop->type == AOP_DPTR2)
1308 emitcode ("lcall", "__decdptr");
1311 if (aop->type == AOP_DPTR2)
1321 #define AOP(op) op->aop
1322 #define AOP_TYPE(op) AOP(op)->type
1323 #define AOP_SIZE(op) AOP(op)->size
1324 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1325 AOP_TYPE(x) == AOP_R0))
1327 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1328 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1331 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1332 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1333 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1335 /* Workaround for DS80C390 bug: div ab may return bogus results
1336 * if A is accessed in instruction immediately before the div.
1338 * Will be fixed in B4 rev of processor, Dallas claims.
1341 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1342 if (!AOP_NEEDSACC(RIGHT)) \
1344 /* We can load A first, then B, since \
1345 * B (the RIGHT operand) won't clobber A, \
1346 * thus avoiding touching A right before the div. \
1348 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1349 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1351 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1355 /* Just stuff in a nop after loading A. */ \
1356 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1357 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1359 emitcode("nop", "; workaround for DS80C390 div bug."); \
1362 /*-----------------------------------------------------------------*/
1363 /* genNotFloat - generates not for float operations */
1364 /*-----------------------------------------------------------------*/
1366 genNotFloat (operand * op, operand * res)
1372 D (emitcode (";", "genNotFloat ");
1375 /* we will put 127 in the first byte of
1377 aopPut (AOP (res), "#127", 0);
1378 size = AOP_SIZE (op) - 1;
1381 _startLazyDPSEvaluation ();
1382 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1387 emitcode ("orl", "a,%s",
1389 offset++, FALSE, FALSE, FALSE));
1391 _endLazyDPSEvaluation ();
1393 tlbl = newiTempLabel (NULL);
1394 aopPut (res->aop, one, 1);
1395 emitcode ("jz", "%05d$", (tlbl->key + 100));
1396 aopPut (res->aop, zero, 1);
1397 emitcode ("", "%05d$:", (tlbl->key + 100));
1399 size = res->aop->size - 2;
1401 /* put zeros in the rest */
1403 aopPut (res->aop, zero, offset++);
1406 /*-----------------------------------------------------------------*/
1407 /* opIsGptr: returns non-zero if the passed operand is */
1408 /* a generic pointer type. */
1409 /*-----------------------------------------------------------------*/
1411 opIsGptr (operand * op)
1413 sym_link *type = operandType (op);
1415 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1422 /*-----------------------------------------------------------------*/
1423 /* getDataSize - get the operand data size */
1424 /*-----------------------------------------------------------------*/
1426 getDataSize (operand * op)
1429 size = AOP_SIZE (op);
1430 if (size == GPTRSIZE)
1432 sym_link *type = operandType (op);
1433 if (IS_GENPTR (type))
1435 /* generic pointer; arithmetic operations
1436 * should ignore the high byte (pointer type).
1444 /*-----------------------------------------------------------------*/
1445 /* outAcc - output Acc */
1446 /*-----------------------------------------------------------------*/
1448 outAcc (operand * result)
1451 size = getDataSize (result);
1454 aopPut (AOP (result), "a", 0);
1457 /* unsigned or positive */
1460 aopPut (AOP (result), zero, offset++);
1465 /*-----------------------------------------------------------------*/
1466 /* outBitC - output a bit C */
1467 /*-----------------------------------------------------------------*/
1469 outBitC (operand * result)
1471 /* if the result is bit */
1472 if (AOP_TYPE (result) == AOP_CRY)
1474 aopPut (AOP (result), "c", 0);
1478 emitcode ("clr", "a");
1479 emitcode ("rlc", "a");
1484 /*-----------------------------------------------------------------*/
1485 /* toBoolean - emit code for orl a,operator(sizeop) */
1486 /*-----------------------------------------------------------------*/
1488 toBoolean (operand * oper)
1490 int size = AOP_SIZE (oper) - 1;
1494 /* The generic part of a generic pointer should
1495 * not participate in it's truth value.
1497 * i.e. 0x10000000 is zero.
1499 if (opIsGptr (oper))
1501 D (emitcode (";", "toBoolean: generic ptr special case.");
1506 _startLazyDPSEvaluation ();
1507 if (AOP_NEEDSACC (oper) && size)
1510 emitcode ("push", "b");
1511 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1515 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1521 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1525 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1528 _endLazyDPSEvaluation ();
1532 emitcode ("mov", "a,b");
1533 emitcode ("pop", "b");
1538 /*-----------------------------------------------------------------*/
1539 /* genNot - generate code for ! operation */
1540 /*-----------------------------------------------------------------*/
1545 sym_link *optype = operandType (IC_LEFT (ic));
1547 D (emitcode (";", "genNot ");
1550 /* assign asmOps to operand & result */
1551 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1552 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1554 /* if in bit space then a special case */
1555 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1557 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1558 emitcode ("cpl", "c");
1559 outBitC (IC_RESULT (ic));
1563 /* if type float then do float */
1564 if (IS_FLOAT (optype))
1566 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1570 toBoolean (IC_LEFT (ic));
1572 tlbl = newiTempLabel (NULL);
1573 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1574 emitcode ("", "%05d$:", tlbl->key + 100);
1575 outBitC (IC_RESULT (ic));
1578 /* release the aops */
1579 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1580 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1584 /*-----------------------------------------------------------------*/
1585 /* genCpl - generate code for complement */
1586 /*-----------------------------------------------------------------*/
1593 D (emitcode (";", "genCpl ");
1597 /* assign asmOps to operand & result */
1598 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1599 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1601 /* if both are in bit space then
1603 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1604 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1607 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1608 emitcode ("cpl", "c");
1609 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1613 size = AOP_SIZE (IC_RESULT (ic));
1614 _startLazyDPSEvaluation ();
1617 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1619 emitcode ("cpl", "a");
1620 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1622 _endLazyDPSEvaluation ();
1626 /* release the aops */
1627 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1628 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1631 /*-----------------------------------------------------------------*/
1632 /* genUminusFloat - unary minus for floating points */
1633 /*-----------------------------------------------------------------*/
1635 genUminusFloat (operand * op, operand * result)
1637 int size, offset = 0;
1639 /* for this we just need to flip the
1640 first it then copy the rest in place */
1641 D (emitcode (";", "genUminusFloat");
1644 _startLazyDPSEvaluation ();
1645 size = AOP_SIZE (op) - 1;
1646 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1649 emitcode ("cpl", "acc.7");
1650 aopPut (AOP (result), "a", 3);
1654 aopPut (AOP (result),
1655 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1659 _endLazyDPSEvaluation ();
1662 /*-----------------------------------------------------------------*/
1663 /* genUminus - unary minus code generation */
1664 /*-----------------------------------------------------------------*/
1666 genUminus (iCode * ic)
1669 sym_link *optype, *rtype;
1671 D (emitcode (";", "genUminus ");
1676 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1677 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1679 /* if both in bit space then special
1681 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1682 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1685 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1686 emitcode ("cpl", "c");
1687 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1691 optype = operandType (IC_LEFT (ic));
1692 rtype = operandType (IC_RESULT (ic));
1694 /* if float then do float stuff */
1695 if (IS_FLOAT (optype))
1697 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1701 /* otherwise subtract from zero */
1702 size = AOP_SIZE (IC_LEFT (ic));
1704 _startLazyDPSEvaluation ();
1707 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1708 if (!strcmp (l, "a"))
1712 emitcode ("cpl", "a");
1713 emitcode ("addc", "a,#0");
1719 emitcode ("clr", "a");
1720 emitcode ("subb", "a,%s", l);
1722 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1724 _endLazyDPSEvaluation ();
1726 /* if any remaining bytes in the result */
1727 /* we just need to propagate the sign */
1728 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1730 emitcode ("rlc", "a");
1731 emitcode ("subb", "a,acc");
1733 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1737 /* release the aops */
1738 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1739 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1742 /*-----------------------------------------------------------------*/
1743 /* saveRegisters - will look for a call and save the registers */
1744 /*-----------------------------------------------------------------*/
1746 saveRegisters (iCode * lic)
1754 for (ic = lic; ic; ic = ic->next)
1755 if (ic->op == CALL || ic->op == PCALL)
1760 fprintf (stderr, "found parameter push with no function call\n");
1764 /* if the registers have been saved already then
1766 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
1767 SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
1770 /* find the registers in use at this time
1771 and push them away to safety */
1772 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1776 if (options.useXstack)
1778 if (bitVectBitValue (rsave, R0_IDX))
1779 emitcode ("mov", "b,r0");
1780 emitcode ("mov", "r0,%s", spname);
1781 for (i = 0; i < ds390_nRegs; i++)
1783 if (bitVectBitValue (rsave, i))
1786 emitcode ("mov", "a,b");
1788 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1789 emitcode ("movx", "@r0,a");
1790 emitcode ("inc", "r0");
1793 emitcode ("mov", "%s,r0", spname);
1794 if (bitVectBitValue (rsave, R0_IDX))
1795 emitcode ("mov", "r0,b");
1798 for (i = 0; i < ds390_nRegs; i++)
1800 if (bitVectBitValue (rsave, i))
1801 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1804 detype = getSpec (operandType (IC_LEFT (ic)));
1807 /*-----------------------------------------------------------------*/
1808 /* unsaveRegisters - pop the pushed registers */
1809 /*-----------------------------------------------------------------*/
1811 unsaveRegisters (iCode * ic)
1815 /* find the registers in use at this time
1816 and push them away to safety */
1817 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1820 if (options.useXstack)
1822 emitcode ("mov", "r0,%s", spname);
1823 for (i = ds390_nRegs; i >= 0; i--)
1825 if (bitVectBitValue (rsave, i))
1827 emitcode ("dec", "r0");
1828 emitcode ("movx", "a,@r0");
1830 emitcode ("mov", "b,a");
1832 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1836 emitcode ("mov", "%s,r0", spname);
1837 if (bitVectBitValue (rsave, R0_IDX))
1838 emitcode ("mov", "r0,b");
1841 for (i = ds390_nRegs; i >= 0; i--)
1843 if (bitVectBitValue (rsave, i))
1844 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1850 /*-----------------------------------------------------------------*/
1852 /*-----------------------------------------------------------------*/
1854 pushSide (operand * oper, int size)
1857 _startLazyDPSEvaluation ();
1860 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1861 if (AOP_TYPE (oper) != AOP_REG &&
1862 AOP_TYPE (oper) != AOP_DIR &&
1865 emitcode ("mov", "a,%s", l);
1866 emitcode ("push", "acc");
1869 emitcode ("push", "%s", l);
1871 _endLazyDPSEvaluation ();
1874 /*-----------------------------------------------------------------*/
1875 /* assignResultValue - */
1876 /*-----------------------------------------------------------------*/
1878 assignResultValue (operand * oper)
1881 int size = AOP_SIZE (oper);
1883 _startLazyDPSEvaluation ();
1886 aopPut (AOP (oper), fReturn[offset], offset);
1889 _endLazyDPSEvaluation ();
1893 /*-----------------------------------------------------------------*/
1894 /* genXpush - pushes onto the external stack */
1895 /*-----------------------------------------------------------------*/
1897 genXpush (iCode * ic)
1899 asmop *aop = newAsmop (0);
1901 int size, offset = 0;
1903 D (emitcode (";", "genXpush ");
1906 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1907 r = getFreePtr (ic, &aop, FALSE);
1910 emitcode ("mov", "%s,_spx", r->name);
1912 size = AOP_SIZE (IC_LEFT (ic));
1913 _startLazyDPSEvaluation ();
1917 char *l = aopGet (AOP (IC_LEFT (ic)),
1918 offset++, FALSE, FALSE, TRUE);
1920 emitcode ("movx", "@%s,a", r->name);
1921 emitcode ("inc", "%s", r->name);
1924 _endLazyDPSEvaluation ();
1927 emitcode ("mov", "_spx,%s", r->name);
1929 freeAsmop (NULL, aop, ic, TRUE);
1930 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1933 /*-----------------------------------------------------------------*/
1934 /* genIpush - genrate code for pushing this gets a little complex */
1935 /*-----------------------------------------------------------------*/
1937 genIpush (iCode * ic)
1939 int size, offset = 0;
1942 D (emitcode (";", "genIpush ");
1945 /* if this is not a parm push : ie. it is spill push
1946 and spill push is always done on the local stack */
1950 /* and the item is spilt then do nothing */
1951 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1954 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1955 size = AOP_SIZE (IC_LEFT (ic));
1956 /* push it on the stack */
1957 _startLazyDPSEvaluation ();
1960 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1966 emitcode ("push", "%s", l);
1968 _endLazyDPSEvaluation ();
1972 /* this is a paramter push: in this case we call
1973 the routine to find the call and save those
1974 registers that need to be saved */
1977 /* if use external stack then call the external
1978 stack pushing routine */
1979 if (options.useXstack)
1985 /* then do the push */
1986 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1988 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1989 size = AOP_SIZE (IC_LEFT (ic));
1991 _startLazyDPSEvaluation ();
1994 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1995 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1996 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1999 emitcode ("mov", "a,%s", l);
2000 emitcode ("push", "acc");
2003 emitcode ("push", "%s", l);
2005 _endLazyDPSEvaluation ();
2007 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2010 /*-----------------------------------------------------------------*/
2011 /* genIpop - recover the registers: can happen only for spilling */
2012 /*-----------------------------------------------------------------*/
2014 genIpop (iCode * ic)
2018 D (emitcode (";", "genIpop ");
2022 /* if the temp was not pushed then */
2023 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2026 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2027 size = AOP_SIZE (IC_LEFT (ic));
2028 offset = (size - 1);
2029 _startLazyDPSEvaluation ();
2032 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2033 FALSE, TRUE, TRUE));
2035 _endLazyDPSEvaluation ();
2037 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2040 /*-----------------------------------------------------------------*/
2041 /* unsaveRBank - restores the resgister bank from stack */
2042 /*-----------------------------------------------------------------*/
2044 unsaveRBank (int bank, iCode * ic, bool popPsw)
2050 if (options.useXstack)
2054 /* Assume r0 is available for use. */
2055 r = ds390_regWithIdx (R0_IDX);;
2060 r = getFreePtr (ic, &aop, FALSE);
2062 emitcode ("mov", "%s,_spx", r->name);
2067 if (options.useXstack)
2069 emitcode ("movx", "a,@%s", r->name);
2070 emitcode ("mov", "psw,a");
2071 emitcode ("dec", "%s", r->name);
2075 emitcode ("pop", "psw");
2079 for (i = (ds390_nRegs - 1); i >= 0; i--)
2081 if (options.useXstack)
2083 emitcode ("movx", "a,@%s", r->name);
2084 emitcode ("mov", "(%s+%d),a",
2085 regs390[i].base, 8 * bank + regs390[i].offset);
2086 emitcode ("dec", "%s", r->name);
2090 emitcode ("pop", "(%s+%d)",
2091 regs390[i].base, 8 * bank + regs390[i].offset);
2094 if (options.useXstack)
2096 emitcode ("mov", "_spx,%s", r->name);
2101 freeAsmop (NULL, aop, ic, TRUE);
2105 /*-----------------------------------------------------------------*/
2106 /* saveRBank - saves an entire register bank on the stack */
2107 /*-----------------------------------------------------------------*/
2109 saveRBank (int bank, iCode * ic, bool pushPsw)
2115 if (options.useXstack)
2119 /* Assume r0 is available for use. */
2120 r = ds390_regWithIdx (R0_IDX);;
2125 r = getFreePtr (ic, &aop, FALSE);
2127 emitcode ("mov", "%s,_spx", r->name);
2130 for (i = 0; i < ds390_nRegs; i++)
2132 if (options.useXstack)
2134 emitcode ("inc", "%s", r->name);
2135 emitcode ("mov", "a,(%s+%d)",
2136 regs390[i].base, 8 * bank + regs390[i].offset);
2137 emitcode ("movx", "@%s,a", r->name);
2140 emitcode ("push", "(%s+%d)",
2141 regs390[i].base, 8 * bank + regs390[i].offset);
2146 if (options.useXstack)
2148 emitcode ("mov", "a,psw");
2149 emitcode ("movx", "@%s,a", r->name);
2150 emitcode ("inc", "%s", r->name);
2151 emitcode ("mov", "_spx,%s", r->name);
2155 emitcode ("push", "psw");
2158 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2163 freeAsmop (NULL, aop, ic, TRUE);
2172 /*-----------------------------------------------------------------*/
2173 /* genCall - generates a call statement */
2174 /*-----------------------------------------------------------------*/
2176 genCall (iCode * ic)
2179 bool restoreBank = FALSE;
2180 bool swapBanks = FALSE;
2182 D (emitcode (";", "genCall "););
2184 /* if we are calling a not _naked function that is not using
2185 the same register bank then we need to save the
2186 destination registers on the stack */
2187 detype = getSpec (operandType (IC_LEFT (ic)));
2188 if (detype && !SPEC_NAKED(detype) &&
2189 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2190 IS_ISR (currFunc->etype))
2194 /* This is unexpected; the bank should have been saved in
2197 saveRBank (SPEC_BANK (detype), ic, FALSE);
2203 /* if caller saves & we have not saved then */
2207 /* if send set is not empty the assign */
2208 /* We've saved all the registers we care about;
2209 * therefore, we may clobber any register not used
2210 * in the calling convention (i.e. anything not in
2217 for (sic = setFirstItem (_G.sendSet); sic;
2218 sic = setNextItem (_G.sendSet))
2220 int size, offset = 0;
2222 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2223 size = AOP_SIZE (IC_LEFT (sic));
2225 _startLazyDPSEvaluation ();
2228 char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2229 FALSE, FALSE, TRUE);
2230 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2232 emitcode("mov", "%s,%s", regs390[offset].name, l);
2234 else if (strcmp (l, fReturn[offset]))
2236 emitcode ("mov", "%s,%s",
2242 _endLazyDPSEvaluation ();
2243 if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2245 size = AOP_SIZE (IC_LEFT (sic));
2253 emitcode("mov", "%s,%s",
2254 fReturn[size], regs390[size].name);
2257 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2264 emitcode ("mov", "psw,#0x%02x",
2265 ((SPEC_BANK(detype)) << 3) & 0xff);
2269 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2270 OP_SYMBOL (IC_LEFT (ic))->rname :
2271 OP_SYMBOL (IC_LEFT (ic))->name));
2275 emitcode ("mov", "psw,#0x%02x",
2276 ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
2279 /* if we need assign a result value */
2280 if ((IS_ITEMP (IC_RESULT (ic)) &&
2281 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2282 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2283 IS_TRUE_SYMOP (IC_RESULT (ic)))
2285 if (isOperandInFarSpace (IC_RESULT (ic))
2286 && getSize (operandType (IC_RESULT (ic))) <= 2)
2288 int size = getSize (operandType (IC_RESULT (ic)));
2290 /* Special case for 1 or 2 byte return in far space. */
2294 emitcode ("mov", "b,%s", fReturn[1]);
2297 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2298 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2302 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2304 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2309 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2312 assignResultValue (IC_RESULT (ic));
2314 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2318 /* adjust the stack for parameters if
2323 if (ic->parmBytes > 3)
2325 emitcode ("mov", "a,%s", spname);
2326 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2327 emitcode ("mov", "%s,a", spname);
2330 for (i = 0; i < ic->parmBytes; i++)
2331 emitcode ("dec", "%s", spname);
2334 /* if we hade saved some registers then unsave them */
2335 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2336 unsaveRegisters (ic);
2338 /* if register bank was saved then pop them */
2340 unsaveRBank (SPEC_BANK (detype), ic, FALSE);
2343 /*-----------------------------------------------------------------*/
2344 /* genPcall - generates a call by pointer statement */
2345 /*-----------------------------------------------------------------*/
2347 genPcall (iCode * ic)
2350 symbol *rlbl = newiTempLabel (NULL);
2352 D (emitcode (";", "genPcall ");
2356 /* if caller saves & we have not saved then */
2360 /* if we are calling a function that is not using
2361 the same register bank then we need to save the
2362 destination registers on the stack */
2363 detype = getSpec (operandType (IC_LEFT (ic)));
2365 IS_ISR (currFunc->etype) &&
2366 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2367 saveRBank (SPEC_BANK (detype), ic, TRUE);
2370 /* push the return address on to the stack */
2371 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2372 emitcode ("push", "acc");
2373 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2374 emitcode ("push", "acc");
2376 if (options.model == MODEL_FLAT24)
2378 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2379 emitcode ("push", "acc");
2382 /* now push the calling address */
2383 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2385 pushSide (IC_LEFT (ic), FPTRSIZE);
2387 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2389 /* if send set is not empty the assign */
2394 for (sic = setFirstItem (_G.sendSet); sic;
2395 sic = setNextItem (_G.sendSet))
2397 int size, offset = 0;
2399 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2400 size = AOP_SIZE (IC_LEFT (sic));
2401 _startLazyDPSEvaluation ();
2404 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2405 FALSE, FALSE, TRUE);
2406 if (strcmp (l, fReturn[offset]))
2408 emitcode ("mov", "%s,%s",
2414 _endLazyDPSEvaluation ();
2415 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2420 emitcode ("ret", "");
2421 emitcode ("", "%05d$:", (rlbl->key + 100));
2424 /* if we need assign a result value */
2425 if ((IS_ITEMP (IC_RESULT (ic)) &&
2426 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2427 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2428 IS_TRUE_SYMOP (IC_RESULT (ic)))
2432 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2435 assignResultValue (IC_RESULT (ic));
2437 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2440 /* adjust the stack for parameters if
2445 if (ic->parmBytes > 3)
2447 emitcode ("mov", "a,%s", spname);
2448 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2449 emitcode ("mov", "%s,a", spname);
2452 for (i = 0; i < ic->parmBytes; i++)
2453 emitcode ("dec", "%s", spname);
2457 /* if register bank was saved then unsave them */
2459 (SPEC_BANK (currFunc->etype) !=
2460 SPEC_BANK (detype)))
2461 unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2463 /* if we hade saved some registers then
2466 unsaveRegisters (ic);
2470 /*-----------------------------------------------------------------*/
2471 /* resultRemat - result is rematerializable */
2472 /*-----------------------------------------------------------------*/
2474 resultRemat (iCode * ic)
2476 if (SKIP_IC (ic) || ic->op == IFX)
2479 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2481 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2482 if (sym->remat && !POINTER_SET (ic))
2489 #if defined(__BORLANDC__) || defined(_MSC_VER)
2490 #define STRCASECMP stricmp
2492 #define STRCASECMP strcasecmp
2495 /*-----------------------------------------------------------------*/
2496 /* inExcludeList - return 1 if the string is in exclude Reg list */
2497 /*-----------------------------------------------------------------*/
2499 inExcludeList (char *s)
2503 if (options.excludeRegs[i] &&
2504 STRCASECMP (options.excludeRegs[i], "none") == 0)
2507 for (i = 0; options.excludeRegs[i]; i++)
2509 if (options.excludeRegs[i] &&
2510 STRCASECMP (s, options.excludeRegs[i]) == 0)
2516 /*-----------------------------------------------------------------*/
2517 /* genFunction - generated code for function entry */
2518 /*-----------------------------------------------------------------*/
2520 genFunction (iCode * ic)
2524 bool switchedPSW = FALSE;
2526 D (emitcode (";", "genFunction "););
2529 /* create the function header */
2530 emitcode (";", "-----------------------------------------");
2531 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2532 emitcode (";", "-----------------------------------------");
2534 emitcode ("", "%s:", sym->rname);
2535 fetype = getSpec (operandType (IC_LEFT (ic)));
2537 if (SPEC_NAKED(fetype))
2539 emitcode(";", "naked function: no prologue.");
2543 /* if critical function then turn interrupts off */
2544 if (SPEC_CRTCL (fetype))
2545 emitcode ("clr", "ea");
2547 /* here we need to generate the equates for the
2548 register bank if required */
2549 if (SPEC_BANK (fetype) != rbank)
2553 rbank = SPEC_BANK (fetype);
2554 for (i = 0; i < ds390_nRegs; i++)
2556 if (strcmp (regs390[i].base, "0") == 0)
2557 emitcode ("", "%s = 0x%02x",
2559 8 * rbank + regs390[i].offset);
2561 emitcode ("", "%s = %s + 0x%02x",
2564 8 * rbank + regs390[i].offset);
2568 /* if this is an interrupt service routine then
2569 save acc, b, dpl, dph */
2570 if (IS_ISR (sym->etype))
2573 if (!inExcludeList ("acc"))
2574 emitcode ("push", "acc");
2575 if (!inExcludeList ("b"))
2576 emitcode ("push", "b");
2577 if (!inExcludeList ("dpl"))
2578 emitcode ("push", "dpl");
2579 if (!inExcludeList ("dph"))
2580 emitcode ("push", "dph");
2581 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2583 emitcode ("push", "dpx");
2584 /* Make sure we're using standard DPTR */
2585 emitcode ("push", "dps");
2586 emitcode ("mov", "dps, #0x00");
2587 if (options.stack10bit)
2589 /* This ISR could conceivably use DPTR2. Better save it. */
2590 emitcode ("push", "dpl1");
2591 emitcode ("push", "dph1");
2592 emitcode ("push", "dpx1");
2593 emitcode ("push", DP2_RESULT_REG);
2596 /* if this isr has no bank i.e. is going to
2597 run with bank 0 , then we need to save more
2599 if (!SPEC_BANK (sym->etype))
2602 /* if this function does not call any other
2603 function then we can be economical and
2604 save only those registers that are used */
2609 /* if any registers used */
2612 /* save the registers used */
2613 for (i = 0; i < sym->regsUsed->size; i++)
2615 if (bitVectBitValue (sym->regsUsed, i) ||
2616 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2617 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2624 /* this function has a function call cannot
2625 determines register usage so we will have to push the
2627 saveRBank (0, ic, FALSE);
2632 /* This ISR uses a non-zero bank.
2634 * We assume that the bank is available for our
2637 * However, if this ISR calls a function which uses some
2638 * other bank, we must save that bank entirely.
2640 unsigned long banksToSave = 0;
2645 #define MAX_REGISTER_BANKS 4
2650 for (i = ic; i; i = i->next)
2652 if (i->op == ENDFUNCTION)
2654 /* we got to the end OK. */
2662 detype = getSpec(operandType (IC_LEFT(i)));
2664 && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
2666 /* Mark this bank for saving. */
2667 if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
2669 werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
2673 banksToSave |= (1 << SPEC_BANK(detype));
2676 /* And note that we don't need to do it in
2684 /* This is a mess; we have no idea what
2685 * register bank the called function might
2688 * The only thing I can think of to do is
2689 * throw a warning and hope.
2691 werror(W_FUNCPTR_IN_USING_ISR);
2695 if (banksToSave && options.useXstack)
2697 /* Since we aren't passing it an ic,
2698 * saveRBank will assume r0 is available to abuse.
2700 * So switch to our (trashable) bank now, so
2701 * the caller's R0 isn't trashed.
2703 emitcode ("push", "psw");
2704 emitcode ("mov", "psw,#0x%02x",
2705 (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2709 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2711 if (banksToSave & (1 << ix))
2713 saveRBank(ix, NULL, FALSE);
2717 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2722 /* if callee-save to be used for this function
2723 then save the registers being used in this function */
2724 if (sym->calleeSave)
2728 /* if any registers used */
2731 /* save the registers used */
2732 for (i = 0; i < sym->regsUsed->size; i++)
2734 if (bitVectBitValue (sym->regsUsed, i) ||
2735 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2737 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2745 /* set the register bank to the desired value */
2746 if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2749 emitcode ("push", "psw");
2750 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2753 if (IS_RENT (sym->etype) || options.stackAuto)
2756 if (options.useXstack)
2758 emitcode ("mov", "r0,%s", spname);
2759 emitcode ("mov", "a,_bp");
2760 emitcode ("movx", "@r0,a");
2761 emitcode ("inc", "%s", spname);
2765 /* set up the stack */
2766 emitcode ("push", "_bp"); /* save the callers stack */
2768 emitcode ("mov", "_bp,%s", spname);
2771 /* adjust the stack for the function */
2777 werror (W_STACK_OVERFLOW, sym->name);
2779 if (i > 3 && sym->recvSize < 4)
2782 emitcode ("mov", "a,sp");
2783 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2784 emitcode ("mov", "sp,a");
2789 emitcode ("inc", "sp");
2795 emitcode ("mov", "a,_spx");
2796 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2797 emitcode ("mov", "_spx,a");
2802 /*-----------------------------------------------------------------*/
2803 /* genEndFunction - generates epilogue for functions */
2804 /*-----------------------------------------------------------------*/
2806 genEndFunction (iCode * ic)
2808 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2810 D (emitcode (";", "genEndFunction "););
2812 if (SPEC_NAKED(sym->etype))
2814 emitcode(";", "naked function: no epilogue.");
2818 if (IS_RENT (sym->etype) || options.stackAuto)
2820 emitcode ("mov", "%s,_bp", spname);
2823 /* if use external stack but some variables were
2824 added to the local stack then decrement the
2826 if (options.useXstack && sym->stack)
2828 emitcode ("mov", "a,sp");
2829 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2830 emitcode ("mov", "sp,a");
2834 if ((IS_RENT (sym->etype) || options.stackAuto))
2836 if (options.useXstack)
2838 emitcode ("mov", "r0,%s", spname);
2839 emitcode ("movx", "a,@r0");
2840 emitcode ("mov", "_bp,a");
2841 emitcode ("dec", "%s", spname);
2845 emitcode ("pop", "_bp");
2849 /* restore the register bank */
2850 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2852 if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
2853 || !options.useXstack)
2855 /* Special case of ISR using non-zero bank with useXstack
2858 emitcode ("pop", "psw");
2862 if (IS_ISR (sym->etype))
2865 /* now we need to restore the registers */
2866 /* if this isr has no bank i.e. is going to
2867 run with bank 0 , then we need to save more
2869 if (!SPEC_BANK (sym->etype))
2871 /* if this function does not call any other
2872 function then we can be economical and
2873 save only those registers that are used */
2878 /* if any registers used */
2881 /* save the registers used */
2882 for (i = sym->regsUsed->size; i >= 0; i--)
2884 if (bitVectBitValue (sym->regsUsed, i) ||
2885 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2886 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2893 /* this function has a function call cannot
2894 determines register usage so we will have to pop the
2896 unsaveRBank (0, ic, FALSE);
2901 /* This ISR uses a non-zero bank.
2903 * Restore any register banks saved by genFunction
2906 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2909 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2911 if (savedBanks & (1 << ix))
2913 unsaveRBank(ix, NULL, FALSE);
2917 if (options.useXstack)
2919 /* Restore bank AFTER calling unsaveRBank,
2920 * since it can trash r0.
2922 emitcode ("pop", "psw");
2926 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2928 if (options.stack10bit)
2930 emitcode ("pop", DP2_RESULT_REG);
2931 emitcode ("pop", "dpx1");
2932 emitcode ("pop", "dph1");
2933 emitcode ("pop", "dpl1");
2935 emitcode ("pop", "dps");
2936 emitcode ("pop", "dpx");
2938 if (!inExcludeList ("dph"))
2939 emitcode ("pop", "dph");
2940 if (!inExcludeList ("dpl"))
2941 emitcode ("pop", "dpl");
2942 if (!inExcludeList ("b"))
2943 emitcode ("pop", "b");
2944 if (!inExcludeList ("acc"))
2945 emitcode ("pop", "acc");
2947 if (SPEC_CRTCL (sym->etype))
2948 emitcode ("setb", "ea");
2950 /* if debug then send end of function */
2951 if (options.debug && currFunc) {
2953 emitcode ("", "C$%s$%d$%d$%d ==.",
2954 FileBaseName (ic->filename), currFunc->lastLine,
2955 ic->level, ic->block);
2956 if (IS_STATIC (currFunc->etype))
2957 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2959 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2963 emitcode ("reti", "");
2967 if (SPEC_CRTCL (sym->etype))
2968 emitcode ("setb", "ea");
2970 if (sym->calleeSave)
2974 /* if any registers used */
2977 /* save the registers used */
2978 for (i = sym->regsUsed->size; i >= 0; i--)
2980 if (bitVectBitValue (sym->regsUsed, i) ||
2981 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2982 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2988 /* if debug then send end of function */
2989 if (options.debug && currFunc)
2992 emitcode ("", "C$%s$%d$%d$%d ==.",
2993 FileBaseName (ic->filename), currFunc->lastLine,
2994 ic->level, ic->block);
2995 if (IS_STATIC (currFunc->etype))
2996 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2998 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3002 emitcode ("ret", "");
3007 /*-----------------------------------------------------------------*/
3008 /* genRet - generate code for return statement */
3009 /*-----------------------------------------------------------------*/
3013 int size, offset = 0, pushed = 0;
3015 D (emitcode (";", "genRet ");
3018 /* if we have no return value then
3019 just generate the "ret" */
3023 /* we have something to return then
3024 move the return value into place */
3025 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3026 size = AOP_SIZE (IC_LEFT (ic));
3028 _startLazyDPSEvaluation ();
3032 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3034 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3035 FALSE, TRUE, FALSE);
3036 emitcode ("push", "%s", l);
3041 /* Since A is the last element of fReturn,
3042 * is is OK to clobber it in the aopGet.
3044 l = aopGet (AOP (IC_LEFT (ic)), offset,
3045 FALSE, FALSE, TRUE);
3046 if (strcmp (fReturn[offset], l))
3047 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3050 _endLazyDPSEvaluation ();
3057 if (strcmp (fReturn[pushed], "a"))
3058 emitcode ("pop", fReturn[pushed]);
3060 emitcode ("pop", "acc");
3063 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3066 /* generate a jump to the return label
3067 if the next is not the return statement */
3068 if (!(ic->next && ic->next->op == LABEL &&
3069 IC_LABEL (ic->next) == returnLabel))
3071 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3075 /*-----------------------------------------------------------------*/
3076 /* genLabel - generates a label */
3077 /*-----------------------------------------------------------------*/
3079 genLabel (iCode * ic)
3081 /* special case never generate */
3082 if (IC_LABEL (ic) == entryLabel)
3085 D (emitcode (";", "genLabel ");
3088 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3091 /*-----------------------------------------------------------------*/
3092 /* genGoto - generates a ljmp */
3093 /*-----------------------------------------------------------------*/
3095 genGoto (iCode * ic)
3097 D (emitcode (";", "genGoto ");
3099 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3102 /*-----------------------------------------------------------------*/
3103 /* findLabelBackwards: walks back through the iCode chain looking */
3104 /* for the given label. Returns number of iCode instructions */
3105 /* between that label and given ic. */
3106 /* Returns zero if label not found. */
3107 /*-----------------------------------------------------------------*/
3109 findLabelBackwards (iCode * ic, int key)
3118 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3120 /* printf("findLabelBackwards = %d\n", count); */
3128 /*-----------------------------------------------------------------*/
3129 /* genPlusIncr :- does addition with increment if possible */
3130 /*-----------------------------------------------------------------*/
3132 genPlusIncr (iCode * ic)
3134 unsigned int icount;
3135 unsigned int size = getDataSize (IC_RESULT (ic));
3137 /* will try to generate an increment */
3138 /* if the right side is not a literal
3140 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3143 /* if the literal value of the right hand side
3144 is greater than 4 then it is not worth it */
3145 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3148 /* if increment 16 bits in register */
3150 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3151 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3152 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3160 /* If the next instruction is a goto and the goto target
3161 * is <= 5 instructions previous to this, we can generate
3162 * jumps straight to that target.
3164 if (ic->next && ic->next->op == GOTO
3165 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3168 emitcode (";", "tail increment optimized (range %d)", labelRange);
3169 tlbl = IC_LABEL (ic->next);
3174 tlbl = newiTempLabel (NULL);
3177 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3178 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3179 IS_AOP_PREG (IC_RESULT (ic)))
3180 emitcode ("cjne", "%s,#0x00,%05d$"
3181 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3185 emitcode ("clr", "a");
3186 emitcode ("cjne", "a,%s,%05d$"
3187 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3191 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3194 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3195 IS_AOP_PREG (IC_RESULT (ic)))
3196 emitcode ("cjne", "%s,#0x00,%05d$"
3197 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3200 emitcode ("cjne", "a,%s,%05d$"
3201 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3204 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3208 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3209 IS_AOP_PREG (IC_RESULT (ic)))
3210 emitcode ("cjne", "%s,#0x00,%05d$"
3211 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3215 emitcode ("cjne", "a,%s,%05d$"
3216 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3219 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3224 emitcode ("", "%05d$:", tlbl->key + 100);
3229 /* if the sizes are greater than 1 then we cannot */
3230 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3231 AOP_SIZE (IC_LEFT (ic)) > 1)
3234 /* we can if the aops of the left & result match or
3235 if they are in registers and the registers are the
3238 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3239 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3240 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3245 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3246 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3247 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3252 _startLazyDPSEvaluation ();
3255 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3257 _endLazyDPSEvaluation ();
3266 /*-----------------------------------------------------------------*/
3267 /* outBitAcc - output a bit in acc */
3268 /*-----------------------------------------------------------------*/
3270 outBitAcc (operand * result)
3272 symbol *tlbl = newiTempLabel (NULL);
3273 /* if the result is a bit */
3274 if (AOP_TYPE (result) == AOP_CRY)
3276 aopPut (AOP (result), "a", 0);
3280 emitcode ("jz", "%05d$", tlbl->key + 100);
3281 emitcode ("mov", "a,%s", one);
3282 emitcode ("", "%05d$:", tlbl->key + 100);
3287 /*-----------------------------------------------------------------*/
3288 /* genPlusBits - generates code for addition of two bits */
3289 /*-----------------------------------------------------------------*/
3291 genPlusBits (iCode * ic)
3293 D (emitcode (";", "genPlusBits ");
3295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3297 symbol *lbl = newiTempLabel (NULL);
3298 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3299 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3300 emitcode ("cpl", "c");
3301 emitcode ("", "%05d$:", (lbl->key + 100));
3302 outBitC (IC_RESULT (ic));
3306 emitcode ("clr", "a");
3307 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3308 emitcode ("rlc", "a");
3309 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3310 emitcode ("addc", "a,#0x00");
3311 outAcc (IC_RESULT (ic));
3316 adjustArithmeticResult (iCode * ic)
3318 if (opIsGptr (IC_RESULT (ic)) &&
3319 opIsGptr (IC_LEFT (ic)) &&
3320 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3322 aopPut (AOP (IC_RESULT (ic)),
3323 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3327 if (opIsGptr (IC_RESULT (ic)) &&
3328 opIsGptr (IC_RIGHT (ic)) &&
3329 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3331 aopPut (AOP (IC_RESULT (ic)),
3332 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3336 if (opIsGptr (IC_RESULT (ic)) &&
3337 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3338 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3339 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3340 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3343 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3344 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3348 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3349 // (because all three operands are in far space).
3350 #define AOP_OP_3(ic) \
3351 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3352 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3353 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3354 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3355 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3356 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3358 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3360 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3363 // Macro to aopOp all three operands of an ic. If this cannot be done,
3364 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3365 // will be set TRUE. The caller must then handle the case specially, noting
3366 // that the IC_RESULT operand is not aopOp'd.
3367 #define AOP_OP_3_NOFATAL(ic, rc) \
3368 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3369 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3370 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3371 isOperandInFarSpace(IC_RESULT(ic))) \
3373 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3378 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3379 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3381 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3382 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3384 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3386 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3390 // aopOp the left & right operands of an ic.
3391 #define AOP_OP_2(ic) \
3392 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3393 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3395 // convienience macro.
3396 #define AOP_SET_LOCALS(ic) \
3397 left = IC_LEFT(ic); \
3398 right = IC_RIGHT(ic); \
3399 result = IC_RESULT(ic);
3402 // Given an integer value of pushedSize bytes on the stack,
3403 // adjust it to be resultSize bytes, either by discarding
3404 // the most significant bytes or by zero-padding.
3406 // On exit from this macro, pushedSize will have been adjusted to
3407 // equal resultSize, and ACC may be trashed.
3408 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3409 /* If the pushed data is bigger than the result, \
3410 * simply discard unused bytes. Icky, but works. \
3412 while (pushedSize > resultSize) \
3414 D (emitcode (";", "discarding unused result byte."););\
3415 emitcode ("pop", "acc"); \
3418 if (pushedSize < resultSize) \
3420 emitcode ("clr", "a"); \
3421 /* Conversly, we haven't pushed enough here. \
3422 * just zero-pad, and all is well. \
3424 while (pushedSize < resultSize) \
3426 emitcode("push", "acc"); \
3430 assert(pushedSize == resultSize);
3432 /*-----------------------------------------------------------------*/
3433 /* genPlus - generates code for addition */
3434 /*-----------------------------------------------------------------*/
3436 genPlus (iCode * ic)
3438 int size, offset = 0;
3439 bool pushResult = FALSE;
3442 D (emitcode (";", "genPlus "););
3444 /* special cases :- */
3446 AOP_OP_3_NOFATAL (ic, pushResult);
3449 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3454 /* if literal, literal on the right or
3455 if left requires ACC or right is already
3457 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3458 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3459 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3461 operand *t = IC_RIGHT (ic);
3462 IC_RIGHT (ic) = IC_LEFT (ic);
3464 emitcode (";", "Swapped plus args.");
3467 /* if both left & right are in bit
3469 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3470 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3476 /* if left in bit space & right literal */
3477 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3478 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3480 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3481 /* if result in bit space */
3482 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3484 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3485 emitcode ("cpl", "c");
3486 outBitC (IC_RESULT (ic));
3490 size = getDataSize (IC_RESULT (ic));
3491 _startLazyDPSEvaluation ();
3494 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3495 emitcode ("addc", "a,#00");
3496 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3498 _endLazyDPSEvaluation ();
3503 /* if I can do an increment instead
3504 of add then GOOD for ME */
3505 if (genPlusIncr (ic) == TRUE)
3507 emitcode (";", "did genPlusIncr");
3512 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3514 _startLazyDPSEvaluation ();
3517 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3519 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3521 emitcode ("add", "a,%s",
3522 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3524 emitcode ("addc", "a,%s",
3525 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3529 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3531 /* right is going to use ACC or we would have taken the
3534 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3535 D(emitcode(";", "+ AOP_ACC special case."););
3536 emitcode("xch", "a, %s", DP2_RESULT_REG);
3538 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3541 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3543 emitcode("add", "a, %s", DP2_RESULT_REG);
3547 emitcode ("add", "a,%s",
3548 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3553 emitcode ("addc", "a,%s",
3554 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3559 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3563 emitcode ("push", "acc");
3567 _endLazyDPSEvaluation ();
3571 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3573 size = getDataSize (IC_LEFT (ic));
3574 rSize = getDataSize (IC_RESULT (ic));
3576 ADJUST_PUSHED_RESULT(size, rSize);
3578 _startLazyDPSEvaluation ();
3581 emitcode ("pop", "acc");
3582 aopPut (AOP (IC_RESULT (ic)), "a", size);
3584 _endLazyDPSEvaluation ();
3587 adjustArithmeticResult (ic);
3590 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3591 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3592 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3595 /*-----------------------------------------------------------------*/
3596 /* genMinusDec :- does subtraction with deccrement if possible */
3597 /*-----------------------------------------------------------------*/
3599 genMinusDec (iCode * ic)
3601 unsigned int icount;
3602 unsigned int size = getDataSize (IC_RESULT (ic));
3604 /* will try to generate an increment */
3605 /* if the right side is not a literal
3607 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3610 /* if the literal value of the right hand side
3611 is greater than 4 then it is not worth it */
3612 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3615 /* if decrement 16 bits in register */
3616 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3617 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3618 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3626 /* If the next instruction is a goto and the goto target
3627 * is <= 5 instructions previous to this, we can generate
3628 * jumps straight to that target.
3630 if (ic->next && ic->next->op == GOTO
3631 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3634 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3635 tlbl = IC_LABEL (ic->next);
3640 tlbl = newiTempLabel (NULL);
3644 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3645 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3646 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3647 IS_AOP_PREG (IC_RESULT (ic)))
3648 emitcode ("cjne", "%s,#0xff,%05d$"
3649 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3653 emitcode ("mov", "a,#0xff");
3654 emitcode ("cjne", "a,%s,%05d$"
3655 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3658 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3661 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3662 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3663 IS_AOP_PREG (IC_RESULT (ic)))
3664 emitcode ("cjne", "%s,#0xff,%05d$"
3665 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3669 emitcode ("cjne", "a,%s,%05d$"
3670 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3673 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3677 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3678 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3679 IS_AOP_PREG (IC_RESULT (ic)))
3680 emitcode ("cjne", "%s,#0xff,%05d$"
3681 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3685 emitcode ("cjne", "a,%s,%05d$"
3686 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3689 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3693 emitcode ("", "%05d$:", tlbl->key + 100);
3698 /* if the sizes are greater than 1 then we cannot */
3699 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3700 AOP_SIZE (IC_LEFT (ic)) > 1)
3703 /* we can if the aops of the left & result match or
3704 if they are in registers and the registers are the
3707 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3708 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3709 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3712 _startLazyDPSEvaluation ();
3715 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3717 _endLazyDPSEvaluation ();
3725 /*-----------------------------------------------------------------*/
3726 /* addSign - complete with sign */
3727 /*-----------------------------------------------------------------*/
3729 addSign (operand * result, int offset, int sign)
3731 int size = (getDataSize (result) - offset);
3734 _startLazyDPSEvaluation();
3737 emitcode ("rlc", "a");
3738 emitcode ("subb", "a,acc");
3741 aopPut (AOP (result), "a", offset++);
3748 aopPut (AOP (result), zero, offset++);
3751 _endLazyDPSEvaluation();
3755 /*-----------------------------------------------------------------*/
3756 /* genMinusBits - generates code for subtraction of two bits */
3757 /*-----------------------------------------------------------------*/
3759 genMinusBits (iCode * ic)
3761 symbol *lbl = newiTempLabel (NULL);
3763 D (emitcode (";", "genMinusBits "););
3765 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3767 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3768 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3769 emitcode ("cpl", "c");
3770 emitcode ("", "%05d$:", (lbl->key + 100));
3771 outBitC (IC_RESULT (ic));
3775 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3776 emitcode ("subb", "a,acc");
3777 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3778 emitcode ("inc", "a");
3779 emitcode ("", "%05d$:", (lbl->key + 100));
3780 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3781 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3785 /*-----------------------------------------------------------------*/
3786 /* genMinus - generates code for subtraction */
3787 /*-----------------------------------------------------------------*/
3789 genMinus (iCode * ic)
3791 int size, offset = 0;
3793 unsigned long lit = 0L;
3794 bool pushResult = FALSE;
3796 D (emitcode (";", "genMinus "););
3798 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3799 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3800 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3801 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3807 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3809 /* special cases :- */
3810 /* if both left & right are in bit space */
3811 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3812 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3818 /* if I can do an decrement instead
3819 of subtract then GOOD for ME */
3820 if (genMinusDec (ic) == TRUE)
3825 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3827 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3833 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3838 /* if literal, add a,#-lit, else normal subb */
3839 _startLazyDPSEvaluation ();
3842 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3843 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3844 emitcode ("subb", "a,%s",
3845 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3848 /* first add without previous c */
3850 if (!size && lit==-1) {
3851 emitcode ("dec", "a");
3853 emitcode ("add", "a,#0x%02x",
3854 (unsigned int) (lit & 0x0FFL));
3857 emitcode ("addc", "a,#0x%02x",
3858 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3864 emitcode ("push", "acc");
3868 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3872 _endLazyDPSEvaluation ();
3876 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3878 size = getDataSize (IC_LEFT (ic));
3879 rSize = getDataSize (IC_RESULT (ic));
3881 ADJUST_PUSHED_RESULT(size, rSize);
3883 _startLazyDPSEvaluation ();
3886 emitcode ("pop", "acc");
3887 aopPut (AOP (IC_RESULT (ic)), "a", size);
3889 _endLazyDPSEvaluation ();
3892 adjustArithmeticResult (ic);
3895 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3896 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3897 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3901 /*-----------------------------------------------------------------*/
3902 /* genMultbits :- multiplication of bits */
3903 /*-----------------------------------------------------------------*/
3905 genMultbits (operand * left,
3909 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3910 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3915 /*-----------------------------------------------------------------*/
3916 /* genMultOneByte : 8*8=8/16 bit multiplication */
3917 /*-----------------------------------------------------------------*/
3919 genMultOneByte (operand * left,
3923 sym_link *opetype = operandType (result);
3925 int size=AOP_SIZE(result);
3927 if (size<1 || size>2) {
3928 // this should never happen
3929 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3930 AOP_SIZE(result), __FILE__, lineno);
3934 /* (if two literals: the value is computed before) */
3935 /* if one literal, literal on the right */
3936 if (AOP_TYPE (left) == AOP_LIT)
3941 emitcode (";", "swapped left and right");
3944 if (SPEC_USIGN(opetype)
3945 // ignore the sign of left and right, what else can we do?
3946 || (SPEC_USIGN(operandType(left)) &&
3947 SPEC_USIGN(operandType(right)))) {
3948 // just an unsigned 8*8=8/16 multiply
3949 //emitcode (";","unsigned");
3950 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3951 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3952 emitcode ("mul", "ab");
3953 aopPut (AOP (result), "a", 0);
3955 aopPut (AOP (result), "b", 1);
3960 // we have to do a signed multiply
3962 emitcode (";", "signed");
3963 emitcode ("clr", "F0"); // reset sign flag
3964 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3966 lbl=newiTempLabel(NULL);
3967 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3968 // left side is negative, 8-bit two's complement, this fails for -128
3969 emitcode ("setb", "F0"); // set sign flag
3970 emitcode ("cpl", "a");
3971 emitcode ("inc", "a");
3973 emitcode ("", "%05d$:", lbl->key+100);
3976 if (AOP_TYPE(right)==AOP_LIT) {
3977 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3978 /* AND literal negative */
3979 if ((int) val < 0) {
3980 emitcode ("cpl", "F0"); // complement sign flag
3981 emitcode ("mov", "b,#0x%02x", -val);
3983 emitcode ("mov", "b,#0x%02x", val);
3986 lbl=newiTempLabel(NULL);
3987 emitcode ("mov", "b,a");
3988 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3989 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3990 // right side is negative, 8-bit two's complement
3991 emitcode ("cpl", "F0"); // complement sign flag
3992 emitcode ("cpl", "a");
3993 emitcode ("inc", "a");
3994 emitcode ("", "%05d$:", lbl->key+100);
3996 emitcode ("mul", "ab");
3998 lbl=newiTempLabel(NULL);
3999 emitcode ("jnb", "F0,%05d$", lbl->key+100);
4000 // only ONE op was negative, we have to do a 8/16-bit two's complement
4001 emitcode ("cpl", "a"); // lsb
4003 emitcode ("inc", "a");
4005 emitcode ("add", "a,#1");
4006 emitcode ("xch", "a,b");
4007 emitcode ("cpl", "a"); // msb
4008 emitcode ("addc", "a,#0");
4009 emitcode ("xch", "a,b");
4012 emitcode ("", "%05d$:", lbl->key+100);
4013 aopPut (AOP (result), "a", 0);
4015 aopPut (AOP (result), "b", 1);
4019 /*-----------------------------------------------------------------*/
4020 /* genMult - generates code for multiplication */
4021 /*-----------------------------------------------------------------*/
4023 genMult (iCode * ic)
4025 operand *left = IC_LEFT (ic);
4026 operand *right = IC_RIGHT (ic);
4027 operand *result = IC_RESULT (ic);
4029 D (emitcode (";", "genMult "););
4031 /* assign the amsops */
4034 /* special cases first */
4036 if (AOP_TYPE (left) == AOP_CRY &&
4037 AOP_TYPE (right) == AOP_CRY)
4039 genMultbits (left, right, result);
4043 /* if both are of size == 1 */
4044 if (AOP_SIZE (left) == 1 &&
4045 AOP_SIZE (right) == 1)
4047 genMultOneByte (left, right, result);
4051 /* should have been converted to function call */
4055 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4056 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4057 freeAsmop (result, NULL, ic, TRUE);
4060 /*-----------------------------------------------------------------*/
4061 /* genDivbits :- division of bits */
4062 /*-----------------------------------------------------------------*/
4064 genDivbits (operand * left,
4071 /* the result must be bit */
4072 LOAD_AB_FOR_DIV (left, right, l);
4073 emitcode ("div", "ab");
4074 emitcode ("rrc", "a");
4075 aopPut (AOP (result), "c", 0);
4078 /*-----------------------------------------------------------------*/
4079 /* genDivOneByte : 8 bit division */
4080 /*-----------------------------------------------------------------*/
4082 genDivOneByte (operand * left,
4086 sym_link *opetype = operandType (result);
4091 size = AOP_SIZE (result) - 1;
4093 /* signed or unsigned */
4094 if (SPEC_USIGN (opetype))
4096 /* unsigned is easy */
4097 LOAD_AB_FOR_DIV (left, right, l);
4098 emitcode ("div", "ab");
4099 aopPut (AOP (result), "a", 0);
4101 aopPut (AOP (result), zero, offset++);
4105 /* signed is a little bit more difficult */
4107 /* save the signs of the operands */
4108 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4110 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4111 emitcode ("push", "acc"); /* save it on the stack */
4113 /* now sign adjust for both left & right */
4114 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4116 lbl = newiTempLabel (NULL);
4117 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4118 emitcode ("cpl", "a");
4119 emitcode ("inc", "a");
4120 emitcode ("", "%05d$:", (lbl->key + 100));
4121 emitcode ("mov", "b,a");
4123 /* sign adjust left side */
4124 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4127 lbl = newiTempLabel (NULL);
4128 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4129 emitcode ("cpl", "a");
4130 emitcode ("inc", "a");
4131 emitcode ("", "%05d$:", (lbl->key + 100));
4133 /* now the division */
4134 emitcode ("nop", "; workaround for DS80C390 div bug.");
4135 emitcode ("div", "ab");
4136 /* we are interested in the lower order
4138 emitcode ("mov", "b,a");
4139 lbl = newiTempLabel (NULL);
4140 emitcode ("pop", "acc");
4141 /* if there was an over flow we don't
4142 adjust the sign of the result */
4143 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4144 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4146 emitcode ("clr", "a");
4147 emitcode ("subb", "a,b");
4148 emitcode ("mov", "b,a");
4149 emitcode ("", "%05d$:", (lbl->key + 100));
4151 /* now we are done */
4152 aopPut (AOP (result), "b", 0);
4155 emitcode ("mov", "c,b.7");
4156 emitcode ("subb", "a,acc");
4159 aopPut (AOP (result), "a", offset++);
4163 /*-----------------------------------------------------------------*/
4164 /* genDiv - generates code for division */
4165 /*-----------------------------------------------------------------*/
4169 operand *left = IC_LEFT (ic);
4170 operand *right = IC_RIGHT (ic);
4171 operand *result = IC_RESULT (ic);
4173 D (emitcode (";", "genDiv ");
4176 /* assign the amsops */
4179 /* special cases first */
4181 if (AOP_TYPE (left) == AOP_CRY &&
4182 AOP_TYPE (right) == AOP_CRY)
4184 genDivbits (left, right, result);
4188 /* if both are of size == 1 */
4189 if (AOP_SIZE (left) == 1 &&
4190 AOP_SIZE (right) == 1)
4192 genDivOneByte (left, right, result);
4196 /* should have been converted to function call */
4199 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4200 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4201 freeAsmop (result, NULL, ic, TRUE);
4204 /*-----------------------------------------------------------------*/
4205 /* genModbits :- modulus of bits */
4206 /*-----------------------------------------------------------------*/
4208 genModbits (operand * left,
4215 /* the result must be bit */
4216 LOAD_AB_FOR_DIV (left, right, l);
4217 emitcode ("div", "ab");
4218 emitcode ("mov", "a,b");
4219 emitcode ("rrc", "a");
4220 aopPut (AOP (result), "c", 0);
4223 /*-----------------------------------------------------------------*/
4224 /* genModOneByte : 8 bit modulus */
4225 /*-----------------------------------------------------------------*/
4227 genModOneByte (operand * left,
4231 sym_link *opetype = operandType (result);
4235 /* signed or unsigned */
4236 if (SPEC_USIGN (opetype))
4238 /* unsigned is easy */
4239 LOAD_AB_FOR_DIV (left, right, l);
4240 emitcode ("div", "ab");
4241 aopPut (AOP (result), "b", 0);
4245 /* signed is a little bit more difficult */
4247 /* save the signs of the operands */
4248 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4251 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4252 emitcode ("push", "acc"); /* save it on the stack */
4254 /* now sign adjust for both left & right */
4255 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4258 lbl = newiTempLabel (NULL);
4259 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4260 emitcode ("cpl", "a");
4261 emitcode ("inc", "a");
4262 emitcode ("", "%05d$:", (lbl->key + 100));
4263 emitcode ("mov", "b,a");
4265 /* sign adjust left side */
4266 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4269 lbl = newiTempLabel (NULL);
4270 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4271 emitcode ("cpl", "a");
4272 emitcode ("inc", "a");
4273 emitcode ("", "%05d$:", (lbl->key + 100));
4275 /* now the multiplication */
4276 emitcode ("nop", "; workaround for DS80C390 div bug.");
4277 emitcode ("div", "ab");
4278 /* we are interested in the lower order
4280 lbl = newiTempLabel (NULL);
4281 emitcode ("pop", "acc");
4282 /* if there was an over flow we don't
4283 adjust the sign of the result */
4284 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4285 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4287 emitcode ("clr", "a");
4288 emitcode ("subb", "a,b");
4289 emitcode ("mov", "b,a");
4290 emitcode ("", "%05d$:", (lbl->key + 100));
4292 /* now we are done */
4293 aopPut (AOP (result), "b", 0);
4297 /*-----------------------------------------------------------------*/
4298 /* genMod - generates code for division */
4299 /*-----------------------------------------------------------------*/
4303 operand *left = IC_LEFT (ic);
4304 operand *right = IC_RIGHT (ic);
4305 operand *result = IC_RESULT (ic);
4307 D (emitcode (";", "genMod ");
4310 /* assign the amsops */
4313 /* special cases first */
4315 if (AOP_TYPE (left) == AOP_CRY &&
4316 AOP_TYPE (right) == AOP_CRY)
4318 genModbits (left, right, result);
4322 /* if both are of size == 1 */
4323 if (AOP_SIZE (left) == 1 &&
4324 AOP_SIZE (right) == 1)
4326 genModOneByte (left, right, result);
4330 /* should have been converted to function call */
4334 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4335 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4336 freeAsmop (result, NULL, ic, TRUE);
4339 /*-----------------------------------------------------------------*/
4340 /* genIfxJump :- will create a jump depending on the ifx */
4341 /*-----------------------------------------------------------------*/
4343 genIfxJump (iCode * ic, char *jval)
4346 symbol *tlbl = newiTempLabel (NULL);
4349 D (emitcode (";", "genIfxJump ");
4352 /* if true label then we jump if condition
4356 jlbl = IC_TRUE (ic);
4357 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4358 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4362 /* false label is present */
4363 jlbl = IC_FALSE (ic);
4364 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4365 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4367 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4368 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4370 emitcode (inst, "%05d$", tlbl->key + 100);
4371 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4372 emitcode ("", "%05d$:", tlbl->key + 100);
4374 /* mark the icode as generated */
4378 /*-----------------------------------------------------------------*/
4379 /* genCmp :- greater or less than comparison */
4380 /*-----------------------------------------------------------------*/
4382 genCmp (operand * left, operand * right,
4383 iCode * ic, iCode * ifx, int sign)
4385 int size, offset = 0;
4386 unsigned long lit = 0L;
4389 D (emitcode (";", "genCmp");
4392 result = IC_RESULT (ic);
4394 /* if left & right are bit variables */
4395 if (AOP_TYPE (left) == AOP_CRY &&
4396 AOP_TYPE (right) == AOP_CRY)
4398 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4399 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4403 /* subtract right from left if at the
4404 end the carry flag is set then we know that
4405 left is greater than right */
4406 size = max (AOP_SIZE (left), AOP_SIZE (right));
4408 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4409 if ((size == 1) && !sign &&
4410 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4412 symbol *lbl = newiTempLabel (NULL);
4413 emitcode ("cjne", "%s,%s,%05d$",
4414 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4415 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4417 emitcode ("", "%05d$:", lbl->key + 100);
4421 if (AOP_TYPE (right) == AOP_LIT)
4423 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4424 /* optimize if(x < 0) or if(x >= 0) */
4433 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4435 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4436 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4438 aopOp (result, ic, FALSE, FALSE);
4440 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4442 freeAsmop (result, NULL, ic, TRUE);
4443 genIfxJump (ifx, "acc.7");
4448 emitcode ("rlc", "a");
4450 goto release_freedLR;
4458 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4459 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4460 emitcode (";", "genCmp #2");
4461 if (sign && (size == 0))
4463 emitcode (";", "genCmp #3");
4464 emitcode ("xrl", "a,#0x80");
4465 if (AOP_TYPE (right) == AOP_LIT)
4467 unsigned long lit = (unsigned long)
4468 floatFromVal (AOP (right)->aopu.aop_lit);
4469 emitcode (";", "genCmp #3.1");
4470 emitcode ("subb", "a,#0x%02x",
4471 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4475 emitcode (";", "genCmp #3.2");
4476 if (AOP_NEEDSACC (right))
4478 emitcode ("push", "acc");
4480 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4481 FALSE, FALSE, FALSE));
4482 emitcode ("xrl", "b,#0x80");
4483 if (AOP_NEEDSACC (right))
4485 emitcode ("pop", "acc");
4487 emitcode ("subb", "a,b");
4494 emitcode (";", "genCmp #4");
4495 if (AOP_NEEDSACC (right))
4498 emitcode (";", "genCmp #4.1");
4499 emitcode ("xch", "a, b");
4500 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4501 emitcode ("xch", "a, b");
4506 emitcode (";", "genCmp #4.2");
4507 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4510 emitcode ("subb", "a,%s", s);
4517 /* Don't need the left & right operands any more; do need the result. */
4518 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4519 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521 aopOp (result, ic, FALSE, FALSE);
4525 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4531 /* if the result is used in the next
4532 ifx conditional branch then generate
4533 code a little differently */
4536 genIfxJump (ifx, "c");
4542 /* leave the result in acc */
4544 freeAsmop (result, NULL, ic, TRUE);
4547 /*-----------------------------------------------------------------*/
4548 /* genCmpGt :- greater than comparison */
4549 /*-----------------------------------------------------------------*/
4551 genCmpGt (iCode * ic, iCode * ifx)
4553 operand *left, *right;
4554 sym_link *letype, *retype;
4557 D (emitcode (";", "genCmpGt ");
4560 left = IC_LEFT (ic);
4561 right = IC_RIGHT (ic);
4563 letype = getSpec (operandType (left));
4564 retype = getSpec (operandType (right));
4565 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4567 /* assign the left & right amsops */
4570 genCmp (right, left, ic, ifx, sign);
4573 /*-----------------------------------------------------------------*/
4574 /* genCmpLt - less than comparisons */
4575 /*-----------------------------------------------------------------*/
4577 genCmpLt (iCode * ic, iCode * ifx)
4579 operand *left, *right;
4580 sym_link *letype, *retype;
4583 D (emitcode (";", "genCmpLt "););
4585 left = IC_LEFT (ic);
4586 right = IC_RIGHT (ic);
4588 letype = getSpec (operandType (left));
4589 retype = getSpec (operandType (right));
4590 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4592 /* assign the left & right amsops */
4595 genCmp (left, right, ic, ifx, sign);
4598 /*-----------------------------------------------------------------*/
4599 /* gencjneshort - compare and jump if not equal */
4600 /*-----------------------------------------------------------------*/
4602 gencjneshort (operand * left, operand * right, symbol * lbl)
4604 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4606 unsigned long lit = 0L;
4608 D (emitcode (";", "gencjneshort");
4611 /* if the left side is a literal or
4612 if the right is in a pointer register and left
4614 if ((AOP_TYPE (left) == AOP_LIT) ||
4615 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4622 if (AOP_TYPE (right) == AOP_LIT)
4623 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4625 if (opIsGptr (left) || opIsGptr (right))
4627 /* We are comparing a generic pointer to something.
4628 * Exclude the generic type byte from the comparison.
4631 D (emitcode (";", "cjneshort: generic ptr special case.");
4636 /* if the right side is a literal then anything goes */
4637 if (AOP_TYPE (right) == AOP_LIT &&
4638 AOP_TYPE (left) != AOP_DIR)
4642 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4644 emitcode ("cjne", "a,%s,%05d$",
4645 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4651 /* if the right side is in a register or in direct space or
4652 if the left is a pointer register & right is not */
4653 else if (AOP_TYPE (right) == AOP_REG ||
4654 AOP_TYPE (right) == AOP_DIR ||
4655 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4656 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4660 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4661 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4662 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4663 emitcode ("jnz", "%05d$", lbl->key + 100);
4665 emitcode ("cjne", "a,%s,%05d$",
4666 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4673 /* right is a pointer reg need both a & b */
4676 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4677 if (strcmp (l, "b"))
4678 emitcode ("mov", "b,%s", l);
4679 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4680 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4686 /*-----------------------------------------------------------------*/
4687 /* gencjne - compare and jump if not equal */
4688 /*-----------------------------------------------------------------*/
4690 gencjne (operand * left, operand * right, symbol * lbl)
4692 symbol *tlbl = newiTempLabel (NULL);
4694 D (emitcode (";", "gencjne");
4697 gencjneshort (left, right, lbl);
4699 emitcode ("mov", "a,%s", one);
4700 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4701 emitcode ("", "%05d$:", lbl->key + 100);
4702 emitcode ("clr", "a");
4703 emitcode ("", "%05d$:", tlbl->key + 100);
4706 /*-----------------------------------------------------------------*/
4707 /* genCmpEq - generates code for equal to */
4708 /*-----------------------------------------------------------------*/
4710 genCmpEq (iCode * ic, iCode * ifx)
4712 operand *left, *right, *result;
4714 D (emitcode (";", "genCmpEq ");
4718 AOP_SET_LOCALS (ic);
4720 /* if literal, literal on the right or
4721 if the right is in a pointer register and left
4723 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4724 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4726 operand *t = IC_RIGHT (ic);
4727 IC_RIGHT (ic) = IC_LEFT (ic);
4731 if (ifx && /* !AOP_SIZE(result) */
4732 OP_SYMBOL (result) &&
4733 OP_SYMBOL (result)->regType == REG_CND)
4736 /* if they are both bit variables */
4737 if (AOP_TYPE (left) == AOP_CRY &&
4738 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4740 if (AOP_TYPE (right) == AOP_LIT)
4742 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4745 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4746 emitcode ("cpl", "c");
4750 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4754 emitcode ("clr", "c");
4756 /* AOP_TYPE(right) == AOP_CRY */
4760 symbol *lbl = newiTempLabel (NULL);
4761 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4762 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4763 emitcode ("cpl", "c");
4764 emitcode ("", "%05d$:", (lbl->key + 100));
4766 /* if true label then we jump if condition
4768 tlbl = newiTempLabel (NULL);
4771 emitcode ("jnc", "%05d$", tlbl->key + 100);
4772 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4776 emitcode ("jc", "%05d$", tlbl->key + 100);
4777 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4779 emitcode ("", "%05d$:", tlbl->key + 100);
4783 tlbl = newiTempLabel (NULL);
4784 gencjneshort (left, right, tlbl);
4787 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4788 emitcode ("", "%05d$:", tlbl->key + 100);
4792 symbol *lbl = newiTempLabel (NULL);
4793 emitcode ("sjmp", "%05d$", lbl->key + 100);
4794 emitcode ("", "%05d$:", tlbl->key + 100);
4795 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4796 emitcode ("", "%05d$:", lbl->key + 100);
4799 /* mark the icode as generated */
4802 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4803 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4807 /* if they are both bit variables */
4808 if (AOP_TYPE (left) == AOP_CRY &&
4809 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4811 if (AOP_TYPE (right) == AOP_LIT)
4813 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4816 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4817 emitcode ("cpl", "c");
4821 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4825 emitcode ("clr", "c");
4827 /* AOP_TYPE(right) == AOP_CRY */
4831 symbol *lbl = newiTempLabel (NULL);
4832 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4833 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4834 emitcode ("cpl", "c");
4835 emitcode ("", "%05d$:", (lbl->key + 100));
4838 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4839 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4841 aopOp (result, ic, TRUE, FALSE);
4844 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4851 genIfxJump (ifx, "c");
4854 /* if the result is used in an arithmetic operation
4855 then put the result in place */
4860 gencjne (left, right, newiTempLabel (NULL));
4862 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865 aopOp (result, ic, TRUE, FALSE);
4867 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4869 aopPut (AOP (result), "a", 0);
4874 genIfxJump (ifx, "a");
4877 /* if the result is used in an arithmetic operation
4878 then put the result in place */
4879 if (AOP_TYPE (result) != AOP_CRY)
4881 /* leave the result in acc */
4885 freeAsmop (result, NULL, ic, TRUE);
4888 /*-----------------------------------------------------------------*/
4889 /* ifxForOp - returns the icode containing the ifx for operand */
4890 /*-----------------------------------------------------------------*/
4892 ifxForOp (operand * op, iCode * ic)
4894 /* if true symbol then needs to be assigned */
4895 if (IS_TRUE_SYMOP (op))
4898 /* if this has register type condition and
4899 the next instruction is ifx with the same operand
4900 and live to of the operand is upto the ifx only then */
4902 ic->next->op == IFX &&
4903 IC_COND (ic->next)->key == op->key &&
4904 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4909 /*-----------------------------------------------------------------*/
4910 /* genAndOp - for && operation */
4911 /*-----------------------------------------------------------------*/
4913 genAndOp (iCode * ic)
4915 operand *left, *right, *result;
4918 D (emitcode (";", "genAndOp "););
4920 /* note here that && operations that are in an
4921 if statement are taken away by backPatchLabels
4922 only those used in arthmetic operations remain */
4924 AOP_SET_LOCALS (ic);
4926 /* if both are bit variables */
4927 if (AOP_TYPE (left) == AOP_CRY &&
4928 AOP_TYPE (right) == AOP_CRY)
4930 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4931 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4932 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4933 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4935 aopOp (result,ic,FALSE, FALSE);
4940 tlbl = newiTempLabel (NULL);
4942 emitcode ("jz", "%05d$", tlbl->key + 100);
4944 emitcode ("", "%05d$:", tlbl->key + 100);
4945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4946 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4948 aopOp (result,ic,FALSE, FALSE);
4951 freeAsmop (result, NULL, ic, TRUE);
4955 /*-----------------------------------------------------------------*/
4956 /* genOrOp - for || operation */
4957 /*-----------------------------------------------------------------*/
4959 genOrOp (iCode * ic)
4961 operand *left, *right, *result;
4964 D (emitcode (";", "genOrOp "););
4966 /* note here that || operations that are in an
4967 if statement are taken away by backPatchLabels
4968 only those used in arthmetic operations remain */
4970 AOP_SET_LOCALS (ic);
4972 /* if both are bit variables */
4973 if (AOP_TYPE (left) == AOP_CRY &&
4974 AOP_TYPE (right) == AOP_CRY)
4976 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4977 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4978 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4979 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4981 aopOp (result,ic,FALSE, FALSE);
4987 tlbl = newiTempLabel (NULL);
4989 emitcode ("jnz", "%05d$", tlbl->key + 100);
4991 emitcode ("", "%05d$:", tlbl->key + 100);
4992 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4993 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4995 aopOp (result,ic,FALSE, FALSE);
5000 freeAsmop (result, NULL, ic, TRUE);
5003 /*-----------------------------------------------------------------*/
5004 /* isLiteralBit - test if lit == 2^n */
5005 /*-----------------------------------------------------------------*/
5007 isLiteralBit (unsigned long lit)
5009 unsigned long pw[32] =
5010 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5011 0x100L, 0x200L, 0x400L, 0x800L,
5012 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5013 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5014 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5015 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5016 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5019 for (idx = 0; idx < 32; idx++)
5025 /*-----------------------------------------------------------------*/
5026 /* continueIfTrue - */
5027 /*-----------------------------------------------------------------*/
5029 continueIfTrue (iCode * ic)
5032 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5036 /*-----------------------------------------------------------------*/
5038 /*-----------------------------------------------------------------*/
5040 jumpIfTrue (iCode * ic)
5043 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5047 /*-----------------------------------------------------------------*/
5048 /* jmpTrueOrFalse - */
5049 /*-----------------------------------------------------------------*/
5051 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5053 // ugly but optimized by peephole
5056 symbol *nlbl = newiTempLabel (NULL);
5057 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5058 emitcode ("", "%05d$:", tlbl->key + 100);
5059 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5060 emitcode ("", "%05d$:", nlbl->key + 100);
5064 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5065 emitcode ("", "%05d$:", tlbl->key + 100);
5070 // Generate code to perform a bit-wise logic operation
5071 // on two operands in far space (assumed to already have been
5072 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5073 // in far space. This requires pushing the result on the stack
5074 // then popping it into the result.
5076 genFarFarLogicOp(iCode *ic, char *logicOp)
5078 int size, resultSize, compSize;
5081 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5082 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
5083 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5085 _startLazyDPSEvaluation();
5086 for (size = compSize; (size--); offset++)
5088 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5089 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5090 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5092 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5093 emitcode ("push", "acc");
5095 _endLazyDPSEvaluation();
5097 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5098 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5099 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5101 resultSize = AOP_SIZE(IC_RESULT(ic));
5103 ADJUST_PUSHED_RESULT(compSize, resultSize);
5105 _startLazyDPSEvaluation();
5108 emitcode ("pop", "acc");
5109 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5111 _endLazyDPSEvaluation();
5112 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5116 /*-----------------------------------------------------------------*/
5117 /* genAnd - code for and */
5118 /*-----------------------------------------------------------------*/
5120 genAnd (iCode * ic, iCode * ifx)
5122 operand *left, *right, *result;
5123 int size, offset = 0;
5124 unsigned long lit = 0L;
5129 D (emitcode (";", "genAnd "););
5131 AOP_OP_3_NOFATAL (ic, pushResult);
5132 AOP_SET_LOCALS (ic);
5136 genFarFarLogicOp(ic, "anl");
5141 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5143 AOP_TYPE (left), AOP_TYPE (right));
5144 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5146 AOP_SIZE (left), AOP_SIZE (right));
5149 /* if left is a literal & right is not then exchange them */
5150 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5151 AOP_NEEDSACC (left))
5153 operand *tmp = right;
5158 /* if result = right then exchange them */
5159 if (sameRegs (AOP (result), AOP (right)))
5161 operand *tmp = right;
5166 /* if right is bit then exchange them */
5167 if (AOP_TYPE (right) == AOP_CRY &&
5168 AOP_TYPE (left) != AOP_CRY)
5170 operand *tmp = right;
5174 if (AOP_TYPE (right) == AOP_LIT)
5175 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5177 size = AOP_SIZE (result);
5180 // result = bit & yy;
5181 if (AOP_TYPE (left) == AOP_CRY)
5183 // c = bit & literal;
5184 if (AOP_TYPE (right) == AOP_LIT)
5188 if (size && sameRegs (AOP (result), AOP (left)))
5191 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5196 if (size && (AOP_TYPE (result) == AOP_CRY))
5198 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5201 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5206 emitcode ("clr", "c");
5211 if (AOP_TYPE (right) == AOP_CRY)
5214 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5215 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5220 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5222 emitcode ("rrc", "a");
5223 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5231 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5232 genIfxJump (ifx, "c");
5236 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5237 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5238 if ((AOP_TYPE (right) == AOP_LIT) &&
5239 (AOP_TYPE (result) == AOP_CRY) &&
5240 (AOP_TYPE (left) != AOP_CRY))
5242 int posbit = isLiteralBit (lit);
5247 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5250 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5256 sprintf (buffer, "acc.%d", posbit & 0x07);
5257 genIfxJump (ifx, buffer);
5264 symbol *tlbl = newiTempLabel (NULL);
5265 int sizel = AOP_SIZE (left);
5267 emitcode ("setb", "c");
5270 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5272 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5274 if ((posbit = isLiteralBit (bytelit)) != 0)
5275 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5278 if (bytelit != 0x0FFL)
5279 emitcode ("anl", "a,%s",
5280 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5281 emitcode ("jnz", "%05d$", tlbl->key + 100);
5286 // bit = left & literal
5289 emitcode ("clr", "c");
5290 emitcode ("", "%05d$:", tlbl->key + 100);
5292 // if(left & literal)
5296 jmpTrueOrFalse (ifx, tlbl);
5304 /* if left is same as result */
5305 if (sameRegs (AOP (result), AOP (left)))
5307 for (; size--; offset++)
5309 if (AOP_TYPE (right) == AOP_LIT)
5311 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5313 else if (bytelit == 0)
5314 aopPut (AOP (result), zero, offset);
5315 else if (IS_AOP_PREG (result))
5317 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5318 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5319 aopPut (AOP (result), "a", offset);
5322 emitcode ("anl", "%s,%s",
5323 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5324 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5328 if (AOP_TYPE (left) == AOP_ACC)
5329 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5332 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5333 if (IS_AOP_PREG (result))
5335 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5336 aopPut (AOP (result), "a", offset);
5340 emitcode ("anl", "%s,a",
5341 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5348 // left & result in different registers
5349 if (AOP_TYPE (result) == AOP_CRY)
5352 // if(size), result in bit
5353 // if(!size && ifx), conditional oper: if(left & right)
5354 symbol *tlbl = newiTempLabel (NULL);
5355 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5357 emitcode ("setb", "c");
5360 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5361 emitcode ("anl", "a,%s",
5362 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5364 if (AOP_TYPE(left)==AOP_ACC) {
5365 emitcode("mov", "b,a");
5366 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5367 emitcode("anl", "a,b");
5369 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5370 emitcode ("anl", "a,%s",
5371 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5374 emitcode ("jnz", "%05d$", tlbl->key + 100);
5380 emitcode ("", "%05d$:", tlbl->key + 100);
5384 jmpTrueOrFalse (ifx, tlbl);
5388 for (; (size--); offset++)
5391 // result = left & right
5392 if (AOP_TYPE (right) == AOP_LIT)
5394 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5396 aopPut (AOP (result),
5397 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5401 else if (bytelit == 0)
5403 aopPut (AOP (result), zero, offset);
5406 D (emitcode (";", "better literal AND.");
5408 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5409 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5410 FALSE, FALSE, FALSE));
5415 // faster than result <- left, anl result,right
5416 // and better if result is SFR
5417 if (AOP_TYPE (left) == AOP_ACC)
5419 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5420 FALSE, FALSE, FALSE));
5424 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5425 emitcode ("anl", "a,%s",
5426 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5429 aopPut (AOP (result), "a", offset);
5435 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5436 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5437 freeAsmop (result, NULL, ic, TRUE);
5441 /*-----------------------------------------------------------------*/
5442 /* genOr - code for or */
5443 /*-----------------------------------------------------------------*/
5445 genOr (iCode * ic, iCode * ifx)
5447 operand *left, *right, *result;
5448 int size, offset = 0;
5449 unsigned long lit = 0L;
5452 D (emitcode (";", "genOr "););
5454 AOP_OP_3_NOFATAL (ic, pushResult);
5455 AOP_SET_LOCALS (ic);
5459 genFarFarLogicOp(ic, "orl");
5465 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5467 AOP_TYPE (left), AOP_TYPE (right));
5468 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5470 AOP_SIZE (left), AOP_SIZE (right));
5473 /* if left is a literal & right is not then exchange them */
5474 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5475 AOP_NEEDSACC (left))
5477 operand *tmp = right;
5482 /* if result = right then exchange them */
5483 if (sameRegs (AOP (result), AOP (right)))
5485 operand *tmp = right;
5490 /* if right is bit then exchange them */
5491 if (AOP_TYPE (right) == AOP_CRY &&
5492 AOP_TYPE (left) != AOP_CRY)
5494 operand *tmp = right;
5498 if (AOP_TYPE (right) == AOP_LIT)
5499 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5501 size = AOP_SIZE (result);
5505 if (AOP_TYPE (left) == AOP_CRY)
5507 if (AOP_TYPE (right) == AOP_LIT)
5509 // c = bit & literal;
5512 // lit != 0 => result = 1
5513 if (AOP_TYPE (result) == AOP_CRY)
5516 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5518 continueIfTrue (ifx);
5521 emitcode ("setb", "c");
5525 // lit == 0 => result = left
5526 if (size && sameRegs (AOP (result), AOP (left)))
5528 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5533 if (AOP_TYPE (right) == AOP_CRY)
5536 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5537 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5542 symbol *tlbl = newiTempLabel (NULL);
5543 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5544 emitcode ("setb", "c");
5545 emitcode ("jb", "%s,%05d$",
5546 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5548 emitcode ("jnz", "%05d$", tlbl->key + 100);
5549 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5551 jmpTrueOrFalse (ifx, tlbl);
5557 emitcode ("", "%05d$:", tlbl->key + 100);
5566 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5567 genIfxJump (ifx, "c");
5571 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5572 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5573 if ((AOP_TYPE (right) == AOP_LIT) &&
5574 (AOP_TYPE (result) == AOP_CRY) &&
5575 (AOP_TYPE (left) != AOP_CRY))
5581 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5583 continueIfTrue (ifx);
5588 // lit = 0, result = boolean(left)
5590 emitcode ("setb", "c");
5594 symbol *tlbl = newiTempLabel (NULL);
5595 emitcode ("jnz", "%05d$", tlbl->key + 100);
5597 emitcode ("", "%05d$:", tlbl->key + 100);
5601 genIfxJump (ifx, "a");
5609 /* if left is same as result */
5610 if (sameRegs (AOP (result), AOP (left)))
5612 for (; size--; offset++)
5614 if (AOP_TYPE (right) == AOP_LIT)
5616 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5622 if (IS_AOP_PREG (left))
5624 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5625 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5626 aopPut (AOP (result), "a", offset);
5630 emitcode ("orl", "%s,%s",
5631 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5632 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5638 if (AOP_TYPE (left) == AOP_ACC)
5640 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5644 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5645 if (IS_AOP_PREG (left))
5647 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5648 aopPut (AOP (result), "a", offset);
5652 emitcode ("orl", "%s,a",
5653 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5661 // left & result in different registers
5662 if (AOP_TYPE (result) == AOP_CRY)
5665 // if(size), result in bit
5666 // if(!size && ifx), conditional oper: if(left | right)
5667 symbol *tlbl = newiTempLabel (NULL);
5668 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5670 emitcode ("setb", "c");
5673 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5674 emitcode ("orl", "a,%s",
5675 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5677 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5678 emitcode ("orl", "a,%s",
5679 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5681 emitcode ("jnz", "%05d$", tlbl->key + 100);
5687 emitcode ("", "%05d$:", tlbl->key + 100);
5691 jmpTrueOrFalse (ifx, tlbl);
5695 for (; (size--); offset++)
5698 // result = left & right
5699 if (AOP_TYPE (right) == AOP_LIT)
5701 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5703 aopPut (AOP (result),
5704 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5708 D (emitcode (";", "better literal OR.");
5710 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5711 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5712 FALSE, FALSE, FALSE));
5717 // faster than result <- left, anl result,right
5718 // and better if result is SFR
5719 if (AOP_TYPE (left) == AOP_ACC)
5721 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5722 FALSE, FALSE, FALSE));
5726 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5727 emitcode ("orl", "a,%s",
5728 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5731 aopPut (AOP (result), "a", offset);
5737 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5738 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5739 freeAsmop (result, NULL, ic, TRUE);
5742 /*-----------------------------------------------------------------*/
5743 /* genXor - code for xclusive or */
5744 /*-----------------------------------------------------------------*/
5746 genXor (iCode * ic, iCode * ifx)
5748 operand *left, *right, *result;
5749 int size, offset = 0;
5750 unsigned long lit = 0L;
5753 D (emitcode (";", "genXor "););
5755 AOP_OP_3_NOFATAL (ic, pushResult);
5756 AOP_SET_LOCALS (ic);
5760 genFarFarLogicOp(ic, "xrl");
5765 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5767 AOP_TYPE (left), AOP_TYPE (right));
5768 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5770 AOP_SIZE (left), AOP_SIZE (right));
5773 /* if left is a literal & right is not ||
5774 if left needs acc & right does not */
5775 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5776 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5778 operand *tmp = right;
5783 /* if result = right then exchange them */
5784 if (sameRegs (AOP (result), AOP (right)))
5786 operand *tmp = right;
5791 /* if right is bit then exchange them */
5792 if (AOP_TYPE (right) == AOP_CRY &&
5793 AOP_TYPE (left) != AOP_CRY)
5795 operand *tmp = right;
5799 if (AOP_TYPE (right) == AOP_LIT)
5800 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5802 size = AOP_SIZE (result);
5806 if (AOP_TYPE (left) == AOP_CRY)
5808 if (AOP_TYPE (right) == AOP_LIT)
5810 // c = bit & literal;
5813 // lit>>1 != 0 => result = 1
5814 if (AOP_TYPE (result) == AOP_CRY)
5817 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5819 continueIfTrue (ifx);
5822 emitcode ("setb", "c");
5829 // lit == 0, result = left
5830 if (size && sameRegs (AOP (result), AOP (left)))
5832 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5836 // lit == 1, result = not(left)
5837 if (size && sameRegs (AOP (result), AOP (left)))
5839 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5844 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5845 emitcode ("cpl", "c");
5854 symbol *tlbl = newiTempLabel (NULL);
5855 if (AOP_TYPE (right) == AOP_CRY)
5858 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5862 int sizer = AOP_SIZE (right);
5864 // if val>>1 != 0, result = 1
5865 emitcode ("setb", "c");
5868 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5870 // test the msb of the lsb
5871 emitcode ("anl", "a,#0xfe");
5872 emitcode ("jnz", "%05d$", tlbl->key + 100);
5876 emitcode ("rrc", "a");
5878 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5879 emitcode ("cpl", "c");
5880 emitcode ("", "%05d$:", (tlbl->key + 100));
5887 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5888 genIfxJump (ifx, "c");
5892 if (sameRegs (AOP (result), AOP (left)))
5894 /* if left is same as result */
5895 for (; size--; offset++)
5897 if (AOP_TYPE (right) == AOP_LIT)
5899 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5901 else if (IS_AOP_PREG (left))
5903 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5904 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5905 aopPut (AOP (result), "a", offset);
5908 emitcode ("xrl", "%s,%s",
5909 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5910 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5914 if (AOP_TYPE (left) == AOP_ACC)
5915 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5918 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5919 if (IS_AOP_PREG (left))
5921 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5922 aopPut (AOP (result), "a", offset);
5925 emitcode ("xrl", "%s,a",
5926 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5933 // left & result in different registers
5934 if (AOP_TYPE (result) == AOP_CRY)
5937 // if(size), result in bit
5938 // if(!size && ifx), conditional oper: if(left ^ right)
5939 symbol *tlbl = newiTempLabel (NULL);
5940 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5942 emitcode ("setb", "c");
5945 if ((AOP_TYPE (right) == AOP_LIT) &&
5946 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5948 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5952 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5953 emitcode ("xrl", "a,%s",
5954 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5956 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5957 emitcode ("xrl", "a,%s",
5958 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5961 emitcode ("jnz", "%05d$", tlbl->key + 100);
5967 emitcode ("", "%05d$:", tlbl->key + 100);
5971 jmpTrueOrFalse (ifx, tlbl);
5974 for (; (size--); offset++)
5977 // result = left & right
5978 if (AOP_TYPE (right) == AOP_LIT)
5980 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5982 aopPut (AOP (result),
5983 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5987 D (emitcode (";", "better literal XOR.");
5989 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5990 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5991 FALSE, FALSE, FALSE));
5995 // faster than result <- left, anl result,right
5996 // and better if result is SFR
5997 if (AOP_TYPE (left) == AOP_ACC)
5999 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6000 FALSE, FALSE, FALSE));
6004 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6005 emitcode ("xrl", "a,%s",
6006 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6009 aopPut (AOP (result), "a", offset);
6014 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6015 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6016 freeAsmop (result, NULL, ic, TRUE);
6019 /*-----------------------------------------------------------------*/
6020 /* genInline - write the inline code out */
6021 /*-----------------------------------------------------------------*/
6023 genInline (iCode * ic)
6025 char *buffer, *bp, *bp1;
6027 D (emitcode (";", "genInline ");
6030 _G.inLine += (!options.asmpeep);
6032 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6033 strcpy (buffer, IC_INLINE (ic));
6035 /* emit each line as a code */
6060 /* emitcode("",buffer); */
6061 _G.inLine -= (!options.asmpeep);
6064 /*-----------------------------------------------------------------*/
6065 /* genRRC - rotate right with carry */
6066 /*-----------------------------------------------------------------*/
6070 operand *left, *result;
6071 int size, offset = 0;
6074 D (emitcode (";", "genRRC ");
6077 /* rotate right with carry */
6078 left = IC_LEFT (ic);
6079 result = IC_RESULT (ic);
6080 aopOp (left, ic, FALSE, FALSE);
6081 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6083 /* move it to the result */
6084 size = AOP_SIZE (result);
6088 _startLazyDPSEvaluation ();
6091 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6093 emitcode ("rrc", "a");
6094 if (AOP_SIZE (result) > 1)
6095 aopPut (AOP (result), "a", offset--);
6097 _endLazyDPSEvaluation ();
6099 /* now we need to put the carry into the
6100 highest order byte of the result */
6101 if (AOP_SIZE (result) > 1)
6103 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6106 emitcode ("mov", "acc.7,c");
6107 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6108 freeAsmop (left, NULL, ic, TRUE);
6109 freeAsmop (result, NULL, ic, TRUE);
6112 /*-----------------------------------------------------------------*/
6113 /* genRLC - generate code for rotate left with carry */
6114 /*-----------------------------------------------------------------*/
6118 operand *left, *result;
6119 int size, offset = 0;
6122 D (emitcode (";", "genRLC ");
6125 /* rotate right with carry */
6126 left = IC_LEFT (ic);
6127 result = IC_RESULT (ic);
6128 aopOp (left, ic, FALSE, FALSE);
6129 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6131 /* move it to the result */
6132 size = AOP_SIZE (result);
6136 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6138 emitcode ("add", "a,acc");
6139 if (AOP_SIZE (result) > 1)
6141 aopPut (AOP (result), "a", offset++);
6144 _startLazyDPSEvaluation ();
6147 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6149 emitcode ("rlc", "a");
6150 if (AOP_SIZE (result) > 1)
6151 aopPut (AOP (result), "a", offset++);
6153 _endLazyDPSEvaluation ();
6155 /* now we need to put the carry into the
6156 highest order byte of the result */
6157 if (AOP_SIZE (result) > 1)
6159 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6162 emitcode ("mov", "acc.0,c");
6163 aopPut (AOP (result), "a", 0);
6164 freeAsmop (left, NULL, ic, TRUE);
6165 freeAsmop (result, NULL, ic, TRUE);
6168 /*-----------------------------------------------------------------*/
6169 /* genGetHbit - generates code get highest order bit */
6170 /*-----------------------------------------------------------------*/
6172 genGetHbit (iCode * ic)
6174 operand *left, *result;
6175 left = IC_LEFT (ic);
6176 result = IC_RESULT (ic);
6177 aopOp (left, ic, FALSE, FALSE);
6178 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6180 D (emitcode (";", "genGetHbit ");
6183 /* get the highest order byte into a */
6184 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6185 if (AOP_TYPE (result) == AOP_CRY)
6187 emitcode ("rlc", "a");
6192 emitcode ("rl", "a");
6193 emitcode ("anl", "a,#0x01");
6198 freeAsmop (left, NULL, ic, TRUE);
6199 freeAsmop (result, NULL, ic, TRUE);
6202 /*-----------------------------------------------------------------*/
6203 /* AccRol - rotate left accumulator by known count */
6204 /*-----------------------------------------------------------------*/
6206 AccRol (int shCount)
6208 shCount &= 0x0007; // shCount : 0..7
6215 emitcode ("rl", "a");
6218 emitcode ("rl", "a");
6219 emitcode ("rl", "a");
6222 emitcode ("swap", "a");
6223 emitcode ("rr", "a");
6226 emitcode ("swap", "a");
6229 emitcode ("swap", "a");
6230 emitcode ("rl", "a");
6233 emitcode ("rr", "a");
6234 emitcode ("rr", "a");
6237 emitcode ("rr", "a");
6242 /*-----------------------------------------------------------------*/
6243 /* AccLsh - left shift accumulator by known count */
6244 /*-----------------------------------------------------------------*/
6246 AccLsh (int shCount)
6251 emitcode ("add", "a,acc");
6252 else if (shCount == 2)
6254 emitcode ("add", "a,acc");
6255 emitcode ("add", "a,acc");
6259 /* rotate left accumulator */
6261 /* and kill the lower order bits */
6262 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6267 /*-----------------------------------------------------------------*/
6268 /* AccRsh - right shift accumulator by known count */
6269 /*-----------------------------------------------------------------*/
6271 AccRsh (int shCount)
6278 emitcode ("rrc", "a");
6282 /* rotate right accumulator */
6283 AccRol (8 - shCount);
6284 /* and kill the higher order bits */
6285 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6290 #ifdef BETTER_LITERAL_SHIFT
6291 /*-----------------------------------------------------------------*/
6292 /* AccSRsh - signed right shift accumulator by known count */
6293 /*-----------------------------------------------------------------*/
6295 AccSRsh (int shCount)
6302 emitcode ("mov", "c,acc.7");
6303 emitcode ("rrc", "a");
6305 else if (shCount == 2)
6307 emitcode ("mov", "c,acc.7");
6308 emitcode ("rrc", "a");
6309 emitcode ("mov", "c,acc.7");
6310 emitcode ("rrc", "a");
6314 tlbl = newiTempLabel (NULL);
6315 /* rotate right accumulator */
6316 AccRol (8 - shCount);
6317 /* and kill the higher order bits */
6318 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6319 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6320 emitcode ("orl", "a,#0x%02x",
6321 (unsigned char) ~SRMask[shCount]);
6322 emitcode ("", "%05d$:", tlbl->key + 100);
6328 #ifdef BETTER_LITERAL_SHIFT
6329 /*-----------------------------------------------------------------*/
6330 /* shiftR1Left2Result - shift right one byte from left to result */
6331 /*-----------------------------------------------------------------*/
6333 shiftR1Left2Result (operand * left, int offl,
6334 operand * result, int offr,
6335 int shCount, int sign)
6337 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6338 /* shift right accumulator */
6343 aopPut (AOP (result), "a", offr);
6347 #ifdef BETTER_LITERAL_SHIFT
6348 /*-----------------------------------------------------------------*/
6349 /* shiftL1Left2Result - shift left one byte from left to result */
6350 /*-----------------------------------------------------------------*/
6352 shiftL1Left2Result (operand * left, int offl,
6353 operand * result, int offr, int shCount)
6355 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6356 /* shift left accumulator */
6358 aopPut (AOP (result), "a", offr);
6362 #ifdef BETTER_LITERAL_SHIFT
6363 /*-----------------------------------------------------------------*/
6364 /* movLeft2Result - move byte from left to result */
6365 /*-----------------------------------------------------------------*/
6367 movLeft2Result (operand * left, int offl,
6368 operand * result, int offr, int sign)
6371 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6373 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6375 if (*l == '@' && (IS_AOP_PREG (result)))
6377 emitcode ("mov", "a,%s", l);
6378 aopPut (AOP (result), "a", offr);
6384 aopPut (AOP (result), l, offr);
6388 /* MSB sign in acc.7 ! */
6389 if (getDataSize (left) == offl + 1)
6391 emitcode ("mov", "a,%s", l);
6392 aopPut (AOP (result), "a", offr);
6400 #ifdef BETTER_LITERAL_SHIFT
6401 /*-----------------------------------------------------------------*/
6402 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6403 /*-----------------------------------------------------------------*/
6407 emitcode ("rrc", "a");
6408 emitcode ("xch", "a,%s", x);
6409 emitcode ("rrc", "a");
6410 emitcode ("xch", "a,%s", x);
6414 #ifdef BETTER_LITERAL_SHIFT
6416 /*-----------------------------------------------------------------*/
6417 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6418 /*-----------------------------------------------------------------*/
6422 emitcode ("xch", "a,%s", x);
6423 emitcode ("rlc", "a");
6424 emitcode ("xch", "a,%s", x);
6425 emitcode ("rlc", "a");
6429 #ifdef BETTER_LITERAL_SHIFT
6430 /*-----------------------------------------------------------------*/
6431 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6432 /*-----------------------------------------------------------------*/
6436 emitcode ("xch", "a,%s", x);
6437 emitcode ("add", "a,acc");
6438 emitcode ("xch", "a,%s", x);
6439 emitcode ("rlc", "a");
6443 #ifdef BETTER_LITERAL_SHIFT
6444 /*-----------------------------------------------------------------*/
6445 /* AccAXLsh - left shift a:x by known count (0..7) */
6446 /*-----------------------------------------------------------------*/
6448 AccAXLsh (char *x, int shCount)
6463 case 5: // AAAAABBB:CCCCCDDD
6465 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6467 emitcode ("anl", "a,#0x%02x",
6468 SLMask[shCount]); // BBB00000:CCCCCDDD
6470 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6472 AccRol (shCount); // DDDCCCCC:BBB00000
6474 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6476 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6478 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6480 emitcode ("anl", "a,#0x%02x",
6481 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6483 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6485 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6488 case 6: // AAAAAABB:CCCCCCDD
6489 emitcode ("anl", "a,#0x%02x",
6490 SRMask[shCount]); // 000000BB:CCCCCCDD
6491 emitcode ("mov", "c,acc.0"); // c = B
6492 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6494 AccAXRrl1 (x); // BCCCCCCD:D000000B
6495 AccAXRrl1 (x); // BBCCCCCC:DD000000
6497 emitcode("rrc","a");
6498 emitcode("xch","a,%s", x);
6499 emitcode("rrc","a");
6500 emitcode("mov","c,acc.0"); //<< get correct bit
6501 emitcode("xch","a,%s", x);
6503 emitcode("rrc","a");
6504 emitcode("xch","a,%s", x);
6505 emitcode("rrc","a");
6506 emitcode("xch","a,%s", x);
6509 case 7: // a:x <<= 7
6511 emitcode ("anl", "a,#0x%02x",
6512 SRMask[shCount]); // 0000000B:CCCCCCCD
6514 emitcode ("mov", "c,acc.0"); // c = B
6516 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6518 AccAXRrl1 (x); // BCCCCCCC:D0000000
6527 #ifdef BETTER_LITERAL_SHIFT
6529 /*-----------------------------------------------------------------*/
6530 /* AccAXRsh - right shift a:x known count (0..7) */
6531 /*-----------------------------------------------------------------*/
6533 AccAXRsh (char *x, int shCount)
6541 AccAXRrl1 (x); // 0->a:x
6546 AccAXRrl1 (x); // 0->a:x
6549 AccAXRrl1 (x); // 0->a:x
6554 case 5: // AAAAABBB:CCCCCDDD = a:x
6556 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6558 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6560 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6562 emitcode ("anl", "a,#0x%02x",
6563 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6565 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6567 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6569 emitcode ("anl", "a,#0x%02x",
6570 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6572 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6574 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6576 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6579 case 6: // AABBBBBB:CCDDDDDD
6581 emitcode ("mov", "c,acc.7");
6582 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6584 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6586 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6588 emitcode ("anl", "a,#0x%02x",
6589 SRMask[shCount]); // 000000AA:BBBBBBCC
6592 case 7: // ABBBBBBB:CDDDDDDD
6594 emitcode ("mov", "c,acc.7"); // c = A
6596 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6598 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6600 emitcode ("anl", "a,#0x%02x",
6601 SRMask[shCount]); // 0000000A:BBBBBBBC
6610 #ifdef BETTER_LITERAL_SHIFT
6611 /*-----------------------------------------------------------------*/
6612 /* AccAXRshS - right shift signed a:x known count (0..7) */
6613 /*-----------------------------------------------------------------*/
6615 AccAXRshS (char *x, int shCount)
6623 emitcode ("mov", "c,acc.7");
6624 AccAXRrl1 (x); // s->a:x
6628 emitcode ("mov", "c,acc.7");
6629 AccAXRrl1 (x); // s->a:x
6631 emitcode ("mov", "c,acc.7");
6632 AccAXRrl1 (x); // s->a:x
6637 case 5: // AAAAABBB:CCCCCDDD = a:x
6639 tlbl = newiTempLabel (NULL);
6640 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6642 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6644 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6646 emitcode ("anl", "a,#0x%02x",
6647 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6649 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6651 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6653 emitcode ("anl", "a,#0x%02x",
6654 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6656 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6658 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6660 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6662 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6663 emitcode ("orl", "a,#0x%02x",
6664 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6666 emitcode ("", "%05d$:", tlbl->key + 100);
6667 break; // SSSSAAAA:BBBCCCCC
6669 case 6: // AABBBBBB:CCDDDDDD
6671 tlbl = newiTempLabel (NULL);
6672 emitcode ("mov", "c,acc.7");
6673 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6675 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6677 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6679 emitcode ("anl", "a,#0x%02x",
6680 SRMask[shCount]); // 000000AA:BBBBBBCC
6682 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6683 emitcode ("orl", "a,#0x%02x",
6684 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6686 emitcode ("", "%05d$:", tlbl->key + 100);
6688 case 7: // ABBBBBBB:CDDDDDDD
6690 tlbl = newiTempLabel (NULL);
6691 emitcode ("mov", "c,acc.7"); // c = A
6693 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6695 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6697 emitcode ("anl", "a,#0x%02x",
6698 SRMask[shCount]); // 0000000A:BBBBBBBC
6700 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6701 emitcode ("orl", "a,#0x%02x",
6702 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6704 emitcode ("", "%05d$:", tlbl->key + 100);
6712 #ifdef BETTER_LITERAL_SHIFT
6714 _loadLeftIntoAx(char **lsb,
6720 // Get the initial value from left into a pair of registers.
6721 // MSB must be in A, LSB can be any register.
6723 // If the result is held in registers, it is an optimization
6724 // if the LSB can be held in the register which will hold the,
6725 // result LSB since this saves us from having to copy it into
6726 // the result following AccAXLsh.
6728 // If the result is addressed indirectly, this is not a gain.
6729 if (AOP_NEEDSACC(result))
6733 _startLazyDPSEvaluation();
6734 if (AOP_TYPE(left) == AOP_DPTR2)
6737 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6738 // get LSB in DP2_RESULT_REG.
6739 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6740 assert(!strcmp(leftByte, DP2_RESULT_REG));
6744 // get LSB into DP2_RESULT_REG
6745 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6746 if (strcmp(leftByte, DP2_RESULT_REG))
6748 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6751 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6752 assert(strcmp(leftByte, DP2_RESULT_REG));
6755 _endLazyDPSEvaluation();
6756 *lsb = DP2_RESULT_REG;
6760 if (sameRegs (AOP (result), AOP (left)) &&
6761 ((offl + MSB16) == offr))
6763 /* don't crash result[offr] */
6764 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6765 emitcode ("xch", "a,%s",
6766 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6770 movLeft2Result (left, offl, result, offr, 0);
6771 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6773 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6774 assert(strcmp(*lsb,"a"));
6779 _storeAxResults(char *lsb,
6783 _startLazyDPSEvaluation();
6784 if (AOP_NEEDSACC(result))
6786 /* We have to explicitly update the result LSB.
6788 emitcode("xch","a,%s", lsb);
6789 aopPut(AOP(result), "a", offr);
6790 emitcode("mov","a,%s", lsb);
6792 if (getDataSize (result) > 1)
6794 aopPut (AOP (result), "a", offr + MSB16);
6796 _endLazyDPSEvaluation();
6799 /*-----------------------------------------------------------------*/
6800 /* shiftL2Left2Result - shift left two bytes from left to result */
6801 /*-----------------------------------------------------------------*/
6803 shiftL2Left2Result (operand * left, int offl,
6804 operand * result, int offr, int shCount)
6808 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6810 AccAXLsh (lsb, shCount);
6812 _storeAxResults(lsb, result, offr);
6816 #ifdef BETTER_LITERAL_SHIFT
6817 /*-----------------------------------------------------------------*/
6818 /* shiftR2Left2Result - shift right two bytes from left to result */
6819 /*-----------------------------------------------------------------*/
6821 shiftR2Left2Result (operand * left, int offl,
6822 operand * result, int offr,
6823 int shCount, int sign)
6827 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6829 /* a:x >> shCount (x = lsb(result)) */
6832 AccAXRshS(lsb, shCount);
6836 AccAXRsh(lsb, shCount);
6839 _storeAxResults(lsb, result, offr);
6845 /*-----------------------------------------------------------------*/
6846 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6847 /*-----------------------------------------------------------------*/
6849 shiftLLeftOrResult (operand * left, int offl,
6850 operand * result, int offr, int shCount)
6852 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6853 /* shift left accumulator */
6855 /* or with result */
6856 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6857 /* back to result */
6858 aopPut (AOP (result), "a", offr);
6864 /*-----------------------------------------------------------------*/
6865 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6866 /*-----------------------------------------------------------------*/
6868 shiftRLeftOrResult (operand * left, int offl,
6869 operand * result, int offr, int shCount)
6871 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6872 /* shift right accumulator */
6874 /* or with result */
6875 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6876 /* back to result */
6877 aopPut (AOP (result), "a", offr);
6881 #ifdef BETTER_LITERAL_SHIFT
6882 /*-----------------------------------------------------------------*/
6883 /* genlshOne - left shift a one byte quantity by known count */
6884 /*-----------------------------------------------------------------*/
6886 genlshOne (operand * result, operand * left, int shCount)
6888 D (emitcode (";", "genlshOne "););
6889 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6893 #ifdef BETTER_LITERAL_SHIFT
6894 /*-----------------------------------------------------------------*/
6895 /* genlshTwo - left shift two bytes by known amount != 0 */
6896 /*-----------------------------------------------------------------*/
6898 genlshTwo (operand * result, operand * left, int shCount)
6902 D (emitcode (";", "genlshTwo "););
6904 size = getDataSize (result);
6906 /* if shCount >= 8 */
6911 _startLazyDPSEvaluation();
6917 _endLazyDPSEvaluation();
6918 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6919 aopPut (AOP (result), zero, LSB);
6923 movLeft2Result (left, LSB, result, MSB16, 0);
6924 aopPut (AOP (result), zero, LSB);
6925 _endLazyDPSEvaluation();
6930 aopPut (AOP (result), zero, LSB);
6931 _endLazyDPSEvaluation();
6935 /* 1 <= shCount <= 7 */
6940 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6944 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6952 /*-----------------------------------------------------------------*/
6953 /* shiftLLong - shift left one long from left to result */
6954 /* offl = LSB or MSB16 */
6955 /*-----------------------------------------------------------------*/
6957 shiftLLong (operand * left, operand * result, int offr)
6960 int size = AOP_SIZE (result);
6962 if (size >= LSB + offr)
6964 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6966 emitcode ("add", "a,acc");
6967 if (sameRegs (AOP (left), AOP (result)) &&
6968 size >= MSB16 + offr && offr != LSB)
6969 emitcode ("xch", "a,%s",
6970 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6972 aopPut (AOP (result), "a", LSB + offr);
6975 if (size >= MSB16 + offr)
6977 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6979 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6982 emitcode ("rlc", "a");
6983 if (sameRegs (AOP (left), AOP (result)) &&
6984 size >= MSB24 + offr && offr != LSB)
6985 emitcode ("xch", "a,%s",
6986 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6988 aopPut (AOP (result), "a", MSB16 + offr);
6991 if (size >= MSB24 + offr)
6993 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6995 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6998 emitcode ("rlc", "a");
6999 if (sameRegs (AOP (left), AOP (result)) &&
7000 size >= MSB32 + offr && offr != LSB)
7001 emitcode ("xch", "a,%s",
7002 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7004 aopPut (AOP (result), "a", MSB24 + offr);
7007 if (size > MSB32 + offr)
7009 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7011 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7014 emitcode ("rlc", "a");
7015 aopPut (AOP (result), "a", MSB32 + offr);
7018 aopPut (AOP (result), zero, LSB);
7024 /*-----------------------------------------------------------------*/
7025 /* genlshFour - shift four byte by a known amount != 0 */
7026 /*-----------------------------------------------------------------*/
7028 genlshFour (operand * result, operand * left, int shCount)
7032 D (emitcode (";", "genlshFour ");
7035 size = AOP_SIZE (result);
7037 /* if shifting more that 3 bytes */
7042 /* lowest order of left goes to the highest
7043 order of the destination */
7044 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7046 movLeft2Result (left, LSB, result, MSB32, 0);
7047 aopPut (AOP (result), zero, LSB);
7048 aopPut (AOP (result), zero, MSB16);
7049 aopPut (AOP (result), zero, MSB24);
7053 /* more than two bytes */
7054 else if (shCount >= 16)
7056 /* lower order two bytes goes to higher order two bytes */
7058 /* if some more remaining */
7060 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7063 movLeft2Result (left, MSB16, result, MSB32, 0);
7064 movLeft2Result (left, LSB, result, MSB24, 0);
7066 aopPut (AOP (result), zero, MSB16);
7067 aopPut (AOP (result), zero, LSB);
7071 /* if more than 1 byte */
7072 else if (shCount >= 8)
7074 /* lower order three bytes goes to higher order three bytes */
7079 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7081 movLeft2Result (left, LSB, result, MSB16, 0);
7087 movLeft2Result (left, MSB24, result, MSB32, 0);
7088 movLeft2Result (left, MSB16, result, MSB24, 0);
7089 movLeft2Result (left, LSB, result, MSB16, 0);
7090 aopPut (AOP (result), zero, LSB);
7092 else if (shCount == 1)
7093 shiftLLong (left, result, MSB16);
7096 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7097 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7098 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7099 aopPut (AOP (result), zero, LSB);
7104 /* 1 <= shCount <= 7 */
7105 else if (shCount <= 2)
7107 shiftLLong (left, result, LSB);
7109 shiftLLong (result, result, LSB);
7111 /* 3 <= shCount <= 7, optimize */
7114 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7115 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7116 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7121 #ifdef BETTER_LITERAL_SHIFT
7122 /*-----------------------------------------------------------------*/
7123 /* genLeftShiftLiteral - left shifting by known count */
7124 /*-----------------------------------------------------------------*/
7126 genLeftShiftLiteral (operand * left,
7131 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7134 size = getSize (operandType (result));
7136 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7138 /* We only handle certain easy cases so far. */
7140 && (shCount < (size * 8))
7144 D(emitcode (";", "genLeftShiftLiteral wimping out"););
7148 freeAsmop (right, NULL, ic, TRUE);
7150 aopOp(left, ic, FALSE, FALSE);
7151 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7154 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7156 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7157 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7159 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7162 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7164 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7165 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7167 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7173 emitcode ("; shift left ", "result %d, left %d", size,
7177 /* I suppose that the left size >= result size */
7180 _startLazyDPSEvaluation();
7183 movLeft2Result (left, size, result, size, 0);
7185 _endLazyDPSEvaluation();
7187 else if (shCount >= (size * 8))
7189 _startLazyDPSEvaluation();
7192 aopPut (AOP (result), zero, size);
7194 _endLazyDPSEvaluation();
7201 genlshOne (result, left, shCount);
7205 genlshTwo (result, left, shCount);
7209 genlshFour (result, left, shCount);
7213 fprintf(stderr, "*** ack! mystery literal shift!\n");
7217 freeAsmop (left, NULL, ic, TRUE);
7218 freeAsmop (result, NULL, ic, TRUE);
7223 /*-----------------------------------------------------------------*/
7224 /* genLeftShift - generates code for left shifting */
7225 /*-----------------------------------------------------------------*/
7227 genLeftShift (iCode * ic)
7229 operand *left, *right, *result;
7232 symbol *tlbl, *tlbl1;
7234 D (emitcode (";", "genLeftShift "););
7236 right = IC_RIGHT (ic);
7237 left = IC_LEFT (ic);
7238 result = IC_RESULT (ic);
7240 aopOp (right, ic, FALSE, FALSE);
7243 #ifdef BETTER_LITERAL_SHIFT
7244 /* if the shift count is known then do it
7245 as efficiently as possible */
7246 if (AOP_TYPE (right) == AOP_LIT)
7248 if (genLeftShiftLiteral (left, right, result, ic))
7255 /* shift count is unknown then we have to form
7256 a loop get the loop count in B : Note: we take
7257 only the lower order byte since shifting
7258 more that 32 bits make no sense anyway, ( the
7259 largest size of an object can be only 32 bits ) */
7261 if (AOP_TYPE (right) == AOP_LIT)
7263 /* Really should be handled by genLeftShiftLiteral,
7264 * but since I'm too lazy to fix that today, at least we can make
7265 * some small improvement.
7267 emitcode("mov", "b,#0x%02x",
7268 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7272 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7273 emitcode ("inc", "b");
7275 freeAsmop (right, NULL, ic, TRUE);
7276 aopOp (left, ic, FALSE, FALSE);
7277 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7279 /* now move the left to the result if they are not the
7281 if (!sameRegs (AOP (left), AOP (result)) &&
7282 AOP_SIZE (result) > 1)
7285 size = AOP_SIZE (result);
7287 _startLazyDPSEvaluation ();
7290 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7291 if (*l == '@' && (IS_AOP_PREG (result)))
7294 emitcode ("mov", "a,%s", l);
7295 aopPut (AOP (result), "a", offset);
7298 aopPut (AOP (result), l, offset);
7301 _endLazyDPSEvaluation ();
7304 tlbl = newiTempLabel (NULL);
7305 size = AOP_SIZE (result);
7307 tlbl1 = newiTempLabel (NULL);
7309 /* if it is only one byte then */
7312 symbol *tlbl1 = newiTempLabel (NULL);
7314 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7316 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7317 emitcode ("", "%05d$:", tlbl->key + 100);
7318 emitcode ("add", "a,acc");
7319 emitcode ("", "%05d$:", tlbl1->key + 100);
7320 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7321 aopPut (AOP (result), "a", 0);
7325 reAdjustPreg (AOP (result));
7327 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7328 emitcode ("", "%05d$:", tlbl->key + 100);
7329 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7331 emitcode ("add", "a,acc");
7332 aopPut (AOP (result), "a", offset++);
7333 _startLazyDPSEvaluation ();
7336 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7338 emitcode ("rlc", "a");
7339 aopPut (AOP (result), "a", offset++);
7341 _endLazyDPSEvaluation ();
7342 reAdjustPreg (AOP (result));
7344 emitcode ("", "%05d$:", tlbl1->key + 100);
7345 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7347 freeAsmop (left, NULL, ic, TRUE);
7348 freeAsmop (result, NULL, ic, TRUE);
7351 #ifdef BETTER_LITERAL_SHIFT
7352 /*-----------------------------------------------------------------*/
7353 /* genrshOne - right shift a one byte quantity by known count */
7354 /*-----------------------------------------------------------------*/
7356 genrshOne (operand * result, operand * left,
7357 int shCount, int sign)
7359 D (emitcode (";", "genrshOne"););
7360 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7364 #ifdef BETTER_LITERAL_SHIFT
7365 /*-----------------------------------------------------------------*/
7366 /* genrshTwo - right shift two bytes by known amount != 0 */
7367 /*-----------------------------------------------------------------*/
7369 genrshTwo (operand * result, operand * left,
7370 int shCount, int sign)
7372 D (emitcode (";", "genrshTwo"););
7374 /* if shCount >= 8 */
7378 _startLazyDPSEvaluation();
7381 shiftR1Left2Result (left, MSB16, result, LSB,
7386 movLeft2Result (left, MSB16, result, LSB, sign);
7388 addSign (result, MSB16, sign);
7389 _endLazyDPSEvaluation();
7392 /* 1 <= shCount <= 7 */
7395 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7402 /*-----------------------------------------------------------------*/
7403 /* shiftRLong - shift right one long from left to result */
7404 /* offl = LSB or MSB16 */
7405 /*-----------------------------------------------------------------*/
7407 shiftRLong (operand * left, int offl,
7408 operand * result, int sign)
7410 int isSameRegs=sameRegs(AOP(left),AOP(result));
7412 if (isSameRegs && offl>1) {
7413 // we are in big trouble, but this shouldn't happen
7414 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7417 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7422 emitcode ("rlc", "a");
7423 emitcode ("subb", "a,acc");
7424 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7426 aopPut (AOP(result), zero, MSB32);
7431 emitcode ("clr", "c");
7433 emitcode ("mov", "c,acc.7");
7436 emitcode ("rrc", "a");
7438 if (isSameRegs && offl==MSB16) {
7439 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7441 aopPut (AOP (result), "a", MSB32);
7442 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7445 emitcode ("rrc", "a");
7446 if (isSameRegs && offl==1) {
7447 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7449 aopPut (AOP (result), "a", MSB24);
7450 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7452 emitcode ("rrc", "a");
7453 aopPut (AOP (result), "a", MSB16 - offl);
7457 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7458 emitcode ("rrc", "a");
7459 aopPut (AOP (result), "a", LSB);
7466 /*-----------------------------------------------------------------*/
7467 /* genrshFour - shift four byte by a known amount != 0 */
7468 /*-----------------------------------------------------------------*/
7470 genrshFour (operand * result, operand * left,
7471 int shCount, int sign)
7473 D (emitcode (";", "genrshFour");
7476 /* if shifting more that 3 bytes */
7481 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7483 movLeft2Result (left, MSB32, result, LSB, sign);
7484 addSign (result, MSB16, sign);
7486 else if (shCount >= 16)
7490 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7493 movLeft2Result (left, MSB24, result, LSB, 0);
7494 movLeft2Result (left, MSB32, result, MSB16, sign);
7496 addSign (result, MSB24, sign);
7498 else if (shCount >= 8)
7502 shiftRLong (left, MSB16, result, sign);
7503 else if (shCount == 0)
7505 movLeft2Result (left, MSB16, result, LSB, 0);
7506 movLeft2Result (left, MSB24, result, MSB16, 0);
7507 movLeft2Result (left, MSB32, result, MSB24, sign);
7508 addSign (result, MSB32, sign);
7512 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7513 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7514 /* the last shift is signed */
7515 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7516 addSign (result, MSB32, sign);
7520 { /* 1 <= shCount <= 7 */
7523 shiftRLong (left, LSB, result, sign);
7525 shiftRLong (result, LSB, result, sign);
7529 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7530 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7531 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7537 #ifdef BETTER_LITERAL_SHIFT
7538 /*-----------------------------------------------------------------*/
7539 /* genRightShiftLiteral - right shifting by known count */
7540 /*-----------------------------------------------------------------*/
7542 genRightShiftLiteral (operand * left,
7548 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7551 size = getSize (operandType (result));
7553 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7555 /* We only handle certain easy cases so far. */
7557 && (shCount < (size * 8))
7561 D(emitcode (";", "genRightShiftLiteral wimping out"););
7565 freeAsmop (right, NULL, ic, TRUE);
7567 aopOp (left, ic, FALSE, FALSE);
7568 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7571 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7575 /* test the LEFT size !!! */
7577 /* I suppose that the left size >= result size */
7580 size = getDataSize (result);
7581 _startLazyDPSEvaluation();
7584 movLeft2Result (left, size, result, size, 0);
7586 _endLazyDPSEvaluation();
7588 else if (shCount >= (size * 8))
7592 /* get sign in acc.7 */
7593 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7595 addSign (result, LSB, sign);
7602 genrshOne (result, left, shCount, sign);
7606 genrshTwo (result, left, shCount, sign);
7610 genrshFour (result, left, shCount, sign);
7617 freeAsmop (left, NULL, ic, TRUE);
7618 freeAsmop (result, NULL, ic, TRUE);
7624 /*-----------------------------------------------------------------*/
7625 /* genSignedRightShift - right shift of signed number */
7626 /*-----------------------------------------------------------------*/
7628 genSignedRightShift (iCode * ic)
7630 operand *right, *left, *result;
7633 symbol *tlbl, *tlbl1;
7635 D (emitcode (";", "genSignedRightShift "););
7637 /* we do it the hard way put the shift count in b
7638 and loop thru preserving the sign */
7640 right = IC_RIGHT (ic);
7641 left = IC_LEFT (ic);
7642 result = IC_RESULT (ic);
7644 aopOp (right, ic, FALSE, FALSE);
7646 #ifdef BETTER_LITERAL_SHIFT
7647 if (AOP_TYPE (right) == AOP_LIT)
7649 if (genRightShiftLiteral (left, right, result, ic, 1))
7655 /* shift count is unknown then we have to form
7656 a loop get the loop count in B : Note: we take
7657 only the lower order byte since shifting
7658 more that 32 bits make no sense anyway, ( the
7659 largest size of an object can be only 32 bits ) */
7661 if (AOP_TYPE (right) == AOP_LIT)
7663 /* Really should be handled by genRightShiftLiteral,
7664 * but since I'm too lazy to fix that today, at least we can make
7665 * some small improvement.
7667 emitcode("mov", "b,#0x%02x",
7668 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7672 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7673 emitcode ("inc", "b");
7675 freeAsmop (right, NULL, ic, TRUE);
7676 aopOp (left, ic, FALSE, FALSE);
7677 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7679 /* now move the left to the result if they are not the
7681 if (!sameRegs (AOP (left), AOP (result)) &&
7682 AOP_SIZE (result) > 1)
7685 size = AOP_SIZE (result);
7687 _startLazyDPSEvaluation ();
7690 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7691 if (*l == '@' && IS_AOP_PREG (result))
7694 emitcode ("mov", "a,%s", l);
7695 aopPut (AOP (result), "a", offset);
7698 aopPut (AOP (result), l, offset);
7701 _endLazyDPSEvaluation ();
7704 /* mov the highest order bit to OVR */
7705 tlbl = newiTempLabel (NULL);
7706 tlbl1 = newiTempLabel (NULL);
7708 size = AOP_SIZE (result);
7710 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7711 emitcode ("rlc", "a");
7712 emitcode ("mov", "ov,c");
7713 /* if it is only one byte then */
7716 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7718 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7719 emitcode ("", "%05d$:", tlbl->key + 100);
7720 emitcode ("mov", "c,ov");
7721 emitcode ("rrc", "a");
7722 emitcode ("", "%05d$:", tlbl1->key + 100);
7723 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7724 aopPut (AOP (result), "a", 0);
7728 reAdjustPreg (AOP (result));
7729 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7730 emitcode ("", "%05d$:", tlbl->key + 100);
7731 emitcode ("mov", "c,ov");
7732 _startLazyDPSEvaluation ();
7735 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7737 emitcode ("rrc", "a");
7738 aopPut (AOP (result), "a", offset--);
7740 _endLazyDPSEvaluation ();
7741 reAdjustPreg (AOP (result));
7742 emitcode ("", "%05d$:", tlbl1->key + 100);
7743 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7746 freeAsmop (left, NULL, ic, TRUE);
7747 freeAsmop (result, NULL, ic, TRUE);
7750 /*-----------------------------------------------------------------*/
7751 /* genRightShift - generate code for right shifting */
7752 /*-----------------------------------------------------------------*/
7754 genRightShift (iCode * ic)
7756 operand *right, *left, *result;
7760 symbol *tlbl, *tlbl1;
7762 D (emitcode (";", "genRightShift "););
7764 /* if signed then we do it the hard way preserve the
7765 sign bit moving it inwards */
7766 retype = getSpec (operandType (IC_RESULT (ic)));
7768 if (!SPEC_USIGN (retype))
7770 genSignedRightShift (ic);
7774 /* signed & unsigned types are treated the same : i.e. the
7775 signed is NOT propagated inwards : quoting from the
7776 ANSI - standard : "for E1 >> E2, is equivalent to division
7777 by 2**E2 if unsigned or if it has a non-negative value,
7778 otherwise the result is implementation defined ", MY definition
7779 is that the sign does not get propagated */
7781 right = IC_RIGHT (ic);
7782 left = IC_LEFT (ic);
7783 result = IC_RESULT (ic);
7785 aopOp (right, ic, FALSE, FALSE);
7787 #ifdef BETTER_LITERAL_SHIFT
7788 /* if the shift count is known then do it
7789 as efficiently as possible */
7790 if (AOP_TYPE (right) == AOP_LIT)
7792 if (genRightShiftLiteral (left, right, result, ic, 0))
7799 /* shift count is unknown then we have to form
7800 a loop get the loop count in B : Note: we take
7801 only the lower order byte since shifting
7802 more that 32 bits make no sense anyway, ( the
7803 largest size of an object can be only 32 bits ) */
7805 if (AOP_TYPE (right) == AOP_LIT)
7807 /* Really should be handled by genRightShiftLiteral,
7808 * but since I'm too lazy to fix that today, at least we can make
7809 * some small improvement.
7811 emitcode("mov", "b,#0x%02x",
7812 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7816 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7817 emitcode ("inc", "b");
7819 freeAsmop (right, NULL, ic, TRUE);
7820 aopOp (left, ic, FALSE, FALSE);
7821 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7823 /* now move the left to the result if they are not the
7825 if (!sameRegs (AOP (left), AOP (result)) &&
7826 AOP_SIZE (result) > 1)
7829 size = AOP_SIZE (result);
7831 _startLazyDPSEvaluation ();
7834 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7835 if (*l == '@' && IS_AOP_PREG (result))
7838 emitcode ("mov", "a,%s", l);
7839 aopPut (AOP (result), "a", offset);
7842 aopPut (AOP (result), l, offset);
7845 _endLazyDPSEvaluation ();
7848 tlbl = newiTempLabel (NULL);
7849 tlbl1 = newiTempLabel (NULL);
7850 size = AOP_SIZE (result);
7853 /* if it is only one byte then */
7856 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7858 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7859 emitcode ("", "%05d$:", tlbl->key + 100);
7861 emitcode ("rrc", "a");
7862 emitcode ("", "%05d$:", tlbl1->key + 100);
7863 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7864 aopPut (AOP (result), "a", 0);
7868 reAdjustPreg (AOP (result));
7869 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7870 emitcode ("", "%05d$:", tlbl->key + 100);
7872 _startLazyDPSEvaluation ();
7875 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7877 emitcode ("rrc", "a");
7878 aopPut (AOP (result), "a", offset--);
7880 _endLazyDPSEvaluation ();
7881 reAdjustPreg (AOP (result));
7883 emitcode ("", "%05d$:", tlbl1->key + 100);
7884 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7887 freeAsmop (left, NULL, ic, TRUE);
7888 freeAsmop (result, NULL, ic, TRUE);
7891 /*-----------------------------------------------------------------*/
7892 /* genUnpackBits - generates code for unpacking bits */
7893 /*-----------------------------------------------------------------*/
7895 genUnpackBits (operand * result, char *rname, int ptype)
7902 D (emitcode (";", "genUnpackBits ");
7905 etype = getSpec (operandType (result));
7907 /* read the first byte */
7913 emitcode ("mov", "a,@%s", rname);
7917 emitcode ("movx", "a,@%s", rname);
7921 emitcode ("movx", "a,@dptr");
7925 emitcode ("clr", "a");
7926 emitcode ("movc", "a", "@a+dptr");
7930 emitcode ("lcall", "__gptrget");
7934 /* if we have bitdisplacement then it fits */
7935 /* into this byte completely or if length is */
7936 /* less than a byte */
7937 if ((shCnt = SPEC_BSTR (etype)) ||
7938 (SPEC_BLEN (etype) <= 8))
7941 /* shift right acc */
7944 emitcode ("anl", "a,#0x%02x",
7945 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7946 aopPut (AOP (result), "a", offset);
7950 /* bit field did not fit in a byte */
7951 rlen = SPEC_BLEN (etype) - 8;
7952 aopPut (AOP (result), "a", offset++);
7961 emitcode ("inc", "%s", rname);
7962 emitcode ("mov", "a,@%s", rname);
7966 emitcode ("inc", "%s", rname);
7967 emitcode ("movx", "a,@%s", rname);
7971 emitcode ("inc", "dptr");
7972 emitcode ("movx", "a,@dptr");
7976 emitcode ("clr", "a");
7977 emitcode ("inc", "dptr");
7978 emitcode ("movc", "a", "@a+dptr");
7982 emitcode ("inc", "dptr");
7983 emitcode ("lcall", "__gptrget");
7988 /* if we are done */
7992 aopPut (AOP (result), "a", offset++);
7998 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7999 aopPut (AOP (result), "a", offset);
8006 /*-----------------------------------------------------------------*/
8007 /* genDataPointerGet - generates code when ptr offset is known */
8008 /*-----------------------------------------------------------------*/
8010 genDataPointerGet (operand * left,
8016 int size, offset = 0;
8017 aopOp (result, ic, TRUE, FALSE);
8019 /* get the string representation of the name */
8020 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8021 size = AOP_SIZE (result);
8022 _startLazyDPSEvaluation ();
8026 sprintf (buffer, "(%s + %d)", l + 1, offset);
8028 sprintf (buffer, "%s", l + 1);
8029 aopPut (AOP (result), buffer, offset++);
8031 _endLazyDPSEvaluation ();
8033 freeAsmop (left, NULL, ic, TRUE);
8034 freeAsmop (result, NULL, ic, TRUE);
8037 /*-----------------------------------------------------------------*/
8038 /* genNearPointerGet - emitcode for near pointer fetch */
8039 /*-----------------------------------------------------------------*/
8041 genNearPointerGet (operand * left,
8048 sym_link *rtype, *retype, *letype;
8049 sym_link *ltype = operandType (left);
8052 rtype = operandType (result);
8053 retype = getSpec (rtype);
8054 letype = getSpec (ltype);
8056 aopOp (left, ic, FALSE, FALSE);
8058 /* if left is rematerialisable and
8059 result is not bit variable type and
8060 the left is pointer to data space i.e
8061 lower 128 bytes of space */
8062 if (AOP_TYPE (left) == AOP_IMMD &&
8063 !IS_BITVAR (retype) &&
8064 !IS_BITVAR (letype) &&
8065 DCL_TYPE (ltype) == POINTER)
8067 genDataPointerGet (left, result, ic);
8071 /* if the value is already in a pointer register
8072 then don't need anything more */
8073 if (!AOP_INPREG (AOP (left)))
8075 /* otherwise get a free pointer register */
8077 preg = getFreePtr (ic, &aop, FALSE);
8078 emitcode ("mov", "%s,%s",
8080 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8084 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8086 freeAsmop (left, NULL, ic, TRUE);
8087 aopOp (result, ic, FALSE, FALSE);
8089 /* if bitfield then unpack the bits */
8090 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8091 genUnpackBits (result, rname, POINTER);
8094 /* we have can just get the values */
8095 int size = AOP_SIZE (result);
8100 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8103 emitcode ("mov", "a,@%s", rname);
8104 aopPut (AOP (result), "a", offset);
8108 sprintf (buffer, "@%s", rname);
8109 aopPut (AOP (result), buffer, offset);
8113 emitcode ("inc", "%s", rname);
8117 /* now some housekeeping stuff */
8120 /* we had to allocate for this iCode */
8121 freeAsmop (NULL, aop, ic, TRUE);
8125 /* we did not allocate which means left
8126 already in a pointer register, then
8127 if size > 0 && this could be used again
8128 we have to point it back to where it
8130 if (AOP_SIZE (result) > 1 &&
8131 !OP_SYMBOL (left)->remat &&
8132 (OP_SYMBOL (left)->liveTo > ic->seq ||
8135 int size = AOP_SIZE (result) - 1;
8137 emitcode ("dec", "%s", rname);
8142 freeAsmop (result, NULL, ic, TRUE);
8146 /*-----------------------------------------------------------------*/
8147 /* genPagedPointerGet - emitcode for paged pointer fetch */
8148 /*-----------------------------------------------------------------*/
8150 genPagedPointerGet (operand * left,
8157 sym_link *rtype, *retype, *letype;
8159 rtype = operandType (result);
8160 retype = getSpec (rtype);
8161 letype = getSpec (operandType (left));
8162 aopOp (left, ic, FALSE, FALSE);
8164 /* if the value is already in a pointer register
8165 then don't need anything more */
8166 if (!AOP_INPREG (AOP (left)))
8168 /* otherwise get a free pointer register */
8170 preg = getFreePtr (ic, &aop, FALSE);
8171 emitcode ("mov", "%s,%s",
8173 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8177 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8179 freeAsmop (left, NULL, ic, TRUE);
8180 aopOp (result, ic, FALSE, FALSE);
8182 /* if bitfield then unpack the bits */
8183 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8184 genUnpackBits (result, rname, PPOINTER);
8187 /* we have can just get the values */
8188 int size = AOP_SIZE (result);
8194 emitcode ("movx", "a,@%s", rname);
8195 aopPut (AOP (result), "a", offset);
8200 emitcode ("inc", "%s", rname);
8204 /* now some housekeeping stuff */
8207 /* we had to allocate for this iCode */
8208 freeAsmop (NULL, aop, ic, TRUE);
8212 /* we did not allocate which means left
8213 already in a pointer register, then
8214 if size > 0 && this could be used again
8215 we have to point it back to where it
8217 if (AOP_SIZE (result) > 1 &&
8218 !OP_SYMBOL (left)->remat &&
8219 (OP_SYMBOL (left)->liveTo > ic->seq ||
8222 int size = AOP_SIZE (result) - 1;
8224 emitcode ("dec", "%s", rname);
8229 freeAsmop (result, NULL, ic, TRUE);
8234 /*-----------------------------------------------------------------*/
8235 /* genFarPointerGet - gget value from far space */
8236 /*-----------------------------------------------------------------*/
8238 genFarPointerGet (operand * left,
8239 operand * result, iCode * ic)
8242 sym_link *retype = getSpec (operandType (result));
8243 sym_link *letype = getSpec (operandType (left));
8244 D (emitcode (";", "genFarPointerGet");
8247 aopOp (left, ic, FALSE, FALSE);
8249 /* if the operand is already in dptr
8250 then we do nothing else we move the value to dptr */
8251 if (AOP_TYPE (left) != AOP_STR)
8253 /* if this is remateriazable */
8254 if (AOP_TYPE (left) == AOP_IMMD)
8256 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8260 /* we need to get it byte by byte */
8261 _startLazyDPSEvaluation ();
8262 if (AOP_TYPE (left) != AOP_DPTR)
8264 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8265 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8266 if (options.model == MODEL_FLAT24)
8267 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8271 /* We need to generate a load to DPTR indirect through DPTR. */
8272 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8274 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8275 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8276 if (options.model == MODEL_FLAT24)
8277 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8278 emitcode ("pop", "dph");
8279 emitcode ("pop", "dpl");
8281 _endLazyDPSEvaluation ();
8284 /* so dptr know contains the address */
8285 freeAsmop (left, NULL, ic, TRUE);
8286 aopOp (result, ic, FALSE, TRUE);
8288 /* if bit then unpack */
8289 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8290 genUnpackBits (result, "dptr", FPOINTER);
8293 size = AOP_SIZE (result);
8296 _startLazyDPSEvaluation ();
8303 emitcode ("movx", "a,@dptr");
8305 emitcode ("inc", "dptr");
8307 aopPut (AOP (result), "a", offset++);
8309 _endLazyDPSEvaluation ();
8312 freeAsmop (result, NULL, ic, TRUE);
8315 /*-----------------------------------------------------------------*/
8316 /* emitcodePointerGet - gget value from code space */
8317 /*-----------------------------------------------------------------*/
8319 emitcodePointerGet (operand * left,
8320 operand * result, iCode * ic)
8323 sym_link *retype = getSpec (operandType (result));
8325 aopOp (left, ic, FALSE, FALSE);
8327 /* if the operand is already in dptr
8328 then we do nothing else we move the value to dptr */
8329 if (AOP_TYPE (left) != AOP_STR)
8331 /* if this is remateriazable */
8332 if (AOP_TYPE (left) == AOP_IMMD)
8334 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8337 { /* we need to get it byte by byte */
8338 _startLazyDPSEvaluation ();
8339 if (AOP_TYPE (left) != AOP_DPTR)
8341 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8342 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8343 if (options.model == MODEL_FLAT24)
8344 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8348 /* We need to generate a load to DPTR indirect through DPTR. */
8349 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8351 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8352 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8353 if (options.model == MODEL_FLAT24)
8354 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8355 emitcode ("pop", "dph");
8356 emitcode ("pop", "dpl");
8358 _endLazyDPSEvaluation ();
8361 /* so dptr know contains the address */
8362 freeAsmop (left, NULL, ic, TRUE);
8363 aopOp (result, ic, FALSE, TRUE);
8365 /* if bit then unpack */
8366 if (IS_BITVAR (retype))
8367 genUnpackBits (result, "dptr", CPOINTER);
8370 size = AOP_SIZE (result);
8373 _startLazyDPSEvaluation ();
8379 emitcode ("clr", "a");
8380 emitcode ("movc", "a,@a+dptr");
8382 emitcode ("inc", "dptr");
8383 aopPut (AOP (result), "a", offset++);
8385 _endLazyDPSEvaluation ();
8388 freeAsmop (result, NULL, ic, TRUE);
8391 /*-----------------------------------------------------------------*/
8392 /* genGenPointerGet - gget value from generic pointer space */
8393 /*-----------------------------------------------------------------*/
8395 genGenPointerGet (operand * left,
8396 operand * result, iCode * ic)
8399 sym_link *retype = getSpec (operandType (result));
8400 sym_link *letype = getSpec (operandType (left));
8402 D (emitcode (";", "genGenPointerGet "); );
8404 aopOp (left, ic, FALSE, TRUE);
8406 /* if the operand is already in dptr
8407 then we do nothing else we move the value to dptr */
8408 if (AOP_TYPE (left) != AOP_STR)
8410 /* if this is remateriazable */
8411 if (AOP_TYPE (left) == AOP_IMMD)
8413 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8414 emitcode ("mov", "b,#%d", pointerCode (retype));
8417 { /* we need to get it byte by byte */
8418 _startLazyDPSEvaluation ();
8419 if (AOP(left)->type==AOP_DPTR2) {
8421 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8424 emitcode ("mov", "dpl,%s", l);
8425 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8428 emitcode ("mov", "dph,%s", l);
8429 if (options.model == MODEL_FLAT24) {
8430 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8433 emitcode ("mov", "dpx,%s", l);
8434 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8436 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8439 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8440 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8441 if (options.model == MODEL_FLAT24) {
8442 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8443 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8445 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8448 _endLazyDPSEvaluation ();
8451 /* so dptr know contains the address */
8452 freeAsmop (left, NULL, ic, TRUE);
8453 aopOp (result, ic, FALSE, TRUE);
8455 /* if bit then unpack */
8456 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8457 genUnpackBits (result, "dptr", GPOINTER);
8460 size = AOP_SIZE (result);
8465 emitcode ("lcall", "__gptrget");
8466 aopPut (AOP (result), "a", offset++);
8468 emitcode ("inc", "dptr");
8472 freeAsmop (result, NULL, ic, TRUE);
8475 /*-----------------------------------------------------------------*/
8476 /* genPointerGet - generate code for pointer get */
8477 /*-----------------------------------------------------------------*/
8479 genPointerGet (iCode * ic)
8481 operand *left, *result;
8482 sym_link *type, *etype;
8485 D (emitcode (";", "genPointerGet ");
8488 left = IC_LEFT (ic);
8489 result = IC_RESULT (ic);
8491 /* depending on the type of pointer we need to
8492 move it to the correct pointer register */
8493 type = operandType (left);
8494 etype = getSpec (type);
8495 /* if left is of type of pointer then it is simple */
8496 if (IS_PTR (type) && !IS_FUNC (type->next))
8497 p_type = DCL_TYPE (type);
8500 /* we have to go by the storage class */
8501 p_type = PTR_TYPE (SPEC_OCLS (etype));
8504 /* now that we have the pointer type we assign
8505 the pointer values */
8511 genNearPointerGet (left, result, ic);
8515 genPagedPointerGet (left, result, ic);
8519 genFarPointerGet (left, result, ic);
8523 emitcodePointerGet (left, result, ic);
8527 genGenPointerGet (left, result, ic);
8533 /*-----------------------------------------------------------------*/
8534 /* genPackBits - generates code for packed bit storage */
8535 /*-----------------------------------------------------------------*/
8537 genPackBits (sym_link * etype,
8539 char *rname, int p_type)
8547 blen = SPEC_BLEN (etype);
8548 bstr = SPEC_BSTR (etype);
8550 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8553 /* if the bit lenth is less than or */
8554 /* it exactly fits a byte then */
8555 if (SPEC_BLEN (etype) <= 8)
8557 shCount = SPEC_BSTR (etype);
8559 /* shift left acc */
8562 if (SPEC_BLEN (etype) < 8)
8563 { /* if smaller than a byte */
8569 emitcode ("mov", "b,a");
8570 emitcode ("mov", "a,@%s", rname);
8574 emitcode ("mov", "b,a");
8575 emitcode ("movx", "a,@dptr");
8579 emitcode ("push", "b");
8580 emitcode ("push", "acc");
8581 emitcode ("lcall", "__gptrget");
8582 emitcode ("pop", "b");
8586 emitcode ("anl", "a,#0x%02x", (unsigned char)
8587 ((unsigned char) (0xFF << (blen + bstr)) |
8588 (unsigned char) (0xFF >> (8 - bstr))));
8589 emitcode ("orl", "a,b");
8590 if (p_type == GPOINTER)
8591 emitcode ("pop", "b");
8598 emitcode ("mov", "@%s,a", rname);
8602 emitcode ("movx", "@dptr,a");
8606 emitcode ("lcall", "__gptrput");
8611 if (SPEC_BLEN (etype) <= 8)
8614 emitcode ("inc", "%s", rname);
8615 rLen = SPEC_BLEN (etype);
8617 /* now generate for lengths greater than one byte */
8621 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8633 emitcode ("mov", "@%s,a", rname);
8636 emitcode ("mov", "@%s,%s", rname, l);
8641 emitcode ("movx", "@dptr,a");
8646 emitcode ("lcall", "__gptrput");
8649 emitcode ("inc", "%s", rname);
8654 /* last last was not complete */
8657 /* save the byte & read byte */
8661 emitcode ("mov", "b,a");
8662 emitcode ("mov", "a,@%s", rname);
8666 emitcode ("mov", "b,a");
8667 emitcode ("movx", "a,@dptr");
8671 emitcode ("push", "b");
8672 emitcode ("push", "acc");
8673 emitcode ("lcall", "__gptrget");
8674 emitcode ("pop", "b");
8678 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8679 emitcode ("orl", "a,b");
8682 if (p_type == GPOINTER)
8683 emitcode ("pop", "b");
8689 emitcode ("mov", "@%s,a", rname);
8693 emitcode ("movx", "@dptr,a");
8697 emitcode ("lcall", "__gptrput");
8701 /*-----------------------------------------------------------------*/
8702 /* genDataPointerSet - remat pointer to data space */
8703 /*-----------------------------------------------------------------*/
8705 genDataPointerSet (operand * right,
8709 int size, offset = 0;
8710 char *l, buffer[256];
8712 aopOp (right, ic, FALSE, FALSE);
8714 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8715 size = AOP_SIZE (right);
8719 sprintf (buffer, "(%s + %d)", l + 1, offset);
8721 sprintf (buffer, "%s", l + 1);
8722 emitcode ("mov", "%s,%s", buffer,
8723 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8726 freeAsmop (right, NULL, ic, TRUE);
8727 freeAsmop (result, NULL, ic, TRUE);
8730 /*-----------------------------------------------------------------*/
8731 /* genNearPointerSet - emitcode for near pointer put */
8732 /*-----------------------------------------------------------------*/
8734 genNearPointerSet (operand * right,
8741 sym_link *retype, *letype;
8742 sym_link *ptype = operandType (result);
8744 retype = getSpec (operandType (right));
8745 letype = getSpec (ptype);
8747 aopOp (result, ic, FALSE, FALSE);
8749 /* if the result is rematerializable &
8750 in data space & not a bit variable */
8751 if (AOP_TYPE (result) == AOP_IMMD &&
8752 DCL_TYPE (ptype) == POINTER &&
8753 !IS_BITVAR (retype) &&
8754 !IS_BITVAR (letype))
8756 genDataPointerSet (right, result, ic);
8760 /* if the value is already in a pointer register
8761 then don't need anything more */
8762 if (!AOP_INPREG (AOP (result)))
8764 /* otherwise get a free pointer register */
8766 preg = getFreePtr (ic, &aop, FALSE);
8767 emitcode ("mov", "%s,%s",
8769 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8773 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8775 freeAsmop (result, NULL, ic, TRUE);
8776 aopOp (right, ic, FALSE, FALSE);
8778 /* if bitfield then unpack the bits */
8779 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8780 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8783 /* we have can just get the values */
8784 int size = AOP_SIZE (right);
8789 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8793 emitcode ("mov", "@%s,a", rname);
8796 emitcode ("mov", "@%s,%s", rname, l);
8798 emitcode ("inc", "%s", rname);
8803 /* now some housekeeping stuff */
8806 /* we had to allocate for this iCode */
8807 freeAsmop (NULL, aop, ic, TRUE);
8811 /* we did not allocate which means left
8812 already in a pointer register, then
8813 if size > 0 && this could be used again
8814 we have to point it back to where it
8816 if (AOP_SIZE (right) > 1 &&
8817 !OP_SYMBOL (result)->remat &&
8818 (OP_SYMBOL (result)->liveTo > ic->seq ||
8821 int size = AOP_SIZE (right) - 1;
8823 emitcode ("dec", "%s", rname);
8828 freeAsmop (right, NULL, ic, TRUE);
8833 /*-----------------------------------------------------------------*/
8834 /* genPagedPointerSet - emitcode for Paged pointer put */
8835 /*-----------------------------------------------------------------*/
8837 genPagedPointerSet (operand * right,
8844 sym_link *retype, *letype;
8846 retype = getSpec (operandType (right));
8847 letype = getSpec (operandType (result));
8849 aopOp (result, ic, FALSE, FALSE);
8851 /* if the value is already in a pointer register
8852 then don't need anything more */
8853 if (!AOP_INPREG (AOP (result)))
8855 /* otherwise get a free pointer register */
8857 preg = getFreePtr (ic, &aop, FALSE);
8858 emitcode ("mov", "%s,%s",
8860 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8864 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8866 freeAsmop (result, NULL, ic, TRUE);
8867 aopOp (right, ic, FALSE, FALSE);
8869 /* if bitfield then unpack the bits */
8870 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8871 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8874 /* we have can just get the values */
8875 int size = AOP_SIZE (right);
8880 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8883 emitcode ("movx", "@%s,a", rname);
8886 emitcode ("inc", "%s", rname);
8892 /* now some housekeeping stuff */
8895 /* we had to allocate for this iCode */
8896 freeAsmop (NULL, aop, ic, TRUE);
8900 /* we did not allocate which means left
8901 already in a pointer register, then
8902 if size > 0 && this could be used again
8903 we have to point it back to where it
8905 if (AOP_SIZE (right) > 1 &&
8906 !OP_SYMBOL (result)->remat &&
8907 (OP_SYMBOL (result)->liveTo > ic->seq ||
8910 int size = AOP_SIZE (right) - 1;
8912 emitcode ("dec", "%s", rname);
8917 freeAsmop (right, NULL, ic, TRUE);
8922 /*-----------------------------------------------------------------*/
8923 /* genFarPointerSet - set value from far space */
8924 /*-----------------------------------------------------------------*/
8926 genFarPointerSet (operand * right,
8927 operand * result, iCode * ic)
8930 sym_link *retype = getSpec (operandType (right));
8931 sym_link *letype = getSpec (operandType (result));
8933 aopOp (result, ic, FALSE, FALSE);
8935 /* if the operand is already in dptr
8936 then we do nothing else we move the value to dptr */
8937 if (AOP_TYPE (result) != AOP_STR)
8939 /* if this is remateriazable */
8940 if (AOP_TYPE (result) == AOP_IMMD)
8941 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8944 /* we need to get it byte by byte */
8945 _startLazyDPSEvaluation ();
8946 if (AOP_TYPE (result) != AOP_DPTR)
8948 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8949 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8950 if (options.model == MODEL_FLAT24)
8951 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8955 /* We need to generate a load to DPTR indirect through DPTR. */
8956 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8958 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8959 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8960 if (options.model == MODEL_FLAT24)
8961 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8962 emitcode ("pop", "dph");
8963 emitcode ("pop", "dpl");
8965 _endLazyDPSEvaluation ();
8968 /* so dptr know contains the address */
8969 freeAsmop (result, NULL, ic, TRUE);
8970 aopOp (right, ic, FALSE, TRUE);
8972 /* if bit then unpack */
8973 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8974 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8977 size = AOP_SIZE (right);
8980 _startLazyDPSEvaluation ();
8983 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8989 emitcode ("movx", "@dptr,a");
8991 emitcode ("inc", "dptr");
8993 _endLazyDPSEvaluation ();
8996 freeAsmop (right, NULL, ic, TRUE);
8999 /*-----------------------------------------------------------------*/
9000 /* genGenPointerSet - set value from generic pointer space */
9001 /*-----------------------------------------------------------------*/
9003 genGenPointerSet (operand * right,
9004 operand * result, iCode * ic)
9007 sym_link *retype = getSpec (operandType (right));
9008 sym_link *letype = getSpec (operandType (result));
9010 aopOp (result, ic, FALSE, TRUE);
9012 /* if the operand is already in dptr
9013 then we do nothing else we move the value to dptr */
9014 if (AOP_TYPE (result) != AOP_STR)
9016 _startLazyDPSEvaluation ();
9017 /* if this is remateriazable */
9018 if (AOP_TYPE (result) == AOP_IMMD)
9020 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9021 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9024 { /* we need to get it byte by byte */
9025 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9026 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9027 if (options.model == MODEL_FLAT24) {
9028 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9029 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9031 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9034 _endLazyDPSEvaluation ();
9036 /* so dptr know contains the address */
9037 freeAsmop (result, NULL, ic, TRUE);
9038 aopOp (right, ic, FALSE, TRUE);
9040 /* if bit then unpack */
9041 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9042 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9045 size = AOP_SIZE (right);
9048 _startLazyDPSEvaluation ();
9051 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9057 emitcode ("lcall", "__gptrput");
9059 emitcode ("inc", "dptr");
9061 _endLazyDPSEvaluation ();
9064 freeAsmop (right, NULL, ic, TRUE);
9067 /*-----------------------------------------------------------------*/
9068 /* genPointerSet - stores the value into a pointer location */
9069 /*-----------------------------------------------------------------*/
9071 genPointerSet (iCode * ic)
9073 operand *right, *result;
9074 sym_link *type, *etype;
9077 D (emitcode (";", "genPointerSet ");
9080 right = IC_RIGHT (ic);
9081 result = IC_RESULT (ic);
9083 /* depending on the type of pointer we need to
9084 move it to the correct pointer register */
9085 type = operandType (result);
9086 etype = getSpec (type);
9087 /* if left is of type of pointer then it is simple */
9088 if (IS_PTR (type) && !IS_FUNC (type->next))
9090 p_type = DCL_TYPE (type);
9094 /* we have to go by the storage class */
9095 p_type = PTR_TYPE (SPEC_OCLS (etype));
9098 /* now that we have the pointer type we assign
9099 the pointer values */
9105 genNearPointerSet (right, result, ic);
9109 genPagedPointerSet (right, result, ic);
9113 genFarPointerSet (right, result, ic);
9117 genGenPointerSet (right, result, ic);
9123 /*-----------------------------------------------------------------*/
9124 /* genIfx - generate code for Ifx statement */
9125 /*-----------------------------------------------------------------*/
9127 genIfx (iCode * ic, iCode * popIc)
9129 operand *cond = IC_COND (ic);
9132 D (emitcode (";", "genIfx "););
9134 aopOp (cond, ic, FALSE, FALSE);
9136 /* get the value into acc */
9137 if (AOP_TYPE (cond) != AOP_CRY)
9141 /* the result is now in the accumulator */
9142 freeAsmop (cond, NULL, ic, TRUE);
9144 /* if there was something to be popped then do it */
9148 /* if the condition is a bit variable */
9149 if (isbit && IS_ITEMP (cond) &&
9151 genIfxJump (ic, SPIL_LOC (cond)->rname);
9152 else if (isbit && !IS_ITEMP (cond))
9153 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9155 genIfxJump (ic, "a");
9160 /*-----------------------------------------------------------------*/
9161 /* genAddrOf - generates code for address of */
9162 /*-----------------------------------------------------------------*/
9164 genAddrOf (iCode * ic)
9166 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9169 D (emitcode (";", "genAddrOf ");
9172 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9174 /* if the operand is on the stack then we
9175 need to get the stack offset of this
9179 /* if it has an offset then we need to compute
9183 emitcode ("mov", "a,_bp");
9184 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9185 aopPut (AOP (IC_RESULT (ic)), "a", 0);
9189 /* we can just move _bp */
9190 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9192 /* fill the result with zero */
9193 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9196 if (options.stack10bit && size < (FPTRSIZE - 1))
9199 "*** warning: pointer to stack var truncated.\n");
9206 if (options.stack10bit && offset == 2)
9208 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9212 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9219 /* object not on stack then we need the name */
9220 size = AOP_SIZE (IC_RESULT (ic));
9225 char s[SDCC_NAME_MAX];
9227 sprintf (s, "#(%s >> %d)",
9231 sprintf (s, "#%s", sym->rname);
9232 aopPut (AOP (IC_RESULT (ic)), s, offset++);
9236 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9240 /*-----------------------------------------------------------------*/
9241 /* genArrayInit - generates code for address of */
9242 /*-----------------------------------------------------------------*/
9244 genArrayInit (iCode * ic)
9248 int elementSize = 0, eIndex;
9249 unsigned val, lastVal;
9252 D (emitcode (";", "genArrayInit "););
9254 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9256 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9258 // Load immediate value into DPTR.
9259 emitcode("mov", "dptr, %s",
9260 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9262 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9264 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9265 "Unexpected operand to genArrayInit.\n");
9269 type = operandType(IC_LEFT(ic));
9271 if (type && type->next)
9273 elementSize = getSize(type->next);
9277 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9278 "can't determine element size in genArrayInit.\n");
9282 iLoop = IC_ARRAYILIST(ic);
9287 bool firstpass = TRUE;
9289 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
9290 iLoop->count, (int)iLoop->literalValue, elementSize);
9296 symbol *tlbl = NULL;
9298 count = ix > 256 ? 256 : ix;
9302 tlbl = newiTempLabel (NULL);
9303 if (firstpass || (count & 0xff))
9305 emitcode("mov", "b, #0x%x", count & 0xff);
9308 emitcode ("", "%05d$:", tlbl->key + 100);
9313 for (eIndex = 0; eIndex < elementSize; eIndex++)
9315 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9318 emitcode("mov", "a, #0x%x", val);
9322 emitcode("movx", "@dptr, a");
9323 emitcode("inc", "dptr");
9328 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9334 iLoop = iLoop->next;
9337 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9340 /*-----------------------------------------------------------------*/
9341 /* genFarFarAssign - assignment when both are in far space */
9342 /*-----------------------------------------------------------------*/
9344 genFarFarAssign (operand * result, operand * right, iCode * ic)
9346 int size = AOP_SIZE (right);
9348 symbol *rSym = NULL;
9352 /* quick & easy case. */
9353 D(emitcode(";","genFarFarAssign (1 byte case)"););
9354 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9355 freeAsmop (right, NULL, ic, FALSE);
9356 /* now assign DPTR to result */
9358 aopOp(result, ic, FALSE, FALSE);
9360 aopPut(AOP(result), "a", 0);
9361 freeAsmop(result, NULL, ic, FALSE);
9365 /* See if we've got an underlying symbol to abuse. */
9366 if (IS_SYMOP(result) && OP_SYMBOL(result))
9368 if (IS_TRUE_SYMOP(result))
9370 rSym = OP_SYMBOL(result);
9372 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9374 rSym = OP_SYMBOL(result)->usl.spillLoc;
9378 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9380 /* We can use the '390 auto-toggle feature to good effect here. */
9382 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9383 emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */
9384 emitcode ("mov", "dptr,#%s", rSym->rname);
9385 /* DP2 = result, DP1 = right, DP1 is current. */
9388 emitcode("movx", "a,@dptr");
9389 emitcode("movx", "@dptr,a");
9392 emitcode("inc", "dptr");
9393 emitcode("inc", "dptr");
9396 emitcode("mov", "dps, #0");
9397 freeAsmop (right, NULL, ic, FALSE);
9401 D (emitcode (";", "genFarFarAssign"););
9402 aopOp (result, ic, TRUE, TRUE);
9404 _startLazyDPSEvaluation ();
9408 aopPut (AOP (result),
9409 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9412 _endLazyDPSEvaluation ();
9413 freeAsmop (result, NULL, ic, FALSE);
9414 freeAsmop (right, NULL, ic, FALSE);
9418 /*-----------------------------------------------------------------*/
9419 /* genAssign - generate code for assignment */
9420 /*-----------------------------------------------------------------*/
9422 genAssign (iCode * ic)
9424 operand *result, *right;
9426 unsigned long lit = 0L;
9428 D (emitcode (";", "genAssign ");
9431 result = IC_RESULT (ic);
9432 right = IC_RIGHT (ic);
9434 /* if they are the same */
9435 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9438 aopOp (right, ic, FALSE, FALSE);
9440 emitcode (";", "genAssign: resultIsFar = %s",
9441 isOperandInFarSpace (result) ?
9444 /* special case both in far space */
9445 if ((AOP_TYPE (right) == AOP_DPTR ||
9446 AOP_TYPE (right) == AOP_DPTR2) &&
9447 /* IS_TRUE_SYMOP(result) && */
9448 isOperandInFarSpace (result))
9450 genFarFarAssign (result, right, ic);
9454 aopOp (result, ic, TRUE, FALSE);
9456 /* if they are the same registers */
9457 if (sameRegs (AOP (right), AOP (result)))
9460 /* if the result is a bit */
9461 if (AOP_TYPE (result) == AOP_CRY)
9464 /* if the right size is a literal then
9465 we know what the value is */
9466 if (AOP_TYPE (right) == AOP_LIT)
9468 if (((int) operandLitValue (right)))
9469 aopPut (AOP (result), one, 0);
9471 aopPut (AOP (result), zero, 0);
9475 /* the right is also a bit variable */
9476 if (AOP_TYPE (right) == AOP_CRY)
9478 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9479 aopPut (AOP (result), "c", 0);
9485 aopPut (AOP (result), "a", 0);
9489 /* bit variables done */
9491 size = AOP_SIZE (result);
9493 if (AOP_TYPE (right) == AOP_LIT)
9494 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9497 (AOP_TYPE (result) != AOP_REG) &&
9498 (AOP_TYPE (right) == AOP_LIT) &&
9499 !IS_FLOAT (operandType (right)))
9501 _startLazyDPSEvaluation ();
9502 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9504 aopPut (AOP (result),
9505 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9510 /* And now fill the rest with zeros. */
9513 emitcode ("clr", "a");
9517 aopPut (AOP (result), "a", offset++);
9519 _endLazyDPSEvaluation ();
9523 _startLazyDPSEvaluation ();
9526 aopPut (AOP (result),
9527 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9531 _endLazyDPSEvaluation ();
9535 freeAsmop (right, NULL, ic, FALSE);
9536 freeAsmop (result, NULL, ic, TRUE);
9539 /*-----------------------------------------------------------------*/
9540 /* genJumpTab - generates code for jump table */
9541 /*-----------------------------------------------------------------*/
9543 genJumpTab (iCode * ic)
9548 D (emitcode (";", "genJumpTab ");
9551 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9552 /* get the condition into accumulator */
9553 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9555 /* multiply by four! */
9556 emitcode ("add", "a,acc");
9557 emitcode ("add", "a,acc");
9558 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9560 jtab = newiTempLabel (NULL);
9561 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9562 emitcode ("jmp", "@a+dptr");
9563 emitcode ("", "%05d$:", jtab->key + 100);
9564 /* now generate the jump labels */
9565 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9566 jtab = setNextItem (IC_JTLABELS (ic)))
9567 emitcode ("ljmp", "%05d$", jtab->key + 100);
9571 /*-----------------------------------------------------------------*/
9572 /* genCast - gen code for casting */
9573 /*-----------------------------------------------------------------*/
9575 genCast (iCode * ic)
9577 operand *result = IC_RESULT (ic);
9578 sym_link *ctype = operandType (IC_LEFT (ic));
9579 sym_link *rtype = operandType (IC_RIGHT (ic));
9580 operand *right = IC_RIGHT (ic);
9583 D (emitcode (";", "genCast ");
9586 /* if they are equivalent then do nothing */
9587 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9590 aopOp (right, ic, FALSE, FALSE);
9591 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9593 /* if the result is a bit */
9594 if (AOP_TYPE (result) == AOP_CRY)
9596 /* if the right size is a literal then
9597 we know what the value is */
9598 if (AOP_TYPE (right) == AOP_LIT)
9600 if (((int) operandLitValue (right)))
9601 aopPut (AOP (result), one, 0);
9603 aopPut (AOP (result), zero, 0);
9608 /* the right is also a bit variable */
9609 if (AOP_TYPE (right) == AOP_CRY)
9611 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9612 aopPut (AOP (result), "c", 0);
9618 aopPut (AOP (result), "a", 0);
9622 /* if they are the same size : or less */
9623 if (AOP_SIZE (result) <= AOP_SIZE (right))
9626 /* if they are in the same place */
9627 if (sameRegs (AOP (right), AOP (result)))
9630 /* if they in different places then copy */
9631 size = AOP_SIZE (result);
9633 _startLazyDPSEvaluation ();
9636 aopPut (AOP (result),
9637 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9641 _endLazyDPSEvaluation ();
9646 /* if the result is of type pointer */
9651 sym_link *type = operandType (right);
9653 /* pointer to generic pointer */
9654 if (IS_GENPTR (ctype))
9660 p_type = DCL_TYPE (type);
9664 #if OLD_CAST_BEHAVIOR
9665 /* KV: we are converting a non-pointer type to
9666 * a generic pointer. This (ifdef'd out) code
9667 * says that the resulting generic pointer
9668 * should have the same class as the storage
9669 * location of the non-pointer variable.
9671 * For example, converting an int (which happens
9672 * to be stored in DATA space) to a pointer results
9673 * in a DATA generic pointer; if the original int
9674 * in XDATA space, so will be the resulting pointer.
9676 * I don't like that behavior, and thus this change:
9677 * all such conversions will be forced to XDATA and
9678 * throw a warning. If you want some non-XDATA
9679 * type, or you want to suppress the warning, you
9680 * must go through an intermediate cast, like so:
9682 * char _generic *gp = (char _xdata *)(intVar);
9684 sym_link *etype = getSpec (type);
9686 /* we have to go by the storage class */
9687 if (SPEC_OCLS (etype) != generic)
9689 p_type = PTR_TYPE (SPEC_OCLS (etype));
9694 /* Converting unknown class (i.e. register variable)
9695 * to generic pointer. This is not good, but
9696 * we'll make a guess (and throw a warning).
9699 werror (W_INT_TO_GEN_PTR_CAST);
9703 /* the first two bytes are known */
9704 size = GPTRSIZE - 1;
9706 _startLazyDPSEvaluation ();
9709 aopPut (AOP (result),
9710 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9714 _endLazyDPSEvaluation ();
9716 /* the last byte depending on type */
9734 /* this should never happen */
9735 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9736 "got unknown pointer type");
9739 aopPut (AOP (result), l, GPTRSIZE - 1);
9743 /* just copy the pointers */
9744 size = AOP_SIZE (result);
9746 _startLazyDPSEvaluation ();
9749 aopPut (AOP (result),
9750 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9754 _endLazyDPSEvaluation ();
9758 /* so we now know that the size of destination is greater
9759 than the size of the source */
9760 /* we move to result for the size of source */
9761 size = AOP_SIZE (right);
9763 _startLazyDPSEvaluation ();
9766 aopPut (AOP (result),
9767 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9771 _endLazyDPSEvaluation ();
9773 /* now depending on the sign of the source && destination */
9774 size = AOP_SIZE (result) - AOP_SIZE (right);
9775 /* if unsigned or not an integral type */
9776 /* also, if the source is a bit, we don't need to sign extend, because
9777 * it can't possibly have set the sign bit.
9779 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9783 aopPut (AOP (result), zero, offset++);
9788 /* we need to extend the sign :{ */
9789 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9790 FALSE, FALSE, TRUE);
9792 emitcode ("rlc", "a");
9793 emitcode ("subb", "a,acc");
9795 aopPut (AOP (result), "a", offset++);
9798 /* we are done hurray !!!! */
9801 freeAsmop (right, NULL, ic, TRUE);
9802 freeAsmop (result, NULL, ic, TRUE);
9806 /*-----------------------------------------------------------------*/
9807 /* genDjnz - generate decrement & jump if not zero instrucion */
9808 /*-----------------------------------------------------------------*/
9810 genDjnz (iCode * ic, iCode * ifx)
9816 /* if the if condition has a false label
9817 then we cannot save */
9821 /* if the minus is not of the form
9823 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9824 !IS_OP_LITERAL (IC_RIGHT (ic)))
9827 if (operandLitValue (IC_RIGHT (ic)) != 1)
9830 /* if the size of this greater than one then no
9832 if (getSize (operandType (IC_RESULT (ic))) > 1)
9835 /* otherwise we can save BIG */
9836 D(emitcode(";", "genDjnz"););
9838 lbl = newiTempLabel (NULL);
9839 lbl1 = newiTempLabel (NULL);
9841 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9843 if (AOP_NEEDSACC(IC_RESULT(ic)))
9845 /* If the result is accessed indirectly via
9846 * the accumulator, we must explicitly write
9847 * it back after the decrement.
9849 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9851 if (strcmp(rByte, "a"))
9853 /* Something is hopelessly wrong */
9854 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9855 __FILE__, __LINE__);
9856 /* We can just give up; the generated code will be inefficient,
9859 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9862 emitcode ("dec", "%s", rByte);
9863 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9864 emitcode ("jnz", "%05d$", lbl->key + 100);
9866 else if (IS_AOP_PREG (IC_RESULT (ic)))
9868 emitcode ("dec", "%s",
9869 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9870 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9871 emitcode ("jnz", "%05d$", lbl->key + 100);
9875 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9878 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9879 emitcode ("", "%05d$:", lbl->key + 100);
9880 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9881 emitcode ("", "%05d$:", lbl1->key + 100);
9883 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9888 /*-----------------------------------------------------------------*/
9889 /* genReceive - generate code for a receive iCode */
9890 /*-----------------------------------------------------------------*/
9892 genReceive (iCode * ic)
9895 D (emitcode (";", "genReceive ");
9898 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9899 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9900 IS_TRUE_SYMOP (IC_RESULT (ic))))
9902 int size = getSize (operandType (IC_RESULT (ic)));
9903 int offset = fReturnSizeDS390 - size;
9906 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9907 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9910 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9911 size = AOP_SIZE (IC_RESULT (ic));
9915 emitcode ("pop", "acc");
9916 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9923 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9925 assignResultValue (IC_RESULT (ic));
9928 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9931 /*-----------------------------------------------------------------*/
9932 /* gen390Code - generate code for Dallas 390 based controllers */
9933 /*-----------------------------------------------------------------*/
9935 gen390Code (iCode * lic)
9940 lineHead = lineCurr = NULL;
9942 if (options.model == MODEL_FLAT24) {
9943 fReturnSizeDS390 = 5;
9944 fReturn = fReturn24;
9946 fReturnSizeDS390 = 4;
9947 fReturn = fReturn16;
9948 options.stack10bit=0;
9952 /* print the allocation information */
9954 printAllocInfo (currFunc, codeOutFile);
9956 /* if debug information required */
9957 if (options.debug && currFunc)
9959 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9961 if (IS_STATIC (currFunc->etype))
9962 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9964 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9967 /* stack pointer name */
9968 if (options.useXstack)
9974 for (ic = lic; ic; ic = ic->next)
9977 if (cln != ic->lineno)
9982 emitcode ("", "C$%s$%d$%d$%d ==.",
9983 FileBaseName (ic->filename), ic->lineno,
9984 ic->level, ic->block);
9987 emitcode (";", "%s %d", ic->filename, ic->lineno);
9990 /* if the result is marked as
9991 spilt and rematerializable or code for
9992 this has already been generated then
9994 if (resultRemat (ic) || ic->generated)
9997 /* depending on the operation */
10017 /* IPOP happens only when trying to restore a
10018 spilt live range, if there is an ifx statement
10019 following this pop then the if statement might
10020 be using some of the registers being popped which
10021 would destory the contents of the register so
10022 we need to check for this condition and handle it */
10024 ic->next->op == IFX &&
10025 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10026 genIfx (ic->next, ic);
10044 genEndFunction (ic);
10064 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10081 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10085 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10092 /* note these two are xlated by algebraic equivalence
10093 during parsing SDCC.y */
10094 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10095 "got '>=' or '<=' shouldn't have come here");
10099 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10111 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10115 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10119 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10143 genRightShift (ic);
10146 case GET_VALUE_AT_ADDRESS:
10147 genPointerGet (ic);
10151 if (POINTER_SET (ic))
10152 genPointerSet (ic);
10178 addSet (&_G.sendSet, ic);
10191 /* now we are ready to call the
10192 peep hole optimizer */
10193 if (!options.nopeep)
10194 peepHole (&lineHead);
10196 /* now do the actual printing */
10197 printLine (lineHead, codeOutFile);