1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 char *aopLiteral (value * val, int offset);
53 /* this is the down and dirty file with all kinds of
54 kludgy & hacky stuff. This is what it is all about
55 CODE GENERATION for a specific MCU . some of the
56 routines may be reusable, will have to see */
58 static char *zero = "#0x00";
59 static char *one = "#0x01";
64 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
65 static char *fReturn[] =
66 {"dpl", "dph", "dpx", "b", "a"};
67 static char *accUse[] =
70 static short rbank = -1;
84 static void saverbank (int, iCode *, bool);
86 #define RESULTONSTACK(x) \
87 (IC_RESULT(x) && IC_RESULT(x)->aop && \
88 IC_RESULT(x)->aop->type == AOP_STK )
90 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
91 #define MOVA(x) { char *_mova_tmp = strdup(x); \
92 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
94 emitcode("mov","a,%s",_mova_tmp); \
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] =
105 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
106 0xE0, 0xC0, 0x80, 0x00};
107 static unsigned char SRMask[] =
108 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
120 emitcode (char *inst, char *fmt,...)
123 char lb[MAX_INLINEASM];
131 sprintf (lb, "%s\t", inst);
133 sprintf (lb, "%s", inst);
134 vsprintf (lb + (strlen (lb)), fmt, ap);
137 vsprintf (lb, fmt, ap);
139 while (isspace (*lbp))
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
151 /*-----------------------------------------------------------------*/
152 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
153 /*-----------------------------------------------------------------*/
155 getFreePtr (iCode * ic, asmop ** aopp, bool result)
157 bool r0iu = FALSE, r1iu = FALSE;
158 bool r0ou = FALSE, r1ou = FALSE;
160 /* the logic: if r0 & r1 used in the instruction
161 then we are in trouble otherwise */
163 /* first check if r0 & r1 are used by this
164 instruction, in which case we are in trouble */
165 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
166 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
171 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
172 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
174 /* if no usage of r0 then return it */
177 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
178 (*aopp)->type = AOP_R0;
180 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
183 /* if no usage of r1 then return it */
186 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
187 (*aopp)->type = AOP_R1;
189 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
192 /* now we know they both have usage */
193 /* if r0 not used in this instruction */
196 /* push it if not already pushed */
199 emitcode ("push", "%s",
200 ds390_regWithIdx (R0_IDX)->dname);
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
210 /* if r1 not used then */
214 /* push it if not already pushed */
217 emitcode ("push", "%s",
218 ds390_regWithIdx (R1_IDX)->dname);
222 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
223 (*aopp)->type = AOP_R1;
224 return ds390_regWithIdx (R1_IDX);
228 /* I said end of world but not quite end of world yet */
229 /* if this is a result then we can push it on the stack */
232 (*aopp)->type = AOP_STK;
237 /* other wise this is true end of the world */
238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
239 "getFreePtr should never reach here");
243 /*-----------------------------------------------------------------*/
244 /* newAsmop - creates a new asmOp */
245 /*-----------------------------------------------------------------*/
247 newAsmop (short type)
251 aop = Safe_calloc (1, sizeof (asmop));
256 static int _currentDPS; /* Current processor DPS. */
257 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
258 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
260 /*-----------------------------------------------------------------*/
261 /* genSetDPTR: generate code to select which DPTR is in use (zero */
262 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
263 /* alternate DPTR (DPL1/DPH1/DPX1). */
264 /*-----------------------------------------------------------------*/
269 /* If we are doing lazy evaluation, simply note the desired
270 * change, but don't emit any code yet.
280 emitcode ("mov", "dps, #0x00");
284 emitcode ("mov", "dps, #0x01");
288 /*-----------------------------------------------------------------*/
289 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
291 /* Any code that operates on DPTR (NB: not on the individual */
292 /* components, like DPH) *must* call _flushLazyDPS() before using */
293 /* DPTR within a lazy DPS evaluation block. */
295 /* Note that aopPut and aopGet already contain the proper calls to */
296 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
297 /* DPS evaluation block. */
299 /* Also, _flushLazyDPS must be called before any flow control */
300 /* operations that could potentially branch out of the block. */
302 /* Lazy DPS evaluation is simply an optimization (though an */
303 /* important one), so if in doubt, leave it out. */
304 /*-----------------------------------------------------------------*/
306 _startLazyDPSEvaluation (void)
313 /*-----------------------------------------------------------------*/
314 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
315 /* desired one. Call before using DPTR within a lazy DPS evaluation */
317 /*-----------------------------------------------------------------*/
327 if (_desiredDPS != _currentDPS)
331 emitcode ("inc", "dps");
335 emitcode ("dec", "dps");
337 _currentDPS = _desiredDPS;
341 /*-----------------------------------------------------------------*/
342 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
344 /* Forces us back to the safe state (standard DPTR selected). */
345 /*-----------------------------------------------------------------*/
347 _endLazyDPSEvaluation (void)
361 /*-----------------------------------------------------------------*/
362 /* pointerCode - returns the code for a pointer type */
363 /*-----------------------------------------------------------------*/
365 pointerCode (sym_link * etype)
368 return PTR_TYPE (SPEC_OCLS (etype));
372 /*-----------------------------------------------------------------*/
373 /* aopForSym - for a true symbol */
374 /*-----------------------------------------------------------------*/
376 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
379 memmap *space = SPEC_OCLS (sym->etype);
381 /* if already has one */
385 /* assign depending on the storage class */
386 /* if it is on the stack or indirectly addressable */
387 /* space we need to assign either r0 or r1 to it */
388 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
390 sym->aop = aop = newAsmop (0);
391 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
392 aop->size = getSize (sym->type);
394 /* now assign the address of the variable to
395 the pointer register */
396 if (aop->type != AOP_STK)
402 emitcode ("push", "acc");
404 emitcode ("mov", "a,_bp");
405 emitcode ("add", "a,#0x%02x",
407 ((char) (sym->stack - _G.nRegsSaved)) :
408 ((char) sym->stack)) & 0xff);
409 emitcode ("mov", "%s,a",
410 aop->aopu.aop_ptr->name);
413 emitcode ("pop", "acc");
416 emitcode ("mov", "%s,#%s",
417 aop->aopu.aop_ptr->name,
419 aop->paged = space->paged;
422 aop->aopu.aop_stk = sym->stack;
426 if (sym->onStack && options.stack10bit)
428 /* It's on the 10 bit stack, which is located in
433 emitcode ("push", "acc");
435 emitcode ("mov", "a,_bp");
436 emitcode ("add", "a,#0x%02x",
438 ((char) (sym->stack - _G.nRegsSaved)) :
439 ((char) sym->stack)) & 0xff);
444 emitcode ("mov", "dpx1,#0x40");
445 emitcode ("mov", "dph1,#0x00");
446 emitcode ("mov", "dpl1, a");
451 emitcode ("mov", "dpx,#0x40");
452 emitcode ("mov", "dph,#0x00");
453 emitcode ("mov", "dpl, a");
457 emitcode ("pop", "acc");
459 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
460 aop->size = getSize (sym->type);
464 /* if in bit space */
465 if (IN_BITSPACE (space))
467 sym->aop = aop = newAsmop (AOP_CRY);
468 aop->aopu.aop_dir = sym->rname;
469 aop->size = getSize (sym->type);
472 /* if it is in direct space */
473 if (IN_DIRSPACE (space))
475 sym->aop = aop = newAsmop (AOP_DIR);
476 aop->aopu.aop_dir = sym->rname;
477 aop->size = getSize (sym->type);
481 /* special case for a function */
482 if (IS_FUNC (sym->type))
484 sym->aop = aop = newAsmop (AOP_IMMD);
485 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
486 strcpy (aop->aopu.aop_immd, sym->rname);
487 aop->size = FPTRSIZE;
491 /* only remaining is far space */
492 /* in which case DPTR gets the address */
493 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
498 emitcode ("mov", "dptr,#%s", sym->rname);
503 emitcode ("mov", "dptr,#%s", sym->rname);
505 aop->size = getSize (sym->type);
507 /* if it is in code space */
508 if (IN_CODESPACE (space))
514 /*-----------------------------------------------------------------*/
515 /* aopForRemat - rematerialzes an object */
516 /*-----------------------------------------------------------------*/
518 aopForRemat (symbol * sym)
520 iCode *ic = sym->rematiCode;
521 asmop *aop = newAsmop (AOP_IMMD);
528 val += (int) operandLitValue (IC_RIGHT (ic));
529 else if (ic->op == '-')
530 val -= (int) operandLitValue (IC_RIGHT (ic));
534 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
538 sprintf (buffer, "(%s %c 0x%04x)",
539 OP_SYMBOL (IC_LEFT (ic))->rname,
540 val >= 0 ? '+' : '-',
543 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
545 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
546 strcpy (aop->aopu.aop_immd, buffer);
550 /*-----------------------------------------------------------------*/
551 /* regsInCommon - two operands have some registers in common */
552 /*-----------------------------------------------------------------*/
554 regsInCommon (operand * op1, operand * op2)
559 /* if they have registers in common */
560 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
563 sym1 = OP_SYMBOL (op1);
564 sym2 = OP_SYMBOL (op2);
566 if (sym1->nRegs == 0 || sym2->nRegs == 0)
569 for (i = 0; i < sym1->nRegs; i++)
575 for (j = 0; j < sym2->nRegs; j++)
580 if (sym2->regs[j] == sym1->regs[i])
588 /*-----------------------------------------------------------------*/
589 /* operandsEqu - equivalent */
590 /*-----------------------------------------------------------------*/
592 operandsEqu (operand * op1, operand * op2)
596 /* if they not symbols */
597 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
600 sym1 = OP_SYMBOL (op1);
601 sym2 = OP_SYMBOL (op2);
603 /* if both are itemps & one is spilt
604 and the other is not then false */
605 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
606 sym1->isspilt != sym2->isspilt)
609 /* if they are the same */
613 if (strcmp (sym1->rname, sym2->rname) == 0)
617 /* if left is a tmp & right is not */
618 if (IS_ITEMP (op1) &&
621 (sym1->usl.spillLoc == sym2))
624 if (IS_ITEMP (op2) &&
628 (sym2->usl.spillLoc == sym1))
634 /*-----------------------------------------------------------------*/
635 /* sameRegs - two asmops have the same registers */
636 /*-----------------------------------------------------------------*/
638 sameRegs (asmop * aop1, asmop * aop2)
644 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
651 if (aop1->type != AOP_REG ||
652 aop2->type != AOP_REG)
655 if (aop1->size != aop2->size)
658 for (i = 0; i < aop1->size; i++)
659 if (aop1->aopu.aop_reg[i] !=
660 aop2->aopu.aop_reg[i])
666 /*-----------------------------------------------------------------*/
667 /* aopOp - allocates an asmop for an operand : */
668 /*-----------------------------------------------------------------*/
670 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
679 /* if this a literal */
680 if (IS_OP_LITERAL (op))
682 op->aop = aop = newAsmop (AOP_LIT);
683 aop->aopu.aop_lit = op->operand.valOperand;
684 aop->size = getSize (operandType (op));
688 /* if already has a asmop then continue */
692 /* if the underlying symbol has a aop */
693 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
695 op->aop = OP_SYMBOL (op)->aop;
699 /* if this is a true symbol */
700 if (IS_TRUE_SYMOP (op))
702 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
706 /* this is a temporary : this has
712 e) can be a return use only */
714 sym = OP_SYMBOL (op);
717 /* if the type is a conditional */
718 if (sym->regType == REG_CND)
720 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
725 /* if it is spilt then two situations
727 b) has a spill location */
728 if (sym->isspilt || sym->nRegs == 0)
731 /* rematerialize it NOW */
734 sym->aop = op->aop = aop =
736 aop->size = getSize (sym->type);
743 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
744 aop->size = getSize (sym->type);
745 for (i = 0; i < 2; i++)
746 aop->aopu.aop_str[i] = accUse[i];
756 /* a AOP_STR uses DPTR, but DPTR is already in use;
759 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
762 aop = op->aop = sym->aop = newAsmop (AOP_STR);
763 aop->size = getSize (sym->type);
764 for (i = 0; i < (int) fReturnSizeDS390; i++)
765 aop->aopu.aop_str[i] = fReturn[i];
769 /* else spill location */
770 sym->aop = op->aop = aop =
771 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
772 aop->size = getSize (sym->type);
776 /* must be in a register */
777 sym->aop = op->aop = aop = newAsmop (AOP_REG);
778 aop->size = sym->nRegs;
779 for (i = 0; i < sym->nRegs; i++)
780 aop->aopu.aop_reg[i] = sym->regs[i];
783 /*-----------------------------------------------------------------*/
784 /* freeAsmop - free up the asmop given to an operand */
785 /*----------------------------------------------------------------*/
787 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
804 /* depending on the asmop type only three cases need work AOP_RO
805 , AOP_R1 && AOP_STK */
813 emitcode ("pop", "ar0");
817 bitVectUnSetBit (ic->rUsed, R0_IDX);
825 emitcode ("pop", "ar1");
829 bitVectUnSetBit (ic->rUsed, R1_IDX);
835 int stk = aop->aopu.aop_stk + aop->size;
836 bitVectUnSetBit (ic->rUsed, R0_IDX);
837 bitVectUnSetBit (ic->rUsed, R1_IDX);
839 getFreePtr (ic, &aop, FALSE);
841 if (options.stack10bit)
843 /* I'm not sure what to do here yet... */
846 "*** Warning: probably generating bad code for "
847 "10 bit stack mode.\n");
852 emitcode ("mov", "a,_bp");
853 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
854 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
858 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
863 emitcode ("pop", "acc");
864 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
867 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
870 freeAsmop (op, NULL, ic, TRUE);
873 emitcode ("pop", "ar0");
879 emitcode ("pop", "ar1");
886 /* all other cases just dealloc */
892 OP_SYMBOL (op)->aop = NULL;
893 /* if the symbol has a spill */
895 SPIL_LOC (op)->aop = NULL;
900 /*------------------------------------------------------------------*/
901 /* aopGet - for fetching value of the aop */
903 /* Set canClobberACC if you are aure it is OK to clobber the value */
904 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
905 /* just less efficient. */
906 /*------------------------------------------------------------------*/
918 /* offset is greater than
920 if (offset > (aop->size - 1) &&
921 aop->type != AOP_LIT)
924 /* depending on type */
930 /* if we need to increment it */
931 while (offset > aop->coff)
933 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
937 while (offset < aop->coff)
939 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
946 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
947 return (dname ? "acc" : "a");
949 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
950 rs = Safe_calloc (1, strlen (s) + 1);
957 if (aop->type == AOP_DPTR2)
962 emitcode ("xch", "a, ap");
968 while (offset > aop->coff)
970 emitcode ("inc", "dptr");
974 while (offset < aop->coff)
976 emitcode ("lcall", "__decdptr");
983 emitcode ("clr", "a");
984 emitcode ("movc", "a,@a+dptr");
988 emitcode ("movx", "a,@dptr");
991 if (aop->type == AOP_DPTR2)
996 emitcode ("xch", "a, ap");
1000 return (dname ? "acc" : "a");
1004 sprintf (s, "#%s", aop->aopu.aop_immd);
1006 sprintf (s, "#(%s >> %d)",
1011 aop->aopu.aop_immd);
1012 rs = Safe_calloc (1, strlen (s) + 1);
1018 sprintf (s, "(%s + %d)",
1022 sprintf (s, "%s", aop->aopu.aop_dir);
1023 rs = Safe_calloc (1, strlen (s) + 1);
1029 return aop->aopu.aop_reg[offset]->dname;
1031 return aop->aopu.aop_reg[offset]->name;
1034 emitcode ("clr", "a");
1035 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1036 emitcode ("rlc", "a");
1037 return (dname ? "acc" : "a");
1040 if (!offset && dname)
1042 return aop->aopu.aop_str[offset];
1045 return aopLiteral (aop->aopu.aop_lit, offset);
1049 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1053 return aop->aopu.aop_str[offset];
1057 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1058 "aopget got unsupported aop->type");
1061 /*-----------------------------------------------------------------*/
1062 /* aopPut - puts a string for a aop */
1063 /*-----------------------------------------------------------------*/
1065 aopPut (asmop * aop, char *s, int offset)
1069 if (aop->size && offset > (aop->size - 1))
1071 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1072 "aopPut got offset > aop->size");
1076 /* will assign value to value */
1077 /* depending on where it is ofcourse */
1082 sprintf (d, "(%s + %d)",
1083 aop->aopu.aop_dir, offset);
1085 sprintf (d, "%s", aop->aopu.aop_dir);
1088 emitcode ("mov", "%s,%s", d, s);
1093 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1094 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1097 strcmp (s, "r0") == 0 ||
1098 strcmp (s, "r1") == 0 ||
1099 strcmp (s, "r2") == 0 ||
1100 strcmp (s, "r3") == 0 ||
1101 strcmp (s, "r4") == 0 ||
1102 strcmp (s, "r5") == 0 ||
1103 strcmp (s, "r6") == 0 ||
1104 strcmp (s, "r7") == 0)
1105 emitcode ("mov", "%s,%s",
1106 aop->aopu.aop_reg[offset]->dname, s);
1108 emitcode ("mov", "%s,%s",
1109 aop->aopu.aop_reg[offset]->name, s);
1116 if (aop->type == AOP_DPTR2)
1124 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1125 "aopPut writting to code space");
1129 while (offset > aop->coff)
1132 emitcode ("inc", "dptr");
1135 while (offset < aop->coff)
1138 emitcode ("lcall", "__decdptr");
1143 /* if not in accumulater */
1146 emitcode ("movx", "@dptr,a");
1148 if (aop->type == AOP_DPTR2)
1156 while (offset > aop->coff)
1159 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1161 while (offset < aop->coff)
1164 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1171 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1177 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1179 else if (strcmp (s, "r0") == 0 ||
1180 strcmp (s, "r1") == 0 ||
1181 strcmp (s, "r2") == 0 ||
1182 strcmp (s, "r3") == 0 ||
1183 strcmp (s, "r4") == 0 ||
1184 strcmp (s, "r5") == 0 ||
1185 strcmp (s, "r6") == 0 ||
1186 strcmp (s, "r7") == 0)
1189 sprintf (buffer, "a%s", s);
1190 emitcode ("mov", "@%s,%s",
1191 aop->aopu.aop_ptr->name, buffer);
1194 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1199 if (strcmp (s, "a") == 0)
1200 emitcode ("push", "acc");
1202 emitcode ("push", "%s", s);
1207 /* if bit variable */
1208 if (!aop->aopu.aop_dir)
1210 emitcode ("clr", "a");
1211 emitcode ("rlc", "a");
1216 emitcode ("clr", "%s", aop->aopu.aop_dir);
1218 emitcode ("setb", "%s", aop->aopu.aop_dir);
1219 else if (!strcmp (s, "c"))
1220 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1223 if (strcmp (s, "a"))
1227 #if 0 // jwk: I am not 1000% sure
1229 symbol *lbl = newiTempLabel (NULL);
1230 emitcode ("clr", "c");
1231 emitcode ("jz", "%05d$", lbl->key + 100);
1232 emitcode ("cpl", "c");
1233 emitcode ("", "%05d$:", lbl->key + 100);
1234 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1237 emitcode ("mov", "%s,acc.0", aop->aopu.aop_dir);
1245 if (strcmp (aop->aopu.aop_str[offset], s))
1246 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1251 if (!offset && (strcmp (s, "acc") == 0))
1254 if (strcmp (aop->aopu.aop_str[offset], s))
1255 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1260 "aopPut got unsupported aop->type");
1267 /*--------------------------------------------------------------------*/
1268 /* reAdjustPreg - points a register back to where it should (coff==0) */
1269 /*--------------------------------------------------------------------*/
1271 reAdjustPreg (asmop * aop)
1273 if ((aop->coff==0) || (aop->size <= 1)) {
1282 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1286 if (aop->type == AOP_DPTR2)
1293 emitcode ("lcall", "__decdptr");
1296 if (aop->type == AOP_DPTR2)
1306 #define AOP(op) op->aop
1307 #define AOP_TYPE(op) AOP(op)->type
1308 #define AOP_SIZE(op) AOP(op)->size
1309 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1310 AOP_TYPE(x) == AOP_R0))
1312 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1313 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1316 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1317 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1318 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1320 /* Workaround for DS80C390 bug: div ab may return bogus results
1321 * if A is accessed in instruction immediately before the div.
1323 * Will be fixed in B4 rev of processor, Dallas claims.
1326 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1327 if (!AOP_NEEDSACC(RIGHT)) \
1329 /* We can load A first, then B, since \
1330 * B (the RIGHT operand) won't clobber A, \
1331 * thus avoiding touching A right before the div. \
1333 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1334 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1336 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1340 /* Just stuff in a nop after loading A. */ \
1341 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1342 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1344 emitcode("nop", "; workaround for DS80C390 div bug."); \
1347 /*-----------------------------------------------------------------*/
1348 /* genNotFloat - generates not for float operations */
1349 /*-----------------------------------------------------------------*/
1351 genNotFloat (operand * op, operand * res)
1357 D (emitcode (";", "genNotFloat ");
1360 /* we will put 127 in the first byte of
1362 aopPut (AOP (res), "#127", 0);
1363 size = AOP_SIZE (op) - 1;
1366 _startLazyDPSEvaluation ();
1367 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1372 emitcode ("orl", "a,%s",
1374 offset++, FALSE, FALSE, FALSE));
1376 _endLazyDPSEvaluation ();
1377 tlbl = newiTempLabel (NULL);
1379 tlbl = newiTempLabel (NULL);
1380 aopPut (res->aop, one, 1);
1381 emitcode ("jz", "%05d$", (tlbl->key + 100));
1382 aopPut (res->aop, zero, 1);
1383 emitcode ("", "%05d$:", (tlbl->key + 100));
1385 size = res->aop->size - 2;
1387 /* put zeros in the rest */
1389 aopPut (res->aop, zero, offset++);
1392 /*-----------------------------------------------------------------*/
1393 /* opIsGptr: returns non-zero if the passed operand is */
1394 /* a generic pointer type. */
1395 /*-----------------------------------------------------------------*/
1397 opIsGptr (operand * op)
1399 sym_link *type = operandType (op);
1401 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1408 /*-----------------------------------------------------------------*/
1409 /* getDataSize - get the operand data size */
1410 /*-----------------------------------------------------------------*/
1412 getDataSize (operand * op)
1415 size = AOP_SIZE (op);
1416 if (size == GPTRSIZE)
1418 sym_link *type = operandType (op);
1419 if (IS_GENPTR (type))
1421 /* generic pointer; arithmetic operations
1422 * should ignore the high byte (pointer type).
1430 /*-----------------------------------------------------------------*/
1431 /* outAcc - output Acc */
1432 /*-----------------------------------------------------------------*/
1434 outAcc (operand * result)
1437 size = getDataSize (result);
1440 aopPut (AOP (result), "a", 0);
1443 /* unsigned or positive */
1446 aopPut (AOP (result), zero, offset++);
1451 /*-----------------------------------------------------------------*/
1452 /* outBitC - output a bit C */
1453 /*-----------------------------------------------------------------*/
1455 outBitC (operand * result)
1457 /* if the result is bit */
1458 if (AOP_TYPE (result) == AOP_CRY)
1460 aopPut (AOP (result), "c", 0);
1464 emitcode ("clr", "a");
1465 emitcode ("rlc", "a");
1470 /*-----------------------------------------------------------------*/
1471 /* toBoolean - emit code for orl a,operator(sizeop) */
1472 /*-----------------------------------------------------------------*/
1474 toBoolean (operand * oper)
1476 int size = AOP_SIZE (oper) - 1;
1479 /* The generic part of a generic pointer should
1480 * not participate in it's truth value.
1482 * i.e. 0x10000000 is zero.
1484 if (opIsGptr (oper))
1486 D (emitcode (";", "toBoolean: generic ptr special case.");
1491 _startLazyDPSEvaluation ();
1492 if (AOP_NEEDSACC (oper))
1494 emitcode ("push", "b");
1495 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1499 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1503 if (AOP_NEEDSACC (oper))
1505 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1509 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1512 _endLazyDPSEvaluation ();
1514 if (AOP_NEEDSACC (oper))
1516 emitcode ("mov", "a,b");
1517 emitcode ("pop", "b");
1522 /*-----------------------------------------------------------------*/
1523 /* genNot - generate code for ! operation */
1524 /*-----------------------------------------------------------------*/
1529 sym_link *optype = operandType (IC_LEFT (ic));
1531 D (emitcode (";", "genNot ");
1534 /* assign asmOps to operand & result */
1535 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1536 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1538 /* if in bit space then a special case */
1539 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1541 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1542 emitcode ("cpl", "c");
1543 outBitC (IC_RESULT (ic));
1547 /* if type float then do float */
1548 if (IS_FLOAT (optype))
1550 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1554 toBoolean (IC_LEFT (ic));
1556 tlbl = newiTempLabel (NULL);
1557 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1558 emitcode ("", "%05d$:", tlbl->key + 100);
1559 outBitC (IC_RESULT (ic));
1562 /* release the aops */
1563 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1564 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1568 /*-----------------------------------------------------------------*/
1569 /* genCpl - generate code for complement */
1570 /*-----------------------------------------------------------------*/
1577 D (emitcode (";", "genCpl ");
1581 /* assign asmOps to operand & result */
1582 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1585 /* if both are in bit space then
1587 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1588 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1591 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1592 emitcode ("cpl", "c");
1593 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1597 size = AOP_SIZE (IC_RESULT (ic));
1598 _startLazyDPSEvaluation ();
1601 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1603 emitcode ("cpl", "a");
1604 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1606 _endLazyDPSEvaluation ();
1610 /* release the aops */
1611 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1612 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* genUminusFloat - unary minus for floating points */
1617 /*-----------------------------------------------------------------*/
1619 genUminusFloat (operand * op, operand * result)
1621 int size, offset = 0;
1623 /* for this we just need to flip the
1624 first it then copy the rest in place */
1625 D (emitcode (";", "genUminusFloat");
1628 _startLazyDPSEvaluation ();
1629 size = AOP_SIZE (op) - 1;
1630 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1633 emitcode ("cpl", "acc.7");
1634 aopPut (AOP (result), "a", 3);
1638 aopPut (AOP (result),
1639 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1643 _endLazyDPSEvaluation ();
1646 /*-----------------------------------------------------------------*/
1647 /* genUminus - unary minus code generation */
1648 /*-----------------------------------------------------------------*/
1650 genUminus (iCode * ic)
1653 sym_link *optype, *rtype;
1655 D (emitcode (";", "genUminus ");
1660 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1661 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1663 /* if both in bit space then special
1665 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1666 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1669 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1670 emitcode ("cpl", "c");
1671 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1675 optype = operandType (IC_LEFT (ic));
1676 rtype = operandType (IC_RESULT (ic));
1678 /* if float then do float stuff */
1679 if (IS_FLOAT (optype))
1681 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1685 /* otherwise subtract from zero */
1686 size = AOP_SIZE (IC_LEFT (ic));
1688 _startLazyDPSEvaluation ();
1691 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1692 if (!strcmp (l, "a"))
1696 emitcode ("cpl", "a");
1697 emitcode ("addc", "a,#0");
1703 emitcode ("clr", "a");
1704 emitcode ("subb", "a,%s", l);
1706 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1708 _endLazyDPSEvaluation ();
1710 /* if any remaining bytes in the result */
1711 /* we just need to propagate the sign */
1712 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1714 emitcode ("rlc", "a");
1715 emitcode ("subb", "a,acc");
1717 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1721 /* release the aops */
1722 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1723 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1726 /*-----------------------------------------------------------------*/
1727 /* saveRegisters - will look for a call and save the registers */
1728 /*-----------------------------------------------------------------*/
1730 saveRegisters (iCode * lic)
1738 for (ic = lic; ic; ic = ic->next)
1739 if (ic->op == CALL || ic->op == PCALL)
1744 fprintf (stderr, "found parameter push with no function call\n");
1748 /* if the registers have been saved already then
1750 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1753 /* find the registers in use at this time
1754 and push them away to safety */
1755 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1759 if (options.useXstack)
1761 if (bitVectBitValue (rsave, R0_IDX))
1762 emitcode ("mov", "b,r0");
1763 emitcode ("mov", "r0,%s", spname);
1764 for (i = 0; i < ds390_nRegs; i++)
1766 if (bitVectBitValue (rsave, i))
1769 emitcode ("mov", "a,b");
1771 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1772 emitcode ("movx", "@r0,a");
1773 emitcode ("inc", "r0");
1776 emitcode ("mov", "%s,r0", spname);
1777 if (bitVectBitValue (rsave, R0_IDX))
1778 emitcode ("mov", "r0,b");
1781 for (i = 0; i < ds390_nRegs; i++)
1783 if (bitVectBitValue (rsave, i))
1784 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1787 detype = getSpec (operandType (IC_LEFT (ic)));
1789 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1790 IS_ISR (currFunc->etype) &&
1793 saverbank (SPEC_BANK (detype), ic, TRUE);
1796 /*-----------------------------------------------------------------*/
1797 /* unsaveRegisters - pop the pushed registers */
1798 /*-----------------------------------------------------------------*/
1800 unsaveRegisters (iCode * ic)
1804 /* find the registers in use at this time
1805 and push them away to safety */
1806 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1809 if (options.useXstack)
1811 emitcode ("mov", "r0,%s", spname);
1812 for (i = ds390_nRegs; i >= 0; i--)
1814 if (bitVectBitValue (rsave, i))
1816 emitcode ("dec", "r0");
1817 emitcode ("movx", "a,@r0");
1819 emitcode ("mov", "b,a");
1821 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1825 emitcode ("mov", "%s,r0", spname);
1826 if (bitVectBitValue (rsave, R0_IDX))
1827 emitcode ("mov", "r0,b");
1830 for (i = ds390_nRegs; i >= 0; i--)
1832 if (bitVectBitValue (rsave, i))
1833 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1839 /*-----------------------------------------------------------------*/
1841 /*-----------------------------------------------------------------*/
1843 pushSide (operand * oper, int size)
1846 _startLazyDPSEvaluation ();
1849 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1850 if (AOP_TYPE (oper) != AOP_REG &&
1851 AOP_TYPE (oper) != AOP_DIR &&
1854 emitcode ("mov", "a,%s", l);
1855 emitcode ("push", "acc");
1858 emitcode ("push", "%s", l);
1860 _endLazyDPSEvaluation ();
1863 /*-----------------------------------------------------------------*/
1864 /* assignResultValue - */
1865 /*-----------------------------------------------------------------*/
1867 assignResultValue (operand * oper)
1870 int size = AOP_SIZE (oper);
1872 _startLazyDPSEvaluation ();
1875 aopPut (AOP (oper), fReturn[offset], offset);
1878 _endLazyDPSEvaluation ();
1882 /*-----------------------------------------------------------------*/
1883 /* genXpush - pushes onto the external stack */
1884 /*-----------------------------------------------------------------*/
1886 genXpush (iCode * ic)
1888 asmop *aop = newAsmop (0);
1890 int size, offset = 0;
1892 D (emitcode (";", "genXpush ");
1895 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1896 r = getFreePtr (ic, &aop, FALSE);
1899 emitcode ("mov", "%s,_spx", r->name);
1901 size = AOP_SIZE (IC_LEFT (ic));
1902 _startLazyDPSEvaluation ();
1906 char *l = aopGet (AOP (IC_LEFT (ic)),
1907 offset++, FALSE, FALSE, TRUE);
1909 emitcode ("movx", "@%s,a", r->name);
1910 emitcode ("inc", "%s", r->name);
1913 _endLazyDPSEvaluation ();
1916 emitcode ("mov", "_spx,%s", r->name);
1918 freeAsmop (NULL, aop, ic, TRUE);
1919 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1922 /*-----------------------------------------------------------------*/
1923 /* genIpush - genrate code for pushing this gets a little complex */
1924 /*-----------------------------------------------------------------*/
1926 genIpush (iCode * ic)
1928 int size, offset = 0;
1931 D (emitcode (";", "genIpush ");
1934 /* if this is not a parm push : ie. it is spill push
1935 and spill push is always done on the local stack */
1939 /* and the item is spilt then do nothing */
1940 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1943 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1944 size = AOP_SIZE (IC_LEFT (ic));
1945 /* push it on the stack */
1946 _startLazyDPSEvaluation ();
1949 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1955 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1957 _endLazyDPSEvaluation ();
1961 /* this is a paramter push: in this case we call
1962 the routine to find the call and save those
1963 registers that need to be saved */
1966 /* if use external stack then call the external
1967 stack pushing routine */
1968 if (options.useXstack)
1974 /* then do the push */
1975 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1977 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1978 size = AOP_SIZE (IC_LEFT (ic));
1980 _startLazyDPSEvaluation ();
1983 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1984 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1985 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1988 emitcode ("mov", "a,%s", l);
1989 emitcode ("push", "acc");
1992 emitcode ("push", "%s ;jwk genIpush", l);
1994 _endLazyDPSEvaluation ();
1996 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1999 /*-----------------------------------------------------------------*/
2000 /* genIpop - recover the registers: can happen only for spilling */
2001 /*-----------------------------------------------------------------*/
2003 genIpop (iCode * ic)
2007 D (emitcode (";", "genIpop ");
2011 /* if the temp was not pushed then */
2012 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2015 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2016 size = AOP_SIZE (IC_LEFT (ic));
2017 offset = (size - 1);
2018 _startLazyDPSEvaluation ();
2021 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2022 FALSE, TRUE, TRUE));
2024 _endLazyDPSEvaluation ();
2026 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2029 /*-----------------------------------------------------------------*/
2030 /* unsaverbank - restores the resgister bank from stack */
2031 /*-----------------------------------------------------------------*/
2033 unsaverbank (int bank, iCode * ic, bool popPsw)
2041 if (options.useXstack)
2044 r = getFreePtr (ic, &aop, FALSE);
2047 emitcode ("mov", "%s,_spx", r->name);
2048 emitcode ("movx", "a,@%s", r->name);
2049 emitcode ("mov", "psw,a");
2050 emitcode ("dec", "%s", r->name);
2054 emitcode ("pop", "psw");
2057 for (i = (ds390_nRegs - 1); i >= 0; i--)
2059 if (options.useXstack)
2061 emitcode ("movx", "a,@%s", r->name);
2062 emitcode ("mov", "(%s+%d),a",
2063 regs390[i].base, 8 * bank + regs390[i].offset);
2064 emitcode ("dec", "%s", r->name);
2068 emitcode ("pop", "(%s+%d)",
2069 regs390[i].base, 8 * bank + regs390[i].offset);
2072 if (options.useXstack)
2075 emitcode ("mov", "_spx,%s", r->name);
2076 freeAsmop (NULL, aop, ic, TRUE);
2081 /*-----------------------------------------------------------------*/
2082 /* saverbank - saves an entire register bank on the stack */
2083 /*-----------------------------------------------------------------*/
2085 saverbank (int bank, iCode * ic, bool pushPsw)
2091 if (options.useXstack)
2095 r = getFreePtr (ic, &aop, FALSE);
2096 emitcode ("mov", "%s,_spx", r->name);
2100 for (i = 0; i < ds390_nRegs; i++)
2102 if (options.useXstack)
2104 emitcode ("inc", "%s", r->name);
2105 emitcode ("mov", "a,(%s+%d)",
2106 regs390[i].base, 8 * bank + regs390[i].offset);
2107 emitcode ("movx", "@%s,a", r->name);
2110 emitcode ("push", "(%s+%d)",
2111 regs390[i].base, 8 * bank + regs390[i].offset);
2116 if (options.useXstack)
2118 emitcode ("mov", "a,psw");
2119 emitcode ("movx", "@%s,a", r->name);
2120 emitcode ("inc", "%s", r->name);
2121 emitcode ("mov", "_spx,%s", r->name);
2122 freeAsmop (NULL, aop, ic, TRUE);
2126 emitcode ("push", "psw");
2128 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2134 /*-----------------------------------------------------------------*/
2135 /* genCall - generates a call statement */
2136 /*-----------------------------------------------------------------*/
2138 genCall (iCode * ic)
2142 D (emitcode (";", "genCall ");
2145 /* if caller saves & we have not saved then */
2149 /* if we are calling a function that is not using
2150 the same register bank then we need to save the
2151 destination registers on the stack */
2152 detype = getSpec (operandType (IC_LEFT (ic)));
2154 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2155 IS_ISR (currFunc->etype) &&
2158 saverbank (SPEC_BANK (detype), ic, TRUE);
2160 /* if send set is not empty the assign */
2165 for (sic = setFirstItem (_G.sendSet); sic;
2166 sic = setNextItem (_G.sendSet))
2168 int size, offset = 0;
2170 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2171 size = AOP_SIZE (IC_LEFT (sic));
2173 _startLazyDPSEvaluation ();
2176 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2177 FALSE, FALSE, TRUE);
2178 if (strcmp (l, fReturn[offset])) {
2181 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2187 _endLazyDPSEvaluation ();
2188 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2193 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2194 OP_SYMBOL (IC_LEFT (ic))->rname :
2195 OP_SYMBOL (IC_LEFT (ic))->name));
2197 /* if we need assign a result value */
2198 if ((IS_ITEMP (IC_RESULT (ic)) &&
2199 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2200 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2201 IS_TRUE_SYMOP (IC_RESULT (ic)))
2203 if (isOperandInFarSpace (IC_RESULT (ic))
2204 && getSize (operandType (IC_RESULT (ic))) <= 2)
2206 int size = getSize (operandType (IC_RESULT (ic)));
2208 /* Special case for 1 or 2 byte return in far space. */
2209 emitcode (";", "Kevin function call abuse #1");
2214 emitcode ("mov", "b,%s", fReturn[1]);
2217 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2218 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2222 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2224 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2229 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2232 assignResultValue (IC_RESULT (ic));
2234 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2238 /* adjust the stack for parameters if
2243 if (ic->parmBytes > 3)
2245 emitcode ("mov", "a,%s", spname);
2246 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2247 emitcode ("mov", "%s,a", spname);
2250 for (i = 0; i < ic->parmBytes; i++)
2251 emitcode ("dec", "%s", spname);
2255 /* if register bank was saved then pop them */
2257 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2259 /* if we hade saved some registers then unsave them */
2260 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2261 unsaveRegisters (ic);
2266 /*-----------------------------------------------------------------*/
2267 /* genPcall - generates a call by pointer statement */
2268 /*-----------------------------------------------------------------*/
2270 genPcall (iCode * ic)
2273 symbol *rlbl = newiTempLabel (NULL);
2275 D (emitcode (";", "genPcall ");
2279 /* if caller saves & we have not saved then */
2283 /* if we are calling a function that is not using
2284 the same register bank then we need to save the
2285 destination registers on the stack */
2286 detype = getSpec (operandType (IC_LEFT (ic)));
2288 IS_ISR (currFunc->etype) &&
2289 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2290 saverbank (SPEC_BANK (detype), ic, TRUE);
2293 /* push the return address on to the stack */
2294 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2295 emitcode ("push", "acc");
2296 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2297 emitcode ("push", "acc");
2299 if (options.model == MODEL_FLAT24)
2301 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2302 emitcode ("push", "acc");
2305 /* now push the calling address */
2306 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2308 pushSide (IC_LEFT (ic), FPTRSIZE);
2310 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2312 /* if send set is not empty the assign */
2317 for (sic = setFirstItem (_G.sendSet); sic;
2318 sic = setNextItem (_G.sendSet))
2320 int size, offset = 0;
2322 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2323 size = AOP_SIZE (IC_LEFT (sic));
2324 _startLazyDPSEvaluation ();
2327 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2328 FALSE, FALSE, TRUE);
2329 if (strcmp (l, fReturn[offset]))
2331 emitcode ("mov", "%s,%s",
2337 _endLazyDPSEvaluation ();
2338 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2343 emitcode ("ret", "");
2344 emitcode ("", "%05d$:", (rlbl->key + 100));
2347 /* if we need assign a result value */
2348 if ((IS_ITEMP (IC_RESULT (ic)) &&
2349 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2350 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2351 IS_TRUE_SYMOP (IC_RESULT (ic)))
2355 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2358 assignResultValue (IC_RESULT (ic));
2360 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2363 /* adjust the stack for parameters if
2368 if (ic->parmBytes > 3)
2370 emitcode ("mov", "a,%s", spname);
2371 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2372 emitcode ("mov", "%s,a", spname);
2375 for (i = 0; i < ic->parmBytes; i++)
2376 emitcode ("dec", "%s", spname);
2380 /* if register bank was saved then unsave them */
2382 (SPEC_BANK (currFunc->etype) !=
2383 SPEC_BANK (detype)))
2384 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2386 /* if we hade saved some registers then
2389 unsaveRegisters (ic);
2393 /*-----------------------------------------------------------------*/
2394 /* resultRemat - result is rematerializable */
2395 /*-----------------------------------------------------------------*/
2397 resultRemat (iCode * ic)
2399 if (SKIP_IC (ic) || ic->op == IFX)
2402 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2404 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2405 if (sym->remat && !POINTER_SET (ic))
2412 #if defined(__BORLANDC__) || defined(_MSC_VER)
2413 #define STRCASECMP stricmp
2415 #define STRCASECMP strcasecmp
2418 /*-----------------------------------------------------------------*/
2419 /* inExcludeList - return 1 if the string is in exclude Reg list */
2420 /*-----------------------------------------------------------------*/
2422 inExcludeList (char *s)
2426 if (options.excludeRegs[i] &&
2427 STRCASECMP (options.excludeRegs[i], "none") == 0)
2430 for (i = 0; options.excludeRegs[i]; i++)
2432 if (options.excludeRegs[i] &&
2433 STRCASECMP (s, options.excludeRegs[i]) == 0)
2439 /*-----------------------------------------------------------------*/
2440 /* genFunction - generated code for function entry */
2441 /*-----------------------------------------------------------------*/
2443 genFunction (iCode * ic)
2448 D (emitcode (";", "genFunction ");
2452 /* create the function header */
2453 emitcode (";", "-----------------------------------------");
2454 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2455 emitcode (";", "-----------------------------------------");
2457 emitcode ("", "%s:", sym->rname);
2458 fetype = getSpec (operandType (IC_LEFT (ic)));
2460 /* if critical function then turn interrupts off */
2461 if (SPEC_CRTCL (fetype))
2462 emitcode ("clr", "ea");
2464 /* here we need to generate the equates for the
2465 register bank if required */
2466 if (SPEC_BANK (fetype) != rbank)
2470 rbank = SPEC_BANK (fetype);
2471 for (i = 0; i < ds390_nRegs; i++)
2473 if (strcmp (regs390[i].base, "0") == 0)
2474 emitcode ("", "%s = 0x%02x",
2476 8 * rbank + regs390[i].offset);
2478 emitcode ("", "%s = %s + 0x%02x",
2481 8 * rbank + regs390[i].offset);
2485 /* if this is an interrupt service routine then
2486 save acc, b, dpl, dph */
2487 if (IS_ISR (sym->etype))
2490 if (!inExcludeList ("acc"))
2491 emitcode ("push", "acc");
2492 if (!inExcludeList ("b"))
2493 emitcode ("push", "b");
2494 if (!inExcludeList ("dpl"))
2495 emitcode ("push", "dpl");
2496 if (!inExcludeList ("dph"))
2497 emitcode ("push", "dph");
2498 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2500 emitcode ("push", "dpx");
2501 /* Make sure we're using standard DPTR */
2502 emitcode ("push", "dps");
2503 emitcode ("mov", "dps, #0x00");
2504 if (options.stack10bit)
2506 /* This ISR could conceivably use DPTR2. Better save it. */
2507 emitcode ("push", "dpl1");
2508 emitcode ("push", "dph1");
2509 emitcode ("push", "dpx1");
2510 emitcode ("push", "ap");
2513 /* if this isr has no bank i.e. is going to
2514 run with bank 0 , then we need to save more
2516 if (!SPEC_BANK (sym->etype))
2519 /* if this function does not call any other
2520 function then we can be economical and
2521 save only those registers that are used */
2526 /* if any registers used */
2529 /* save the registers used */
2530 for (i = 0; i < sym->regsUsed->size; i++)
2532 if (bitVectBitValue (sym->regsUsed, i) ||
2533 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2534 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2541 /* this function has a function call cannot
2542 determines register usage so we will have the
2544 saverbank (0, ic, FALSE);
2550 /* if callee-save to be used for this function
2551 then save the registers being used in this function */
2552 if (sym->calleeSave)
2556 /* if any registers used */
2559 /* save the registers used */
2560 for (i = 0; i < sym->regsUsed->size; i++)
2562 if (bitVectBitValue (sym->regsUsed, i) ||
2563 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2565 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2573 /* set the register bank to the desired value */
2574 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2576 emitcode ("push", "psw");
2577 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2580 if (IS_RENT (sym->etype) || options.stackAuto)
2583 if (options.useXstack)
2585 emitcode ("mov", "r0,%s", spname);
2586 emitcode ("mov", "a,_bp");
2587 emitcode ("movx", "@r0,a");
2588 emitcode ("inc", "%s", spname);
2592 /* set up the stack */
2593 emitcode ("push", "_bp"); /* save the callers stack */
2595 emitcode ("mov", "_bp,%s", spname);
2598 /* adjust the stack for the function */
2604 werror (W_STACK_OVERFLOW, sym->name);
2606 if (i > 3 && sym->recvSize < 4)
2609 emitcode ("mov", "a,sp");
2610 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2611 emitcode ("mov", "sp,a");
2616 emitcode ("inc", "sp");
2622 emitcode ("mov", "a,_spx");
2623 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2624 emitcode ("mov", "_spx,a");
2629 /*-----------------------------------------------------------------*/
2630 /* genEndFunction - generates epilogue for functions */
2631 /*-----------------------------------------------------------------*/
2633 genEndFunction (iCode * ic)
2635 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2637 D (emitcode (";", "genEndFunction ");
2640 if (IS_RENT (sym->etype) || options.stackAuto)
2642 emitcode ("mov", "%s,_bp", spname);
2645 /* if use external stack but some variables were
2646 added to the local stack then decrement the
2648 if (options.useXstack && sym->stack)
2650 emitcode ("mov", "a,sp");
2651 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2652 emitcode ("mov", "sp,a");
2656 if ((IS_RENT (sym->etype) || options.stackAuto))
2658 if (options.useXstack)
2660 emitcode ("mov", "r0,%s", spname);
2661 emitcode ("movx", "a,@r0");
2662 emitcode ("mov", "_bp,a");
2663 emitcode ("dec", "%s", spname);
2667 emitcode ("pop", "_bp");
2671 /* restore the register bank */
2672 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2673 emitcode ("pop", "psw");
2675 if (IS_ISR (sym->etype))
2678 /* now we need to restore the registers */
2679 /* if this isr has no bank i.e. is going to
2680 run with bank 0 , then we need to save more
2682 if (!SPEC_BANK (sym->etype))
2685 /* if this function does not call any other
2686 function then we can be economical and
2687 save only those registers that are used */
2692 /* if any registers used */
2695 /* save the registers used */
2696 for (i = sym->regsUsed->size; i >= 0; i--)
2698 if (bitVectBitValue (sym->regsUsed, i) ||
2699 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2700 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2707 /* this function has a function call cannot
2708 determines register usage so we will have the
2710 unsaverbank (0, ic, FALSE);
2714 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2716 if (options.stack10bit)
2718 emitcode ("pop", "ap");
2719 emitcode ("pop", "dpx1");
2720 emitcode ("pop", "dph1");
2721 emitcode ("pop", "dpl1");
2723 emitcode ("pop", "dps");
2724 emitcode ("pop", "dpx");
2726 if (!inExcludeList ("dph"))
2727 emitcode ("pop", "dph");
2728 if (!inExcludeList ("dpl"))
2729 emitcode ("pop", "dpl");
2730 if (!inExcludeList ("b"))
2731 emitcode ("pop", "b");
2732 if (!inExcludeList ("acc"))
2733 emitcode ("pop", "acc");
2735 if (SPEC_CRTCL (sym->etype))
2736 emitcode ("setb", "ea");
2738 /* if debug then send end of function */
2739 /* if (options.debug && currFunc) { */
2743 emitcode ("", "C$%s$%d$%d$%d ==.",
2744 FileBaseName (ic->filename), currFunc->lastLine,
2745 ic->level, ic->block);
2746 if (IS_STATIC (currFunc->etype))
2747 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2749 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2753 emitcode ("reti", "");
2757 if (SPEC_CRTCL (sym->etype))
2758 emitcode ("setb", "ea");
2760 if (sym->calleeSave)
2764 /* if any registers used */
2767 /* save the registers used */
2768 for (i = sym->regsUsed->size; i >= 0; i--)
2770 if (bitVectBitValue (sym->regsUsed, i) ||
2771 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2772 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2778 /* if debug then send end of function */
2782 emitcode ("", "C$%s$%d$%d$%d ==.",
2783 FileBaseName (ic->filename), currFunc->lastLine,
2784 ic->level, ic->block);
2785 if (IS_STATIC (currFunc->etype))
2786 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2788 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2792 emitcode ("ret", "");
2797 /*-----------------------------------------------------------------*/
2798 /* genRet - generate code for return statement */
2799 /*-----------------------------------------------------------------*/
2803 int size, offset = 0, pushed = 0;
2805 D (emitcode (";", "genRet ");
2808 /* if we have no return value then
2809 just generate the "ret" */
2813 /* we have something to return then
2814 move the return value into place */
2815 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2816 size = AOP_SIZE (IC_LEFT (ic));
2818 _startLazyDPSEvaluation ();
2822 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2824 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2825 FALSE, TRUE, FALSE);
2826 emitcode ("push", "%s", l);
2831 l = aopGet (AOP (IC_LEFT (ic)), offset,
2832 FALSE, FALSE, FALSE);
2833 if (strcmp (fReturn[offset], l))
2834 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2837 _endLazyDPSEvaluation ();
2844 if (strcmp (fReturn[pushed], "a"))
2845 emitcode ("pop", fReturn[pushed]);
2847 emitcode ("pop", "acc");
2850 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2853 /* generate a jump to the return label
2854 if the next is not the return statement */
2855 if (!(ic->next && ic->next->op == LABEL &&
2856 IC_LABEL (ic->next) == returnLabel))
2858 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2862 /*-----------------------------------------------------------------*/
2863 /* genLabel - generates a label */
2864 /*-----------------------------------------------------------------*/
2866 genLabel (iCode * ic)
2868 /* special case never generate */
2869 if (IC_LABEL (ic) == entryLabel)
2872 D (emitcode (";", "genLabel ");
2875 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2878 /*-----------------------------------------------------------------*/
2879 /* genGoto - generates a ljmp */
2880 /*-----------------------------------------------------------------*/
2882 genGoto (iCode * ic)
2884 D (emitcode (";", "genGoto ");
2886 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2889 /*-----------------------------------------------------------------*/
2890 /* findLabelBackwards: walks back through the iCode chain looking */
2891 /* for the given label. Returns number of iCode instructions */
2892 /* between that label and given ic. */
2893 /* Returns zero if label not found. */
2894 /*-----------------------------------------------------------------*/
2896 findLabelBackwards (iCode * ic, int key)
2905 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2907 /* printf("findLabelBackwards = %d\n", count); */
2915 /*-----------------------------------------------------------------*/
2916 /* genPlusIncr :- does addition with increment if possible */
2917 /*-----------------------------------------------------------------*/
2919 genPlusIncr (iCode * ic)
2921 unsigned int icount;
2922 unsigned int size = getDataSize (IC_RESULT (ic));
2924 /* will try to generate an increment */
2925 /* if the right side is not a literal
2927 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2930 /* if the literal value of the right hand side
2931 is greater than 4 then it is not worth it */
2932 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2935 /* if increment 16 bits in register */
2937 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2938 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2939 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2947 /* If the next instruction is a goto and the goto target
2948 * is <= 5 instructions previous to this, we can generate
2949 * jumps straight to that target.
2951 if (ic->next && ic->next->op == GOTO
2952 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2955 emitcode (";", "tail increment optimized (range %d)", labelRange);
2956 tlbl = IC_LABEL (ic->next);
2961 tlbl = newiTempLabel (NULL);
2964 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2965 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2966 IS_AOP_PREG (IC_RESULT (ic)))
2967 emitcode ("cjne", "%s,#0x00,%05d$"
2968 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2972 emitcode ("clr", "a");
2973 emitcode ("cjne", "a,%s,%05d$"
2974 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2978 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2981 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2982 IS_AOP_PREG (IC_RESULT (ic)))
2983 emitcode ("cjne", "%s,#0x00,%05d$"
2984 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2987 emitcode ("cjne", "a,%s,%05d$"
2988 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2991 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2995 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2996 IS_AOP_PREG (IC_RESULT (ic)))
2997 emitcode ("cjne", "%s,#0x00,%05d$"
2998 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3002 emitcode ("cjne", "a,%s,%05d$"
3003 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3006 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3011 emitcode ("", "%05d$:", tlbl->key + 100);
3016 /* if the sizes are greater than 1 then we cannot */
3017 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3018 AOP_SIZE (IC_LEFT (ic)) > 1)
3021 /* we can if the aops of the left & result match or
3022 if they are in registers and the registers are the
3025 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3026 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3027 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3032 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3033 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3034 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3039 _startLazyDPSEvaluation ();
3042 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3044 _endLazyDPSEvaluation ();
3053 /*-----------------------------------------------------------------*/
3054 /* outBitAcc - output a bit in acc */
3055 /*-----------------------------------------------------------------*/
3057 outBitAcc (operand * result)
3059 symbol *tlbl = newiTempLabel (NULL);
3060 /* if the result is a bit */
3061 if (AOP_TYPE (result) == AOP_CRY)
3063 aopPut (AOP (result), "a", 0);
3067 emitcode ("jz", "%05d$", tlbl->key + 100);
3068 emitcode ("mov", "a,%s", one);
3069 emitcode ("", "%05d$:", tlbl->key + 100);
3074 /*-----------------------------------------------------------------*/
3075 /* genPlusBits - generates code for addition of two bits */
3076 /*-----------------------------------------------------------------*/
3078 genPlusBits (iCode * ic)
3080 D (emitcode (";", "genPlusBits ");
3082 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3084 symbol *lbl = newiTempLabel (NULL);
3085 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3086 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3087 emitcode ("cpl", "c");
3088 emitcode ("", "%05d$:", (lbl->key + 100));
3089 outBitC (IC_RESULT (ic));
3093 emitcode ("clr", "a");
3094 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095 emitcode ("rlc", "a");
3096 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3097 emitcode ("addc", "a,#0x00");
3098 outAcc (IC_RESULT (ic));
3103 adjustArithmeticResult (iCode * ic)
3105 if (opIsGptr (IC_RESULT (ic)) &&
3106 opIsGptr (IC_LEFT (ic)) &&
3107 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3109 aopPut (AOP (IC_RESULT (ic)),
3110 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3114 if (opIsGptr (IC_RESULT (ic)) &&
3115 opIsGptr (IC_RIGHT (ic)) &&
3116 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3118 aopPut (AOP (IC_RESULT (ic)),
3119 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3123 if (opIsGptr (IC_RESULT (ic)) &&
3124 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3125 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3126 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3127 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3130 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3131 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3135 #define AOP_OP_3(ic) \
3136 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3137 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3138 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3139 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3140 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3141 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3143 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3145 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3148 #define AOP_OP_3_NOFATAL(ic, rc) \
3149 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3150 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3151 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3152 isOperandInFarSpace(IC_RESULT(ic))) \
3154 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3159 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3160 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3162 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3163 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3165 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3167 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3171 #define AOP_OP_2(ic) \
3172 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3173 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3175 #define AOP_SET_LOCALS(ic) \
3176 left = IC_LEFT(ic); \
3177 right = IC_RIGHT(ic); \
3178 result = IC_RESULT(ic);
3180 /*-----------------------------------------------------------------*/
3181 /* genPlus - generates code for addition */
3182 /*-----------------------------------------------------------------*/
3184 genPlus (iCode * ic)
3186 int size, offset = 0;
3187 bool pushResult = FALSE;
3190 D (emitcode (";", "genPlus ");
3193 /* special cases :- */
3195 AOP_OP_3_NOFATAL (ic, pushResult);
3198 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3204 /* if literal, literal on the right or
3205 if left requires ACC or right is already
3207 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3208 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3209 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3211 operand *t = IC_RIGHT (ic);
3212 IC_RIGHT (ic) = IC_LEFT (ic);
3214 emitcode (";", "Swapped plus args.");
3217 /* if both left & right are in bit
3219 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3220 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3226 /* if left in bit space & right literal */
3227 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3228 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3230 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3231 /* if result in bit space */
3232 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3234 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3235 emitcode ("cpl", "c");
3236 outBitC (IC_RESULT (ic));
3240 size = getDataSize (IC_RESULT (ic));
3241 _startLazyDPSEvaluation ();
3244 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3245 emitcode ("addc", "a,#00");
3246 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3248 _endLazyDPSEvaluation ();
3253 /* if I can do an increment instead
3254 of add then GOOD for ME */
3255 if (genPlusIncr (ic) == TRUE)
3257 emitcode (";", "did genPlusIncr");
3262 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3264 _startLazyDPSEvaluation ();
3267 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3269 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3271 emitcode ("add", "a,%s",
3272 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3274 emitcode ("addc", "a,%s",
3275 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3279 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3281 emitcode ("add", "a,%s",
3282 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3284 emitcode ("addc", "a,%s",
3285 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3289 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3293 emitcode ("push", "acc");
3297 _endLazyDPSEvaluation ();
3301 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3303 size = getDataSize (IC_LEFT (ic));
3304 rSize = getDataSize (IC_RESULT (ic));
3306 /* If the pushed data is bigger than the result,
3307 * simply discard unused bytes. Icky, but works.
3309 * Should we throw a warning here? We're losing data...
3311 while (size > rSize)
3313 D (emitcode (";", "discarding unused result byte.");
3315 emitcode ("pop", "acc");
3321 emitcode ("clr", "a");
3322 /* Conversly, we haven't pushed enough here.
3323 * just zero-pad, and all is well.
3325 while (size < rSize)
3327 emitcode ("push", "acc");
3333 _startLazyDPSEvaluation ();
3336 emitcode ("pop", "acc");
3337 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3339 _endLazyDPSEvaluation ();
3342 adjustArithmeticResult (ic);
3345 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3346 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3347 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3350 /*-----------------------------------------------------------------*/
3351 /* genMinusDec :- does subtraction with deccrement if possible */
3352 /*-----------------------------------------------------------------*/
3354 genMinusDec (iCode * ic)
3356 unsigned int icount;
3357 unsigned int size = getDataSize (IC_RESULT (ic));
3359 /* will try to generate an increment */
3360 /* if the right side is not a literal
3362 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3365 /* if the literal value of the right hand side
3366 is greater than 4 then it is not worth it */
3367 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3370 /* if decrement 16 bits in register */
3371 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3372 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3373 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3381 /* If the next instruction is a goto and the goto target
3382 * is <= 5 instructions previous to this, we can generate
3383 * jumps straight to that target.
3385 if (ic->next && ic->next->op == GOTO
3386 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3389 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3390 tlbl = IC_LABEL (ic->next);
3395 tlbl = newiTempLabel (NULL);
3399 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3400 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3401 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3402 IS_AOP_PREG (IC_RESULT (ic)))
3403 emitcode ("cjne", "%s,#0xff,%05d$"
3404 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3408 emitcode ("mov", "a,#0xff");
3409 emitcode ("cjne", "a,%s,%05d$"
3410 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3413 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3416 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3417 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3418 IS_AOP_PREG (IC_RESULT (ic)))
3419 emitcode ("cjne", "%s,#0xff,%05d$"
3420 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3424 emitcode ("cjne", "a,%s,%05d$"
3425 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3428 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3432 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3433 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3434 IS_AOP_PREG (IC_RESULT (ic)))
3435 emitcode ("cjne", "%s,#0xff,%05d$"
3436 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3440 emitcode ("cjne", "a,%s,%05d$"
3441 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3444 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3448 emitcode ("", "%05d$:", tlbl->key + 100);
3453 /* if the sizes are greater than 1 then we cannot */
3454 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3455 AOP_SIZE (IC_LEFT (ic)) > 1)
3458 /* we can if the aops of the left & result match or
3459 if they are in registers and the registers are the
3462 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3463 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3464 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3467 _startLazyDPSEvaluation ();
3470 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3472 _endLazyDPSEvaluation ();
3480 /*-----------------------------------------------------------------*/
3481 /* addSign - complete with sign */
3482 /*-----------------------------------------------------------------*/
3484 addSign (operand * result, int offset, int sign)
3486 int size = (getDataSize (result) - offset);
3491 emitcode ("rlc", "a");
3492 emitcode ("subb", "a,acc");
3494 aopPut (AOP (result), "a", offset++);
3498 aopPut (AOP (result), zero, offset++);
3502 /*-----------------------------------------------------------------*/
3503 /* genMinusBits - generates code for subtraction of two bits */
3504 /*-----------------------------------------------------------------*/
3506 genMinusBits (iCode * ic)
3508 symbol *lbl = newiTempLabel (NULL);
3510 D (emitcode (";", "genMinusBits ");
3513 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3515 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3516 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3517 emitcode ("cpl", "c");
3518 emitcode ("", "%05d$:", (lbl->key + 100));
3519 outBitC (IC_RESULT (ic));
3523 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3524 emitcode ("subb", "a,acc");
3525 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3526 emitcode ("inc", "a");
3527 emitcode ("", "%05d$:", (lbl->key + 100));
3528 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3529 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3533 /*-----------------------------------------------------------------*/
3534 /* genMinus - generates code for subtraction */
3535 /*-----------------------------------------------------------------*/
3537 genMinus (iCode * ic)
3539 int size, offset = 0;
3541 unsigned long lit = 0L;
3542 bool pushResult = FALSE;
3544 D (emitcode (";", "genMinus ");
3547 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3548 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3549 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3550 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3556 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3558 /* special cases :- */
3559 /* if both left & right are in bit space */
3560 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3561 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3567 /* if I can do an decrement instead
3568 of subtract then GOOD for ME */
3569 if (genMinusDec (ic) == TRUE)
3574 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3576 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3582 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3587 /* if literal, add a,#-lit, else normal subb */
3588 _startLazyDPSEvaluation ();
3591 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3592 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3593 emitcode ("subb", "a,%s",
3594 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3597 /* first add without previous c */
3599 emitcode ("add", "a,#0x%02x",
3600 (unsigned int) (lit & 0x0FFL));
3602 emitcode ("addc", "a,#0x%02x",
3603 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3608 emitcode ("push", "acc");
3612 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3616 _endLazyDPSEvaluation ();
3620 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3622 size = getDataSize (IC_LEFT (ic));
3623 rSize = getDataSize (IC_RESULT (ic));
3625 /* If the pushed data is bigger than the result,
3626 * simply discard unused bytes. Icky, but works.
3628 * Should we throw a warning here? We're losing data...
3630 while (size > getDataSize (IC_RESULT (ic)))
3632 emitcode (";", "discarding unused result byte.");
3633 emitcode ("pop", "acc");
3639 emitcode ("clr", "a");
3640 /* Conversly, we haven't pushed enough here.
3641 * just zero-pad, and all is well.
3643 while (size < rSize)
3645 emitcode ("push", "acc");
3653 emitcode ("pop", "acc");
3654 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3658 adjustArithmeticResult (ic);
3661 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3662 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3663 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3667 /*-----------------------------------------------------------------*/
3668 /* genMultbits :- multiplication of bits */
3669 /*-----------------------------------------------------------------*/
3671 genMultbits (operand * left,
3675 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3676 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3681 /*-----------------------------------------------------------------*/
3682 /* genMultOneByte : 8*8=8/16 bit multiplication */
3683 /*-----------------------------------------------------------------*/
3685 genMultOneByte (operand * left,
3689 sym_link *opetype = operandType (result);
3691 int size=AOP_SIZE(result);
3693 emitcode (";",__FUNCTION__);
3694 if (size<1 || size>2) {
3695 // this should never happen
3696 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3697 AOP_SIZE(result), __FUNCTION__, lineno);
3701 /* (if two literals: the value is computed before) */
3702 /* if one literal, literal on the right */
3703 if (AOP_TYPE (left) == AOP_LIT)
3708 emitcode (";", "swapped left and right");
3711 if (SPEC_USIGN(opetype)
3712 // ignore the sign of left and right, what else can we do?
3713 || (SPEC_USIGN(operandType(left)) &&
3714 SPEC_USIGN(operandType(right)))) {
3715 // just an unsigned 8*8=8/16 multiply
3716 //emitcode (";","unsigned");
3717 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3718 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3719 emitcode ("mul", "ab");
3720 aopPut (AOP (result), "a", 0);
3722 aopPut (AOP (result), "b", 1);
3727 // we have to do a signed multiply
3729 emitcode (";", "signed");
3730 emitcode ("clr", "F0"); // reset sign flag
3731 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3732 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3734 lbl=newiTempLabel(NULL);
3735 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3736 // left side is negative, 8-bit two's complement, this fails for -128
3737 emitcode ("setb", "F0"); // set sign flag
3738 emitcode ("cpl", "a");
3739 emitcode ("inc", "a");
3741 emitcode ("", "%05d$:", lbl->key+100);
3742 emitcode ("xch", "a,b");
3745 if (AOP_TYPE(right)==AOP_LIT) {
3746 /* AND literal negative */
3747 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3748 // two's complement for literal<0
3749 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3750 emitcode ("cpl", "a");
3751 emitcode ("inc", "a");
3754 lbl=newiTempLabel(NULL);
3755 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3756 // right side is negative, 8-bit two's complement
3757 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3758 emitcode ("cpl", "a");
3759 emitcode ("inc", "a");
3760 emitcode ("", "%05d$:", lbl->key+100);
3762 emitcode ("mul", "ab");
3764 lbl=newiTempLabel(NULL);
3765 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3766 // only ONE op was negative, we have to do a 8/16-bit two's complement
3767 emitcode ("cpl", "a"); // lsb
3769 emitcode ("inc", "a");
3771 emitcode ("add", "a,#1");
3772 emitcode ("xch", "a,b");
3773 emitcode ("cpl", "a"); // msb
3774 emitcode ("addc", "a,#0");
3775 emitcode ("xch", "a,b");
3778 emitcode ("", "%05d$:", lbl->key+100);
3779 aopPut (AOP (result), "a", 0);
3781 aopPut (AOP (result), "b", 1);
3785 /*-----------------------------------------------------------------*/
3786 /* genMult - generates code for multiplication */
3787 /*-----------------------------------------------------------------*/
3789 genMult (iCode * ic)
3791 operand *left = IC_LEFT (ic);
3792 operand *right = IC_RIGHT (ic);
3793 operand *result = IC_RESULT (ic);
3795 D (emitcode (";", "genMult ");
3798 /* assign the amsops */
3801 /* special cases first */
3803 if (AOP_TYPE (left) == AOP_CRY &&
3804 AOP_TYPE (right) == AOP_CRY)
3806 genMultbits (left, right, result);
3810 /* if both are of size == 1 */
3811 if (AOP_SIZE (left) == 1 &&
3812 AOP_SIZE (right) == 1)
3814 genMultOneByte (left, right, result);
3818 /* should have been converted to function call */
3822 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3823 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3824 freeAsmop (result, NULL, ic, TRUE);
3827 /*-----------------------------------------------------------------*/
3828 /* genDivbits :- division of bits */
3829 /*-----------------------------------------------------------------*/
3831 genDivbits (operand * left,
3838 /* the result must be bit */
3839 LOAD_AB_FOR_DIV (left, right, l);
3840 emitcode ("div", "ab");
3841 emitcode ("rrc", "a");
3842 aopPut (AOP (result), "c", 0);
3845 /*-----------------------------------------------------------------*/
3846 /* genDivOneByte : 8 bit division */
3847 /*-----------------------------------------------------------------*/
3849 genDivOneByte (operand * left,
3853 sym_link *opetype = operandType (result);
3858 size = AOP_SIZE (result) - 1;
3860 /* signed or unsigned */
3861 if (SPEC_USIGN (opetype))
3863 /* unsigned is easy */
3864 LOAD_AB_FOR_DIV (left, right, l);
3865 emitcode ("div", "ab");
3866 aopPut (AOP (result), "a", 0);
3868 aopPut (AOP (result), zero, offset++);
3872 /* signed is a little bit more difficult */
3874 /* save the signs of the operands */
3875 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3877 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3878 emitcode ("push", "acc"); /* save it on the stack */
3880 /* now sign adjust for both left & right */
3881 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3883 lbl = newiTempLabel (NULL);
3884 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3885 emitcode ("cpl", "a");
3886 emitcode ("inc", "a");
3887 emitcode ("", "%05d$:", (lbl->key + 100));
3888 emitcode ("mov", "b,a");
3890 /* sign adjust left side */
3891 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3894 lbl = newiTempLabel (NULL);
3895 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3896 emitcode ("cpl", "a");
3897 emitcode ("inc", "a");
3898 emitcode ("", "%05d$:", (lbl->key + 100));
3900 /* now the division */
3901 emitcode ("nop", "; workaround for DS80C390 div bug.");
3902 emitcode ("div", "ab");
3903 /* we are interested in the lower order
3905 emitcode ("mov", "b,a");
3906 lbl = newiTempLabel (NULL);
3907 emitcode ("pop", "acc");
3908 /* if there was an over flow we don't
3909 adjust the sign of the result */
3910 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3911 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3913 emitcode ("clr", "a");
3914 emitcode ("subb", "a,b");
3915 emitcode ("mov", "b,a");
3916 emitcode ("", "%05d$:", (lbl->key + 100));
3918 /* now we are done */
3919 aopPut (AOP (result), "b", 0);
3922 emitcode ("mov", "c,b.7");
3923 emitcode ("subb", "a,acc");
3926 aopPut (AOP (result), "a", offset++);
3930 /*-----------------------------------------------------------------*/
3931 /* genDiv - generates code for division */
3932 /*-----------------------------------------------------------------*/
3936 operand *left = IC_LEFT (ic);
3937 operand *right = IC_RIGHT (ic);
3938 operand *result = IC_RESULT (ic);
3940 D (emitcode (";", "genDiv ");
3943 /* assign the amsops */
3946 /* special cases first */
3948 if (AOP_TYPE (left) == AOP_CRY &&
3949 AOP_TYPE (right) == AOP_CRY)
3951 genDivbits (left, right, result);
3955 /* if both are of size == 1 */
3956 if (AOP_SIZE (left) == 1 &&
3957 AOP_SIZE (right) == 1)
3959 genDivOneByte (left, right, result);
3963 /* should have been converted to function call */
3966 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3967 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3968 freeAsmop (result, NULL, ic, TRUE);
3971 /*-----------------------------------------------------------------*/
3972 /* genModbits :- modulus of bits */
3973 /*-----------------------------------------------------------------*/
3975 genModbits (operand * left,
3982 /* the result must be bit */
3983 LOAD_AB_FOR_DIV (left, right, l);
3984 emitcode ("div", "ab");
3985 emitcode ("mov", "a,b");
3986 emitcode ("rrc", "a");
3987 aopPut (AOP (result), "c", 0);
3990 /*-----------------------------------------------------------------*/
3991 /* genModOneByte : 8 bit modulus */
3992 /*-----------------------------------------------------------------*/
3994 genModOneByte (operand * left,
3998 sym_link *opetype = operandType (result);
4002 /* signed or unsigned */
4003 if (SPEC_USIGN (opetype))
4005 /* unsigned is easy */
4006 LOAD_AB_FOR_DIV (left, right, l);
4007 emitcode ("div", "ab");
4008 aopPut (AOP (result), "b", 0);
4012 /* signed is a little bit more difficult */
4014 /* save the signs of the operands */
4015 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4018 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4019 emitcode ("push", "acc"); /* save it on the stack */
4021 /* now sign adjust for both left & right */
4022 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4025 lbl = newiTempLabel (NULL);
4026 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4027 emitcode ("cpl", "a");
4028 emitcode ("inc", "a");
4029 emitcode ("", "%05d$:", (lbl->key + 100));
4030 emitcode ("mov", "b,a");
4032 /* sign adjust left side */
4033 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4036 lbl = newiTempLabel (NULL);
4037 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4038 emitcode ("cpl", "a");
4039 emitcode ("inc", "a");
4040 emitcode ("", "%05d$:", (lbl->key + 100));
4042 /* now the multiplication */
4043 emitcode ("nop", "; workaround for DS80C390 div bug.");
4044 emitcode ("div", "ab");
4045 /* we are interested in the lower order
4047 lbl = newiTempLabel (NULL);
4048 emitcode ("pop", "acc");
4049 /* if there was an over flow we don't
4050 adjust the sign of the result */
4051 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4052 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4054 emitcode ("clr", "a");
4055 emitcode ("subb", "a,b");
4056 emitcode ("mov", "b,a");
4057 emitcode ("", "%05d$:", (lbl->key + 100));
4059 /* now we are done */
4060 aopPut (AOP (result), "b", 0);
4064 /*-----------------------------------------------------------------*/
4065 /* genMod - generates code for division */
4066 /*-----------------------------------------------------------------*/
4070 operand *left = IC_LEFT (ic);
4071 operand *right = IC_RIGHT (ic);
4072 operand *result = IC_RESULT (ic);
4074 D (emitcode (";", "genMod ");
4077 /* assign the amsops */
4080 /* special cases first */
4082 if (AOP_TYPE (left) == AOP_CRY &&
4083 AOP_TYPE (right) == AOP_CRY)
4085 genModbits (left, right, result);
4089 /* if both are of size == 1 */
4090 if (AOP_SIZE (left) == 1 &&
4091 AOP_SIZE (right) == 1)
4093 genModOneByte (left, right, result);
4097 /* should have been converted to function call */
4101 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4103 freeAsmop (result, NULL, ic, TRUE);
4106 /*-----------------------------------------------------------------*/
4107 /* genIfxJump :- will create a jump depending on the ifx */
4108 /*-----------------------------------------------------------------*/
4110 genIfxJump (iCode * ic, char *jval)
4113 symbol *tlbl = newiTempLabel (NULL);
4116 D (emitcode (";", "genIfxJump ");
4119 /* if true label then we jump if condition
4123 jlbl = IC_TRUE (ic);
4124 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4125 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4129 /* false label is present */
4130 jlbl = IC_FALSE (ic);
4131 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4132 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4134 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4135 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4137 emitcode (inst, "%05d$", tlbl->key + 100);
4138 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4139 emitcode ("", "%05d$:", tlbl->key + 100);
4141 /* mark the icode as generated */
4145 /*-----------------------------------------------------------------*/
4146 /* genCmp :- greater or less than comparison */
4147 /*-----------------------------------------------------------------*/
4149 genCmp (operand * left, operand * right,
4150 iCode * ic, iCode * ifx, int sign)
4152 int size, offset = 0;
4153 unsigned long lit = 0L;
4156 D (emitcode (";", "genCmp");
4159 result = IC_RESULT (ic);
4161 /* if left & right are bit variables */
4162 if (AOP_TYPE (left) == AOP_CRY &&
4163 AOP_TYPE (right) == AOP_CRY)
4165 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4166 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4170 /* subtract right from left if at the
4171 end the carry flag is set then we know that
4172 left is greater than right */
4173 size = max (AOP_SIZE (left), AOP_SIZE (right));
4175 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4176 if ((size == 1) && !sign &&
4177 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4179 symbol *lbl = newiTempLabel (NULL);
4180 emitcode ("cjne", "%s,%s,%05d$",
4181 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4182 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4184 emitcode ("", "%05d$:", lbl->key + 100);
4188 if (AOP_TYPE (right) == AOP_LIT)
4190 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4191 /* optimize if(x < 0) or if(x >= 0) */
4200 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4202 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4203 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4205 aopOp (result, ic, FALSE, FALSE);
4207 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4209 freeAsmop (result, NULL, ic, TRUE);
4210 genIfxJump (ifx, "acc.7");
4215 emitcode ("rlc", "a");
4217 goto release_freedLR;
4225 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4226 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4227 emitcode (";", "genCmp #2");
4228 if (sign && (size == 0))
4230 emitcode (";", "genCmp #3");
4231 emitcode ("xrl", "a,#0x80");
4232 if (AOP_TYPE (right) == AOP_LIT)
4234 unsigned long lit = (unsigned long)
4235 floatFromVal (AOP (right)->aopu.aop_lit);
4236 emitcode (";", "genCmp #3.1");
4237 emitcode ("subb", "a,#0x%02x",
4238 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4242 emitcode (";", "genCmp #3.2");
4243 if (AOP_NEEDSACC (right))
4245 emitcode ("push", "acc");
4247 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4248 FALSE, FALSE, FALSE));
4249 emitcode ("xrl", "b,#0x80");
4250 if (AOP_NEEDSACC (right))
4252 emitcode ("pop", "acc");
4254 emitcode ("subb", "a,b");
4261 emitcode (";", "genCmp #4");
4262 if (AOP_NEEDSACC (right))
4265 emitcode (";", "genCmp #4.1");
4266 emitcode ("xch", "a, b");
4267 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4268 emitcode ("xch", "a, b");
4273 emitcode (";", "genCmp #4.2");
4274 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4277 emitcode ("subb", "a,%s", s);
4284 /* Don't need the left & right operands any more; do need the result. */
4285 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4286 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4288 aopOp (result, ic, FALSE, FALSE);
4292 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4298 /* if the result is used in the next
4299 ifx conditional branch then generate
4300 code a little differently */
4303 genIfxJump (ifx, "c");
4309 /* leave the result in acc */
4311 freeAsmop (result, NULL, ic, TRUE);
4314 /*-----------------------------------------------------------------*/
4315 /* genCmpGt :- greater than comparison */
4316 /*-----------------------------------------------------------------*/
4318 genCmpGt (iCode * ic, iCode * ifx)
4320 operand *left, *right;
4321 sym_link *letype, *retype;
4324 D (emitcode (";", "genCmpGt ");
4327 left = IC_LEFT (ic);
4328 right = IC_RIGHT (ic);
4330 letype = getSpec (operandType (left));
4331 retype = getSpec (operandType (right));
4332 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4334 /* assign the left & right amsops */
4337 genCmp (right, left, ic, ifx, sign);
4340 /*-----------------------------------------------------------------*/
4341 /* genCmpLt - less than comparisons */
4342 /*-----------------------------------------------------------------*/
4344 genCmpLt (iCode * ic, iCode * ifx)
4346 operand *left, *right;
4347 sym_link *letype, *retype;
4350 D (emitcode (";", "genCmpLt ");
4353 left = IC_LEFT (ic);
4354 right = IC_RIGHT (ic);
4356 letype = getSpec (operandType (left));
4357 retype = getSpec (operandType (right));
4358 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4360 /* assign the left & right amsops */
4363 genCmp (left, right, ic, ifx, sign);
4366 /*-----------------------------------------------------------------*/
4367 /* gencjneshort - compare and jump if not equal */
4368 /*-----------------------------------------------------------------*/
4370 gencjneshort (operand * left, operand * right, symbol * lbl)
4372 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4374 unsigned long lit = 0L;
4376 D (emitcode (";", "gencjneshort");
4379 /* if the left side is a literal or
4380 if the right is in a pointer register and left
4382 if ((AOP_TYPE (left) == AOP_LIT) ||
4383 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4390 if (AOP_TYPE (right) == AOP_LIT)
4391 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4393 if (opIsGptr (left) || opIsGptr (right))
4395 /* We are comparing a generic pointer to something.
4396 * Exclude the generic type byte from the comparison.
4399 D (emitcode (";", "cjneshort: generic ptr special case.");
4404 /* if the right side is a literal then anything goes */
4405 if (AOP_TYPE (right) == AOP_LIT &&
4406 AOP_TYPE (left) != AOP_DIR)
4410 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4412 emitcode ("cjne", "a,%s,%05d$",
4413 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4419 /* if the right side is in a register or in direct space or
4420 if the left is a pointer register & right is not */
4421 else if (AOP_TYPE (right) == AOP_REG ||
4422 AOP_TYPE (right) == AOP_DIR ||
4423 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4424 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4428 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4429 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4430 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4431 emitcode ("jnz", "%05d$", lbl->key + 100);
4433 emitcode ("cjne", "a,%s,%05d$",
4434 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4441 /* right is a pointer reg need both a & b */
4444 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4445 if (strcmp (l, "b"))
4446 emitcode ("mov", "b,%s", l);
4447 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4448 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4454 /*-----------------------------------------------------------------*/
4455 /* gencjne - compare and jump if not equal */
4456 /*-----------------------------------------------------------------*/
4458 gencjne (operand * left, operand * right, symbol * lbl)
4460 symbol *tlbl = newiTempLabel (NULL);
4462 D (emitcode (";", "gencjne");
4465 gencjneshort (left, right, lbl);
4467 emitcode ("mov", "a,%s", one);
4468 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4469 emitcode ("", "%05d$:", lbl->key + 100);
4470 emitcode ("clr", "a");
4471 emitcode ("", "%05d$:", tlbl->key + 100);
4474 /*-----------------------------------------------------------------*/
4475 /* genCmpEq - generates code for equal to */
4476 /*-----------------------------------------------------------------*/
4478 genCmpEq (iCode * ic, iCode * ifx)
4480 operand *left, *right, *result;
4482 D (emitcode (";", "genCmpEq ");
4486 AOP_SET_LOCALS (ic);
4488 /* if literal, literal on the right or
4489 if the right is in a pointer register and left
4491 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4492 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4494 operand *t = IC_RIGHT (ic);
4495 IC_RIGHT (ic) = IC_LEFT (ic);
4499 if (ifx && /* !AOP_SIZE(result) */
4500 OP_SYMBOL (result) &&
4501 OP_SYMBOL (result)->regType == REG_CND)
4504 /* if they are both bit variables */
4505 if (AOP_TYPE (left) == AOP_CRY &&
4506 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4508 if (AOP_TYPE (right) == AOP_LIT)
4510 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4513 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4514 emitcode ("cpl", "c");
4518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4522 emitcode ("clr", "c");
4524 /* AOP_TYPE(right) == AOP_CRY */
4528 symbol *lbl = newiTempLabel (NULL);
4529 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4530 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4531 emitcode ("cpl", "c");
4532 emitcode ("", "%05d$:", (lbl->key + 100));
4534 /* if true label then we jump if condition
4536 tlbl = newiTempLabel (NULL);
4539 emitcode ("jnc", "%05d$", tlbl->key + 100);
4540 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4544 emitcode ("jc", "%05d$", tlbl->key + 100);
4545 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4547 emitcode ("", "%05d$:", tlbl->key + 100);
4551 tlbl = newiTempLabel (NULL);
4552 gencjneshort (left, right, tlbl);
4555 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4556 emitcode ("", "%05d$:", tlbl->key + 100);
4560 symbol *lbl = newiTempLabel (NULL);
4561 emitcode ("sjmp", "%05d$", lbl->key + 100);
4562 emitcode ("", "%05d$:", tlbl->key + 100);
4563 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4564 emitcode ("", "%05d$:", lbl->key + 100);
4567 /* mark the icode as generated */
4570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4575 /* if they are both bit variables */
4576 if (AOP_TYPE (left) == AOP_CRY &&
4577 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4579 if (AOP_TYPE (right) == AOP_LIT)
4581 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4584 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4585 emitcode ("cpl", "c");
4589 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4593 emitcode ("clr", "c");
4595 /* AOP_TYPE(right) == AOP_CRY */
4599 symbol *lbl = newiTempLabel (NULL);
4600 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4601 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4602 emitcode ("cpl", "c");
4603 emitcode ("", "%05d$:", (lbl->key + 100));
4606 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4607 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4609 aopOp (result, ic, TRUE, FALSE);
4612 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4619 genIfxJump (ifx, "c");
4622 /* if the result is used in an arithmetic operation
4623 then put the result in place */
4628 gencjne (left, right, newiTempLabel (NULL));
4630 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4631 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4633 aopOp (result, ic, TRUE, FALSE);
4635 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4637 aopPut (AOP (result), "a", 0);
4642 genIfxJump (ifx, "a");
4645 /* if the result is used in an arithmetic operation
4646 then put the result in place */
4647 if (AOP_TYPE (result) != AOP_CRY)
4649 /* leave the result in acc */
4653 freeAsmop (result, NULL, ic, TRUE);
4656 /*-----------------------------------------------------------------*/
4657 /* ifxForOp - returns the icode containing the ifx for operand */
4658 /*-----------------------------------------------------------------*/
4660 ifxForOp (operand * op, iCode * ic)
4662 /* if true symbol then needs to be assigned */
4663 if (IS_TRUE_SYMOP (op))
4666 /* if this has register type condition and
4667 the next instruction is ifx with the same operand
4668 and live to of the operand is upto the ifx only then */
4670 ic->next->op == IFX &&
4671 IC_COND (ic->next)->key == op->key &&
4672 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4677 /*-----------------------------------------------------------------*/
4678 /* genAndOp - for && operation */
4679 /*-----------------------------------------------------------------*/
4681 genAndOp (iCode * ic)
4683 operand *left, *right, *result;
4686 D (emitcode (";", "genAndOp ");
4689 /* note here that && operations that are in an
4690 if statement are taken away by backPatchLabels
4691 only those used in arthmetic operations remain */
4693 AOP_SET_LOCALS (ic);
4695 /* if both are bit variables */
4696 if (AOP_TYPE (left) == AOP_CRY &&
4697 AOP_TYPE (right) == AOP_CRY)
4699 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4700 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4705 tlbl = newiTempLabel (NULL);
4707 emitcode ("jz", "%05d$", tlbl->key + 100);
4709 emitcode ("", "%05d$:", tlbl->key + 100);
4713 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4715 freeAsmop (result, NULL, ic, TRUE);
4719 /*-----------------------------------------------------------------*/
4720 /* genOrOp - for || operation */
4721 /*-----------------------------------------------------------------*/
4723 genOrOp (iCode * ic)
4725 operand *left, *right, *result;
4728 D (emitcode (";", "genOrOp ");
4731 /* note here that || operations that are in an
4732 if statement are taken away by backPatchLabels
4733 only those used in arthmetic operations remain */
4735 AOP_SET_LOCALS (ic);
4737 /* if both are bit variables */
4738 if (AOP_TYPE (left) == AOP_CRY &&
4739 AOP_TYPE (right) == AOP_CRY)
4741 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4742 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4747 tlbl = newiTempLabel (NULL);
4749 emitcode ("jnz", "%05d$", tlbl->key + 100);
4751 emitcode ("", "%05d$:", tlbl->key + 100);
4755 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4756 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4757 freeAsmop (result, NULL, ic, TRUE);
4760 /*-----------------------------------------------------------------*/
4761 /* isLiteralBit - test if lit == 2^n */
4762 /*-----------------------------------------------------------------*/
4764 isLiteralBit (unsigned long lit)
4766 unsigned long pw[32] =
4767 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4768 0x100L, 0x200L, 0x400L, 0x800L,
4769 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4770 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4771 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4772 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4773 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4776 for (idx = 0; idx < 32; idx++)
4782 /*-----------------------------------------------------------------*/
4783 /* continueIfTrue - */
4784 /*-----------------------------------------------------------------*/
4786 continueIfTrue (iCode * ic)
4789 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4793 /*-----------------------------------------------------------------*/
4795 /*-----------------------------------------------------------------*/
4797 jumpIfTrue (iCode * ic)
4800 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4804 /*-----------------------------------------------------------------*/
4805 /* jmpTrueOrFalse - */
4806 /*-----------------------------------------------------------------*/
4808 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4810 // ugly but optimized by peephole
4813 symbol *nlbl = newiTempLabel (NULL);
4814 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4815 emitcode ("", "%05d$:", tlbl->key + 100);
4816 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4817 emitcode ("", "%05d$:", nlbl->key + 100);
4821 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4822 emitcode ("", "%05d$:", tlbl->key + 100);
4827 /*-----------------------------------------------------------------*/
4828 /* genAnd - code for and */
4829 /*-----------------------------------------------------------------*/
4831 genAnd (iCode * ic, iCode * ifx)
4833 operand *left, *right, *result;
4834 int size, offset = 0;
4835 unsigned long lit = 0L;
4839 D (emitcode (";", "genAnd ");
4843 AOP_SET_LOCALS (ic);
4846 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4848 AOP_TYPE (left), AOP_TYPE (right));
4849 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4851 AOP_SIZE (left), AOP_SIZE (right));
4854 /* if left is a literal & right is not then exchange them */
4855 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4856 AOP_NEEDSACC (left))
4858 operand *tmp = right;
4863 /* if result = right then exchange them */
4864 if (sameRegs (AOP (result), AOP (right)))
4866 operand *tmp = right;
4871 /* if right is bit then exchange them */
4872 if (AOP_TYPE (right) == AOP_CRY &&
4873 AOP_TYPE (left) != AOP_CRY)
4875 operand *tmp = right;
4879 if (AOP_TYPE (right) == AOP_LIT)
4880 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4882 size = AOP_SIZE (result);
4885 // result = bit & yy;
4886 if (AOP_TYPE (left) == AOP_CRY)
4888 // c = bit & literal;
4889 if (AOP_TYPE (right) == AOP_LIT)
4893 if (size && sameRegs (AOP (result), AOP (left)))
4896 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4901 if (size && (AOP_TYPE (result) == AOP_CRY))
4903 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4906 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4911 emitcode ("clr", "c");
4916 if (AOP_TYPE (right) == AOP_CRY)
4919 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4920 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4925 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4927 emitcode ("rrc", "a");
4928 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4936 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4937 genIfxJump (ifx, "c");
4941 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4942 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4943 if ((AOP_TYPE (right) == AOP_LIT) &&
4944 (AOP_TYPE (result) == AOP_CRY) &&
4945 (AOP_TYPE (left) != AOP_CRY))
4947 int posbit = isLiteralBit (lit);
4952 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4955 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4961 sprintf (buffer, "acc.%d", posbit & 0x07);
4962 genIfxJump (ifx, buffer);
4969 symbol *tlbl = newiTempLabel (NULL);
4970 int sizel = AOP_SIZE (left);
4972 emitcode ("setb", "c");
4975 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4977 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4979 if ((posbit = isLiteralBit (bytelit)) != 0)
4980 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4983 if (bytelit != 0x0FFL)
4984 emitcode ("anl", "a,%s",
4985 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4986 emitcode ("jnz", "%05d$", tlbl->key + 100);
4991 // bit = left & literal
4994 emitcode ("clr", "c");
4995 emitcode ("", "%05d$:", tlbl->key + 100);
4997 // if(left & literal)
5001 jmpTrueOrFalse (ifx, tlbl);
5009 /* if left is same as result */
5010 if (sameRegs (AOP (result), AOP (left)))
5012 for (; size--; offset++)
5014 if (AOP_TYPE (right) == AOP_LIT)
5016 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5018 else if (bytelit == 0)
5019 aopPut (AOP (result), zero, offset);
5020 else if (IS_AOP_PREG (result))
5022 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5023 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5024 aopPut (AOP (result), "a", offset);
5027 emitcode ("anl", "%s,%s",
5028 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5029 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5033 if (AOP_TYPE (left) == AOP_ACC)
5034 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5037 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5038 if (IS_AOP_PREG (result))
5040 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5041 aopPut (AOP (result), "a", offset);
5045 emitcode ("anl", "%s,a",
5046 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5053 // left & result in different registers
5054 if (AOP_TYPE (result) == AOP_CRY)
5057 // if(size), result in bit
5058 // if(!size && ifx), conditional oper: if(left & right)
5059 symbol *tlbl = newiTempLabel (NULL);
5060 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5062 emitcode ("setb", "c");
5065 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5066 emitcode ("anl", "a,%s",
5067 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5068 emitcode ("jnz", "%05d$", tlbl->key + 100);
5074 emitcode ("", "%05d$:", tlbl->key + 100);
5078 jmpTrueOrFalse (ifx, tlbl);
5082 for (; (size--); offset++)
5085 // result = left & right
5086 if (AOP_TYPE (right) == AOP_LIT)
5088 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5090 aopPut (AOP (result),
5091 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5095 else if (bytelit == 0)
5097 aopPut (AOP (result), zero, offset);
5100 D (emitcode (";", "better literal AND.");
5102 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5103 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5104 FALSE, FALSE, FALSE));
5109 // faster than result <- left, anl result,right
5110 // and better if result is SFR
5111 if (AOP_TYPE (left) == AOP_ACC)
5113 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5114 FALSE, FALSE, FALSE));
5118 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5119 emitcode ("anl", "a,%s",
5120 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5123 aopPut (AOP (result), "a", offset);
5129 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5130 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5131 freeAsmop (result, NULL, ic, TRUE);
5134 /*-----------------------------------------------------------------*/
5135 /* genOr - code for or */
5136 /*-----------------------------------------------------------------*/
5138 genOr (iCode * ic, iCode * ifx)
5140 operand *left, *right, *result;
5141 int size, offset = 0;
5142 unsigned long lit = 0L;
5144 D (emitcode (";", "genOr ");
5148 AOP_SET_LOCALS (ic);
5151 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5153 AOP_TYPE (left), AOP_TYPE (right));
5154 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5156 AOP_SIZE (left), AOP_SIZE (right));
5159 /* if left is a literal & right is not then exchange them */
5160 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5161 AOP_NEEDSACC (left))
5163 operand *tmp = right;
5168 /* if result = right then exchange them */
5169 if (sameRegs (AOP (result), AOP (right)))
5171 operand *tmp = right;
5176 /* if right is bit then exchange them */
5177 if (AOP_TYPE (right) == AOP_CRY &&
5178 AOP_TYPE (left) != AOP_CRY)
5180 operand *tmp = right;
5184 if (AOP_TYPE (right) == AOP_LIT)
5185 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5187 size = AOP_SIZE (result);
5191 if (AOP_TYPE (left) == AOP_CRY)
5193 if (AOP_TYPE (right) == AOP_LIT)
5195 // c = bit & literal;
5198 // lit != 0 => result = 1
5199 if (AOP_TYPE (result) == AOP_CRY)
5202 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5204 continueIfTrue (ifx);
5207 emitcode ("setb", "c");
5211 // lit == 0 => result = left
5212 if (size && sameRegs (AOP (result), AOP (left)))
5214 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5219 if (AOP_TYPE (right) == AOP_CRY)
5222 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5223 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5228 symbol *tlbl = newiTempLabel (NULL);
5229 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5230 emitcode ("setb", "c");
5231 emitcode ("jb", "%s,%05d$",
5232 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5234 emitcode ("jnz", "%05d$", tlbl->key + 100);
5235 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5237 jmpTrueOrFalse (ifx, tlbl);
5243 emitcode ("", "%05d$:", tlbl->key + 100);
5252 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5253 genIfxJump (ifx, "c");
5257 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5258 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5259 if ((AOP_TYPE (right) == AOP_LIT) &&
5260 (AOP_TYPE (result) == AOP_CRY) &&
5261 (AOP_TYPE (left) != AOP_CRY))
5267 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5269 continueIfTrue (ifx);
5274 // lit = 0, result = boolean(left)
5276 emitcode ("setb", "c");
5280 symbol *tlbl = newiTempLabel (NULL);
5281 emitcode ("jnz", "%05d$", tlbl->key + 100);
5283 emitcode ("", "%05d$:", tlbl->key + 100);
5287 genIfxJump (ifx, "a");
5295 /* if left is same as result */
5296 if (sameRegs (AOP (result), AOP (left)))
5298 for (; size--; offset++)
5300 if (AOP_TYPE (right) == AOP_LIT)
5302 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5308 if (IS_AOP_PREG (left))
5310 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5311 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5312 aopPut (AOP (result), "a", offset);
5316 emitcode ("orl", "%s,%s",
5317 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5318 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5324 if (AOP_TYPE (left) == AOP_ACC)
5326 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5330 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5331 if (IS_AOP_PREG (left))
5333 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5334 aopPut (AOP (result), "a", offset);
5338 emitcode ("orl", "%s,a",
5339 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5347 // left & result in different registers
5348 if (AOP_TYPE (result) == AOP_CRY)
5351 // if(size), result in bit
5352 // if(!size && ifx), conditional oper: if(left | right)
5353 symbol *tlbl = newiTempLabel (NULL);
5354 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5356 emitcode ("setb", "c");
5359 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5360 emitcode ("orl", "a,%s",
5361 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5362 emitcode ("jnz", "%05d$", tlbl->key + 100);
5368 emitcode ("", "%05d$:", tlbl->key + 100);
5372 jmpTrueOrFalse (ifx, tlbl);
5376 for (; (size--); offset++)
5379 // result = left & right
5380 if (AOP_TYPE (right) == AOP_LIT)
5382 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5384 aopPut (AOP (result),
5385 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5389 D (emitcode (";", "better literal OR.");
5391 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5392 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5393 FALSE, FALSE, FALSE));
5398 // faster than result <- left, anl result,right
5399 // and better if result is SFR
5400 if (AOP_TYPE (left) == AOP_ACC)
5402 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5403 FALSE, FALSE, FALSE));
5407 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5408 emitcode ("orl", "a,%s",
5409 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5412 aopPut (AOP (result), "a", offset);
5418 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5420 freeAsmop (result, NULL, ic, TRUE);
5423 /*-----------------------------------------------------------------*/
5424 /* genXor - code for xclusive or */
5425 /*-----------------------------------------------------------------*/
5427 genXor (iCode * ic, iCode * ifx)
5429 operand *left, *right, *result;
5430 int size, offset = 0;
5431 unsigned long lit = 0L;
5433 D (emitcode (";", "genXor ");
5437 AOP_SET_LOCALS (ic);
5440 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5442 AOP_TYPE (left), AOP_TYPE (right));
5443 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5445 AOP_SIZE (left), AOP_SIZE (right));
5448 /* if left is a literal & right is not ||
5449 if left needs acc & right does not */
5450 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5451 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5453 operand *tmp = right;
5458 /* if result = right then exchange them */
5459 if (sameRegs (AOP (result), AOP (right)))
5461 operand *tmp = right;
5466 /* if right is bit then exchange them */
5467 if (AOP_TYPE (right) == AOP_CRY &&
5468 AOP_TYPE (left) != AOP_CRY)
5470 operand *tmp = right;
5474 if (AOP_TYPE (right) == AOP_LIT)
5475 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5477 size = AOP_SIZE (result);
5481 if (AOP_TYPE (left) == AOP_CRY)
5483 if (AOP_TYPE (right) == AOP_LIT)
5485 // c = bit & literal;
5488 // lit>>1 != 0 => result = 1
5489 if (AOP_TYPE (result) == AOP_CRY)
5492 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5494 continueIfTrue (ifx);
5497 emitcode ("setb", "c");
5504 // lit == 0, result = left
5505 if (size && sameRegs (AOP (result), AOP (left)))
5507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5511 // lit == 1, result = not(left)
5512 if (size && sameRegs (AOP (result), AOP (left)))
5514 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5519 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5520 emitcode ("cpl", "c");
5529 symbol *tlbl = newiTempLabel (NULL);
5530 if (AOP_TYPE (right) == AOP_CRY)
5533 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5537 int sizer = AOP_SIZE (right);
5539 // if val>>1 != 0, result = 1
5540 emitcode ("setb", "c");
5543 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5545 // test the msb of the lsb
5546 emitcode ("anl", "a,#0xfe");
5547 emitcode ("jnz", "%05d$", tlbl->key + 100);
5551 emitcode ("rrc", "a");
5553 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5554 emitcode ("cpl", "c");
5555 emitcode ("", "%05d$:", (tlbl->key + 100));
5562 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5563 genIfxJump (ifx, "c");
5567 if (sameRegs (AOP (result), AOP (left)))
5569 /* if left is same as result */
5570 for (; size--; offset++)
5572 if (AOP_TYPE (right) == AOP_LIT)
5574 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5576 else if (IS_AOP_PREG (left))
5578 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5579 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5580 aopPut (AOP (result), "a", offset);
5583 emitcode ("xrl", "%s,%s",
5584 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5585 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5589 if (AOP_TYPE (left) == AOP_ACC)
5590 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5593 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5594 if (IS_AOP_PREG (left))
5596 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5597 aopPut (AOP (result), "a", offset);
5600 emitcode ("xrl", "%s,a",
5601 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5608 // left & result in different registers
5609 if (AOP_TYPE (result) == AOP_CRY)
5612 // if(size), result in bit
5613 // if(!size && ifx), conditional oper: if(left ^ right)
5614 symbol *tlbl = newiTempLabel (NULL);
5615 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5617 emitcode ("setb", "c");
5620 if ((AOP_TYPE (right) == AOP_LIT) &&
5621 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5623 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5627 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5628 emitcode ("xrl", "a,%s",
5629 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5631 emitcode ("jnz", "%05d$", tlbl->key + 100);
5637 emitcode ("", "%05d$:", tlbl->key + 100);
5641 jmpTrueOrFalse (ifx, tlbl);
5644 for (; (size--); offset++)
5647 // result = left & right
5648 if (AOP_TYPE (right) == AOP_LIT)
5650 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5652 aopPut (AOP (result),
5653 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5657 D (emitcode (";", "better literal XOR.");
5659 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5660 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5661 FALSE, FALSE, FALSE));
5665 // faster than result <- left, anl result,right
5666 // and better if result is SFR
5667 if (AOP_TYPE (left) == AOP_ACC)
5669 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5670 FALSE, FALSE, FALSE));
5674 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5675 emitcode ("xrl", "a,%s",
5676 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5679 aopPut (AOP (result), "a", offset);
5684 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5685 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5686 freeAsmop (result, NULL, ic, TRUE);
5689 /*-----------------------------------------------------------------*/
5690 /* genInline - write the inline code out */
5691 /*-----------------------------------------------------------------*/
5693 genInline (iCode * ic)
5695 char buffer[MAX_INLINEASM];
5699 D (emitcode (";", "genInline ");
5702 _G.inLine += (!options.asmpeep);
5703 strcpy (buffer, IC_INLINE (ic));
5705 /* emit each line as a code */
5730 /* emitcode("",buffer); */
5731 _G.inLine -= (!options.asmpeep);
5734 /*-----------------------------------------------------------------*/
5735 /* genRRC - rotate right with carry */
5736 /*-----------------------------------------------------------------*/
5740 operand *left, *result;
5741 int size, offset = 0;
5744 D (emitcode (";", "genRRC ");
5747 /* rotate right with carry */
5748 left = IC_LEFT (ic);
5749 result = IC_RESULT (ic);
5750 aopOp (left, ic, FALSE, FALSE);
5751 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5753 /* move it to the result */
5754 size = AOP_SIZE (result);
5758 _startLazyDPSEvaluation ();
5761 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5763 emitcode ("rrc", "a");
5764 if (AOP_SIZE (result) > 1)
5765 aopPut (AOP (result), "a", offset--);
5767 _endLazyDPSEvaluation ();
5769 /* now we need to put the carry into the
5770 highest order byte of the result */
5771 if (AOP_SIZE (result) > 1)
5773 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5776 emitcode ("mov", "acc.7,c");
5777 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5778 freeAsmop (left, NULL, ic, TRUE);
5779 freeAsmop (result, NULL, ic, TRUE);
5782 /*-----------------------------------------------------------------*/
5783 /* genRLC - generate code for rotate left with carry */
5784 /*-----------------------------------------------------------------*/
5788 operand *left, *result;
5789 int size, offset = 0;
5792 D (emitcode (";", "genRLC ");
5795 /* rotate right with carry */
5796 left = IC_LEFT (ic);
5797 result = IC_RESULT (ic);
5798 aopOp (left, ic, FALSE, FALSE);
5799 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5801 /* move it to the result */
5802 size = AOP_SIZE (result);
5806 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5808 emitcode ("add", "a,acc");
5809 if (AOP_SIZE (result) > 1)
5811 aopPut (AOP (result), "a", offset++);
5814 _startLazyDPSEvaluation ();
5817 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5819 emitcode ("rlc", "a");
5820 if (AOP_SIZE (result) > 1)
5821 aopPut (AOP (result), "a", offset++);
5823 _endLazyDPSEvaluation ();
5825 /* now we need to put the carry into the
5826 highest order byte of the result */
5827 if (AOP_SIZE (result) > 1)
5829 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5832 emitcode ("mov", "acc.0,c");
5833 aopPut (AOP (result), "a", 0);
5834 freeAsmop (left, NULL, ic, TRUE);
5835 freeAsmop (result, NULL, ic, TRUE);
5838 /*-----------------------------------------------------------------*/
5839 /* genGetHbit - generates code get highest order bit */
5840 /*-----------------------------------------------------------------*/
5842 genGetHbit (iCode * ic)
5844 operand *left, *result;
5845 left = IC_LEFT (ic);
5846 result = IC_RESULT (ic);
5847 aopOp (left, ic, FALSE, FALSE);
5848 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5850 D (emitcode (";", "genGetHbit ");
5853 /* get the highest order byte into a */
5854 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5855 if (AOP_TYPE (result) == AOP_CRY)
5857 emitcode ("rlc", "a");
5862 emitcode ("rl", "a");
5863 emitcode ("anl", "a,#0x01");
5868 freeAsmop (left, NULL, ic, TRUE);
5869 freeAsmop (result, NULL, ic, TRUE);
5872 /*-----------------------------------------------------------------*/
5873 /* AccRol - rotate left accumulator by known count */
5874 /*-----------------------------------------------------------------*/
5876 AccRol (int shCount)
5878 shCount &= 0x0007; // shCount : 0..7
5885 emitcode ("rl", "a");
5888 emitcode ("rl", "a");
5889 emitcode ("rl", "a");
5892 emitcode ("swap", "a");
5893 emitcode ("rr", "a");
5896 emitcode ("swap", "a");
5899 emitcode ("swap", "a");
5900 emitcode ("rl", "a");
5903 emitcode ("rr", "a");
5904 emitcode ("rr", "a");
5907 emitcode ("rr", "a");
5912 /*-----------------------------------------------------------------*/
5913 /* AccLsh - left shift accumulator by known count */
5914 /*-----------------------------------------------------------------*/
5916 AccLsh (int shCount)
5921 emitcode ("add", "a,acc");
5922 else if (shCount == 2)
5924 emitcode ("add", "a,acc");
5925 emitcode ("add", "a,acc");
5929 /* rotate left accumulator */
5931 /* and kill the lower order bits */
5932 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5937 /*-----------------------------------------------------------------*/
5938 /* AccRsh - right shift accumulator by known count */
5939 /*-----------------------------------------------------------------*/
5941 AccRsh (int shCount)
5948 emitcode ("rrc", "a");
5952 /* rotate right accumulator */
5953 AccRol (8 - shCount);
5954 /* and kill the higher order bits */
5955 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5962 /*-----------------------------------------------------------------*/
5963 /* AccSRsh - signed right shift accumulator by known count */
5964 /*-----------------------------------------------------------------*/
5966 AccSRsh (int shCount)
5973 emitcode ("mov", "c,acc.7");
5974 emitcode ("rrc", "a");
5976 else if (shCount == 2)
5978 emitcode ("mov", "c,acc.7");
5979 emitcode ("rrc", "a");
5980 emitcode ("mov", "c,acc.7");
5981 emitcode ("rrc", "a");
5985 tlbl = newiTempLabel (NULL);
5986 /* rotate right accumulator */
5987 AccRol (8 - shCount);
5988 /* and kill the higher order bits */
5989 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5990 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5991 emitcode ("orl", "a,#0x%02x",
5992 (unsigned char) ~SRMask[shCount]);
5993 emitcode ("", "%05d$:", tlbl->key + 100);
6001 /*-----------------------------------------------------------------*/
6002 /* shiftR1Left2Result - shift right one byte from left to result */
6003 /*-----------------------------------------------------------------*/
6005 shiftR1Left2Result (operand * left, int offl,
6006 operand * result, int offr,
6007 int shCount, int sign)
6009 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6010 /* shift right accumulator */
6015 aopPut (AOP (result), "a", offr);
6021 /*-----------------------------------------------------------------*/
6022 /* shiftL1Left2Result - shift left one byte from left to result */
6023 /*-----------------------------------------------------------------*/
6025 shiftL1Left2Result (operand * left, int offl,
6026 operand * result, int offr, int shCount)
6029 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6031 /* shift left accumulator */
6033 aopPut (AOP (result), "a", offr);
6039 /*-----------------------------------------------------------------*/
6040 /* movLeft2Result - move byte from left to result */
6041 /*-----------------------------------------------------------------*/
6043 movLeft2Result (operand * left, int offl,
6044 operand * result, int offr, int sign)
6047 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6049 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6051 if (*l == '@' && (IS_AOP_PREG (result)))
6053 emitcode ("mov", "a,%s", l);
6054 aopPut (AOP (result), "a", offr);
6059 aopPut (AOP (result), l, offr);
6062 /* MSB sign in acc.7 ! */
6063 if (getDataSize (left) == offl + 1)
6065 emitcode ("mov", "a,%s", l);
6066 aopPut (AOP (result), "a", offr);
6076 /*-----------------------------------------------------------------*/
6077 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6078 /*-----------------------------------------------------------------*/
6082 emitcode ("rrc", "a");
6083 emitcode ("xch", "a,%s", x);
6084 emitcode ("rrc", "a");
6085 emitcode ("xch", "a,%s", x);
6091 /*-----------------------------------------------------------------*/
6092 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6093 /*-----------------------------------------------------------------*/
6097 emitcode ("xch", "a,%s", x);
6098 emitcode ("rlc", "a");
6099 emitcode ("xch", "a,%s", x);
6100 emitcode ("rlc", "a");
6106 /*-----------------------------------------------------------------*/
6107 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6108 /*-----------------------------------------------------------------*/
6112 emitcode ("xch", "a,%s", x);
6113 emitcode ("add", "a,acc");
6114 emitcode ("xch", "a,%s", x);
6115 emitcode ("rlc", "a");
6121 /*-----------------------------------------------------------------*/
6122 /* AccAXLsh - left shift a:x by known count (0..7) */
6123 /*-----------------------------------------------------------------*/
6125 AccAXLsh (char *x, int shCount)
6140 case 5: // AAAAABBB:CCCCCDDD
6142 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6144 emitcode ("anl", "a,#0x%02x",
6145 SLMask[shCount]); // BBB00000:CCCCCDDD
6147 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6149 AccRol (shCount); // DDDCCCCC:BBB00000
6151 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6153 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6155 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6157 emitcode ("anl", "a,#0x%02x",
6158 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6160 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6162 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6165 case 6: // AAAAAABB:CCCCCCDD
6166 emitcode ("anl", "a,#0x%02x",
6167 SRMask[shCount]); // 000000BB:CCCCCCDD
6168 emitcode ("mov", "c,acc.0"); // c = B
6169 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6171 AccAXRrl1 (x); // BCCCCCCD:D000000B
6172 AccAXRrl1 (x); // BBCCCCCC:DD000000
6174 emitcode("rrc","a");
6175 emitcode("xch","a,%s", x);
6176 emitcode("rrc","a");
6177 emitcode("mov","c,acc.0"); //<< get correct bit
6178 emitcode("xch","a,%s", x);
6180 emitcode("rrc","a");
6181 emitcode("xch","a,%s", x);
6182 emitcode("rrc","a");
6183 emitcode("xch","a,%s", x);
6186 case 7: // a:x <<= 7
6188 emitcode ("anl", "a,#0x%02x",
6189 SRMask[shCount]); // 0000000B:CCCCCCCD
6191 emitcode ("mov", "c,acc.0"); // c = B
6193 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6195 AccAXRrl1 (x); // BCCCCCCC:D0000000
6206 /*-----------------------------------------------------------------*/
6207 /* AccAXRsh - right shift a:x known count (0..7) */
6208 /*-----------------------------------------------------------------*/
6210 AccAXRsh (char *x, int shCount)
6218 AccAXRrl1 (x); // 0->a:x
6223 AccAXRrl1 (x); // 0->a:x
6226 AccAXRrl1 (x); // 0->a:x
6231 case 5: // AAAAABBB:CCCCCDDD = a:x
6233 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6235 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6237 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6239 emitcode ("anl", "a,#0x%02x",
6240 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6242 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6244 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6246 emitcode ("anl", "a,#0x%02x",
6247 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6249 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6251 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6253 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6256 case 6: // AABBBBBB:CCDDDDDD
6258 emitcode ("mov", "c,acc.7");
6259 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6261 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6263 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6265 emitcode ("anl", "a,#0x%02x",
6266 SRMask[shCount]); // 000000AA:BBBBBBCC
6269 case 7: // ABBBBBBB:CDDDDDDD
6271 emitcode ("mov", "c,acc.7"); // c = A
6273 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6275 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6277 emitcode ("anl", "a,#0x%02x",
6278 SRMask[shCount]); // 0000000A:BBBBBBBC
6289 /*-----------------------------------------------------------------*/
6290 /* AccAXRshS - right shift signed a:x known count (0..7) */
6291 /*-----------------------------------------------------------------*/
6293 AccAXRshS (char *x, int shCount)
6301 emitcode ("mov", "c,acc.7");
6302 AccAXRrl1 (x); // s->a:x
6306 emitcode ("mov", "c,acc.7");
6307 AccAXRrl1 (x); // s->a:x
6309 emitcode ("mov", "c,acc.7");
6310 AccAXRrl1 (x); // s->a:x
6315 case 5: // AAAAABBB:CCCCCDDD = a:x
6317 tlbl = newiTempLabel (NULL);
6318 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6320 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6322 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6324 emitcode ("anl", "a,#0x%02x",
6325 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6327 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6329 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6331 emitcode ("anl", "a,#0x%02x",
6332 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6334 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6336 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6338 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6340 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6341 emitcode ("orl", "a,#0x%02x",
6342 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6344 emitcode ("", "%05d$:", tlbl->key + 100);
6345 break; // SSSSAAAA:BBBCCCCC
6347 case 6: // AABBBBBB:CCDDDDDD
6349 tlbl = newiTempLabel (NULL);
6350 emitcode ("mov", "c,acc.7");
6351 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6353 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6355 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6357 emitcode ("anl", "a,#0x%02x",
6358 SRMask[shCount]); // 000000AA:BBBBBBCC
6360 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6361 emitcode ("orl", "a,#0x%02x",
6362 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6364 emitcode ("", "%05d$:", tlbl->key + 100);
6366 case 7: // ABBBBBBB:CDDDDDDD
6368 tlbl = newiTempLabel (NULL);
6369 emitcode ("mov", "c,acc.7"); // c = A
6371 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6373 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6375 emitcode ("anl", "a,#0x%02x",
6376 SRMask[shCount]); // 0000000A:BBBBBBBC
6378 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6379 emitcode ("orl", "a,#0x%02x",
6380 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6382 emitcode ("", "%05d$:", tlbl->key + 100);
6392 /*-----------------------------------------------------------------*/
6393 /* shiftL2Left2Result - shift left two bytes from left to result */
6394 /*-----------------------------------------------------------------*/
6396 shiftL2Left2Result (operand * left, int offl,
6397 operand * result, int offr, int shCount)
6399 if (sameRegs (AOP (result), AOP (left)) &&
6400 ((offl + MSB16) == offr))
6402 /* don't crash result[offr] */
6403 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6404 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6408 movLeft2Result (left, offl, result, offr, 0);
6409 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6411 /* ax << shCount (x = lsb(result)) */
6412 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6413 aopPut (AOP (result), "a", offr + MSB16);
6419 /*-----------------------------------------------------------------*/
6420 /* shiftR2Left2Result - shift right two bytes from left to result */
6421 /*-----------------------------------------------------------------*/
6423 shiftR2Left2Result (operand * left, int offl,
6424 operand * result, int offr,
6425 int shCount, int sign)
6427 if (sameRegs (AOP (result), AOP (left)) &&
6428 ((offl + MSB16) == offr))
6430 /* don't crash result[offr] */
6431 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6432 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6436 movLeft2Result (left, offl, result, offr, 0);
6437 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6439 /* a:x >> shCount (x = lsb(result)) */
6441 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6443 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6444 if (getDataSize (result) > 1)
6445 aopPut (AOP (result), "a", offr + MSB16);
6451 /*-----------------------------------------------------------------*/
6452 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6453 /*-----------------------------------------------------------------*/
6455 shiftLLeftOrResult (operand * left, int offl,
6456 operand * result, int offr, int shCount)
6458 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6459 /* shift left accumulator */
6461 /* or with result */
6462 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6463 /* back to result */
6464 aopPut (AOP (result), "a", offr);
6470 /*-----------------------------------------------------------------*/
6471 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6472 /*-----------------------------------------------------------------*/
6474 shiftRLeftOrResult (operand * left, int offl,
6475 operand * result, int offr, int shCount)
6477 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6478 /* shift right accumulator */
6480 /* or with result */
6481 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6482 /* back to result */
6483 aopPut (AOP (result), "a", offr);
6489 /*-----------------------------------------------------------------*/
6490 /* genlshOne - left shift a one byte quantity by known count */
6491 /*-----------------------------------------------------------------*/
6493 genlshOne (operand * result, operand * left, int shCount)
6495 D (emitcode (";", "genlshOne ");
6497 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6503 /*-----------------------------------------------------------------*/
6504 /* genlshTwo - left shift two bytes by known amount != 0 */
6505 /*-----------------------------------------------------------------*/
6507 genlshTwo (operand * result, operand * left, int shCount)
6511 D (emitcode (";", "genlshTwo ");
6514 size = getDataSize (result);
6516 /* if shCount >= 8 */
6524 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6526 movLeft2Result (left, LSB, result, MSB16, 0);
6528 aopPut (AOP (result), zero, LSB);
6531 /* 1 <= shCount <= 7 */
6535 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6537 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6544 /*-----------------------------------------------------------------*/
6545 /* shiftLLong - shift left one long from left to result */
6546 /* offl = LSB or MSB16 */
6547 /*-----------------------------------------------------------------*/
6549 shiftLLong (operand * left, operand * result, int offr)
6552 int size = AOP_SIZE (result);
6554 if (size >= LSB + offr)
6556 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6558 emitcode ("add", "a,acc");
6559 if (sameRegs (AOP (left), AOP (result)) &&
6560 size >= MSB16 + offr && offr != LSB)
6561 emitcode ("xch", "a,%s",
6562 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6564 aopPut (AOP (result), "a", LSB + offr);
6567 if (size >= MSB16 + offr)
6569 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6571 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6574 emitcode ("rlc", "a");
6575 if (sameRegs (AOP (left), AOP (result)) &&
6576 size >= MSB24 + offr && offr != LSB)
6577 emitcode ("xch", "a,%s",
6578 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6580 aopPut (AOP (result), "a", MSB16 + offr);
6583 if (size >= MSB24 + offr)
6585 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6587 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6590 emitcode ("rlc", "a");
6591 if (sameRegs (AOP (left), AOP (result)) &&
6592 size >= MSB32 + offr && offr != LSB)
6593 emitcode ("xch", "a,%s",
6594 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6596 aopPut (AOP (result), "a", MSB24 + offr);
6599 if (size > MSB32 + offr)
6601 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6603 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6606 emitcode ("rlc", "a");
6607 aopPut (AOP (result), "a", MSB32 + offr);
6610 aopPut (AOP (result), zero, LSB);
6616 /*-----------------------------------------------------------------*/
6617 /* genlshFour - shift four byte by a known amount != 0 */
6618 /*-----------------------------------------------------------------*/
6620 genlshFour (operand * result, operand * left, int shCount)
6624 D (emitcode (";", "genlshFour ");
6627 size = AOP_SIZE (result);
6629 /* if shifting more that 3 bytes */
6634 /* lowest order of left goes to the highest
6635 order of the destination */
6636 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6638 movLeft2Result (left, LSB, result, MSB32, 0);
6639 aopPut (AOP (result), zero, LSB);
6640 aopPut (AOP (result), zero, MSB16);
6641 aopPut (AOP (result), zero, MSB32);
6645 /* more than two bytes */
6646 else if (shCount >= 16)
6648 /* lower order two bytes goes to higher order two bytes */
6650 /* if some more remaining */
6652 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6655 movLeft2Result (left, MSB16, result, MSB32, 0);
6656 movLeft2Result (left, LSB, result, MSB24, 0);
6658 aopPut (AOP (result), zero, MSB16);
6659 aopPut (AOP (result), zero, LSB);
6663 /* if more than 1 byte */
6664 else if (shCount >= 8)
6666 /* lower order three bytes goes to higher order three bytes */
6671 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6673 movLeft2Result (left, LSB, result, MSB16, 0);
6679 movLeft2Result (left, MSB24, result, MSB32, 0);
6680 movLeft2Result (left, MSB16, result, MSB24, 0);
6681 movLeft2Result (left, LSB, result, MSB16, 0);
6682 aopPut (AOP (result), zero, LSB);
6684 else if (shCount == 1)
6685 shiftLLong (left, result, MSB16);
6688 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6689 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6690 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6691 aopPut (AOP (result), zero, LSB);
6696 /* 1 <= shCount <= 7 */
6697 else if (shCount <= 2)
6699 shiftLLong (left, result, LSB);
6701 shiftLLong (result, result, LSB);
6703 /* 3 <= shCount <= 7, optimize */
6706 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6707 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6708 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6715 /*-----------------------------------------------------------------*/
6716 /* genLeftShiftLiteral - left shifting by known count */
6717 /*-----------------------------------------------------------------*/
6719 genLeftShiftLiteral (operand * left,
6724 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6727 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6730 freeAsmop (right, NULL, ic, TRUE);
6732 aopOp (left, ic, FALSE, FALSE);
6733 aopOp (result, ic, FALSE, TRUE);
6735 size = getSize (operandType (result));
6738 emitcode ("; shift left ", "result %d, left %d", size,
6742 /* I suppose that the left size >= result size */
6747 movLeft2Result (left, size, result, size, 0);
6751 else if (shCount >= (size * 8))
6753 aopPut (AOP (result), zero, size);
6759 genlshOne (result, left, shCount);
6763 case 3: /* bug: this is for generic pointers, I bet. */
6764 genlshTwo (result, left, shCount);
6768 genlshFour (result, left, shCount);
6772 freeAsmop (left, NULL, ic, TRUE);
6773 freeAsmop (result, NULL, ic, TRUE);
6777 /*-----------------------------------------------------------------*/
6778 /* genLeftShift - generates code for left shifting */
6779 /*-----------------------------------------------------------------*/
6781 genLeftShift (iCode * ic)
6783 operand *left, *right, *result;
6786 symbol *tlbl, *tlbl1;
6788 D (emitcode (";", "genLeftShift ");
6791 right = IC_RIGHT (ic);
6792 left = IC_LEFT (ic);
6793 result = IC_RESULT (ic);
6795 aopOp (right, ic, FALSE, FALSE);
6798 /* if the shift count is known then do it
6799 as efficiently as possible */
6800 if (AOP_TYPE (right) == AOP_LIT)
6802 genLeftShiftLiteral (left, right, result, ic);
6807 /* shift count is unknown then we have to form
6808 a loop get the loop count in B : Note: we take
6809 only the lower order byte since shifting
6810 more that 32 bits make no sense anyway, ( the
6811 largest size of an object can be only 32 bits ) */
6813 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6814 emitcode ("inc", "b");
6815 freeAsmop (right, NULL, ic, TRUE);
6816 aopOp (left, ic, FALSE, FALSE);
6817 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6819 /* now move the left to the result if they are not the
6821 if (!sameRegs (AOP (left), AOP (result)) &&
6822 AOP_SIZE (result) > 1)
6825 size = AOP_SIZE (result);
6827 _startLazyDPSEvaluation ();
6830 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6831 if (*l == '@' && (IS_AOP_PREG (result)))
6834 emitcode ("mov", "a,%s", l);
6835 aopPut (AOP (result), "a", offset);
6838 aopPut (AOP (result), l, offset);
6841 _endLazyDPSEvaluation ();
6844 tlbl = newiTempLabel (NULL);
6845 size = AOP_SIZE (result);
6847 tlbl1 = newiTempLabel (NULL);
6849 /* if it is only one byte then */
6852 symbol *tlbl1 = newiTempLabel (NULL);
6854 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6856 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6857 emitcode ("", "%05d$:", tlbl->key + 100);
6858 emitcode ("add", "a,acc");
6859 emitcode ("", "%05d$:", tlbl1->key + 100);
6860 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6861 aopPut (AOP (result), "a", 0);
6865 reAdjustPreg (AOP (result));
6867 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6868 emitcode ("", "%05d$:", tlbl->key + 100);
6869 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6871 emitcode ("add", "a,acc");
6872 aopPut (AOP (result), "a", offset++);
6873 _startLazyDPSEvaluation ();
6876 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6878 emitcode ("rlc", "a");
6879 aopPut (AOP (result), "a", offset++);
6881 _endLazyDPSEvaluation ();
6882 reAdjustPreg (AOP (result));
6884 emitcode ("", "%05d$:", tlbl1->key + 100);
6885 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6887 freeAsmop (left, NULL, ic, TRUE);
6888 freeAsmop (result, NULL, ic, TRUE);
6893 /*-----------------------------------------------------------------*/
6894 /* genrshOne - right shift a one byte quantity by known count */
6895 /*-----------------------------------------------------------------*/
6897 genrshOne (operand * result, operand * left,
6898 int shCount, int sign)
6900 D (emitcode (";", "genrshOne");
6902 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6908 /*-----------------------------------------------------------------*/
6909 /* genrshTwo - right shift two bytes by known amount != 0 */
6910 /*-----------------------------------------------------------------*/
6912 genrshTwo (operand * result, operand * left,
6913 int shCount, int sign)
6915 D (emitcode (";", "genrshTwo");
6918 /* if shCount >= 8 */
6923 shiftR1Left2Result (left, MSB16, result, LSB,
6926 movLeft2Result (left, MSB16, result, LSB, sign);
6927 addSign (result, MSB16, sign);
6930 /* 1 <= shCount <= 7 */
6932 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6938 /*-----------------------------------------------------------------*/
6939 /* shiftRLong - shift right one long from left to result */
6940 /* offl = LSB or MSB16 */
6941 /*-----------------------------------------------------------------*/
6943 shiftRLong (operand * left, int offl,
6944 operand * result, int sign)
6947 emitcode ("clr", "c");
6948 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6950 emitcode ("mov", "c,acc.7");
6951 emitcode ("rrc", "a");
6952 aopPut (AOP (result), "a", MSB32 - offl);
6954 /* add sign of "a" */
6955 addSign (result, MSB32, sign);
6957 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6958 emitcode ("rrc", "a");
6959 aopPut (AOP (result), "a", MSB24 - offl);
6961 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6962 emitcode ("rrc", "a");
6963 aopPut (AOP (result), "a", MSB16 - offl);
6967 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6968 emitcode ("rrc", "a");
6969 aopPut (AOP (result), "a", LSB);
6976 /*-----------------------------------------------------------------*/
6977 /* genrshFour - shift four byte by a known amount != 0 */
6978 /*-----------------------------------------------------------------*/
6980 genrshFour (operand * result, operand * left,
6981 int shCount, int sign)
6983 D (emitcode (";", "genrshFour");
6986 /* if shifting more that 3 bytes */
6991 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6993 movLeft2Result (left, MSB32, result, LSB, sign);
6994 addSign (result, MSB16, sign);
6996 else if (shCount >= 16)
7000 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7003 movLeft2Result (left, MSB24, result, LSB, 0);
7004 movLeft2Result (left, MSB32, result, MSB16, sign);
7006 addSign (result, MSB24, sign);
7008 else if (shCount >= 8)
7012 shiftRLong (left, MSB16, result, sign);
7013 else if (shCount == 0)
7015 movLeft2Result (left, MSB16, result, LSB, 0);
7016 movLeft2Result (left, MSB24, result, MSB16, 0);
7017 movLeft2Result (left, MSB32, result, MSB24, sign);
7018 addSign (result, MSB32, sign);
7022 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7023 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7024 /* the last shift is signed */
7025 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7026 addSign (result, MSB32, sign);
7030 { /* 1 <= shCount <= 7 */
7033 shiftRLong (left, LSB, result, sign);
7035 shiftRLong (result, LSB, result, sign);
7039 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7040 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7041 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7049 /*-----------------------------------------------------------------*/
7050 /* genRightShiftLiteral - right shifting by known count */
7051 /*-----------------------------------------------------------------*/
7053 genRightShiftLiteral (operand * left,
7059 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7062 D (emitcode (";", "genRightShiftLiteral");
7065 freeAsmop (right, NULL, ic, TRUE);
7067 aopOp (left, ic, FALSE, FALSE);
7068 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7071 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7075 size = getDataSize (left);
7076 /* test the LEFT size !!! */
7078 /* I suppose that the left size >= result size */
7081 size = getDataSize (result);
7083 movLeft2Result (left, size, result, size, 0);
7086 else if (shCount >= (size * 8))
7089 /* get sign in acc.7 */
7090 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7091 addSign (result, LSB, sign);
7098 genrshOne (result, left, shCount, sign);
7102 genrshTwo (result, left, shCount, sign);
7106 genrshFour (result, left, shCount, sign);
7112 freeAsmop (left, NULL, ic, TRUE);
7113 freeAsmop (result, NULL, ic, TRUE);
7118 /*-----------------------------------------------------------------*/
7119 /* genSignedRightShift - right shift of signed number */
7120 /*-----------------------------------------------------------------*/
7122 genSignedRightShift (iCode * ic)
7124 operand *right, *left, *result;
7127 symbol *tlbl, *tlbl1;
7129 D (emitcode (";", "genSignedRightShift ");
7132 /* we do it the hard way put the shift count in b
7133 and loop thru preserving the sign */
7135 right = IC_RIGHT (ic);
7136 left = IC_LEFT (ic);
7137 result = IC_RESULT (ic);
7139 aopOp (right, ic, FALSE, FALSE);
7142 if (AOP_TYPE (right) == AOP_LIT)
7144 genRightShiftLiteral (left, right, result, ic, 1);
7148 /* shift count is unknown then we have to form
7149 a loop get the loop count in B : Note: we take
7150 only the lower order byte since shifting
7151 more that 32 bits make no sense anyway, ( the
7152 largest size of an object can be only 32 bits ) */
7154 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7155 emitcode ("inc", "b");
7156 freeAsmop (right, NULL, ic, TRUE);
7157 aopOp (left, ic, FALSE, FALSE);
7158 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7160 /* now move the left to the result if they are not the
7162 if (!sameRegs (AOP (left), AOP (result)) &&
7163 AOP_SIZE (result) > 1)
7166 size = AOP_SIZE (result);
7168 _startLazyDPSEvaluation ();
7171 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7172 if (*l == '@' && IS_AOP_PREG (result))
7175 emitcode ("mov", "a,%s", l);
7176 aopPut (AOP (result), "a", offset);
7179 aopPut (AOP (result), l, offset);
7182 _endLazyDPSEvaluation ();
7185 /* mov the highest order bit to OVR */
7186 tlbl = newiTempLabel (NULL);
7187 tlbl1 = newiTempLabel (NULL);
7189 size = AOP_SIZE (result);
7191 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7192 emitcode ("rlc", "a");
7193 emitcode ("mov", "ov,c");
7194 /* if it is only one byte then */
7197 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7199 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7200 emitcode ("", "%05d$:", tlbl->key + 100);
7201 emitcode ("mov", "c,ov");
7202 emitcode ("rrc", "a");
7203 emitcode ("", "%05d$:", tlbl1->key + 100);
7204 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7205 aopPut (AOP (result), "a", 0);
7209 reAdjustPreg (AOP (result));
7210 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7211 emitcode ("", "%05d$:", tlbl->key + 100);
7212 emitcode ("mov", "c,ov");
7213 _startLazyDPSEvaluation ();
7216 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7218 emitcode ("rrc", "a");
7219 aopPut (AOP (result), "a", offset--);
7221 _endLazyDPSEvaluation ();
7222 reAdjustPreg (AOP (result));
7223 emitcode ("", "%05d$:", tlbl1->key + 100);
7224 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7227 freeAsmop (left, NULL, ic, TRUE);
7228 freeAsmop (result, NULL, ic, TRUE);
7231 /*-----------------------------------------------------------------*/
7232 /* genRightShift - generate code for right shifting */
7233 /*-----------------------------------------------------------------*/
7235 genRightShift (iCode * ic)
7237 operand *right, *left, *result;
7241 symbol *tlbl, *tlbl1;
7243 D (emitcode (";", "genRightShift ");
7246 /* if signed then we do it the hard way preserve the
7247 sign bit moving it inwards */
7248 retype = getSpec (operandType (IC_RESULT (ic)));
7250 if (!SPEC_USIGN (retype))
7252 genSignedRightShift (ic);
7256 /* signed & unsigned types are treated the same : i.e. the
7257 signed is NOT propagated inwards : quoting from the
7258 ANSI - standard : "for E1 >> E2, is equivalent to division
7259 by 2**E2 if unsigned or if it has a non-negative value,
7260 otherwise the result is implementation defined ", MY definition
7261 is that the sign does not get propagated */
7263 right = IC_RIGHT (ic);
7264 left = IC_LEFT (ic);
7265 result = IC_RESULT (ic);
7267 aopOp (right, ic, FALSE, FALSE);
7270 /* if the shift count is known then do it
7271 as efficiently as possible */
7272 if (AOP_TYPE (right) == AOP_LIT)
7274 genRightShiftLiteral (left, right, result, ic, 0);
7279 /* shift count is unknown then we have to form
7280 a loop get the loop count in B : Note: we take
7281 only the lower order byte since shifting
7282 more that 32 bits make no sense anyway, ( the
7283 largest size of an object can be only 32 bits ) */
7285 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7286 emitcode ("inc", "b");
7287 freeAsmop (right, NULL, ic, TRUE);
7288 aopOp (left, ic, FALSE, FALSE);
7289 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7291 /* now move the left to the result if they are not the
7293 if (!sameRegs (AOP (left), AOP (result)) &&
7294 AOP_SIZE (result) > 1)
7297 size = AOP_SIZE (result);
7299 _startLazyDPSEvaluation ();
7302 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7303 if (*l == '@' && IS_AOP_PREG (result))
7306 emitcode ("mov", "a,%s", l);
7307 aopPut (AOP (result), "a", offset);
7310 aopPut (AOP (result), l, offset);
7313 _endLazyDPSEvaluation ();
7316 tlbl = newiTempLabel (NULL);
7317 tlbl1 = newiTempLabel (NULL);
7318 size = AOP_SIZE (result);
7321 /* if it is only one byte then */
7324 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7326 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7327 emitcode ("", "%05d$:", tlbl->key + 100);
7329 emitcode ("rrc", "a");
7330 emitcode ("", "%05d$:", tlbl1->key + 100);
7331 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7332 aopPut (AOP (result), "a", 0);
7336 reAdjustPreg (AOP (result));
7337 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7338 emitcode ("", "%05d$:", tlbl->key + 100);
7340 _startLazyDPSEvaluation ();
7343 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7345 emitcode ("rrc", "a");
7346 aopPut (AOP (result), "a", offset--);
7348 _endLazyDPSEvaluation ();
7349 reAdjustPreg (AOP (result));
7351 emitcode ("", "%05d$:", tlbl1->key + 100);
7352 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7355 freeAsmop (left, NULL, ic, TRUE);
7356 freeAsmop (result, NULL, ic, TRUE);
7359 /*-----------------------------------------------------------------*/
7360 /* genUnpackBits - generates code for unpacking bits */
7361 /*-----------------------------------------------------------------*/
7363 genUnpackBits (operand * result, char *rname, int ptype)
7370 D (emitcode (";", "genUnpackBits ");
7373 etype = getSpec (operandType (result));
7375 /* read the first byte */
7381 emitcode ("mov", "a,@%s", rname);
7385 emitcode ("movx", "a,@%s", rname);
7389 emitcode ("movx", "a,@dptr");
7393 emitcode ("clr", "a");
7394 emitcode ("movc", "a", "@a+dptr");
7398 emitcode ("lcall", "__gptrget");
7402 /* if we have bitdisplacement then it fits */
7403 /* into this byte completely or if length is */
7404 /* less than a byte */
7405 if ((shCnt = SPEC_BSTR (etype)) ||
7406 (SPEC_BLEN (etype) <= 8))
7409 /* shift right acc */
7412 emitcode ("anl", "a,#0x%02x",
7413 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7414 aopPut (AOP (result), "a", offset);
7418 /* bit field did not fit in a byte */
7419 rlen = SPEC_BLEN (etype) - 8;
7420 aopPut (AOP (result), "a", offset++);
7429 emitcode ("inc", "%s", rname);
7430 emitcode ("mov", "a,@%s", rname);
7434 emitcode ("inc", "%s", rname);
7435 emitcode ("movx", "a,@%s", rname);
7439 emitcode ("inc", "dptr");
7440 emitcode ("movx", "a,@dptr");
7444 emitcode ("clr", "a");
7445 emitcode ("inc", "dptr");
7446 emitcode ("movc", "a", "@a+dptr");
7450 emitcode ("inc", "dptr");
7451 emitcode ("lcall", "__gptrget");
7456 /* if we are done */
7460 aopPut (AOP (result), "a", offset++);
7466 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7467 aopPut (AOP (result), "a", offset);
7474 /*-----------------------------------------------------------------*/
7475 /* genDataPointerGet - generates code when ptr offset is known */
7476 /*-----------------------------------------------------------------*/
7478 genDataPointerGet (operand * left,
7484 int size, offset = 0;
7485 aopOp (result, ic, TRUE, FALSE);
7487 /* get the string representation of the name */
7488 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7489 size = AOP_SIZE (result);
7490 _startLazyDPSEvaluation ();
7494 sprintf (buffer, "(%s + %d)", l + 1, offset);
7496 sprintf (buffer, "%s", l + 1);
7497 aopPut (AOP (result), buffer, offset++);
7499 _endLazyDPSEvaluation ();
7501 freeAsmop (left, NULL, ic, TRUE);
7502 freeAsmop (result, NULL, ic, TRUE);
7505 /*-----------------------------------------------------------------*/
7506 /* genNearPointerGet - emitcode for near pointer fetch */
7507 /*-----------------------------------------------------------------*/
7509 genNearPointerGet (operand * left,
7516 sym_link *rtype, *retype, *letype;
7517 sym_link *ltype = operandType (left);
7520 rtype = operandType (result);
7521 retype = getSpec (rtype);
7522 letype = getSpec (ltype);
7524 aopOp (left, ic, FALSE, FALSE);
7526 /* if left is rematerialisable and
7527 result is not bit variable type and
7528 the left is pointer to data space i.e
7529 lower 128 bytes of space */
7530 if (AOP_TYPE (left) == AOP_IMMD &&
7531 !IS_BITVAR (retype) &&
7532 !IS_BITVAR (letype) &&
7533 DCL_TYPE (ltype) == POINTER)
7535 genDataPointerGet (left, result, ic);
7539 /* if the value is already in a pointer register
7540 then don't need anything more */
7541 if (!AOP_INPREG (AOP (left)))
7543 /* otherwise get a free pointer register */
7545 preg = getFreePtr (ic, &aop, FALSE);
7546 emitcode ("mov", "%s,%s",
7548 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7552 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7554 freeAsmop (left, NULL, ic, TRUE);
7555 aopOp (result, ic, FALSE, FALSE);
7557 /* if bitfield then unpack the bits */
7558 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7559 genUnpackBits (result, rname, POINTER);
7562 /* we have can just get the values */
7563 int size = AOP_SIZE (result);
7568 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7571 emitcode ("mov", "a,@%s", rname);
7572 aopPut (AOP (result), "a", offset);
7576 sprintf (buffer, "@%s", rname);
7577 aopPut (AOP (result), buffer, offset);
7581 emitcode ("inc", "%s", rname);
7585 /* now some housekeeping stuff */
7588 /* we had to allocate for this iCode */
7589 freeAsmop (NULL, aop, ic, TRUE);
7593 /* we did not allocate which means left
7594 already in a pointer register, then
7595 if size > 0 && this could be used again
7596 we have to point it back to where it
7598 if (AOP_SIZE (result) > 1 &&
7599 !OP_SYMBOL (left)->remat &&
7600 (OP_SYMBOL (left)->liveTo > ic->seq ||
7603 int size = AOP_SIZE (result) - 1;
7605 emitcode ("dec", "%s", rname);
7610 freeAsmop (result, NULL, ic, TRUE);
7614 /*-----------------------------------------------------------------*/
7615 /* genPagedPointerGet - emitcode for paged pointer fetch */
7616 /*-----------------------------------------------------------------*/
7618 genPagedPointerGet (operand * left,
7625 sym_link *rtype, *retype, *letype;
7627 rtype = operandType (result);
7628 retype = getSpec (rtype);
7629 letype = getSpec (operandType (left));
7630 aopOp (left, ic, FALSE, FALSE);
7632 /* if the value is already in a pointer register
7633 then don't need anything more */
7634 if (!AOP_INPREG (AOP (left)))
7636 /* otherwise get a free pointer register */
7638 preg = getFreePtr (ic, &aop, FALSE);
7639 emitcode ("mov", "%s,%s",
7641 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7645 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7647 freeAsmop (left, NULL, ic, TRUE);
7648 aopOp (result, ic, FALSE, FALSE);
7650 /* if bitfield then unpack the bits */
7651 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7652 genUnpackBits (result, rname, PPOINTER);
7655 /* we have can just get the values */
7656 int size = AOP_SIZE (result);
7662 emitcode ("movx", "a,@%s", rname);
7663 aopPut (AOP (result), "a", offset);
7668 emitcode ("inc", "%s", rname);
7672 /* now some housekeeping stuff */
7675 /* we had to allocate for this iCode */
7676 freeAsmop (NULL, aop, ic, TRUE);
7680 /* we did not allocate which means left
7681 already in a pointer register, then
7682 if size > 0 && this could be used again
7683 we have to point it back to where it
7685 if (AOP_SIZE (result) > 1 &&
7686 !OP_SYMBOL (left)->remat &&
7687 (OP_SYMBOL (left)->liveTo > ic->seq ||
7690 int size = AOP_SIZE (result) - 1;
7692 emitcode ("dec", "%s", rname);
7697 freeAsmop (result, NULL, ic, TRUE);
7702 /*-----------------------------------------------------------------*/
7703 /* genFarPointerGet - gget value from far space */
7704 /*-----------------------------------------------------------------*/
7706 genFarPointerGet (operand * left,
7707 operand * result, iCode * ic)
7710 sym_link *retype = getSpec (operandType (result));
7711 sym_link *letype = getSpec (operandType (left));
7712 D (emitcode (";", "genFarPointerGet");
7715 aopOp (left, ic, FALSE, FALSE);
7717 /* if the operand is already in dptr
7718 then we do nothing else we move the value to dptr */
7719 if (AOP_TYPE (left) != AOP_STR)
7721 /* if this is remateriazable */
7722 if (AOP_TYPE (left) == AOP_IMMD)
7724 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7728 /* we need to get it byte by byte */
7729 _startLazyDPSEvaluation ();
7730 if (AOP_TYPE (left) != AOP_DPTR)
7732 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7733 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7734 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7738 /* We need to generate a load to DPTR indirect through DPTR. */
7739 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7741 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7742 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7743 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7744 emitcode ("pop", "dph");
7745 emitcode ("pop", "dpl");
7747 _endLazyDPSEvaluation ();
7750 /* so dptr know contains the address */
7751 freeAsmop (left, NULL, ic, TRUE);
7752 aopOp (result, ic, FALSE, TRUE);
7754 /* if bit then unpack */
7755 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7756 genUnpackBits (result, "dptr", FPOINTER);
7759 size = AOP_SIZE (result);
7762 _startLazyDPSEvaluation ();
7769 emitcode ("movx", "a,@dptr");
7771 emitcode ("inc", "dptr");
7773 aopPut (AOP (result), "a", offset++);
7775 _endLazyDPSEvaluation ();
7778 freeAsmop (result, NULL, ic, TRUE);
7781 /*-----------------------------------------------------------------*/
7782 /* emitcodePointerGet - gget value from code space */
7783 /*-----------------------------------------------------------------*/
7785 emitcodePointerGet (operand * left,
7786 operand * result, iCode * ic)
7789 sym_link *retype = getSpec (operandType (result));
7791 aopOp (left, ic, FALSE, FALSE);
7793 /* if the operand is already in dptr
7794 then we do nothing else we move the value to dptr */
7795 if (AOP_TYPE (left) != AOP_STR)
7797 /* if this is remateriazable */
7798 if (AOP_TYPE (left) == AOP_IMMD)
7800 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7803 { /* we need to get it byte by byte */
7804 _startLazyDPSEvaluation ();
7805 if (AOP_TYPE (left) != AOP_DPTR)
7807 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7808 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7809 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7813 /* We need to generate a load to DPTR indirect through DPTR. */
7814 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7816 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7817 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7818 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7819 emitcode ("pop", "dph");
7820 emitcode ("pop", "dpl");
7822 _endLazyDPSEvaluation ();
7825 /* so dptr know contains the address */
7826 freeAsmop (left, NULL, ic, TRUE);
7827 aopOp (result, ic, FALSE, TRUE);
7829 /* if bit then unpack */
7830 if (IS_BITVAR (retype))
7831 genUnpackBits (result, "dptr", CPOINTER);
7834 size = AOP_SIZE (result);
7837 _startLazyDPSEvaluation ();
7843 emitcode ("clr", "a");
7844 emitcode ("movc", "a,@a+dptr");
7846 emitcode ("inc", "dptr");
7847 aopPut (AOP (result), "a", offset++);
7849 _endLazyDPSEvaluation ();
7852 freeAsmop (result, NULL, ic, TRUE);
7855 /*-----------------------------------------------------------------*/
7856 /* genGenPointerGet - gget value from generic pointer space */
7857 /*-----------------------------------------------------------------*/
7859 genGenPointerGet (operand * left,
7860 operand * result, iCode * ic)
7863 sym_link *retype = getSpec (operandType (result));
7864 sym_link *letype = getSpec (operandType (left));
7866 D (emitcode (";", "genGenPointerGet "); );
7868 aopOp (left, ic, FALSE, TRUE);
7870 /* if the operand is already in dptr
7871 then we do nothing else we move the value to dptr */
7872 if (AOP_TYPE (left) != AOP_STR)
7874 /* if this is remateriazable */
7875 if (AOP_TYPE (left) == AOP_IMMD)
7877 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7878 emitcode ("mov", "b,#%d", pointerCode (retype));
7881 { /* we need to get it byte by byte */
7882 _startLazyDPSEvaluation ();
7883 if (AOP(left)->type==AOP_DPTR2) {
7885 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7888 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7889 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7892 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7893 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7896 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7897 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7899 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7900 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7901 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7902 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7904 _endLazyDPSEvaluation ();
7907 /* so dptr know contains the address */
7908 freeAsmop (left, NULL, ic, TRUE);
7909 aopOp (result, ic, FALSE, TRUE);
7911 /* if bit then unpack */
7912 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7913 genUnpackBits (result, "dptr", GPOINTER);
7916 size = AOP_SIZE (result);
7921 emitcode ("lcall", "__gptrget");
7922 aopPut (AOP (result), "a", offset++);
7924 emitcode ("inc", "dptr");
7928 freeAsmop (result, NULL, ic, TRUE);
7931 /*-----------------------------------------------------------------*/
7932 /* genPointerGet - generate code for pointer get */
7933 /*-----------------------------------------------------------------*/
7935 genPointerGet (iCode * ic)
7937 operand *left, *result;
7938 sym_link *type, *etype;
7941 D (emitcode (";", "genPointerGet ");
7944 left = IC_LEFT (ic);
7945 result = IC_RESULT (ic);
7947 /* depending on the type of pointer we need to
7948 move it to the correct pointer register */
7949 type = operandType (left);
7950 etype = getSpec (type);
7951 /* if left is of type of pointer then it is simple */
7952 if (IS_PTR (type) && !IS_FUNC (type->next))
7953 p_type = DCL_TYPE (type);
7956 /* we have to go by the storage class */
7957 p_type = PTR_TYPE (SPEC_OCLS (etype));
7960 /* now that we have the pointer type we assign
7961 the pointer values */
7967 genNearPointerGet (left, result, ic);
7971 genPagedPointerGet (left, result, ic);
7975 genFarPointerGet (left, result, ic);
7979 emitcodePointerGet (left, result, ic);
7983 genGenPointerGet (left, result, ic);
7989 /*-----------------------------------------------------------------*/
7990 /* genPackBits - generates code for packed bit storage */
7991 /*-----------------------------------------------------------------*/
7993 genPackBits (sym_link * etype,
7995 char *rname, int p_type)
8003 blen = SPEC_BLEN (etype);
8004 bstr = SPEC_BSTR (etype);
8006 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8009 /* if the bit lenth is less than or */
8010 /* it exactly fits a byte then */
8011 if (SPEC_BLEN (etype) <= 8)
8013 shCount = SPEC_BSTR (etype);
8015 /* shift left acc */
8018 if (SPEC_BLEN (etype) < 8)
8019 { /* if smaller than a byte */
8025 emitcode ("mov", "b,a");
8026 emitcode ("mov", "a,@%s", rname);
8030 emitcode ("mov", "b,a");
8031 emitcode ("movx", "a,@dptr");
8035 emitcode ("push", "b");
8036 emitcode ("push", "acc");
8037 emitcode ("lcall", "__gptrget");
8038 emitcode ("pop", "b");
8042 emitcode ("anl", "a,#0x%02x", (unsigned char)
8043 ((unsigned char) (0xFF << (blen + bstr)) |
8044 (unsigned char) (0xFF >> (8 - bstr))));
8045 emitcode ("orl", "a,b");
8046 if (p_type == GPOINTER)
8047 emitcode ("pop", "b");
8054 emitcode ("mov", "@%s,a", rname);
8058 emitcode ("movx", "@dptr,a");
8062 emitcode ("lcall", "__gptrput");
8067 if (SPEC_BLEN (etype) <= 8)
8070 emitcode ("inc", "%s", rname);
8071 rLen = SPEC_BLEN (etype);
8073 /* now generate for lengths greater than one byte */
8077 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8089 emitcode ("mov", "@%s,a", rname);
8092 emitcode ("mov", "@%s,%s", rname, l);
8097 emitcode ("movx", "@dptr,a");
8102 emitcode ("lcall", "__gptrput");
8105 emitcode ("inc", "%s", rname);
8110 /* last last was not complete */
8113 /* save the byte & read byte */
8117 emitcode ("mov", "b,a");
8118 emitcode ("mov", "a,@%s", rname);
8122 emitcode ("mov", "b,a");
8123 emitcode ("movx", "a,@dptr");
8127 emitcode ("push", "b");
8128 emitcode ("push", "acc");
8129 emitcode ("lcall", "__gptrget");
8130 emitcode ("pop", "b");
8134 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8135 emitcode ("orl", "a,b");
8138 if (p_type == GPOINTER)
8139 emitcode ("pop", "b");
8145 emitcode ("mov", "@%s,a", rname);
8149 emitcode ("movx", "@dptr,a");
8153 emitcode ("lcall", "__gptrput");
8157 /*-----------------------------------------------------------------*/
8158 /* genDataPointerSet - remat pointer to data space */
8159 /*-----------------------------------------------------------------*/
8161 genDataPointerSet (operand * right,
8165 int size, offset = 0;
8166 char *l, buffer[256];
8168 aopOp (right, ic, FALSE, FALSE);
8170 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8171 size = AOP_SIZE (right);
8175 sprintf (buffer, "(%s + %d)", l + 1, offset);
8177 sprintf (buffer, "%s", l + 1);
8178 emitcode ("mov", "%s,%s", buffer,
8179 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8182 freeAsmop (right, NULL, ic, TRUE);
8183 freeAsmop (result, NULL, ic, TRUE);
8186 /*-----------------------------------------------------------------*/
8187 /* genNearPointerSet - emitcode for near pointer put */
8188 /*-----------------------------------------------------------------*/
8190 genNearPointerSet (operand * right,
8197 sym_link *retype, *letype;
8198 sym_link *ptype = operandType (result);
8200 retype = getSpec (operandType (right));
8201 letype = getSpec (ptype);
8203 aopOp (result, ic, FALSE, FALSE);
8205 /* if the result is rematerializable &
8206 in data space & not a bit variable */
8207 if (AOP_TYPE (result) == AOP_IMMD &&
8208 DCL_TYPE (ptype) == POINTER &&
8209 !IS_BITVAR (retype) &&
8210 !IS_BITVAR (letype))
8212 genDataPointerSet (right, result, ic);
8216 /* if the value is already in a pointer register
8217 then don't need anything more */
8218 if (!AOP_INPREG (AOP (result)))
8220 /* otherwise get a free pointer register */
8222 preg = getFreePtr (ic, &aop, FALSE);
8223 emitcode ("mov", "%s,%s",
8225 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8229 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8231 freeAsmop (result, NULL, ic, TRUE);
8232 aopOp (right, ic, FALSE, FALSE);
8234 /* if bitfield then unpack the bits */
8235 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8236 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8239 /* we have can just get the values */
8240 int size = AOP_SIZE (right);
8245 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8249 emitcode ("mov", "@%s,a", rname);
8252 emitcode ("mov", "@%s,%s", rname, l);
8254 emitcode ("inc", "%s", rname);
8259 /* now some housekeeping stuff */
8262 /* we had to allocate for this iCode */
8263 freeAsmop (NULL, aop, ic, TRUE);
8267 /* we did not allocate which means left
8268 already in a pointer register, then
8269 if size > 0 && this could be used again
8270 we have to point it back to where it
8272 if (AOP_SIZE (right) > 1 &&
8273 !OP_SYMBOL (result)->remat &&
8274 (OP_SYMBOL (result)->liveTo > ic->seq ||
8277 int size = AOP_SIZE (right) - 1;
8279 emitcode ("dec", "%s", rname);
8284 freeAsmop (right, NULL, ic, TRUE);
8289 /*-----------------------------------------------------------------*/
8290 /* genPagedPointerSet - emitcode for Paged pointer put */
8291 /*-----------------------------------------------------------------*/
8293 genPagedPointerSet (operand * right,
8300 sym_link *retype, *letype;
8302 retype = getSpec (operandType (right));
8303 letype = getSpec (operandType (result));
8305 aopOp (result, ic, FALSE, FALSE);
8307 /* if the value is already in a pointer register
8308 then don't need anything more */
8309 if (!AOP_INPREG (AOP (result)))
8311 /* otherwise get a free pointer register */
8313 preg = getFreePtr (ic, &aop, FALSE);
8314 emitcode ("mov", "%s,%s",
8316 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8320 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8322 freeAsmop (result, NULL, ic, TRUE);
8323 aopOp (right, ic, FALSE, FALSE);
8325 /* if bitfield then unpack the bits */
8326 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8327 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8330 /* we have can just get the values */
8331 int size = AOP_SIZE (right);
8336 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8339 emitcode ("movx", "@%s,a", rname);
8342 emitcode ("inc", "%s", rname);
8348 /* now some housekeeping stuff */
8351 /* we had to allocate for this iCode */
8352 freeAsmop (NULL, aop, ic, TRUE);
8356 /* we did not allocate which means left
8357 already in a pointer register, then
8358 if size > 0 && this could be used again
8359 we have to point it back to where it
8361 if (AOP_SIZE (right) > 1 &&
8362 !OP_SYMBOL (result)->remat &&
8363 (OP_SYMBOL (result)->liveTo > ic->seq ||
8366 int size = AOP_SIZE (right) - 1;
8368 emitcode ("dec", "%s", rname);
8373 freeAsmop (right, NULL, ic, TRUE);
8378 /*-----------------------------------------------------------------*/
8379 /* genFarPointerSet - set value from far space */
8380 /*-----------------------------------------------------------------*/
8382 genFarPointerSet (operand * right,
8383 operand * result, iCode * ic)
8386 sym_link *retype = getSpec (operandType (right));
8387 sym_link *letype = getSpec (operandType (result));
8389 aopOp (result, ic, FALSE, FALSE);
8391 /* if the operand is already in dptr
8392 then we do nothing else we move the value to dptr */
8393 if (AOP_TYPE (result) != AOP_STR)
8395 /* if this is remateriazable */
8396 if (AOP_TYPE (result) == AOP_IMMD)
8397 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8400 /* we need to get it byte by byte */
8401 _startLazyDPSEvaluation ();
8402 if (AOP_TYPE (result) != AOP_DPTR)
8404 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8405 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8406 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8410 /* We need to generate a load to DPTR indirect through DPTR. */
8411 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8413 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8414 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8415 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8416 emitcode ("pop", "dph");
8417 emitcode ("pop", "dpl");
8419 _endLazyDPSEvaluation ();
8422 /* so dptr know contains the address */
8423 freeAsmop (result, NULL, ic, TRUE);
8424 aopOp (right, ic, FALSE, TRUE);
8426 /* if bit then unpack */
8427 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8428 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8431 size = AOP_SIZE (right);
8434 _startLazyDPSEvaluation ();
8437 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8443 emitcode ("movx", "@dptr,a");
8445 emitcode ("inc", "dptr");
8447 _endLazyDPSEvaluation ();
8450 freeAsmop (right, NULL, ic, TRUE);
8453 /*-----------------------------------------------------------------*/
8454 /* genGenPointerSet - set value from generic pointer space */
8455 /*-----------------------------------------------------------------*/
8457 genGenPointerSet (operand * right,
8458 operand * result, iCode * ic)
8461 sym_link *retype = getSpec (operandType (right));
8462 sym_link *letype = getSpec (operandType (result));
8464 aopOp (result, ic, FALSE, TRUE);
8466 /* if the operand is already in dptr
8467 then we do nothing else we move the value to dptr */
8468 if (AOP_TYPE (result) != AOP_STR)
8470 _startLazyDPSEvaluation ();
8471 /* if this is remateriazable */
8472 if (AOP_TYPE (result) == AOP_IMMD)
8474 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8475 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8478 { /* we need to get it byte by byte */
8479 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8480 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8481 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8482 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8484 _endLazyDPSEvaluation ();
8486 /* so dptr know contains the address */
8487 freeAsmop (result, NULL, ic, TRUE);
8488 aopOp (right, ic, FALSE, TRUE);
8490 /* if bit then unpack */
8491 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8492 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8495 size = AOP_SIZE (right);
8498 _startLazyDPSEvaluation ();
8501 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8507 emitcode ("lcall", "__gptrput");
8509 emitcode ("inc", "dptr");
8511 _endLazyDPSEvaluation ();
8514 freeAsmop (right, NULL, ic, TRUE);
8517 /*-----------------------------------------------------------------*/
8518 /* genPointerSet - stores the value into a pointer location */
8519 /*-----------------------------------------------------------------*/
8521 genPointerSet (iCode * ic)
8523 operand *right, *result;
8524 sym_link *type, *etype;
8527 D (emitcode (";", "genPointerSet ");
8530 right = IC_RIGHT (ic);
8531 result = IC_RESULT (ic);
8533 /* depending on the type of pointer we need to
8534 move it to the correct pointer register */
8535 type = operandType (result);
8536 etype = getSpec (type);
8537 /* if left is of type of pointer then it is simple */
8538 if (IS_PTR (type) && !IS_FUNC (type->next))
8540 p_type = DCL_TYPE (type);
8544 /* we have to go by the storage class */
8545 p_type = PTR_TYPE (SPEC_OCLS (etype));
8548 /* now that we have the pointer type we assign
8549 the pointer values */
8555 genNearPointerSet (right, result, ic);
8559 genPagedPointerSet (right, result, ic);
8563 genFarPointerSet (right, result, ic);
8567 genGenPointerSet (right, result, ic);
8573 /*-----------------------------------------------------------------*/
8574 /* genIfx - generate code for Ifx statement */
8575 /*-----------------------------------------------------------------*/
8577 genIfx (iCode * ic, iCode * popIc)
8579 operand *cond = IC_COND (ic);
8582 D (emitcode (";", "genIfx ");
8585 aopOp (cond, ic, FALSE, FALSE);
8587 /* get the value into acc */
8588 if (AOP_TYPE (cond) != AOP_CRY)
8592 /* the result is now in the accumulator */
8593 freeAsmop (cond, NULL, ic, TRUE);
8595 /* if there was something to be popped then do it */
8599 /* if the condition is a bit variable */
8600 if (isbit && IS_ITEMP (cond) &&
8602 genIfxJump (ic, SPIL_LOC (cond)->rname);
8603 else if (isbit && !IS_ITEMP (cond))
8604 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8606 genIfxJump (ic, "a");
8611 /*-----------------------------------------------------------------*/
8612 /* genAddrOf - generates code for address of */
8613 /*-----------------------------------------------------------------*/
8615 genAddrOf (iCode * ic)
8617 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8620 D (emitcode (";", "genAddrOf ");
8623 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8625 /* if the operand is on the stack then we
8626 need to get the stack offset of this
8630 /* if it has an offset then we need to compute
8634 emitcode ("mov", "a,_bp");
8635 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8636 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8640 /* we can just move _bp */
8641 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8643 /* fill the result with zero */
8644 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8647 if (options.stack10bit && size < (FPTRSIZE - 1))
8650 "*** warning: pointer to stack var truncated.\n");
8657 if (options.stack10bit && offset == 2)
8659 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8663 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8670 /* object not on stack then we need the name */
8671 size = AOP_SIZE (IC_RESULT (ic));
8676 char s[SDCC_NAME_MAX];
8678 sprintf (s, "#(%s >> %d)",
8682 sprintf (s, "#%s", sym->rname);
8683 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8687 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8691 /*-----------------------------------------------------------------*/
8692 /* genFarFarAssign - assignment when both are in far space */
8693 /*-----------------------------------------------------------------*/
8695 genFarFarAssign (operand * result, operand * right, iCode * ic)
8697 int size = AOP_SIZE (right);
8703 /* This is a net loss for size == 1, but a big gain
8706 D (emitcode (";", "genFarFarAssign (improved)");
8709 aopOp (result, ic, TRUE, TRUE);
8711 _startLazyDPSEvaluation ();
8714 aopPut (AOP (result),
8715 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8718 _endLazyDPSEvaluation ();
8719 freeAsmop (result, NULL, ic, FALSE);
8720 freeAsmop (right, NULL, ic, FALSE);
8724 D (emitcode (";", "genFarFarAssign ");
8727 /* first push the right side on to the stack */
8728 _startLazyDPSEvaluation ();
8731 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8733 emitcode ("push", "acc");
8736 freeAsmop (right, NULL, ic, FALSE);
8737 /* now assign DPTR to result */
8738 aopOp (result, ic, FALSE, FALSE);
8739 size = AOP_SIZE (result);
8742 emitcode ("pop", "acc");
8743 aopPut (AOP (result), "a", --offset);
8745 freeAsmop (result, NULL, ic, FALSE);
8746 _endLazyDPSEvaluation ();
8750 /*-----------------------------------------------------------------*/
8751 /* genAssign - generate code for assignment */
8752 /*-----------------------------------------------------------------*/
8754 genAssign (iCode * ic)
8756 operand *result, *right;
8758 unsigned long lit = 0L;
8760 D (emitcode (";", "genAssign ");
8763 result = IC_RESULT (ic);
8764 right = IC_RIGHT (ic);
8766 /* if they are the same */
8767 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8770 aopOp (right, ic, FALSE, FALSE);
8772 emitcode (";", "genAssign: resultIsFar = %s",
8773 isOperandInFarSpace (result) ?
8776 /* special case both in far space */
8777 if ((AOP_TYPE (right) == AOP_DPTR ||
8778 AOP_TYPE (right) == AOP_DPTR2) &&
8779 /* IS_TRUE_SYMOP(result) && */
8780 isOperandInFarSpace (result))
8782 genFarFarAssign (result, right, ic);
8786 aopOp (result, ic, TRUE, FALSE);
8788 /* if they are the same registers */
8789 if (sameRegs (AOP (right), AOP (result)))
8792 /* if the result is a bit */
8793 if (AOP_TYPE (result) == AOP_CRY)
8796 /* if the right size is a literal then
8797 we know what the value is */
8798 if (AOP_TYPE (right) == AOP_LIT)
8800 if (((int) operandLitValue (right)))
8801 aopPut (AOP (result), one, 0);
8803 aopPut (AOP (result), zero, 0);
8807 /* the right is also a bit variable */
8808 if (AOP_TYPE (right) == AOP_CRY)
8810 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8811 aopPut (AOP (result), "c", 0);
8817 aopPut (AOP (result), "a", 0);
8821 /* bit variables done */
8823 size = AOP_SIZE (result);
8825 if (AOP_TYPE (right) == AOP_LIT)
8826 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8829 (AOP_TYPE (result) != AOP_REG) &&
8830 (AOP_TYPE (right) == AOP_LIT) &&
8831 !IS_FLOAT (operandType (right)))
8833 D (emitcode (";", "Kevin's better literal load code");
8835 _startLazyDPSEvaluation ();
8836 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8838 aopPut (AOP (result),
8839 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8844 /* And now fill the rest with zeros. */
8847 emitcode ("clr", "a");
8851 aopPut (AOP (result), "a", offset++);
8853 _endLazyDPSEvaluation ();
8857 _startLazyDPSEvaluation ();
8860 aopPut (AOP (result),
8861 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8865 _endLazyDPSEvaluation ();
8869 freeAsmop (right, NULL, ic, FALSE);
8870 freeAsmop (result, NULL, ic, TRUE);
8873 /*-----------------------------------------------------------------*/
8874 /* genJumpTab - generates code for jump table */
8875 /*-----------------------------------------------------------------*/
8877 genJumpTab (iCode * ic)
8882 D (emitcode (";", "genJumpTab ");
8885 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8886 /* get the condition into accumulator */
8887 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8889 /* multiply by four! */
8890 emitcode ("add", "a,acc");
8891 emitcode ("add", "a,acc");
8892 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8894 jtab = newiTempLabel (NULL);
8895 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8896 emitcode ("jmp", "@a+dptr");
8897 emitcode ("", "%05d$:", jtab->key + 100);
8898 /* now generate the jump labels */
8899 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8900 jtab = setNextItem (IC_JTLABELS (ic)))
8901 emitcode ("ljmp", "%05d$", jtab->key + 100);
8905 /*-----------------------------------------------------------------*/
8906 /* genCast - gen code for casting */
8907 /*-----------------------------------------------------------------*/
8909 genCast (iCode * ic)
8911 operand *result = IC_RESULT (ic);
8912 sym_link *ctype = operandType (IC_LEFT (ic));
8913 sym_link *rtype = operandType (IC_RIGHT (ic));
8914 operand *right = IC_RIGHT (ic);
8917 D (emitcode (";", "genCast ");
8920 /* if they are equivalent then do nothing */
8921 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8924 aopOp (right, ic, FALSE, FALSE);
8925 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8927 /* if the result is a bit */
8928 if (AOP_TYPE (result) == AOP_CRY)
8930 /* if the right size is a literal then
8931 we know what the value is */
8932 if (AOP_TYPE (right) == AOP_LIT)
8934 if (((int) operandLitValue (right)))
8935 aopPut (AOP (result), one, 0);
8937 aopPut (AOP (result), zero, 0);
8942 /* the right is also a bit variable */
8943 if (AOP_TYPE (right) == AOP_CRY)
8945 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8946 aopPut (AOP (result), "c", 0);
8952 aopPut (AOP (result), "a", 0);
8956 /* if they are the same size : or less */
8957 if (AOP_SIZE (result) <= AOP_SIZE (right))
8960 /* if they are in the same place */
8961 if (sameRegs (AOP (right), AOP (result)))
8964 /* if they in different places then copy */
8965 size = AOP_SIZE (result);
8967 _startLazyDPSEvaluation ();
8970 aopPut (AOP (result),
8971 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8975 _endLazyDPSEvaluation ();
8980 /* if the result is of type pointer */
8985 sym_link *type = operandType (right);
8987 /* pointer to generic pointer */
8988 if (IS_GENPTR (ctype))
8994 p_type = DCL_TYPE (type);
8998 #if OLD_CAST_BEHAVIOR
8999 /* KV: we are converting a non-pointer type to
9000 * a generic pointer. This (ifdef'd out) code
9001 * says that the resulting generic pointer
9002 * should have the same class as the storage
9003 * location of the non-pointer variable.
9005 * For example, converting an int (which happens
9006 * to be stored in DATA space) to a pointer results
9007 * in a DATA generic pointer; if the original int
9008 * in XDATA space, so will be the resulting pointer.
9010 * I don't like that behavior, and thus this change:
9011 * all such conversions will be forced to XDATA and
9012 * throw a warning. If you want some non-XDATA
9013 * type, or you want to suppress the warning, you
9014 * must go through an intermediate cast, like so:
9016 * char _generic *gp = (char _xdata *)(intVar);
9018 sym_link *etype = getSpec (type);
9020 /* we have to go by the storage class */
9021 if (SPEC_OCLS (etype) != generic)
9023 p_type = PTR_TYPE (SPEC_OCLS (etype));
9028 /* Converting unknown class (i.e. register variable)
9029 * to generic pointer. This is not good, but
9030 * we'll make a guess (and throw a warning).
9033 werror (W_INT_TO_GEN_PTR_CAST);
9037 /* the first two bytes are known */
9038 size = GPTRSIZE - 1;
9040 _startLazyDPSEvaluation ();
9043 aopPut (AOP (result),
9044 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9048 _endLazyDPSEvaluation ();
9050 /* the last byte depending on type */
9068 /* this should never happen */
9069 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9070 "got unknown pointer type");
9073 aopPut (AOP (result), l, GPTRSIZE - 1);
9077 /* just copy the pointers */
9078 size = AOP_SIZE (result);
9080 _startLazyDPSEvaluation ();
9083 aopPut (AOP (result),
9084 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9088 _endLazyDPSEvaluation ();
9092 /* so we now know that the size of destination is greater
9093 than the size of the source */
9094 /* we move to result for the size of source */
9095 size = AOP_SIZE (right);
9097 _startLazyDPSEvaluation ();
9100 aopPut (AOP (result),
9101 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9105 _endLazyDPSEvaluation ();
9107 /* now depending on the sign of the source && destination */
9108 size = AOP_SIZE (result) - AOP_SIZE (right);
9109 /* if unsigned or not an integral type */
9110 /* also, if the source is a bit, we don't need to sign extend, because
9111 * it can't possibly have set the sign bit.
9113 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9117 aopPut (AOP (result), zero, offset++);
9122 /* we need to extend the sign :{ */
9123 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9124 FALSE, FALSE, TRUE);
9126 emitcode ("rlc", "a");
9127 emitcode ("subb", "a,acc");
9129 aopPut (AOP (result), "a", offset++);
9132 /* we are done hurray !!!! */
9135 freeAsmop (right, NULL, ic, TRUE);
9136 freeAsmop (result, NULL, ic, TRUE);
9140 /*-----------------------------------------------------------------*/
9141 /* genDjnz - generate decrement & jump if not zero instrucion */
9142 /*-----------------------------------------------------------------*/
9144 genDjnz (iCode * ic, iCode * ifx)
9150 /* if the if condition has a false label
9151 then we cannot save */
9155 /* if the minus is not of the form
9157 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9158 !IS_OP_LITERAL (IC_RIGHT (ic)))
9161 if (operandLitValue (IC_RIGHT (ic)) != 1)
9164 /* if the size of this greater than one then no
9166 if (getSize (operandType (IC_RESULT (ic))) > 1)
9169 /* otherwise we can save BIG */
9170 lbl = newiTempLabel (NULL);
9171 lbl1 = newiTempLabel (NULL);
9173 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9175 if (IS_AOP_PREG (IC_RESULT (ic)))
9177 emitcode ("dec", "%s",
9178 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9179 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9180 emitcode ("jnz", "%05d$", lbl->key + 100);
9184 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9187 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9188 emitcode ("", "%05d$:", lbl->key + 100);
9189 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9190 emitcode ("", "%05d$:", lbl1->key + 100);
9192 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9197 /*-----------------------------------------------------------------*/
9198 /* genReceive - generate code for a receive iCode */
9199 /*-----------------------------------------------------------------*/
9201 genReceive (iCode * ic)
9204 D (emitcode (";", "genReceive ");
9207 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9208 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9209 IS_TRUE_SYMOP (IC_RESULT (ic))))
9211 int size = getSize (operandType (IC_RESULT (ic)));
9212 int offset = fReturnSizeDS390 - size;
9215 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9216 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9219 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9220 size = AOP_SIZE (IC_RESULT (ic));
9224 emitcode ("pop", "acc");
9225 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9232 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9234 assignResultValue (IC_RESULT (ic));
9237 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9240 /*-----------------------------------------------------------------*/
9241 /* gen390Code - generate code for Dallas 390 based controllers */
9242 /*-----------------------------------------------------------------*/
9244 gen390Code (iCode * lic)
9249 lineHead = lineCurr = NULL;
9253 /* print the allocation information */
9255 printAllocInfo (currFunc, codeOutFile);
9257 /* if debug information required */
9258 if (options.debug && currFunc)
9260 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9262 if (IS_STATIC (currFunc->etype))
9263 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9265 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9268 /* stack pointer name */
9269 if (options.useXstack)
9275 for (ic = lic; ic; ic = ic->next)
9278 if (cln != ic->lineno)
9283 emitcode ("", "C$%s$%d$%d$%d ==.",
9284 FileBaseName (ic->filename), ic->lineno,
9285 ic->level, ic->block);
9288 emitcode (";", "%s %d", ic->filename, ic->lineno);
9291 /* if the result is marked as
9292 spilt and rematerializable or code for
9293 this has already been generated then
9295 if (resultRemat (ic) || ic->generated)
9298 /* depending on the operation */
9318 /* IPOP happens only when trying to restore a
9319 spilt live range, if there is an ifx statement
9320 following this pop then the if statement might
9321 be using some of the registers being popped which
9322 would destory the contents of the register so
9323 we need to check for this condition and handle it */
9325 ic->next->op == IFX &&
9326 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9327 genIfx (ic->next, ic);
9345 genEndFunction (ic);
9365 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9382 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9386 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9393 /* note these two are xlated by algebraic equivalence
9394 during parsing SDCC.y */
9395 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9396 "got '>=' or '<=' shouldn't have come here");
9400 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9412 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9416 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9420 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9447 case GET_VALUE_AT_ADDRESS:
9452 if (POINTER_SET (ic))
9479 addSet (&_G.sendSet, ic);
9484 /* piCode(ic,stdout); */
9490 /* now we are ready to call the
9491 peep hole optimizer */
9492 if (!options.nopeep)
9493 peepHole (&lineHead);
9495 /* now do the actual printing */
9496 printLine (lineHead, codeOutFile);