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 ();
1378 tlbl = newiTempLabel (NULL);
1379 aopPut (res->aop, one, 1);
1380 emitcode ("jz", "%05d$", (tlbl->key + 100));
1381 aopPut (res->aop, zero, 1);
1382 emitcode ("", "%05d$:", (tlbl->key + 100));
1384 size = res->aop->size - 2;
1386 /* put zeros in the rest */
1388 aopPut (res->aop, zero, offset++);
1391 /*-----------------------------------------------------------------*/
1392 /* opIsGptr: returns non-zero if the passed operand is */
1393 /* a generic pointer type. */
1394 /*-----------------------------------------------------------------*/
1396 opIsGptr (operand * op)
1398 sym_link *type = operandType (op);
1400 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1407 /*-----------------------------------------------------------------*/
1408 /* getDataSize - get the operand data size */
1409 /*-----------------------------------------------------------------*/
1411 getDataSize (operand * op)
1414 size = AOP_SIZE (op);
1415 if (size == GPTRSIZE)
1417 sym_link *type = operandType (op);
1418 if (IS_GENPTR (type))
1420 /* generic pointer; arithmetic operations
1421 * should ignore the high byte (pointer type).
1429 /*-----------------------------------------------------------------*/
1430 /* outAcc - output Acc */
1431 /*-----------------------------------------------------------------*/
1433 outAcc (operand * result)
1436 size = getDataSize (result);
1439 aopPut (AOP (result), "a", 0);
1442 /* unsigned or positive */
1445 aopPut (AOP (result), zero, offset++);
1450 /*-----------------------------------------------------------------*/
1451 /* outBitC - output a bit C */
1452 /*-----------------------------------------------------------------*/
1454 outBitC (operand * result)
1456 /* if the result is bit */
1457 if (AOP_TYPE (result) == AOP_CRY)
1459 aopPut (AOP (result), "c", 0);
1463 emitcode ("clr", "a");
1464 emitcode ("rlc", "a");
1469 /*-----------------------------------------------------------------*/
1470 /* toBoolean - emit code for orl a,operator(sizeop) */
1471 /*-----------------------------------------------------------------*/
1473 toBoolean (operand * oper)
1475 int size = AOP_SIZE (oper) - 1;
1478 /* The generic part of a generic pointer should
1479 * not participate in it's truth value.
1481 * i.e. 0x10000000 is zero.
1483 if (opIsGptr (oper))
1485 D (emitcode (";", "toBoolean: generic ptr special case.");
1490 _startLazyDPSEvaluation ();
1491 if (AOP_NEEDSACC (oper))
1493 emitcode ("push", "b");
1494 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1498 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1502 if (AOP_NEEDSACC (oper))
1504 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1508 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1511 _endLazyDPSEvaluation ();
1513 if (AOP_NEEDSACC (oper))
1515 emitcode ("mov", "a,b");
1516 emitcode ("pop", "b");
1521 /*-----------------------------------------------------------------*/
1522 /* genNot - generate code for ! operation */
1523 /*-----------------------------------------------------------------*/
1528 sym_link *optype = operandType (IC_LEFT (ic));
1530 D (emitcode (";", "genNot ");
1533 /* assign asmOps to operand & result */
1534 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1535 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1537 /* if in bit space then a special case */
1538 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1540 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1541 emitcode ("cpl", "c");
1542 outBitC (IC_RESULT (ic));
1546 /* if type float then do float */
1547 if (IS_FLOAT (optype))
1549 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1553 toBoolean (IC_LEFT (ic));
1555 tlbl = newiTempLabel (NULL);
1556 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1557 emitcode ("", "%05d$:", tlbl->key + 100);
1558 outBitC (IC_RESULT (ic));
1561 /* release the aops */
1562 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1563 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1567 /*-----------------------------------------------------------------*/
1568 /* genCpl - generate code for complement */
1569 /*-----------------------------------------------------------------*/
1576 D (emitcode (";", "genCpl ");
1580 /* assign asmOps to operand & result */
1581 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1582 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1584 /* if both are in bit space then
1586 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1587 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1590 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1591 emitcode ("cpl", "c");
1592 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1596 size = AOP_SIZE (IC_RESULT (ic));
1597 _startLazyDPSEvaluation ();
1600 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1602 emitcode ("cpl", "a");
1603 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1605 _endLazyDPSEvaluation ();
1609 /* release the aops */
1610 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1611 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1614 /*-----------------------------------------------------------------*/
1615 /* genUminusFloat - unary minus for floating points */
1616 /*-----------------------------------------------------------------*/
1618 genUminusFloat (operand * op, operand * result)
1620 int size, offset = 0;
1622 /* for this we just need to flip the
1623 first it then copy the rest in place */
1624 D (emitcode (";", "genUminusFloat");
1627 _startLazyDPSEvaluation ();
1628 size = AOP_SIZE (op) - 1;
1629 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1632 emitcode ("cpl", "acc.7");
1633 aopPut (AOP (result), "a", 3);
1637 aopPut (AOP (result),
1638 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1642 _endLazyDPSEvaluation ();
1645 /*-----------------------------------------------------------------*/
1646 /* genUminus - unary minus code generation */
1647 /*-----------------------------------------------------------------*/
1649 genUminus (iCode * ic)
1652 sym_link *optype, *rtype;
1654 D (emitcode (";", "genUminus ");
1659 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1660 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1662 /* if both in bit space then special
1664 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1665 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1668 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1669 emitcode ("cpl", "c");
1670 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1674 optype = operandType (IC_LEFT (ic));
1675 rtype = operandType (IC_RESULT (ic));
1677 /* if float then do float stuff */
1678 if (IS_FLOAT (optype))
1680 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1684 /* otherwise subtract from zero */
1685 size = AOP_SIZE (IC_LEFT (ic));
1687 _startLazyDPSEvaluation ();
1690 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1691 if (!strcmp (l, "a"))
1695 emitcode ("cpl", "a");
1696 emitcode ("addc", "a,#0");
1702 emitcode ("clr", "a");
1703 emitcode ("subb", "a,%s", l);
1705 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1707 _endLazyDPSEvaluation ();
1709 /* if any remaining bytes in the result */
1710 /* we just need to propagate the sign */
1711 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1713 emitcode ("rlc", "a");
1714 emitcode ("subb", "a,acc");
1716 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1720 /* release the aops */
1721 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1722 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1725 /*-----------------------------------------------------------------*/
1726 /* saveRegisters - will look for a call and save the registers */
1727 /*-----------------------------------------------------------------*/
1729 saveRegisters (iCode * lic)
1737 for (ic = lic; ic; ic = ic->next)
1738 if (ic->op == CALL || ic->op == PCALL)
1743 fprintf (stderr, "found parameter push with no function call\n");
1747 /* if the registers have been saved already then
1749 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1752 /* find the registers in use at this time
1753 and push them away to safety */
1754 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1758 if (options.useXstack)
1760 if (bitVectBitValue (rsave, R0_IDX))
1761 emitcode ("mov", "b,r0");
1762 emitcode ("mov", "r0,%s", spname);
1763 for (i = 0; i < ds390_nRegs; i++)
1765 if (bitVectBitValue (rsave, i))
1768 emitcode ("mov", "a,b");
1770 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1771 emitcode ("movx", "@r0,a");
1772 emitcode ("inc", "r0");
1775 emitcode ("mov", "%s,r0", spname);
1776 if (bitVectBitValue (rsave, R0_IDX))
1777 emitcode ("mov", "r0,b");
1780 for (i = 0; i < ds390_nRegs; i++)
1782 if (bitVectBitValue (rsave, i))
1783 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1786 detype = getSpec (operandType (IC_LEFT (ic)));
1788 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1789 IS_ISR (currFunc->etype) &&
1792 saverbank (SPEC_BANK (detype), ic, TRUE);
1795 /*-----------------------------------------------------------------*/
1796 /* unsaveRegisters - pop the pushed registers */
1797 /*-----------------------------------------------------------------*/
1799 unsaveRegisters (iCode * ic)
1803 /* find the registers in use at this time
1804 and push them away to safety */
1805 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1808 if (options.useXstack)
1810 emitcode ("mov", "r0,%s", spname);
1811 for (i = ds390_nRegs; i >= 0; i--)
1813 if (bitVectBitValue (rsave, i))
1815 emitcode ("dec", "r0");
1816 emitcode ("movx", "a,@r0");
1818 emitcode ("mov", "b,a");
1820 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1824 emitcode ("mov", "%s,r0", spname);
1825 if (bitVectBitValue (rsave, R0_IDX))
1826 emitcode ("mov", "r0,b");
1829 for (i = ds390_nRegs; i >= 0; i--)
1831 if (bitVectBitValue (rsave, i))
1832 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1838 /*-----------------------------------------------------------------*/
1840 /*-----------------------------------------------------------------*/
1842 pushSide (operand * oper, int size)
1845 _startLazyDPSEvaluation ();
1848 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1849 if (AOP_TYPE (oper) != AOP_REG &&
1850 AOP_TYPE (oper) != AOP_DIR &&
1853 emitcode ("mov", "a,%s", l);
1854 emitcode ("push", "acc");
1857 emitcode ("push", "%s", l);
1859 _endLazyDPSEvaluation ();
1862 /*-----------------------------------------------------------------*/
1863 /* assignResultValue - */
1864 /*-----------------------------------------------------------------*/
1866 assignResultValue (operand * oper)
1869 int size = AOP_SIZE (oper);
1871 _startLazyDPSEvaluation ();
1874 aopPut (AOP (oper), fReturn[offset], offset);
1877 _endLazyDPSEvaluation ();
1881 /*-----------------------------------------------------------------*/
1882 /* genXpush - pushes onto the external stack */
1883 /*-----------------------------------------------------------------*/
1885 genXpush (iCode * ic)
1887 asmop *aop = newAsmop (0);
1889 int size, offset = 0;
1891 D (emitcode (";", "genXpush ");
1894 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1895 r = getFreePtr (ic, &aop, FALSE);
1898 emitcode ("mov", "%s,_spx", r->name);
1900 size = AOP_SIZE (IC_LEFT (ic));
1901 _startLazyDPSEvaluation ();
1905 char *l = aopGet (AOP (IC_LEFT (ic)),
1906 offset++, FALSE, FALSE, TRUE);
1908 emitcode ("movx", "@%s,a", r->name);
1909 emitcode ("inc", "%s", r->name);
1912 _endLazyDPSEvaluation ();
1915 emitcode ("mov", "_spx,%s", r->name);
1917 freeAsmop (NULL, aop, ic, TRUE);
1918 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1921 /*-----------------------------------------------------------------*/
1922 /* genIpush - genrate code for pushing this gets a little complex */
1923 /*-----------------------------------------------------------------*/
1925 genIpush (iCode * ic)
1927 int size, offset = 0;
1930 D (emitcode (";", "genIpush ");
1933 /* if this is not a parm push : ie. it is spill push
1934 and spill push is always done on the local stack */
1938 /* and the item is spilt then do nothing */
1939 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1942 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1943 size = AOP_SIZE (IC_LEFT (ic));
1944 /* push it on the stack */
1945 _startLazyDPSEvaluation ();
1948 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1954 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1956 _endLazyDPSEvaluation ();
1960 /* this is a paramter push: in this case we call
1961 the routine to find the call and save those
1962 registers that need to be saved */
1965 /* if use external stack then call the external
1966 stack pushing routine */
1967 if (options.useXstack)
1973 /* then do the push */
1974 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1976 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1977 size = AOP_SIZE (IC_LEFT (ic));
1979 _startLazyDPSEvaluation ();
1982 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1983 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1984 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1987 emitcode ("mov", "a,%s", l);
1988 emitcode ("push", "acc");
1991 emitcode ("push", "%s ;jwk genIpush", l);
1993 _endLazyDPSEvaluation ();
1995 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1998 /*-----------------------------------------------------------------*/
1999 /* genIpop - recover the registers: can happen only for spilling */
2000 /*-----------------------------------------------------------------*/
2002 genIpop (iCode * ic)
2006 D (emitcode (";", "genIpop ");
2010 /* if the temp was not pushed then */
2011 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2014 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2015 size = AOP_SIZE (IC_LEFT (ic));
2016 offset = (size - 1);
2017 _startLazyDPSEvaluation ();
2020 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2021 FALSE, TRUE, TRUE));
2023 _endLazyDPSEvaluation ();
2025 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2028 /*-----------------------------------------------------------------*/
2029 /* unsaverbank - restores the resgister bank from stack */
2030 /*-----------------------------------------------------------------*/
2032 unsaverbank (int bank, iCode * ic, bool popPsw)
2040 if (options.useXstack)
2043 r = getFreePtr (ic, &aop, FALSE);
2046 emitcode ("mov", "%s,_spx", r->name);
2047 emitcode ("movx", "a,@%s", r->name);
2048 emitcode ("mov", "psw,a");
2049 emitcode ("dec", "%s", r->name);
2053 emitcode ("pop", "psw");
2056 for (i = (ds390_nRegs - 1); i >= 0; i--)
2058 if (options.useXstack)
2060 emitcode ("movx", "a,@%s", r->name);
2061 emitcode ("mov", "(%s+%d),a",
2062 regs390[i].base, 8 * bank + regs390[i].offset);
2063 emitcode ("dec", "%s", r->name);
2067 emitcode ("pop", "(%s+%d)",
2068 regs390[i].base, 8 * bank + regs390[i].offset);
2071 if (options.useXstack)
2074 emitcode ("mov", "_spx,%s", r->name);
2075 freeAsmop (NULL, aop, ic, TRUE);
2080 /*-----------------------------------------------------------------*/
2081 /* saverbank - saves an entire register bank on the stack */
2082 /*-----------------------------------------------------------------*/
2084 saverbank (int bank, iCode * ic, bool pushPsw)
2090 if (options.useXstack)
2094 r = getFreePtr (ic, &aop, FALSE);
2095 emitcode ("mov", "%s,_spx", r->name);
2099 for (i = 0; i < ds390_nRegs; i++)
2101 if (options.useXstack)
2103 emitcode ("inc", "%s", r->name);
2104 emitcode ("mov", "a,(%s+%d)",
2105 regs390[i].base, 8 * bank + regs390[i].offset);
2106 emitcode ("movx", "@%s,a", r->name);
2109 emitcode ("push", "(%s+%d)",
2110 regs390[i].base, 8 * bank + regs390[i].offset);
2115 if (options.useXstack)
2117 emitcode ("mov", "a,psw");
2118 emitcode ("movx", "@%s,a", r->name);
2119 emitcode ("inc", "%s", r->name);
2120 emitcode ("mov", "_spx,%s", r->name);
2121 freeAsmop (NULL, aop, ic, TRUE);
2125 emitcode ("push", "psw");
2127 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2133 /*-----------------------------------------------------------------*/
2134 /* genCall - generates a call statement */
2135 /*-----------------------------------------------------------------*/
2137 genCall (iCode * ic)
2141 D (emitcode (";", "genCall ");
2144 /* if caller saves & we have not saved then */
2148 /* if we are calling a function that is not using
2149 the same register bank then we need to save the
2150 destination registers on the stack */
2151 detype = getSpec (operandType (IC_LEFT (ic)));
2153 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2154 IS_ISR (currFunc->etype) &&
2157 saverbank (SPEC_BANK (detype), ic, TRUE);
2159 /* if send set is not empty the assign */
2164 for (sic = setFirstItem (_G.sendSet); sic;
2165 sic = setNextItem (_G.sendSet))
2167 int size, offset = 0;
2169 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2170 size = AOP_SIZE (IC_LEFT (sic));
2172 _startLazyDPSEvaluation ();
2175 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2176 FALSE, FALSE, TRUE);
2177 if (strcmp (l, fReturn[offset])) {
2180 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2186 _endLazyDPSEvaluation ();
2187 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2192 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2193 OP_SYMBOL (IC_LEFT (ic))->rname :
2194 OP_SYMBOL (IC_LEFT (ic))->name));
2196 /* if we need assign a result value */
2197 if ((IS_ITEMP (IC_RESULT (ic)) &&
2198 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2199 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2200 IS_TRUE_SYMOP (IC_RESULT (ic)))
2202 if (isOperandInFarSpace (IC_RESULT (ic))
2203 && getSize (operandType (IC_RESULT (ic))) <= 2)
2205 int size = getSize (operandType (IC_RESULT (ic)));
2207 /* Special case for 1 or 2 byte return in far space. */
2208 emitcode (";", "Kevin function call abuse #1");
2213 emitcode ("mov", "b,%s", fReturn[1]);
2216 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2217 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2221 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2223 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2228 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2231 assignResultValue (IC_RESULT (ic));
2233 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2237 /* adjust the stack for parameters if
2242 if (ic->parmBytes > 3)
2244 emitcode ("mov", "a,%s", spname);
2245 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2246 emitcode ("mov", "%s,a", spname);
2249 for (i = 0; i < ic->parmBytes; i++)
2250 emitcode ("dec", "%s", spname);
2254 /* if register bank was saved then pop them */
2256 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2258 /* if we hade saved some registers then unsave them */
2259 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2260 unsaveRegisters (ic);
2265 /*-----------------------------------------------------------------*/
2266 /* genPcall - generates a call by pointer statement */
2267 /*-----------------------------------------------------------------*/
2269 genPcall (iCode * ic)
2272 symbol *rlbl = newiTempLabel (NULL);
2274 D (emitcode (";", "genPcall ");
2278 /* if caller saves & we have not saved then */
2282 /* if we are calling a function that is not using
2283 the same register bank then we need to save the
2284 destination registers on the stack */
2285 detype = getSpec (operandType (IC_LEFT (ic)));
2287 IS_ISR (currFunc->etype) &&
2288 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2289 saverbank (SPEC_BANK (detype), ic, TRUE);
2292 /* push the return address on to the stack */
2293 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2294 emitcode ("push", "acc");
2295 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2296 emitcode ("push", "acc");
2298 if (options.model == MODEL_FLAT24)
2300 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2301 emitcode ("push", "acc");
2304 /* now push the calling address */
2305 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2307 pushSide (IC_LEFT (ic), FPTRSIZE);
2309 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2311 /* if send set is not empty the assign */
2316 for (sic = setFirstItem (_G.sendSet); sic;
2317 sic = setNextItem (_G.sendSet))
2319 int size, offset = 0;
2321 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2322 size = AOP_SIZE (IC_LEFT (sic));
2323 _startLazyDPSEvaluation ();
2326 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2327 FALSE, FALSE, TRUE);
2328 if (strcmp (l, fReturn[offset]))
2330 emitcode ("mov", "%s,%s",
2336 _endLazyDPSEvaluation ();
2337 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2342 emitcode ("ret", "");
2343 emitcode ("", "%05d$:", (rlbl->key + 100));
2346 /* if we need assign a result value */
2347 if ((IS_ITEMP (IC_RESULT (ic)) &&
2348 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2349 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2350 IS_TRUE_SYMOP (IC_RESULT (ic)))
2354 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2357 assignResultValue (IC_RESULT (ic));
2359 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2362 /* adjust the stack for parameters if
2367 if (ic->parmBytes > 3)
2369 emitcode ("mov", "a,%s", spname);
2370 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2371 emitcode ("mov", "%s,a", spname);
2374 for (i = 0; i < ic->parmBytes; i++)
2375 emitcode ("dec", "%s", spname);
2379 /* if register bank was saved then unsave them */
2381 (SPEC_BANK (currFunc->etype) !=
2382 SPEC_BANK (detype)))
2383 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2385 /* if we hade saved some registers then
2388 unsaveRegisters (ic);
2392 /*-----------------------------------------------------------------*/
2393 /* resultRemat - result is rematerializable */
2394 /*-----------------------------------------------------------------*/
2396 resultRemat (iCode * ic)
2398 if (SKIP_IC (ic) || ic->op == IFX)
2401 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2403 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2404 if (sym->remat && !POINTER_SET (ic))
2411 #if defined(__BORLANDC__) || defined(_MSC_VER)
2412 #define STRCASECMP stricmp
2414 #define STRCASECMP strcasecmp
2417 /*-----------------------------------------------------------------*/
2418 /* inExcludeList - return 1 if the string is in exclude Reg list */
2419 /*-----------------------------------------------------------------*/
2421 inExcludeList (char *s)
2425 if (options.excludeRegs[i] &&
2426 STRCASECMP (options.excludeRegs[i], "none") == 0)
2429 for (i = 0; options.excludeRegs[i]; i++)
2431 if (options.excludeRegs[i] &&
2432 STRCASECMP (s, options.excludeRegs[i]) == 0)
2438 /*-----------------------------------------------------------------*/
2439 /* genFunction - generated code for function entry */
2440 /*-----------------------------------------------------------------*/
2442 genFunction (iCode * ic)
2447 D (emitcode (";", "genFunction ");
2451 /* create the function header */
2452 emitcode (";", "-----------------------------------------");
2453 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2454 emitcode (";", "-----------------------------------------");
2456 emitcode ("", "%s:", sym->rname);
2457 fetype = getSpec (operandType (IC_LEFT (ic)));
2459 /* if critical function then turn interrupts off */
2460 if (SPEC_CRTCL (fetype))
2461 emitcode ("clr", "ea");
2463 /* here we need to generate the equates for the
2464 register bank if required */
2465 if (SPEC_BANK (fetype) != rbank)
2469 rbank = SPEC_BANK (fetype);
2470 for (i = 0; i < ds390_nRegs; i++)
2472 if (strcmp (regs390[i].base, "0") == 0)
2473 emitcode ("", "%s = 0x%02x",
2475 8 * rbank + regs390[i].offset);
2477 emitcode ("", "%s = %s + 0x%02x",
2480 8 * rbank + regs390[i].offset);
2484 /* if this is an interrupt service routine then
2485 save acc, b, dpl, dph */
2486 if (IS_ISR (sym->etype))
2489 if (!inExcludeList ("acc"))
2490 emitcode ("push", "acc");
2491 if (!inExcludeList ("b"))
2492 emitcode ("push", "b");
2493 if (!inExcludeList ("dpl"))
2494 emitcode ("push", "dpl");
2495 if (!inExcludeList ("dph"))
2496 emitcode ("push", "dph");
2497 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2499 emitcode ("push", "dpx");
2500 /* Make sure we're using standard DPTR */
2501 emitcode ("push", "dps");
2502 emitcode ("mov", "dps, #0x00");
2503 if (options.stack10bit)
2505 /* This ISR could conceivably use DPTR2. Better save it. */
2506 emitcode ("push", "dpl1");
2507 emitcode ("push", "dph1");
2508 emitcode ("push", "dpx1");
2509 emitcode ("push", "ap");
2512 /* if this isr has no bank i.e. is going to
2513 run with bank 0 , then we need to save more
2515 if (!SPEC_BANK (sym->etype))
2518 /* if this function does not call any other
2519 function then we can be economical and
2520 save only those registers that are used */
2525 /* if any registers used */
2528 /* save the registers used */
2529 for (i = 0; i < sym->regsUsed->size; i++)
2531 if (bitVectBitValue (sym->regsUsed, i) ||
2532 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2533 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2540 /* this function has a function call cannot
2541 determines register usage so we will have the
2543 saverbank (0, ic, FALSE);
2549 /* if callee-save to be used for this function
2550 then save the registers being used in this function */
2551 if (sym->calleeSave)
2555 /* if any registers used */
2558 /* save the registers used */
2559 for (i = 0; i < sym->regsUsed->size; i++)
2561 if (bitVectBitValue (sym->regsUsed, i) ||
2562 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2564 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2572 /* set the register bank to the desired value */
2573 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2575 emitcode ("push", "psw");
2576 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2579 if (IS_RENT (sym->etype) || options.stackAuto)
2582 if (options.useXstack)
2584 emitcode ("mov", "r0,%s", spname);
2585 emitcode ("mov", "a,_bp");
2586 emitcode ("movx", "@r0,a");
2587 emitcode ("inc", "%s", spname);
2591 /* set up the stack */
2592 emitcode ("push", "_bp"); /* save the callers stack */
2594 emitcode ("mov", "_bp,%s", spname);
2597 /* adjust the stack for the function */
2603 werror (W_STACK_OVERFLOW, sym->name);
2605 if (i > 3 && sym->recvSize < 4)
2608 emitcode ("mov", "a,sp");
2609 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2610 emitcode ("mov", "sp,a");
2615 emitcode ("inc", "sp");
2621 emitcode ("mov", "a,_spx");
2622 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2623 emitcode ("mov", "_spx,a");
2628 /*-----------------------------------------------------------------*/
2629 /* genEndFunction - generates epilogue for functions */
2630 /*-----------------------------------------------------------------*/
2632 genEndFunction (iCode * ic)
2634 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2636 D (emitcode (";", "genEndFunction ");
2639 if (IS_RENT (sym->etype) || options.stackAuto)
2641 emitcode ("mov", "%s,_bp", spname);
2644 /* if use external stack but some variables were
2645 added to the local stack then decrement the
2647 if (options.useXstack && sym->stack)
2649 emitcode ("mov", "a,sp");
2650 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2651 emitcode ("mov", "sp,a");
2655 if ((IS_RENT (sym->etype) || options.stackAuto))
2657 if (options.useXstack)
2659 emitcode ("mov", "r0,%s", spname);
2660 emitcode ("movx", "a,@r0");
2661 emitcode ("mov", "_bp,a");
2662 emitcode ("dec", "%s", spname);
2666 emitcode ("pop", "_bp");
2670 /* restore the register bank */
2671 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2672 emitcode ("pop", "psw");
2674 if (IS_ISR (sym->etype))
2677 /* now we need to restore the registers */
2678 /* if this isr has no bank i.e. is going to
2679 run with bank 0 , then we need to save more
2681 if (!SPEC_BANK (sym->etype))
2684 /* if this function does not call any other
2685 function then we can be economical and
2686 save only those registers that are used */
2691 /* if any registers used */
2694 /* save the registers used */
2695 for (i = sym->regsUsed->size; i >= 0; i--)
2697 if (bitVectBitValue (sym->regsUsed, i) ||
2698 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2699 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2706 /* this function has a function call cannot
2707 determines register usage so we will have the
2709 unsaverbank (0, ic, FALSE);
2713 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2715 if (options.stack10bit)
2717 emitcode ("pop", "ap");
2718 emitcode ("pop", "dpx1");
2719 emitcode ("pop", "dph1");
2720 emitcode ("pop", "dpl1");
2722 emitcode ("pop", "dps");
2723 emitcode ("pop", "dpx");
2725 if (!inExcludeList ("dph"))
2726 emitcode ("pop", "dph");
2727 if (!inExcludeList ("dpl"))
2728 emitcode ("pop", "dpl");
2729 if (!inExcludeList ("b"))
2730 emitcode ("pop", "b");
2731 if (!inExcludeList ("acc"))
2732 emitcode ("pop", "acc");
2734 if (SPEC_CRTCL (sym->etype))
2735 emitcode ("setb", "ea");
2737 /* if debug then send end of function */
2738 /* if (options.debug && currFunc) { */
2742 emitcode ("", "C$%s$%d$%d$%d ==.",
2743 FileBaseName (ic->filename), currFunc->lastLine,
2744 ic->level, ic->block);
2745 if (IS_STATIC (currFunc->etype))
2746 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2748 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2752 emitcode ("reti", "");
2756 if (SPEC_CRTCL (sym->etype))
2757 emitcode ("setb", "ea");
2759 if (sym->calleeSave)
2763 /* if any registers used */
2766 /* save the registers used */
2767 for (i = sym->regsUsed->size; i >= 0; i--)
2769 if (bitVectBitValue (sym->regsUsed, i) ||
2770 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2771 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2777 /* if debug then send end of function */
2781 emitcode ("", "C$%s$%d$%d$%d ==.",
2782 FileBaseName (ic->filename), currFunc->lastLine,
2783 ic->level, ic->block);
2784 if (IS_STATIC (currFunc->etype))
2785 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2787 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2791 emitcode ("ret", "");
2796 /*-----------------------------------------------------------------*/
2797 /* genRet - generate code for return statement */
2798 /*-----------------------------------------------------------------*/
2802 int size, offset = 0, pushed = 0;
2804 D (emitcode (";", "genRet ");
2807 /* if we have no return value then
2808 just generate the "ret" */
2812 /* we have something to return then
2813 move the return value into place */
2814 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2815 size = AOP_SIZE (IC_LEFT (ic));
2817 _startLazyDPSEvaluation ();
2821 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2823 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2824 FALSE, TRUE, FALSE);
2825 emitcode ("push", "%s", l);
2830 l = aopGet (AOP (IC_LEFT (ic)), offset,
2831 FALSE, FALSE, FALSE);
2832 if (strcmp (fReturn[offset], l))
2833 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2836 _endLazyDPSEvaluation ();
2843 if (strcmp (fReturn[pushed], "a"))
2844 emitcode ("pop", fReturn[pushed]);
2846 emitcode ("pop", "acc");
2849 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2852 /* generate a jump to the return label
2853 if the next is not the return statement */
2854 if (!(ic->next && ic->next->op == LABEL &&
2855 IC_LABEL (ic->next) == returnLabel))
2857 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2861 /*-----------------------------------------------------------------*/
2862 /* genLabel - generates a label */
2863 /*-----------------------------------------------------------------*/
2865 genLabel (iCode * ic)
2867 /* special case never generate */
2868 if (IC_LABEL (ic) == entryLabel)
2871 D (emitcode (";", "genLabel ");
2874 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2877 /*-----------------------------------------------------------------*/
2878 /* genGoto - generates a ljmp */
2879 /*-----------------------------------------------------------------*/
2881 genGoto (iCode * ic)
2883 D (emitcode (";", "genGoto ");
2885 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2888 /*-----------------------------------------------------------------*/
2889 /* findLabelBackwards: walks back through the iCode chain looking */
2890 /* for the given label. Returns number of iCode instructions */
2891 /* between that label and given ic. */
2892 /* Returns zero if label not found. */
2893 /*-----------------------------------------------------------------*/
2895 findLabelBackwards (iCode * ic, int key)
2904 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2906 /* printf("findLabelBackwards = %d\n", count); */
2914 /*-----------------------------------------------------------------*/
2915 /* genPlusIncr :- does addition with increment if possible */
2916 /*-----------------------------------------------------------------*/
2918 genPlusIncr (iCode * ic)
2920 unsigned int icount;
2921 unsigned int size = getDataSize (IC_RESULT (ic));
2923 /* will try to generate an increment */
2924 /* if the right side is not a literal
2926 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2929 /* if the literal value of the right hand side
2930 is greater than 4 then it is not worth it */
2931 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2934 /* if increment 16 bits in register */
2936 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2937 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2938 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2946 /* If the next instruction is a goto and the goto target
2947 * is <= 5 instructions previous to this, we can generate
2948 * jumps straight to that target.
2950 if (ic->next && ic->next->op == GOTO
2951 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2954 emitcode (";", "tail increment optimized (range %d)", labelRange);
2955 tlbl = IC_LABEL (ic->next);
2960 tlbl = newiTempLabel (NULL);
2963 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2964 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2965 IS_AOP_PREG (IC_RESULT (ic)))
2966 emitcode ("cjne", "%s,#0x00,%05d$"
2967 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2971 emitcode ("clr", "a");
2972 emitcode ("cjne", "a,%s,%05d$"
2973 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2977 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2980 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2981 IS_AOP_PREG (IC_RESULT (ic)))
2982 emitcode ("cjne", "%s,#0x00,%05d$"
2983 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2986 emitcode ("cjne", "a,%s,%05d$"
2987 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2990 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2994 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2995 IS_AOP_PREG (IC_RESULT (ic)))
2996 emitcode ("cjne", "%s,#0x00,%05d$"
2997 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3001 emitcode ("cjne", "a,%s,%05d$"
3002 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3005 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3010 emitcode ("", "%05d$:", tlbl->key + 100);
3015 /* if the sizes are greater than 1 then we cannot */
3016 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3017 AOP_SIZE (IC_LEFT (ic)) > 1)
3020 /* we can if the aops of the left & result match or
3021 if they are in registers and the registers are the
3024 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3025 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3026 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3031 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3032 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3033 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3038 _startLazyDPSEvaluation ();
3041 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3043 _endLazyDPSEvaluation ();
3052 /*-----------------------------------------------------------------*/
3053 /* outBitAcc - output a bit in acc */
3054 /*-----------------------------------------------------------------*/
3056 outBitAcc (operand * result)
3058 symbol *tlbl = newiTempLabel (NULL);
3059 /* if the result is a bit */
3060 if (AOP_TYPE (result) == AOP_CRY)
3062 aopPut (AOP (result), "a", 0);
3066 emitcode ("jz", "%05d$", tlbl->key + 100);
3067 emitcode ("mov", "a,%s", one);
3068 emitcode ("", "%05d$:", tlbl->key + 100);
3073 /*-----------------------------------------------------------------*/
3074 /* genPlusBits - generates code for addition of two bits */
3075 /*-----------------------------------------------------------------*/
3077 genPlusBits (iCode * ic)
3079 D (emitcode (";", "genPlusBits ");
3081 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3083 symbol *lbl = newiTempLabel (NULL);
3084 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3085 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3086 emitcode ("cpl", "c");
3087 emitcode ("", "%05d$:", (lbl->key + 100));
3088 outBitC (IC_RESULT (ic));
3092 emitcode ("clr", "a");
3093 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3094 emitcode ("rlc", "a");
3095 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3096 emitcode ("addc", "a,#0x00");
3097 outAcc (IC_RESULT (ic));
3102 adjustArithmeticResult (iCode * ic)
3104 if (opIsGptr (IC_RESULT (ic)) &&
3105 opIsGptr (IC_LEFT (ic)) &&
3106 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3108 aopPut (AOP (IC_RESULT (ic)),
3109 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3113 if (opIsGptr (IC_RESULT (ic)) &&
3114 opIsGptr (IC_RIGHT (ic)) &&
3115 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3117 aopPut (AOP (IC_RESULT (ic)),
3118 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3122 if (opIsGptr (IC_RESULT (ic)) &&
3123 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3124 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3125 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3126 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3129 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3130 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3134 #define AOP_OP_3(ic) \
3135 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3136 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3137 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3138 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3139 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3140 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3142 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3144 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3147 #define AOP_OP_3_NOFATAL(ic, rc) \
3148 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3149 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3150 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3151 isOperandInFarSpace(IC_RESULT(ic))) \
3153 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3158 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3159 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3161 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3162 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3164 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3166 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3170 #define AOP_OP_2(ic) \
3171 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3172 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3174 #define AOP_SET_LOCALS(ic) \
3175 left = IC_LEFT(ic); \
3176 right = IC_RIGHT(ic); \
3177 result = IC_RESULT(ic);
3179 /*-----------------------------------------------------------------*/
3180 /* genPlus - generates code for addition */
3181 /*-----------------------------------------------------------------*/
3183 genPlus (iCode * ic)
3185 int size, offset = 0;
3186 bool pushResult = FALSE;
3189 D (emitcode (";", "genPlus ");
3192 /* special cases :- */
3194 AOP_OP_3_NOFATAL (ic, pushResult);
3197 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3203 /* if literal, literal on the right or
3204 if left requires ACC or right is already
3206 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3207 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3208 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3210 operand *t = IC_RIGHT (ic);
3211 IC_RIGHT (ic) = IC_LEFT (ic);
3213 emitcode (";", "Swapped plus args.");
3216 /* if both left & right are in bit
3218 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3219 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3225 /* if left in bit space & right literal */
3226 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3227 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3229 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3230 /* if result in bit space */
3231 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3233 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3234 emitcode ("cpl", "c");
3235 outBitC (IC_RESULT (ic));
3239 size = getDataSize (IC_RESULT (ic));
3240 _startLazyDPSEvaluation ();
3243 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3244 emitcode ("addc", "a,#00");
3245 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3247 _endLazyDPSEvaluation ();
3252 /* if I can do an increment instead
3253 of add then GOOD for ME */
3254 if (genPlusIncr (ic) == TRUE)
3256 emitcode (";", "did genPlusIncr");
3261 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3263 _startLazyDPSEvaluation ();
3266 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3268 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3270 emitcode ("add", "a,%s",
3271 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3273 emitcode ("addc", "a,%s",
3274 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3278 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3280 emitcode ("add", "a,%s",
3281 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3283 emitcode ("addc", "a,%s",
3284 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3288 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3292 emitcode ("push", "acc");
3296 _endLazyDPSEvaluation ();
3300 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3302 size = getDataSize (IC_LEFT (ic));
3303 rSize = getDataSize (IC_RESULT (ic));
3305 /* If the pushed data is bigger than the result,
3306 * simply discard unused bytes. Icky, but works.
3308 * Should we throw a warning here? We're losing data...
3310 while (size > rSize)
3312 D (emitcode (";", "discarding unused result byte.");
3314 emitcode ("pop", "acc");
3320 emitcode ("clr", "a");
3321 /* Conversly, we haven't pushed enough here.
3322 * just zero-pad, and all is well.
3324 while (size < rSize)
3326 emitcode ("push", "acc");
3332 _startLazyDPSEvaluation ();
3335 emitcode ("pop", "acc");
3336 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3338 _endLazyDPSEvaluation ();
3341 adjustArithmeticResult (ic);
3344 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3345 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3346 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3349 /*-----------------------------------------------------------------*/
3350 /* genMinusDec :- does subtraction with deccrement if possible */
3351 /*-----------------------------------------------------------------*/
3353 genMinusDec (iCode * ic)
3355 unsigned int icount;
3356 unsigned int size = getDataSize (IC_RESULT (ic));
3358 /* will try to generate an increment */
3359 /* if the right side is not a literal
3361 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3364 /* if the literal value of the right hand side
3365 is greater than 4 then it is not worth it */
3366 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3369 /* if decrement 16 bits in register */
3370 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3371 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3372 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3380 /* If the next instruction is a goto and the goto target
3381 * is <= 5 instructions previous to this, we can generate
3382 * jumps straight to that target.
3384 if (ic->next && ic->next->op == GOTO
3385 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3388 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3389 tlbl = IC_LABEL (ic->next);
3394 tlbl = newiTempLabel (NULL);
3398 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3399 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3400 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3401 IS_AOP_PREG (IC_RESULT (ic)))
3402 emitcode ("cjne", "%s,#0xff,%05d$"
3403 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3407 emitcode ("mov", "a,#0xff");
3408 emitcode ("cjne", "a,%s,%05d$"
3409 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3412 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3415 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3416 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3417 IS_AOP_PREG (IC_RESULT (ic)))
3418 emitcode ("cjne", "%s,#0xff,%05d$"
3419 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3423 emitcode ("cjne", "a,%s,%05d$"
3424 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3427 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3431 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3432 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3433 IS_AOP_PREG (IC_RESULT (ic)))
3434 emitcode ("cjne", "%s,#0xff,%05d$"
3435 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3439 emitcode ("cjne", "a,%s,%05d$"
3440 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3443 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3447 emitcode ("", "%05d$:", tlbl->key + 100);
3452 /* if the sizes are greater than 1 then we cannot */
3453 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3454 AOP_SIZE (IC_LEFT (ic)) > 1)
3457 /* we can if the aops of the left & result match or
3458 if they are in registers and the registers are the
3461 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3462 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3463 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3466 _startLazyDPSEvaluation ();
3469 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3471 _endLazyDPSEvaluation ();
3479 /*-----------------------------------------------------------------*/
3480 /* addSign - complete with sign */
3481 /*-----------------------------------------------------------------*/
3483 addSign (operand * result, int offset, int sign)
3485 int size = (getDataSize (result) - offset);
3490 emitcode ("rlc", "a");
3491 emitcode ("subb", "a,acc");
3493 aopPut (AOP (result), "a", offset++);
3497 aopPut (AOP (result), zero, offset++);
3501 /*-----------------------------------------------------------------*/
3502 /* genMinusBits - generates code for subtraction of two bits */
3503 /*-----------------------------------------------------------------*/
3505 genMinusBits (iCode * ic)
3507 symbol *lbl = newiTempLabel (NULL);
3509 D (emitcode (";", "genMinusBits ");
3512 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3514 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3515 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3516 emitcode ("cpl", "c");
3517 emitcode ("", "%05d$:", (lbl->key + 100));
3518 outBitC (IC_RESULT (ic));
3522 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3523 emitcode ("subb", "a,acc");
3524 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3525 emitcode ("inc", "a");
3526 emitcode ("", "%05d$:", (lbl->key + 100));
3527 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3528 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3532 /*-----------------------------------------------------------------*/
3533 /* genMinus - generates code for subtraction */
3534 /*-----------------------------------------------------------------*/
3536 genMinus (iCode * ic)
3538 int size, offset = 0;
3540 unsigned long lit = 0L;
3541 bool pushResult = FALSE;
3543 D (emitcode (";", "genMinus ");
3546 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3547 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3548 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3549 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3555 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3557 /* special cases :- */
3558 /* if both left & right are in bit space */
3559 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3560 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3566 /* if I can do an decrement instead
3567 of subtract then GOOD for ME */
3568 if (genMinusDec (ic) == TRUE)
3573 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3575 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3581 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3586 /* if literal, add a,#-lit, else normal subb */
3587 _startLazyDPSEvaluation ();
3590 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3591 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3592 emitcode ("subb", "a,%s",
3593 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3596 /* first add without previous c */
3598 emitcode ("add", "a,#0x%02x",
3599 (unsigned int) (lit & 0x0FFL));
3601 emitcode ("addc", "a,#0x%02x",
3602 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3607 emitcode ("push", "acc");
3611 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3615 _endLazyDPSEvaluation ();
3619 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3621 size = getDataSize (IC_LEFT (ic));
3622 rSize = getDataSize (IC_RESULT (ic));
3624 /* If the pushed data is bigger than the result,
3625 * simply discard unused bytes. Icky, but works.
3627 * Should we throw a warning here? We're losing data...
3629 while (size > getDataSize (IC_RESULT (ic)))
3631 emitcode (";", "discarding unused result byte.");
3632 emitcode ("pop", "acc");
3638 emitcode ("clr", "a");
3639 /* Conversly, we haven't pushed enough here.
3640 * just zero-pad, and all is well.
3642 while (size < rSize)
3644 emitcode ("push", "acc");
3652 emitcode ("pop", "acc");
3653 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3657 adjustArithmeticResult (ic);
3660 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3661 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3662 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3666 /*-----------------------------------------------------------------*/
3667 /* genMultbits :- multiplication of bits */
3668 /*-----------------------------------------------------------------*/
3670 genMultbits (operand * left,
3674 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3675 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3680 /*-----------------------------------------------------------------*/
3681 /* genMultOneByte : 8*8=8/16 bit multiplication */
3682 /*-----------------------------------------------------------------*/
3684 genMultOneByte (operand * left,
3688 sym_link *opetype = operandType (result);
3690 int size=AOP_SIZE(result);
3692 emitcode (";",__FUNCTION__);
3693 if (size<1 || size>2) {
3694 // this should never happen
3695 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3696 AOP_SIZE(result), __FUNCTION__, lineno);
3700 /* (if two literals: the value is computed before) */
3701 /* if one literal, literal on the right */
3702 if (AOP_TYPE (left) == AOP_LIT)
3707 emitcode (";", "swapped left and right");
3710 if (SPEC_USIGN(opetype)
3711 // ignore the sign of left and right, what else can we do?
3712 || (SPEC_USIGN(operandType(left)) &&
3713 SPEC_USIGN(operandType(right)))) {
3714 // just an unsigned 8*8=8/16 multiply
3715 //emitcode (";","unsigned");
3716 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3717 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3718 emitcode ("mul", "ab");
3719 aopPut (AOP (result), "a", 0);
3721 aopPut (AOP (result), "b", 1);
3726 // we have to do a signed multiply
3728 emitcode (";", "signed");
3729 emitcode ("clr", "F0"); // reset sign flag
3730 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3731 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3733 lbl=newiTempLabel(NULL);
3734 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3735 // left side is negative, 8-bit two's complement, this fails for -128
3736 emitcode ("setb", "F0"); // set sign flag
3737 emitcode ("cpl", "a");
3738 emitcode ("inc", "a");
3740 emitcode ("", "%05d$:", lbl->key+100);
3741 emitcode ("xch", "a,b");
3744 if (AOP_TYPE(right)==AOP_LIT) {
3745 /* AND literal negative */
3746 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3747 // two's complement for literal<0
3748 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3749 emitcode ("cpl", "a");
3750 emitcode ("inc", "a");
3753 lbl=newiTempLabel(NULL);
3754 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3755 // right side is negative, 8-bit two's complement
3756 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3757 emitcode ("cpl", "a");
3758 emitcode ("inc", "a");
3759 emitcode ("", "%05d$:", lbl->key+100);
3761 emitcode ("mul", "ab");
3763 lbl=newiTempLabel(NULL);
3764 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3765 // only ONE op was negative, we have to do a 8/16-bit two's complement
3766 emitcode ("cpl", "a"); // lsb
3768 emitcode ("inc", "a");
3770 emitcode ("add", "a,#1");
3771 emitcode ("xch", "a,b");
3772 emitcode ("cpl", "a"); // msb
3773 emitcode ("addc", "a,#0");
3774 emitcode ("xch", "a,b");
3777 emitcode ("", "%05d$:", lbl->key+100);
3778 aopPut (AOP (result), "a", 0);
3780 aopPut (AOP (result), "b", 1);
3784 /*-----------------------------------------------------------------*/
3785 /* genMult - generates code for multiplication */
3786 /*-----------------------------------------------------------------*/
3788 genMult (iCode * ic)
3790 operand *left = IC_LEFT (ic);
3791 operand *right = IC_RIGHT (ic);
3792 operand *result = IC_RESULT (ic);
3794 D (emitcode (";", "genMult ");
3797 /* assign the amsops */
3800 /* special cases first */
3802 if (AOP_TYPE (left) == AOP_CRY &&
3803 AOP_TYPE (right) == AOP_CRY)
3805 genMultbits (left, right, result);
3809 /* if both are of size == 1 */
3810 if (AOP_SIZE (left) == 1 &&
3811 AOP_SIZE (right) == 1)
3813 genMultOneByte (left, right, result);
3817 /* should have been converted to function call */
3821 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3822 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3823 freeAsmop (result, NULL, ic, TRUE);
3826 /*-----------------------------------------------------------------*/
3827 /* genDivbits :- division of bits */
3828 /*-----------------------------------------------------------------*/
3830 genDivbits (operand * left,
3837 /* the result must be bit */
3838 LOAD_AB_FOR_DIV (left, right, l);
3839 emitcode ("div", "ab");
3840 emitcode ("rrc", "a");
3841 aopPut (AOP (result), "c", 0);
3844 /*-----------------------------------------------------------------*/
3845 /* genDivOneByte : 8 bit division */
3846 /*-----------------------------------------------------------------*/
3848 genDivOneByte (operand * left,
3852 sym_link *opetype = operandType (result);
3857 size = AOP_SIZE (result) - 1;
3859 /* signed or unsigned */
3860 if (SPEC_USIGN (opetype))
3862 /* unsigned is easy */
3863 LOAD_AB_FOR_DIV (left, right, l);
3864 emitcode ("div", "ab");
3865 aopPut (AOP (result), "a", 0);
3867 aopPut (AOP (result), zero, offset++);
3871 /* signed is a little bit more difficult */
3873 /* save the signs of the operands */
3874 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3876 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3877 emitcode ("push", "acc"); /* save it on the stack */
3879 /* now sign adjust for both left & right */
3880 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3882 lbl = newiTempLabel (NULL);
3883 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3884 emitcode ("cpl", "a");
3885 emitcode ("inc", "a");
3886 emitcode ("", "%05d$:", (lbl->key + 100));
3887 emitcode ("mov", "b,a");
3889 /* sign adjust left side */
3890 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3893 lbl = newiTempLabel (NULL);
3894 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3895 emitcode ("cpl", "a");
3896 emitcode ("inc", "a");
3897 emitcode ("", "%05d$:", (lbl->key + 100));
3899 /* now the division */
3900 emitcode ("nop", "; workaround for DS80C390 div bug.");
3901 emitcode ("div", "ab");
3902 /* we are interested in the lower order
3904 emitcode ("mov", "b,a");
3905 lbl = newiTempLabel (NULL);
3906 emitcode ("pop", "acc");
3907 /* if there was an over flow we don't
3908 adjust the sign of the result */
3909 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3910 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3912 emitcode ("clr", "a");
3913 emitcode ("subb", "a,b");
3914 emitcode ("mov", "b,a");
3915 emitcode ("", "%05d$:", (lbl->key + 100));
3917 /* now we are done */
3918 aopPut (AOP (result), "b", 0);
3921 emitcode ("mov", "c,b.7");
3922 emitcode ("subb", "a,acc");
3925 aopPut (AOP (result), "a", offset++);
3929 /*-----------------------------------------------------------------*/
3930 /* genDiv - generates code for division */
3931 /*-----------------------------------------------------------------*/
3935 operand *left = IC_LEFT (ic);
3936 operand *right = IC_RIGHT (ic);
3937 operand *result = IC_RESULT (ic);
3939 D (emitcode (";", "genDiv ");
3942 /* assign the amsops */
3945 /* special cases first */
3947 if (AOP_TYPE (left) == AOP_CRY &&
3948 AOP_TYPE (right) == AOP_CRY)
3950 genDivbits (left, right, result);
3954 /* if both are of size == 1 */
3955 if (AOP_SIZE (left) == 1 &&
3956 AOP_SIZE (right) == 1)
3958 genDivOneByte (left, right, result);
3962 /* should have been converted to function call */
3965 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3966 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3967 freeAsmop (result, NULL, ic, TRUE);
3970 /*-----------------------------------------------------------------*/
3971 /* genModbits :- modulus of bits */
3972 /*-----------------------------------------------------------------*/
3974 genModbits (operand * left,
3981 /* the result must be bit */
3982 LOAD_AB_FOR_DIV (left, right, l);
3983 emitcode ("div", "ab");
3984 emitcode ("mov", "a,b");
3985 emitcode ("rrc", "a");
3986 aopPut (AOP (result), "c", 0);
3989 /*-----------------------------------------------------------------*/
3990 /* genModOneByte : 8 bit modulus */
3991 /*-----------------------------------------------------------------*/
3993 genModOneByte (operand * left,
3997 sym_link *opetype = operandType (result);
4001 /* signed or unsigned */
4002 if (SPEC_USIGN (opetype))
4004 /* unsigned is easy */
4005 LOAD_AB_FOR_DIV (left, right, l);
4006 emitcode ("div", "ab");
4007 aopPut (AOP (result), "b", 0);
4011 /* signed is a little bit more difficult */
4013 /* save the signs of the operands */
4014 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4017 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4018 emitcode ("push", "acc"); /* save it on the stack */
4020 /* now sign adjust for both left & right */
4021 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4024 lbl = newiTempLabel (NULL);
4025 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4026 emitcode ("cpl", "a");
4027 emitcode ("inc", "a");
4028 emitcode ("", "%05d$:", (lbl->key + 100));
4029 emitcode ("mov", "b,a");
4031 /* sign adjust left side */
4032 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4035 lbl = newiTempLabel (NULL);
4036 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4037 emitcode ("cpl", "a");
4038 emitcode ("inc", "a");
4039 emitcode ("", "%05d$:", (lbl->key + 100));
4041 /* now the multiplication */
4042 emitcode ("nop", "; workaround for DS80C390 div bug.");
4043 emitcode ("div", "ab");
4044 /* we are interested in the lower order
4046 lbl = newiTempLabel (NULL);
4047 emitcode ("pop", "acc");
4048 /* if there was an over flow we don't
4049 adjust the sign of the result */
4050 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4051 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4053 emitcode ("clr", "a");
4054 emitcode ("subb", "a,b");
4055 emitcode ("mov", "b,a");
4056 emitcode ("", "%05d$:", (lbl->key + 100));
4058 /* now we are done */
4059 aopPut (AOP (result), "b", 0);
4063 /*-----------------------------------------------------------------*/
4064 /* genMod - generates code for division */
4065 /*-----------------------------------------------------------------*/
4069 operand *left = IC_LEFT (ic);
4070 operand *right = IC_RIGHT (ic);
4071 operand *result = IC_RESULT (ic);
4073 D (emitcode (";", "genMod ");
4076 /* assign the amsops */
4079 /* special cases first */
4081 if (AOP_TYPE (left) == AOP_CRY &&
4082 AOP_TYPE (right) == AOP_CRY)
4084 genModbits (left, right, result);
4088 /* if both are of size == 1 */
4089 if (AOP_SIZE (left) == 1 &&
4090 AOP_SIZE (right) == 1)
4092 genModOneByte (left, right, result);
4096 /* should have been converted to function call */
4100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 freeAsmop (result, NULL, ic, TRUE);
4105 /*-----------------------------------------------------------------*/
4106 /* genIfxJump :- will create a jump depending on the ifx */
4107 /*-----------------------------------------------------------------*/
4109 genIfxJump (iCode * ic, char *jval)
4112 symbol *tlbl = newiTempLabel (NULL);
4115 D (emitcode (";", "genIfxJump ");
4118 /* if true label then we jump if condition
4122 jlbl = IC_TRUE (ic);
4123 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4124 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4128 /* false label is present */
4129 jlbl = IC_FALSE (ic);
4130 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4131 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4133 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4134 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4136 emitcode (inst, "%05d$", tlbl->key + 100);
4137 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4138 emitcode ("", "%05d$:", tlbl->key + 100);
4140 /* mark the icode as generated */
4144 /*-----------------------------------------------------------------*/
4145 /* genCmp :- greater or less than comparison */
4146 /*-----------------------------------------------------------------*/
4148 genCmp (operand * left, operand * right,
4149 iCode * ic, iCode * ifx, int sign)
4151 int size, offset = 0;
4152 unsigned long lit = 0L;
4155 D (emitcode (";", "genCmp");
4158 result = IC_RESULT (ic);
4160 /* if left & right are bit variables */
4161 if (AOP_TYPE (left) == AOP_CRY &&
4162 AOP_TYPE (right) == AOP_CRY)
4164 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4165 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4169 /* subtract right from left if at the
4170 end the carry flag is set then we know that
4171 left is greater than right */
4172 size = max (AOP_SIZE (left), AOP_SIZE (right));
4174 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4175 if ((size == 1) && !sign &&
4176 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4178 symbol *lbl = newiTempLabel (NULL);
4179 emitcode ("cjne", "%s,%s,%05d$",
4180 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4181 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4183 emitcode ("", "%05d$:", lbl->key + 100);
4187 if (AOP_TYPE (right) == AOP_LIT)
4189 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4190 /* optimize if(x < 0) or if(x >= 0) */
4199 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4201 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4202 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4204 aopOp (result, ic, FALSE, FALSE);
4206 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4208 freeAsmop (result, NULL, ic, TRUE);
4209 genIfxJump (ifx, "acc.7");
4214 emitcode ("rlc", "a");
4216 goto release_freedLR;
4224 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4225 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4226 emitcode (";", "genCmp #2");
4227 if (sign && (size == 0))
4229 emitcode (";", "genCmp #3");
4230 emitcode ("xrl", "a,#0x80");
4231 if (AOP_TYPE (right) == AOP_LIT)
4233 unsigned long lit = (unsigned long)
4234 floatFromVal (AOP (right)->aopu.aop_lit);
4235 emitcode (";", "genCmp #3.1");
4236 emitcode ("subb", "a,#0x%02x",
4237 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4241 emitcode (";", "genCmp #3.2");
4242 if (AOP_NEEDSACC (right))
4244 emitcode ("push", "acc");
4246 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4247 FALSE, FALSE, FALSE));
4248 emitcode ("xrl", "b,#0x80");
4249 if (AOP_NEEDSACC (right))
4251 emitcode ("pop", "acc");
4253 emitcode ("subb", "a,b");
4260 emitcode (";", "genCmp #4");
4261 if (AOP_NEEDSACC (right))
4264 emitcode (";", "genCmp #4.1");
4265 emitcode ("xch", "a, b");
4266 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4267 emitcode ("xch", "a, b");
4272 emitcode (";", "genCmp #4.2");
4273 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4276 emitcode ("subb", "a,%s", s);
4283 /* Don't need the left & right operands any more; do need the result. */
4284 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4285 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4287 aopOp (result, ic, FALSE, FALSE);
4291 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4297 /* if the result is used in the next
4298 ifx conditional branch then generate
4299 code a little differently */
4302 genIfxJump (ifx, "c");
4308 /* leave the result in acc */
4310 freeAsmop (result, NULL, ic, TRUE);
4313 /*-----------------------------------------------------------------*/
4314 /* genCmpGt :- greater than comparison */
4315 /*-----------------------------------------------------------------*/
4317 genCmpGt (iCode * ic, iCode * ifx)
4319 operand *left, *right;
4320 sym_link *letype, *retype;
4323 D (emitcode (";", "genCmpGt ");
4326 left = IC_LEFT (ic);
4327 right = IC_RIGHT (ic);
4329 letype = getSpec (operandType (left));
4330 retype = getSpec (operandType (right));
4331 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4333 /* assign the left & right amsops */
4336 genCmp (right, left, ic, ifx, sign);
4339 /*-----------------------------------------------------------------*/
4340 /* genCmpLt - less than comparisons */
4341 /*-----------------------------------------------------------------*/
4343 genCmpLt (iCode * ic, iCode * ifx)
4345 operand *left, *right;
4346 sym_link *letype, *retype;
4349 D (emitcode (";", "genCmpLt ");
4352 left = IC_LEFT (ic);
4353 right = IC_RIGHT (ic);
4355 letype = getSpec (operandType (left));
4356 retype = getSpec (operandType (right));
4357 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4359 /* assign the left & right amsops */
4362 genCmp (left, right, ic, ifx, sign);
4365 /*-----------------------------------------------------------------*/
4366 /* gencjneshort - compare and jump if not equal */
4367 /*-----------------------------------------------------------------*/
4369 gencjneshort (operand * left, operand * right, symbol * lbl)
4371 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4373 unsigned long lit = 0L;
4375 D (emitcode (";", "gencjneshort");
4378 /* if the left side is a literal or
4379 if the right is in a pointer register and left
4381 if ((AOP_TYPE (left) == AOP_LIT) ||
4382 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4389 if (AOP_TYPE (right) == AOP_LIT)
4390 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4392 if (opIsGptr (left) || opIsGptr (right))
4394 /* We are comparing a generic pointer to something.
4395 * Exclude the generic type byte from the comparison.
4398 D (emitcode (";", "cjneshort: generic ptr special case.");
4403 /* if the right side is a literal then anything goes */
4404 if (AOP_TYPE (right) == AOP_LIT &&
4405 AOP_TYPE (left) != AOP_DIR)
4409 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4411 emitcode ("cjne", "a,%s,%05d$",
4412 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4418 /* if the right side is in a register or in direct space or
4419 if the left is a pointer register & right is not */
4420 else if (AOP_TYPE (right) == AOP_REG ||
4421 AOP_TYPE (right) == AOP_DIR ||
4422 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4423 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4427 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4428 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4429 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4430 emitcode ("jnz", "%05d$", lbl->key + 100);
4432 emitcode ("cjne", "a,%s,%05d$",
4433 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4440 /* right is a pointer reg need both a & b */
4443 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4444 if (strcmp (l, "b"))
4445 emitcode ("mov", "b,%s", l);
4446 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4447 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4453 /*-----------------------------------------------------------------*/
4454 /* gencjne - compare and jump if not equal */
4455 /*-----------------------------------------------------------------*/
4457 gencjne (operand * left, operand * right, symbol * lbl)
4459 symbol *tlbl = newiTempLabel (NULL);
4461 D (emitcode (";", "gencjne");
4464 gencjneshort (left, right, lbl);
4466 emitcode ("mov", "a,%s", one);
4467 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4468 emitcode ("", "%05d$:", lbl->key + 100);
4469 emitcode ("clr", "a");
4470 emitcode ("", "%05d$:", tlbl->key + 100);
4473 /*-----------------------------------------------------------------*/
4474 /* genCmpEq - generates code for equal to */
4475 /*-----------------------------------------------------------------*/
4477 genCmpEq (iCode * ic, iCode * ifx)
4479 operand *left, *right, *result;
4481 D (emitcode (";", "genCmpEq ");
4485 AOP_SET_LOCALS (ic);
4487 /* if literal, literal on the right or
4488 if the right is in a pointer register and left
4490 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4491 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4493 operand *t = IC_RIGHT (ic);
4494 IC_RIGHT (ic) = IC_LEFT (ic);
4498 if (ifx && /* !AOP_SIZE(result) */
4499 OP_SYMBOL (result) &&
4500 OP_SYMBOL (result)->regType == REG_CND)
4503 /* if they are both bit variables */
4504 if (AOP_TYPE (left) == AOP_CRY &&
4505 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4507 if (AOP_TYPE (right) == AOP_LIT)
4509 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4512 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513 emitcode ("cpl", "c");
4517 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4521 emitcode ("clr", "c");
4523 /* AOP_TYPE(right) == AOP_CRY */
4527 symbol *lbl = newiTempLabel (NULL);
4528 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4529 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4530 emitcode ("cpl", "c");
4531 emitcode ("", "%05d$:", (lbl->key + 100));
4533 /* if true label then we jump if condition
4535 tlbl = newiTempLabel (NULL);
4538 emitcode ("jnc", "%05d$", tlbl->key + 100);
4539 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4543 emitcode ("jc", "%05d$", tlbl->key + 100);
4544 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4546 emitcode ("", "%05d$:", tlbl->key + 100);
4550 tlbl = newiTempLabel (NULL);
4551 gencjneshort (left, right, tlbl);
4554 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4555 emitcode ("", "%05d$:", tlbl->key + 100);
4559 symbol *lbl = newiTempLabel (NULL);
4560 emitcode ("sjmp", "%05d$", lbl->key + 100);
4561 emitcode ("", "%05d$:", tlbl->key + 100);
4562 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4563 emitcode ("", "%05d$:", lbl->key + 100);
4566 /* mark the icode as generated */
4569 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4570 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4574 /* if they are both bit variables */
4575 if (AOP_TYPE (left) == AOP_CRY &&
4576 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4578 if (AOP_TYPE (right) == AOP_LIT)
4580 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4583 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4584 emitcode ("cpl", "c");
4588 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4592 emitcode ("clr", "c");
4594 /* AOP_TYPE(right) == AOP_CRY */
4598 symbol *lbl = newiTempLabel (NULL);
4599 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4600 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4601 emitcode ("cpl", "c");
4602 emitcode ("", "%05d$:", (lbl->key + 100));
4605 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4606 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4608 aopOp (result, ic, TRUE, FALSE);
4611 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4618 genIfxJump (ifx, "c");
4621 /* if the result is used in an arithmetic operation
4622 then put the result in place */
4627 gencjne (left, right, newiTempLabel (NULL));
4629 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4630 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4632 aopOp (result, ic, TRUE, FALSE);
4634 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4636 aopPut (AOP (result), "a", 0);
4641 genIfxJump (ifx, "a");
4644 /* if the result is used in an arithmetic operation
4645 then put the result in place */
4646 if (AOP_TYPE (result) != AOP_CRY)
4648 /* leave the result in acc */
4652 freeAsmop (result, NULL, ic, TRUE);
4655 /*-----------------------------------------------------------------*/
4656 /* ifxForOp - returns the icode containing the ifx for operand */
4657 /*-----------------------------------------------------------------*/
4659 ifxForOp (operand * op, iCode * ic)
4661 /* if true symbol then needs to be assigned */
4662 if (IS_TRUE_SYMOP (op))
4665 /* if this has register type condition and
4666 the next instruction is ifx with the same operand
4667 and live to of the operand is upto the ifx only then */
4669 ic->next->op == IFX &&
4670 IC_COND (ic->next)->key == op->key &&
4671 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4676 /*-----------------------------------------------------------------*/
4677 /* genAndOp - for && operation */
4678 /*-----------------------------------------------------------------*/
4680 genAndOp (iCode * ic)
4682 operand *left, *right, *result;
4685 D (emitcode (";", "genAndOp ");
4688 /* note here that && operations that are in an
4689 if statement are taken away by backPatchLabels
4690 only those used in arthmetic operations remain */
4692 AOP_SET_LOCALS (ic);
4694 /* if both are bit variables */
4695 if (AOP_TYPE (left) == AOP_CRY &&
4696 AOP_TYPE (right) == AOP_CRY)
4698 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4699 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4704 tlbl = newiTempLabel (NULL);
4706 emitcode ("jz", "%05d$", tlbl->key + 100);
4708 emitcode ("", "%05d$:", tlbl->key + 100);
4712 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4713 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714 freeAsmop (result, NULL, ic, TRUE);
4718 /*-----------------------------------------------------------------*/
4719 /* genOrOp - for || operation */
4720 /*-----------------------------------------------------------------*/
4722 genOrOp (iCode * ic)
4724 operand *left, *right, *result;
4727 D (emitcode (";", "genOrOp ");
4730 /* note here that || operations that are in an
4731 if statement are taken away by backPatchLabels
4732 only those used in arthmetic operations remain */
4734 AOP_SET_LOCALS (ic);
4736 /* if both are bit variables */
4737 if (AOP_TYPE (left) == AOP_CRY &&
4738 AOP_TYPE (right) == AOP_CRY)
4740 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4741 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4746 tlbl = newiTempLabel (NULL);
4748 emitcode ("jnz", "%05d$", tlbl->key + 100);
4750 emitcode ("", "%05d$:", tlbl->key + 100);
4754 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4755 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4756 freeAsmop (result, NULL, ic, TRUE);
4759 /*-----------------------------------------------------------------*/
4760 /* isLiteralBit - test if lit == 2^n */
4761 /*-----------------------------------------------------------------*/
4763 isLiteralBit (unsigned long lit)
4765 unsigned long pw[32] =
4766 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4767 0x100L, 0x200L, 0x400L, 0x800L,
4768 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4769 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4770 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4771 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4772 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4775 for (idx = 0; idx < 32; idx++)
4781 /*-----------------------------------------------------------------*/
4782 /* continueIfTrue - */
4783 /*-----------------------------------------------------------------*/
4785 continueIfTrue (iCode * ic)
4788 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4792 /*-----------------------------------------------------------------*/
4794 /*-----------------------------------------------------------------*/
4796 jumpIfTrue (iCode * ic)
4799 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4803 /*-----------------------------------------------------------------*/
4804 /* jmpTrueOrFalse - */
4805 /*-----------------------------------------------------------------*/
4807 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4809 // ugly but optimized by peephole
4812 symbol *nlbl = newiTempLabel (NULL);
4813 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4814 emitcode ("", "%05d$:", tlbl->key + 100);
4815 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4816 emitcode ("", "%05d$:", nlbl->key + 100);
4820 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4821 emitcode ("", "%05d$:", tlbl->key + 100);
4826 /*-----------------------------------------------------------------*/
4827 /* genAnd - code for and */
4828 /*-----------------------------------------------------------------*/
4830 genAnd (iCode * ic, iCode * ifx)
4832 operand *left, *right, *result;
4833 int size, offset = 0;
4834 unsigned long lit = 0L;
4838 D (emitcode (";", "genAnd ");
4842 AOP_SET_LOCALS (ic);
4845 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4847 AOP_TYPE (left), AOP_TYPE (right));
4848 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4850 AOP_SIZE (left), AOP_SIZE (right));
4853 /* if left is a literal & right is not then exchange them */
4854 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4855 AOP_NEEDSACC (left))
4857 operand *tmp = right;
4862 /* if result = right then exchange them */
4863 if (sameRegs (AOP (result), AOP (right)))
4865 operand *tmp = right;
4870 /* if right is bit then exchange them */
4871 if (AOP_TYPE (right) == AOP_CRY &&
4872 AOP_TYPE (left) != AOP_CRY)
4874 operand *tmp = right;
4878 if (AOP_TYPE (right) == AOP_LIT)
4879 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4881 size = AOP_SIZE (result);
4884 // result = bit & yy;
4885 if (AOP_TYPE (left) == AOP_CRY)
4887 // c = bit & literal;
4888 if (AOP_TYPE (right) == AOP_LIT)
4892 if (size && sameRegs (AOP (result), AOP (left)))
4895 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4900 if (size && (AOP_TYPE (result) == AOP_CRY))
4902 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4905 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4910 emitcode ("clr", "c");
4915 if (AOP_TYPE (right) == AOP_CRY)
4918 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4919 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4924 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4926 emitcode ("rrc", "a");
4927 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4935 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4936 genIfxJump (ifx, "c");
4940 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4941 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4942 if ((AOP_TYPE (right) == AOP_LIT) &&
4943 (AOP_TYPE (result) == AOP_CRY) &&
4944 (AOP_TYPE (left) != AOP_CRY))
4946 int posbit = isLiteralBit (lit);
4951 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4954 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4960 sprintf (buffer, "acc.%d", posbit & 0x07);
4961 genIfxJump (ifx, buffer);
4968 symbol *tlbl = newiTempLabel (NULL);
4969 int sizel = AOP_SIZE (left);
4971 emitcode ("setb", "c");
4974 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4976 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4978 if ((posbit = isLiteralBit (bytelit)) != 0)
4979 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4982 if (bytelit != 0x0FFL)
4983 emitcode ("anl", "a,%s",
4984 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4985 emitcode ("jnz", "%05d$", tlbl->key + 100);
4990 // bit = left & literal
4993 emitcode ("clr", "c");
4994 emitcode ("", "%05d$:", tlbl->key + 100);
4996 // if(left & literal)
5000 jmpTrueOrFalse (ifx, tlbl);
5008 /* if left is same as result */
5009 if (sameRegs (AOP (result), AOP (left)))
5011 for (; size--; offset++)
5013 if (AOP_TYPE (right) == AOP_LIT)
5015 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5017 else if (bytelit == 0)
5018 aopPut (AOP (result), zero, offset);
5019 else if (IS_AOP_PREG (result))
5021 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5022 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5023 aopPut (AOP (result), "a", offset);
5026 emitcode ("anl", "%s,%s",
5027 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5028 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5032 if (AOP_TYPE (left) == AOP_ACC)
5033 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5036 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5037 if (IS_AOP_PREG (result))
5039 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5040 aopPut (AOP (result), "a", offset);
5044 emitcode ("anl", "%s,a",
5045 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5052 // left & result in different registers
5053 if (AOP_TYPE (result) == AOP_CRY)
5056 // if(size), result in bit
5057 // if(!size && ifx), conditional oper: if(left & right)
5058 symbol *tlbl = newiTempLabel (NULL);
5059 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5061 emitcode ("setb", "c");
5064 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5065 emitcode ("anl", "a,%s",
5066 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5067 emitcode ("jnz", "%05d$", tlbl->key + 100);
5073 emitcode ("", "%05d$:", tlbl->key + 100);
5077 jmpTrueOrFalse (ifx, tlbl);
5081 for (; (size--); offset++)
5084 // result = left & right
5085 if (AOP_TYPE (right) == AOP_LIT)
5087 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5089 aopPut (AOP (result),
5090 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5094 else if (bytelit == 0)
5096 aopPut (AOP (result), zero, offset);
5099 D (emitcode (";", "better literal AND.");
5101 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5102 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5103 FALSE, FALSE, FALSE));
5108 // faster than result <- left, anl result,right
5109 // and better if result is SFR
5110 if (AOP_TYPE (left) == AOP_ACC)
5112 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5113 FALSE, FALSE, FALSE));
5117 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5118 emitcode ("anl", "a,%s",
5119 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5122 aopPut (AOP (result), "a", offset);
5128 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5129 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5130 freeAsmop (result, NULL, ic, TRUE);
5133 /*-----------------------------------------------------------------*/
5134 /* genOr - code for or */
5135 /*-----------------------------------------------------------------*/
5137 genOr (iCode * ic, iCode * ifx)
5139 operand *left, *right, *result;
5140 int size, offset = 0;
5141 unsigned long lit = 0L;
5143 D (emitcode (";", "genOr ");
5147 AOP_SET_LOCALS (ic);
5150 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5152 AOP_TYPE (left), AOP_TYPE (right));
5153 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5155 AOP_SIZE (left), AOP_SIZE (right));
5158 /* if left is a literal & right is not then exchange them */
5159 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5160 AOP_NEEDSACC (left))
5162 operand *tmp = right;
5167 /* if result = right then exchange them */
5168 if (sameRegs (AOP (result), AOP (right)))
5170 operand *tmp = right;
5175 /* if right is bit then exchange them */
5176 if (AOP_TYPE (right) == AOP_CRY &&
5177 AOP_TYPE (left) != AOP_CRY)
5179 operand *tmp = right;
5183 if (AOP_TYPE (right) == AOP_LIT)
5184 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5186 size = AOP_SIZE (result);
5190 if (AOP_TYPE (left) == AOP_CRY)
5192 if (AOP_TYPE (right) == AOP_LIT)
5194 // c = bit & literal;
5197 // lit != 0 => result = 1
5198 if (AOP_TYPE (result) == AOP_CRY)
5201 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5203 continueIfTrue (ifx);
5206 emitcode ("setb", "c");
5210 // lit == 0 => result = left
5211 if (size && sameRegs (AOP (result), AOP (left)))
5213 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5218 if (AOP_TYPE (right) == AOP_CRY)
5221 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5222 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5227 symbol *tlbl = newiTempLabel (NULL);
5228 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5229 emitcode ("setb", "c");
5230 emitcode ("jb", "%s,%05d$",
5231 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5233 emitcode ("jnz", "%05d$", tlbl->key + 100);
5234 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5236 jmpTrueOrFalse (ifx, tlbl);
5242 emitcode ("", "%05d$:", tlbl->key + 100);
5251 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5252 genIfxJump (ifx, "c");
5256 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5257 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5258 if ((AOP_TYPE (right) == AOP_LIT) &&
5259 (AOP_TYPE (result) == AOP_CRY) &&
5260 (AOP_TYPE (left) != AOP_CRY))
5266 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5268 continueIfTrue (ifx);
5273 // lit = 0, result = boolean(left)
5275 emitcode ("setb", "c");
5279 symbol *tlbl = newiTempLabel (NULL);
5280 emitcode ("jnz", "%05d$", tlbl->key + 100);
5282 emitcode ("", "%05d$:", tlbl->key + 100);
5286 genIfxJump (ifx, "a");
5294 /* if left is same as result */
5295 if (sameRegs (AOP (result), AOP (left)))
5297 for (; size--; offset++)
5299 if (AOP_TYPE (right) == AOP_LIT)
5301 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5307 if (IS_AOP_PREG (left))
5309 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5310 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5311 aopPut (AOP (result), "a", offset);
5315 emitcode ("orl", "%s,%s",
5316 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5317 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5323 if (AOP_TYPE (left) == AOP_ACC)
5325 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5329 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5330 if (IS_AOP_PREG (left))
5332 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5333 aopPut (AOP (result), "a", offset);
5337 emitcode ("orl", "%s,a",
5338 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5346 // left & result in different registers
5347 if (AOP_TYPE (result) == AOP_CRY)
5350 // if(size), result in bit
5351 // if(!size && ifx), conditional oper: if(left | right)
5352 symbol *tlbl = newiTempLabel (NULL);
5353 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5355 emitcode ("setb", "c");
5358 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5359 emitcode ("orl", "a,%s",
5360 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5361 emitcode ("jnz", "%05d$", tlbl->key + 100);
5367 emitcode ("", "%05d$:", tlbl->key + 100);
5371 jmpTrueOrFalse (ifx, tlbl);
5375 for (; (size--); offset++)
5378 // result = left & right
5379 if (AOP_TYPE (right) == AOP_LIT)
5381 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5383 aopPut (AOP (result),
5384 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5388 D (emitcode (";", "better literal OR.");
5390 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5391 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5392 FALSE, FALSE, FALSE));
5397 // faster than result <- left, anl result,right
5398 // and better if result is SFR
5399 if (AOP_TYPE (left) == AOP_ACC)
5401 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5402 FALSE, FALSE, FALSE));
5406 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5407 emitcode ("orl", "a,%s",
5408 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5411 aopPut (AOP (result), "a", offset);
5417 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 freeAsmop (result, NULL, ic, TRUE);
5422 /*-----------------------------------------------------------------*/
5423 /* genXor - code for xclusive or */
5424 /*-----------------------------------------------------------------*/
5426 genXor (iCode * ic, iCode * ifx)
5428 operand *left, *right, *result;
5429 int size, offset = 0;
5430 unsigned long lit = 0L;
5432 D (emitcode (";", "genXor ");
5436 AOP_SET_LOCALS (ic);
5439 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5441 AOP_TYPE (left), AOP_TYPE (right));
5442 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5444 AOP_SIZE (left), AOP_SIZE (right));
5447 /* if left is a literal & right is not ||
5448 if left needs acc & right does not */
5449 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5450 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5452 operand *tmp = right;
5457 /* if result = right then exchange them */
5458 if (sameRegs (AOP (result), AOP (right)))
5460 operand *tmp = right;
5465 /* if right is bit then exchange them */
5466 if (AOP_TYPE (right) == AOP_CRY &&
5467 AOP_TYPE (left) != AOP_CRY)
5469 operand *tmp = right;
5473 if (AOP_TYPE (right) == AOP_LIT)
5474 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5476 size = AOP_SIZE (result);
5480 if (AOP_TYPE (left) == AOP_CRY)
5482 if (AOP_TYPE (right) == AOP_LIT)
5484 // c = bit & literal;
5487 // lit>>1 != 0 => result = 1
5488 if (AOP_TYPE (result) == AOP_CRY)
5491 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5493 continueIfTrue (ifx);
5496 emitcode ("setb", "c");
5503 // lit == 0, result = left
5504 if (size && sameRegs (AOP (result), AOP (left)))
5506 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5510 // lit == 1, result = not(left)
5511 if (size && sameRegs (AOP (result), AOP (left)))
5513 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5519 emitcode ("cpl", "c");
5528 symbol *tlbl = newiTempLabel (NULL);
5529 if (AOP_TYPE (right) == AOP_CRY)
5532 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5536 int sizer = AOP_SIZE (right);
5538 // if val>>1 != 0, result = 1
5539 emitcode ("setb", "c");
5542 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5544 // test the msb of the lsb
5545 emitcode ("anl", "a,#0xfe");
5546 emitcode ("jnz", "%05d$", tlbl->key + 100);
5550 emitcode ("rrc", "a");
5552 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5553 emitcode ("cpl", "c");
5554 emitcode ("", "%05d$:", (tlbl->key + 100));
5561 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5562 genIfxJump (ifx, "c");
5566 if (sameRegs (AOP (result), AOP (left)))
5568 /* if left is same as result */
5569 for (; size--; offset++)
5571 if (AOP_TYPE (right) == AOP_LIT)
5573 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5575 else if (IS_AOP_PREG (left))
5577 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5578 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5579 aopPut (AOP (result), "a", offset);
5582 emitcode ("xrl", "%s,%s",
5583 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5584 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5588 if (AOP_TYPE (left) == AOP_ACC)
5589 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5592 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5593 if (IS_AOP_PREG (left))
5595 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5596 aopPut (AOP (result), "a", offset);
5599 emitcode ("xrl", "%s,a",
5600 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5607 // left & result in different registers
5608 if (AOP_TYPE (result) == AOP_CRY)
5611 // if(size), result in bit
5612 // if(!size && ifx), conditional oper: if(left ^ right)
5613 symbol *tlbl = newiTempLabel (NULL);
5614 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5616 emitcode ("setb", "c");
5619 if ((AOP_TYPE (right) == AOP_LIT) &&
5620 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5622 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5626 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5627 emitcode ("xrl", "a,%s",
5628 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5630 emitcode ("jnz", "%05d$", tlbl->key + 100);
5636 emitcode ("", "%05d$:", tlbl->key + 100);
5640 jmpTrueOrFalse (ifx, tlbl);
5643 for (; (size--); offset++)
5646 // result = left & right
5647 if (AOP_TYPE (right) == AOP_LIT)
5649 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5651 aopPut (AOP (result),
5652 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5656 D (emitcode (";", "better literal XOR.");
5658 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5659 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5660 FALSE, FALSE, FALSE));
5664 // faster than result <- left, anl result,right
5665 // and better if result is SFR
5666 if (AOP_TYPE (left) == AOP_ACC)
5668 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5669 FALSE, FALSE, FALSE));
5673 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5674 emitcode ("xrl", "a,%s",
5675 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5678 aopPut (AOP (result), "a", offset);
5683 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5684 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5685 freeAsmop (result, NULL, ic, TRUE);
5688 /*-----------------------------------------------------------------*/
5689 /* genInline - write the inline code out */
5690 /*-----------------------------------------------------------------*/
5692 genInline (iCode * ic)
5694 char buffer[MAX_INLINEASM];
5698 D (emitcode (";", "genInline ");
5701 _G.inLine += (!options.asmpeep);
5702 strcpy (buffer, IC_INLINE (ic));
5704 /* emit each line as a code */
5729 /* emitcode("",buffer); */
5730 _G.inLine -= (!options.asmpeep);
5733 /*-----------------------------------------------------------------*/
5734 /* genRRC - rotate right with carry */
5735 /*-----------------------------------------------------------------*/
5739 operand *left, *result;
5740 int size, offset = 0;
5743 D (emitcode (";", "genRRC ");
5746 /* rotate right with carry */
5747 left = IC_LEFT (ic);
5748 result = IC_RESULT (ic);
5749 aopOp (left, ic, FALSE, FALSE);
5750 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5752 /* move it to the result */
5753 size = AOP_SIZE (result);
5757 _startLazyDPSEvaluation ();
5760 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5762 emitcode ("rrc", "a");
5763 if (AOP_SIZE (result) > 1)
5764 aopPut (AOP (result), "a", offset--);
5766 _endLazyDPSEvaluation ();
5768 /* now we need to put the carry into the
5769 highest order byte of the result */
5770 if (AOP_SIZE (result) > 1)
5772 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5775 emitcode ("mov", "acc.7,c");
5776 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5777 freeAsmop (left, NULL, ic, TRUE);
5778 freeAsmop (result, NULL, ic, TRUE);
5781 /*-----------------------------------------------------------------*/
5782 /* genRLC - generate code for rotate left with carry */
5783 /*-----------------------------------------------------------------*/
5787 operand *left, *result;
5788 int size, offset = 0;
5791 D (emitcode (";", "genRLC ");
5794 /* rotate right with carry */
5795 left = IC_LEFT (ic);
5796 result = IC_RESULT (ic);
5797 aopOp (left, ic, FALSE, FALSE);
5798 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5800 /* move it to the result */
5801 size = AOP_SIZE (result);
5805 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5807 emitcode ("add", "a,acc");
5808 if (AOP_SIZE (result) > 1)
5810 aopPut (AOP (result), "a", offset++);
5813 _startLazyDPSEvaluation ();
5816 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5818 emitcode ("rlc", "a");
5819 if (AOP_SIZE (result) > 1)
5820 aopPut (AOP (result), "a", offset++);
5822 _endLazyDPSEvaluation ();
5824 /* now we need to put the carry into the
5825 highest order byte of the result */
5826 if (AOP_SIZE (result) > 1)
5828 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5831 emitcode ("mov", "acc.0,c");
5832 aopPut (AOP (result), "a", 0);
5833 freeAsmop (left, NULL, ic, TRUE);
5834 freeAsmop (result, NULL, ic, TRUE);
5837 /*-----------------------------------------------------------------*/
5838 /* genGetHbit - generates code get highest order bit */
5839 /*-----------------------------------------------------------------*/
5841 genGetHbit (iCode * ic)
5843 operand *left, *result;
5844 left = IC_LEFT (ic);
5845 result = IC_RESULT (ic);
5846 aopOp (left, ic, FALSE, FALSE);
5847 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5849 D (emitcode (";", "genGetHbit ");
5852 /* get the highest order byte into a */
5853 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5854 if (AOP_TYPE (result) == AOP_CRY)
5856 emitcode ("rlc", "a");
5861 emitcode ("rl", "a");
5862 emitcode ("anl", "a,#0x01");
5867 freeAsmop (left, NULL, ic, TRUE);
5868 freeAsmop (result, NULL, ic, TRUE);
5871 /*-----------------------------------------------------------------*/
5872 /* AccRol - rotate left accumulator by known count */
5873 /*-----------------------------------------------------------------*/
5875 AccRol (int shCount)
5877 shCount &= 0x0007; // shCount : 0..7
5884 emitcode ("rl", "a");
5887 emitcode ("rl", "a");
5888 emitcode ("rl", "a");
5891 emitcode ("swap", "a");
5892 emitcode ("rr", "a");
5895 emitcode ("swap", "a");
5898 emitcode ("swap", "a");
5899 emitcode ("rl", "a");
5902 emitcode ("rr", "a");
5903 emitcode ("rr", "a");
5906 emitcode ("rr", "a");
5911 /*-----------------------------------------------------------------*/
5912 /* AccLsh - left shift accumulator by known count */
5913 /*-----------------------------------------------------------------*/
5915 AccLsh (int shCount)
5920 emitcode ("add", "a,acc");
5921 else if (shCount == 2)
5923 emitcode ("add", "a,acc");
5924 emitcode ("add", "a,acc");
5928 /* rotate left accumulator */
5930 /* and kill the lower order bits */
5931 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5936 /*-----------------------------------------------------------------*/
5937 /* AccRsh - right shift accumulator by known count */
5938 /*-----------------------------------------------------------------*/
5940 AccRsh (int shCount)
5947 emitcode ("rrc", "a");
5951 /* rotate right accumulator */
5952 AccRol (8 - shCount);
5953 /* and kill the higher order bits */
5954 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5961 /*-----------------------------------------------------------------*/
5962 /* AccSRsh - signed right shift accumulator by known count */
5963 /*-----------------------------------------------------------------*/
5965 AccSRsh (int shCount)
5972 emitcode ("mov", "c,acc.7");
5973 emitcode ("rrc", "a");
5975 else if (shCount == 2)
5977 emitcode ("mov", "c,acc.7");
5978 emitcode ("rrc", "a");
5979 emitcode ("mov", "c,acc.7");
5980 emitcode ("rrc", "a");
5984 tlbl = newiTempLabel (NULL);
5985 /* rotate right accumulator */
5986 AccRol (8 - shCount);
5987 /* and kill the higher order bits */
5988 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5989 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5990 emitcode ("orl", "a,#0x%02x",
5991 (unsigned char) ~SRMask[shCount]);
5992 emitcode ("", "%05d$:", tlbl->key + 100);
6000 /*-----------------------------------------------------------------*/
6001 /* shiftR1Left2Result - shift right one byte from left to result */
6002 /*-----------------------------------------------------------------*/
6004 shiftR1Left2Result (operand * left, int offl,
6005 operand * result, int offr,
6006 int shCount, int sign)
6008 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6009 /* shift right accumulator */
6014 aopPut (AOP (result), "a", offr);
6020 /*-----------------------------------------------------------------*/
6021 /* shiftL1Left2Result - shift left one byte from left to result */
6022 /*-----------------------------------------------------------------*/
6024 shiftL1Left2Result (operand * left, int offl,
6025 operand * result, int offr, int shCount)
6028 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6030 /* shift left accumulator */
6032 aopPut (AOP (result), "a", offr);
6038 /*-----------------------------------------------------------------*/
6039 /* movLeft2Result - move byte from left to result */
6040 /*-----------------------------------------------------------------*/
6042 movLeft2Result (operand * left, int offl,
6043 operand * result, int offr, int sign)
6046 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6048 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6050 if (*l == '@' && (IS_AOP_PREG (result)))
6052 emitcode ("mov", "a,%s", l);
6053 aopPut (AOP (result), "a", offr);
6058 aopPut (AOP (result), l, offr);
6061 /* MSB sign in acc.7 ! */
6062 if (getDataSize (left) == offl + 1)
6064 emitcode ("mov", "a,%s", l);
6065 aopPut (AOP (result), "a", offr);
6075 /*-----------------------------------------------------------------*/
6076 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6077 /*-----------------------------------------------------------------*/
6081 emitcode ("rrc", "a");
6082 emitcode ("xch", "a,%s", x);
6083 emitcode ("rrc", "a");
6084 emitcode ("xch", "a,%s", x);
6090 /*-----------------------------------------------------------------*/
6091 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6092 /*-----------------------------------------------------------------*/
6096 emitcode ("xch", "a,%s", x);
6097 emitcode ("rlc", "a");
6098 emitcode ("xch", "a,%s", x);
6099 emitcode ("rlc", "a");
6105 /*-----------------------------------------------------------------*/
6106 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6107 /*-----------------------------------------------------------------*/
6111 emitcode ("xch", "a,%s", x);
6112 emitcode ("add", "a,acc");
6113 emitcode ("xch", "a,%s", x);
6114 emitcode ("rlc", "a");
6120 /*-----------------------------------------------------------------*/
6121 /* AccAXLsh - left shift a:x by known count (0..7) */
6122 /*-----------------------------------------------------------------*/
6124 AccAXLsh (char *x, int shCount)
6139 case 5: // AAAAABBB:CCCCCDDD
6141 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6143 emitcode ("anl", "a,#0x%02x",
6144 SLMask[shCount]); // BBB00000:CCCCCDDD
6146 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6148 AccRol (shCount); // DDDCCCCC:BBB00000
6150 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6152 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6154 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6156 emitcode ("anl", "a,#0x%02x",
6157 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6159 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6161 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6164 case 6: // AAAAAABB:CCCCCCDD
6165 emitcode ("anl", "a,#0x%02x",
6166 SRMask[shCount]); // 000000BB:CCCCCCDD
6167 emitcode ("mov", "c,acc.0"); // c = B
6168 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6170 AccAXRrl1 (x); // BCCCCCCD:D000000B
6171 AccAXRrl1 (x); // BBCCCCCC:DD000000
6173 emitcode("rrc","a");
6174 emitcode("xch","a,%s", x);
6175 emitcode("rrc","a");
6176 emitcode("mov","c,acc.0"); //<< get correct bit
6177 emitcode("xch","a,%s", x);
6179 emitcode("rrc","a");
6180 emitcode("xch","a,%s", x);
6181 emitcode("rrc","a");
6182 emitcode("xch","a,%s", x);
6185 case 7: // a:x <<= 7
6187 emitcode ("anl", "a,#0x%02x",
6188 SRMask[shCount]); // 0000000B:CCCCCCCD
6190 emitcode ("mov", "c,acc.0"); // c = B
6192 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6194 AccAXRrl1 (x); // BCCCCCCC:D0000000
6205 /*-----------------------------------------------------------------*/
6206 /* AccAXRsh - right shift a:x known count (0..7) */
6207 /*-----------------------------------------------------------------*/
6209 AccAXRsh (char *x, int shCount)
6217 AccAXRrl1 (x); // 0->a:x
6222 AccAXRrl1 (x); // 0->a:x
6225 AccAXRrl1 (x); // 0->a:x
6230 case 5: // AAAAABBB:CCCCCDDD = a:x
6232 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6234 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6236 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6238 emitcode ("anl", "a,#0x%02x",
6239 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6241 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6243 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6245 emitcode ("anl", "a,#0x%02x",
6246 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6248 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6250 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6252 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6255 case 6: // AABBBBBB:CCDDDDDD
6257 emitcode ("mov", "c,acc.7");
6258 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6260 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6262 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6264 emitcode ("anl", "a,#0x%02x",
6265 SRMask[shCount]); // 000000AA:BBBBBBCC
6268 case 7: // ABBBBBBB:CDDDDDDD
6270 emitcode ("mov", "c,acc.7"); // c = A
6272 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6274 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6276 emitcode ("anl", "a,#0x%02x",
6277 SRMask[shCount]); // 0000000A:BBBBBBBC
6288 /*-----------------------------------------------------------------*/
6289 /* AccAXRshS - right shift signed a:x known count (0..7) */
6290 /*-----------------------------------------------------------------*/
6292 AccAXRshS (char *x, int shCount)
6300 emitcode ("mov", "c,acc.7");
6301 AccAXRrl1 (x); // s->a:x
6305 emitcode ("mov", "c,acc.7");
6306 AccAXRrl1 (x); // s->a:x
6308 emitcode ("mov", "c,acc.7");
6309 AccAXRrl1 (x); // s->a:x
6314 case 5: // AAAAABBB:CCCCCDDD = a:x
6316 tlbl = newiTempLabel (NULL);
6317 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6319 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6321 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6323 emitcode ("anl", "a,#0x%02x",
6324 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6326 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6328 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6330 emitcode ("anl", "a,#0x%02x",
6331 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6333 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6335 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6337 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6339 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6340 emitcode ("orl", "a,#0x%02x",
6341 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6343 emitcode ("", "%05d$:", tlbl->key + 100);
6344 break; // SSSSAAAA:BBBCCCCC
6346 case 6: // AABBBBBB:CCDDDDDD
6348 tlbl = newiTempLabel (NULL);
6349 emitcode ("mov", "c,acc.7");
6350 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6352 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6354 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6356 emitcode ("anl", "a,#0x%02x",
6357 SRMask[shCount]); // 000000AA:BBBBBBCC
6359 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6360 emitcode ("orl", "a,#0x%02x",
6361 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6363 emitcode ("", "%05d$:", tlbl->key + 100);
6365 case 7: // ABBBBBBB:CDDDDDDD
6367 tlbl = newiTempLabel (NULL);
6368 emitcode ("mov", "c,acc.7"); // c = A
6370 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6372 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6374 emitcode ("anl", "a,#0x%02x",
6375 SRMask[shCount]); // 0000000A:BBBBBBBC
6377 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6378 emitcode ("orl", "a,#0x%02x",
6379 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6381 emitcode ("", "%05d$:", tlbl->key + 100);
6391 /*-----------------------------------------------------------------*/
6392 /* shiftL2Left2Result - shift left two bytes from left to result */
6393 /*-----------------------------------------------------------------*/
6395 shiftL2Left2Result (operand * left, int offl,
6396 operand * result, int offr, int shCount)
6398 if (sameRegs (AOP (result), AOP (left)) &&
6399 ((offl + MSB16) == offr))
6401 /* don't crash result[offr] */
6402 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6403 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6407 movLeft2Result (left, offl, result, offr, 0);
6408 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6410 /* ax << shCount (x = lsb(result)) */
6411 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6412 aopPut (AOP (result), "a", offr + MSB16);
6418 /*-----------------------------------------------------------------*/
6419 /* shiftR2Left2Result - shift right two bytes from left to result */
6420 /*-----------------------------------------------------------------*/
6422 shiftR2Left2Result (operand * left, int offl,
6423 operand * result, int offr,
6424 int shCount, int sign)
6426 if (sameRegs (AOP (result), AOP (left)) &&
6427 ((offl + MSB16) == offr))
6429 /* don't crash result[offr] */
6430 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6431 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6435 movLeft2Result (left, offl, result, offr, 0);
6436 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6438 /* a:x >> shCount (x = lsb(result)) */
6440 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6442 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6443 if (getDataSize (result) > 1)
6444 aopPut (AOP (result), "a", offr + MSB16);
6450 /*-----------------------------------------------------------------*/
6451 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6452 /*-----------------------------------------------------------------*/
6454 shiftLLeftOrResult (operand * left, int offl,
6455 operand * result, int offr, int shCount)
6457 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6458 /* shift left accumulator */
6460 /* or with result */
6461 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6462 /* back to result */
6463 aopPut (AOP (result), "a", offr);
6469 /*-----------------------------------------------------------------*/
6470 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6471 /*-----------------------------------------------------------------*/
6473 shiftRLeftOrResult (operand * left, int offl,
6474 operand * result, int offr, int shCount)
6476 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6477 /* shift right accumulator */
6479 /* or with result */
6480 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6481 /* back to result */
6482 aopPut (AOP (result), "a", offr);
6488 /*-----------------------------------------------------------------*/
6489 /* genlshOne - left shift a one byte quantity by known count */
6490 /*-----------------------------------------------------------------*/
6492 genlshOne (operand * result, operand * left, int shCount)
6494 D (emitcode (";", "genlshOne ");
6496 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6502 /*-----------------------------------------------------------------*/
6503 /* genlshTwo - left shift two bytes by known amount != 0 */
6504 /*-----------------------------------------------------------------*/
6506 genlshTwo (operand * result, operand * left, int shCount)
6510 D (emitcode (";", "genlshTwo ");
6513 size = getDataSize (result);
6515 /* if shCount >= 8 */
6523 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6525 movLeft2Result (left, LSB, result, MSB16, 0);
6527 aopPut (AOP (result), zero, LSB);
6530 /* 1 <= shCount <= 7 */
6534 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6536 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6543 /*-----------------------------------------------------------------*/
6544 /* shiftLLong - shift left one long from left to result */
6545 /* offl = LSB or MSB16 */
6546 /*-----------------------------------------------------------------*/
6548 shiftLLong (operand * left, operand * result, int offr)
6551 int size = AOP_SIZE (result);
6553 if (size >= LSB + offr)
6555 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6557 emitcode ("add", "a,acc");
6558 if (sameRegs (AOP (left), AOP (result)) &&
6559 size >= MSB16 + offr && offr != LSB)
6560 emitcode ("xch", "a,%s",
6561 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6563 aopPut (AOP (result), "a", LSB + offr);
6566 if (size >= MSB16 + offr)
6568 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6570 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6573 emitcode ("rlc", "a");
6574 if (sameRegs (AOP (left), AOP (result)) &&
6575 size >= MSB24 + offr && offr != LSB)
6576 emitcode ("xch", "a,%s",
6577 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6579 aopPut (AOP (result), "a", MSB16 + offr);
6582 if (size >= MSB24 + offr)
6584 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6586 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6589 emitcode ("rlc", "a");
6590 if (sameRegs (AOP (left), AOP (result)) &&
6591 size >= MSB32 + offr && offr != LSB)
6592 emitcode ("xch", "a,%s",
6593 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6595 aopPut (AOP (result), "a", MSB24 + offr);
6598 if (size > MSB32 + offr)
6600 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6602 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6605 emitcode ("rlc", "a");
6606 aopPut (AOP (result), "a", MSB32 + offr);
6609 aopPut (AOP (result), zero, LSB);
6615 /*-----------------------------------------------------------------*/
6616 /* genlshFour - shift four byte by a known amount != 0 */
6617 /*-----------------------------------------------------------------*/
6619 genlshFour (operand * result, operand * left, int shCount)
6623 D (emitcode (";", "genlshFour ");
6626 size = AOP_SIZE (result);
6628 /* if shifting more that 3 bytes */
6633 /* lowest order of left goes to the highest
6634 order of the destination */
6635 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6637 movLeft2Result (left, LSB, result, MSB32, 0);
6638 aopPut (AOP (result), zero, LSB);
6639 aopPut (AOP (result), zero, MSB16);
6640 aopPut (AOP (result), zero, MSB32);
6644 /* more than two bytes */
6645 else if (shCount >= 16)
6647 /* lower order two bytes goes to higher order two bytes */
6649 /* if some more remaining */
6651 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6654 movLeft2Result (left, MSB16, result, MSB32, 0);
6655 movLeft2Result (left, LSB, result, MSB24, 0);
6657 aopPut (AOP (result), zero, MSB16);
6658 aopPut (AOP (result), zero, LSB);
6662 /* if more than 1 byte */
6663 else if (shCount >= 8)
6665 /* lower order three bytes goes to higher order three bytes */
6670 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6672 movLeft2Result (left, LSB, result, MSB16, 0);
6678 movLeft2Result (left, MSB24, result, MSB32, 0);
6679 movLeft2Result (left, MSB16, result, MSB24, 0);
6680 movLeft2Result (left, LSB, result, MSB16, 0);
6681 aopPut (AOP (result), zero, LSB);
6683 else if (shCount == 1)
6684 shiftLLong (left, result, MSB16);
6687 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6688 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6689 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6690 aopPut (AOP (result), zero, LSB);
6695 /* 1 <= shCount <= 7 */
6696 else if (shCount <= 2)
6698 shiftLLong (left, result, LSB);
6700 shiftLLong (result, result, LSB);
6702 /* 3 <= shCount <= 7, optimize */
6705 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6706 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6707 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6714 /*-----------------------------------------------------------------*/
6715 /* genLeftShiftLiteral - left shifting by known count */
6716 /*-----------------------------------------------------------------*/
6718 genLeftShiftLiteral (operand * left,
6723 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6726 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6729 freeAsmop (right, NULL, ic, TRUE);
6731 aopOp (left, ic, FALSE, FALSE);
6732 aopOp (result, ic, FALSE, TRUE);
6734 size = getSize (operandType (result));
6737 emitcode ("; shift left ", "result %d, left %d", size,
6741 /* I suppose that the left size >= result size */
6746 movLeft2Result (left, size, result, size, 0);
6750 else if (shCount >= (size * 8))
6752 aopPut (AOP (result), zero, size);
6758 genlshOne (result, left, shCount);
6762 case 3: /* bug: this is for generic pointers, I bet. */
6763 genlshTwo (result, left, shCount);
6767 genlshFour (result, left, shCount);
6771 freeAsmop (left, NULL, ic, TRUE);
6772 freeAsmop (result, NULL, ic, TRUE);
6776 /*-----------------------------------------------------------------*/
6777 /* genLeftShift - generates code for left shifting */
6778 /*-----------------------------------------------------------------*/
6780 genLeftShift (iCode * ic)
6782 operand *left, *right, *result;
6785 symbol *tlbl, *tlbl1;
6787 D (emitcode (";", "genLeftShift ");
6790 right = IC_RIGHT (ic);
6791 left = IC_LEFT (ic);
6792 result = IC_RESULT (ic);
6794 aopOp (right, ic, FALSE, FALSE);
6797 /* if the shift count is known then do it
6798 as efficiently as possible */
6799 if (AOP_TYPE (right) == AOP_LIT)
6801 genLeftShiftLiteral (left, right, result, ic);
6806 /* shift count is unknown then we have to form
6807 a loop get the loop count in B : Note: we take
6808 only the lower order byte since shifting
6809 more that 32 bits make no sense anyway, ( the
6810 largest size of an object can be only 32 bits ) */
6812 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6813 emitcode ("inc", "b");
6814 freeAsmop (right, NULL, ic, TRUE);
6815 aopOp (left, ic, FALSE, FALSE);
6816 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6818 /* now move the left to the result if they are not the
6820 if (!sameRegs (AOP (left), AOP (result)) &&
6821 AOP_SIZE (result) > 1)
6824 size = AOP_SIZE (result);
6826 _startLazyDPSEvaluation ();
6829 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6830 if (*l == '@' && (IS_AOP_PREG (result)))
6833 emitcode ("mov", "a,%s", l);
6834 aopPut (AOP (result), "a", offset);
6837 aopPut (AOP (result), l, offset);
6840 _endLazyDPSEvaluation ();
6843 tlbl = newiTempLabel (NULL);
6844 size = AOP_SIZE (result);
6846 tlbl1 = newiTempLabel (NULL);
6848 /* if it is only one byte then */
6851 symbol *tlbl1 = newiTempLabel (NULL);
6853 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6855 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6856 emitcode ("", "%05d$:", tlbl->key + 100);
6857 emitcode ("add", "a,acc");
6858 emitcode ("", "%05d$:", tlbl1->key + 100);
6859 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6860 aopPut (AOP (result), "a", 0);
6864 reAdjustPreg (AOP (result));
6866 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6867 emitcode ("", "%05d$:", tlbl->key + 100);
6868 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6870 emitcode ("add", "a,acc");
6871 aopPut (AOP (result), "a", offset++);
6872 _startLazyDPSEvaluation ();
6875 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6877 emitcode ("rlc", "a");
6878 aopPut (AOP (result), "a", offset++);
6880 _endLazyDPSEvaluation ();
6881 reAdjustPreg (AOP (result));
6883 emitcode ("", "%05d$:", tlbl1->key + 100);
6884 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6886 freeAsmop (left, NULL, ic, TRUE);
6887 freeAsmop (result, NULL, ic, TRUE);
6892 /*-----------------------------------------------------------------*/
6893 /* genrshOne - right shift a one byte quantity by known count */
6894 /*-----------------------------------------------------------------*/
6896 genrshOne (operand * result, operand * left,
6897 int shCount, int sign)
6899 D (emitcode (";", "genrshOne");
6901 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6907 /*-----------------------------------------------------------------*/
6908 /* genrshTwo - right shift two bytes by known amount != 0 */
6909 /*-----------------------------------------------------------------*/
6911 genrshTwo (operand * result, operand * left,
6912 int shCount, int sign)
6914 D (emitcode (";", "genrshTwo");
6917 /* if shCount >= 8 */
6922 shiftR1Left2Result (left, MSB16, result, LSB,
6925 movLeft2Result (left, MSB16, result, LSB, sign);
6926 addSign (result, MSB16, sign);
6929 /* 1 <= shCount <= 7 */
6931 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6937 /*-----------------------------------------------------------------*/
6938 /* shiftRLong - shift right one long from left to result */
6939 /* offl = LSB or MSB16 */
6940 /*-----------------------------------------------------------------*/
6942 shiftRLong (operand * left, int offl,
6943 operand * result, int sign)
6946 emitcode ("clr", "c");
6947 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6949 emitcode ("mov", "c,acc.7");
6950 emitcode ("rrc", "a");
6951 aopPut (AOP (result), "a", MSB32 - offl);
6953 /* add sign of "a" */
6954 addSign (result, MSB32, sign);
6956 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6957 emitcode ("rrc", "a");
6958 aopPut (AOP (result), "a", MSB24 - offl);
6960 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6961 emitcode ("rrc", "a");
6962 aopPut (AOP (result), "a", MSB16 - offl);
6966 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6967 emitcode ("rrc", "a");
6968 aopPut (AOP (result), "a", LSB);
6975 /*-----------------------------------------------------------------*/
6976 /* genrshFour - shift four byte by a known amount != 0 */
6977 /*-----------------------------------------------------------------*/
6979 genrshFour (operand * result, operand * left,
6980 int shCount, int sign)
6982 D (emitcode (";", "genrshFour");
6985 /* if shifting more that 3 bytes */
6990 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6992 movLeft2Result (left, MSB32, result, LSB, sign);
6993 addSign (result, MSB16, sign);
6995 else if (shCount >= 16)
6999 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7002 movLeft2Result (left, MSB24, result, LSB, 0);
7003 movLeft2Result (left, MSB32, result, MSB16, sign);
7005 addSign (result, MSB24, sign);
7007 else if (shCount >= 8)
7011 shiftRLong (left, MSB16, result, sign);
7012 else if (shCount == 0)
7014 movLeft2Result (left, MSB16, result, LSB, 0);
7015 movLeft2Result (left, MSB24, result, MSB16, 0);
7016 movLeft2Result (left, MSB32, result, MSB24, sign);
7017 addSign (result, MSB32, sign);
7021 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7022 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7023 /* the last shift is signed */
7024 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7025 addSign (result, MSB32, sign);
7029 { /* 1 <= shCount <= 7 */
7032 shiftRLong (left, LSB, result, sign);
7034 shiftRLong (result, LSB, result, sign);
7038 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7039 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7040 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7048 /*-----------------------------------------------------------------*/
7049 /* genRightShiftLiteral - right shifting by known count */
7050 /*-----------------------------------------------------------------*/
7052 genRightShiftLiteral (operand * left,
7058 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7061 D (emitcode (";", "genRightShiftLiteral");
7064 freeAsmop (right, NULL, ic, TRUE);
7066 aopOp (left, ic, FALSE, FALSE);
7067 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7070 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7074 size = getDataSize (left);
7075 /* test the LEFT size !!! */
7077 /* I suppose that the left size >= result size */
7080 size = getDataSize (result);
7082 movLeft2Result (left, size, result, size, 0);
7085 else if (shCount >= (size * 8))
7088 /* get sign in acc.7 */
7089 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7090 addSign (result, LSB, sign);
7097 genrshOne (result, left, shCount, sign);
7101 genrshTwo (result, left, shCount, sign);
7105 genrshFour (result, left, shCount, sign);
7111 freeAsmop (left, NULL, ic, TRUE);
7112 freeAsmop (result, NULL, ic, TRUE);
7117 /*-----------------------------------------------------------------*/
7118 /* genSignedRightShift - right shift of signed number */
7119 /*-----------------------------------------------------------------*/
7121 genSignedRightShift (iCode * ic)
7123 operand *right, *left, *result;
7126 symbol *tlbl, *tlbl1;
7128 D (emitcode (";", "genSignedRightShift ");
7131 /* we do it the hard way put the shift count in b
7132 and loop thru preserving the sign */
7134 right = IC_RIGHT (ic);
7135 left = IC_LEFT (ic);
7136 result = IC_RESULT (ic);
7138 aopOp (right, ic, FALSE, FALSE);
7141 if (AOP_TYPE (right) == AOP_LIT)
7143 genRightShiftLiteral (left, right, result, ic, 1);
7147 /* shift count is unknown then we have to form
7148 a loop get the loop count in B : Note: we take
7149 only the lower order byte since shifting
7150 more that 32 bits make no sense anyway, ( the
7151 largest size of an object can be only 32 bits ) */
7153 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7154 emitcode ("inc", "b");
7155 freeAsmop (right, NULL, ic, TRUE);
7156 aopOp (left, ic, FALSE, FALSE);
7157 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7159 /* now move the left to the result if they are not the
7161 if (!sameRegs (AOP (left), AOP (result)) &&
7162 AOP_SIZE (result) > 1)
7165 size = AOP_SIZE (result);
7167 _startLazyDPSEvaluation ();
7170 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7171 if (*l == '@' && IS_AOP_PREG (result))
7174 emitcode ("mov", "a,%s", l);
7175 aopPut (AOP (result), "a", offset);
7178 aopPut (AOP (result), l, offset);
7181 _endLazyDPSEvaluation ();
7184 /* mov the highest order bit to OVR */
7185 tlbl = newiTempLabel (NULL);
7186 tlbl1 = newiTempLabel (NULL);
7188 size = AOP_SIZE (result);
7190 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7191 emitcode ("rlc", "a");
7192 emitcode ("mov", "ov,c");
7193 /* if it is only one byte then */
7196 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7198 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7199 emitcode ("", "%05d$:", tlbl->key + 100);
7200 emitcode ("mov", "c,ov");
7201 emitcode ("rrc", "a");
7202 emitcode ("", "%05d$:", tlbl1->key + 100);
7203 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7204 aopPut (AOP (result), "a", 0);
7208 reAdjustPreg (AOP (result));
7209 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7210 emitcode ("", "%05d$:", tlbl->key + 100);
7211 emitcode ("mov", "c,ov");
7212 _startLazyDPSEvaluation ();
7215 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7217 emitcode ("rrc", "a");
7218 aopPut (AOP (result), "a", offset--);
7220 _endLazyDPSEvaluation ();
7221 reAdjustPreg (AOP (result));
7222 emitcode ("", "%05d$:", tlbl1->key + 100);
7223 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7226 freeAsmop (left, NULL, ic, TRUE);
7227 freeAsmop (result, NULL, ic, TRUE);
7230 /*-----------------------------------------------------------------*/
7231 /* genRightShift - generate code for right shifting */
7232 /*-----------------------------------------------------------------*/
7234 genRightShift (iCode * ic)
7236 operand *right, *left, *result;
7240 symbol *tlbl, *tlbl1;
7242 D (emitcode (";", "genRightShift ");
7245 /* if signed then we do it the hard way preserve the
7246 sign bit moving it inwards */
7247 retype = getSpec (operandType (IC_RESULT (ic)));
7249 if (!SPEC_USIGN (retype))
7251 genSignedRightShift (ic);
7255 /* signed & unsigned types are treated the same : i.e. the
7256 signed is NOT propagated inwards : quoting from the
7257 ANSI - standard : "for E1 >> E2, is equivalent to division
7258 by 2**E2 if unsigned or if it has a non-negative value,
7259 otherwise the result is implementation defined ", MY definition
7260 is that the sign does not get propagated */
7262 right = IC_RIGHT (ic);
7263 left = IC_LEFT (ic);
7264 result = IC_RESULT (ic);
7266 aopOp (right, ic, FALSE, FALSE);
7269 /* if the shift count is known then do it
7270 as efficiently as possible */
7271 if (AOP_TYPE (right) == AOP_LIT)
7273 genRightShiftLiteral (left, right, result, ic, 0);
7278 /* shift count is unknown then we have to form
7279 a loop get the loop count in B : Note: we take
7280 only the lower order byte since shifting
7281 more that 32 bits make no sense anyway, ( the
7282 largest size of an object can be only 32 bits ) */
7284 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7285 emitcode ("inc", "b");
7286 freeAsmop (right, NULL, ic, TRUE);
7287 aopOp (left, ic, FALSE, FALSE);
7288 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7290 /* now move the left to the result if they are not the
7292 if (!sameRegs (AOP (left), AOP (result)) &&
7293 AOP_SIZE (result) > 1)
7296 size = AOP_SIZE (result);
7298 _startLazyDPSEvaluation ();
7301 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7302 if (*l == '@' && IS_AOP_PREG (result))
7305 emitcode ("mov", "a,%s", l);
7306 aopPut (AOP (result), "a", offset);
7309 aopPut (AOP (result), l, offset);
7312 _endLazyDPSEvaluation ();
7315 tlbl = newiTempLabel (NULL);
7316 tlbl1 = newiTempLabel (NULL);
7317 size = AOP_SIZE (result);
7320 /* if it is only one byte then */
7323 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7325 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7326 emitcode ("", "%05d$:", tlbl->key + 100);
7328 emitcode ("rrc", "a");
7329 emitcode ("", "%05d$:", tlbl1->key + 100);
7330 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7331 aopPut (AOP (result), "a", 0);
7335 reAdjustPreg (AOP (result));
7336 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7337 emitcode ("", "%05d$:", tlbl->key + 100);
7339 _startLazyDPSEvaluation ();
7342 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7344 emitcode ("rrc", "a");
7345 aopPut (AOP (result), "a", offset--);
7347 _endLazyDPSEvaluation ();
7348 reAdjustPreg (AOP (result));
7350 emitcode ("", "%05d$:", tlbl1->key + 100);
7351 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7354 freeAsmop (left, NULL, ic, TRUE);
7355 freeAsmop (result, NULL, ic, TRUE);
7358 /*-----------------------------------------------------------------*/
7359 /* genUnpackBits - generates code for unpacking bits */
7360 /*-----------------------------------------------------------------*/
7362 genUnpackBits (operand * result, char *rname, int ptype)
7369 D (emitcode (";", "genUnpackBits ");
7372 etype = getSpec (operandType (result));
7374 /* read the first byte */
7380 emitcode ("mov", "a,@%s", rname);
7384 emitcode ("movx", "a,@%s", rname);
7388 emitcode ("movx", "a,@dptr");
7392 emitcode ("clr", "a");
7393 emitcode ("movc", "a", "@a+dptr");
7397 emitcode ("lcall", "__gptrget");
7401 /* if we have bitdisplacement then it fits */
7402 /* into this byte completely or if length is */
7403 /* less than a byte */
7404 if ((shCnt = SPEC_BSTR (etype)) ||
7405 (SPEC_BLEN (etype) <= 8))
7408 /* shift right acc */
7411 emitcode ("anl", "a,#0x%02x",
7412 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7413 aopPut (AOP (result), "a", offset);
7417 /* bit field did not fit in a byte */
7418 rlen = SPEC_BLEN (etype) - 8;
7419 aopPut (AOP (result), "a", offset++);
7428 emitcode ("inc", "%s", rname);
7429 emitcode ("mov", "a,@%s", rname);
7433 emitcode ("inc", "%s", rname);
7434 emitcode ("movx", "a,@%s", rname);
7438 emitcode ("inc", "dptr");
7439 emitcode ("movx", "a,@dptr");
7443 emitcode ("clr", "a");
7444 emitcode ("inc", "dptr");
7445 emitcode ("movc", "a", "@a+dptr");
7449 emitcode ("inc", "dptr");
7450 emitcode ("lcall", "__gptrget");
7455 /* if we are done */
7459 aopPut (AOP (result), "a", offset++);
7465 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7466 aopPut (AOP (result), "a", offset);
7473 /*-----------------------------------------------------------------*/
7474 /* genDataPointerGet - generates code when ptr offset is known */
7475 /*-----------------------------------------------------------------*/
7477 genDataPointerGet (operand * left,
7483 int size, offset = 0;
7484 aopOp (result, ic, TRUE, FALSE);
7486 /* get the string representation of the name */
7487 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7488 size = AOP_SIZE (result);
7489 _startLazyDPSEvaluation ();
7493 sprintf (buffer, "(%s + %d)", l + 1, offset);
7495 sprintf (buffer, "%s", l + 1);
7496 aopPut (AOP (result), buffer, offset++);
7498 _endLazyDPSEvaluation ();
7500 freeAsmop (left, NULL, ic, TRUE);
7501 freeAsmop (result, NULL, ic, TRUE);
7504 /*-----------------------------------------------------------------*/
7505 /* genNearPointerGet - emitcode for near pointer fetch */
7506 /*-----------------------------------------------------------------*/
7508 genNearPointerGet (operand * left,
7515 sym_link *rtype, *retype, *letype;
7516 sym_link *ltype = operandType (left);
7519 rtype = operandType (result);
7520 retype = getSpec (rtype);
7521 letype = getSpec (ltype);
7523 aopOp (left, ic, FALSE, FALSE);
7525 /* if left is rematerialisable and
7526 result is not bit variable type and
7527 the left is pointer to data space i.e
7528 lower 128 bytes of space */
7529 if (AOP_TYPE (left) == AOP_IMMD &&
7530 !IS_BITVAR (retype) &&
7531 !IS_BITVAR (letype) &&
7532 DCL_TYPE (ltype) == POINTER)
7534 genDataPointerGet (left, result, ic);
7538 /* if the value is already in a pointer register
7539 then don't need anything more */
7540 if (!AOP_INPREG (AOP (left)))
7542 /* otherwise get a free pointer register */
7544 preg = getFreePtr (ic, &aop, FALSE);
7545 emitcode ("mov", "%s,%s",
7547 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7551 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7553 freeAsmop (left, NULL, ic, TRUE);
7554 aopOp (result, ic, FALSE, FALSE);
7556 /* if bitfield then unpack the bits */
7557 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7558 genUnpackBits (result, rname, POINTER);
7561 /* we have can just get the values */
7562 int size = AOP_SIZE (result);
7567 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7570 emitcode ("mov", "a,@%s", rname);
7571 aopPut (AOP (result), "a", offset);
7575 sprintf (buffer, "@%s", rname);
7576 aopPut (AOP (result), buffer, offset);
7580 emitcode ("inc", "%s", rname);
7584 /* now some housekeeping stuff */
7587 /* we had to allocate for this iCode */
7588 freeAsmop (NULL, aop, ic, TRUE);
7592 /* we did not allocate which means left
7593 already in a pointer register, then
7594 if size > 0 && this could be used again
7595 we have to point it back to where it
7597 if (AOP_SIZE (result) > 1 &&
7598 !OP_SYMBOL (left)->remat &&
7599 (OP_SYMBOL (left)->liveTo > ic->seq ||
7602 int size = AOP_SIZE (result) - 1;
7604 emitcode ("dec", "%s", rname);
7609 freeAsmop (result, NULL, ic, TRUE);
7613 /*-----------------------------------------------------------------*/
7614 /* genPagedPointerGet - emitcode for paged pointer fetch */
7615 /*-----------------------------------------------------------------*/
7617 genPagedPointerGet (operand * left,
7624 sym_link *rtype, *retype, *letype;
7626 rtype = operandType (result);
7627 retype = getSpec (rtype);
7628 letype = getSpec (operandType (left));
7629 aopOp (left, ic, FALSE, FALSE);
7631 /* if the value is already in a pointer register
7632 then don't need anything more */
7633 if (!AOP_INPREG (AOP (left)))
7635 /* otherwise get a free pointer register */
7637 preg = getFreePtr (ic, &aop, FALSE);
7638 emitcode ("mov", "%s,%s",
7640 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7644 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7646 freeAsmop (left, NULL, ic, TRUE);
7647 aopOp (result, ic, FALSE, FALSE);
7649 /* if bitfield then unpack the bits */
7650 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7651 genUnpackBits (result, rname, PPOINTER);
7654 /* we have can just get the values */
7655 int size = AOP_SIZE (result);
7661 emitcode ("movx", "a,@%s", rname);
7662 aopPut (AOP (result), "a", offset);
7667 emitcode ("inc", "%s", rname);
7671 /* now some housekeeping stuff */
7674 /* we had to allocate for this iCode */
7675 freeAsmop (NULL, aop, ic, TRUE);
7679 /* we did not allocate which means left
7680 already in a pointer register, then
7681 if size > 0 && this could be used again
7682 we have to point it back to where it
7684 if (AOP_SIZE (result) > 1 &&
7685 !OP_SYMBOL (left)->remat &&
7686 (OP_SYMBOL (left)->liveTo > ic->seq ||
7689 int size = AOP_SIZE (result) - 1;
7691 emitcode ("dec", "%s", rname);
7696 freeAsmop (result, NULL, ic, TRUE);
7701 /*-----------------------------------------------------------------*/
7702 /* genFarPointerGet - gget value from far space */
7703 /*-----------------------------------------------------------------*/
7705 genFarPointerGet (operand * left,
7706 operand * result, iCode * ic)
7709 sym_link *retype = getSpec (operandType (result));
7710 sym_link *letype = getSpec (operandType (left));
7711 D (emitcode (";", "genFarPointerGet");
7714 aopOp (left, ic, FALSE, FALSE);
7716 /* if the operand is already in dptr
7717 then we do nothing else we move the value to dptr */
7718 if (AOP_TYPE (left) != AOP_STR)
7720 /* if this is remateriazable */
7721 if (AOP_TYPE (left) == AOP_IMMD)
7723 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7727 /* we need to get it byte by byte */
7728 _startLazyDPSEvaluation ();
7729 if (AOP_TYPE (left) != AOP_DPTR)
7731 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7732 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7733 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7737 /* We need to generate a load to DPTR indirect through DPTR. */
7738 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7740 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7741 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7742 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7743 emitcode ("pop", "dph");
7744 emitcode ("pop", "dpl");
7746 _endLazyDPSEvaluation ();
7749 /* so dptr know contains the address */
7750 freeAsmop (left, NULL, ic, TRUE);
7751 aopOp (result, ic, FALSE, TRUE);
7753 /* if bit then unpack */
7754 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7755 genUnpackBits (result, "dptr", FPOINTER);
7758 size = AOP_SIZE (result);
7761 _startLazyDPSEvaluation ();
7768 emitcode ("movx", "a,@dptr");
7770 emitcode ("inc", "dptr");
7772 aopPut (AOP (result), "a", offset++);
7774 _endLazyDPSEvaluation ();
7777 freeAsmop (result, NULL, ic, TRUE);
7780 /*-----------------------------------------------------------------*/
7781 /* emitcodePointerGet - gget value from code space */
7782 /*-----------------------------------------------------------------*/
7784 emitcodePointerGet (operand * left,
7785 operand * result, iCode * ic)
7788 sym_link *retype = getSpec (operandType (result));
7790 aopOp (left, ic, FALSE, FALSE);
7792 /* if the operand is already in dptr
7793 then we do nothing else we move the value to dptr */
7794 if (AOP_TYPE (left) != AOP_STR)
7796 /* if this is remateriazable */
7797 if (AOP_TYPE (left) == AOP_IMMD)
7799 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7802 { /* we need to get it byte by byte */
7803 _startLazyDPSEvaluation ();
7804 if (AOP_TYPE (left) != AOP_DPTR)
7806 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7807 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7808 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7812 /* We need to generate a load to DPTR indirect through DPTR. */
7813 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7815 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7816 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7817 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7818 emitcode ("pop", "dph");
7819 emitcode ("pop", "dpl");
7821 _endLazyDPSEvaluation ();
7824 /* so dptr know contains the address */
7825 freeAsmop (left, NULL, ic, TRUE);
7826 aopOp (result, ic, FALSE, TRUE);
7828 /* if bit then unpack */
7829 if (IS_BITVAR (retype))
7830 genUnpackBits (result, "dptr", CPOINTER);
7833 size = AOP_SIZE (result);
7836 _startLazyDPSEvaluation ();
7842 emitcode ("clr", "a");
7843 emitcode ("movc", "a,@a+dptr");
7845 emitcode ("inc", "dptr");
7846 aopPut (AOP (result), "a", offset++);
7848 _endLazyDPSEvaluation ();
7851 freeAsmop (result, NULL, ic, TRUE);
7854 /*-----------------------------------------------------------------*/
7855 /* genGenPointerGet - gget value from generic pointer space */
7856 /*-----------------------------------------------------------------*/
7858 genGenPointerGet (operand * left,
7859 operand * result, iCode * ic)
7862 sym_link *retype = getSpec (operandType (result));
7863 sym_link *letype = getSpec (operandType (left));
7865 D (emitcode (";", "genGenPointerGet "); );
7867 aopOp (left, ic, FALSE, TRUE);
7869 /* if the operand is already in dptr
7870 then we do nothing else we move the value to dptr */
7871 if (AOP_TYPE (left) != AOP_STR)
7873 /* if this is remateriazable */
7874 if (AOP_TYPE (left) == AOP_IMMD)
7876 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7877 emitcode ("mov", "b,#%d", pointerCode (retype));
7880 { /* we need to get it byte by byte */
7881 _startLazyDPSEvaluation ();
7882 if (AOP(left)->type==AOP_DPTR2) {
7884 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7887 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7888 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7891 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7892 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7895 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7896 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7898 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7899 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7900 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7901 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7903 _endLazyDPSEvaluation ();
7906 /* so dptr know contains the address */
7907 freeAsmop (left, NULL, ic, TRUE);
7908 aopOp (result, ic, FALSE, TRUE);
7910 /* if bit then unpack */
7911 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7912 genUnpackBits (result, "dptr", GPOINTER);
7915 size = AOP_SIZE (result);
7920 emitcode ("lcall", "__gptrget");
7921 aopPut (AOP (result), "a", offset++);
7923 emitcode ("inc", "dptr");
7927 freeAsmop (result, NULL, ic, TRUE);
7930 /*-----------------------------------------------------------------*/
7931 /* genPointerGet - generate code for pointer get */
7932 /*-----------------------------------------------------------------*/
7934 genPointerGet (iCode * ic)
7936 operand *left, *result;
7937 sym_link *type, *etype;
7940 D (emitcode (";", "genPointerGet ");
7943 left = IC_LEFT (ic);
7944 result = IC_RESULT (ic);
7946 /* depending on the type of pointer we need to
7947 move it to the correct pointer register */
7948 type = operandType (left);
7949 etype = getSpec (type);
7950 /* if left is of type of pointer then it is simple */
7951 if (IS_PTR (type) && !IS_FUNC (type->next))
7952 p_type = DCL_TYPE (type);
7955 /* we have to go by the storage class */
7956 p_type = PTR_TYPE (SPEC_OCLS (etype));
7959 /* now that we have the pointer type we assign
7960 the pointer values */
7966 genNearPointerGet (left, result, ic);
7970 genPagedPointerGet (left, result, ic);
7974 genFarPointerGet (left, result, ic);
7978 emitcodePointerGet (left, result, ic);
7982 genGenPointerGet (left, result, ic);
7988 /*-----------------------------------------------------------------*/
7989 /* genPackBits - generates code for packed bit storage */
7990 /*-----------------------------------------------------------------*/
7992 genPackBits (sym_link * etype,
7994 char *rname, int p_type)
8002 blen = SPEC_BLEN (etype);
8003 bstr = SPEC_BSTR (etype);
8005 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8008 /* if the bit lenth is less than or */
8009 /* it exactly fits a byte then */
8010 if (SPEC_BLEN (etype) <= 8)
8012 shCount = SPEC_BSTR (etype);
8014 /* shift left acc */
8017 if (SPEC_BLEN (etype) < 8)
8018 { /* if smaller than a byte */
8024 emitcode ("mov", "b,a");
8025 emitcode ("mov", "a,@%s", rname);
8029 emitcode ("mov", "b,a");
8030 emitcode ("movx", "a,@dptr");
8034 emitcode ("push", "b");
8035 emitcode ("push", "acc");
8036 emitcode ("lcall", "__gptrget");
8037 emitcode ("pop", "b");
8041 emitcode ("anl", "a,#0x%02x", (unsigned char)
8042 ((unsigned char) (0xFF << (blen + bstr)) |
8043 (unsigned char) (0xFF >> (8 - bstr))));
8044 emitcode ("orl", "a,b");
8045 if (p_type == GPOINTER)
8046 emitcode ("pop", "b");
8053 emitcode ("mov", "@%s,a", rname);
8057 emitcode ("movx", "@dptr,a");
8061 emitcode ("lcall", "__gptrput");
8066 if (SPEC_BLEN (etype) <= 8)
8069 emitcode ("inc", "%s", rname);
8070 rLen = SPEC_BLEN (etype);
8072 /* now generate for lengths greater than one byte */
8076 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8088 emitcode ("mov", "@%s,a", rname);
8091 emitcode ("mov", "@%s,%s", rname, l);
8096 emitcode ("movx", "@dptr,a");
8101 emitcode ("lcall", "__gptrput");
8104 emitcode ("inc", "%s", rname);
8109 /* last last was not complete */
8112 /* save the byte & read byte */
8116 emitcode ("mov", "b,a");
8117 emitcode ("mov", "a,@%s", rname);
8121 emitcode ("mov", "b,a");
8122 emitcode ("movx", "a,@dptr");
8126 emitcode ("push", "b");
8127 emitcode ("push", "acc");
8128 emitcode ("lcall", "__gptrget");
8129 emitcode ("pop", "b");
8133 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8134 emitcode ("orl", "a,b");
8137 if (p_type == GPOINTER)
8138 emitcode ("pop", "b");
8144 emitcode ("mov", "@%s,a", rname);
8148 emitcode ("movx", "@dptr,a");
8152 emitcode ("lcall", "__gptrput");
8156 /*-----------------------------------------------------------------*/
8157 /* genDataPointerSet - remat pointer to data space */
8158 /*-----------------------------------------------------------------*/
8160 genDataPointerSet (operand * right,
8164 int size, offset = 0;
8165 char *l, buffer[256];
8167 aopOp (right, ic, FALSE, FALSE);
8169 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8170 size = AOP_SIZE (right);
8174 sprintf (buffer, "(%s + %d)", l + 1, offset);
8176 sprintf (buffer, "%s", l + 1);
8177 emitcode ("mov", "%s,%s", buffer,
8178 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8181 freeAsmop (right, NULL, ic, TRUE);
8182 freeAsmop (result, NULL, ic, TRUE);
8185 /*-----------------------------------------------------------------*/
8186 /* genNearPointerSet - emitcode for near pointer put */
8187 /*-----------------------------------------------------------------*/
8189 genNearPointerSet (operand * right,
8196 sym_link *retype, *letype;
8197 sym_link *ptype = operandType (result);
8199 retype = getSpec (operandType (right));
8200 letype = getSpec (ptype);
8202 aopOp (result, ic, FALSE, FALSE);
8204 /* if the result is rematerializable &
8205 in data space & not a bit variable */
8206 if (AOP_TYPE (result) == AOP_IMMD &&
8207 DCL_TYPE (ptype) == POINTER &&
8208 !IS_BITVAR (retype) &&
8209 !IS_BITVAR (letype))
8211 genDataPointerSet (right, result, ic);
8215 /* if the value is already in a pointer register
8216 then don't need anything more */
8217 if (!AOP_INPREG (AOP (result)))
8219 /* otherwise get a free pointer register */
8221 preg = getFreePtr (ic, &aop, FALSE);
8222 emitcode ("mov", "%s,%s",
8224 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8228 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8230 freeAsmop (result, NULL, ic, TRUE);
8231 aopOp (right, ic, FALSE, FALSE);
8233 /* if bitfield then unpack the bits */
8234 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8235 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8238 /* we have can just get the values */
8239 int size = AOP_SIZE (right);
8244 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8248 emitcode ("mov", "@%s,a", rname);
8251 emitcode ("mov", "@%s,%s", rname, l);
8253 emitcode ("inc", "%s", rname);
8258 /* now some housekeeping stuff */
8261 /* we had to allocate for this iCode */
8262 freeAsmop (NULL, aop, ic, TRUE);
8266 /* we did not allocate which means left
8267 already in a pointer register, then
8268 if size > 0 && this could be used again
8269 we have to point it back to where it
8271 if (AOP_SIZE (right) > 1 &&
8272 !OP_SYMBOL (result)->remat &&
8273 (OP_SYMBOL (result)->liveTo > ic->seq ||
8276 int size = AOP_SIZE (right) - 1;
8278 emitcode ("dec", "%s", rname);
8283 freeAsmop (right, NULL, ic, TRUE);
8288 /*-----------------------------------------------------------------*/
8289 /* genPagedPointerSet - emitcode for Paged pointer put */
8290 /*-----------------------------------------------------------------*/
8292 genPagedPointerSet (operand * right,
8299 sym_link *retype, *letype;
8301 retype = getSpec (operandType (right));
8302 letype = getSpec (operandType (result));
8304 aopOp (result, ic, FALSE, FALSE);
8306 /* if the value is already in a pointer register
8307 then don't need anything more */
8308 if (!AOP_INPREG (AOP (result)))
8310 /* otherwise get a free pointer register */
8312 preg = getFreePtr (ic, &aop, FALSE);
8313 emitcode ("mov", "%s,%s",
8315 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8319 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8321 freeAsmop (result, NULL, ic, TRUE);
8322 aopOp (right, ic, FALSE, FALSE);
8324 /* if bitfield then unpack the bits */
8325 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8326 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8329 /* we have can just get the values */
8330 int size = AOP_SIZE (right);
8335 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8338 emitcode ("movx", "@%s,a", rname);
8341 emitcode ("inc", "%s", rname);
8347 /* now some housekeeping stuff */
8350 /* we had to allocate for this iCode */
8351 freeAsmop (NULL, aop, ic, TRUE);
8355 /* we did not allocate which means left
8356 already in a pointer register, then
8357 if size > 0 && this could be used again
8358 we have to point it back to where it
8360 if (AOP_SIZE (right) > 1 &&
8361 !OP_SYMBOL (result)->remat &&
8362 (OP_SYMBOL (result)->liveTo > ic->seq ||
8365 int size = AOP_SIZE (right) - 1;
8367 emitcode ("dec", "%s", rname);
8372 freeAsmop (right, NULL, ic, TRUE);
8377 /*-----------------------------------------------------------------*/
8378 /* genFarPointerSet - set value from far space */
8379 /*-----------------------------------------------------------------*/
8381 genFarPointerSet (operand * right,
8382 operand * result, iCode * ic)
8385 sym_link *retype = getSpec (operandType (right));
8386 sym_link *letype = getSpec (operandType (result));
8388 aopOp (result, ic, FALSE, FALSE);
8390 /* if the operand is already in dptr
8391 then we do nothing else we move the value to dptr */
8392 if (AOP_TYPE (result) != AOP_STR)
8394 /* if this is remateriazable */
8395 if (AOP_TYPE (result) == AOP_IMMD)
8396 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8399 /* we need to get it byte by byte */
8400 _startLazyDPSEvaluation ();
8401 if (AOP_TYPE (result) != AOP_DPTR)
8403 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8404 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8405 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8409 /* We need to generate a load to DPTR indirect through DPTR. */
8410 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8412 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8413 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8414 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8415 emitcode ("pop", "dph");
8416 emitcode ("pop", "dpl");
8418 _endLazyDPSEvaluation ();
8421 /* so dptr know contains the address */
8422 freeAsmop (result, NULL, ic, TRUE);
8423 aopOp (right, ic, FALSE, TRUE);
8425 /* if bit then unpack */
8426 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8427 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8430 size = AOP_SIZE (right);
8433 _startLazyDPSEvaluation ();
8436 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8442 emitcode ("movx", "@dptr,a");
8444 emitcode ("inc", "dptr");
8446 _endLazyDPSEvaluation ();
8449 freeAsmop (right, NULL, ic, TRUE);
8452 /*-----------------------------------------------------------------*/
8453 /* genGenPointerSet - set value from generic pointer space */
8454 /*-----------------------------------------------------------------*/
8456 genGenPointerSet (operand * right,
8457 operand * result, iCode * ic)
8460 sym_link *retype = getSpec (operandType (right));
8461 sym_link *letype = getSpec (operandType (result));
8463 aopOp (result, ic, FALSE, TRUE);
8465 /* if the operand is already in dptr
8466 then we do nothing else we move the value to dptr */
8467 if (AOP_TYPE (result) != AOP_STR)
8469 _startLazyDPSEvaluation ();
8470 /* if this is remateriazable */
8471 if (AOP_TYPE (result) == AOP_IMMD)
8473 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8474 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8477 { /* we need to get it byte by byte */
8478 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8479 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8480 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8481 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8483 _endLazyDPSEvaluation ();
8485 /* so dptr know contains the address */
8486 freeAsmop (result, NULL, ic, TRUE);
8487 aopOp (right, ic, FALSE, TRUE);
8489 /* if bit then unpack */
8490 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8491 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8494 size = AOP_SIZE (right);
8497 _startLazyDPSEvaluation ();
8500 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8506 emitcode ("lcall", "__gptrput");
8508 emitcode ("inc", "dptr");
8510 _endLazyDPSEvaluation ();
8513 freeAsmop (right, NULL, ic, TRUE);
8516 /*-----------------------------------------------------------------*/
8517 /* genPointerSet - stores the value into a pointer location */
8518 /*-----------------------------------------------------------------*/
8520 genPointerSet (iCode * ic)
8522 operand *right, *result;
8523 sym_link *type, *etype;
8526 D (emitcode (";", "genPointerSet ");
8529 right = IC_RIGHT (ic);
8530 result = IC_RESULT (ic);
8532 /* depending on the type of pointer we need to
8533 move it to the correct pointer register */
8534 type = operandType (result);
8535 etype = getSpec (type);
8536 /* if left is of type of pointer then it is simple */
8537 if (IS_PTR (type) && !IS_FUNC (type->next))
8539 p_type = DCL_TYPE (type);
8543 /* we have to go by the storage class */
8544 p_type = PTR_TYPE (SPEC_OCLS (etype));
8547 /* now that we have the pointer type we assign
8548 the pointer values */
8554 genNearPointerSet (right, result, ic);
8558 genPagedPointerSet (right, result, ic);
8562 genFarPointerSet (right, result, ic);
8566 genGenPointerSet (right, result, ic);
8572 /*-----------------------------------------------------------------*/
8573 /* genIfx - generate code for Ifx statement */
8574 /*-----------------------------------------------------------------*/
8576 genIfx (iCode * ic, iCode * popIc)
8578 operand *cond = IC_COND (ic);
8581 D (emitcode (";", "genIfx ");
8584 aopOp (cond, ic, FALSE, FALSE);
8586 /* get the value into acc */
8587 if (AOP_TYPE (cond) != AOP_CRY)
8591 /* the result is now in the accumulator */
8592 freeAsmop (cond, NULL, ic, TRUE);
8594 /* if there was something to be popped then do it */
8598 /* if the condition is a bit variable */
8599 if (isbit && IS_ITEMP (cond) &&
8601 genIfxJump (ic, SPIL_LOC (cond)->rname);
8602 else if (isbit && !IS_ITEMP (cond))
8603 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8605 genIfxJump (ic, "a");
8610 /*-----------------------------------------------------------------*/
8611 /* genAddrOf - generates code for address of */
8612 /*-----------------------------------------------------------------*/
8614 genAddrOf (iCode * ic)
8616 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8619 D (emitcode (";", "genAddrOf ");
8622 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8624 /* if the operand is on the stack then we
8625 need to get the stack offset of this
8629 /* if it has an offset then we need to compute
8633 emitcode ("mov", "a,_bp");
8634 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8635 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8639 /* we can just move _bp */
8640 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8642 /* fill the result with zero */
8643 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8646 if (options.stack10bit && size < (FPTRSIZE - 1))
8649 "*** warning: pointer to stack var truncated.\n");
8656 if (options.stack10bit && offset == 2)
8658 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8662 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8669 /* object not on stack then we need the name */
8670 size = AOP_SIZE (IC_RESULT (ic));
8675 char s[SDCC_NAME_MAX];
8677 sprintf (s, "#(%s >> %d)",
8681 sprintf (s, "#%s", sym->rname);
8682 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8686 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8690 /*-----------------------------------------------------------------*/
8691 /* genFarFarAssign - assignment when both are in far space */
8692 /*-----------------------------------------------------------------*/
8694 genFarFarAssign (operand * result, operand * right, iCode * ic)
8696 int size = AOP_SIZE (right);
8702 /* This is a net loss for size == 1, but a big gain
8705 D (emitcode (";", "genFarFarAssign (improved)");
8708 aopOp (result, ic, TRUE, TRUE);
8710 _startLazyDPSEvaluation ();
8713 aopPut (AOP (result),
8714 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8717 _endLazyDPSEvaluation ();
8718 freeAsmop (result, NULL, ic, FALSE);
8719 freeAsmop (right, NULL, ic, FALSE);
8723 D (emitcode (";", "genFarFarAssign ");
8726 /* first push the right side on to the stack */
8727 _startLazyDPSEvaluation ();
8730 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8732 emitcode ("push", "acc");
8735 freeAsmop (right, NULL, ic, FALSE);
8736 /* now assign DPTR to result */
8737 aopOp (result, ic, FALSE, FALSE);
8738 size = AOP_SIZE (result);
8741 emitcode ("pop", "acc");
8742 aopPut (AOP (result), "a", --offset);
8744 freeAsmop (result, NULL, ic, FALSE);
8745 _endLazyDPSEvaluation ();
8749 /*-----------------------------------------------------------------*/
8750 /* genAssign - generate code for assignment */
8751 /*-----------------------------------------------------------------*/
8753 genAssign (iCode * ic)
8755 operand *result, *right;
8757 unsigned long lit = 0L;
8759 D (emitcode (";", "genAssign ");
8762 result = IC_RESULT (ic);
8763 right = IC_RIGHT (ic);
8765 /* if they are the same */
8766 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8769 aopOp (right, ic, FALSE, FALSE);
8771 emitcode (";", "genAssign: resultIsFar = %s",
8772 isOperandInFarSpace (result) ?
8775 /* special case both in far space */
8776 if ((AOP_TYPE (right) == AOP_DPTR ||
8777 AOP_TYPE (right) == AOP_DPTR2) &&
8778 /* IS_TRUE_SYMOP(result) && */
8779 isOperandInFarSpace (result))
8781 genFarFarAssign (result, right, ic);
8785 aopOp (result, ic, TRUE, FALSE);
8787 /* if they are the same registers */
8788 if (sameRegs (AOP (right), AOP (result)))
8791 /* if the result is a bit */
8792 if (AOP_TYPE (result) == AOP_CRY)
8795 /* if the right size is a literal then
8796 we know what the value is */
8797 if (AOP_TYPE (right) == AOP_LIT)
8799 if (((int) operandLitValue (right)))
8800 aopPut (AOP (result), one, 0);
8802 aopPut (AOP (result), zero, 0);
8806 /* the right is also a bit variable */
8807 if (AOP_TYPE (right) == AOP_CRY)
8809 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8810 aopPut (AOP (result), "c", 0);
8816 aopPut (AOP (result), "a", 0);
8820 /* bit variables done */
8822 size = AOP_SIZE (result);
8824 if (AOP_TYPE (right) == AOP_LIT)
8825 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8828 (AOP_TYPE (result) != AOP_REG) &&
8829 (AOP_TYPE (right) == AOP_LIT) &&
8830 !IS_FLOAT (operandType (right)))
8832 D (emitcode (";", "Kevin's better literal load code");
8834 _startLazyDPSEvaluation ();
8835 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8837 aopPut (AOP (result),
8838 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8843 /* And now fill the rest with zeros. */
8846 emitcode ("clr", "a");
8850 aopPut (AOP (result), "a", offset++);
8852 _endLazyDPSEvaluation ();
8856 _startLazyDPSEvaluation ();
8859 aopPut (AOP (result),
8860 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8864 _endLazyDPSEvaluation ();
8868 freeAsmop (right, NULL, ic, FALSE);
8869 freeAsmop (result, NULL, ic, TRUE);
8872 /*-----------------------------------------------------------------*/
8873 /* genJumpTab - generates code for jump table */
8874 /*-----------------------------------------------------------------*/
8876 genJumpTab (iCode * ic)
8881 D (emitcode (";", "genJumpTab ");
8884 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8885 /* get the condition into accumulator */
8886 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8888 /* multiply by four! */
8889 emitcode ("add", "a,acc");
8890 emitcode ("add", "a,acc");
8891 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8893 jtab = newiTempLabel (NULL);
8894 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8895 emitcode ("jmp", "@a+dptr");
8896 emitcode ("", "%05d$:", jtab->key + 100);
8897 /* now generate the jump labels */
8898 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8899 jtab = setNextItem (IC_JTLABELS (ic)))
8900 emitcode ("ljmp", "%05d$", jtab->key + 100);
8904 /*-----------------------------------------------------------------*/
8905 /* genCast - gen code for casting */
8906 /*-----------------------------------------------------------------*/
8908 genCast (iCode * ic)
8910 operand *result = IC_RESULT (ic);
8911 sym_link *ctype = operandType (IC_LEFT (ic));
8912 sym_link *rtype = operandType (IC_RIGHT (ic));
8913 operand *right = IC_RIGHT (ic);
8916 D (emitcode (";", "genCast ");
8919 /* if they are equivalent then do nothing */
8920 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8923 aopOp (right, ic, FALSE, FALSE);
8924 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8926 /* if the result is a bit */
8927 if (AOP_TYPE (result) == AOP_CRY)
8929 /* if the right size is a literal then
8930 we know what the value is */
8931 if (AOP_TYPE (right) == AOP_LIT)
8933 if (((int) operandLitValue (right)))
8934 aopPut (AOP (result), one, 0);
8936 aopPut (AOP (result), zero, 0);
8941 /* the right is also a bit variable */
8942 if (AOP_TYPE (right) == AOP_CRY)
8944 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8945 aopPut (AOP (result), "c", 0);
8951 aopPut (AOP (result), "a", 0);
8955 /* if they are the same size : or less */
8956 if (AOP_SIZE (result) <= AOP_SIZE (right))
8959 /* if they are in the same place */
8960 if (sameRegs (AOP (right), AOP (result)))
8963 /* if they in different places then copy */
8964 size = AOP_SIZE (result);
8966 _startLazyDPSEvaluation ();
8969 aopPut (AOP (result),
8970 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8974 _endLazyDPSEvaluation ();
8979 /* if the result is of type pointer */
8984 sym_link *type = operandType (right);
8986 /* pointer to generic pointer */
8987 if (IS_GENPTR (ctype))
8993 p_type = DCL_TYPE (type);
8997 #if OLD_CAST_BEHAVIOR
8998 /* KV: we are converting a non-pointer type to
8999 * a generic pointer. This (ifdef'd out) code
9000 * says that the resulting generic pointer
9001 * should have the same class as the storage
9002 * location of the non-pointer variable.
9004 * For example, converting an int (which happens
9005 * to be stored in DATA space) to a pointer results
9006 * in a DATA generic pointer; if the original int
9007 * in XDATA space, so will be the resulting pointer.
9009 * I don't like that behavior, and thus this change:
9010 * all such conversions will be forced to XDATA and
9011 * throw a warning. If you want some non-XDATA
9012 * type, or you want to suppress the warning, you
9013 * must go through an intermediate cast, like so:
9015 * char _generic *gp = (char _xdata *)(intVar);
9017 sym_link *etype = getSpec (type);
9019 /* we have to go by the storage class */
9020 if (SPEC_OCLS (etype) != generic)
9022 p_type = PTR_TYPE (SPEC_OCLS (etype));
9027 /* Converting unknown class (i.e. register variable)
9028 * to generic pointer. This is not good, but
9029 * we'll make a guess (and throw a warning).
9032 werror (W_INT_TO_GEN_PTR_CAST);
9036 /* the first two bytes are known */
9037 size = GPTRSIZE - 1;
9039 _startLazyDPSEvaluation ();
9042 aopPut (AOP (result),
9043 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9047 _endLazyDPSEvaluation ();
9049 /* the last byte depending on type */
9067 /* this should never happen */
9068 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9069 "got unknown pointer type");
9072 aopPut (AOP (result), l, GPTRSIZE - 1);
9076 /* just copy the pointers */
9077 size = AOP_SIZE (result);
9079 _startLazyDPSEvaluation ();
9082 aopPut (AOP (result),
9083 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9087 _endLazyDPSEvaluation ();
9091 /* so we now know that the size of destination is greater
9092 than the size of the source */
9093 /* we move to result for the size of source */
9094 size = AOP_SIZE (right);
9096 _startLazyDPSEvaluation ();
9099 aopPut (AOP (result),
9100 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9104 _endLazyDPSEvaluation ();
9106 /* now depending on the sign of the source && destination */
9107 size = AOP_SIZE (result) - AOP_SIZE (right);
9108 /* if unsigned or not an integral type */
9109 /* also, if the source is a bit, we don't need to sign extend, because
9110 * it can't possibly have set the sign bit.
9112 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9116 aopPut (AOP (result), zero, offset++);
9121 /* we need to extend the sign :{ */
9122 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9123 FALSE, FALSE, TRUE);
9125 emitcode ("rlc", "a");
9126 emitcode ("subb", "a,acc");
9128 aopPut (AOP (result), "a", offset++);
9131 /* we are done hurray !!!! */
9134 freeAsmop (right, NULL, ic, TRUE);
9135 freeAsmop (result, NULL, ic, TRUE);
9139 /*-----------------------------------------------------------------*/
9140 /* genDjnz - generate decrement & jump if not zero instrucion */
9141 /*-----------------------------------------------------------------*/
9143 genDjnz (iCode * ic, iCode * ifx)
9149 /* if the if condition has a false label
9150 then we cannot save */
9154 /* if the minus is not of the form
9156 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9157 !IS_OP_LITERAL (IC_RIGHT (ic)))
9160 if (operandLitValue (IC_RIGHT (ic)) != 1)
9163 /* if the size of this greater than one then no
9165 if (getSize (operandType (IC_RESULT (ic))) > 1)
9168 /* otherwise we can save BIG */
9169 lbl = newiTempLabel (NULL);
9170 lbl1 = newiTempLabel (NULL);
9172 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9174 if (IS_AOP_PREG (IC_RESULT (ic)))
9176 emitcode ("dec", "%s",
9177 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9178 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9179 emitcode ("jnz", "%05d$", lbl->key + 100);
9183 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9186 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9187 emitcode ("", "%05d$:", lbl->key + 100);
9188 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9189 emitcode ("", "%05d$:", lbl1->key + 100);
9191 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9196 /*-----------------------------------------------------------------*/
9197 /* genReceive - generate code for a receive iCode */
9198 /*-----------------------------------------------------------------*/
9200 genReceive (iCode * ic)
9203 D (emitcode (";", "genReceive ");
9206 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9207 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9208 IS_TRUE_SYMOP (IC_RESULT (ic))))
9210 int size = getSize (operandType (IC_RESULT (ic)));
9211 int offset = fReturnSizeDS390 - size;
9214 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9215 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9218 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9219 size = AOP_SIZE (IC_RESULT (ic));
9223 emitcode ("pop", "acc");
9224 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9231 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9233 assignResultValue (IC_RESULT (ic));
9236 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9239 /*-----------------------------------------------------------------*/
9240 /* gen390Code - generate code for Dallas 390 based controllers */
9241 /*-----------------------------------------------------------------*/
9243 gen390Code (iCode * lic)
9248 lineHead = lineCurr = NULL;
9252 /* print the allocation information */
9254 printAllocInfo (currFunc, codeOutFile);
9256 /* if debug information required */
9257 if (options.debug && currFunc)
9259 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9261 if (IS_STATIC (currFunc->etype))
9262 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9264 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9267 /* stack pointer name */
9268 if (options.useXstack)
9274 for (ic = lic; ic; ic = ic->next)
9277 if (cln != ic->lineno)
9282 emitcode ("", "C$%s$%d$%d$%d ==.",
9283 FileBaseName (ic->filename), ic->lineno,
9284 ic->level, ic->block);
9287 emitcode (";", "%s %d", ic->filename, ic->lineno);
9290 /* if the result is marked as
9291 spilt and rematerializable or code for
9292 this has already been generated then
9294 if (resultRemat (ic) || ic->generated)
9297 /* depending on the operation */
9317 /* IPOP happens only when trying to restore a
9318 spilt live range, if there is an ifx statement
9319 following this pop then the if statement might
9320 be using some of the registers being popped which
9321 would destory the contents of the register so
9322 we need to check for this condition and handle it */
9324 ic->next->op == IFX &&
9325 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9326 genIfx (ic->next, ic);
9344 genEndFunction (ic);
9364 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9381 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9385 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9392 /* note these two are xlated by algebraic equivalence
9393 during parsing SDCC.y */
9394 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9395 "got '>=' or '<=' shouldn't have come here");
9399 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9411 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9415 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9419 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9446 case GET_VALUE_AT_ADDRESS:
9451 if (POINTER_SET (ic))
9478 addSet (&_G.sendSet, ic);
9483 /* piCode(ic,stdout); */
9489 /* now we are ready to call the
9490 peep hole optimizer */
9491 if (!options.nopeep)
9492 peepHole (&lineHead);
9494 /* now do the actual printing */
9495 printLine (lineHead, codeOutFile);