1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
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!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 char *aopLiteral (value * val, int offset);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0x00";
67 static char *one = "#0x01";
72 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
73 static char *fReturn[] =
74 {"dpl", "dph", "dpx", "b", "a"};
75 static char *accUse[] =
78 static short rbank = -1;
92 static void saverbank (int, iCode *, bool);
94 #define RESULTONSTACK(x) \
95 (IC_RESULT(x) && IC_RESULT(x)->aop && \
96 IC_RESULT(x)->aop->type == AOP_STK )
98 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
99 #define MOVA(x) { char *_mova_tmp = strdup(x); \
100 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
102 emitcode("mov","a,%s",_mova_tmp); \
106 #define CLRC emitcode("clr","c")
107 #define SETC emitcode("setb","c")
109 static lineNode *lineHead = NULL;
110 static lineNode *lineCurr = NULL;
112 static unsigned char SLMask[] =
113 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
114 0xE0, 0xC0, 0x80, 0x00};
115 static unsigned char SRMask[] =
116 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
117 0x07, 0x03, 0x01, 0x00};
124 /*-----------------------------------------------------------------*/
125 /* emitcode - writes the code into a file : for now it is simple */
126 /*-----------------------------------------------------------------*/
128 emitcode (char *inst, char *fmt,...)
131 char lb[MAX_INLINEASM];
139 sprintf (lb, "%s\t", inst);
141 sprintf (lb, "%s", inst);
142 vsprintf (lb + (strlen (lb)), fmt, ap);
145 vsprintf (lb, fmt, ap);
147 while (isspace (*lbp))
151 lineCurr = (lineCurr ?
152 connectLine (lineCurr, newLineNode (lb)) :
153 (lineHead = newLineNode (lb)));
154 lineCurr->isInline = _G.inLine;
155 lineCurr->isDebug = _G.debugLine;
159 /*-----------------------------------------------------------------*/
160 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
161 /*-----------------------------------------------------------------*/
163 getFreePtr (iCode * ic, asmop ** aopp, bool result)
165 bool r0iu = FALSE, r1iu = FALSE;
166 bool r0ou = FALSE, r1ou = FALSE;
168 /* the logic: if r0 & r1 used in the instruction
169 then we are in trouble otherwise */
171 /* first check if r0 & r1 are used by this
172 instruction, in which case we are in trouble */
173 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
174 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
179 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
180 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
182 /* if no usage of r0 then return it */
185 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
186 (*aopp)->type = AOP_R0;
188 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
191 /* if no usage of r1 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
195 (*aopp)->type = AOP_R1;
197 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
200 /* now we know they both have usage */
201 /* if r0 not used in this instruction */
204 /* push it if not already pushed */
207 emitcode ("push", "%s",
208 ds390_regWithIdx (R0_IDX)->dname);
212 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
213 (*aopp)->type = AOP_R0;
215 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
218 /* if r1 not used then */
222 /* push it if not already pushed */
225 emitcode ("push", "%s",
226 ds390_regWithIdx (R1_IDX)->dname);
230 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
231 (*aopp)->type = AOP_R1;
232 return ds390_regWithIdx (R1_IDX);
236 /* I said end of world but not quite end of world yet */
237 /* if this is a result then we can push it on the stack */
240 (*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)
321 /*-----------------------------------------------------------------*/
322 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
323 /* desired one. Call before using DPTR within a lazy DPS evaluation */
325 /*-----------------------------------------------------------------*/
335 if (_desiredDPS != _currentDPS)
339 emitcode ("inc", "dps");
343 emitcode ("dec", "dps");
345 _currentDPS = _desiredDPS;
349 /*-----------------------------------------------------------------*/
350 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
352 /* Forces us back to the safe state (standard DPTR selected). */
353 /*-----------------------------------------------------------------*/
355 _endLazyDPSEvaluation (void)
369 /*-----------------------------------------------------------------*/
370 /* pointerCode - returns the code for a pointer type */
371 /*-----------------------------------------------------------------*/
373 pointerCode (sym_link * etype)
376 return PTR_TYPE (SPEC_OCLS (etype));
380 /*-----------------------------------------------------------------*/
381 /* aopForSym - for a true symbol */
382 /*-----------------------------------------------------------------*/
384 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
387 memmap *space = SPEC_OCLS (sym->etype);
389 /* if already has one */
393 /* assign depending on the storage class */
394 /* if it is on the stack or indirectly addressable */
395 /* space we need to assign either r0 or r1 to it */
396 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
398 sym->aop = aop = newAsmop (0);
399 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
400 aop->size = getSize (sym->type);
402 /* now assign the address of the variable to
403 the pointer register */
404 if (aop->type != AOP_STK)
410 emitcode ("push", "acc");
412 emitcode ("mov", "a,_bp");
413 emitcode ("add", "a,#0x%02x",
415 ((char) (sym->stack - _G.nRegsSaved)) :
416 ((char) sym->stack)) & 0xff);
417 emitcode ("mov", "%s,a",
418 aop->aopu.aop_ptr->name);
421 emitcode ("pop", "acc");
424 emitcode ("mov", "%s,#%s",
425 aop->aopu.aop_ptr->name,
427 aop->paged = space->paged;
430 aop->aopu.aop_stk = sym->stack;
434 if (sym->onStack && options.stack10bit)
436 /* It's on the 10 bit stack, which is located in
441 emitcode ("push", "acc");
443 emitcode ("mov", "a,_bp");
444 emitcode ("add", "a,#0x%02x",
446 ((char) (sym->stack - _G.nRegsSaved)) :
447 ((char) sym->stack)) & 0xff);
452 emitcode ("mov", "dpx1,#0x40");
453 emitcode ("mov", "dph1,#0x00");
454 emitcode ("mov", "dpl1, a");
459 emitcode ("mov", "dpx,#0x40");
460 emitcode ("mov", "dph,#0x00");
461 emitcode ("mov", "dpl, a");
465 emitcode ("pop", "acc");
467 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
468 aop->size = getSize (sym->type);
472 /* if in bit space */
473 if (IN_BITSPACE (space))
475 sym->aop = aop = newAsmop (AOP_CRY);
476 aop->aopu.aop_dir = sym->rname;
477 aop->size = getSize (sym->type);
480 /* if it is in direct space */
481 if (IN_DIRSPACE (space))
483 sym->aop = aop = newAsmop (AOP_DIR);
484 aop->aopu.aop_dir = sym->rname;
485 aop->size = getSize (sym->type);
489 /* special case for a function */
490 if (IS_FUNC (sym->type))
492 sym->aop = aop = newAsmop (AOP_IMMD);
493 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
494 strcpy (aop->aopu.aop_immd, sym->rname);
495 aop->size = FPTRSIZE;
499 /* only remaining is far space */
500 /* in which case DPTR gets the address */
501 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
506 emitcode ("mov", "dptr,#%s", sym->rname);
511 emitcode ("mov", "dptr,#%s", sym->rname);
513 aop->size = getSize (sym->type);
515 /* if it is in code space */
516 if (IN_CODESPACE (space))
522 /*-----------------------------------------------------------------*/
523 /* aopForRemat - rematerialzes an object */
524 /*-----------------------------------------------------------------*/
526 aopForRemat (symbol * sym)
528 iCode *ic = sym->rematiCode;
529 asmop *aop = newAsmop (AOP_IMMD);
536 val += (int) operandLitValue (IC_RIGHT (ic));
537 else if (ic->op == '-')
538 val -= (int) operandLitValue (IC_RIGHT (ic));
542 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
546 sprintf (buffer, "(%s %c 0x%04x)",
547 OP_SYMBOL (IC_LEFT (ic))->rname,
548 val >= 0 ? '+' : '-',
551 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
553 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
554 strcpy (aop->aopu.aop_immd, buffer);
558 /*-----------------------------------------------------------------*/
559 /* regsInCommon - two operands have some registers in common */
560 /*-----------------------------------------------------------------*/
562 regsInCommon (operand * op1, operand * op2)
567 /* if they have registers in common */
568 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
571 sym1 = OP_SYMBOL (op1);
572 sym2 = OP_SYMBOL (op2);
574 if (sym1->nRegs == 0 || sym2->nRegs == 0)
577 for (i = 0; i < sym1->nRegs; i++)
583 for (j = 0; j < sym2->nRegs; j++)
588 if (sym2->regs[j] == sym1->regs[i])
596 /*-----------------------------------------------------------------*/
597 /* operandsEqu - equivalent */
598 /*-----------------------------------------------------------------*/
600 operandsEqu (operand * op1, operand * op2)
604 /* if they not symbols */
605 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
608 sym1 = OP_SYMBOL (op1);
609 sym2 = OP_SYMBOL (op2);
611 /* if both are itemps & one is spilt
612 and the other is not then false */
613 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
614 sym1->isspilt != sym2->isspilt)
617 /* if they are the same */
621 if (strcmp (sym1->rname, sym2->rname) == 0)
625 /* if left is a tmp & right is not */
626 if (IS_ITEMP (op1) &&
629 (sym1->usl.spillLoc == sym2))
632 if (IS_ITEMP (op2) &&
636 (sym2->usl.spillLoc == sym1))
642 /*-----------------------------------------------------------------*/
643 /* sameRegs - two asmops have the same registers */
644 /*-----------------------------------------------------------------*/
646 sameRegs (asmop * aop1, asmop * aop2)
652 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
659 if (aop1->type != AOP_REG ||
660 aop2->type != AOP_REG)
663 if (aop1->size != aop2->size)
666 for (i = 0; i < aop1->size; i++)
667 if (aop1->aopu.aop_reg[i] !=
668 aop2->aopu.aop_reg[i])
674 /*-----------------------------------------------------------------*/
675 /* aopOp - allocates an asmop for an operand : */
676 /*-----------------------------------------------------------------*/
678 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
687 /* if this a literal */
688 if (IS_OP_LITERAL (op))
690 op->aop = aop = newAsmop (AOP_LIT);
691 aop->aopu.aop_lit = op->operand.valOperand;
692 aop->size = getSize (operandType (op));
696 /* if already has a asmop then continue */
700 /* if the underlying symbol has a aop */
701 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
703 op->aop = OP_SYMBOL (op)->aop;
707 /* if this is a true symbol */
708 if (IS_TRUE_SYMOP (op))
710 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
714 /* this is a temporary : this has
720 e) can be a return use only */
722 sym = OP_SYMBOL (op);
725 /* if the type is a conditional */
726 if (sym->regType == REG_CND)
728 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
733 /* if it is spilt then two situations
735 b) has a spill location */
736 if (sym->isspilt || sym->nRegs == 0)
739 /* rematerialize it NOW */
742 sym->aop = op->aop = aop =
744 aop->size = getSize (sym->type);
751 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
752 aop->size = getSize (sym->type);
753 for (i = 0; i < 2; i++)
754 aop->aopu.aop_str[i] = accUse[i];
764 /* a AOP_STR uses DPTR, but DPTR is already in use;
767 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
770 aop = op->aop = sym->aop = newAsmop (AOP_STR);
771 aop->size = getSize (sym->type);
772 for (i = 0; i < (int) fReturnSize_390; i++)
773 aop->aopu.aop_str[i] = fReturn[i];
777 /* else spill location */
778 sym->aop = op->aop = aop =
779 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
780 aop->size = getSize (sym->type);
784 /* must be in a register */
785 sym->aop = op->aop = aop = newAsmop (AOP_REG);
786 aop->size = sym->nRegs;
787 for (i = 0; i < sym->nRegs; i++)
788 aop->aopu.aop_reg[i] = sym->regs[i];
791 /*-----------------------------------------------------------------*/
792 /* freeAsmop - free up the asmop given to an operand */
793 /*----------------------------------------------------------------*/
795 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
812 /* depending on the asmop type only three cases need work AOP_RO
813 , AOP_R1 && AOP_STK */
821 emitcode ("pop", "ar0");
825 bitVectUnSetBit (ic->rUsed, R0_IDX);
833 emitcode ("pop", "ar1");
837 bitVectUnSetBit (ic->rUsed, R1_IDX);
843 int stk = aop->aopu.aop_stk + aop->size;
844 bitVectUnSetBit (ic->rUsed, R0_IDX);
845 bitVectUnSetBit (ic->rUsed, R1_IDX);
847 getFreePtr (ic, &aop, FALSE);
849 if (options.stack10bit)
851 /* I'm not sure what to do here yet... */
854 "*** Warning: probably generating bad code for "
855 "10 bit stack mode.\n");
860 emitcode ("mov", "a,_bp");
861 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
862 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
866 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
871 emitcode ("pop", "acc");
872 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
875 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
878 freeAsmop (op, NULL, ic, TRUE);
881 emitcode ("pop", "ar0");
887 emitcode ("pop", "ar1");
894 /* all other cases just dealloc */
900 OP_SYMBOL (op)->aop = NULL;
901 /* if the symbol has a spill */
903 SPIL_LOC (op)->aop = NULL;
908 /*------------------------------------------------------------------*/
909 /* aopGet - for fetching value of the aop */
911 /* Set canClobberACC if you are aure it is OK to clobber the value */
912 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
913 /* just less efficient. */
914 /*------------------------------------------------------------------*/
926 /* offset is greater than
928 if (offset > (aop->size - 1) &&
929 aop->type != AOP_LIT)
932 /* depending on type */
938 /* if we need to increment it */
939 while (offset > aop->coff)
941 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
945 while (offset < aop->coff)
947 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
954 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
955 return (dname ? "acc" : "a");
957 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
958 rs = Safe_calloc (1, strlen (s) + 1);
965 if (aop->type == AOP_DPTR2)
971 emitcode ("xch", "a, ap");
977 while (offset > aop->coff)
979 emitcode ("inc", "dptr");
983 while (offset < aop->coff)
985 emitcode ("lcall", "__decdptr");
992 emitcode ("clr", "a");
993 emitcode ("movc", "a,@a+dptr");
997 emitcode ("movx", "a,@dptr");
1000 if (aop->type == AOP_DPTR2)
1006 emitcode ("xch", "a, ap");
1011 return (dname ? "acc" : "a");
1015 sprintf (s, "#%s", aop->aopu.aop_immd);
1017 sprintf (s, "#(%s >> %d)",
1022 aop->aopu.aop_immd);
1023 rs = Safe_calloc (1, strlen (s) + 1);
1029 sprintf (s, "(%s + %d)",
1033 sprintf (s, "%s", aop->aopu.aop_dir);
1034 rs = Safe_calloc (1, strlen (s) + 1);
1040 return aop->aopu.aop_reg[offset]->dname;
1042 return aop->aopu.aop_reg[offset]->name;
1045 emitcode ("clr", "a");
1046 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1047 emitcode ("rlc", "a");
1048 return (dname ? "acc" : "a");
1051 if (!offset && dname)
1053 return aop->aopu.aop_str[offset];
1056 return aopLiteral (aop->aopu.aop_lit, offset);
1060 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1064 return aop->aopu.aop_str[offset];
1068 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1069 "aopget got unsupported aop->type");
1072 /*-----------------------------------------------------------------*/
1073 /* aopPut - puts a string for a aop */
1074 /*-----------------------------------------------------------------*/
1076 aopPut (asmop * aop, char *s, int offset)
1081 if (aop->size && offset > (aop->size - 1))
1083 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1084 "aopPut got offset > aop->size");
1088 /* will assign value to value */
1089 /* depending on where it is ofcourse */
1094 sprintf (d, "(%s + %d)",
1095 aop->aopu.aop_dir, offset);
1097 sprintf (d, "%s", aop->aopu.aop_dir);
1100 emitcode ("mov", "%s,%s", d, s);
1105 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1106 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1109 strcmp (s, "r0") == 0 ||
1110 strcmp (s, "r1") == 0 ||
1111 strcmp (s, "r2") == 0 ||
1112 strcmp (s, "r3") == 0 ||
1113 strcmp (s, "r4") == 0 ||
1114 strcmp (s, "r5") == 0 ||
1115 strcmp (s, "r6") == 0 ||
1116 strcmp (s, "r7") == 0)
1117 emitcode ("mov", "%s,%s",
1118 aop->aopu.aop_reg[offset]->dname, s);
1120 emitcode ("mov", "%s,%s",
1121 aop->aopu.aop_reg[offset]->name, s);
1128 if (aop->type == AOP_DPTR2)
1136 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1137 "aopPut writting to code space");
1141 while (offset > aop->coff)
1144 emitcode ("inc", "dptr");
1147 while (offset < aop->coff)
1150 emitcode ("lcall", "__decdptr");
1155 /* if not in accumulater */
1158 emitcode ("movx", "@dptr,a");
1160 if (aop->type == AOP_DPTR2)
1168 while (offset > aop->coff)
1171 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1173 while (offset < aop->coff)
1176 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1183 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1189 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1191 else if (strcmp (s, "r0") == 0 ||
1192 strcmp (s, "r1") == 0 ||
1193 strcmp (s, "r2") == 0 ||
1194 strcmp (s, "r3") == 0 ||
1195 strcmp (s, "r4") == 0 ||
1196 strcmp (s, "r5") == 0 ||
1197 strcmp (s, "r6") == 0 ||
1198 strcmp (s, "r7") == 0)
1201 sprintf (buffer, "a%s", s);
1202 emitcode ("mov", "@%s,%s",
1203 aop->aopu.aop_ptr->name, buffer);
1206 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1211 if (strcmp (s, "a") == 0)
1212 emitcode ("push", "acc");
1214 emitcode ("push", "%s", s);
1219 /* if bit variable */
1220 if (!aop->aopu.aop_dir)
1222 emitcode ("clr", "a");
1223 emitcode ("rlc", "a");
1228 emitcode ("clr", "%s", aop->aopu.aop_dir);
1230 emitcode ("setb", "%s", aop->aopu.aop_dir);
1231 else if (!strcmp (s, "c"))
1232 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1235 lbl = newiTempLabel (NULL);
1237 if (strcmp (s, "a"))
1241 emitcode ("clr", "c");
1242 emitcode ("jz", "%05d$", lbl->key + 100);
1243 emitcode ("cpl", "c");
1244 emitcode ("", "%05d$:", lbl->key + 100);
1245 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1252 if (strcmp (aop->aopu.aop_str[offset], s))
1253 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1258 if (!offset && (strcmp (s, "acc") == 0))
1261 if (strcmp (aop->aopu.aop_str[offset], s))
1262 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1266 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1267 "aopPut got unsupported aop->type");
1274 /*-----------------------------------------------------------------*/
1275 /* reAdjustPreg - points a register back to where it should */
1276 /*-----------------------------------------------------------------*/
1278 reAdjustPreg (asmop * aop)
1283 if ((size = aop->size) <= 1)
1291 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1295 if (aop->type == AOP_DPTR2)
1302 emitcode ("lcall", "__decdptr");
1305 if (aop->type == AOP_DPTR2)
1315 #define AOP(op) op->aop
1316 #define AOP_TYPE(op) AOP(op)->type
1317 #define AOP_SIZE(op) AOP(op)->size
1318 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1319 AOP_TYPE(x) == AOP_R0))
1321 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1322 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1325 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1326 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1327 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1329 /* Workaround for DS80C390 bug: div ab may return bogus results
1330 * if A is accessed in instruction immediately before the div.
1332 * Will be fixed in B4 rev of processor, Dallas claims.
1335 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1336 if (!AOP_NEEDSACC(RIGHT)) \
1338 /* We can load A first, then B, since \
1339 * B (the RIGHT operand) won't clobber A, \
1340 * thus avoiding touching A right before the div. \
1342 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1343 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1345 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1349 /* Just stuff in a nop after loading A. */ \
1350 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1351 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1353 emitcode("nop", "; workaround for DS80C390 div bug."); \
1356 /*-----------------------------------------------------------------*/
1357 /* genNotFloat - generates not for float operations */
1358 /*-----------------------------------------------------------------*/
1360 genNotFloat (operand * op, operand * res)
1366 D (emitcode (";", "genNotFloat ");
1369 /* we will put 127 in the first byte of
1371 aopPut (AOP (res), "#127", 0);
1372 size = AOP_SIZE (op) - 1;
1375 _startLazyDPSEvaluation ();
1376 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1381 emitcode ("orl", "a,%s",
1383 offset++, FALSE, FALSE, FALSE));
1385 _endLazyDPSEvaluation ();
1386 tlbl = newiTempLabel (NULL);
1388 tlbl = newiTempLabel (NULL);
1389 aopPut (res->aop, one, 1);
1390 emitcode ("jz", "%05d$", (tlbl->key + 100));
1391 aopPut (res->aop, zero, 1);
1392 emitcode ("", "%05d$:", (tlbl->key + 100));
1394 size = res->aop->size - 2;
1396 /* put zeros in the rest */
1398 aopPut (res->aop, zero, offset++);
1401 /*-----------------------------------------------------------------*/
1402 /* opIsGptr: returns non-zero if the passed operand is */
1403 /* a generic pointer type. */
1404 /*-----------------------------------------------------------------*/
1406 opIsGptr (operand * op)
1408 sym_link *type = operandType (op);
1410 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1417 /*-----------------------------------------------------------------*/
1418 /* getDataSize - get the operand data size */
1419 /*-----------------------------------------------------------------*/
1421 getDataSize (operand * op)
1424 size = AOP_SIZE (op);
1425 if (size == GPTRSIZE)
1427 sym_link *type = operandType (op);
1428 if (IS_GENPTR (type))
1430 /* generic pointer; arithmetic operations
1431 * should ignore the high byte (pointer type).
1439 /*-----------------------------------------------------------------*/
1440 /* outAcc - output Acc */
1441 /*-----------------------------------------------------------------*/
1443 outAcc (operand * result)
1446 size = getDataSize (result);
1449 aopPut (AOP (result), "a", 0);
1452 /* unsigned or positive */
1455 aopPut (AOP (result), zero, offset++);
1460 /*-----------------------------------------------------------------*/
1461 /* outBitC - output a bit C */
1462 /*-----------------------------------------------------------------*/
1464 outBitC (operand * result)
1466 /* if the result is bit */
1467 if (AOP_TYPE (result) == AOP_CRY)
1469 aopPut (AOP (result), "c", 0);
1473 emitcode ("clr", "a");
1474 emitcode ("rlc", "a");
1479 /*-----------------------------------------------------------------*/
1480 /* toBoolean - emit code for orl a,operator(sizeop) */
1481 /*-----------------------------------------------------------------*/
1483 toBoolean (operand * oper)
1485 int size = AOP_SIZE (oper) - 1;
1488 /* The generic part of a generic pointer should
1489 * not participate in it's truth value.
1491 * i.e. 0x10000000 is zero.
1493 if (opIsGptr (oper))
1495 D (emitcode (";", "toBoolean: generic ptr special case.");
1500 _startLazyDPSEvaluation ();
1501 if (AOP_NEEDSACC (oper))
1503 emitcode ("push", "b");
1504 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1508 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1512 if (AOP_NEEDSACC (oper))
1514 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1518 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1521 _endLazyDPSEvaluation ();
1523 if (AOP_NEEDSACC (oper))
1525 emitcode ("mov", "a,b");
1526 emitcode ("pop", "b");
1531 /*-----------------------------------------------------------------*/
1532 /* genNot - generate code for ! operation */
1533 /*-----------------------------------------------------------------*/
1538 sym_link *optype = operandType (IC_LEFT (ic));
1540 D (emitcode (";", "genNot ");
1543 /* assign asmOps to operand & result */
1544 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1545 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1547 /* if in bit space then a special case */
1548 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1550 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1551 emitcode ("cpl", "c");
1552 outBitC (IC_RESULT (ic));
1556 /* if type float then do float */
1557 if (IS_FLOAT (optype))
1559 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1563 toBoolean (IC_LEFT (ic));
1565 tlbl = newiTempLabel (NULL);
1566 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1567 emitcode ("", "%05d$:", tlbl->key + 100);
1568 outBitC (IC_RESULT (ic));
1571 /* release the aops */
1572 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1573 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1577 /*-----------------------------------------------------------------*/
1578 /* genCpl - generate code for complement */
1579 /*-----------------------------------------------------------------*/
1586 D (emitcode (";", "genCpl ");
1590 /* assign asmOps to operand & result */
1591 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1592 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1594 /* if both are in bit space then
1596 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1597 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1600 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1601 emitcode ("cpl", "c");
1602 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1606 size = AOP_SIZE (IC_RESULT (ic));
1607 _startLazyDPSEvaluation ();
1610 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1612 emitcode ("cpl", "a");
1613 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1615 _endLazyDPSEvaluation ();
1619 /* release the aops */
1620 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1621 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1624 /*-----------------------------------------------------------------*/
1625 /* genUminusFloat - unary minus for floating points */
1626 /*-----------------------------------------------------------------*/
1628 genUminusFloat (operand * op, operand * result)
1630 int size, offset = 0;
1632 /* for this we just need to flip the
1633 first it then copy the rest in place */
1634 D (emitcode (";", "genUminusFloat");
1637 _startLazyDPSEvaluation ();
1638 size = AOP_SIZE (op) - 1;
1639 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1642 emitcode ("cpl", "acc.7");
1643 aopPut (AOP (result), "a", 3);
1647 aopPut (AOP (result),
1648 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1652 _endLazyDPSEvaluation ();
1655 /*-----------------------------------------------------------------*/
1656 /* genUminus - unary minus code generation */
1657 /*-----------------------------------------------------------------*/
1659 genUminus (iCode * ic)
1662 sym_link *optype, *rtype;
1664 D (emitcode (";", "genUminus ");
1669 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1670 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1672 /* if both in bit space then special
1674 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1675 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1678 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1679 emitcode ("cpl", "c");
1680 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1684 optype = operandType (IC_LEFT (ic));
1685 rtype = operandType (IC_RESULT (ic));
1687 /* if float then do float stuff */
1688 if (IS_FLOAT (optype))
1690 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1694 /* otherwise subtract from zero */
1695 size = AOP_SIZE (IC_LEFT (ic));
1697 _startLazyDPSEvaluation ();
1700 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1701 if (!strcmp (l, "a"))
1705 emitcode ("cpl", "a");
1706 emitcode ("addc", "a,#0");
1712 emitcode ("clr", "a");
1713 emitcode ("subb", "a,%s", l);
1715 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1717 _endLazyDPSEvaluation ();
1719 /* if any remaining bytes in the result */
1720 /* we just need to propagate the sign */
1721 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1723 emitcode ("rlc", "a");
1724 emitcode ("subb", "a,acc");
1726 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1730 /* release the aops */
1731 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1732 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1735 /*-----------------------------------------------------------------*/
1736 /* saveRegisters - will look for a call and save the registers */
1737 /*-----------------------------------------------------------------*/
1739 saveRegisters (iCode * lic)
1747 for (ic = lic; ic; ic = ic->next)
1748 if (ic->op == CALL || ic->op == PCALL)
1753 fprintf (stderr, "found parameter push with no function call\n");
1757 /* if the registers have been saved already then
1759 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1762 /* find the registers in use at this time
1763 and push them away to safety */
1764 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1768 if (options.useXstack)
1770 if (bitVectBitValue (rsave, R0_IDX))
1771 emitcode ("mov", "b,r0");
1772 emitcode ("mov", "r0,%s", spname);
1773 for (i = 0; i < ds390_nRegs; i++)
1775 if (bitVectBitValue (rsave, i))
1778 emitcode ("mov", "a,b");
1780 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1781 emitcode ("movx", "@r0,a");
1782 emitcode ("inc", "r0");
1785 emitcode ("mov", "%s,r0", spname);
1786 if (bitVectBitValue (rsave, R0_IDX))
1787 emitcode ("mov", "r0,b");
1790 for (i = 0; i < ds390_nRegs; i++)
1792 if (bitVectBitValue (rsave, i))
1793 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1796 detype = getSpec (operandType (IC_LEFT (ic)));
1798 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1799 IS_ISR (currFunc->etype) &&
1802 saverbank (SPEC_BANK (detype), ic, TRUE);
1805 /*-----------------------------------------------------------------*/
1806 /* unsaveRegisters - pop the pushed registers */
1807 /*-----------------------------------------------------------------*/
1809 unsaveRegisters (iCode * ic)
1813 /* find the registers in use at this time
1814 and push them away to safety */
1815 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1818 if (options.useXstack)
1820 emitcode ("mov", "r0,%s", spname);
1821 for (i = ds390_nRegs; i >= 0; i--)
1823 if (bitVectBitValue (rsave, i))
1825 emitcode ("dec", "r0");
1826 emitcode ("movx", "a,@r0");
1828 emitcode ("mov", "b,a");
1830 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1834 emitcode ("mov", "%s,r0", spname);
1835 if (bitVectBitValue (rsave, R0_IDX))
1836 emitcode ("mov", "r0,b");
1839 for (i = ds390_nRegs; i >= 0; i--)
1841 if (bitVectBitValue (rsave, i))
1842 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1848 /*-----------------------------------------------------------------*/
1850 /*-----------------------------------------------------------------*/
1852 pushSide (operand * oper, int size)
1855 _startLazyDPSEvaluation ();
1858 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1859 if (AOP_TYPE (oper) != AOP_REG &&
1860 AOP_TYPE (oper) != AOP_DIR &&
1863 emitcode ("mov", "a,%s", l);
1864 emitcode ("push", "acc");
1867 emitcode ("push", "%s", l);
1869 _endLazyDPSEvaluation ();
1872 /*-----------------------------------------------------------------*/
1873 /* assignResultValue - */
1874 /*-----------------------------------------------------------------*/
1876 assignResultValue (operand * oper)
1879 int size = AOP_SIZE (oper);
1881 _startLazyDPSEvaluation ();
1884 aopPut (AOP (oper), fReturn[offset], offset);
1887 _endLazyDPSEvaluation ();
1891 /*-----------------------------------------------------------------*/
1892 /* genXpush - pushes onto the external stack */
1893 /*-----------------------------------------------------------------*/
1895 genXpush (iCode * ic)
1897 asmop *aop = newAsmop (0);
1899 int size, offset = 0;
1901 D (emitcode (";", "genXpush ");
1904 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1905 r = getFreePtr (ic, &aop, FALSE);
1908 emitcode ("mov", "%s,_spx", r->name);
1910 size = AOP_SIZE (IC_LEFT (ic));
1911 _startLazyDPSEvaluation ();
1915 char *l = aopGet (AOP (IC_LEFT (ic)),
1916 offset++, FALSE, FALSE, TRUE);
1918 emitcode ("movx", "@%s,a", r->name);
1919 emitcode ("inc", "%s", r->name);
1922 _endLazyDPSEvaluation ();
1925 emitcode ("mov", "_spx,%s", r->name);
1927 freeAsmop (NULL, aop, ic, TRUE);
1928 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1931 /*-----------------------------------------------------------------*/
1932 /* genIpush - genrate code for pushing this gets a little complex */
1933 /*-----------------------------------------------------------------*/
1935 genIpush (iCode * ic)
1937 int size, offset = 0;
1940 D (emitcode (";", "genIpush ");
1944 /* if this is not a parm push : ie. it is spill push
1945 and spill push is always done on the local stack */
1949 /* and the item is spilt then do nothing */
1950 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1953 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1954 size = AOP_SIZE (IC_LEFT (ic));
1955 /* push it on the stack */
1956 _startLazyDPSEvaluation ();
1959 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1965 emitcode ("push", "%s", l);
1967 _endLazyDPSEvaluation ();
1971 /* this is a paramter push: in this case we call
1972 the routine to find the call and save those
1973 registers that need to be saved */
1976 /* if use external stack then call the external
1977 stack pushing routine */
1978 if (options.useXstack)
1984 /* then do the push */
1985 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1987 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1988 size = AOP_SIZE (IC_LEFT (ic));
1990 _startLazyDPSEvaluation ();
1993 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1994 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1995 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1998 emitcode ("mov", "a,%s", l);
1999 emitcode ("push", "acc");
2002 emitcode ("push", "%s", l);
2004 _endLazyDPSEvaluation ();
2006 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2009 /*-----------------------------------------------------------------*/
2010 /* genIpop - recover the registers: can happen only for spilling */
2011 /*-----------------------------------------------------------------*/
2013 genIpop (iCode * ic)
2017 D (emitcode (";", "genIpop ");
2021 /* if the temp was not pushed then */
2022 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2025 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2026 size = AOP_SIZE (IC_LEFT (ic));
2027 offset = (size - 1);
2028 _startLazyDPSEvaluation ();
2031 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2032 FALSE, TRUE, TRUE));
2034 _endLazyDPSEvaluation ();
2036 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2039 /*-----------------------------------------------------------------*/
2040 /* unsaverbank - restores the resgister bank from stack */
2041 /*-----------------------------------------------------------------*/
2043 unsaverbank (int bank, iCode * ic, bool popPsw)
2051 if (options.useXstack)
2054 r = getFreePtr (ic, &aop, FALSE);
2057 emitcode ("mov", "%s,_spx", r->name);
2058 emitcode ("movx", "a,@%s", r->name);
2059 emitcode ("mov", "psw,a");
2060 emitcode ("dec", "%s", r->name);
2064 emitcode ("pop", "psw");
2067 for (i = (ds390_nRegs - 1); i >= 0; i--)
2069 if (options.useXstack)
2071 emitcode ("movx", "a,@%s", r->name);
2072 emitcode ("mov", "(%s+%d),a",
2073 regs390[i].base, 8 * bank + regs390[i].offset);
2074 emitcode ("dec", "%s", r->name);
2078 emitcode ("pop", "(%s+%d)",
2079 regs390[i].base, 8 * bank + regs390[i].offset);
2082 if (options.useXstack)
2085 emitcode ("mov", "_spx,%s", r->name);
2086 freeAsmop (NULL, aop, ic, TRUE);
2091 /*-----------------------------------------------------------------*/
2092 /* saverbank - saves an entire register bank on the stack */
2093 /*-----------------------------------------------------------------*/
2095 saverbank (int bank, iCode * ic, bool pushPsw)
2101 if (options.useXstack)
2105 r = getFreePtr (ic, &aop, FALSE);
2106 emitcode ("mov", "%s,_spx", r->name);
2110 for (i = 0; i < ds390_nRegs; i++)
2112 if (options.useXstack)
2114 emitcode ("inc", "%s", r->name);
2115 emitcode ("mov", "a,(%s+%d)",
2116 regs390[i].base, 8 * bank + regs390[i].offset);
2117 emitcode ("movx", "@%s,a", r->name);
2120 emitcode ("push", "(%s+%d)",
2121 regs390[i].base, 8 * bank + regs390[i].offset);
2126 if (options.useXstack)
2128 emitcode ("mov", "a,psw");
2129 emitcode ("movx", "@%s,a", r->name);
2130 emitcode ("inc", "%s", r->name);
2131 emitcode ("mov", "_spx,%s", r->name);
2132 freeAsmop (NULL, aop, ic, TRUE);
2136 emitcode ("push", "psw");
2138 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2144 /*-----------------------------------------------------------------*/
2145 /* genCall - generates a call statement */
2146 /*-----------------------------------------------------------------*/
2148 genCall (iCode * ic)
2152 D (emitcode (";", "genCall ");
2155 /* if caller saves & we have not saved then */
2159 /* if we are calling a function that is not using
2160 the same register bank then we need to save the
2161 destination registers on the stack */
2162 detype = getSpec (operandType (IC_LEFT (ic)));
2164 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2165 IS_ISR (currFunc->etype) &&
2168 saverbank (SPEC_BANK (detype), ic, TRUE);
2170 /* if send set is not empty the assign */
2175 for (sic = setFirstItem (_G.sendSet); sic;
2176 sic = setNextItem (_G.sendSet))
2178 int size, offset = 0;
2180 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2181 size = AOP_SIZE (IC_LEFT (sic));
2183 _startLazyDPSEvaluation ();
2186 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2187 FALSE, FALSE, TRUE);
2188 if (strcmp (l, fReturn[offset]))
2189 emitcode ("mov", "%s,%s",
2194 _endLazyDPSEvaluation ();
2195 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2200 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2201 OP_SYMBOL (IC_LEFT (ic))->rname :
2202 OP_SYMBOL (IC_LEFT (ic))->name));
2204 /* if we need assign a result value */
2205 if ((IS_ITEMP (IC_RESULT (ic)) &&
2206 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2207 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2208 IS_TRUE_SYMOP (IC_RESULT (ic)))
2210 if (isOperandInFarSpace (IC_RESULT (ic))
2211 && getSize (operandType (IC_RESULT (ic))) <= 2)
2213 int size = getSize (operandType (IC_RESULT (ic)));
2215 /* Special case for 1 or 2 byte return in far space. */
2216 emitcode (";", "Kevin function call abuse #1");
2221 emitcode ("mov", "b,%s", fReturn[1]);
2224 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2225 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2229 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2231 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2236 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2239 assignResultValue (IC_RESULT (ic));
2241 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2245 /* adjust the stack for parameters if
2247 if (IC_LEFT (ic)->parmBytes)
2250 if (IC_LEFT (ic)->parmBytes > 3)
2252 emitcode ("mov", "a,%s", spname);
2253 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
2254 emitcode ("mov", "%s,a", spname);
2257 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
2258 emitcode ("dec", "%s", spname);
2262 /* if register bank was saved then pop them */
2264 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2266 /* if we hade saved some registers then unsave them */
2267 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2268 unsaveRegisters (ic);
2273 /*-----------------------------------------------------------------*/
2274 /* genPcall - generates a call by pointer statement */
2275 /*-----------------------------------------------------------------*/
2277 genPcall (iCode * ic)
2280 symbol *rlbl = newiTempLabel (NULL);
2282 D (emitcode (";", "genPcall ");
2286 /* if caller saves & we have not saved then */
2290 /* if we are calling a function that is not using
2291 the same register bank then we need to save the
2292 destination registers on the stack */
2293 detype = getSpec (operandType (IC_LEFT (ic)));
2295 IS_ISR (currFunc->etype) &&
2296 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2297 saverbank (SPEC_BANK (detype), ic, TRUE);
2300 /* push the return address on to the stack */
2301 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2302 emitcode ("push", "acc");
2303 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2304 emitcode ("push", "acc");
2306 if (options.model == MODEL_FLAT24)
2308 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2309 emitcode ("push", "acc");
2312 /* now push the calling address */
2313 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2315 pushSide (IC_LEFT (ic), FPTRSIZE);
2317 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2319 /* if send set is not empty the assign */
2324 for (sic = setFirstItem (_G.sendSet); sic;
2325 sic = setNextItem (_G.sendSet))
2327 int size, offset = 0;
2329 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2330 size = AOP_SIZE (IC_LEFT (sic));
2331 _startLazyDPSEvaluation ();
2334 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2335 FALSE, FALSE, TRUE);
2336 if (strcmp (l, fReturn[offset]))
2338 emitcode ("mov", "%s,%s",
2344 _endLazyDPSEvaluation ();
2345 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2350 emitcode ("ret", "");
2351 emitcode ("", "%05d$:", (rlbl->key + 100));
2354 /* if we need assign a result value */
2355 if ((IS_ITEMP (IC_RESULT (ic)) &&
2356 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2357 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2358 IS_TRUE_SYMOP (IC_RESULT (ic)))
2362 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2365 assignResultValue (IC_RESULT (ic));
2367 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2370 /* adjust the stack for parameters if
2372 if (IC_LEFT (ic)->parmBytes)
2375 if (IC_LEFT (ic)->parmBytes > 3)
2377 emitcode ("mov", "a,%s", spname);
2378 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
2379 emitcode ("mov", "%s,a", spname);
2382 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
2383 emitcode ("dec", "%s", spname);
2387 /* if register bank was saved then unsave them */
2389 (SPEC_BANK (currFunc->etype) !=
2390 SPEC_BANK (detype)))
2391 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2393 /* if we hade saved some registers then
2396 unsaveRegisters (ic);
2400 /*-----------------------------------------------------------------*/
2401 /* resultRemat - result is rematerializable */
2402 /*-----------------------------------------------------------------*/
2404 resultRemat (iCode * ic)
2406 if (SKIP_IC (ic) || ic->op == IFX)
2409 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2411 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2412 if (sym->remat && !POINTER_SET (ic))
2419 #if defined(__BORLANDC__) || defined(_MSC_VER)
2420 #define STRCASECMP stricmp
2422 #define STRCASECMP strcasecmp
2425 /*-----------------------------------------------------------------*/
2426 /* inExcludeList - return 1 if the string is in exclude Reg list */
2427 /*-----------------------------------------------------------------*/
2429 inExcludeList (char *s)
2433 if (options.excludeRegs[i] &&
2434 STRCASECMP (options.excludeRegs[i], "none") == 0)
2437 for (i = 0; options.excludeRegs[i]; i++)
2439 if (options.excludeRegs[i] &&
2440 STRCASECMP (s, options.excludeRegs[i]) == 0)
2446 /*-----------------------------------------------------------------*/
2447 /* genFunction - generated code for function entry */
2448 /*-----------------------------------------------------------------*/
2450 genFunction (iCode * ic)
2455 D (emitcode (";", "genFunction ");
2459 /* create the function header */
2460 emitcode (";", "-----------------------------------------");
2461 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2462 emitcode (";", "-----------------------------------------");
2464 emitcode ("", "%s:", sym->rname);
2465 fetype = getSpec (operandType (IC_LEFT (ic)));
2467 /* if critical function then turn interrupts off */
2468 if (SPEC_CRTCL (fetype))
2469 emitcode ("clr", "ea");
2471 /* here we need to generate the equates for the
2472 register bank if required */
2473 if (SPEC_BANK (fetype) != rbank)
2477 rbank = SPEC_BANK (fetype);
2478 for (i = 0; i < ds390_nRegs; i++)
2480 if (strcmp (regs390[i].base, "0") == 0)
2481 emitcode ("", "%s = 0x%02x",
2483 8 * rbank + regs390[i].offset);
2485 emitcode ("", "%s = %s + 0x%02x",
2488 8 * rbank + regs390[i].offset);
2492 /* if this is an interrupt service routine then
2493 save acc, b, dpl, dph */
2494 if (IS_ISR (sym->etype))
2497 if (!inExcludeList ("acc"))
2498 emitcode ("push", "acc");
2499 if (!inExcludeList ("b"))
2500 emitcode ("push", "b");
2501 if (!inExcludeList ("dpl"))
2502 emitcode ("push", "dpl");
2503 if (!inExcludeList ("dph"))
2504 emitcode ("push", "dph");
2505 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2507 emitcode ("push", "dpx");
2508 /* Make sure we're using standard DPTR */
2509 emitcode ("push", "dps");
2510 emitcode ("mov", "dps, #0x00");
2511 if (options.stack10bit)
2513 /* This ISR could conceivably use DPTR2. Better save it. */
2514 emitcode ("push", "dpl1");
2515 emitcode ("push", "dph1");
2516 emitcode ("push", "dpx1");
2517 emitcode ("push", "ap");
2520 /* if this isr has no bank i.e. is going to
2521 run with bank 0 , then we need to save more
2523 if (!SPEC_BANK (sym->etype))
2526 /* if this function does not call any other
2527 function then we can be economical and
2528 save only those registers that are used */
2533 /* if any registers used */
2536 /* save the registers used */
2537 for (i = 0; i < sym->regsUsed->size; i++)
2539 if (bitVectBitValue (sym->regsUsed, i) ||
2540 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2541 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2548 /* this function has a function call cannot
2549 determines register usage so we will have the
2551 saverbank (0, ic, FALSE);
2557 /* if callee-save to be used for this function
2558 then save the registers being used in this function */
2559 if (sym->calleeSave)
2563 /* if any registers used */
2566 /* save the registers used */
2567 for (i = 0; i < sym->regsUsed->size; i++)
2569 if (bitVectBitValue (sym->regsUsed, i) ||
2570 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2572 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2580 /* set the register bank to the desired value */
2581 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2583 emitcode ("push", "psw");
2584 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2587 if (IS_RENT (sym->etype) || options.stackAuto)
2590 if (options.useXstack)
2592 emitcode ("mov", "r0,%s", spname);
2593 emitcode ("mov", "a,_bp");
2594 emitcode ("movx", "@r0,a");
2595 emitcode ("inc", "%s", spname);
2599 /* set up the stack */
2600 emitcode ("push", "_bp"); /* save the callers stack */
2602 emitcode ("mov", "_bp,%s", spname);
2605 /* adjust the stack for the function */
2611 werror (W_STACK_OVERFLOW, sym->name);
2613 if (i > 3 && sym->recvSize < 4)
2616 emitcode ("mov", "a,sp");
2617 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2618 emitcode ("mov", "sp,a");
2623 emitcode ("inc", "sp");
2629 emitcode ("mov", "a,_spx");
2630 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2631 emitcode ("mov", "_spx,a");
2636 /*-----------------------------------------------------------------*/
2637 /* genEndFunction - generates epilogue for functions */
2638 /*-----------------------------------------------------------------*/
2640 genEndFunction (iCode * ic)
2642 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2644 D (emitcode (";", "genEndFunction ");
2647 if (IS_RENT (sym->etype) || options.stackAuto)
2649 emitcode ("mov", "%s,_bp", spname);
2652 /* if use external stack but some variables were
2653 added to the local stack then decrement the
2655 if (options.useXstack && sym->stack)
2657 emitcode ("mov", "a,sp");
2658 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2659 emitcode ("mov", "sp,a");
2663 if ((IS_RENT (sym->etype) || options.stackAuto))
2665 if (options.useXstack)
2667 emitcode ("mov", "r0,%s", spname);
2668 emitcode ("movx", "a,@r0");
2669 emitcode ("mov", "_bp,a");
2670 emitcode ("dec", "%s", spname);
2674 emitcode ("pop", "_bp");
2678 /* restore the register bank */
2679 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2680 emitcode ("pop", "psw");
2682 if (IS_ISR (sym->etype))
2685 /* now we need to restore the registers */
2686 /* if this isr has no bank i.e. is going to
2687 run with bank 0 , then we need to save more
2689 if (!SPEC_BANK (sym->etype))
2692 /* if this function does not call any other
2693 function then we can be economical and
2694 save only those registers that are used */
2699 /* if any registers used */
2702 /* save the registers used */
2703 for (i = sym->regsUsed->size; i >= 0; i--)
2705 if (bitVectBitValue (sym->regsUsed, i) ||
2706 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2707 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2714 /* this function has a function call cannot
2715 determines register usage so we will have the
2717 unsaverbank (0, ic, FALSE);
2721 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2723 if (options.stack10bit)
2725 emitcode ("pop", "ap");
2726 emitcode ("pop", "dpx1");
2727 emitcode ("pop", "dph1");
2728 emitcode ("pop", "dpl1");
2730 emitcode ("pop", "dps");
2731 emitcode ("pop", "dpx");
2733 if (!inExcludeList ("dph"))
2734 emitcode ("pop", "dph");
2735 if (!inExcludeList ("dpl"))
2736 emitcode ("pop", "dpl");
2737 if (!inExcludeList ("b"))
2738 emitcode ("pop", "b");
2739 if (!inExcludeList ("acc"))
2740 emitcode ("pop", "acc");
2742 if (SPEC_CRTCL (sym->etype))
2743 emitcode ("setb", "ea");
2745 /* if debug then send end of function */
2746 /* if (options.debug && currFunc) { */
2750 emitcode ("", "C$%s$%d$%d$%d ==.",
2751 FileBaseName (ic->filename), currFunc->lastLine,
2752 ic->level, ic->block);
2753 if (IS_STATIC (currFunc->etype))
2754 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2756 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2760 emitcode ("reti", "");
2764 if (SPEC_CRTCL (sym->etype))
2765 emitcode ("setb", "ea");
2767 if (sym->calleeSave)
2771 /* if any registers used */
2774 /* save the registers used */
2775 for (i = sym->regsUsed->size; i >= 0; i--)
2777 if (bitVectBitValue (sym->regsUsed, i) ||
2778 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2779 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2785 /* if debug then send end of function */
2789 emitcode ("", "C$%s$%d$%d$%d ==.",
2790 FileBaseName (ic->filename), currFunc->lastLine,
2791 ic->level, ic->block);
2792 if (IS_STATIC (currFunc->etype))
2793 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2795 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2799 emitcode ("ret", "");
2804 /*-----------------------------------------------------------------*/
2805 /* genRet - generate code for return statement */
2806 /*-----------------------------------------------------------------*/
2810 int size, offset = 0, pushed = 0;
2812 D (emitcode (";", "genRet ");
2815 /* if we have no return value then
2816 just generate the "ret" */
2820 /* we have something to return then
2821 move the return value into place */
2822 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2823 size = AOP_SIZE (IC_LEFT (ic));
2825 _startLazyDPSEvaluation ();
2829 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2831 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2832 FALSE, TRUE, FALSE);
2833 emitcode ("push", "%s", l);
2838 l = aopGet (AOP (IC_LEFT (ic)), offset,
2839 FALSE, FALSE, FALSE);
2840 if (strcmp (fReturn[offset], l))
2841 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2844 _endLazyDPSEvaluation ();
2851 if (strcmp (fReturn[pushed], "a"))
2852 emitcode ("pop", fReturn[pushed]);
2854 emitcode ("pop", "acc");
2857 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2860 /* generate a jump to the return label
2861 if the next is not the return statement */
2862 if (!(ic->next && ic->next->op == LABEL &&
2863 IC_LABEL (ic->next) == returnLabel))
2865 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2869 /*-----------------------------------------------------------------*/
2870 /* genLabel - generates a label */
2871 /*-----------------------------------------------------------------*/
2873 genLabel (iCode * ic)
2875 /* special case never generate */
2876 if (IC_LABEL (ic) == entryLabel)
2879 D (emitcode (";", "genLabel ");
2882 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2885 /*-----------------------------------------------------------------*/
2886 /* genGoto - generates a ljmp */
2887 /*-----------------------------------------------------------------*/
2889 genGoto (iCode * ic)
2891 D (emitcode (";", "genGoto ");
2893 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2896 /*-----------------------------------------------------------------*/
2897 /* findLabelBackwards: walks back through the iCode chain looking */
2898 /* for the given label. Returns number of iCode instructions */
2899 /* between that label and given ic. */
2900 /* Returns zero if label not found. */
2901 /*-----------------------------------------------------------------*/
2903 findLabelBackwards (iCode * ic, int key)
2912 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2914 /* printf("findLabelBackwards = %d\n", count); */
2922 /*-----------------------------------------------------------------*/
2923 /* genPlusIncr :- does addition with increment if possible */
2924 /*-----------------------------------------------------------------*/
2926 genPlusIncr (iCode * ic)
2928 unsigned int icount;
2929 unsigned int size = getDataSize (IC_RESULT (ic));
2931 /* will try to generate an increment */
2932 /* if the right side is not a literal
2934 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2937 /* if the literal value of the right hand side
2938 is greater than 4 then it is not worth it */
2939 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2942 /* if increment 16 bits in register */
2944 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2945 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2946 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2954 /* If the next instruction is a goto and the goto target
2955 * is <= 5 instructions previous to this, we can generate
2956 * jumps straight to that target.
2958 if (ic->next && ic->next->op == GOTO
2959 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2962 emitcode (";", "tail increment optimized (range %d)", labelRange);
2963 tlbl = IC_LABEL (ic->next);
2968 tlbl = newiTempLabel (NULL);
2971 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2972 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2973 IS_AOP_PREG (IC_RESULT (ic)))
2974 emitcode ("cjne", "%s,#0x00,%05d$"
2975 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2979 emitcode ("clr", "a");
2980 emitcode ("cjne", "a,%s,%05d$"
2981 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2985 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2988 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2989 IS_AOP_PREG (IC_RESULT (ic)))
2990 emitcode ("cjne", "%s,#0x00,%05d$"
2991 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2994 emitcode ("cjne", "a,%s,%05d$"
2995 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2998 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3002 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3003 IS_AOP_PREG (IC_RESULT (ic)))
3004 emitcode ("cjne", "%s,#0x00,%05d$"
3005 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3009 emitcode ("cjne", "a,%s,%05d$"
3010 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3013 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3018 emitcode ("", "%05d$:", tlbl->key + 100);
3023 /* if the sizes are greater than 1 then we cannot */
3024 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3025 AOP_SIZE (IC_LEFT (ic)) > 1)
3028 /* we can if the aops of the left & result match or
3029 if they are in registers and the registers are the
3032 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3033 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3034 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3039 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3040 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3041 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3046 _startLazyDPSEvaluation ();
3049 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3051 _endLazyDPSEvaluation ();
3060 /*-----------------------------------------------------------------*/
3061 /* outBitAcc - output a bit in acc */
3062 /*-----------------------------------------------------------------*/
3064 outBitAcc (operand * result)
3066 symbol *tlbl = newiTempLabel (NULL);
3067 /* if the result is a bit */
3068 if (AOP_TYPE (result) == AOP_CRY)
3070 aopPut (AOP (result), "a", 0);
3074 emitcode ("jz", "%05d$", tlbl->key + 100);
3075 emitcode ("mov", "a,%s", one);
3076 emitcode ("", "%05d$:", tlbl->key + 100);
3081 /*-----------------------------------------------------------------*/
3082 /* genPlusBits - generates code for addition of two bits */
3083 /*-----------------------------------------------------------------*/
3085 genPlusBits (iCode * ic)
3087 D (emitcode (";", "genPlusBits ");
3089 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3091 symbol *lbl = newiTempLabel (NULL);
3092 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3093 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3094 emitcode ("cpl", "c");
3095 emitcode ("", "%05d$:", (lbl->key + 100));
3096 outBitC (IC_RESULT (ic));
3100 emitcode ("clr", "a");
3101 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3102 emitcode ("rlc", "a");
3103 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3104 emitcode ("addc", "a,#0x00");
3105 outAcc (IC_RESULT (ic));
3110 adjustArithmeticResult (iCode * ic)
3112 if (opIsGptr (IC_RESULT (ic)) &&
3113 opIsGptr (IC_LEFT (ic)) &&
3114 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3116 aopPut (AOP (IC_RESULT (ic)),
3117 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3121 if (opIsGptr (IC_RESULT (ic)) &&
3122 opIsGptr (IC_RIGHT (ic)) &&
3123 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3125 aopPut (AOP (IC_RESULT (ic)),
3126 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3130 if (opIsGptr (IC_RESULT (ic)) &&
3131 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3132 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3133 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3134 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3137 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3138 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3142 #define AOP_OP_3(ic) \
3143 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3144 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3145 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3146 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3147 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3148 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3150 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3152 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3155 #define AOP_OP_3_NOFATAL(ic, rc) \
3156 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3157 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3158 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3159 isOperandInFarSpace(IC_RESULT(ic))) \
3161 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3166 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3167 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3169 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3170 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3172 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3174 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3178 #define AOP_OP_2(ic) \
3179 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3180 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3182 #define AOP_SET_LOCALS(ic) \
3183 left = IC_LEFT(ic); \
3184 right = IC_RIGHT(ic); \
3185 result = IC_RESULT(ic);
3187 /*-----------------------------------------------------------------*/
3188 /* genPlus - generates code for addition */
3189 /*-----------------------------------------------------------------*/
3191 genPlus (iCode * ic)
3193 int size, offset = 0;
3194 bool pushResult = FALSE;
3197 D (emitcode (";", "genPlus ");
3200 /* special cases :- */
3202 AOP_OP_3_NOFATAL (ic, pushResult);
3205 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3211 /* if literal, literal on the right or
3212 if left requires ACC or right is already
3214 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3215 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3216 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3218 operand *t = IC_RIGHT (ic);
3219 IC_RIGHT (ic) = IC_LEFT (ic);
3221 emitcode (";", "Swapped plus args.");
3224 /* if both left & right are in bit
3226 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3227 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3233 /* if left in bit space & right literal */
3234 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3235 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3237 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3238 /* if result in bit space */
3239 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3241 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3242 emitcode ("cpl", "c");
3243 outBitC (IC_RESULT (ic));
3247 size = getDataSize (IC_RESULT (ic));
3248 _startLazyDPSEvaluation ();
3251 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3252 emitcode ("addc", "a,#00");
3253 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3255 _endLazyDPSEvaluation ();
3260 /* if I can do an increment instead
3261 of add then GOOD for ME */
3262 if (genPlusIncr (ic) == TRUE)
3264 emitcode (";", "did genPlusIncr");
3269 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3271 _startLazyDPSEvaluation ();
3274 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3276 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3278 emitcode ("add", "a,%s",
3279 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3281 emitcode ("addc", "a,%s",
3282 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3286 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3288 emitcode ("add", "a,%s",
3289 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3291 emitcode ("addc", "a,%s",
3292 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3296 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3300 emitcode ("push", "acc");
3304 _endLazyDPSEvaluation ();
3308 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3310 size = getDataSize (IC_LEFT (ic));
3311 rSize = getDataSize (IC_RESULT (ic));
3313 /* If the pushed data is bigger than the result,
3314 * simply discard unused bytes. Icky, but works.
3316 * Should we throw a warning here? We're losing data...
3318 while (size > rSize)
3320 D (emitcode (";", "discarding unused result byte.");
3322 emitcode ("pop", "acc");
3328 emitcode ("clr", "a");
3329 /* Conversly, we haven't pushed enough here.
3330 * just zero-pad, and all is well.
3332 while (size < rSize)
3334 emitcode ("push", "acc");
3340 _startLazyDPSEvaluation ();
3343 emitcode ("pop", "acc");
3344 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3346 _endLazyDPSEvaluation ();
3349 adjustArithmeticResult (ic);
3352 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3353 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3354 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3357 /*-----------------------------------------------------------------*/
3358 /* genMinusDec :- does subtraction with deccrement if possible */
3359 /*-----------------------------------------------------------------*/
3361 genMinusDec (iCode * ic)
3363 unsigned int icount;
3364 unsigned int size = getDataSize (IC_RESULT (ic));
3366 /* will try to generate an increment */
3367 /* if the right side is not a literal
3369 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3372 /* if the literal value of the right hand side
3373 is greater than 4 then it is not worth it */
3374 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3377 /* if decrement 16 bits in register */
3378 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3379 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3380 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3388 /* If the next instruction is a goto and the goto target
3389 * is <= 5 instructions previous to this, we can generate
3390 * jumps straight to that target.
3392 if (ic->next && ic->next->op == GOTO
3393 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3396 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3397 tlbl = IC_LABEL (ic->next);
3402 tlbl = newiTempLabel (NULL);
3406 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3407 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3408 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3409 IS_AOP_PREG (IC_RESULT (ic)))
3410 emitcode ("cjne", "%s,#0xff,%05d$"
3411 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3415 emitcode ("mov", "a,#0xff");
3416 emitcode ("cjne", "a,%s,%05d$"
3417 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3420 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3423 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3424 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3425 IS_AOP_PREG (IC_RESULT (ic)))
3426 emitcode ("cjne", "%s,#0xff,%05d$"
3427 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3431 emitcode ("cjne", "a,%s,%05d$"
3432 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3435 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3439 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3440 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3441 IS_AOP_PREG (IC_RESULT (ic)))
3442 emitcode ("cjne", "%s,#0xff,%05d$"
3443 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3447 emitcode ("cjne", "a,%s,%05d$"
3448 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3451 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3455 emitcode ("", "%05d$:", tlbl->key + 100);
3460 /* if the sizes are greater than 1 then we cannot */
3461 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3462 AOP_SIZE (IC_LEFT (ic)) > 1)
3465 /* we can if the aops of the left & result match or
3466 if they are in registers and the registers are the
3469 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3470 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3471 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3474 _startLazyDPSEvaluation ();
3477 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3479 _endLazyDPSEvaluation ();
3487 /*-----------------------------------------------------------------*/
3488 /* addSign - complete with sign */
3489 /*-----------------------------------------------------------------*/
3491 addSign (operand * result, int offset, int sign)
3493 int size = (getDataSize (result) - offset);
3498 emitcode ("rlc", "a");
3499 emitcode ("subb", "a,acc");
3501 aopPut (AOP (result), "a", offset++);
3505 aopPut (AOP (result), zero, offset++);
3509 /*-----------------------------------------------------------------*/
3510 /* genMinusBits - generates code for subtraction of two bits */
3511 /*-----------------------------------------------------------------*/
3513 genMinusBits (iCode * ic)
3515 symbol *lbl = newiTempLabel (NULL);
3517 D (emitcode (";", "genMinusBits ");
3520 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3522 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3523 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3524 emitcode ("cpl", "c");
3525 emitcode ("", "%05d$:", (lbl->key + 100));
3526 outBitC (IC_RESULT (ic));
3530 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3531 emitcode ("subb", "a,acc");
3532 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3533 emitcode ("inc", "a");
3534 emitcode ("", "%05d$:", (lbl->key + 100));
3535 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3536 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3540 /*-----------------------------------------------------------------*/
3541 /* genMinus - generates code for subtraction */
3542 /*-----------------------------------------------------------------*/
3544 genMinus (iCode * ic)
3546 int size, offset = 0;
3548 unsigned long lit = 0L;
3549 bool pushResult = FALSE;
3551 D (emitcode (";", "genMinus ");
3554 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3555 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3556 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3557 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3563 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3565 /* special cases :- */
3566 /* if both left & right are in bit space */
3567 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3568 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3574 /* if I can do an decrement instead
3575 of subtract then GOOD for ME */
3576 if (genMinusDec (ic) == TRUE)
3581 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3583 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3589 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3594 /* if literal, add a,#-lit, else normal subb */
3595 _startLazyDPSEvaluation ();
3598 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3599 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3600 emitcode ("subb", "a,%s",
3601 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3604 /* first add without previous c */
3606 emitcode ("add", "a,#0x%02x",
3607 (unsigned int) (lit & 0x0FFL));
3609 emitcode ("addc", "a,#0x%02x",
3610 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3615 emitcode ("push", "acc");
3619 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3623 _endLazyDPSEvaluation ();
3627 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3629 size = getDataSize (IC_LEFT (ic));
3630 rSize = getDataSize (IC_RESULT (ic));
3632 /* If the pushed data is bigger than the result,
3633 * simply discard unused bytes. Icky, but works.
3635 * Should we throw a warning here? We're losing data...
3637 while (size > getDataSize (IC_RESULT (ic)))
3639 emitcode (";", "discarding unused result byte.");
3640 emitcode ("pop", "acc");
3646 emitcode ("clr", "a");
3647 /* Conversly, we haven't pushed enough here.
3648 * just zero-pad, and all is well.
3650 while (size < rSize)
3652 emitcode ("push", "acc");
3660 emitcode ("pop", "acc");
3661 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3665 adjustArithmeticResult (ic);
3668 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3669 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3670 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3674 /*-----------------------------------------------------------------*/
3675 /* genMultbits :- multiplication of bits */
3676 /*-----------------------------------------------------------------*/
3678 genMultbits (operand * left,
3682 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3683 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3688 /*-----------------------------------------------------------------*/
3689 /* genMultOneByte : 8 bit multiplication & division */
3690 /*-----------------------------------------------------------------*/
3692 genMultOneByte (operand * left,
3696 sym_link *opetype = operandType (result);
3701 /* (if two literals, the value is computed before) */
3702 /* if one literal, literal on the right */
3703 if (AOP_TYPE (left) == AOP_LIT)
3710 size = AOP_SIZE (result);
3711 /* signed or unsigned */
3712 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3713 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3715 emitcode ("mul", "ab");
3716 /* if result size = 1, mul signed = mul unsigned */
3717 aopPut (AOP (result), "a", 0);
3720 if (SPEC_USIGN (opetype))
3722 aopPut (AOP (result), "b", 1);
3724 /* for filling the MSBs */
3725 emitcode ("clr", "a");
3729 emitcode ("mov", "a,b");
3731 /* adjust the MSB if left or right neg */
3733 /* if one literal */
3734 if (AOP_TYPE (right) == AOP_LIT)
3736 /* AND literal negative */
3737 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3739 /* adjust MSB (c==0 after mul) */
3740 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3745 lbl = newiTempLabel (NULL);
3746 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3747 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3748 emitcode ("", "%05d$:", (lbl->key + 100));
3749 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3750 lbl = newiTempLabel (NULL);
3751 emitcode ("jc", "%05d$", (lbl->key + 100));
3752 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3753 emitcode ("", "%05d$:", (lbl->key + 100));
3756 lbl = newiTempLabel (NULL);
3757 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3758 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3759 emitcode ("", "%05d$:", (lbl->key + 100));
3760 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
3761 lbl = newiTempLabel (NULL);
3762 emitcode ("jc", "%05d$", (lbl->key + 100));
3763 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
3764 emitcode ("", "%05d$:", (lbl->key + 100));
3766 aopPut (AOP (result), "a", 1);
3770 emitcode ("rlc", "a");
3771 emitcode ("subb", "a,acc");
3778 aopPut (AOP (result), "a", offset++);
3782 /*-----------------------------------------------------------------*/
3783 /* genMult - generates code for multiplication */
3784 /*-----------------------------------------------------------------*/
3786 genMult (iCode * ic)
3788 operand *left = IC_LEFT (ic);
3789 operand *right = IC_RIGHT (ic);
3790 operand *result = IC_RESULT (ic);
3792 D (emitcode (";", "genMult ");
3795 /* assign the amsops */
3798 /* special cases first */
3800 if (AOP_TYPE (left) == AOP_CRY &&
3801 AOP_TYPE (right) == AOP_CRY)
3803 genMultbits (left, right, result);
3807 /* if both are of size == 1 */
3808 if (AOP_SIZE (left) == 1 &&
3809 AOP_SIZE (right) == 1)
3811 genMultOneByte (left, right, result);
3815 /* should have been converted to function call */
3819 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3820 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3821 freeAsmop (result, NULL, ic, TRUE);
3824 /*-----------------------------------------------------------------*/
3825 /* genDivbits :- division of bits */
3826 /*-----------------------------------------------------------------*/
3828 genDivbits (operand * left,
3835 /* the result must be bit */
3836 LOAD_AB_FOR_DIV (left, right, l);
3837 emitcode ("div", "ab");
3838 emitcode ("rrc", "a");
3839 aopPut (AOP (result), "c", 0);
3842 /*-----------------------------------------------------------------*/
3843 /* genDivOneByte : 8 bit division */
3844 /*-----------------------------------------------------------------*/
3846 genDivOneByte (operand * left,
3850 sym_link *opetype = operandType (result);
3855 size = AOP_SIZE (result) - 1;
3857 /* signed or unsigned */
3858 if (SPEC_USIGN (opetype))
3860 /* unsigned is easy */
3861 LOAD_AB_FOR_DIV (left, right, l);
3862 emitcode ("div", "ab");
3863 aopPut (AOP (result), "a", 0);
3865 aopPut (AOP (result), zero, offset++);
3869 /* signed is a little bit more difficult */
3871 /* save the signs of the operands */
3872 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3874 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3875 emitcode ("push", "acc"); /* save it on the stack */
3877 /* now sign adjust for both left & right */
3878 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3880 lbl = newiTempLabel (NULL);
3881 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3882 emitcode ("cpl", "a");
3883 emitcode ("inc", "a");
3884 emitcode ("", "%05d$:", (lbl->key + 100));
3885 emitcode ("mov", "b,a");
3887 /* sign adjust left side */
3888 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3891 lbl = newiTempLabel (NULL);
3892 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3893 emitcode ("cpl", "a");
3894 emitcode ("inc", "a");
3895 emitcode ("", "%05d$:", (lbl->key + 100));
3897 /* now the division */
3898 emitcode ("nop", "; workaround for DS80C390 div bug.");
3899 emitcode ("div", "ab");
3900 /* we are interested in the lower order
3902 emitcode ("mov", "b,a");
3903 lbl = newiTempLabel (NULL);
3904 emitcode ("pop", "acc");
3905 /* if there was an over flow we don't
3906 adjust the sign of the result */
3907 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3908 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3910 emitcode ("clr", "a");
3911 emitcode ("subb", "a,b");
3912 emitcode ("mov", "b,a");
3913 emitcode ("", "%05d$:", (lbl->key + 100));
3915 /* now we are done */
3916 aopPut (AOP (result), "b", 0);
3919 emitcode ("mov", "c,b.7");
3920 emitcode ("subb", "a,acc");
3923 aopPut (AOP (result), "a", offset++);
3927 /*-----------------------------------------------------------------*/
3928 /* genDiv - generates code for division */
3929 /*-----------------------------------------------------------------*/
3933 operand *left = IC_LEFT (ic);
3934 operand *right = IC_RIGHT (ic);
3935 operand *result = IC_RESULT (ic);
3937 D (emitcode (";", "genDiv ");
3940 /* assign the amsops */
3943 /* special cases first */
3945 if (AOP_TYPE (left) == AOP_CRY &&
3946 AOP_TYPE (right) == AOP_CRY)
3948 genDivbits (left, right, result);
3952 /* if both are of size == 1 */
3953 if (AOP_SIZE (left) == 1 &&
3954 AOP_SIZE (right) == 1)
3956 genDivOneByte (left, right, result);
3960 /* should have been converted to function call */
3963 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3964 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3965 freeAsmop (result, NULL, ic, TRUE);
3968 /*-----------------------------------------------------------------*/
3969 /* genModbits :- modulus of bits */
3970 /*-----------------------------------------------------------------*/
3972 genModbits (operand * left,
3979 /* the result must be bit */
3980 LOAD_AB_FOR_DIV (left, right, l);
3981 emitcode ("div", "ab");
3982 emitcode ("mov", "a,b");
3983 emitcode ("rrc", "a");
3984 aopPut (AOP (result), "c", 0);
3987 /*-----------------------------------------------------------------*/
3988 /* genModOneByte : 8 bit modulus */
3989 /*-----------------------------------------------------------------*/
3991 genModOneByte (operand * left,
3995 sym_link *opetype = operandType (result);
3999 /* signed or unsigned */
4000 if (SPEC_USIGN (opetype))
4002 /* unsigned is easy */
4003 LOAD_AB_FOR_DIV (left, right, l);
4004 emitcode ("div", "ab");
4005 aopPut (AOP (result), "b", 0);
4009 /* signed is a little bit more difficult */
4011 /* save the signs of the operands */
4012 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4015 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4016 emitcode ("push", "acc"); /* save it on the stack */
4018 /* now sign adjust for both left & right */
4019 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4022 lbl = newiTempLabel (NULL);
4023 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4024 emitcode ("cpl", "a");
4025 emitcode ("inc", "a");
4026 emitcode ("", "%05d$:", (lbl->key + 100));
4027 emitcode ("mov", "b,a");
4029 /* sign adjust left side */
4030 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4033 lbl = newiTempLabel (NULL);
4034 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4035 emitcode ("cpl", "a");
4036 emitcode ("inc", "a");
4037 emitcode ("", "%05d$:", (lbl->key + 100));
4039 /* now the multiplication */
4040 emitcode ("nop", "; workaround for DS80C390 div bug.");
4041 emitcode ("div", "ab");
4042 /* we are interested in the lower order
4044 lbl = newiTempLabel (NULL);
4045 emitcode ("pop", "acc");
4046 /* if there was an over flow we don't
4047 adjust the sign of the result */
4048 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4049 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4051 emitcode ("clr", "a");
4052 emitcode ("subb", "a,b");
4053 emitcode ("mov", "b,a");
4054 emitcode ("", "%05d$:", (lbl->key + 100));
4056 /* now we are done */
4057 aopPut (AOP (result), "b", 0);
4061 /*-----------------------------------------------------------------*/
4062 /* genMod - generates code for division */
4063 /*-----------------------------------------------------------------*/
4067 operand *left = IC_LEFT (ic);
4068 operand *right = IC_RIGHT (ic);
4069 operand *result = IC_RESULT (ic);
4071 D (emitcode (";", "genMod ");
4074 /* assign the amsops */
4077 /* special cases first */
4079 if (AOP_TYPE (left) == AOP_CRY &&
4080 AOP_TYPE (right) == AOP_CRY)
4082 genModbits (left, right, result);
4086 /* if both are of size == 1 */
4087 if (AOP_SIZE (left) == 1 &&
4088 AOP_SIZE (right) == 1)
4090 genModOneByte (left, right, result);
4094 /* should have been converted to function call */
4098 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4099 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4100 freeAsmop (result, NULL, ic, TRUE);
4103 /*-----------------------------------------------------------------*/
4104 /* genIfxJump :- will create a jump depending on the ifx */
4105 /*-----------------------------------------------------------------*/
4107 genIfxJump (iCode * ic, char *jval)
4110 symbol *tlbl = newiTempLabel (NULL);
4113 D (emitcode (";", "genIfxJump ");
4116 /* if true label then we jump if condition
4120 jlbl = IC_TRUE (ic);
4121 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4122 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4126 /* false label is present */
4127 jlbl = IC_FALSE (ic);
4128 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4129 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4131 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4132 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4134 emitcode (inst, "%05d$", tlbl->key + 100);
4135 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4136 emitcode ("", "%05d$:", tlbl->key + 100);
4138 /* mark the icode as generated */
4142 /*-----------------------------------------------------------------*/
4143 /* genCmp :- greater or less than comparison */
4144 /*-----------------------------------------------------------------*/
4146 genCmp (operand * left, operand * right,
4147 iCode * ic, iCode * ifx, int sign)
4149 int size, offset = 0;
4150 unsigned long lit = 0L;
4153 D (emitcode (";", "genCmp");
4156 result = IC_RESULT (ic);
4158 /* if left & right are bit variables */
4159 if (AOP_TYPE (left) == AOP_CRY &&
4160 AOP_TYPE (right) == AOP_CRY)
4162 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4163 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4167 /* subtract right from left if at the
4168 end the carry flag is set then we know that
4169 left is greater than right */
4170 size = max (AOP_SIZE (left), AOP_SIZE (right));
4172 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4173 if ((size == 1) && !sign &&
4174 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4176 symbol *lbl = newiTempLabel (NULL);
4177 emitcode ("cjne", "%s,%s,%05d$",
4178 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4179 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4181 emitcode ("", "%05d$:", lbl->key + 100);
4185 if (AOP_TYPE (right) == AOP_LIT)
4187 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4188 /* optimize if(x < 0) or if(x >= 0) */
4197 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4199 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4200 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4202 aopOp (result, ic, FALSE, FALSE);
4204 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4206 freeAsmop (result, NULL, ic, TRUE);
4207 genIfxJump (ifx, "acc.7");
4212 emitcode ("rlc", "a");
4214 goto release_freedLR;
4222 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4223 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4224 emitcode (";", "genCmp #2");
4225 if (sign && (size == 0))
4227 emitcode (";", "genCmp #3");
4228 emitcode ("xrl", "a,#0x80");
4229 if (AOP_TYPE (right) == AOP_LIT)
4231 unsigned long lit = (unsigned long)
4232 floatFromVal (AOP (right)->aopu.aop_lit);
4233 emitcode (";", "genCmp #3.1");
4234 emitcode ("subb", "a,#0x%02x",
4235 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4239 emitcode (";", "genCmp #3.2");
4240 if (AOP_NEEDSACC (right))
4242 emitcode ("push", "acc");
4244 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4245 FALSE, FALSE, FALSE));
4246 emitcode ("xrl", "b,#0x80");
4247 if (AOP_NEEDSACC (right))
4249 emitcode ("pop", "acc");
4251 emitcode ("subb", "a,b");
4258 emitcode (";", "genCmp #4");
4259 if (AOP_NEEDSACC (right))
4262 emitcode (";", "genCmp #4.1");
4263 emitcode ("xch", "a, b");
4264 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4265 emitcode ("xch", "a, b");
4270 emitcode (";", "genCmp #4.2");
4271 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4274 emitcode ("subb", "a,%s", s);
4281 /* Don't need the left & right operands any more; do need the result. */
4282 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4283 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4285 aopOp (result, ic, FALSE, FALSE);
4289 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4295 /* if the result is used in the next
4296 ifx conditional branch then generate
4297 code a little differently */
4300 genIfxJump (ifx, "c");
4306 /* leave the result in acc */
4308 freeAsmop (result, NULL, ic, TRUE);
4311 /*-----------------------------------------------------------------*/
4312 /* genCmpGt :- greater than comparison */
4313 /*-----------------------------------------------------------------*/
4315 genCmpGt (iCode * ic, iCode * ifx)
4317 operand *left, *right;
4318 sym_link *letype, *retype;
4321 D (emitcode (";", "genCmpGt ");
4324 left = IC_LEFT (ic);
4325 right = IC_RIGHT (ic);
4327 letype = getSpec (operandType (left));
4328 retype = getSpec (operandType (right));
4329 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4331 /* assign the left & right amsops */
4334 genCmp (right, left, ic, ifx, sign);
4337 /*-----------------------------------------------------------------*/
4338 /* genCmpLt - less than comparisons */
4339 /*-----------------------------------------------------------------*/
4341 genCmpLt (iCode * ic, iCode * ifx)
4343 operand *left, *right;
4344 sym_link *letype, *retype;
4347 D (emitcode (";", "genCmpLt ");
4350 left = IC_LEFT (ic);
4351 right = IC_RIGHT (ic);
4353 letype = getSpec (operandType (left));
4354 retype = getSpec (operandType (right));
4355 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4357 /* assign the left & right amsops */
4360 genCmp (left, right, ic, ifx, sign);
4363 /*-----------------------------------------------------------------*/
4364 /* gencjneshort - compare and jump if not equal */
4365 /*-----------------------------------------------------------------*/
4367 gencjneshort (operand * left, operand * right, symbol * lbl)
4369 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4371 unsigned long lit = 0L;
4373 D (emitcode (";", "gencjneshort");
4376 /* if the left side is a literal or
4377 if the right is in a pointer register and left
4379 if ((AOP_TYPE (left) == AOP_LIT) ||
4380 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4387 if (AOP_TYPE (right) == AOP_LIT)
4388 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4390 if (opIsGptr (left) || opIsGptr (right))
4392 /* We are comparing a generic pointer to something.
4393 * Exclude the generic type byte from the comparison.
4396 D (emitcode (";", "cjneshort: generic ptr special case.");
4401 /* if the right side is a literal then anything goes */
4402 if (AOP_TYPE (right) == AOP_LIT &&
4403 AOP_TYPE (left) != AOP_DIR)
4407 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4409 emitcode ("cjne", "a,%s,%05d$",
4410 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4416 /* if the right side is in a register or in direct space or
4417 if the left is a pointer register & right is not */
4418 else if (AOP_TYPE (right) == AOP_REG ||
4419 AOP_TYPE (right) == AOP_DIR ||
4420 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4421 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4425 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4426 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4427 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4428 emitcode ("jnz", "%05d$", lbl->key + 100);
4430 emitcode ("cjne", "a,%s,%05d$",
4431 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4438 /* right is a pointer reg need both a & b */
4441 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4442 if (strcmp (l, "b"))
4443 emitcode ("mov", "b,%s", l);
4444 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4445 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4451 /*-----------------------------------------------------------------*/
4452 /* gencjne - compare and jump if not equal */
4453 /*-----------------------------------------------------------------*/
4455 gencjne (operand * left, operand * right, symbol * lbl)
4457 symbol *tlbl = newiTempLabel (NULL);
4459 D (emitcode (";", "gencjne");
4462 gencjneshort (left, right, lbl);
4464 emitcode ("mov", "a,%s", one);
4465 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4466 emitcode ("", "%05d$:", lbl->key + 100);
4467 emitcode ("clr", "a");
4468 emitcode ("", "%05d$:", tlbl->key + 100);
4471 /*-----------------------------------------------------------------*/
4472 /* genCmpEq - generates code for equal to */
4473 /*-----------------------------------------------------------------*/
4475 genCmpEq (iCode * ic, iCode * ifx)
4477 operand *left, *right, *result;
4479 D (emitcode (";", "genCmpEq ");
4483 AOP_SET_LOCALS (ic);
4485 /* if literal, literal on the right or
4486 if the right is in a pointer register and left
4488 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4489 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4491 operand *t = IC_RIGHT (ic);
4492 IC_RIGHT (ic) = IC_LEFT (ic);
4496 if (ifx && /* !AOP_SIZE(result) */
4497 OP_SYMBOL (result) &&
4498 OP_SYMBOL (result)->regType == REG_CND)
4501 /* if they are both bit variables */
4502 if (AOP_TYPE (left) == AOP_CRY &&
4503 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4505 if (AOP_TYPE (right) == AOP_LIT)
4507 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4510 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4511 emitcode ("cpl", "c");
4515 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4519 emitcode ("clr", "c");
4521 /* AOP_TYPE(right) == AOP_CRY */
4525 symbol *lbl = newiTempLabel (NULL);
4526 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4527 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4528 emitcode ("cpl", "c");
4529 emitcode ("", "%05d$:", (lbl->key + 100));
4531 /* if true label then we jump if condition
4533 tlbl = newiTempLabel (NULL);
4536 emitcode ("jnc", "%05d$", tlbl->key + 100);
4537 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4541 emitcode ("jc", "%05d$", tlbl->key + 100);
4542 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4544 emitcode ("", "%05d$:", tlbl->key + 100);
4548 tlbl = newiTempLabel (NULL);
4549 gencjneshort (left, right, tlbl);
4552 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4553 emitcode ("", "%05d$:", tlbl->key + 100);
4557 symbol *lbl = newiTempLabel (NULL);
4558 emitcode ("sjmp", "%05d$", lbl->key + 100);
4559 emitcode ("", "%05d$:", tlbl->key + 100);
4560 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4561 emitcode ("", "%05d$:", lbl->key + 100);
4564 /* mark the icode as generated */
4567 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4568 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4572 /* if they are both bit variables */
4573 if (AOP_TYPE (left) == AOP_CRY &&
4574 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4576 if (AOP_TYPE (right) == AOP_LIT)
4578 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4581 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4582 emitcode ("cpl", "c");
4586 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4590 emitcode ("clr", "c");
4592 /* AOP_TYPE(right) == AOP_CRY */
4596 symbol *lbl = newiTempLabel (NULL);
4597 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4598 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4599 emitcode ("cpl", "c");
4600 emitcode ("", "%05d$:", (lbl->key + 100));
4603 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4606 aopOp (result, ic, TRUE, FALSE);
4609 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4616 genIfxJump (ifx, "c");
4619 /* if the result is used in an arithmetic operation
4620 then put the result in place */
4625 gencjne (left, right, newiTempLabel (NULL));
4627 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4628 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4630 aopOp (result, ic, TRUE, FALSE);
4632 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4634 aopPut (AOP (result), "a", 0);
4639 genIfxJump (ifx, "a");
4642 /* if the result is used in an arithmetic operation
4643 then put the result in place */
4644 if (AOP_TYPE (result) != AOP_CRY)
4646 /* leave the result in acc */
4650 freeAsmop (result, NULL, ic, TRUE);
4653 /*-----------------------------------------------------------------*/
4654 /* ifxForOp - returns the icode containing the ifx for operand */
4655 /*-----------------------------------------------------------------*/
4657 ifxForOp (operand * op, iCode * ic)
4659 /* if true symbol then needs to be assigned */
4660 if (IS_TRUE_SYMOP (op))
4663 /* if this has register type condition and
4664 the next instruction is ifx with the same operand
4665 and live to of the operand is upto the ifx only then */
4667 ic->next->op == IFX &&
4668 IC_COND (ic->next)->key == op->key &&
4669 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4674 /*-----------------------------------------------------------------*/
4675 /* genAndOp - for && operation */
4676 /*-----------------------------------------------------------------*/
4678 genAndOp (iCode * ic)
4680 operand *left, *right, *result;
4683 D (emitcode (";", "genAndOp ");
4686 /* note here that && operations that are in an
4687 if statement are taken away by backPatchLabels
4688 only those used in arthmetic operations remain */
4690 AOP_SET_LOCALS (ic);
4692 /* if both are bit variables */
4693 if (AOP_TYPE (left) == AOP_CRY &&
4694 AOP_TYPE (right) == AOP_CRY)
4696 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4697 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4702 tlbl = newiTempLabel (NULL);
4704 emitcode ("jz", "%05d$", tlbl->key + 100);
4706 emitcode ("", "%05d$:", tlbl->key + 100);
4710 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4711 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4712 freeAsmop (result, NULL, ic, TRUE);
4716 /*-----------------------------------------------------------------*/
4717 /* genOrOp - for || operation */
4718 /*-----------------------------------------------------------------*/
4720 genOrOp (iCode * ic)
4722 operand *left, *right, *result;
4725 D (emitcode (";", "genOrOp ");
4728 /* note here that || operations that are in an
4729 if statement are taken away by backPatchLabels
4730 only those used in arthmetic operations remain */
4732 AOP_SET_LOCALS (ic);
4734 /* if both are bit variables */
4735 if (AOP_TYPE (left) == AOP_CRY &&
4736 AOP_TYPE (right) == AOP_CRY)
4738 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4739 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4744 tlbl = newiTempLabel (NULL);
4746 emitcode ("jnz", "%05d$", tlbl->key + 100);
4748 emitcode ("", "%05d$:", tlbl->key + 100);
4752 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4753 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4754 freeAsmop (result, NULL, ic, TRUE);
4757 /*-----------------------------------------------------------------*/
4758 /* isLiteralBit - test if lit == 2^n */
4759 /*-----------------------------------------------------------------*/
4761 isLiteralBit (unsigned long lit)
4763 unsigned long pw[32] =
4764 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4765 0x100L, 0x200L, 0x400L, 0x800L,
4766 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4767 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4768 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4769 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4770 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4773 for (idx = 0; idx < 32; idx++)
4779 /*-----------------------------------------------------------------*/
4780 /* continueIfTrue - */
4781 /*-----------------------------------------------------------------*/
4783 continueIfTrue (iCode * ic)
4786 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4790 /*-----------------------------------------------------------------*/
4792 /*-----------------------------------------------------------------*/
4794 jumpIfTrue (iCode * ic)
4797 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4801 /*-----------------------------------------------------------------*/
4802 /* jmpTrueOrFalse - */
4803 /*-----------------------------------------------------------------*/
4805 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4807 // ugly but optimized by peephole
4810 symbol *nlbl = newiTempLabel (NULL);
4811 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4812 emitcode ("", "%05d$:", tlbl->key + 100);
4813 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4814 emitcode ("", "%05d$:", nlbl->key + 100);
4818 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4819 emitcode ("", "%05d$:", tlbl->key + 100);
4824 /*-----------------------------------------------------------------*/
4825 /* genAnd - code for and */
4826 /*-----------------------------------------------------------------*/
4828 genAnd (iCode * ic, iCode * ifx)
4830 operand *left, *right, *result;
4831 int size, offset = 0;
4832 unsigned long lit = 0L;
4836 D (emitcode (";", "genAnd ");
4840 AOP_SET_LOCALS (ic);
4843 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4845 AOP_TYPE (left), AOP_TYPE (right));
4846 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4848 AOP_SIZE (left), AOP_SIZE (right));
4851 /* if left is a literal & right is not then exchange them */
4852 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4853 AOP_NEEDSACC (left))
4855 operand *tmp = right;
4860 /* if result = right then exchange them */
4861 if (sameRegs (AOP (result), AOP (right)))
4863 operand *tmp = right;
4868 /* if right is bit then exchange them */
4869 if (AOP_TYPE (right) == AOP_CRY &&
4870 AOP_TYPE (left) != AOP_CRY)
4872 operand *tmp = right;
4876 if (AOP_TYPE (right) == AOP_LIT)
4877 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4879 size = AOP_SIZE (result);
4882 // result = bit & yy;
4883 if (AOP_TYPE (left) == AOP_CRY)
4885 // c = bit & literal;
4886 if (AOP_TYPE (right) == AOP_LIT)
4890 if (size && sameRegs (AOP (result), AOP (left)))
4893 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4898 if (size && (AOP_TYPE (result) == AOP_CRY))
4900 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4903 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4908 emitcode ("clr", "c");
4913 if (AOP_TYPE (right) == AOP_CRY)
4916 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4917 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4922 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4924 emitcode ("rrc", "a");
4925 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4933 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4934 genIfxJump (ifx, "c");
4938 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4939 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4940 if ((AOP_TYPE (right) == AOP_LIT) &&
4941 (AOP_TYPE (result) == AOP_CRY) &&
4942 (AOP_TYPE (left) != AOP_CRY))
4944 int posbit = isLiteralBit (lit);
4949 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4952 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4958 sprintf (buffer, "acc.%d", posbit & 0x07);
4959 genIfxJump (ifx, buffer);
4966 symbol *tlbl = newiTempLabel (NULL);
4967 int sizel = AOP_SIZE (left);
4969 emitcode ("setb", "c");
4972 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4974 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4976 if ((posbit = isLiteralBit (bytelit)) != 0)
4977 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4980 if (bytelit != 0x0FFL)
4981 emitcode ("anl", "a,%s",
4982 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4983 emitcode ("jnz", "%05d$", tlbl->key + 100);
4988 // bit = left & literal
4991 emitcode ("clr", "c");
4992 emitcode ("", "%05d$:", tlbl->key + 100);
4994 // if(left & literal)
4998 jmpTrueOrFalse (ifx, tlbl);
5006 /* if left is same as result */
5007 if (sameRegs (AOP (result), AOP (left)))
5009 for (; size--; offset++)
5011 if (AOP_TYPE (right) == AOP_LIT)
5013 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5015 else if (bytelit == 0)
5016 aopPut (AOP (result), zero, offset);
5017 else if (IS_AOP_PREG (result))
5019 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5020 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5021 aopPut (AOP (result), "a", offset);
5024 emitcode ("anl", "%s,%s",
5025 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5026 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5030 if (AOP_TYPE (left) == AOP_ACC)
5031 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5034 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5035 if (IS_AOP_PREG (result))
5037 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5038 aopPut (AOP (result), "a", offset);
5042 emitcode ("anl", "%s,a",
5043 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5050 // left & result in different registers
5051 if (AOP_TYPE (result) == AOP_CRY)
5054 // if(size), result in bit
5055 // if(!size && ifx), conditional oper: if(left & right)
5056 symbol *tlbl = newiTempLabel (NULL);
5057 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5059 emitcode ("setb", "c");
5062 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5063 emitcode ("anl", "a,%s",
5064 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5065 emitcode ("jnz", "%05d$", tlbl->key + 100);
5071 emitcode ("", "%05d$:", tlbl->key + 100);
5075 jmpTrueOrFalse (ifx, tlbl);
5079 for (; (size--); offset++)
5082 // result = left & right
5083 if (AOP_TYPE (right) == AOP_LIT)
5085 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5087 aopPut (AOP (result),
5088 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5092 else if (bytelit == 0)
5094 aopPut (AOP (result), zero, offset);
5097 D (emitcode (";", "better literal AND.");
5099 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5100 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5101 FALSE, FALSE, FALSE));
5106 // faster than result <- left, anl result,right
5107 // and better if result is SFR
5108 if (AOP_TYPE (left) == AOP_ACC)
5110 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5111 FALSE, FALSE, FALSE));
5115 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5116 emitcode ("anl", "a,%s",
5117 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5120 aopPut (AOP (result), "a", offset);
5126 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5127 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128 freeAsmop (result, NULL, ic, TRUE);
5131 /*-----------------------------------------------------------------*/
5132 /* genOr - code for or */
5133 /*-----------------------------------------------------------------*/
5135 genOr (iCode * ic, iCode * ifx)
5137 operand *left, *right, *result;
5138 int size, offset = 0;
5139 unsigned long lit = 0L;
5141 D (emitcode (";", "genOr ");
5145 AOP_SET_LOCALS (ic);
5148 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5150 AOP_TYPE (left), AOP_TYPE (right));
5151 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5153 AOP_SIZE (left), AOP_SIZE (right));
5156 /* if left is a literal & right is not then exchange them */
5157 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5158 AOP_NEEDSACC (left))
5160 operand *tmp = right;
5165 /* if result = right then exchange them */
5166 if (sameRegs (AOP (result), AOP (right)))
5168 operand *tmp = right;
5173 /* if right is bit then exchange them */
5174 if (AOP_TYPE (right) == AOP_CRY &&
5175 AOP_TYPE (left) != AOP_CRY)
5177 operand *tmp = right;
5181 if (AOP_TYPE (right) == AOP_LIT)
5182 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5184 size = AOP_SIZE (result);
5188 if (AOP_TYPE (left) == AOP_CRY)
5190 if (AOP_TYPE (right) == AOP_LIT)
5192 // c = bit & literal;
5195 // lit != 0 => result = 1
5196 if (AOP_TYPE (result) == AOP_CRY)
5199 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5201 continueIfTrue (ifx);
5204 emitcode ("setb", "c");
5208 // lit == 0 => result = left
5209 if (size && sameRegs (AOP (result), AOP (left)))
5211 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5216 if (AOP_TYPE (right) == AOP_CRY)
5219 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5220 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5225 symbol *tlbl = newiTempLabel (NULL);
5226 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5227 emitcode ("setb", "c");
5228 emitcode ("jb", "%s,%05d$",
5229 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5231 emitcode ("jnz", "%05d$", tlbl->key + 100);
5232 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5234 jmpTrueOrFalse (ifx, tlbl);
5240 emitcode ("", "%05d$:", tlbl->key + 100);
5249 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5250 genIfxJump (ifx, "c");
5254 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5255 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5256 if ((AOP_TYPE (right) == AOP_LIT) &&
5257 (AOP_TYPE (result) == AOP_CRY) &&
5258 (AOP_TYPE (left) != AOP_CRY))
5264 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5266 continueIfTrue (ifx);
5271 // lit = 0, result = boolean(left)
5273 emitcode ("setb", "c");
5277 symbol *tlbl = newiTempLabel (NULL);
5278 emitcode ("jnz", "%05d$", tlbl->key + 100);
5280 emitcode ("", "%05d$:", tlbl->key + 100);
5284 genIfxJump (ifx, "a");
5292 /* if left is same as result */
5293 if (sameRegs (AOP (result), AOP (left)))
5295 for (; size--; offset++)
5297 if (AOP_TYPE (right) == AOP_LIT)
5299 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5305 if (IS_AOP_PREG (left))
5307 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5308 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5309 aopPut (AOP (result), "a", offset);
5313 emitcode ("orl", "%s,%s",
5314 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5315 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5321 if (AOP_TYPE (left) == AOP_ACC)
5323 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5327 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5328 if (IS_AOP_PREG (left))
5330 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5331 aopPut (AOP (result), "a", offset);
5335 emitcode ("orl", "%s,a",
5336 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5344 // left & result in different registers
5345 if (AOP_TYPE (result) == AOP_CRY)
5348 // if(size), result in bit
5349 // if(!size && ifx), conditional oper: if(left | right)
5350 symbol *tlbl = newiTempLabel (NULL);
5351 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5353 emitcode ("setb", "c");
5356 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5357 emitcode ("orl", "a,%s",
5358 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5359 emitcode ("jnz", "%05d$", tlbl->key + 100);
5365 emitcode ("", "%05d$:", tlbl->key + 100);
5369 jmpTrueOrFalse (ifx, tlbl);
5373 for (; (size--); offset++)
5376 // result = left & right
5377 if (AOP_TYPE (right) == AOP_LIT)
5379 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5381 aopPut (AOP (result),
5382 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5386 D (emitcode (";", "better literal OR.");
5388 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5389 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5390 FALSE, FALSE, FALSE));
5395 // faster than result <- left, anl result,right
5396 // and better if result is SFR
5397 if (AOP_TYPE (left) == AOP_ACC)
5399 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5400 FALSE, FALSE, FALSE));
5404 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5405 emitcode ("orl", "a,%s",
5406 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5409 aopPut (AOP (result), "a", offset);
5415 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5416 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417 freeAsmop (result, NULL, ic, TRUE);
5420 /*-----------------------------------------------------------------*/
5421 /* genXor - code for xclusive or */
5422 /*-----------------------------------------------------------------*/
5424 genXor (iCode * ic, iCode * ifx)
5426 operand *left, *right, *result;
5427 int size, offset = 0;
5428 unsigned long lit = 0L;
5430 D (emitcode (";", "genXor ");
5434 AOP_SET_LOCALS (ic);
5437 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5439 AOP_TYPE (left), AOP_TYPE (right));
5440 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5442 AOP_SIZE (left), AOP_SIZE (right));
5445 /* if left is a literal & right is not ||
5446 if left needs acc & right does not */
5447 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5448 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5450 operand *tmp = right;
5455 /* if result = right then exchange them */
5456 if (sameRegs (AOP (result), AOP (right)))
5458 operand *tmp = right;
5463 /* if right is bit then exchange them */
5464 if (AOP_TYPE (right) == AOP_CRY &&
5465 AOP_TYPE (left) != AOP_CRY)
5467 operand *tmp = right;
5471 if (AOP_TYPE (right) == AOP_LIT)
5472 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5474 size = AOP_SIZE (result);
5478 if (AOP_TYPE (left) == AOP_CRY)
5480 if (AOP_TYPE (right) == AOP_LIT)
5482 // c = bit & literal;
5485 // lit>>1 != 0 => result = 1
5486 if (AOP_TYPE (result) == AOP_CRY)
5489 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5491 continueIfTrue (ifx);
5494 emitcode ("setb", "c");
5501 // lit == 0, result = left
5502 if (size && sameRegs (AOP (result), AOP (left)))
5504 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5508 // lit == 1, result = not(left)
5509 if (size && sameRegs (AOP (result), AOP (left)))
5511 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5516 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5517 emitcode ("cpl", "c");
5526 symbol *tlbl = newiTempLabel (NULL);
5527 if (AOP_TYPE (right) == AOP_CRY)
5530 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5534 int sizer = AOP_SIZE (right);
5536 // if val>>1 != 0, result = 1
5537 emitcode ("setb", "c");
5540 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5542 // test the msb of the lsb
5543 emitcode ("anl", "a,#0xfe");
5544 emitcode ("jnz", "%05d$", tlbl->key + 100);
5548 emitcode ("rrc", "a");
5550 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5551 emitcode ("cpl", "c");
5552 emitcode ("", "%05d$:", (tlbl->key + 100));
5559 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5560 genIfxJump (ifx, "c");
5564 if (sameRegs (AOP (result), AOP (left)))
5566 /* if left is same as result */
5567 for (; size--; offset++)
5569 if (AOP_TYPE (right) == AOP_LIT)
5571 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5573 else if (IS_AOP_PREG (left))
5575 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5576 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5577 aopPut (AOP (result), "a", offset);
5580 emitcode ("xrl", "%s,%s",
5581 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5582 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5586 if (AOP_TYPE (left) == AOP_ACC)
5587 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5590 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5591 if (IS_AOP_PREG (left))
5593 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5594 aopPut (AOP (result), "a", offset);
5597 emitcode ("xrl", "%s,a",
5598 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5605 // left & result in different registers
5606 if (AOP_TYPE (result) == AOP_CRY)
5609 // if(size), result in bit
5610 // if(!size && ifx), conditional oper: if(left ^ right)
5611 symbol *tlbl = newiTempLabel (NULL);
5612 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5614 emitcode ("setb", "c");
5617 if ((AOP_TYPE (right) == AOP_LIT) &&
5618 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5620 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5624 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5625 emitcode ("xrl", "a,%s",
5626 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5628 emitcode ("jnz", "%05d$", tlbl->key + 100);
5634 emitcode ("", "%05d$:", tlbl->key + 100);
5638 jmpTrueOrFalse (ifx, tlbl);
5641 for (; (size--); offset++)
5644 // result = left & right
5645 if (AOP_TYPE (right) == AOP_LIT)
5647 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5649 aopPut (AOP (result),
5650 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5654 D (emitcode (";", "better literal XOR.");
5656 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5657 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5658 FALSE, FALSE, FALSE));
5662 // faster than result <- left, anl result,right
5663 // and better if result is SFR
5664 if (AOP_TYPE (left) == AOP_ACC)
5666 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5667 FALSE, FALSE, FALSE));
5671 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5672 emitcode ("xrl", "a,%s",
5673 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5676 aopPut (AOP (result), "a", offset);
5681 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5682 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5683 freeAsmop (result, NULL, ic, TRUE);
5686 /*-----------------------------------------------------------------*/
5687 /* genInline - write the inline code out */
5688 /*-----------------------------------------------------------------*/
5690 genInline (iCode * ic)
5692 char buffer[MAX_INLINEASM];
5696 D (emitcode (";", "genInline ");
5699 _G.inLine += (!options.asmpeep);
5700 strcpy (buffer, IC_INLINE (ic));
5702 /* emit each line as a code */
5727 /* emitcode("",buffer); */
5728 _G.inLine -= (!options.asmpeep);
5731 /*-----------------------------------------------------------------*/
5732 /* genRRC - rotate right with carry */
5733 /*-----------------------------------------------------------------*/
5737 operand *left, *result;
5738 int size, offset = 0;
5741 D (emitcode (";", "genRRC ");
5744 /* rotate right with carry */
5745 left = IC_LEFT (ic);
5746 result = IC_RESULT (ic);
5747 aopOp (left, ic, FALSE, FALSE);
5748 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5750 /* move it to the result */
5751 size = AOP_SIZE (result);
5755 _startLazyDPSEvaluation ();
5758 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5760 emitcode ("rrc", "a");
5761 if (AOP_SIZE (result) > 1)
5762 aopPut (AOP (result), "a", offset--);
5764 _endLazyDPSEvaluation ();
5766 /* now we need to put the carry into the
5767 highest order byte of the result */
5768 if (AOP_SIZE (result) > 1)
5770 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5773 emitcode ("mov", "acc.7,c");
5774 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5775 freeAsmop (left, NULL, ic, TRUE);
5776 freeAsmop (result, NULL, ic, TRUE);
5779 /*-----------------------------------------------------------------*/
5780 /* genRLC - generate code for rotate left with carry */
5781 /*-----------------------------------------------------------------*/
5785 operand *left, *result;
5786 int size, offset = 0;
5789 D (emitcode (";", "genRLC ");
5792 /* rotate right with carry */
5793 left = IC_LEFT (ic);
5794 result = IC_RESULT (ic);
5795 aopOp (left, ic, FALSE, FALSE);
5796 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5798 /* move it to the result */
5799 size = AOP_SIZE (result);
5803 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5805 emitcode ("add", "a,acc");
5806 if (AOP_SIZE (result) > 1)
5808 aopPut (AOP (result), "a", offset++);
5811 _startLazyDPSEvaluation ();
5814 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5816 emitcode ("rlc", "a");
5817 if (AOP_SIZE (result) > 1)
5818 aopPut (AOP (result), "a", offset++);
5820 _endLazyDPSEvaluation ();
5822 /* now we need to put the carry into the
5823 highest order byte of the result */
5824 if (AOP_SIZE (result) > 1)
5826 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5829 emitcode ("mov", "acc.0,c");
5830 aopPut (AOP (result), "a", 0);
5831 freeAsmop (left, NULL, ic, TRUE);
5832 freeAsmop (result, NULL, ic, TRUE);
5835 /*-----------------------------------------------------------------*/
5836 /* genGetHbit - generates code get highest order bit */
5837 /*-----------------------------------------------------------------*/
5839 genGetHbit (iCode * ic)
5841 operand *left, *result;
5842 left = IC_LEFT (ic);
5843 result = IC_RESULT (ic);
5844 aopOp (left, ic, FALSE, FALSE);
5845 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5847 D (emitcode (";", "genGetHbit ");
5850 /* get the highest order byte into a */
5851 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5852 if (AOP_TYPE (result) == AOP_CRY)
5854 emitcode ("rlc", "a");
5859 emitcode ("rl", "a");
5860 emitcode ("anl", "a,#0x01");
5865 freeAsmop (left, NULL, ic, TRUE);
5866 freeAsmop (result, NULL, ic, TRUE);
5869 /*-----------------------------------------------------------------*/
5870 /* AccRol - rotate left accumulator by known count */
5871 /*-----------------------------------------------------------------*/
5873 AccRol (int shCount)
5875 shCount &= 0x0007; // shCount : 0..7
5882 emitcode ("rl", "a");
5885 emitcode ("rl", "a");
5886 emitcode ("rl", "a");
5889 emitcode ("swap", "a");
5890 emitcode ("rr", "a");
5893 emitcode ("swap", "a");
5896 emitcode ("swap", "a");
5897 emitcode ("rl", "a");
5900 emitcode ("rr", "a");
5901 emitcode ("rr", "a");
5904 emitcode ("rr", "a");
5909 /*-----------------------------------------------------------------*/
5910 /* AccLsh - left shift accumulator by known count */
5911 /*-----------------------------------------------------------------*/
5913 AccLsh (int shCount)
5918 emitcode ("add", "a,acc");
5919 else if (shCount == 2)
5921 emitcode ("add", "a,acc");
5922 emitcode ("add", "a,acc");
5926 /* rotate left accumulator */
5928 /* and kill the lower order bits */
5929 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5934 /*-----------------------------------------------------------------*/
5935 /* AccRsh - right shift accumulator by known count */
5936 /*-----------------------------------------------------------------*/
5938 AccRsh (int shCount)
5945 emitcode ("rrc", "a");
5949 /* rotate right accumulator */
5950 AccRol (8 - shCount);
5951 /* and kill the higher order bits */
5952 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5959 /*-----------------------------------------------------------------*/
5960 /* AccSRsh - signed right shift accumulator by known count */
5961 /*-----------------------------------------------------------------*/
5963 AccSRsh (int shCount)
5970 emitcode ("mov", "c,acc.7");
5971 emitcode ("rrc", "a");
5973 else if (shCount == 2)
5975 emitcode ("mov", "c,acc.7");
5976 emitcode ("rrc", "a");
5977 emitcode ("mov", "c,acc.7");
5978 emitcode ("rrc", "a");
5982 tlbl = newiTempLabel (NULL);
5983 /* rotate right accumulator */
5984 AccRol (8 - shCount);
5985 /* and kill the higher order bits */
5986 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5987 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5988 emitcode ("orl", "a,#0x%02x",
5989 (unsigned char) ~SRMask[shCount]);
5990 emitcode ("", "%05d$:", tlbl->key + 100);
5998 /*-----------------------------------------------------------------*/
5999 /* shiftR1Left2Result - shift right one byte from left to result */
6000 /*-----------------------------------------------------------------*/
6002 shiftR1Left2Result (operand * left, int offl,
6003 operand * result, int offr,
6004 int shCount, int sign)
6006 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6007 /* shift right accumulator */
6012 aopPut (AOP (result), "a", offr);
6018 /*-----------------------------------------------------------------*/
6019 /* shiftL1Left2Result - shift left one byte from left to result */
6020 /*-----------------------------------------------------------------*/
6022 shiftL1Left2Result (operand * left, int offl,
6023 operand * result, int offr, int shCount)
6026 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6028 /* shift left accumulator */
6030 aopPut (AOP (result), "a", offr);
6036 /*-----------------------------------------------------------------*/
6037 /* movLeft2Result - move byte from left to result */
6038 /*-----------------------------------------------------------------*/
6040 movLeft2Result (operand * left, int offl,
6041 operand * result, int offr, int sign)
6044 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6046 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6048 if (*l == '@' && (IS_AOP_PREG (result)))
6050 emitcode ("mov", "a,%s", l);
6051 aopPut (AOP (result), "a", offr);
6056 aopPut (AOP (result), l, offr);
6059 /* MSB sign in acc.7 ! */
6060 if (getDataSize (left) == offl + 1)
6062 emitcode ("mov", "a,%s", l);
6063 aopPut (AOP (result), "a", offr);
6073 /*-----------------------------------------------------------------*/
6074 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6075 /*-----------------------------------------------------------------*/
6079 emitcode ("rrc", "a");
6080 emitcode ("xch", "a,%s", x);
6081 emitcode ("rrc", "a");
6082 emitcode ("xch", "a,%s", x);
6088 /*-----------------------------------------------------------------*/
6089 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6090 /*-----------------------------------------------------------------*/
6094 emitcode ("xch", "a,%s", x);
6095 emitcode ("rlc", "a");
6096 emitcode ("xch", "a,%s", x);
6097 emitcode ("rlc", "a");
6103 /*-----------------------------------------------------------------*/
6104 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6105 /*-----------------------------------------------------------------*/
6109 emitcode ("xch", "a,%s", x);
6110 emitcode ("add", "a,acc");
6111 emitcode ("xch", "a,%s", x);
6112 emitcode ("rlc", "a");
6118 /*-----------------------------------------------------------------*/
6119 /* AccAXLsh - left shift a:x by known count (0..7) */
6120 /*-----------------------------------------------------------------*/
6122 AccAXLsh (char *x, int shCount)
6137 case 5: // AAAAABBB:CCCCCDDD
6139 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6141 emitcode ("anl", "a,#0x%02x",
6142 SLMask[shCount]); // BBB00000:CCCCCDDD
6144 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6146 AccRol (shCount); // DDDCCCCC:BBB00000
6148 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6150 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6152 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6154 emitcode ("anl", "a,#0x%02x",
6155 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6157 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6159 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6162 case 6: // AAAAAABB:CCCCCCDD
6164 emitcode ("anl", "a,#0x%02x",
6165 SRMask[shCount]); // 000000BB:CCCCCCDD
6167 emitcode ("mov", "c,acc.0"); // c = B
6169 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6171 AccAXRrl1 (x); // BCCCCCCD:D000000B
6173 AccAXRrl1 (x); // BBCCCCCC:DD000000
6176 case 7: // a:x <<= 7
6178 emitcode ("anl", "a,#0x%02x",
6179 SRMask[shCount]); // 0000000B:CCCCCCCD
6181 emitcode ("mov", "c,acc.0"); // c = B
6183 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6185 AccAXRrl1 (x); // BCCCCCCC:D0000000
6196 /*-----------------------------------------------------------------*/
6197 /* AccAXRsh - right shift a:x known count (0..7) */
6198 /*-----------------------------------------------------------------*/
6200 AccAXRsh (char *x, int shCount)
6208 AccAXRrl1 (x); // 0->a:x
6213 AccAXRrl1 (x); // 0->a:x
6216 AccAXRrl1 (x); // 0->a:x
6221 case 5: // AAAAABBB:CCCCCDDD = a:x
6223 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6225 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6227 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6229 emitcode ("anl", "a,#0x%02x",
6230 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6232 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6234 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6236 emitcode ("anl", "a,#0x%02x",
6237 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6239 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6241 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6243 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6246 case 6: // AABBBBBB:CCDDDDDD
6248 emitcode ("mov", "c,acc.7");
6249 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6251 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6253 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6255 emitcode ("anl", "a,#0x%02x",
6256 SRMask[shCount]); // 000000AA:BBBBBBCC
6259 case 7: // ABBBBBBB:CDDDDDDD
6261 emitcode ("mov", "c,acc.7"); // c = A
6263 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6265 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6267 emitcode ("anl", "a,#0x%02x",
6268 SRMask[shCount]); // 0000000A:BBBBBBBC
6279 /*-----------------------------------------------------------------*/
6280 /* AccAXRshS - right shift signed a:x known count (0..7) */
6281 /*-----------------------------------------------------------------*/
6283 AccAXRshS (char *x, int shCount)
6291 emitcode ("mov", "c,acc.7");
6292 AccAXRrl1 (x); // s->a:x
6296 emitcode ("mov", "c,acc.7");
6297 AccAXRrl1 (x); // s->a:x
6299 emitcode ("mov", "c,acc.7");
6300 AccAXRrl1 (x); // s->a:x
6305 case 5: // AAAAABBB:CCCCCDDD = a:x
6307 tlbl = newiTempLabel (NULL);
6308 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6310 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6312 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6314 emitcode ("anl", "a,#0x%02x",
6315 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6317 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6319 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6321 emitcode ("anl", "a,#0x%02x",
6322 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6324 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6326 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6328 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6330 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6331 emitcode ("orl", "a,#0x%02x",
6332 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6334 emitcode ("", "%05d$:", tlbl->key + 100);
6335 break; // SSSSAAAA:BBBCCCCC
6337 case 6: // AABBBBBB:CCDDDDDD
6339 tlbl = newiTempLabel (NULL);
6340 emitcode ("mov", "c,acc.7");
6341 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6343 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6345 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6347 emitcode ("anl", "a,#0x%02x",
6348 SRMask[shCount]); // 000000AA:BBBBBBCC
6350 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6351 emitcode ("orl", "a,#0x%02x",
6352 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6354 emitcode ("", "%05d$:", tlbl->key + 100);
6356 case 7: // ABBBBBBB:CDDDDDDD
6358 tlbl = newiTempLabel (NULL);
6359 emitcode ("mov", "c,acc.7"); // c = A
6361 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6363 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6365 emitcode ("anl", "a,#0x%02x",
6366 SRMask[shCount]); // 0000000A:BBBBBBBC
6368 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6369 emitcode ("orl", "a,#0x%02x",
6370 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6372 emitcode ("", "%05d$:", tlbl->key + 100);
6382 /*-----------------------------------------------------------------*/
6383 /* shiftL2Left2Result - shift left two bytes from left to result */
6384 /*-----------------------------------------------------------------*/
6386 shiftL2Left2Result (operand * left, int offl,
6387 operand * result, int offr, int shCount)
6389 if (sameRegs (AOP (result), AOP (left)) &&
6390 ((offl + MSB16) == offr))
6392 /* don't crash result[offr] */
6393 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6394 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6398 movLeft2Result (left, offl, result, offr, 0);
6399 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6401 /* ax << shCount (x = lsb(result)) */
6402 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6403 aopPut (AOP (result), "a", offr + MSB16);
6409 /*-----------------------------------------------------------------*/
6410 /* shiftR2Left2Result - shift right two bytes from left to result */
6411 /*-----------------------------------------------------------------*/
6413 shiftR2Left2Result (operand * left, int offl,
6414 operand * result, int offr,
6415 int shCount, int sign)
6417 if (sameRegs (AOP (result), AOP (left)) &&
6418 ((offl + MSB16) == offr))
6420 /* don't crash result[offr] */
6421 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6422 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6426 movLeft2Result (left, offl, result, offr, 0);
6427 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6429 /* a:x >> shCount (x = lsb(result)) */
6431 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6433 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6434 if (getDataSize (result) > 1)
6435 aopPut (AOP (result), "a", offr + MSB16);
6441 /*-----------------------------------------------------------------*/
6442 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6443 /*-----------------------------------------------------------------*/
6445 shiftLLeftOrResult (operand * left, int offl,
6446 operand * result, int offr, int shCount)
6448 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6449 /* shift left accumulator */
6451 /* or with result */
6452 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6453 /* back to result */
6454 aopPut (AOP (result), "a", offr);
6460 /*-----------------------------------------------------------------*/
6461 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6462 /*-----------------------------------------------------------------*/
6464 shiftRLeftOrResult (operand * left, int offl,
6465 operand * result, int offr, int shCount)
6467 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6468 /* shift right accumulator */
6470 /* or with result */
6471 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6472 /* back to result */
6473 aopPut (AOP (result), "a", offr);
6479 /*-----------------------------------------------------------------*/
6480 /* genlshOne - left shift a one byte quantity by known count */
6481 /*-----------------------------------------------------------------*/
6483 genlshOne (operand * result, operand * left, int shCount)
6485 D (emitcode (";", "genlshOne ");
6487 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6493 /*-----------------------------------------------------------------*/
6494 /* genlshTwo - left shift two bytes by known amount != 0 */
6495 /*-----------------------------------------------------------------*/
6497 genlshTwo (operand * result, operand * left, int shCount)
6501 D (emitcode (";", "genlshTwo ");
6504 size = getDataSize (result);
6506 /* if shCount >= 8 */
6514 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6516 movLeft2Result (left, LSB, result, MSB16, 0);
6518 aopPut (AOP (result), zero, LSB);
6521 /* 1 <= shCount <= 7 */
6525 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6527 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6534 /*-----------------------------------------------------------------*/
6535 /* shiftLLong - shift left one long from left to result */
6536 /* offl = LSB or MSB16 */
6537 /*-----------------------------------------------------------------*/
6539 shiftLLong (operand * left, operand * result, int offr)
6542 int size = AOP_SIZE (result);
6544 if (size >= LSB + offr)
6546 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6548 emitcode ("add", "a,acc");
6549 if (sameRegs (AOP (left), AOP (result)) &&
6550 size >= MSB16 + offr && offr != LSB)
6551 emitcode ("xch", "a,%s",
6552 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6554 aopPut (AOP (result), "a", LSB + offr);
6557 if (size >= MSB16 + offr)
6559 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6561 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6564 emitcode ("rlc", "a");
6565 if (sameRegs (AOP (left), AOP (result)) &&
6566 size >= MSB24 + offr && offr != LSB)
6567 emitcode ("xch", "a,%s",
6568 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6570 aopPut (AOP (result), "a", MSB16 + offr);
6573 if (size >= MSB24 + offr)
6575 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6577 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6580 emitcode ("rlc", "a");
6581 if (sameRegs (AOP (left), AOP (result)) &&
6582 size >= MSB32 + offr && offr != LSB)
6583 emitcode ("xch", "a,%s",
6584 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6586 aopPut (AOP (result), "a", MSB24 + offr);
6589 if (size > MSB32 + offr)
6591 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6593 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6596 emitcode ("rlc", "a");
6597 aopPut (AOP (result), "a", MSB32 + offr);
6600 aopPut (AOP (result), zero, LSB);
6606 /*-----------------------------------------------------------------*/
6607 /* genlshFour - shift four byte by a known amount != 0 */
6608 /*-----------------------------------------------------------------*/
6610 genlshFour (operand * result, operand * left, int shCount)
6614 D (emitcode (";", "genlshFour ");
6617 size = AOP_SIZE (result);
6619 /* if shifting more that 3 bytes */
6624 /* lowest order of left goes to the highest
6625 order of the destination */
6626 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6628 movLeft2Result (left, LSB, result, MSB32, 0);
6629 aopPut (AOP (result), zero, LSB);
6630 aopPut (AOP (result), zero, MSB16);
6631 aopPut (AOP (result), zero, MSB32);
6635 /* more than two bytes */
6636 else if (shCount >= 16)
6638 /* lower order two bytes goes to higher order two bytes */
6640 /* if some more remaining */
6642 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6645 movLeft2Result (left, MSB16, result, MSB32, 0);
6646 movLeft2Result (left, LSB, result, MSB24, 0);
6648 aopPut (AOP (result), zero, MSB16);
6649 aopPut (AOP (result), zero, LSB);
6653 /* if more than 1 byte */
6654 else if (shCount >= 8)
6656 /* lower order three bytes goes to higher order three bytes */
6661 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6663 movLeft2Result (left, LSB, result, MSB16, 0);
6669 movLeft2Result (left, MSB24, result, MSB32, 0);
6670 movLeft2Result (left, MSB16, result, MSB24, 0);
6671 movLeft2Result (left, LSB, result, MSB16, 0);
6672 aopPut (AOP (result), zero, LSB);
6674 else if (shCount == 1)
6675 shiftLLong (left, result, MSB16);
6678 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6679 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6680 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6681 aopPut (AOP (result), zero, LSB);
6686 /* 1 <= shCount <= 7 */
6687 else if (shCount <= 2)
6689 shiftLLong (left, result, LSB);
6691 shiftLLong (result, result, LSB);
6693 /* 3 <= shCount <= 7, optimize */
6696 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6697 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6698 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6705 /*-----------------------------------------------------------------*/
6706 /* genLeftShiftLiteral - left shifting by known count */
6707 /*-----------------------------------------------------------------*/
6709 genLeftShiftLiteral (operand * left,
6714 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6717 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6720 freeAsmop (right, NULL, ic, TRUE);
6722 aopOp (left, ic, FALSE, FALSE);
6723 aopOp (result, ic, FALSE, TRUE);
6725 size = getSize (operandType (result));
6728 emitcode ("; shift left ", "result %d, left %d", size,
6732 /* I suppose that the left size >= result size */
6737 movLeft2Result (left, size, result, size, 0);
6741 else if (shCount >= (size * 8))
6743 aopPut (AOP (result), zero, size);
6749 genlshOne (result, left, shCount);
6753 case 3: /* bug: this is for generic pointers, I bet. */
6754 genlshTwo (result, left, shCount);
6758 genlshFour (result, left, shCount);
6762 freeAsmop (left, NULL, ic, TRUE);
6763 freeAsmop (result, NULL, ic, TRUE);
6767 /*-----------------------------------------------------------------*/
6768 /* genLeftShift - generates code for left shifting */
6769 /*-----------------------------------------------------------------*/
6771 genLeftShift (iCode * ic)
6773 operand *left, *right, *result;
6776 symbol *tlbl, *tlbl1;
6778 D (emitcode (";", "genLeftShift ");
6781 right = IC_RIGHT (ic);
6782 left = IC_LEFT (ic);
6783 result = IC_RESULT (ic);
6785 aopOp (right, ic, FALSE, FALSE);
6788 /* if the shift count is known then do it
6789 as efficiently as possible */
6790 if (AOP_TYPE (right) == AOP_LIT)
6792 genLeftShiftLiteral (left, right, result, ic);
6797 /* shift count is unknown then we have to form
6798 a loop get the loop count in B : Note: we take
6799 only the lower order byte since shifting
6800 more that 32 bits make no sense anyway, ( the
6801 largest size of an object can be only 32 bits ) */
6803 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6804 emitcode ("inc", "b");
6805 freeAsmop (right, NULL, ic, TRUE);
6806 aopOp (left, ic, FALSE, FALSE);
6807 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6809 /* now move the left to the result if they are not the
6811 if (!sameRegs (AOP (left), AOP (result)) &&
6812 AOP_SIZE (result) > 1)
6815 size = AOP_SIZE (result);
6817 _startLazyDPSEvaluation ();
6820 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6821 if (*l == '@' && (IS_AOP_PREG (result)))
6824 emitcode ("mov", "a,%s", l);
6825 aopPut (AOP (result), "a", offset);
6828 aopPut (AOP (result), l, offset);
6831 _endLazyDPSEvaluation ();
6834 tlbl = newiTempLabel (NULL);
6835 size = AOP_SIZE (result);
6837 tlbl1 = newiTempLabel (NULL);
6839 /* if it is only one byte then */
6842 symbol *tlbl1 = newiTempLabel (NULL);
6844 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6846 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6847 emitcode ("", "%05d$:", tlbl->key + 100);
6848 emitcode ("add", "a,acc");
6849 emitcode ("", "%05d$:", tlbl1->key + 100);
6850 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6851 aopPut (AOP (result), "a", 0);
6855 reAdjustPreg (AOP (result));
6857 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6858 emitcode ("", "%05d$:", tlbl->key + 100);
6859 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6861 emitcode ("add", "a,acc");
6862 aopPut (AOP (result), "a", offset++);
6863 _startLazyDPSEvaluation ();
6866 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6868 emitcode ("rlc", "a");
6869 aopPut (AOP (result), "a", offset++);
6871 _endLazyDPSEvaluation ();
6872 reAdjustPreg (AOP (result));
6874 emitcode ("", "%05d$:", tlbl1->key + 100);
6875 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6877 freeAsmop (left, NULL, ic, TRUE);
6878 freeAsmop (result, NULL, ic, TRUE);
6883 /*-----------------------------------------------------------------*/
6884 /* genrshOne - right shift a one byte quantity by known count */
6885 /*-----------------------------------------------------------------*/
6887 genrshOne (operand * result, operand * left,
6888 int shCount, int sign)
6890 D (emitcode (";", "genrshOne");
6892 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6898 /*-----------------------------------------------------------------*/
6899 /* genrshTwo - right shift two bytes by known amount != 0 */
6900 /*-----------------------------------------------------------------*/
6902 genrshTwo (operand * result, operand * left,
6903 int shCount, int sign)
6905 D (emitcode (";", "genrshTwo");
6908 /* if shCount >= 8 */
6913 shiftR1Left2Result (left, MSB16, result, LSB,
6916 movLeft2Result (left, MSB16, result, LSB, sign);
6917 addSign (result, MSB16, sign);
6920 /* 1 <= shCount <= 7 */
6922 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6928 /*-----------------------------------------------------------------*/
6929 /* shiftRLong - shift right one long from left to result */
6930 /* offl = LSB or MSB16 */
6931 /*-----------------------------------------------------------------*/
6933 shiftRLong (operand * left, int offl,
6934 operand * result, int sign)
6937 emitcode ("clr", "c");
6938 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6940 emitcode ("mov", "c,acc.7");
6941 emitcode ("rrc", "a");
6942 aopPut (AOP (result), "a", MSB32 - offl);
6944 /* add sign of "a" */
6945 addSign (result, MSB32, sign);
6947 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6948 emitcode ("rrc", "a");
6949 aopPut (AOP (result), "a", MSB24 - offl);
6951 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6952 emitcode ("rrc", "a");
6953 aopPut (AOP (result), "a", MSB16 - offl);
6957 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6958 emitcode ("rrc", "a");
6959 aopPut (AOP (result), "a", LSB);
6966 /*-----------------------------------------------------------------*/
6967 /* genrshFour - shift four byte by a known amount != 0 */
6968 /*-----------------------------------------------------------------*/
6970 genrshFour (operand * result, operand * left,
6971 int shCount, int sign)
6973 D (emitcode (";", "genrshFour");
6976 /* if shifting more that 3 bytes */
6981 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6983 movLeft2Result (left, MSB32, result, LSB, sign);
6984 addSign (result, MSB16, sign);
6986 else if (shCount >= 16)
6990 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6993 movLeft2Result (left, MSB24, result, LSB, 0);
6994 movLeft2Result (left, MSB32, result, MSB16, sign);
6996 addSign (result, MSB24, sign);
6998 else if (shCount >= 8)
7002 shiftRLong (left, MSB16, result, sign);
7003 else if (shCount == 0)
7005 movLeft2Result (left, MSB16, result, LSB, 0);
7006 movLeft2Result (left, MSB24, result, MSB16, 0);
7007 movLeft2Result (left, MSB32, result, MSB24, sign);
7008 addSign (result, MSB32, sign);
7012 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7013 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7014 /* the last shift is signed */
7015 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7016 addSign (result, MSB32, sign);
7020 { /* 1 <= shCount <= 7 */
7023 shiftRLong (left, LSB, result, sign);
7025 shiftRLong (result, LSB, result, sign);
7029 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7030 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7031 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7039 /*-----------------------------------------------------------------*/
7040 /* genRightShiftLiteral - right shifting by known count */
7041 /*-----------------------------------------------------------------*/
7043 genRightShiftLiteral (operand * left,
7049 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7052 D (emitcode (";", "genRightShiftLiteral");
7055 freeAsmop (right, NULL, ic, TRUE);
7057 aopOp (left, ic, FALSE, FALSE);
7058 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7061 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7065 size = getDataSize (left);
7066 /* test the LEFT size !!! */
7068 /* I suppose that the left size >= result size */
7071 size = getDataSize (result);
7073 movLeft2Result (left, size, result, size, 0);
7076 else if (shCount >= (size * 8))
7079 /* get sign in acc.7 */
7080 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7081 addSign (result, LSB, sign);
7088 genrshOne (result, left, shCount, sign);
7092 genrshTwo (result, left, shCount, sign);
7096 genrshFour (result, left, shCount, sign);
7102 freeAsmop (left, NULL, ic, TRUE);
7103 freeAsmop (result, NULL, ic, TRUE);
7108 /*-----------------------------------------------------------------*/
7109 /* genSignedRightShift - right shift of signed number */
7110 /*-----------------------------------------------------------------*/
7112 genSignedRightShift (iCode * ic)
7114 operand *right, *left, *result;
7117 symbol *tlbl, *tlbl1;
7119 D (emitcode (";", "genSignedRightShift ");
7122 /* we do it the hard way put the shift count in b
7123 and loop thru preserving the sign */
7125 right = IC_RIGHT (ic);
7126 left = IC_LEFT (ic);
7127 result = IC_RESULT (ic);
7129 aopOp (right, ic, FALSE, FALSE);
7132 if (AOP_TYPE (right) == AOP_LIT)
7134 genRightShiftLiteral (left, right, result, ic, 1);
7138 /* shift count is unknown then we have to form
7139 a loop get the loop count in B : Note: we take
7140 only the lower order byte since shifting
7141 more that 32 bits make no sense anyway, ( the
7142 largest size of an object can be only 32 bits ) */
7144 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7145 emitcode ("inc", "b");
7146 freeAsmop (right, NULL, ic, TRUE);
7147 aopOp (left, ic, FALSE, FALSE);
7148 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7150 /* now move the left to the result if they are not the
7152 if (!sameRegs (AOP (left), AOP (result)) &&
7153 AOP_SIZE (result) > 1)
7156 size = AOP_SIZE (result);
7158 _startLazyDPSEvaluation ();
7161 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7162 if (*l == '@' && IS_AOP_PREG (result))
7165 emitcode ("mov", "a,%s", l);
7166 aopPut (AOP (result), "a", offset);
7169 aopPut (AOP (result), l, offset);
7172 _endLazyDPSEvaluation ();
7175 /* mov the highest order bit to OVR */
7176 tlbl = newiTempLabel (NULL);
7177 tlbl1 = newiTempLabel (NULL);
7179 size = AOP_SIZE (result);
7181 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7182 emitcode ("rlc", "a");
7183 emitcode ("mov", "ov,c");
7184 /* if it is only one byte then */
7187 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7189 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7190 emitcode ("", "%05d$:", tlbl->key + 100);
7191 emitcode ("mov", "c,ov");
7192 emitcode ("rrc", "a");
7193 emitcode ("", "%05d$:", tlbl1->key + 100);
7194 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7195 aopPut (AOP (result), "a", 0);
7199 reAdjustPreg (AOP (result));
7200 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7201 emitcode ("", "%05d$:", tlbl->key + 100);
7202 emitcode ("mov", "c,ov");
7203 _startLazyDPSEvaluation ();
7206 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7208 emitcode ("rrc", "a");
7209 aopPut (AOP (result), "a", offset--);
7211 _endLazyDPSEvaluation ();
7212 reAdjustPreg (AOP (result));
7213 emitcode ("", "%05d$:", tlbl1->key + 100);
7214 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7217 freeAsmop (left, NULL, ic, TRUE);
7218 freeAsmop (result, NULL, ic, TRUE);
7221 /*-----------------------------------------------------------------*/
7222 /* genRightShift - generate code for right shifting */
7223 /*-----------------------------------------------------------------*/
7225 genRightShift (iCode * ic)
7227 operand *right, *left, *result;
7231 symbol *tlbl, *tlbl1;
7233 D (emitcode (";", "genRightShift ");
7236 /* if signed then we do it the hard way preserve the
7237 sign bit moving it inwards */
7238 retype = getSpec (operandType (IC_RESULT (ic)));
7240 if (!SPEC_USIGN (retype))
7242 genSignedRightShift (ic);
7246 /* signed & unsigned types are treated the same : i.e. the
7247 signed is NOT propagated inwards : quoting from the
7248 ANSI - standard : "for E1 >> E2, is equivalent to division
7249 by 2**E2 if unsigned or if it has a non-negative value,
7250 otherwise the result is implementation defined ", MY definition
7251 is that the sign does not get propagated */
7253 right = IC_RIGHT (ic);
7254 left = IC_LEFT (ic);
7255 result = IC_RESULT (ic);
7257 aopOp (right, ic, FALSE, FALSE);
7260 /* if the shift count is known then do it
7261 as efficiently as possible */
7262 if (AOP_TYPE (right) == AOP_LIT)
7264 genRightShiftLiteral (left, right, result, ic, 0);
7269 /* shift count is unknown then we have to form
7270 a loop get the loop count in B : Note: we take
7271 only the lower order byte since shifting
7272 more that 32 bits make no sense anyway, ( the
7273 largest size of an object can be only 32 bits ) */
7275 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7276 emitcode ("inc", "b");
7277 freeAsmop (right, NULL, ic, TRUE);
7278 aopOp (left, ic, FALSE, FALSE);
7279 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7281 /* now move the left to the result if they are not the
7283 if (!sameRegs (AOP (left), AOP (result)) &&
7284 AOP_SIZE (result) > 1)
7287 size = AOP_SIZE (result);
7289 _startLazyDPSEvaluation ();
7292 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7293 if (*l == '@' && IS_AOP_PREG (result))
7296 emitcode ("mov", "a,%s", l);
7297 aopPut (AOP (result), "a", offset);
7300 aopPut (AOP (result), l, offset);
7303 _endLazyDPSEvaluation ();
7306 tlbl = newiTempLabel (NULL);
7307 tlbl1 = newiTempLabel (NULL);
7308 size = AOP_SIZE (result);
7311 /* if it is only one byte then */
7314 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7316 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7317 emitcode ("", "%05d$:", tlbl->key + 100);
7319 emitcode ("rrc", "a");
7320 emitcode ("", "%05d$:", tlbl1->key + 100);
7321 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7322 aopPut (AOP (result), "a", 0);
7326 reAdjustPreg (AOP (result));
7327 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7328 emitcode ("", "%05d$:", tlbl->key + 100);
7330 _startLazyDPSEvaluation ();
7333 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7335 emitcode ("rrc", "a");
7336 aopPut (AOP (result), "a", offset--);
7338 _endLazyDPSEvaluation ();
7339 reAdjustPreg (AOP (result));
7341 emitcode ("", "%05d$:", tlbl1->key + 100);
7342 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7345 freeAsmop (left, NULL, ic, TRUE);
7346 freeAsmop (result, NULL, ic, TRUE);
7349 /*-----------------------------------------------------------------*/
7350 /* genUnpackBits - generates code for unpacking bits */
7351 /*-----------------------------------------------------------------*/
7353 genUnpackBits (operand * result, char *rname, int ptype)
7360 D (emitcode (";", "genUnpackBits ");
7363 etype = getSpec (operandType (result));
7365 /* read the first byte */
7371 emitcode ("mov", "a,@%s", rname);
7375 emitcode ("movx", "a,@%s", rname);
7379 emitcode ("movx", "a,@dptr");
7383 emitcode ("clr", "a");
7384 emitcode ("movc", "a", "@a+dptr");
7388 emitcode ("lcall", "__gptrget");
7392 /* if we have bitdisplacement then it fits */
7393 /* into this byte completely or if length is */
7394 /* less than a byte */
7395 if ((shCnt = SPEC_BSTR (etype)) ||
7396 (SPEC_BLEN (etype) <= 8))
7399 /* shift right acc */
7402 emitcode ("anl", "a,#0x%02x",
7403 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7404 aopPut (AOP (result), "a", offset);
7408 /* bit field did not fit in a byte */
7409 rlen = SPEC_BLEN (etype) - 8;
7410 aopPut (AOP (result), "a", offset++);
7419 emitcode ("inc", "%s", rname);
7420 emitcode ("mov", "a,@%s", rname);
7424 emitcode ("inc", "%s", rname);
7425 emitcode ("movx", "a,@%s", rname);
7429 emitcode ("inc", "dptr");
7430 emitcode ("movx", "a,@dptr");
7434 emitcode ("clr", "a");
7435 emitcode ("inc", "dptr");
7436 emitcode ("movc", "a", "@a+dptr");
7440 emitcode ("inc", "dptr");
7441 emitcode ("lcall", "__gptrget");
7446 /* if we are done */
7450 aopPut (AOP (result), "a", offset++);
7456 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7457 aopPut (AOP (result), "a", offset);
7464 /*-----------------------------------------------------------------*/
7465 /* genDataPointerGet - generates code when ptr offset is known */
7466 /*-----------------------------------------------------------------*/
7468 genDataPointerGet (operand * left,
7474 int size, offset = 0;
7475 aopOp (result, ic, TRUE, FALSE);
7477 /* get the string representation of the name */
7478 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7479 size = AOP_SIZE (result);
7480 _startLazyDPSEvaluation ();
7484 sprintf (buffer, "(%s + %d)", l + 1, offset);
7486 sprintf (buffer, "%s", l + 1);
7487 aopPut (AOP (result), buffer, offset++);
7489 _endLazyDPSEvaluation ();
7491 freeAsmop (left, NULL, ic, TRUE);
7492 freeAsmop (result, NULL, ic, TRUE);
7495 /*-----------------------------------------------------------------*/
7496 /* genNearPointerGet - emitcode for near pointer fetch */
7497 /*-----------------------------------------------------------------*/
7499 genNearPointerGet (operand * left,
7506 sym_link *rtype, *retype, *letype;
7507 sym_link *ltype = operandType (left);
7510 rtype = operandType (result);
7511 retype = getSpec (rtype);
7512 letype = getSpec (ltype);
7514 aopOp (left, ic, FALSE, FALSE);
7516 /* if left is rematerialisable and
7517 result is not bit variable type and
7518 the left is pointer to data space i.e
7519 lower 128 bytes of space */
7520 if (AOP_TYPE (left) == AOP_IMMD &&
7521 !IS_BITVAR (retype) &&
7522 !IS_BITVAR (letype) &&
7523 DCL_TYPE (ltype) == POINTER)
7525 genDataPointerGet (left, result, ic);
7529 /* if the value is already in a pointer register
7530 then don't need anything more */
7531 if (!AOP_INPREG (AOP (left)))
7533 /* otherwise get a free pointer register */
7535 preg = getFreePtr (ic, &aop, FALSE);
7536 emitcode ("mov", "%s,%s",
7538 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7542 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7544 freeAsmop (left, NULL, ic, TRUE);
7545 aopOp (result, ic, FALSE, FALSE);
7547 /* if bitfield then unpack the bits */
7548 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7549 genUnpackBits (result, rname, POINTER);
7552 /* we have can just get the values */
7553 int size = AOP_SIZE (result);
7558 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7561 emitcode ("mov", "a,@%s", rname);
7562 aopPut (AOP (result), "a", offset);
7566 sprintf (buffer, "@%s", rname);
7567 aopPut (AOP (result), buffer, offset);
7571 emitcode ("inc", "%s", rname);
7575 /* now some housekeeping stuff */
7578 /* we had to allocate for this iCode */
7579 freeAsmop (NULL, aop, ic, TRUE);
7583 /* we did not allocate which means left
7584 already in a pointer register, then
7585 if size > 0 && this could be used again
7586 we have to point it back to where it
7588 if (AOP_SIZE (result) > 1 &&
7589 !OP_SYMBOL (left)->remat &&
7590 (OP_SYMBOL (left)->liveTo > ic->seq ||
7593 int size = AOP_SIZE (result) - 1;
7595 emitcode ("dec", "%s", rname);
7600 freeAsmop (result, NULL, ic, TRUE);
7604 /*-----------------------------------------------------------------*/
7605 /* genPagedPointerGet - emitcode for paged pointer fetch */
7606 /*-----------------------------------------------------------------*/
7608 genPagedPointerGet (operand * left,
7615 sym_link *rtype, *retype, *letype;
7617 rtype = operandType (result);
7618 retype = getSpec (rtype);
7619 letype = getSpec (operandType (left));
7620 aopOp (left, ic, FALSE, FALSE);
7622 /* if the value is already in a pointer register
7623 then don't need anything more */
7624 if (!AOP_INPREG (AOP (left)))
7626 /* otherwise get a free pointer register */
7628 preg = getFreePtr (ic, &aop, FALSE);
7629 emitcode ("mov", "%s,%s",
7631 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7635 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7637 freeAsmop (left, NULL, ic, TRUE);
7638 aopOp (result, ic, FALSE, FALSE);
7640 /* if bitfield then unpack the bits */
7641 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7642 genUnpackBits (result, rname, PPOINTER);
7645 /* we have can just get the values */
7646 int size = AOP_SIZE (result);
7652 emitcode ("movx", "a,@%s", rname);
7653 aopPut (AOP (result), "a", offset);
7658 emitcode ("inc", "%s", rname);
7662 /* now some housekeeping stuff */
7665 /* we had to allocate for this iCode */
7666 freeAsmop (NULL, aop, ic, TRUE);
7670 /* we did not allocate which means left
7671 already in a pointer register, then
7672 if size > 0 && this could be used again
7673 we have to point it back to where it
7675 if (AOP_SIZE (result) > 1 &&
7676 !OP_SYMBOL (left)->remat &&
7677 (OP_SYMBOL (left)->liveTo > ic->seq ||
7680 int size = AOP_SIZE (result) - 1;
7682 emitcode ("dec", "%s", rname);
7687 freeAsmop (result, NULL, ic, TRUE);
7692 /*-----------------------------------------------------------------*/
7693 /* genFarPointerGet - gget value from far space */
7694 /*-----------------------------------------------------------------*/
7696 genFarPointerGet (operand * left,
7697 operand * result, iCode * ic)
7700 sym_link *retype = getSpec (operandType (result));
7701 sym_link *letype = getSpec (operandType (left));
7702 D (emitcode (";", "genFarPointerGet");
7705 aopOp (left, ic, FALSE, FALSE);
7707 /* if the operand is already in dptr
7708 then we do nothing else we move the value to dptr */
7709 if (AOP_TYPE (left) != AOP_STR)
7711 /* if this is remateriazable */
7712 if (AOP_TYPE (left) == AOP_IMMD)
7714 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7718 /* we need to get it byte by byte */
7719 _startLazyDPSEvaluation ();
7720 if (AOP_TYPE (left) != AOP_DPTR)
7722 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7723 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7724 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7728 /* We need to generate a load to DPTR indirect through DPTR. */
7729 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7731 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7732 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7733 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7734 emitcode ("pop", "dph");
7735 emitcode ("pop", "dpl");
7737 _endLazyDPSEvaluation ();
7740 /* so dptr know contains the address */
7741 freeAsmop (left, NULL, ic, TRUE);
7742 aopOp (result, ic, FALSE, TRUE);
7744 /* if bit then unpack */
7745 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7746 genUnpackBits (result, "dptr", FPOINTER);
7749 size = AOP_SIZE (result);
7752 _startLazyDPSEvaluation ();
7759 emitcode ("movx", "a,@dptr");
7761 emitcode ("inc", "dptr");
7763 aopPut (AOP (result), "a", offset++);
7765 _endLazyDPSEvaluation ();
7768 freeAsmop (result, NULL, ic, TRUE);
7771 /*-----------------------------------------------------------------*/
7772 /* emitcodePointerGet - gget value from code space */
7773 /*-----------------------------------------------------------------*/
7775 emitcodePointerGet (operand * left,
7776 operand * result, iCode * ic)
7779 sym_link *retype = getSpec (operandType (result));
7781 aopOp (left, ic, FALSE, FALSE);
7783 /* if the operand is already in dptr
7784 then we do nothing else we move the value to dptr */
7785 if (AOP_TYPE (left) != AOP_STR)
7787 /* if this is remateriazable */
7788 if (AOP_TYPE (left) == AOP_IMMD)
7790 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7793 { /* we need to get it byte by byte */
7794 _startLazyDPSEvaluation ();
7795 if (AOP_TYPE (left) != AOP_DPTR)
7797 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7798 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7799 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7803 /* We need to generate a load to DPTR indirect through DPTR. */
7804 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7806 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7807 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7808 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7809 emitcode ("pop", "dph");
7810 emitcode ("pop", "dpl");
7812 _endLazyDPSEvaluation ();
7815 /* so dptr know contains the address */
7816 freeAsmop (left, NULL, ic, TRUE);
7817 aopOp (result, ic, FALSE, TRUE);
7819 /* if bit then unpack */
7820 if (IS_BITVAR (retype))
7821 genUnpackBits (result, "dptr", CPOINTER);
7824 size = AOP_SIZE (result);
7827 _startLazyDPSEvaluation ();
7833 emitcode ("clr", "a");
7834 emitcode ("movc", "a,@a+dptr");
7836 emitcode ("inc", "dptr");
7837 aopPut (AOP (result), "a", offset++);
7839 _endLazyDPSEvaluation ();
7842 freeAsmop (result, NULL, ic, TRUE);
7845 /*-----------------------------------------------------------------*/
7846 /* genGenPointerGet - gget value from generic pointer space */
7847 /*-----------------------------------------------------------------*/
7849 genGenPointerGet (operand * left,
7850 operand * result, iCode * ic)
7853 sym_link *retype = getSpec (operandType (result));
7854 sym_link *letype = getSpec (operandType (left));
7856 aopOp (left, ic, FALSE, TRUE);
7858 /* if the operand is already in dptr
7859 then we do nothing else we move the value to dptr */
7860 if (AOP_TYPE (left) != AOP_STR)
7862 /* if this is remateriazable */
7863 if (AOP_TYPE (left) == AOP_IMMD)
7865 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7866 emitcode ("mov", "b,#%d", pointerCode (retype));
7869 { /* we need to get it byte by byte */
7870 _startLazyDPSEvaluation ();
7871 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7872 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7873 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7874 emitcode ("mov", "b,%s", aopGet (AOP (left), 3, FALSE, FALSE, TRUE));
7875 _endLazyDPSEvaluation ();
7878 /* so dptr know contains the address */
7879 freeAsmop (left, NULL, ic, TRUE);
7880 aopOp (result, ic, FALSE, TRUE);
7882 /* if bit then unpack */
7883 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7884 genUnpackBits (result, "dptr", GPOINTER);
7887 size = AOP_SIZE (result);
7892 emitcode ("lcall", "__gptrget");
7893 aopPut (AOP (result), "a", offset++);
7895 emitcode ("inc", "dptr");
7899 freeAsmop (result, NULL, ic, TRUE);
7902 /*-----------------------------------------------------------------*/
7903 /* genPointerGet - generate code for pointer get */
7904 /*-----------------------------------------------------------------*/
7906 genPointerGet (iCode * ic)
7908 operand *left, *result;
7909 sym_link *type, *etype;
7912 D (emitcode (";", "genPointerGet ");
7915 left = IC_LEFT (ic);
7916 result = IC_RESULT (ic);
7918 /* depending on the type of pointer we need to
7919 move it to the correct pointer register */
7920 type = operandType (left);
7921 etype = getSpec (type);
7922 /* if left is of type of pointer then it is simple */
7923 if (IS_PTR (type) && !IS_FUNC (type->next))
7924 p_type = DCL_TYPE (type);
7927 /* we have to go by the storage class */
7928 p_type = PTR_TYPE (SPEC_OCLS (etype));
7931 /* now that we have the pointer type we assign
7932 the pointer values */
7938 genNearPointerGet (left, result, ic);
7942 genPagedPointerGet (left, result, ic);
7946 genFarPointerGet (left, result, ic);
7950 emitcodePointerGet (left, result, ic);
7954 genGenPointerGet (left, result, ic);
7960 /*-----------------------------------------------------------------*/
7961 /* genPackBits - generates code for packed bit storage */
7962 /*-----------------------------------------------------------------*/
7964 genPackBits (sym_link * etype,
7966 char *rname, int p_type)
7974 blen = SPEC_BLEN (etype);
7975 bstr = SPEC_BSTR (etype);
7977 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
7980 /* if the bit lenth is less than or */
7981 /* it exactly fits a byte then */
7982 if (SPEC_BLEN (etype) <= 8)
7984 shCount = SPEC_BSTR (etype);
7986 /* shift left acc */
7989 if (SPEC_BLEN (etype) < 8)
7990 { /* if smaller than a byte */
7996 emitcode ("mov", "b,a");
7997 emitcode ("mov", "a,@%s", rname);
8001 emitcode ("mov", "b,a");
8002 emitcode ("movx", "a,@dptr");
8006 emitcode ("push", "b");
8007 emitcode ("push", "acc");
8008 emitcode ("lcall", "__gptrget");
8009 emitcode ("pop", "b");
8013 emitcode ("anl", "a,#0x%02x", (unsigned char)
8014 ((unsigned char) (0xFF << (blen + bstr)) |
8015 (unsigned char) (0xFF >> (8 - bstr))));
8016 emitcode ("orl", "a,b");
8017 if (p_type == GPOINTER)
8018 emitcode ("pop", "b");
8025 emitcode ("mov", "@%s,a", rname);
8029 emitcode ("movx", "@dptr,a");
8033 emitcode ("lcall", "__gptrput");
8038 if (SPEC_BLEN (etype) <= 8)
8041 emitcode ("inc", "%s", rname);
8042 rLen = SPEC_BLEN (etype);
8044 /* now generate for lengths greater than one byte */
8048 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8060 emitcode ("mov", "@%s,a", rname);
8063 emitcode ("mov", "@%s,%s", rname, l);
8068 emitcode ("movx", "@dptr,a");
8073 emitcode ("lcall", "__gptrput");
8076 emitcode ("inc", "%s", rname);
8081 /* last last was not complete */
8084 /* save the byte & read byte */
8088 emitcode ("mov", "b,a");
8089 emitcode ("mov", "a,@%s", rname);
8093 emitcode ("mov", "b,a");
8094 emitcode ("movx", "a,@dptr");
8098 emitcode ("push", "b");
8099 emitcode ("push", "acc");
8100 emitcode ("lcall", "__gptrget");
8101 emitcode ("pop", "b");
8105 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8106 emitcode ("orl", "a,b");
8109 if (p_type == GPOINTER)
8110 emitcode ("pop", "b");
8116 emitcode ("mov", "@%s,a", rname);
8120 emitcode ("movx", "@dptr,a");
8124 emitcode ("lcall", "__gptrput");
8128 /*-----------------------------------------------------------------*/
8129 /* genDataPointerSet - remat pointer to data space */
8130 /*-----------------------------------------------------------------*/
8132 genDataPointerSet (operand * right,
8136 int size, offset = 0;
8137 char *l, buffer[256];
8139 aopOp (right, ic, FALSE, FALSE);
8141 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8142 size = AOP_SIZE (right);
8146 sprintf (buffer, "(%s + %d)", l + 1, offset);
8148 sprintf (buffer, "%s", l + 1);
8149 emitcode ("mov", "%s,%s", buffer,
8150 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8153 freeAsmop (right, NULL, ic, TRUE);
8154 freeAsmop (result, NULL, ic, TRUE);
8157 /*-----------------------------------------------------------------*/
8158 /* genNearPointerSet - emitcode for near pointer put */
8159 /*-----------------------------------------------------------------*/
8161 genNearPointerSet (operand * right,
8168 sym_link *retype, *letype;
8169 sym_link *ptype = operandType (result);
8171 retype = getSpec (operandType (right));
8172 letype = getSpec (ptype);
8174 aopOp (result, ic, FALSE, FALSE);
8176 /* if the result is rematerializable &
8177 in data space & not a bit variable */
8178 if (AOP_TYPE (result) == AOP_IMMD &&
8179 DCL_TYPE (ptype) == POINTER &&
8180 !IS_BITVAR (retype) &&
8181 !IS_BITVAR (letype))
8183 genDataPointerSet (right, result, ic);
8187 /* if the value is already in a pointer register
8188 then don't need anything more */
8189 if (!AOP_INPREG (AOP (result)))
8191 /* otherwise get a free pointer register */
8193 preg = getFreePtr (ic, &aop, FALSE);
8194 emitcode ("mov", "%s,%s",
8196 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8200 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8202 freeAsmop (result, NULL, ic, TRUE);
8203 aopOp (right, ic, FALSE, FALSE);
8205 /* if bitfield then unpack the bits */
8206 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8207 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8210 /* we have can just get the values */
8211 int size = AOP_SIZE (right);
8216 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8220 emitcode ("mov", "@%s,a", rname);
8223 emitcode ("mov", "@%s,%s", rname, l);
8225 emitcode ("inc", "%s", rname);
8230 /* now some housekeeping stuff */
8233 /* we had to allocate for this iCode */
8234 freeAsmop (NULL, aop, ic, TRUE);
8238 /* we did not allocate which means left
8239 already in a pointer register, then
8240 if size > 0 && this could be used again
8241 we have to point it back to where it
8243 if (AOP_SIZE (right) > 1 &&
8244 !OP_SYMBOL (result)->remat &&
8245 (OP_SYMBOL (result)->liveTo > ic->seq ||
8248 int size = AOP_SIZE (right) - 1;
8250 emitcode ("dec", "%s", rname);
8255 freeAsmop (right, NULL, ic, TRUE);
8260 /*-----------------------------------------------------------------*/
8261 /* genPagedPointerSet - emitcode for Paged pointer put */
8262 /*-----------------------------------------------------------------*/
8264 genPagedPointerSet (operand * right,
8271 sym_link *retype, *letype;
8273 retype = getSpec (operandType (right));
8274 letype = getSpec (operandType (result));
8276 aopOp (result, ic, FALSE, FALSE);
8278 /* if the value is already in a pointer register
8279 then don't need anything more */
8280 if (!AOP_INPREG (AOP (result)))
8282 /* otherwise get a free pointer register */
8284 preg = getFreePtr (ic, &aop, FALSE);
8285 emitcode ("mov", "%s,%s",
8287 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8291 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8293 freeAsmop (result, NULL, ic, TRUE);
8294 aopOp (right, ic, FALSE, FALSE);
8296 /* if bitfield then unpack the bits */
8297 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8298 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8301 /* we have can just get the values */
8302 int size = AOP_SIZE (right);
8307 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8310 emitcode ("movx", "@%s,a", rname);
8313 emitcode ("inc", "%s", rname);
8319 /* now some housekeeping stuff */
8322 /* we had to allocate for this iCode */
8323 freeAsmop (NULL, aop, ic, TRUE);
8327 /* we did not allocate which means left
8328 already in a pointer register, then
8329 if size > 0 && this could be used again
8330 we have to point it back to where it
8332 if (AOP_SIZE (right) > 1 &&
8333 !OP_SYMBOL (result)->remat &&
8334 (OP_SYMBOL (result)->liveTo > ic->seq ||
8337 int size = AOP_SIZE (right) - 1;
8339 emitcode ("dec", "%s", rname);
8344 freeAsmop (right, NULL, ic, TRUE);
8349 /*-----------------------------------------------------------------*/
8350 /* genFarPointerSet - set value from far space */
8351 /*-----------------------------------------------------------------*/
8353 genFarPointerSet (operand * right,
8354 operand * result, iCode * ic)
8357 sym_link *retype = getSpec (operandType (right));
8358 sym_link *letype = getSpec (operandType (result));
8360 aopOp (result, ic, FALSE, FALSE);
8362 /* if the operand is already in dptr
8363 then we do nothing else we move the value to dptr */
8364 if (AOP_TYPE (result) != AOP_STR)
8366 /* if this is remateriazable */
8367 if (AOP_TYPE (result) == AOP_IMMD)
8368 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8371 /* we need to get it byte by byte */
8372 _startLazyDPSEvaluation ();
8373 if (AOP_TYPE (result) != AOP_DPTR)
8375 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8376 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8377 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8381 /* We need to generate a load to DPTR indirect through DPTR. */
8382 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8384 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8385 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8386 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8387 emitcode ("pop", "dph");
8388 emitcode ("pop", "dpl");
8390 _endLazyDPSEvaluation ();
8393 /* so dptr know contains the address */
8394 freeAsmop (result, NULL, ic, TRUE);
8395 aopOp (right, ic, FALSE, TRUE);
8397 /* if bit then unpack */
8398 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8399 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8402 size = AOP_SIZE (right);
8405 _startLazyDPSEvaluation ();
8408 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8414 emitcode ("movx", "@dptr,a");
8416 emitcode ("inc", "dptr");
8418 _endLazyDPSEvaluation ();
8421 freeAsmop (right, NULL, ic, TRUE);
8424 /*-----------------------------------------------------------------*/
8425 /* genGenPointerSet - set value from generic pointer space */
8426 /*-----------------------------------------------------------------*/
8428 genGenPointerSet (operand * right,
8429 operand * result, iCode * ic)
8432 sym_link *retype = getSpec (operandType (right));
8433 sym_link *letype = getSpec (operandType (result));
8435 aopOp (result, ic, FALSE, TRUE);
8437 /* if the operand is already in dptr
8438 then we do nothing else we move the value to dptr */
8439 if (AOP_TYPE (result) != AOP_STR)
8441 _startLazyDPSEvaluation ();
8442 /* if this is remateriazable */
8443 if (AOP_TYPE (result) == AOP_IMMD)
8445 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8446 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8449 { /* we need to get it byte by byte */
8450 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8451 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8452 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8453 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8455 _endLazyDPSEvaluation ();
8457 /* so dptr know contains the address */
8458 freeAsmop (result, NULL, ic, TRUE);
8459 aopOp (right, ic, FALSE, TRUE);
8461 /* if bit then unpack */
8462 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8463 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8466 size = AOP_SIZE (right);
8469 _startLazyDPSEvaluation ();
8472 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8478 emitcode ("lcall", "__gptrput");
8480 emitcode ("inc", "dptr");
8482 _endLazyDPSEvaluation ();
8485 freeAsmop (right, NULL, ic, TRUE);
8488 /*-----------------------------------------------------------------*/
8489 /* genPointerSet - stores the value into a pointer location */
8490 /*-----------------------------------------------------------------*/
8492 genPointerSet (iCode * ic)
8494 operand *right, *result;
8495 sym_link *type, *etype;
8498 D (emitcode (";", "genPointerSet ");
8501 right = IC_RIGHT (ic);
8502 result = IC_RESULT (ic);
8504 /* depending on the type of pointer we need to
8505 move it to the correct pointer register */
8506 type = operandType (result);
8507 etype = getSpec (type);
8508 /* if left is of type of pointer then it is simple */
8509 if (IS_PTR (type) && !IS_FUNC (type->next))
8511 p_type = DCL_TYPE (type);
8515 /* we have to go by the storage class */
8516 p_type = PTR_TYPE (SPEC_OCLS (etype));
8519 /* now that we have the pointer type we assign
8520 the pointer values */
8526 genNearPointerSet (right, result, ic);
8530 genPagedPointerSet (right, result, ic);
8534 genFarPointerSet (right, result, ic);
8538 genGenPointerSet (right, result, ic);
8544 /*-----------------------------------------------------------------*/
8545 /* genIfx - generate code for Ifx statement */
8546 /*-----------------------------------------------------------------*/
8548 genIfx (iCode * ic, iCode * popIc)
8550 operand *cond = IC_COND (ic);
8553 D (emitcode (";", "genIfx ");
8556 aopOp (cond, ic, FALSE, FALSE);
8558 /* get the value into acc */
8559 if (AOP_TYPE (cond) != AOP_CRY)
8563 /* the result is now in the accumulator */
8564 freeAsmop (cond, NULL, ic, TRUE);
8566 /* if there was something to be popped then do it */
8570 /* if the condition is a bit variable */
8571 if (isbit && IS_ITEMP (cond) &&
8573 genIfxJump (ic, SPIL_LOC (cond)->rname);
8574 else if (isbit && !IS_ITEMP (cond))
8575 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8577 genIfxJump (ic, "a");
8582 /*-----------------------------------------------------------------*/
8583 /* genAddrOf - generates code for address of */
8584 /*-----------------------------------------------------------------*/
8586 genAddrOf (iCode * ic)
8588 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8591 D (emitcode (";", "genAddrOf ");
8594 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8596 /* if the operand is on the stack then we
8597 need to get the stack offset of this
8601 /* if it has an offset then we need to compute
8605 emitcode ("mov", "a,_bp");
8606 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8607 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8611 /* we can just move _bp */
8612 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8614 /* fill the result with zero */
8615 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8618 if (options.stack10bit && size < (FPTRSIZE - 1))
8621 "*** warning: pointer to stack var truncated.\n");
8628 if (options.stack10bit && offset == 2)
8630 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8634 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8641 /* object not on stack then we need the name */
8642 size = AOP_SIZE (IC_RESULT (ic));
8647 char s[SDCC_NAME_MAX];
8649 sprintf (s, "#(%s >> %d)",
8653 sprintf (s, "#%s", sym->rname);
8654 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8662 /*-----------------------------------------------------------------*/
8663 /* genFarFarAssign - assignment when both are in far space */
8664 /*-----------------------------------------------------------------*/
8666 genFarFarAssign (operand * result, operand * right, iCode * ic)
8668 int size = AOP_SIZE (right);
8674 /* This is a net loss for size == 1, but a big gain
8677 D (emitcode (";", "genFarFarAssign (improved)");
8680 aopOp (result, ic, TRUE, TRUE);
8682 _startLazyDPSEvaluation ();
8685 aopPut (AOP (result),
8686 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8689 _endLazyDPSEvaluation ();
8690 freeAsmop (result, NULL, ic, FALSE);
8691 freeAsmop (right, NULL, ic, FALSE);
8695 D (emitcode (";", "genFarFarAssign ");
8698 /* first push the right side on to the stack */
8699 _startLazyDPSEvaluation ();
8702 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8704 emitcode ("push", "acc");
8707 freeAsmop (right, NULL, ic, FALSE);
8708 /* now assign DPTR to result */
8709 aopOp (result, ic, FALSE, FALSE);
8710 size = AOP_SIZE (result);
8713 emitcode ("pop", "acc");
8714 aopPut (AOP (result), "a", --offset);
8716 freeAsmop (result, NULL, ic, FALSE);
8717 _endLazyDPSEvaluation ();
8721 /*-----------------------------------------------------------------*/
8722 /* genAssign - generate code for assignment */
8723 /*-----------------------------------------------------------------*/
8725 genAssign (iCode * ic)
8727 operand *result, *right;
8729 unsigned long lit = 0L;
8731 D (emitcode (";", "genAssign ");
8734 result = IC_RESULT (ic);
8735 right = IC_RIGHT (ic);
8737 /* if they are the same */
8738 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8741 aopOp (right, ic, FALSE, FALSE);
8743 emitcode (";", "genAssign: resultIsFar = %s",
8744 isOperandInFarSpace (result) ?
8747 /* special case both in far space */
8748 if ((AOP_TYPE (right) == AOP_DPTR ||
8749 AOP_TYPE (right) == AOP_DPTR2) &&
8750 /* IS_TRUE_SYMOP(result) && */
8751 isOperandInFarSpace (result))
8753 genFarFarAssign (result, right, ic);
8757 aopOp (result, ic, TRUE, FALSE);
8759 /* if they are the same registers */
8760 if (sameRegs (AOP (right), AOP (result)))
8763 /* if the result is a bit */
8764 if (AOP_TYPE (result) == AOP_CRY)
8767 /* if the right size is a literal then
8768 we know what the value is */
8769 if (AOP_TYPE (right) == AOP_LIT)
8771 if (((int) operandLitValue (right)))
8772 aopPut (AOP (result), one, 0);
8774 aopPut (AOP (result), zero, 0);
8778 /* the right is also a bit variable */
8779 if (AOP_TYPE (right) == AOP_CRY)
8781 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8782 aopPut (AOP (result), "c", 0);
8788 aopPut (AOP (result), "a", 0);
8792 /* bit variables done */
8794 size = AOP_SIZE (result);
8796 if (AOP_TYPE (right) == AOP_LIT)
8797 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8800 (AOP_TYPE (result) != AOP_REG) &&
8801 (AOP_TYPE (right) == AOP_LIT) &&
8802 !IS_FLOAT (operandType (right)))
8804 D (emitcode (";", "Kevin's better literal load code");
8806 _startLazyDPSEvaluation ();
8807 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8809 aopPut (AOP (result),
8810 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8815 /* And now fill the rest with zeros. */
8818 emitcode ("clr", "a");
8822 aopPut (AOP (result), "a", offset++);
8824 _endLazyDPSEvaluation ();
8828 _startLazyDPSEvaluation ();
8831 aopPut (AOP (result),
8832 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8836 _endLazyDPSEvaluation ();
8840 freeAsmop (right, NULL, ic, FALSE);
8841 freeAsmop (result, NULL, ic, TRUE);
8844 /*-----------------------------------------------------------------*/
8845 /* genJumpTab - generates code for jump table */
8846 /*-----------------------------------------------------------------*/
8848 genJumpTab (iCode * ic)
8853 D (emitcode (";", "genJumpTab ");
8856 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8857 /* get the condition into accumulator */
8858 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8860 /* multiply by four! */
8861 emitcode ("add", "a,acc");
8862 emitcode ("add", "a,acc");
8863 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8865 jtab = newiTempLabel (NULL);
8866 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8867 emitcode ("jmp", "@a+dptr");
8868 emitcode ("", "%05d$:", jtab->key + 100);
8869 /* now generate the jump labels */
8870 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8871 jtab = setNextItem (IC_JTLABELS (ic)))
8872 emitcode ("ljmp", "%05d$", jtab->key + 100);
8876 /*-----------------------------------------------------------------*/
8877 /* genCast - gen code for casting */
8878 /*-----------------------------------------------------------------*/
8880 genCast (iCode * ic)
8882 operand *result = IC_RESULT (ic);
8883 sym_link *ctype = operandType (IC_LEFT (ic));
8884 sym_link *rtype = operandType (IC_RIGHT (ic));
8885 operand *right = IC_RIGHT (ic);
8888 D (emitcode (";", "genCast ");
8891 /* if they are equivalent then do nothing */
8892 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8895 aopOp (right, ic, FALSE, FALSE);
8896 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8898 /* if the result is a bit */
8899 if (AOP_TYPE (result) == AOP_CRY)
8901 /* if the right size is a literal then
8902 we know what the value is */
8903 if (AOP_TYPE (right) == AOP_LIT)
8905 if (((int) operandLitValue (right)))
8906 aopPut (AOP (result), one, 0);
8908 aopPut (AOP (result), zero, 0);
8913 /* the right is also a bit variable */
8914 if (AOP_TYPE (right) == AOP_CRY)
8916 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8917 aopPut (AOP (result), "c", 0);
8923 aopPut (AOP (result), "a", 0);
8927 /* if they are the same size : or less */
8928 if (AOP_SIZE (result) <= AOP_SIZE (right))
8931 /* if they are in the same place */
8932 if (sameRegs (AOP (right), AOP (result)))
8935 /* if they in different places then copy */
8936 size = AOP_SIZE (result);
8938 _startLazyDPSEvaluation ();
8941 aopPut (AOP (result),
8942 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8946 _endLazyDPSEvaluation ();
8951 /* if the result is of type pointer */
8956 sym_link *type = operandType (right);
8958 /* pointer to generic pointer */
8959 if (IS_GENPTR (ctype))
8965 p_type = DCL_TYPE (type);
8969 #if OLD_CAST_BEHAVIOR
8970 /* KV: we are converting a non-pointer type to
8971 * a generic pointer. This (ifdef'd out) code
8972 * says that the resulting generic pointer
8973 * should have the same class as the storage
8974 * location of the non-pointer variable.
8976 * For example, converting an int (which happens
8977 * to be stored in DATA space) to a pointer results
8978 * in a DATA generic pointer; if the original int
8979 * in XDATA space, so will be the resulting pointer.
8981 * I don't like that behavior, and thus this change:
8982 * all such conversions will be forced to XDATA and
8983 * throw a warning. If you want some non-XDATA
8984 * type, or you want to suppress the warning, you
8985 * must go through an intermediate cast, like so:
8987 * char _generic *gp = (char _xdata *)(intVar);
8989 sym_link *etype = getSpec (type);
8991 /* we have to go by the storage class */
8992 if (SPEC_OCLS (etype) != generic)
8994 p_type = PTR_TYPE (SPEC_OCLS (etype));
8999 /* Converting unknown class (i.e. register variable)
9000 * to generic pointer. This is not good, but
9001 * we'll make a guess (and throw a warning).
9004 werror (W_INT_TO_GEN_PTR_CAST);
9008 /* the first two bytes are known */
9009 size = GPTRSIZE - 1;
9011 _startLazyDPSEvaluation ();
9014 aopPut (AOP (result),
9015 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9019 _endLazyDPSEvaluation ();
9021 /* the last byte depending on type */
9039 /* this should never happen */
9040 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9041 "got unknown pointer type");
9044 aopPut (AOP (result), l, GPTRSIZE - 1);
9048 /* just copy the pointers */
9049 size = AOP_SIZE (result);
9051 _startLazyDPSEvaluation ();
9054 aopPut (AOP (result),
9055 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9059 _endLazyDPSEvaluation ();
9063 /* so we now know that the size of destination is greater
9064 than the size of the source */
9065 /* we move to result for the size of source */
9066 size = AOP_SIZE (right);
9068 _startLazyDPSEvaluation ();
9071 aopPut (AOP (result),
9072 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9076 _endLazyDPSEvaluation ();
9078 /* now depending on the sign of the source && destination */
9079 size = AOP_SIZE (result) - AOP_SIZE (right);
9080 /* if unsigned or not an integral type */
9081 /* also, if the source is a bit, we don't need to sign extend, because
9082 * it can't possibly have set the sign bit.
9084 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9088 aopPut (AOP (result), zero, offset++);
9093 /* we need to extend the sign :{ */
9094 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9095 FALSE, FALSE, TRUE);
9097 emitcode ("rlc", "a");
9098 emitcode ("subb", "a,acc");
9100 aopPut (AOP (result), "a", offset++);
9103 /* we are done hurray !!!! */
9106 freeAsmop (right, NULL, ic, TRUE);
9107 freeAsmop (result, NULL, ic, TRUE);
9111 /*-----------------------------------------------------------------*/
9112 /* genDjnz - generate decrement & jump if not zero instrucion */
9113 /*-----------------------------------------------------------------*/
9115 genDjnz (iCode * ic, iCode * ifx)
9121 /* if the if condition has a false label
9122 then we cannot save */
9126 /* if the minus is not of the form
9128 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9129 !IS_OP_LITERAL (IC_RIGHT (ic)))
9132 if (operandLitValue (IC_RIGHT (ic)) != 1)
9135 /* if the size of this greater than one then no
9137 if (getSize (operandType (IC_RESULT (ic))) > 1)
9140 /* otherwise we can save BIG */
9141 lbl = newiTempLabel (NULL);
9142 lbl1 = newiTempLabel (NULL);
9144 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9146 if (IS_AOP_PREG (IC_RESULT (ic)))
9148 emitcode ("dec", "%s",
9149 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9150 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9151 emitcode ("jnz", "%05d$", lbl->key + 100);
9155 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9158 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9159 emitcode ("", "%05d$:", lbl->key + 100);
9160 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9161 emitcode ("", "%05d$:", lbl1->key + 100);
9163 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9168 /*-----------------------------------------------------------------*/
9169 /* genReceive - generate code for a receive iCode */
9170 /*-----------------------------------------------------------------*/
9172 genReceive (iCode * ic)
9175 D (emitcode (";", "genReceive ");
9178 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9179 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9180 IS_TRUE_SYMOP (IC_RESULT (ic))))
9182 int size = getSize (operandType (IC_RESULT (ic)));
9183 int offset = fReturnSize_390 - size;
9186 emitcode ("push", "%s", (strcmp (fReturn[fReturnSize_390 - offset - 1], "a") ?
9187 fReturn[fReturnSize_390 - offset - 1] : "acc"));
9190 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9191 size = AOP_SIZE (IC_RESULT (ic));
9195 emitcode ("pop", "acc");
9196 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9203 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9205 assignResultValue (IC_RESULT (ic));
9208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9211 /*-----------------------------------------------------------------*/
9212 /* gen390Code - generate code for Dallas 390 based controllers */
9213 /*-----------------------------------------------------------------*/
9215 gen390Code (iCode * lic)
9220 lineHead = lineCurr = NULL;
9224 /* print the allocation information */
9226 printAllocInfo (currFunc, codeOutFile);
9228 /* if debug information required */
9229 if (options.debug && currFunc)
9231 //jwk if (currFunc) {
9232 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9234 if (IS_STATIC (currFunc->etype))
9235 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9237 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9240 /* stack pointer name */
9241 if (options.useXstack)
9247 for (ic = lic; ic; ic = ic->next)
9250 if (cln != ic->lineno)
9255 emitcode ("", "C$%s$%d$%d$%d ==.",
9256 FileBaseName (ic->filename), ic->lineno,
9257 ic->level, ic->block);
9260 emitcode (";", "%s %d", ic->filename, ic->lineno);
9263 /* if the result is marked as
9264 spilt and rematerializable or code for
9265 this has already been generated then
9267 if (resultRemat (ic) || ic->generated)
9270 /* depending on the operation */
9290 /* IPOP happens only when trying to restore a
9291 spilt live range, if there is an ifx statement
9292 following this pop then the if statement might
9293 be using some of the registers being popped which
9294 would destory the contents of the register so
9295 we need to check for this condition and handle it */
9297 ic->next->op == IFX &&
9298 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9299 genIfx (ic->next, ic);
9317 genEndFunction (ic);
9337 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9354 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9358 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9365 /* note these two are xlated by algebraic equivalence
9366 during parsing SDCC.y */
9367 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9368 "got '>=' or '<=' shouldn't have come here");
9372 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9384 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9388 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9392 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9419 case GET_VALUE_AT_ADDRESS:
9424 if (POINTER_SET (ic))
9451 addSet (&_G.sendSet, ic);
9456 /* piCode(ic,stdout); */
9462 /* now we are ready to call the
9463 peep hole optimizer */
9464 if (!options.nopeep)
9465 peepHole (&lineHead);
9467 /* now do the actual printing */
9468 printLine (lineHead, codeOutFile);