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"))
1228 symbol *lbl = newiTempLabel (NULL);
1229 emitcode ("clr", "c");
1230 emitcode ("jz", "%05d$", lbl->key + 100);
1231 emitcode ("cpl", "c");
1232 emitcode ("", "%05d$:", lbl->key + 100);
1233 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1241 if (strcmp (aop->aopu.aop_str[offset], s))
1242 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1247 if (!offset && (strcmp (s, "acc") == 0))
1250 if (strcmp (aop->aopu.aop_str[offset], s))
1251 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1255 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1256 "aopPut got unsupported aop->type");
1263 /*--------------------------------------------------------------------*/
1264 /* reAdjustPreg - points a register back to where it should (coff==0) */
1265 /*--------------------------------------------------------------------*/
1267 reAdjustPreg (asmop * aop)
1269 if ((aop->coff==0) || (aop->size <= 1)) {
1278 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1282 if (aop->type == AOP_DPTR2)
1289 emitcode ("lcall", "__decdptr");
1292 if (aop->type == AOP_DPTR2)
1302 #define AOP(op) op->aop
1303 #define AOP_TYPE(op) AOP(op)->type
1304 #define AOP_SIZE(op) AOP(op)->size
1305 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1306 AOP_TYPE(x) == AOP_R0))
1308 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1309 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1312 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1313 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1314 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1316 /* Workaround for DS80C390 bug: div ab may return bogus results
1317 * if A is accessed in instruction immediately before the div.
1319 * Will be fixed in B4 rev of processor, Dallas claims.
1322 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1323 if (!AOP_NEEDSACC(RIGHT)) \
1325 /* We can load A first, then B, since \
1326 * B (the RIGHT operand) won't clobber A, \
1327 * thus avoiding touching A right before the div. \
1329 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1330 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1332 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1336 /* Just stuff in a nop after loading A. */ \
1337 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1338 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1340 emitcode("nop", "; workaround for DS80C390 div bug."); \
1343 /*-----------------------------------------------------------------*/
1344 /* genNotFloat - generates not for float operations */
1345 /*-----------------------------------------------------------------*/
1347 genNotFloat (operand * op, operand * res)
1353 D (emitcode (";", "genNotFloat ");
1356 /* we will put 127 in the first byte of
1358 aopPut (AOP (res), "#127", 0);
1359 size = AOP_SIZE (op) - 1;
1362 _startLazyDPSEvaluation ();
1363 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1368 emitcode ("orl", "a,%s",
1370 offset++, FALSE, FALSE, FALSE));
1372 _endLazyDPSEvaluation ();
1374 tlbl = newiTempLabel (NULL);
1375 aopPut (res->aop, one, 1);
1376 emitcode ("jz", "%05d$", (tlbl->key + 100));
1377 aopPut (res->aop, zero, 1);
1378 emitcode ("", "%05d$:", (tlbl->key + 100));
1380 size = res->aop->size - 2;
1382 /* put zeros in the rest */
1384 aopPut (res->aop, zero, offset++);
1387 /*-----------------------------------------------------------------*/
1388 /* opIsGptr: returns non-zero if the passed operand is */
1389 /* a generic pointer type. */
1390 /*-----------------------------------------------------------------*/
1392 opIsGptr (operand * op)
1394 sym_link *type = operandType (op);
1396 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1403 /*-----------------------------------------------------------------*/
1404 /* getDataSize - get the operand data size */
1405 /*-----------------------------------------------------------------*/
1407 getDataSize (operand * op)
1410 size = AOP_SIZE (op);
1411 if (size == GPTRSIZE)
1413 sym_link *type = operandType (op);
1414 if (IS_GENPTR (type))
1416 /* generic pointer; arithmetic operations
1417 * should ignore the high byte (pointer type).
1425 /*-----------------------------------------------------------------*/
1426 /* outAcc - output Acc */
1427 /*-----------------------------------------------------------------*/
1429 outAcc (operand * result)
1432 size = getDataSize (result);
1435 aopPut (AOP (result), "a", 0);
1438 /* unsigned or positive */
1441 aopPut (AOP (result), zero, offset++);
1446 /*-----------------------------------------------------------------*/
1447 /* outBitC - output a bit C */
1448 /*-----------------------------------------------------------------*/
1450 outBitC (operand * result)
1452 /* if the result is bit */
1453 if (AOP_TYPE (result) == AOP_CRY)
1455 aopPut (AOP (result), "c", 0);
1459 emitcode ("clr", "a");
1460 emitcode ("rlc", "a");
1465 /*-----------------------------------------------------------------*/
1466 /* toBoolean - emit code for orl a,operator(sizeop) */
1467 /*-----------------------------------------------------------------*/
1469 toBoolean (operand * oper)
1471 int size = AOP_SIZE (oper) - 1;
1474 /* The generic part of a generic pointer should
1475 * not participate in it's truth value.
1477 * i.e. 0x10000000 is zero.
1479 if (opIsGptr (oper))
1481 D (emitcode (";", "toBoolean: generic ptr special case.");
1486 _startLazyDPSEvaluation ();
1487 if (AOP_NEEDSACC (oper))
1489 emitcode ("push", "b");
1490 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1494 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1498 if (AOP_NEEDSACC (oper))
1500 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1504 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1507 _endLazyDPSEvaluation ();
1509 if (AOP_NEEDSACC (oper))
1511 emitcode ("mov", "a,b");
1512 emitcode ("pop", "b");
1517 /*-----------------------------------------------------------------*/
1518 /* genNot - generate code for ! operation */
1519 /*-----------------------------------------------------------------*/
1524 sym_link *optype = operandType (IC_LEFT (ic));
1526 D (emitcode (";", "genNot ");
1529 /* assign asmOps to operand & result */
1530 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1531 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1533 /* if in bit space then a special case */
1534 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1536 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1537 emitcode ("cpl", "c");
1538 outBitC (IC_RESULT (ic));
1542 /* if type float then do float */
1543 if (IS_FLOAT (optype))
1545 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1549 toBoolean (IC_LEFT (ic));
1551 tlbl = newiTempLabel (NULL);
1552 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1553 emitcode ("", "%05d$:", tlbl->key + 100);
1554 outBitC (IC_RESULT (ic));
1557 /* release the aops */
1558 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1559 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1563 /*-----------------------------------------------------------------*/
1564 /* genCpl - generate code for complement */
1565 /*-----------------------------------------------------------------*/
1572 D (emitcode (";", "genCpl ");
1576 /* assign asmOps to operand & result */
1577 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1578 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1580 /* if both are in bit space then
1582 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1583 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1586 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1587 emitcode ("cpl", "c");
1588 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1592 size = AOP_SIZE (IC_RESULT (ic));
1593 _startLazyDPSEvaluation ();
1596 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1598 emitcode ("cpl", "a");
1599 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1601 _endLazyDPSEvaluation ();
1605 /* release the aops */
1606 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1607 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1610 /*-----------------------------------------------------------------*/
1611 /* genUminusFloat - unary minus for floating points */
1612 /*-----------------------------------------------------------------*/
1614 genUminusFloat (operand * op, operand * result)
1616 int size, offset = 0;
1618 /* for this we just need to flip the
1619 first it then copy the rest in place */
1620 D (emitcode (";", "genUminusFloat");
1623 _startLazyDPSEvaluation ();
1624 size = AOP_SIZE (op) - 1;
1625 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1628 emitcode ("cpl", "acc.7");
1629 aopPut (AOP (result), "a", 3);
1633 aopPut (AOP (result),
1634 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1638 _endLazyDPSEvaluation ();
1641 /*-----------------------------------------------------------------*/
1642 /* genUminus - unary minus code generation */
1643 /*-----------------------------------------------------------------*/
1645 genUminus (iCode * ic)
1648 sym_link *optype, *rtype;
1650 D (emitcode (";", "genUminus ");
1655 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1656 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1658 /* if both in bit space then special
1660 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1661 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1664 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1665 emitcode ("cpl", "c");
1666 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1670 optype = operandType (IC_LEFT (ic));
1671 rtype = operandType (IC_RESULT (ic));
1673 /* if float then do float stuff */
1674 if (IS_FLOAT (optype))
1676 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1680 /* otherwise subtract from zero */
1681 size = AOP_SIZE (IC_LEFT (ic));
1683 _startLazyDPSEvaluation ();
1686 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1687 if (!strcmp (l, "a"))
1691 emitcode ("cpl", "a");
1692 emitcode ("addc", "a,#0");
1698 emitcode ("clr", "a");
1699 emitcode ("subb", "a,%s", l);
1701 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1703 _endLazyDPSEvaluation ();
1705 /* if any remaining bytes in the result */
1706 /* we just need to propagate the sign */
1707 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1709 emitcode ("rlc", "a");
1710 emitcode ("subb", "a,acc");
1712 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1716 /* release the aops */
1717 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1718 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1721 /*-----------------------------------------------------------------*/
1722 /* saveRegisters - will look for a call and save the registers */
1723 /*-----------------------------------------------------------------*/
1725 saveRegisters (iCode * lic)
1733 for (ic = lic; ic; ic = ic->next)
1734 if (ic->op == CALL || ic->op == PCALL)
1739 fprintf (stderr, "found parameter push with no function call\n");
1743 /* if the registers have been saved already then
1745 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1748 /* find the registers in use at this time
1749 and push them away to safety */
1750 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1754 if (options.useXstack)
1756 if (bitVectBitValue (rsave, R0_IDX))
1757 emitcode ("mov", "b,r0");
1758 emitcode ("mov", "r0,%s", spname);
1759 for (i = 0; i < ds390_nRegs; i++)
1761 if (bitVectBitValue (rsave, i))
1764 emitcode ("mov", "a,b");
1766 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1767 emitcode ("movx", "@r0,a");
1768 emitcode ("inc", "r0");
1771 emitcode ("mov", "%s,r0", spname);
1772 if (bitVectBitValue (rsave, R0_IDX))
1773 emitcode ("mov", "r0,b");
1776 for (i = 0; i < ds390_nRegs; i++)
1778 if (bitVectBitValue (rsave, i))
1779 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1782 detype = getSpec (operandType (IC_LEFT (ic)));
1784 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1785 IS_ISR (currFunc->etype) &&
1788 saverbank (SPEC_BANK (detype), ic, TRUE);
1791 /*-----------------------------------------------------------------*/
1792 /* unsaveRegisters - pop the pushed registers */
1793 /*-----------------------------------------------------------------*/
1795 unsaveRegisters (iCode * ic)
1799 /* find the registers in use at this time
1800 and push them away to safety */
1801 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1804 if (options.useXstack)
1806 emitcode ("mov", "r0,%s", spname);
1807 for (i = ds390_nRegs; i >= 0; i--)
1809 if (bitVectBitValue (rsave, i))
1811 emitcode ("dec", "r0");
1812 emitcode ("movx", "a,@r0");
1814 emitcode ("mov", "b,a");
1816 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1820 emitcode ("mov", "%s,r0", spname);
1821 if (bitVectBitValue (rsave, R0_IDX))
1822 emitcode ("mov", "r0,b");
1825 for (i = ds390_nRegs; i >= 0; i--)
1827 if (bitVectBitValue (rsave, i))
1828 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1834 /*-----------------------------------------------------------------*/
1836 /*-----------------------------------------------------------------*/
1838 pushSide (operand * oper, int size)
1841 _startLazyDPSEvaluation ();
1844 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1845 if (AOP_TYPE (oper) != AOP_REG &&
1846 AOP_TYPE (oper) != AOP_DIR &&
1849 emitcode ("mov", "a,%s", l);
1850 emitcode ("push", "acc");
1853 emitcode ("push", "%s", l);
1855 _endLazyDPSEvaluation ();
1858 /*-----------------------------------------------------------------*/
1859 /* assignResultValue - */
1860 /*-----------------------------------------------------------------*/
1862 assignResultValue (operand * oper)
1865 int size = AOP_SIZE (oper);
1867 _startLazyDPSEvaluation ();
1870 aopPut (AOP (oper), fReturn[offset], offset);
1873 _endLazyDPSEvaluation ();
1877 /*-----------------------------------------------------------------*/
1878 /* genXpush - pushes onto the external stack */
1879 /*-----------------------------------------------------------------*/
1881 genXpush (iCode * ic)
1883 asmop *aop = newAsmop (0);
1885 int size, offset = 0;
1887 D (emitcode (";", "genXpush ");
1890 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1891 r = getFreePtr (ic, &aop, FALSE);
1894 emitcode ("mov", "%s,_spx", r->name);
1896 size = AOP_SIZE (IC_LEFT (ic));
1897 _startLazyDPSEvaluation ();
1901 char *l = aopGet (AOP (IC_LEFT (ic)),
1902 offset++, FALSE, FALSE, TRUE);
1904 emitcode ("movx", "@%s,a", r->name);
1905 emitcode ("inc", "%s", r->name);
1908 _endLazyDPSEvaluation ();
1911 emitcode ("mov", "_spx,%s", r->name);
1913 freeAsmop (NULL, aop, ic, TRUE);
1914 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1917 /*-----------------------------------------------------------------*/
1918 /* genIpush - genrate code for pushing this gets a little complex */
1919 /*-----------------------------------------------------------------*/
1921 genIpush (iCode * ic)
1923 int size, offset = 0;
1926 D (emitcode (";", "genIpush ");
1929 /* if this is not a parm push : ie. it is spill push
1930 and spill push is always done on the local stack */
1934 /* and the item is spilt then do nothing */
1935 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1938 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1939 size = AOP_SIZE (IC_LEFT (ic));
1940 /* push it on the stack */
1941 _startLazyDPSEvaluation ();
1944 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1950 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1952 _endLazyDPSEvaluation ();
1956 /* this is a paramter push: in this case we call
1957 the routine to find the call and save those
1958 registers that need to be saved */
1961 /* if use external stack then call the external
1962 stack pushing routine */
1963 if (options.useXstack)
1969 /* then do the push */
1970 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1972 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1973 size = AOP_SIZE (IC_LEFT (ic));
1975 _startLazyDPSEvaluation ();
1978 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1979 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1980 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1983 emitcode ("mov", "a,%s", l);
1984 emitcode ("push", "acc");
1987 emitcode ("push", "%s ;jwk genIpush", l);
1989 _endLazyDPSEvaluation ();
1991 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1994 /*-----------------------------------------------------------------*/
1995 /* genIpop - recover the registers: can happen only for spilling */
1996 /*-----------------------------------------------------------------*/
1998 genIpop (iCode * ic)
2002 D (emitcode (";", "genIpop ");
2006 /* if the temp was not pushed then */
2007 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2010 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2011 size = AOP_SIZE (IC_LEFT (ic));
2012 offset = (size - 1);
2013 _startLazyDPSEvaluation ();
2016 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2017 FALSE, TRUE, TRUE));
2019 _endLazyDPSEvaluation ();
2021 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2024 /*-----------------------------------------------------------------*/
2025 /* unsaverbank - restores the resgister bank from stack */
2026 /*-----------------------------------------------------------------*/
2028 unsaverbank (int bank, iCode * ic, bool popPsw)
2036 if (options.useXstack)
2039 r = getFreePtr (ic, &aop, FALSE);
2042 emitcode ("mov", "%s,_spx", r->name);
2043 emitcode ("movx", "a,@%s", r->name);
2044 emitcode ("mov", "psw,a");
2045 emitcode ("dec", "%s", r->name);
2049 emitcode ("pop", "psw");
2052 for (i = (ds390_nRegs - 1); i >= 0; i--)
2054 if (options.useXstack)
2056 emitcode ("movx", "a,@%s", r->name);
2057 emitcode ("mov", "(%s+%d),a",
2058 regs390[i].base, 8 * bank + regs390[i].offset);
2059 emitcode ("dec", "%s", r->name);
2063 emitcode ("pop", "(%s+%d)",
2064 regs390[i].base, 8 * bank + regs390[i].offset);
2067 if (options.useXstack)
2070 emitcode ("mov", "_spx,%s", r->name);
2071 freeAsmop (NULL, aop, ic, TRUE);
2076 /*-----------------------------------------------------------------*/
2077 /* saverbank - saves an entire register bank on the stack */
2078 /*-----------------------------------------------------------------*/
2080 saverbank (int bank, iCode * ic, bool pushPsw)
2086 if (options.useXstack)
2090 r = getFreePtr (ic, &aop, FALSE);
2091 emitcode ("mov", "%s,_spx", r->name);
2095 for (i = 0; i < ds390_nRegs; i++)
2097 if (options.useXstack)
2099 emitcode ("inc", "%s", r->name);
2100 emitcode ("mov", "a,(%s+%d)",
2101 regs390[i].base, 8 * bank + regs390[i].offset);
2102 emitcode ("movx", "@%s,a", r->name);
2105 emitcode ("push", "(%s+%d)",
2106 regs390[i].base, 8 * bank + regs390[i].offset);
2111 if (options.useXstack)
2113 emitcode ("mov", "a,psw");
2114 emitcode ("movx", "@%s,a", r->name);
2115 emitcode ("inc", "%s", r->name);
2116 emitcode ("mov", "_spx,%s", r->name);
2117 freeAsmop (NULL, aop, ic, TRUE);
2121 emitcode ("push", "psw");
2123 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2129 /*-----------------------------------------------------------------*/
2130 /* genCall - generates a call statement */
2131 /*-----------------------------------------------------------------*/
2133 genCall (iCode * ic)
2137 D (emitcode (";", "genCall ");
2140 /* if caller saves & we have not saved then */
2144 /* if we are calling a function that is not using
2145 the same register bank then we need to save the
2146 destination registers on the stack */
2147 detype = getSpec (operandType (IC_LEFT (ic)));
2149 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2150 IS_ISR (currFunc->etype) &&
2153 saverbank (SPEC_BANK (detype), ic, TRUE);
2155 /* if send set is not empty the assign */
2160 for (sic = setFirstItem (_G.sendSet); sic;
2161 sic = setNextItem (_G.sendSet))
2163 int size, offset = 0;
2165 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2166 size = AOP_SIZE (IC_LEFT (sic));
2168 _startLazyDPSEvaluation ();
2171 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2172 FALSE, FALSE, TRUE);
2173 if (strcmp (l, fReturn[offset])) {
2176 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2182 _endLazyDPSEvaluation ();
2183 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2188 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2189 OP_SYMBOL (IC_LEFT (ic))->rname :
2190 OP_SYMBOL (IC_LEFT (ic))->name));
2192 /* if we need assign a result value */
2193 if ((IS_ITEMP (IC_RESULT (ic)) &&
2194 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2195 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2196 IS_TRUE_SYMOP (IC_RESULT (ic)))
2198 if (isOperandInFarSpace (IC_RESULT (ic))
2199 && getSize (operandType (IC_RESULT (ic))) <= 2)
2201 int size = getSize (operandType (IC_RESULT (ic)));
2203 /* Special case for 1 or 2 byte return in far space. */
2204 emitcode (";", "Kevin function call abuse #1");
2209 emitcode ("mov", "b,%s", fReturn[1]);
2212 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2213 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2217 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2219 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2224 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2227 assignResultValue (IC_RESULT (ic));
2229 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2233 /* adjust the stack for parameters if
2238 if (ic->parmBytes > 3)
2240 emitcode ("mov", "a,%s", spname);
2241 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2242 emitcode ("mov", "%s,a", spname);
2245 for (i = 0; i < ic->parmBytes; i++)
2246 emitcode ("dec", "%s", spname);
2250 /* if register bank was saved then pop them */
2252 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2254 /* if we hade saved some registers then unsave them */
2255 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2256 unsaveRegisters (ic);
2261 /*-----------------------------------------------------------------*/
2262 /* genPcall - generates a call by pointer statement */
2263 /*-----------------------------------------------------------------*/
2265 genPcall (iCode * ic)
2268 symbol *rlbl = newiTempLabel (NULL);
2270 D (emitcode (";", "genPcall ");
2274 /* if caller saves & we have not saved then */
2278 /* if we are calling a function that is not using
2279 the same register bank then we need to save the
2280 destination registers on the stack */
2281 detype = getSpec (operandType (IC_LEFT (ic)));
2283 IS_ISR (currFunc->etype) &&
2284 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2285 saverbank (SPEC_BANK (detype), ic, TRUE);
2288 /* push the return address on to the stack */
2289 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2290 emitcode ("push", "acc");
2291 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2292 emitcode ("push", "acc");
2294 if (options.model == MODEL_FLAT24)
2296 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2297 emitcode ("push", "acc");
2300 /* now push the calling address */
2301 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2303 pushSide (IC_LEFT (ic), FPTRSIZE);
2305 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2307 /* if send set is not empty the assign */
2312 for (sic = setFirstItem (_G.sendSet); sic;
2313 sic = setNextItem (_G.sendSet))
2315 int size, offset = 0;
2317 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2318 size = AOP_SIZE (IC_LEFT (sic));
2319 _startLazyDPSEvaluation ();
2322 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2323 FALSE, FALSE, TRUE);
2324 if (strcmp (l, fReturn[offset]))
2326 emitcode ("mov", "%s,%s",
2332 _endLazyDPSEvaluation ();
2333 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2338 emitcode ("ret", "");
2339 emitcode ("", "%05d$:", (rlbl->key + 100));
2342 /* if we need assign a result value */
2343 if ((IS_ITEMP (IC_RESULT (ic)) &&
2344 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2345 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2346 IS_TRUE_SYMOP (IC_RESULT (ic)))
2350 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2353 assignResultValue (IC_RESULT (ic));
2355 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2358 /* adjust the stack for parameters if
2363 if (ic->parmBytes > 3)
2365 emitcode ("mov", "a,%s", spname);
2366 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2367 emitcode ("mov", "%s,a", spname);
2370 for (i = 0; i < ic->parmBytes; i++)
2371 emitcode ("dec", "%s", spname);
2375 /* if register bank was saved then unsave them */
2377 (SPEC_BANK (currFunc->etype) !=
2378 SPEC_BANK (detype)))
2379 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2381 /* if we hade saved some registers then
2384 unsaveRegisters (ic);
2388 /*-----------------------------------------------------------------*/
2389 /* resultRemat - result is rematerializable */
2390 /*-----------------------------------------------------------------*/
2392 resultRemat (iCode * ic)
2394 if (SKIP_IC (ic) || ic->op == IFX)
2397 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2399 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2400 if (sym->remat && !POINTER_SET (ic))
2407 #if defined(__BORLANDC__) || defined(_MSC_VER)
2408 #define STRCASECMP stricmp
2410 #define STRCASECMP strcasecmp
2413 /*-----------------------------------------------------------------*/
2414 /* inExcludeList - return 1 if the string is in exclude Reg list */
2415 /*-----------------------------------------------------------------*/
2417 inExcludeList (char *s)
2421 if (options.excludeRegs[i] &&
2422 STRCASECMP (options.excludeRegs[i], "none") == 0)
2425 for (i = 0; options.excludeRegs[i]; i++)
2427 if (options.excludeRegs[i] &&
2428 STRCASECMP (s, options.excludeRegs[i]) == 0)
2434 /*-----------------------------------------------------------------*/
2435 /* genFunction - generated code for function entry */
2436 /*-----------------------------------------------------------------*/
2438 genFunction (iCode * ic)
2443 D (emitcode (";", "genFunction ");
2447 /* create the function header */
2448 emitcode (";", "-----------------------------------------");
2449 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2450 emitcode (";", "-----------------------------------------");
2452 emitcode ("", "%s:", sym->rname);
2453 fetype = getSpec (operandType (IC_LEFT (ic)));
2455 /* if critical function then turn interrupts off */
2456 if (SPEC_CRTCL (fetype))
2457 emitcode ("clr", "ea");
2459 /* here we need to generate the equates for the
2460 register bank if required */
2461 if (SPEC_BANK (fetype) != rbank)
2465 rbank = SPEC_BANK (fetype);
2466 for (i = 0; i < ds390_nRegs; i++)
2468 if (strcmp (regs390[i].base, "0") == 0)
2469 emitcode ("", "%s = 0x%02x",
2471 8 * rbank + regs390[i].offset);
2473 emitcode ("", "%s = %s + 0x%02x",
2476 8 * rbank + regs390[i].offset);
2480 /* if this is an interrupt service routine then
2481 save acc, b, dpl, dph */
2482 if (IS_ISR (sym->etype))
2485 if (!inExcludeList ("acc"))
2486 emitcode ("push", "acc");
2487 if (!inExcludeList ("b"))
2488 emitcode ("push", "b");
2489 if (!inExcludeList ("dpl"))
2490 emitcode ("push", "dpl");
2491 if (!inExcludeList ("dph"))
2492 emitcode ("push", "dph");
2493 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2495 emitcode ("push", "dpx");
2496 /* Make sure we're using standard DPTR */
2497 emitcode ("push", "dps");
2498 emitcode ("mov", "dps, #0x00");
2499 if (options.stack10bit)
2501 /* This ISR could conceivably use DPTR2. Better save it. */
2502 emitcode ("push", "dpl1");
2503 emitcode ("push", "dph1");
2504 emitcode ("push", "dpx1");
2505 emitcode ("push", "ap");
2508 /* if this isr has no bank i.e. is going to
2509 run with bank 0 , then we need to save more
2511 if (!SPEC_BANK (sym->etype))
2514 /* if this function does not call any other
2515 function then we can be economical and
2516 save only those registers that are used */
2521 /* if any registers used */
2524 /* save the registers used */
2525 for (i = 0; i < sym->regsUsed->size; i++)
2527 if (bitVectBitValue (sym->regsUsed, i) ||
2528 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2529 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2536 /* this function has a function call cannot
2537 determines register usage so we will have the
2539 saverbank (0, ic, FALSE);
2545 /* if callee-save to be used for this function
2546 then save the registers being used in this function */
2547 if (sym->calleeSave)
2551 /* if any registers used */
2554 /* save the registers used */
2555 for (i = 0; i < sym->regsUsed->size; i++)
2557 if (bitVectBitValue (sym->regsUsed, i) ||
2558 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2560 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2568 /* set the register bank to the desired value */
2569 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2571 emitcode ("push", "psw");
2572 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2575 if (IS_RENT (sym->etype) || options.stackAuto)
2578 if (options.useXstack)
2580 emitcode ("mov", "r0,%s", spname);
2581 emitcode ("mov", "a,_bp");
2582 emitcode ("movx", "@r0,a");
2583 emitcode ("inc", "%s", spname);
2587 /* set up the stack */
2588 emitcode ("push", "_bp"); /* save the callers stack */
2590 emitcode ("mov", "_bp,%s", spname);
2593 /* adjust the stack for the function */
2599 werror (W_STACK_OVERFLOW, sym->name);
2601 if (i > 3 && sym->recvSize < 4)
2604 emitcode ("mov", "a,sp");
2605 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2606 emitcode ("mov", "sp,a");
2611 emitcode ("inc", "sp");
2617 emitcode ("mov", "a,_spx");
2618 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2619 emitcode ("mov", "_spx,a");
2624 /*-----------------------------------------------------------------*/
2625 /* genEndFunction - generates epilogue for functions */
2626 /*-----------------------------------------------------------------*/
2628 genEndFunction (iCode * ic)
2630 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2632 D (emitcode (";", "genEndFunction ");
2635 if (IS_RENT (sym->etype) || options.stackAuto)
2637 emitcode ("mov", "%s,_bp", spname);
2640 /* if use external stack but some variables were
2641 added to the local stack then decrement the
2643 if (options.useXstack && sym->stack)
2645 emitcode ("mov", "a,sp");
2646 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2647 emitcode ("mov", "sp,a");
2651 if ((IS_RENT (sym->etype) || options.stackAuto))
2653 if (options.useXstack)
2655 emitcode ("mov", "r0,%s", spname);
2656 emitcode ("movx", "a,@r0");
2657 emitcode ("mov", "_bp,a");
2658 emitcode ("dec", "%s", spname);
2662 emitcode ("pop", "_bp");
2666 /* restore the register bank */
2667 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2668 emitcode ("pop", "psw");
2670 if (IS_ISR (sym->etype))
2673 /* now we need to restore the registers */
2674 /* if this isr has no bank i.e. is going to
2675 run with bank 0 , then we need to save more
2677 if (!SPEC_BANK (sym->etype))
2680 /* if this function does not call any other
2681 function then we can be economical and
2682 save only those registers that are used */
2687 /* if any registers used */
2690 /* save the registers used */
2691 for (i = sym->regsUsed->size; i >= 0; i--)
2693 if (bitVectBitValue (sym->regsUsed, i) ||
2694 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2695 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2702 /* this function has a function call cannot
2703 determines register usage so we will have the
2705 unsaverbank (0, ic, FALSE);
2709 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2711 if (options.stack10bit)
2713 emitcode ("pop", "ap");
2714 emitcode ("pop", "dpx1");
2715 emitcode ("pop", "dph1");
2716 emitcode ("pop", "dpl1");
2718 emitcode ("pop", "dps");
2719 emitcode ("pop", "dpx");
2721 if (!inExcludeList ("dph"))
2722 emitcode ("pop", "dph");
2723 if (!inExcludeList ("dpl"))
2724 emitcode ("pop", "dpl");
2725 if (!inExcludeList ("b"))
2726 emitcode ("pop", "b");
2727 if (!inExcludeList ("acc"))
2728 emitcode ("pop", "acc");
2730 if (SPEC_CRTCL (sym->etype))
2731 emitcode ("setb", "ea");
2733 /* if debug then send end of function */
2734 /* if (options.debug && currFunc) { */
2738 emitcode ("", "C$%s$%d$%d$%d ==.",
2739 FileBaseName (ic->filename), currFunc->lastLine,
2740 ic->level, ic->block);
2741 if (IS_STATIC (currFunc->etype))
2742 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2744 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2748 emitcode ("reti", "");
2752 if (SPEC_CRTCL (sym->etype))
2753 emitcode ("setb", "ea");
2755 if (sym->calleeSave)
2759 /* if any registers used */
2762 /* save the registers used */
2763 for (i = sym->regsUsed->size; i >= 0; i--)
2765 if (bitVectBitValue (sym->regsUsed, i) ||
2766 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2767 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2773 /* if debug then send end of function */
2777 emitcode ("", "C$%s$%d$%d$%d ==.",
2778 FileBaseName (ic->filename), currFunc->lastLine,
2779 ic->level, ic->block);
2780 if (IS_STATIC (currFunc->etype))
2781 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2783 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2787 emitcode ("ret", "");
2792 /*-----------------------------------------------------------------*/
2793 /* genRet - generate code for return statement */
2794 /*-----------------------------------------------------------------*/
2798 int size, offset = 0, pushed = 0;
2800 D (emitcode (";", "genRet ");
2803 /* if we have no return value then
2804 just generate the "ret" */
2808 /* we have something to return then
2809 move the return value into place */
2810 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2811 size = AOP_SIZE (IC_LEFT (ic));
2813 _startLazyDPSEvaluation ();
2817 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2819 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2820 FALSE, TRUE, FALSE);
2821 emitcode ("push", "%s", l);
2826 l = aopGet (AOP (IC_LEFT (ic)), offset,
2827 FALSE, FALSE, FALSE);
2828 if (strcmp (fReturn[offset], l))
2829 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2832 _endLazyDPSEvaluation ();
2839 if (strcmp (fReturn[pushed], "a"))
2840 emitcode ("pop", fReturn[pushed]);
2842 emitcode ("pop", "acc");
2845 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2848 /* generate a jump to the return label
2849 if the next is not the return statement */
2850 if (!(ic->next && ic->next->op == LABEL &&
2851 IC_LABEL (ic->next) == returnLabel))
2853 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2857 /*-----------------------------------------------------------------*/
2858 /* genLabel - generates a label */
2859 /*-----------------------------------------------------------------*/
2861 genLabel (iCode * ic)
2863 /* special case never generate */
2864 if (IC_LABEL (ic) == entryLabel)
2867 D (emitcode (";", "genLabel ");
2870 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2873 /*-----------------------------------------------------------------*/
2874 /* genGoto - generates a ljmp */
2875 /*-----------------------------------------------------------------*/
2877 genGoto (iCode * ic)
2879 D (emitcode (";", "genGoto ");
2881 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2884 /*-----------------------------------------------------------------*/
2885 /* findLabelBackwards: walks back through the iCode chain looking */
2886 /* for the given label. Returns number of iCode instructions */
2887 /* between that label and given ic. */
2888 /* Returns zero if label not found. */
2889 /*-----------------------------------------------------------------*/
2891 findLabelBackwards (iCode * ic, int key)
2900 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2902 /* printf("findLabelBackwards = %d\n", count); */
2910 /*-----------------------------------------------------------------*/
2911 /* genPlusIncr :- does addition with increment if possible */
2912 /*-----------------------------------------------------------------*/
2914 genPlusIncr (iCode * ic)
2916 unsigned int icount;
2917 unsigned int size = getDataSize (IC_RESULT (ic));
2919 /* will try to generate an increment */
2920 /* if the right side is not a literal
2922 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2925 /* if the literal value of the right hand side
2926 is greater than 4 then it is not worth it */
2927 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2930 /* if increment 16 bits in register */
2932 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2933 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2934 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2942 /* If the next instruction is a goto and the goto target
2943 * is <= 5 instructions previous to this, we can generate
2944 * jumps straight to that target.
2946 if (ic->next && ic->next->op == GOTO
2947 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2950 emitcode (";", "tail increment optimized (range %d)", labelRange);
2951 tlbl = IC_LABEL (ic->next);
2956 tlbl = newiTempLabel (NULL);
2959 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2960 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2961 IS_AOP_PREG (IC_RESULT (ic)))
2962 emitcode ("cjne", "%s,#0x00,%05d$"
2963 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2967 emitcode ("clr", "a");
2968 emitcode ("cjne", "a,%s,%05d$"
2969 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2973 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2976 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2977 IS_AOP_PREG (IC_RESULT (ic)))
2978 emitcode ("cjne", "%s,#0x00,%05d$"
2979 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2982 emitcode ("cjne", "a,%s,%05d$"
2983 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2986 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2990 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2991 IS_AOP_PREG (IC_RESULT (ic)))
2992 emitcode ("cjne", "%s,#0x00,%05d$"
2993 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
2997 emitcode ("cjne", "a,%s,%05d$"
2998 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3001 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3006 emitcode ("", "%05d$:", tlbl->key + 100);
3011 /* if the sizes are greater than 1 then we cannot */
3012 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3013 AOP_SIZE (IC_LEFT (ic)) > 1)
3016 /* we can if the aops of the left & result match or
3017 if they are in registers and the registers are the
3020 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3021 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3022 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3027 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3028 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3029 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3034 _startLazyDPSEvaluation ();
3037 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3039 _endLazyDPSEvaluation ();
3048 /*-----------------------------------------------------------------*/
3049 /* outBitAcc - output a bit in acc */
3050 /*-----------------------------------------------------------------*/
3052 outBitAcc (operand * result)
3054 symbol *tlbl = newiTempLabel (NULL);
3055 /* if the result is a bit */
3056 if (AOP_TYPE (result) == AOP_CRY)
3058 aopPut (AOP (result), "a", 0);
3062 emitcode ("jz", "%05d$", tlbl->key + 100);
3063 emitcode ("mov", "a,%s", one);
3064 emitcode ("", "%05d$:", tlbl->key + 100);
3069 /*-----------------------------------------------------------------*/
3070 /* genPlusBits - generates code for addition of two bits */
3071 /*-----------------------------------------------------------------*/
3073 genPlusBits (iCode * ic)
3075 D (emitcode (";", "genPlusBits ");
3077 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3079 symbol *lbl = newiTempLabel (NULL);
3080 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3081 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3082 emitcode ("cpl", "c");
3083 emitcode ("", "%05d$:", (lbl->key + 100));
3084 outBitC (IC_RESULT (ic));
3088 emitcode ("clr", "a");
3089 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3090 emitcode ("rlc", "a");
3091 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3092 emitcode ("addc", "a,#0x00");
3093 outAcc (IC_RESULT (ic));
3098 adjustArithmeticResult (iCode * ic)
3100 if (opIsGptr (IC_RESULT (ic)) &&
3101 opIsGptr (IC_LEFT (ic)) &&
3102 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3104 aopPut (AOP (IC_RESULT (ic)),
3105 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3109 if (opIsGptr (IC_RESULT (ic)) &&
3110 opIsGptr (IC_RIGHT (ic)) &&
3111 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3113 aopPut (AOP (IC_RESULT (ic)),
3114 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3118 if (opIsGptr (IC_RESULT (ic)) &&
3119 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3120 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3121 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3122 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3125 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3126 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3130 #define AOP_OP_3(ic) \
3131 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3132 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3133 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3134 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3135 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3136 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3138 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3140 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3143 #define AOP_OP_3_NOFATAL(ic, rc) \
3144 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3145 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3146 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3147 isOperandInFarSpace(IC_RESULT(ic))) \
3149 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3154 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3155 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3157 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3158 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3160 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3162 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3166 #define AOP_OP_2(ic) \
3167 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3168 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3170 #define AOP_SET_LOCALS(ic) \
3171 left = IC_LEFT(ic); \
3172 right = IC_RIGHT(ic); \
3173 result = IC_RESULT(ic);
3175 /*-----------------------------------------------------------------*/
3176 /* genPlus - generates code for addition */
3177 /*-----------------------------------------------------------------*/
3179 genPlus (iCode * ic)
3181 int size, offset = 0;
3182 bool pushResult = FALSE;
3185 D (emitcode (";", "genPlus ");
3188 /* special cases :- */
3190 AOP_OP_3_NOFATAL (ic, pushResult);
3193 D (emitcode (";", "genPlus: must push result: 3 ops in far space");
3199 /* if literal, literal on the right or
3200 if left requires ACC or right is already
3202 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3203 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3204 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3206 operand *t = IC_RIGHT (ic);
3207 IC_RIGHT (ic) = IC_LEFT (ic);
3209 emitcode (";", "Swapped plus args.");
3212 /* if both left & right are in bit
3214 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3215 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3221 /* if left in bit space & right literal */
3222 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3223 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3225 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3226 /* if result in bit space */
3227 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3229 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3230 emitcode ("cpl", "c");
3231 outBitC (IC_RESULT (ic));
3235 size = getDataSize (IC_RESULT (ic));
3236 _startLazyDPSEvaluation ();
3239 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3240 emitcode ("addc", "a,#00");
3241 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3243 _endLazyDPSEvaluation ();
3248 /* if I can do an increment instead
3249 of add then GOOD for ME */
3250 if (genPlusIncr (ic) == TRUE)
3252 emitcode (";", "did genPlusIncr");
3257 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3259 _startLazyDPSEvaluation ();
3262 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3264 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3266 emitcode ("add", "a,%s",
3267 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3269 emitcode ("addc", "a,%s",
3270 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3274 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3276 emitcode ("add", "a,%s",
3277 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3279 emitcode ("addc", "a,%s",
3280 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3284 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3288 emitcode ("push", "acc");
3292 _endLazyDPSEvaluation ();
3296 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3298 size = getDataSize (IC_LEFT (ic));
3299 rSize = getDataSize (IC_RESULT (ic));
3301 /* If the pushed data is bigger than the result,
3302 * simply discard unused bytes. Icky, but works.
3304 * Should we throw a warning here? We're losing data...
3306 while (size > rSize)
3308 D (emitcode (";", "discarding unused result byte.");
3310 emitcode ("pop", "acc");
3316 emitcode ("clr", "a");
3317 /* Conversly, we haven't pushed enough here.
3318 * just zero-pad, and all is well.
3320 while (size < rSize)
3322 emitcode ("push", "acc");
3328 _startLazyDPSEvaluation ();
3331 emitcode ("pop", "acc");
3332 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3334 _endLazyDPSEvaluation ();
3337 adjustArithmeticResult (ic);
3340 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3341 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3342 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3345 /*-----------------------------------------------------------------*/
3346 /* genMinusDec :- does subtraction with deccrement if possible */
3347 /*-----------------------------------------------------------------*/
3349 genMinusDec (iCode * ic)
3351 unsigned int icount;
3352 unsigned int size = getDataSize (IC_RESULT (ic));
3354 /* will try to generate an increment */
3355 /* if the right side is not a literal
3357 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3360 /* if the literal value of the right hand side
3361 is greater than 4 then it is not worth it */
3362 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3365 /* if decrement 16 bits in register */
3366 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3367 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3368 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3376 /* If the next instruction is a goto and the goto target
3377 * is <= 5 instructions previous to this, we can generate
3378 * jumps straight to that target.
3380 if (ic->next && ic->next->op == GOTO
3381 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3384 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3385 tlbl = IC_LABEL (ic->next);
3390 tlbl = newiTempLabel (NULL);
3394 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3395 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3396 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3397 IS_AOP_PREG (IC_RESULT (ic)))
3398 emitcode ("cjne", "%s,#0xff,%05d$"
3399 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3403 emitcode ("mov", "a,#0xff");
3404 emitcode ("cjne", "a,%s,%05d$"
3405 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3408 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3411 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3412 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3413 IS_AOP_PREG (IC_RESULT (ic)))
3414 emitcode ("cjne", "%s,#0xff,%05d$"
3415 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3419 emitcode ("cjne", "a,%s,%05d$"
3420 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3423 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3427 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3428 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3429 IS_AOP_PREG (IC_RESULT (ic)))
3430 emitcode ("cjne", "%s,#0xff,%05d$"
3431 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3435 emitcode ("cjne", "a,%s,%05d$"
3436 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3439 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3443 emitcode ("", "%05d$:", tlbl->key + 100);
3448 /* if the sizes are greater than 1 then we cannot */
3449 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3450 AOP_SIZE (IC_LEFT (ic)) > 1)
3453 /* we can if the aops of the left & result match or
3454 if they are in registers and the registers are the
3457 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3458 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3459 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3462 _startLazyDPSEvaluation ();
3465 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3467 _endLazyDPSEvaluation ();
3475 /*-----------------------------------------------------------------*/
3476 /* addSign - complete with sign */
3477 /*-----------------------------------------------------------------*/
3479 addSign (operand * result, int offset, int sign)
3481 int size = (getDataSize (result) - offset);
3486 emitcode ("rlc", "a");
3487 emitcode ("subb", "a,acc");
3489 aopPut (AOP (result), "a", offset++);
3493 aopPut (AOP (result), zero, offset++);
3497 /*-----------------------------------------------------------------*/
3498 /* genMinusBits - generates code for subtraction of two bits */
3499 /*-----------------------------------------------------------------*/
3501 genMinusBits (iCode * ic)
3503 symbol *lbl = newiTempLabel (NULL);
3505 D (emitcode (";", "genMinusBits ");
3508 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3510 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3511 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3512 emitcode ("cpl", "c");
3513 emitcode ("", "%05d$:", (lbl->key + 100));
3514 outBitC (IC_RESULT (ic));
3518 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3519 emitcode ("subb", "a,acc");
3520 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3521 emitcode ("inc", "a");
3522 emitcode ("", "%05d$:", (lbl->key + 100));
3523 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3524 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3528 /*-----------------------------------------------------------------*/
3529 /* genMinus - generates code for subtraction */
3530 /*-----------------------------------------------------------------*/
3532 genMinus (iCode * ic)
3534 int size, offset = 0;
3536 unsigned long lit = 0L;
3537 bool pushResult = FALSE;
3539 D (emitcode (";", "genMinus ");
3542 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3543 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3544 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3545 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3551 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3553 /* special cases :- */
3554 /* if both left & right are in bit space */
3555 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3556 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3562 /* if I can do an decrement instead
3563 of subtract then GOOD for ME */
3564 if (genMinusDec (ic) == TRUE)
3569 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3571 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3577 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3582 /* if literal, add a,#-lit, else normal subb */
3583 _startLazyDPSEvaluation ();
3586 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3587 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3588 emitcode ("subb", "a,%s",
3589 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3592 /* first add without previous c */
3594 emitcode ("add", "a,#0x%02x",
3595 (unsigned int) (lit & 0x0FFL));
3597 emitcode ("addc", "a,#0x%02x",
3598 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3603 emitcode ("push", "acc");
3607 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3611 _endLazyDPSEvaluation ();
3615 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3617 size = getDataSize (IC_LEFT (ic));
3618 rSize = getDataSize (IC_RESULT (ic));
3620 /* If the pushed data is bigger than the result,
3621 * simply discard unused bytes. Icky, but works.
3623 * Should we throw a warning here? We're losing data...
3625 while (size > getDataSize (IC_RESULT (ic)))
3627 emitcode (";", "discarding unused result byte.");
3628 emitcode ("pop", "acc");
3634 emitcode ("clr", "a");
3635 /* Conversly, we haven't pushed enough here.
3636 * just zero-pad, and all is well.
3638 while (size < rSize)
3640 emitcode ("push", "acc");
3648 emitcode ("pop", "acc");
3649 aopPut (AOP (IC_RESULT (ic)), "a", --offset);
3653 adjustArithmeticResult (ic);
3656 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3657 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3662 /*-----------------------------------------------------------------*/
3663 /* genMultbits :- multiplication of bits */
3664 /*-----------------------------------------------------------------*/
3666 genMultbits (operand * left,
3670 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3671 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3676 /*-----------------------------------------------------------------*/
3677 /* genMultOneByte : 8*8=8/16 bit multiplication */
3678 /*-----------------------------------------------------------------*/
3680 genMultOneByte (operand * left,
3684 sym_link *opetype = operandType (result);
3686 int size=AOP_SIZE(result);
3688 emitcode (";",__FUNCTION__);
3689 if (size<1 || size>2) {
3690 // this should never happen
3691 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3692 AOP_SIZE(result), __FUNCTION__, lineno);
3696 /* (if two literals: the value is computed before) */
3697 /* if one literal, literal on the right */
3698 if (AOP_TYPE (left) == AOP_LIT)
3703 emitcode (";", "swapped left and right");
3706 if (SPEC_USIGN(opetype)
3707 // ignore the sign of left and right, what else can we do?
3708 || (SPEC_USIGN(operandType(left)) &&
3709 SPEC_USIGN(operandType(right)))) {
3710 // just an unsigned 8*8=8/16 multiply
3711 //emitcode (";","unsigned");
3712 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3713 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3714 emitcode ("mul", "ab");
3715 aopPut (AOP (result), "a", 0);
3717 aopPut (AOP (result), "b", 1);
3722 // we have to do a signed multiply
3724 emitcode (";", "signed");
3725 emitcode ("clr", "F0"); // reset sign flag
3726 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3727 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3729 lbl=newiTempLabel(NULL);
3730 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3731 // left side is negative, 8-bit two's complement, this fails for -128
3732 emitcode ("setb", "F0"); // set sign flag
3733 emitcode ("cpl", "a");
3734 emitcode ("inc", "a");
3736 emitcode ("", "%05d$:", lbl->key+100);
3737 emitcode ("xch", "a,b");
3740 if (AOP_TYPE(right)==AOP_LIT) {
3741 /* AND literal negative */
3742 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3743 // two's complement for literal<0
3744 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3745 emitcode ("cpl", "a");
3746 emitcode ("inc", "a");
3749 lbl=newiTempLabel(NULL);
3750 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3751 // right side is negative, 8-bit two's complement
3752 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3753 emitcode ("cpl", "a");
3754 emitcode ("inc", "a");
3755 emitcode ("", "%05d$:", lbl->key+100);
3757 emitcode ("mul", "ab");
3759 lbl=newiTempLabel(NULL);
3760 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3761 // only ONE op was negative, we have to do a 8/16-bit two's complement
3762 emitcode ("cpl", "a"); // lsb
3764 emitcode ("inc", "a");
3766 emitcode ("add", "a,#1");
3767 emitcode ("xch", "a,b");
3768 emitcode ("cpl", "a"); // msb
3769 emitcode ("addc", "a,#0");
3770 emitcode ("xch", "a,b");
3773 emitcode ("", "%05d$:", lbl->key+100);
3774 aopPut (AOP (result), "a", 0);
3776 aopPut (AOP (result), "b", 1);
3780 /*-----------------------------------------------------------------*/
3781 /* genMult - generates code for multiplication */
3782 /*-----------------------------------------------------------------*/
3784 genMult (iCode * ic)
3786 operand *left = IC_LEFT (ic);
3787 operand *right = IC_RIGHT (ic);
3788 operand *result = IC_RESULT (ic);
3790 D (emitcode (";", "genMult ");
3793 /* assign the amsops */
3796 /* special cases first */
3798 if (AOP_TYPE (left) == AOP_CRY &&
3799 AOP_TYPE (right) == AOP_CRY)
3801 genMultbits (left, right, result);
3805 /* if both are of size == 1 */
3806 if (AOP_SIZE (left) == 1 &&
3807 AOP_SIZE (right) == 1)
3809 genMultOneByte (left, right, result);
3813 /* should have been converted to function call */
3817 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3818 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3819 freeAsmop (result, NULL, ic, TRUE);
3822 /*-----------------------------------------------------------------*/
3823 /* genDivbits :- division of bits */
3824 /*-----------------------------------------------------------------*/
3826 genDivbits (operand * left,
3833 /* the result must be bit */
3834 LOAD_AB_FOR_DIV (left, right, l);
3835 emitcode ("div", "ab");
3836 emitcode ("rrc", "a");
3837 aopPut (AOP (result), "c", 0);
3840 /*-----------------------------------------------------------------*/
3841 /* genDivOneByte : 8 bit division */
3842 /*-----------------------------------------------------------------*/
3844 genDivOneByte (operand * left,
3848 sym_link *opetype = operandType (result);
3853 size = AOP_SIZE (result) - 1;
3855 /* signed or unsigned */
3856 if (SPEC_USIGN (opetype))
3858 /* unsigned is easy */
3859 LOAD_AB_FOR_DIV (left, right, l);
3860 emitcode ("div", "ab");
3861 aopPut (AOP (result), "a", 0);
3863 aopPut (AOP (result), zero, offset++);
3867 /* signed is a little bit more difficult */
3869 /* save the signs of the operands */
3870 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3872 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3873 emitcode ("push", "acc"); /* save it on the stack */
3875 /* now sign adjust for both left & right */
3876 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3878 lbl = newiTempLabel (NULL);
3879 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3880 emitcode ("cpl", "a");
3881 emitcode ("inc", "a");
3882 emitcode ("", "%05d$:", (lbl->key + 100));
3883 emitcode ("mov", "b,a");
3885 /* sign adjust left side */
3886 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3889 lbl = newiTempLabel (NULL);
3890 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3891 emitcode ("cpl", "a");
3892 emitcode ("inc", "a");
3893 emitcode ("", "%05d$:", (lbl->key + 100));
3895 /* now the division */
3896 emitcode ("nop", "; workaround for DS80C390 div bug.");
3897 emitcode ("div", "ab");
3898 /* we are interested in the lower order
3900 emitcode ("mov", "b,a");
3901 lbl = newiTempLabel (NULL);
3902 emitcode ("pop", "acc");
3903 /* if there was an over flow we don't
3904 adjust the sign of the result */
3905 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3906 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3908 emitcode ("clr", "a");
3909 emitcode ("subb", "a,b");
3910 emitcode ("mov", "b,a");
3911 emitcode ("", "%05d$:", (lbl->key + 100));
3913 /* now we are done */
3914 aopPut (AOP (result), "b", 0);
3917 emitcode ("mov", "c,b.7");
3918 emitcode ("subb", "a,acc");
3921 aopPut (AOP (result), "a", offset++);
3925 /*-----------------------------------------------------------------*/
3926 /* genDiv - generates code for division */
3927 /*-----------------------------------------------------------------*/
3931 operand *left = IC_LEFT (ic);
3932 operand *right = IC_RIGHT (ic);
3933 operand *result = IC_RESULT (ic);
3935 D (emitcode (";", "genDiv ");
3938 /* assign the amsops */
3941 /* special cases first */
3943 if (AOP_TYPE (left) == AOP_CRY &&
3944 AOP_TYPE (right) == AOP_CRY)
3946 genDivbits (left, right, result);
3950 /* if both are of size == 1 */
3951 if (AOP_SIZE (left) == 1 &&
3952 AOP_SIZE (right) == 1)
3954 genDivOneByte (left, right, result);
3958 /* should have been converted to function call */
3961 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3962 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3963 freeAsmop (result, NULL, ic, TRUE);
3966 /*-----------------------------------------------------------------*/
3967 /* genModbits :- modulus of bits */
3968 /*-----------------------------------------------------------------*/
3970 genModbits (operand * left,
3977 /* the result must be bit */
3978 LOAD_AB_FOR_DIV (left, right, l);
3979 emitcode ("div", "ab");
3980 emitcode ("mov", "a,b");
3981 emitcode ("rrc", "a");
3982 aopPut (AOP (result), "c", 0);
3985 /*-----------------------------------------------------------------*/
3986 /* genModOneByte : 8 bit modulus */
3987 /*-----------------------------------------------------------------*/
3989 genModOneByte (operand * left,
3993 sym_link *opetype = operandType (result);
3997 /* signed or unsigned */
3998 if (SPEC_USIGN (opetype))
4000 /* unsigned is easy */
4001 LOAD_AB_FOR_DIV (left, right, l);
4002 emitcode ("div", "ab");
4003 aopPut (AOP (result), "b", 0);
4007 /* signed is a little bit more difficult */
4009 /* save the signs of the operands */
4010 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4013 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4014 emitcode ("push", "acc"); /* save it on the stack */
4016 /* now sign adjust for both left & right */
4017 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4020 lbl = newiTempLabel (NULL);
4021 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4022 emitcode ("cpl", "a");
4023 emitcode ("inc", "a");
4024 emitcode ("", "%05d$:", (lbl->key + 100));
4025 emitcode ("mov", "b,a");
4027 /* sign adjust left side */
4028 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4031 lbl = newiTempLabel (NULL);
4032 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4033 emitcode ("cpl", "a");
4034 emitcode ("inc", "a");
4035 emitcode ("", "%05d$:", (lbl->key + 100));
4037 /* now the multiplication */
4038 emitcode ("nop", "; workaround for DS80C390 div bug.");
4039 emitcode ("div", "ab");
4040 /* we are interested in the lower order
4042 lbl = newiTempLabel (NULL);
4043 emitcode ("pop", "acc");
4044 /* if there was an over flow we don't
4045 adjust the sign of the result */
4046 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4047 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4049 emitcode ("clr", "a");
4050 emitcode ("subb", "a,b");
4051 emitcode ("mov", "b,a");
4052 emitcode ("", "%05d$:", (lbl->key + 100));
4054 /* now we are done */
4055 aopPut (AOP (result), "b", 0);
4059 /*-----------------------------------------------------------------*/
4060 /* genMod - generates code for division */
4061 /*-----------------------------------------------------------------*/
4065 operand *left = IC_LEFT (ic);
4066 operand *right = IC_RIGHT (ic);
4067 operand *result = IC_RESULT (ic);
4069 D (emitcode (";", "genMod ");
4072 /* assign the amsops */
4075 /* special cases first */
4077 if (AOP_TYPE (left) == AOP_CRY &&
4078 AOP_TYPE (right) == AOP_CRY)
4080 genModbits (left, right, result);
4084 /* if both are of size == 1 */
4085 if (AOP_SIZE (left) == 1 &&
4086 AOP_SIZE (right) == 1)
4088 genModOneByte (left, right, result);
4092 /* should have been converted to function call */
4096 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4097 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4098 freeAsmop (result, NULL, ic, TRUE);
4101 /*-----------------------------------------------------------------*/
4102 /* genIfxJump :- will create a jump depending on the ifx */
4103 /*-----------------------------------------------------------------*/
4105 genIfxJump (iCode * ic, char *jval)
4108 symbol *tlbl = newiTempLabel (NULL);
4111 D (emitcode (";", "genIfxJump ");
4114 /* if true label then we jump if condition
4118 jlbl = IC_TRUE (ic);
4119 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4120 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4124 /* false label is present */
4125 jlbl = IC_FALSE (ic);
4126 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4127 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4129 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4130 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4132 emitcode (inst, "%05d$", tlbl->key + 100);
4133 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4134 emitcode ("", "%05d$:", tlbl->key + 100);
4136 /* mark the icode as generated */
4140 /*-----------------------------------------------------------------*/
4141 /* genCmp :- greater or less than comparison */
4142 /*-----------------------------------------------------------------*/
4144 genCmp (operand * left, operand * right,
4145 iCode * ic, iCode * ifx, int sign)
4147 int size, offset = 0;
4148 unsigned long lit = 0L;
4151 D (emitcode (";", "genCmp");
4154 result = IC_RESULT (ic);
4156 /* if left & right are bit variables */
4157 if (AOP_TYPE (left) == AOP_CRY &&
4158 AOP_TYPE (right) == AOP_CRY)
4160 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4161 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4165 /* subtract right from left if at the
4166 end the carry flag is set then we know that
4167 left is greater than right */
4168 size = max (AOP_SIZE (left), AOP_SIZE (right));
4170 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4171 if ((size == 1) && !sign &&
4172 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4174 symbol *lbl = newiTempLabel (NULL);
4175 emitcode ("cjne", "%s,%s,%05d$",
4176 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4177 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4179 emitcode ("", "%05d$:", lbl->key + 100);
4183 if (AOP_TYPE (right) == AOP_LIT)
4185 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4186 /* optimize if(x < 0) or if(x >= 0) */
4195 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4197 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4198 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4200 aopOp (result, ic, FALSE, FALSE);
4202 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4204 freeAsmop (result, NULL, ic, TRUE);
4205 genIfxJump (ifx, "acc.7");
4210 emitcode ("rlc", "a");
4212 goto release_freedLR;
4220 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4221 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4222 emitcode (";", "genCmp #2");
4223 if (sign && (size == 0))
4225 emitcode (";", "genCmp #3");
4226 emitcode ("xrl", "a,#0x80");
4227 if (AOP_TYPE (right) == AOP_LIT)
4229 unsigned long lit = (unsigned long)
4230 floatFromVal (AOP (right)->aopu.aop_lit);
4231 emitcode (";", "genCmp #3.1");
4232 emitcode ("subb", "a,#0x%02x",
4233 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4237 emitcode (";", "genCmp #3.2");
4238 if (AOP_NEEDSACC (right))
4240 emitcode ("push", "acc");
4242 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4243 FALSE, FALSE, FALSE));
4244 emitcode ("xrl", "b,#0x80");
4245 if (AOP_NEEDSACC (right))
4247 emitcode ("pop", "acc");
4249 emitcode ("subb", "a,b");
4256 emitcode (";", "genCmp #4");
4257 if (AOP_NEEDSACC (right))
4260 emitcode (";", "genCmp #4.1");
4261 emitcode ("xch", "a, b");
4262 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4263 emitcode ("xch", "a, b");
4268 emitcode (";", "genCmp #4.2");
4269 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4272 emitcode ("subb", "a,%s", s);
4279 /* Don't need the left & right operands any more; do need the result. */
4280 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4281 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4283 aopOp (result, ic, FALSE, FALSE);
4287 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4293 /* if the result is used in the next
4294 ifx conditional branch then generate
4295 code a little differently */
4298 genIfxJump (ifx, "c");
4304 /* leave the result in acc */
4306 freeAsmop (result, NULL, ic, TRUE);
4309 /*-----------------------------------------------------------------*/
4310 /* genCmpGt :- greater than comparison */
4311 /*-----------------------------------------------------------------*/
4313 genCmpGt (iCode * ic, iCode * ifx)
4315 operand *left, *right;
4316 sym_link *letype, *retype;
4319 D (emitcode (";", "genCmpGt ");
4322 left = IC_LEFT (ic);
4323 right = IC_RIGHT (ic);
4325 letype = getSpec (operandType (left));
4326 retype = getSpec (operandType (right));
4327 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4329 /* assign the left & right amsops */
4332 genCmp (right, left, ic, ifx, sign);
4335 /*-----------------------------------------------------------------*/
4336 /* genCmpLt - less than comparisons */
4337 /*-----------------------------------------------------------------*/
4339 genCmpLt (iCode * ic, iCode * ifx)
4341 operand *left, *right;
4342 sym_link *letype, *retype;
4345 D (emitcode (";", "genCmpLt ");
4348 left = IC_LEFT (ic);
4349 right = IC_RIGHT (ic);
4351 letype = getSpec (operandType (left));
4352 retype = getSpec (operandType (right));
4353 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4355 /* assign the left & right amsops */
4358 genCmp (left, right, ic, ifx, sign);
4361 /*-----------------------------------------------------------------*/
4362 /* gencjneshort - compare and jump if not equal */
4363 /*-----------------------------------------------------------------*/
4365 gencjneshort (operand * left, operand * right, symbol * lbl)
4367 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4369 unsigned long lit = 0L;
4371 D (emitcode (";", "gencjneshort");
4374 /* if the left side is a literal or
4375 if the right is in a pointer register and left
4377 if ((AOP_TYPE (left) == AOP_LIT) ||
4378 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4385 if (AOP_TYPE (right) == AOP_LIT)
4386 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4388 if (opIsGptr (left) || opIsGptr (right))
4390 /* We are comparing a generic pointer to something.
4391 * Exclude the generic type byte from the comparison.
4394 D (emitcode (";", "cjneshort: generic ptr special case.");
4399 /* if the right side is a literal then anything goes */
4400 if (AOP_TYPE (right) == AOP_LIT &&
4401 AOP_TYPE (left) != AOP_DIR)
4405 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4407 emitcode ("cjne", "a,%s,%05d$",
4408 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4414 /* if the right side is in a register or in direct space or
4415 if the left is a pointer register & right is not */
4416 else if (AOP_TYPE (right) == AOP_REG ||
4417 AOP_TYPE (right) == AOP_DIR ||
4418 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4419 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4423 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4424 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4425 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4426 emitcode ("jnz", "%05d$", lbl->key + 100);
4428 emitcode ("cjne", "a,%s,%05d$",
4429 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4436 /* right is a pointer reg need both a & b */
4439 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4440 if (strcmp (l, "b"))
4441 emitcode ("mov", "b,%s", l);
4442 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4443 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4449 /*-----------------------------------------------------------------*/
4450 /* gencjne - compare and jump if not equal */
4451 /*-----------------------------------------------------------------*/
4453 gencjne (operand * left, operand * right, symbol * lbl)
4455 symbol *tlbl = newiTempLabel (NULL);
4457 D (emitcode (";", "gencjne");
4460 gencjneshort (left, right, lbl);
4462 emitcode ("mov", "a,%s", one);
4463 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4464 emitcode ("", "%05d$:", lbl->key + 100);
4465 emitcode ("clr", "a");
4466 emitcode ("", "%05d$:", tlbl->key + 100);
4469 /*-----------------------------------------------------------------*/
4470 /* genCmpEq - generates code for equal to */
4471 /*-----------------------------------------------------------------*/
4473 genCmpEq (iCode * ic, iCode * ifx)
4475 operand *left, *right, *result;
4477 D (emitcode (";", "genCmpEq ");
4481 AOP_SET_LOCALS (ic);
4483 /* if literal, literal on the right or
4484 if the right is in a pointer register and left
4486 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4487 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4489 operand *t = IC_RIGHT (ic);
4490 IC_RIGHT (ic) = IC_LEFT (ic);
4494 if (ifx && /* !AOP_SIZE(result) */
4495 OP_SYMBOL (result) &&
4496 OP_SYMBOL (result)->regType == REG_CND)
4499 /* if they are both bit variables */
4500 if (AOP_TYPE (left) == AOP_CRY &&
4501 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4503 if (AOP_TYPE (right) == AOP_LIT)
4505 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4508 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4509 emitcode ("cpl", "c");
4513 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4517 emitcode ("clr", "c");
4519 /* AOP_TYPE(right) == AOP_CRY */
4523 symbol *lbl = newiTempLabel (NULL);
4524 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4525 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4526 emitcode ("cpl", "c");
4527 emitcode ("", "%05d$:", (lbl->key + 100));
4529 /* if true label then we jump if condition
4531 tlbl = newiTempLabel (NULL);
4534 emitcode ("jnc", "%05d$", tlbl->key + 100);
4535 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4539 emitcode ("jc", "%05d$", tlbl->key + 100);
4540 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4542 emitcode ("", "%05d$:", tlbl->key + 100);
4546 tlbl = newiTempLabel (NULL);
4547 gencjneshort (left, right, tlbl);
4550 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4551 emitcode ("", "%05d$:", tlbl->key + 100);
4555 symbol *lbl = newiTempLabel (NULL);
4556 emitcode ("sjmp", "%05d$", lbl->key + 100);
4557 emitcode ("", "%05d$:", tlbl->key + 100);
4558 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4559 emitcode ("", "%05d$:", lbl->key + 100);
4562 /* mark the icode as generated */
4565 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4570 /* if they are both bit variables */
4571 if (AOP_TYPE (left) == AOP_CRY &&
4572 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4574 if (AOP_TYPE (right) == AOP_LIT)
4576 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4579 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4580 emitcode ("cpl", "c");
4584 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4588 emitcode ("clr", "c");
4590 /* AOP_TYPE(right) == AOP_CRY */
4594 symbol *lbl = newiTempLabel (NULL);
4595 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4596 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4597 emitcode ("cpl", "c");
4598 emitcode ("", "%05d$:", (lbl->key + 100));
4601 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4602 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604 aopOp (result, ic, TRUE, FALSE);
4607 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4614 genIfxJump (ifx, "c");
4617 /* if the result is used in an arithmetic operation
4618 then put the result in place */
4623 gencjne (left, right, newiTempLabel (NULL));
4625 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4626 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4628 aopOp (result, ic, TRUE, FALSE);
4630 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4632 aopPut (AOP (result), "a", 0);
4637 genIfxJump (ifx, "a");
4640 /* if the result is used in an arithmetic operation
4641 then put the result in place */
4642 if (AOP_TYPE (result) != AOP_CRY)
4644 /* leave the result in acc */
4648 freeAsmop (result, NULL, ic, TRUE);
4651 /*-----------------------------------------------------------------*/
4652 /* ifxForOp - returns the icode containing the ifx for operand */
4653 /*-----------------------------------------------------------------*/
4655 ifxForOp (operand * op, iCode * ic)
4657 /* if true symbol then needs to be assigned */
4658 if (IS_TRUE_SYMOP (op))
4661 /* if this has register type condition and
4662 the next instruction is ifx with the same operand
4663 and live to of the operand is upto the ifx only then */
4665 ic->next->op == IFX &&
4666 IC_COND (ic->next)->key == op->key &&
4667 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4672 /*-----------------------------------------------------------------*/
4673 /* genAndOp - for && operation */
4674 /*-----------------------------------------------------------------*/
4676 genAndOp (iCode * ic)
4678 operand *left, *right, *result;
4681 D (emitcode (";", "genAndOp ");
4684 /* note here that && operations that are in an
4685 if statement are taken away by backPatchLabels
4686 only those used in arthmetic operations remain */
4688 AOP_SET_LOCALS (ic);
4690 /* if both are bit variables */
4691 if (AOP_TYPE (left) == AOP_CRY &&
4692 AOP_TYPE (right) == AOP_CRY)
4694 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4695 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4700 tlbl = newiTempLabel (NULL);
4702 emitcode ("jz", "%05d$", tlbl->key + 100);
4704 emitcode ("", "%05d$:", tlbl->key + 100);
4708 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4709 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4710 freeAsmop (result, NULL, ic, TRUE);
4714 /*-----------------------------------------------------------------*/
4715 /* genOrOp - for || operation */
4716 /*-----------------------------------------------------------------*/
4718 genOrOp (iCode * ic)
4720 operand *left, *right, *result;
4723 D (emitcode (";", "genOrOp ");
4726 /* note here that || operations that are in an
4727 if statement are taken away by backPatchLabels
4728 only those used in arthmetic operations remain */
4730 AOP_SET_LOCALS (ic);
4732 /* if both are bit variables */
4733 if (AOP_TYPE (left) == AOP_CRY &&
4734 AOP_TYPE (right) == AOP_CRY)
4736 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4737 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4742 tlbl = newiTempLabel (NULL);
4744 emitcode ("jnz", "%05d$", tlbl->key + 100);
4746 emitcode ("", "%05d$:", tlbl->key + 100);
4750 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4751 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4752 freeAsmop (result, NULL, ic, TRUE);
4755 /*-----------------------------------------------------------------*/
4756 /* isLiteralBit - test if lit == 2^n */
4757 /*-----------------------------------------------------------------*/
4759 isLiteralBit (unsigned long lit)
4761 unsigned long pw[32] =
4762 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4763 0x100L, 0x200L, 0x400L, 0x800L,
4764 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4765 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4766 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4767 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4768 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4771 for (idx = 0; idx < 32; idx++)
4777 /*-----------------------------------------------------------------*/
4778 /* continueIfTrue - */
4779 /*-----------------------------------------------------------------*/
4781 continueIfTrue (iCode * ic)
4784 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4788 /*-----------------------------------------------------------------*/
4790 /*-----------------------------------------------------------------*/
4792 jumpIfTrue (iCode * ic)
4795 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4799 /*-----------------------------------------------------------------*/
4800 /* jmpTrueOrFalse - */
4801 /*-----------------------------------------------------------------*/
4803 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4805 // ugly but optimized by peephole
4808 symbol *nlbl = newiTempLabel (NULL);
4809 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4810 emitcode ("", "%05d$:", tlbl->key + 100);
4811 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4812 emitcode ("", "%05d$:", nlbl->key + 100);
4816 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4817 emitcode ("", "%05d$:", tlbl->key + 100);
4822 /*-----------------------------------------------------------------*/
4823 /* genAnd - code for and */
4824 /*-----------------------------------------------------------------*/
4826 genAnd (iCode * ic, iCode * ifx)
4828 operand *left, *right, *result;
4829 int size, offset = 0;
4830 unsigned long lit = 0L;
4834 D (emitcode (";", "genAnd ");
4838 AOP_SET_LOCALS (ic);
4841 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4843 AOP_TYPE (left), AOP_TYPE (right));
4844 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4846 AOP_SIZE (left), AOP_SIZE (right));
4849 /* if left is a literal & right is not then exchange them */
4850 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4851 AOP_NEEDSACC (left))
4853 operand *tmp = right;
4858 /* if result = right then exchange them */
4859 if (sameRegs (AOP (result), AOP (right)))
4861 operand *tmp = right;
4866 /* if right is bit then exchange them */
4867 if (AOP_TYPE (right) == AOP_CRY &&
4868 AOP_TYPE (left) != AOP_CRY)
4870 operand *tmp = right;
4874 if (AOP_TYPE (right) == AOP_LIT)
4875 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4877 size = AOP_SIZE (result);
4880 // result = bit & yy;
4881 if (AOP_TYPE (left) == AOP_CRY)
4883 // c = bit & literal;
4884 if (AOP_TYPE (right) == AOP_LIT)
4888 if (size && sameRegs (AOP (result), AOP (left)))
4891 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4896 if (size && (AOP_TYPE (result) == AOP_CRY))
4898 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4901 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4906 emitcode ("clr", "c");
4911 if (AOP_TYPE (right) == AOP_CRY)
4914 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4915 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4920 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4922 emitcode ("rrc", "a");
4923 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4931 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4932 genIfxJump (ifx, "c");
4936 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4937 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4938 if ((AOP_TYPE (right) == AOP_LIT) &&
4939 (AOP_TYPE (result) == AOP_CRY) &&
4940 (AOP_TYPE (left) != AOP_CRY))
4942 int posbit = isLiteralBit (lit);
4947 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
4950 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4956 sprintf (buffer, "acc.%d", posbit & 0x07);
4957 genIfxJump (ifx, buffer);
4964 symbol *tlbl = newiTempLabel (NULL);
4965 int sizel = AOP_SIZE (left);
4967 emitcode ("setb", "c");
4970 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4972 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4974 if ((posbit = isLiteralBit (bytelit)) != 0)
4975 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4978 if (bytelit != 0x0FFL)
4979 emitcode ("anl", "a,%s",
4980 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
4981 emitcode ("jnz", "%05d$", tlbl->key + 100);
4986 // bit = left & literal
4989 emitcode ("clr", "c");
4990 emitcode ("", "%05d$:", tlbl->key + 100);
4992 // if(left & literal)
4996 jmpTrueOrFalse (ifx, tlbl);
5004 /* if left is same as result */
5005 if (sameRegs (AOP (result), AOP (left)))
5007 for (; size--; offset++)
5009 if (AOP_TYPE (right) == AOP_LIT)
5011 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5013 else if (bytelit == 0)
5014 aopPut (AOP (result), zero, offset);
5015 else if (IS_AOP_PREG (result))
5017 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5018 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5019 aopPut (AOP (result), "a", offset);
5022 emitcode ("anl", "%s,%s",
5023 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5024 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5028 if (AOP_TYPE (left) == AOP_ACC)
5029 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5032 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5033 if (IS_AOP_PREG (result))
5035 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5036 aopPut (AOP (result), "a", offset);
5040 emitcode ("anl", "%s,a",
5041 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5048 // left & result in different registers
5049 if (AOP_TYPE (result) == AOP_CRY)
5052 // if(size), result in bit
5053 // if(!size && ifx), conditional oper: if(left & right)
5054 symbol *tlbl = newiTempLabel (NULL);
5055 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5057 emitcode ("setb", "c");
5060 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5061 emitcode ("anl", "a,%s",
5062 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5063 emitcode ("jnz", "%05d$", tlbl->key + 100);
5069 emitcode ("", "%05d$:", tlbl->key + 100);
5073 jmpTrueOrFalse (ifx, tlbl);
5077 for (; (size--); offset++)
5080 // result = left & right
5081 if (AOP_TYPE (right) == AOP_LIT)
5083 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5085 aopPut (AOP (result),
5086 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5090 else if (bytelit == 0)
5092 aopPut (AOP (result), zero, offset);
5095 D (emitcode (";", "better literal AND.");
5097 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5098 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5099 FALSE, FALSE, FALSE));
5104 // faster than result <- left, anl result,right
5105 // and better if result is SFR
5106 if (AOP_TYPE (left) == AOP_ACC)
5108 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5109 FALSE, FALSE, FALSE));
5113 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5114 emitcode ("anl", "a,%s",
5115 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5118 aopPut (AOP (result), "a", offset);
5124 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5125 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5126 freeAsmop (result, NULL, ic, TRUE);
5129 /*-----------------------------------------------------------------*/
5130 /* genOr - code for or */
5131 /*-----------------------------------------------------------------*/
5133 genOr (iCode * ic, iCode * ifx)
5135 operand *left, *right, *result;
5136 int size, offset = 0;
5137 unsigned long lit = 0L;
5139 D (emitcode (";", "genOr ");
5143 AOP_SET_LOCALS (ic);
5146 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5148 AOP_TYPE (left), AOP_TYPE (right));
5149 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5151 AOP_SIZE (left), AOP_SIZE (right));
5154 /* if left is a literal & right is not then exchange them */
5155 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5156 AOP_NEEDSACC (left))
5158 operand *tmp = right;
5163 /* if result = right then exchange them */
5164 if (sameRegs (AOP (result), AOP (right)))
5166 operand *tmp = right;
5171 /* if right is bit then exchange them */
5172 if (AOP_TYPE (right) == AOP_CRY &&
5173 AOP_TYPE (left) != AOP_CRY)
5175 operand *tmp = right;
5179 if (AOP_TYPE (right) == AOP_LIT)
5180 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5182 size = AOP_SIZE (result);
5186 if (AOP_TYPE (left) == AOP_CRY)
5188 if (AOP_TYPE (right) == AOP_LIT)
5190 // c = bit & literal;
5193 // lit != 0 => result = 1
5194 if (AOP_TYPE (result) == AOP_CRY)
5197 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5199 continueIfTrue (ifx);
5202 emitcode ("setb", "c");
5206 // lit == 0 => result = left
5207 if (size && sameRegs (AOP (result), AOP (left)))
5209 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5214 if (AOP_TYPE (right) == AOP_CRY)
5217 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5218 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5223 symbol *tlbl = newiTempLabel (NULL);
5224 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5225 emitcode ("setb", "c");
5226 emitcode ("jb", "%s,%05d$",
5227 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5229 emitcode ("jnz", "%05d$", tlbl->key + 100);
5230 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5232 jmpTrueOrFalse (ifx, tlbl);
5238 emitcode ("", "%05d$:", tlbl->key + 100);
5247 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5248 genIfxJump (ifx, "c");
5252 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5253 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5254 if ((AOP_TYPE (right) == AOP_LIT) &&
5255 (AOP_TYPE (result) == AOP_CRY) &&
5256 (AOP_TYPE (left) != AOP_CRY))
5262 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5264 continueIfTrue (ifx);
5269 // lit = 0, result = boolean(left)
5271 emitcode ("setb", "c");
5275 symbol *tlbl = newiTempLabel (NULL);
5276 emitcode ("jnz", "%05d$", tlbl->key + 100);
5278 emitcode ("", "%05d$:", tlbl->key + 100);
5282 genIfxJump (ifx, "a");
5290 /* if left is same as result */
5291 if (sameRegs (AOP (result), AOP (left)))
5293 for (; size--; offset++)
5295 if (AOP_TYPE (right) == AOP_LIT)
5297 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5303 if (IS_AOP_PREG (left))
5305 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5306 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5307 aopPut (AOP (result), "a", offset);
5311 emitcode ("orl", "%s,%s",
5312 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5313 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5319 if (AOP_TYPE (left) == AOP_ACC)
5321 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5325 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5326 if (IS_AOP_PREG (left))
5328 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5329 aopPut (AOP (result), "a", offset);
5333 emitcode ("orl", "%s,a",
5334 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5342 // left & result in different registers
5343 if (AOP_TYPE (result) == AOP_CRY)
5346 // if(size), result in bit
5347 // if(!size && ifx), conditional oper: if(left | right)
5348 symbol *tlbl = newiTempLabel (NULL);
5349 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5351 emitcode ("setb", "c");
5354 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5355 emitcode ("orl", "a,%s",
5356 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5357 emitcode ("jnz", "%05d$", tlbl->key + 100);
5363 emitcode ("", "%05d$:", tlbl->key + 100);
5367 jmpTrueOrFalse (ifx, tlbl);
5371 for (; (size--); offset++)
5374 // result = left & right
5375 if (AOP_TYPE (right) == AOP_LIT)
5377 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5379 aopPut (AOP (result),
5380 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5384 D (emitcode (";", "better literal OR.");
5386 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5387 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5388 FALSE, FALSE, FALSE));
5393 // faster than result <- left, anl result,right
5394 // and better if result is SFR
5395 if (AOP_TYPE (left) == AOP_ACC)
5397 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5398 FALSE, FALSE, FALSE));
5402 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5403 emitcode ("orl", "a,%s",
5404 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5407 aopPut (AOP (result), "a", offset);
5413 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5414 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5415 freeAsmop (result, NULL, ic, TRUE);
5418 /*-----------------------------------------------------------------*/
5419 /* genXor - code for xclusive or */
5420 /*-----------------------------------------------------------------*/
5422 genXor (iCode * ic, iCode * ifx)
5424 operand *left, *right, *result;
5425 int size, offset = 0;
5426 unsigned long lit = 0L;
5428 D (emitcode (";", "genXor ");
5432 AOP_SET_LOCALS (ic);
5435 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5437 AOP_TYPE (left), AOP_TYPE (right));
5438 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5440 AOP_SIZE (left), AOP_SIZE (right));
5443 /* if left is a literal & right is not ||
5444 if left needs acc & right does not */
5445 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5446 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5448 operand *tmp = right;
5453 /* if result = right then exchange them */
5454 if (sameRegs (AOP (result), AOP (right)))
5456 operand *tmp = right;
5461 /* if right is bit then exchange them */
5462 if (AOP_TYPE (right) == AOP_CRY &&
5463 AOP_TYPE (left) != AOP_CRY)
5465 operand *tmp = right;
5469 if (AOP_TYPE (right) == AOP_LIT)
5470 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5472 size = AOP_SIZE (result);
5476 if (AOP_TYPE (left) == AOP_CRY)
5478 if (AOP_TYPE (right) == AOP_LIT)
5480 // c = bit & literal;
5483 // lit>>1 != 0 => result = 1
5484 if (AOP_TYPE (result) == AOP_CRY)
5487 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5489 continueIfTrue (ifx);
5492 emitcode ("setb", "c");
5499 // lit == 0, result = left
5500 if (size && sameRegs (AOP (result), AOP (left)))
5502 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5506 // lit == 1, result = not(left)
5507 if (size && sameRegs (AOP (result), AOP (left)))
5509 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5514 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5515 emitcode ("cpl", "c");
5524 symbol *tlbl = newiTempLabel (NULL);
5525 if (AOP_TYPE (right) == AOP_CRY)
5528 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5532 int sizer = AOP_SIZE (right);
5534 // if val>>1 != 0, result = 1
5535 emitcode ("setb", "c");
5538 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5540 // test the msb of the lsb
5541 emitcode ("anl", "a,#0xfe");
5542 emitcode ("jnz", "%05d$", tlbl->key + 100);
5546 emitcode ("rrc", "a");
5548 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5549 emitcode ("cpl", "c");
5550 emitcode ("", "%05d$:", (tlbl->key + 100));
5557 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5558 genIfxJump (ifx, "c");
5562 if (sameRegs (AOP (result), AOP (left)))
5564 /* if left is same as result */
5565 for (; size--; offset++)
5567 if (AOP_TYPE (right) == AOP_LIT)
5569 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5571 else if (IS_AOP_PREG (left))
5573 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5574 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5575 aopPut (AOP (result), "a", offset);
5578 emitcode ("xrl", "%s,%s",
5579 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5580 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5584 if (AOP_TYPE (left) == AOP_ACC)
5585 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5588 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5589 if (IS_AOP_PREG (left))
5591 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5592 aopPut (AOP (result), "a", offset);
5595 emitcode ("xrl", "%s,a",
5596 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5603 // left & result in different registers
5604 if (AOP_TYPE (result) == AOP_CRY)
5607 // if(size), result in bit
5608 // if(!size && ifx), conditional oper: if(left ^ right)
5609 symbol *tlbl = newiTempLabel (NULL);
5610 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5612 emitcode ("setb", "c");
5615 if ((AOP_TYPE (right) == AOP_LIT) &&
5616 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5618 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5622 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5623 emitcode ("xrl", "a,%s",
5624 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5626 emitcode ("jnz", "%05d$", tlbl->key + 100);
5632 emitcode ("", "%05d$:", tlbl->key + 100);
5636 jmpTrueOrFalse (ifx, tlbl);
5639 for (; (size--); offset++)
5642 // result = left & right
5643 if (AOP_TYPE (right) == AOP_LIT)
5645 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5647 aopPut (AOP (result),
5648 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5652 D (emitcode (";", "better literal XOR.");
5654 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5655 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5656 FALSE, FALSE, FALSE));
5660 // faster than result <- left, anl result,right
5661 // and better if result is SFR
5662 if (AOP_TYPE (left) == AOP_ACC)
5664 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5665 FALSE, FALSE, FALSE));
5669 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5670 emitcode ("xrl", "a,%s",
5671 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5674 aopPut (AOP (result), "a", offset);
5679 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5680 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5681 freeAsmop (result, NULL, ic, TRUE);
5684 /*-----------------------------------------------------------------*/
5685 /* genInline - write the inline code out */
5686 /*-----------------------------------------------------------------*/
5688 genInline (iCode * ic)
5690 char buffer[MAX_INLINEASM];
5694 D (emitcode (";", "genInline ");
5697 _G.inLine += (!options.asmpeep);
5698 strcpy (buffer, IC_INLINE (ic));
5700 /* emit each line as a code */
5725 /* emitcode("",buffer); */
5726 _G.inLine -= (!options.asmpeep);
5729 /*-----------------------------------------------------------------*/
5730 /* genRRC - rotate right with carry */
5731 /*-----------------------------------------------------------------*/
5735 operand *left, *result;
5736 int size, offset = 0;
5739 D (emitcode (";", "genRRC ");
5742 /* rotate right with carry */
5743 left = IC_LEFT (ic);
5744 result = IC_RESULT (ic);
5745 aopOp (left, ic, FALSE, FALSE);
5746 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5748 /* move it to the result */
5749 size = AOP_SIZE (result);
5753 _startLazyDPSEvaluation ();
5756 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5758 emitcode ("rrc", "a");
5759 if (AOP_SIZE (result) > 1)
5760 aopPut (AOP (result), "a", offset--);
5762 _endLazyDPSEvaluation ();
5764 /* now we need to put the carry into the
5765 highest order byte of the result */
5766 if (AOP_SIZE (result) > 1)
5768 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5771 emitcode ("mov", "acc.7,c");
5772 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5773 freeAsmop (left, NULL, ic, TRUE);
5774 freeAsmop (result, NULL, ic, TRUE);
5777 /*-----------------------------------------------------------------*/
5778 /* genRLC - generate code for rotate left with carry */
5779 /*-----------------------------------------------------------------*/
5783 operand *left, *result;
5784 int size, offset = 0;
5787 D (emitcode (";", "genRLC ");
5790 /* rotate right with carry */
5791 left = IC_LEFT (ic);
5792 result = IC_RESULT (ic);
5793 aopOp (left, ic, FALSE, FALSE);
5794 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5796 /* move it to the result */
5797 size = AOP_SIZE (result);
5801 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5803 emitcode ("add", "a,acc");
5804 if (AOP_SIZE (result) > 1)
5806 aopPut (AOP (result), "a", offset++);
5809 _startLazyDPSEvaluation ();
5812 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5814 emitcode ("rlc", "a");
5815 if (AOP_SIZE (result) > 1)
5816 aopPut (AOP (result), "a", offset++);
5818 _endLazyDPSEvaluation ();
5820 /* now we need to put the carry into the
5821 highest order byte of the result */
5822 if (AOP_SIZE (result) > 1)
5824 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5827 emitcode ("mov", "acc.0,c");
5828 aopPut (AOP (result), "a", 0);
5829 freeAsmop (left, NULL, ic, TRUE);
5830 freeAsmop (result, NULL, ic, TRUE);
5833 /*-----------------------------------------------------------------*/
5834 /* genGetHbit - generates code get highest order bit */
5835 /*-----------------------------------------------------------------*/
5837 genGetHbit (iCode * ic)
5839 operand *left, *result;
5840 left = IC_LEFT (ic);
5841 result = IC_RESULT (ic);
5842 aopOp (left, ic, FALSE, FALSE);
5843 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5845 D (emitcode (";", "genGetHbit ");
5848 /* get the highest order byte into a */
5849 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5850 if (AOP_TYPE (result) == AOP_CRY)
5852 emitcode ("rlc", "a");
5857 emitcode ("rl", "a");
5858 emitcode ("anl", "a,#0x01");
5863 freeAsmop (left, NULL, ic, TRUE);
5864 freeAsmop (result, NULL, ic, TRUE);
5867 /*-----------------------------------------------------------------*/
5868 /* AccRol - rotate left accumulator by known count */
5869 /*-----------------------------------------------------------------*/
5871 AccRol (int shCount)
5873 shCount &= 0x0007; // shCount : 0..7
5880 emitcode ("rl", "a");
5883 emitcode ("rl", "a");
5884 emitcode ("rl", "a");
5887 emitcode ("swap", "a");
5888 emitcode ("rr", "a");
5891 emitcode ("swap", "a");
5894 emitcode ("swap", "a");
5895 emitcode ("rl", "a");
5898 emitcode ("rr", "a");
5899 emitcode ("rr", "a");
5902 emitcode ("rr", "a");
5907 /*-----------------------------------------------------------------*/
5908 /* AccLsh - left shift accumulator by known count */
5909 /*-----------------------------------------------------------------*/
5911 AccLsh (int shCount)
5916 emitcode ("add", "a,acc");
5917 else if (shCount == 2)
5919 emitcode ("add", "a,acc");
5920 emitcode ("add", "a,acc");
5924 /* rotate left accumulator */
5926 /* and kill the lower order bits */
5927 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5932 /*-----------------------------------------------------------------*/
5933 /* AccRsh - right shift accumulator by known count */
5934 /*-----------------------------------------------------------------*/
5936 AccRsh (int shCount)
5943 emitcode ("rrc", "a");
5947 /* rotate right accumulator */
5948 AccRol (8 - shCount);
5949 /* and kill the higher order bits */
5950 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5957 /*-----------------------------------------------------------------*/
5958 /* AccSRsh - signed right shift accumulator by known count */
5959 /*-----------------------------------------------------------------*/
5961 AccSRsh (int shCount)
5968 emitcode ("mov", "c,acc.7");
5969 emitcode ("rrc", "a");
5971 else if (shCount == 2)
5973 emitcode ("mov", "c,acc.7");
5974 emitcode ("rrc", "a");
5975 emitcode ("mov", "c,acc.7");
5976 emitcode ("rrc", "a");
5980 tlbl = newiTempLabel (NULL);
5981 /* rotate right accumulator */
5982 AccRol (8 - shCount);
5983 /* and kill the higher order bits */
5984 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5985 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5986 emitcode ("orl", "a,#0x%02x",
5987 (unsigned char) ~SRMask[shCount]);
5988 emitcode ("", "%05d$:", tlbl->key + 100);
5996 /*-----------------------------------------------------------------*/
5997 /* shiftR1Left2Result - shift right one byte from left to result */
5998 /*-----------------------------------------------------------------*/
6000 shiftR1Left2Result (operand * left, int offl,
6001 operand * result, int offr,
6002 int shCount, int sign)
6004 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6005 /* shift right accumulator */
6010 aopPut (AOP (result), "a", offr);
6016 /*-----------------------------------------------------------------*/
6017 /* shiftL1Left2Result - shift left one byte from left to result */
6018 /*-----------------------------------------------------------------*/
6020 shiftL1Left2Result (operand * left, int offl,
6021 operand * result, int offr, int shCount)
6024 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6026 /* shift left accumulator */
6028 aopPut (AOP (result), "a", offr);
6034 /*-----------------------------------------------------------------*/
6035 /* movLeft2Result - move byte from left to result */
6036 /*-----------------------------------------------------------------*/
6038 movLeft2Result (operand * left, int offl,
6039 operand * result, int offr, int sign)
6042 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6044 l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
6046 if (*l == '@' && (IS_AOP_PREG (result)))
6048 emitcode ("mov", "a,%s", l);
6049 aopPut (AOP (result), "a", offr);
6054 aopPut (AOP (result), l, offr);
6057 /* MSB sign in acc.7 ! */
6058 if (getDataSize (left) == offl + 1)
6060 emitcode ("mov", "a,%s", l);
6061 aopPut (AOP (result), "a", offr);
6071 /*-----------------------------------------------------------------*/
6072 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6073 /*-----------------------------------------------------------------*/
6077 emitcode ("rrc", "a");
6078 emitcode ("xch", "a,%s", x);
6079 emitcode ("rrc", "a");
6080 emitcode ("xch", "a,%s", x);
6086 /*-----------------------------------------------------------------*/
6087 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6088 /*-----------------------------------------------------------------*/
6092 emitcode ("xch", "a,%s", x);
6093 emitcode ("rlc", "a");
6094 emitcode ("xch", "a,%s", x);
6095 emitcode ("rlc", "a");
6101 /*-----------------------------------------------------------------*/
6102 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6103 /*-----------------------------------------------------------------*/
6107 emitcode ("xch", "a,%s", x);
6108 emitcode ("add", "a,acc");
6109 emitcode ("xch", "a,%s", x);
6110 emitcode ("rlc", "a");
6116 /*-----------------------------------------------------------------*/
6117 /* AccAXLsh - left shift a:x by known count (0..7) */
6118 /*-----------------------------------------------------------------*/
6120 AccAXLsh (char *x, int shCount)
6135 case 5: // AAAAABBB:CCCCCDDD
6137 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6139 emitcode ("anl", "a,#0x%02x",
6140 SLMask[shCount]); // BBB00000:CCCCCDDD
6142 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6144 AccRol (shCount); // DDDCCCCC:BBB00000
6146 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6148 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6150 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6152 emitcode ("anl", "a,#0x%02x",
6153 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6155 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6157 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6160 case 6: // AAAAAABB:CCCCCCDD
6161 emitcode ("anl", "a,#0x%02x",
6162 SRMask[shCount]); // 000000BB:CCCCCCDD
6163 emitcode ("mov", "c,acc.0"); // c = B
6164 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6166 AccAXRrl1 (x); // BCCCCCCD:D000000B
6167 AccAXRrl1 (x); // BBCCCCCC:DD000000
6169 emitcode("rrc","a");
6170 emitcode("xch","a,%s", x);
6171 emitcode("rrc","a");
6172 emitcode("mov","c,acc.0"); //<< get correct bit
6173 emitcode("xch","a,%s", x);
6175 emitcode("rrc","a");
6176 emitcode("xch","a,%s", x);
6177 emitcode("rrc","a");
6178 emitcode("xch","a,%s", x);
6181 case 7: // a:x <<= 7
6183 emitcode ("anl", "a,#0x%02x",
6184 SRMask[shCount]); // 0000000B:CCCCCCCD
6186 emitcode ("mov", "c,acc.0"); // c = B
6188 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6190 AccAXRrl1 (x); // BCCCCCCC:D0000000
6201 /*-----------------------------------------------------------------*/
6202 /* AccAXRsh - right shift a:x known count (0..7) */
6203 /*-----------------------------------------------------------------*/
6205 AccAXRsh (char *x, int shCount)
6213 AccAXRrl1 (x); // 0->a:x
6218 AccAXRrl1 (x); // 0->a:x
6221 AccAXRrl1 (x); // 0->a:x
6226 case 5: // AAAAABBB:CCCCCDDD = a:x
6228 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6230 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6232 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6234 emitcode ("anl", "a,#0x%02x",
6235 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6237 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6239 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6241 emitcode ("anl", "a,#0x%02x",
6242 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6244 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6246 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6248 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6251 case 6: // AABBBBBB:CCDDDDDD
6253 emitcode ("mov", "c,acc.7");
6254 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6256 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6258 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6260 emitcode ("anl", "a,#0x%02x",
6261 SRMask[shCount]); // 000000AA:BBBBBBCC
6264 case 7: // ABBBBBBB:CDDDDDDD
6266 emitcode ("mov", "c,acc.7"); // c = A
6268 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6270 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6272 emitcode ("anl", "a,#0x%02x",
6273 SRMask[shCount]); // 0000000A:BBBBBBBC
6284 /*-----------------------------------------------------------------*/
6285 /* AccAXRshS - right shift signed a:x known count (0..7) */
6286 /*-----------------------------------------------------------------*/
6288 AccAXRshS (char *x, int shCount)
6296 emitcode ("mov", "c,acc.7");
6297 AccAXRrl1 (x); // s->a:x
6301 emitcode ("mov", "c,acc.7");
6302 AccAXRrl1 (x); // s->a:x
6304 emitcode ("mov", "c,acc.7");
6305 AccAXRrl1 (x); // s->a:x
6310 case 5: // AAAAABBB:CCCCCDDD = a:x
6312 tlbl = newiTempLabel (NULL);
6313 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6315 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6317 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6319 emitcode ("anl", "a,#0x%02x",
6320 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6322 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6324 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6326 emitcode ("anl", "a,#0x%02x",
6327 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6329 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6331 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6333 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6335 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6336 emitcode ("orl", "a,#0x%02x",
6337 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6339 emitcode ("", "%05d$:", tlbl->key + 100);
6340 break; // SSSSAAAA:BBBCCCCC
6342 case 6: // AABBBBBB:CCDDDDDD
6344 tlbl = newiTempLabel (NULL);
6345 emitcode ("mov", "c,acc.7");
6346 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6348 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6350 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6352 emitcode ("anl", "a,#0x%02x",
6353 SRMask[shCount]); // 000000AA:BBBBBBCC
6355 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6356 emitcode ("orl", "a,#0x%02x",
6357 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6359 emitcode ("", "%05d$:", tlbl->key + 100);
6361 case 7: // ABBBBBBB:CDDDDDDD
6363 tlbl = newiTempLabel (NULL);
6364 emitcode ("mov", "c,acc.7"); // c = A
6366 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6368 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6370 emitcode ("anl", "a,#0x%02x",
6371 SRMask[shCount]); // 0000000A:BBBBBBBC
6373 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6374 emitcode ("orl", "a,#0x%02x",
6375 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6377 emitcode ("", "%05d$:", tlbl->key + 100);
6387 /*-----------------------------------------------------------------*/
6388 /* shiftL2Left2Result - shift left two bytes from left to result */
6389 /*-----------------------------------------------------------------*/
6391 shiftL2Left2Result (operand * left, int offl,
6392 operand * result, int offr, int shCount)
6394 if (sameRegs (AOP (result), AOP (left)) &&
6395 ((offl + MSB16) == offr))
6397 /* don't crash result[offr] */
6398 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6399 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6403 movLeft2Result (left, offl, result, offr, 0);
6404 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6406 /* ax << shCount (x = lsb(result)) */
6407 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6408 aopPut (AOP (result), "a", offr + MSB16);
6414 /*-----------------------------------------------------------------*/
6415 /* shiftR2Left2Result - shift right two bytes from left to result */
6416 /*-----------------------------------------------------------------*/
6418 shiftR2Left2Result (operand * left, int offl,
6419 operand * result, int offr,
6420 int shCount, int sign)
6422 if (sameRegs (AOP (result), AOP (left)) &&
6423 ((offl + MSB16) == offr))
6425 /* don't crash result[offr] */
6426 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6427 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6431 movLeft2Result (left, offl, result, offr, 0);
6432 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6434 /* a:x >> shCount (x = lsb(result)) */
6436 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6438 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6439 if (getDataSize (result) > 1)
6440 aopPut (AOP (result), "a", offr + MSB16);
6446 /*-----------------------------------------------------------------*/
6447 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6448 /*-----------------------------------------------------------------*/
6450 shiftLLeftOrResult (operand * left, int offl,
6451 operand * result, int offr, int shCount)
6453 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6454 /* shift left accumulator */
6456 /* or with result */
6457 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6458 /* back to result */
6459 aopPut (AOP (result), "a", offr);
6465 /*-----------------------------------------------------------------*/
6466 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6467 /*-----------------------------------------------------------------*/
6469 shiftRLeftOrResult (operand * left, int offl,
6470 operand * result, int offr, int shCount)
6472 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6473 /* shift right accumulator */
6475 /* or with result */
6476 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6477 /* back to result */
6478 aopPut (AOP (result), "a", offr);
6484 /*-----------------------------------------------------------------*/
6485 /* genlshOne - left shift a one byte quantity by known count */
6486 /*-----------------------------------------------------------------*/
6488 genlshOne (operand * result, operand * left, int shCount)
6490 D (emitcode (";", "genlshOne ");
6492 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6498 /*-----------------------------------------------------------------*/
6499 /* genlshTwo - left shift two bytes by known amount != 0 */
6500 /*-----------------------------------------------------------------*/
6502 genlshTwo (operand * result, operand * left, int shCount)
6506 D (emitcode (";", "genlshTwo ");
6509 size = getDataSize (result);
6511 /* if shCount >= 8 */
6519 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6521 movLeft2Result (left, LSB, result, MSB16, 0);
6523 aopPut (AOP (result), zero, LSB);
6526 /* 1 <= shCount <= 7 */
6530 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6532 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6539 /*-----------------------------------------------------------------*/
6540 /* shiftLLong - shift left one long from left to result */
6541 /* offl = LSB or MSB16 */
6542 /*-----------------------------------------------------------------*/
6544 shiftLLong (operand * left, operand * result, int offr)
6547 int size = AOP_SIZE (result);
6549 if (size >= LSB + offr)
6551 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6553 emitcode ("add", "a,acc");
6554 if (sameRegs (AOP (left), AOP (result)) &&
6555 size >= MSB16 + offr && offr != LSB)
6556 emitcode ("xch", "a,%s",
6557 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6559 aopPut (AOP (result), "a", LSB + offr);
6562 if (size >= MSB16 + offr)
6564 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6566 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6569 emitcode ("rlc", "a");
6570 if (sameRegs (AOP (left), AOP (result)) &&
6571 size >= MSB24 + offr && offr != LSB)
6572 emitcode ("xch", "a,%s",
6573 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6575 aopPut (AOP (result), "a", MSB16 + offr);
6578 if (size >= MSB24 + offr)
6580 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6582 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6585 emitcode ("rlc", "a");
6586 if (sameRegs (AOP (left), AOP (result)) &&
6587 size >= MSB32 + offr && offr != LSB)
6588 emitcode ("xch", "a,%s",
6589 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6591 aopPut (AOP (result), "a", MSB24 + offr);
6594 if (size > MSB32 + offr)
6596 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6598 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6601 emitcode ("rlc", "a");
6602 aopPut (AOP (result), "a", MSB32 + offr);
6605 aopPut (AOP (result), zero, LSB);
6611 /*-----------------------------------------------------------------*/
6612 /* genlshFour - shift four byte by a known amount != 0 */
6613 /*-----------------------------------------------------------------*/
6615 genlshFour (operand * result, operand * left, int shCount)
6619 D (emitcode (";", "genlshFour ");
6622 size = AOP_SIZE (result);
6624 /* if shifting more that 3 bytes */
6629 /* lowest order of left goes to the highest
6630 order of the destination */
6631 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6633 movLeft2Result (left, LSB, result, MSB32, 0);
6634 aopPut (AOP (result), zero, LSB);
6635 aopPut (AOP (result), zero, MSB16);
6636 aopPut (AOP (result), zero, MSB32);
6640 /* more than two bytes */
6641 else if (shCount >= 16)
6643 /* lower order two bytes goes to higher order two bytes */
6645 /* if some more remaining */
6647 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6650 movLeft2Result (left, MSB16, result, MSB32, 0);
6651 movLeft2Result (left, LSB, result, MSB24, 0);
6653 aopPut (AOP (result), zero, MSB16);
6654 aopPut (AOP (result), zero, LSB);
6658 /* if more than 1 byte */
6659 else if (shCount >= 8)
6661 /* lower order three bytes goes to higher order three bytes */
6666 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6668 movLeft2Result (left, LSB, result, MSB16, 0);
6674 movLeft2Result (left, MSB24, result, MSB32, 0);
6675 movLeft2Result (left, MSB16, result, MSB24, 0);
6676 movLeft2Result (left, LSB, result, MSB16, 0);
6677 aopPut (AOP (result), zero, LSB);
6679 else if (shCount == 1)
6680 shiftLLong (left, result, MSB16);
6683 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6684 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6685 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6686 aopPut (AOP (result), zero, LSB);
6691 /* 1 <= shCount <= 7 */
6692 else if (shCount <= 2)
6694 shiftLLong (left, result, LSB);
6696 shiftLLong (result, result, LSB);
6698 /* 3 <= shCount <= 7, optimize */
6701 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6702 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6703 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6710 /*-----------------------------------------------------------------*/
6711 /* genLeftShiftLiteral - left shifting by known count */
6712 /*-----------------------------------------------------------------*/
6714 genLeftShiftLiteral (operand * left,
6719 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6722 D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
6725 freeAsmop (right, NULL, ic, TRUE);
6727 aopOp (left, ic, FALSE, FALSE);
6728 aopOp (result, ic, FALSE, TRUE);
6730 size = getSize (operandType (result));
6733 emitcode ("; shift left ", "result %d, left %d", size,
6737 /* I suppose that the left size >= result size */
6742 movLeft2Result (left, size, result, size, 0);
6746 else if (shCount >= (size * 8))
6748 aopPut (AOP (result), zero, size);
6754 genlshOne (result, left, shCount);
6758 case 3: /* bug: this is for generic pointers, I bet. */
6759 genlshTwo (result, left, shCount);
6763 genlshFour (result, left, shCount);
6767 freeAsmop (left, NULL, ic, TRUE);
6768 freeAsmop (result, NULL, ic, TRUE);
6772 /*-----------------------------------------------------------------*/
6773 /* genLeftShift - generates code for left shifting */
6774 /*-----------------------------------------------------------------*/
6776 genLeftShift (iCode * ic)
6778 operand *left, *right, *result;
6781 symbol *tlbl, *tlbl1;
6783 D (emitcode (";", "genLeftShift ");
6786 right = IC_RIGHT (ic);
6787 left = IC_LEFT (ic);
6788 result = IC_RESULT (ic);
6790 aopOp (right, ic, FALSE, FALSE);
6793 /* if the shift count is known then do it
6794 as efficiently as possible */
6795 if (AOP_TYPE (right) == AOP_LIT)
6797 genLeftShiftLiteral (left, right, result, ic);
6802 /* shift count is unknown then we have to form
6803 a loop get the loop count in B : Note: we take
6804 only the lower order byte since shifting
6805 more that 32 bits make no sense anyway, ( the
6806 largest size of an object can be only 32 bits ) */
6808 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6809 emitcode ("inc", "b");
6810 freeAsmop (right, NULL, ic, TRUE);
6811 aopOp (left, ic, FALSE, FALSE);
6812 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6814 /* now move the left to the result if they are not the
6816 if (!sameRegs (AOP (left), AOP (result)) &&
6817 AOP_SIZE (result) > 1)
6820 size = AOP_SIZE (result);
6822 _startLazyDPSEvaluation ();
6825 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
6826 if (*l == '@' && (IS_AOP_PREG (result)))
6829 emitcode ("mov", "a,%s", l);
6830 aopPut (AOP (result), "a", offset);
6833 aopPut (AOP (result), l, offset);
6836 _endLazyDPSEvaluation ();
6839 tlbl = newiTempLabel (NULL);
6840 size = AOP_SIZE (result);
6842 tlbl1 = newiTempLabel (NULL);
6844 /* if it is only one byte then */
6847 symbol *tlbl1 = newiTempLabel (NULL);
6849 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
6851 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6852 emitcode ("", "%05d$:", tlbl->key + 100);
6853 emitcode ("add", "a,acc");
6854 emitcode ("", "%05d$:", tlbl1->key + 100);
6855 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6856 aopPut (AOP (result), "a", 0);
6860 reAdjustPreg (AOP (result));
6862 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6863 emitcode ("", "%05d$:", tlbl->key + 100);
6864 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6866 emitcode ("add", "a,acc");
6867 aopPut (AOP (result), "a", offset++);
6868 _startLazyDPSEvaluation ();
6871 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
6873 emitcode ("rlc", "a");
6874 aopPut (AOP (result), "a", offset++);
6876 _endLazyDPSEvaluation ();
6877 reAdjustPreg (AOP (result));
6879 emitcode ("", "%05d$:", tlbl1->key + 100);
6880 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6882 freeAsmop (left, NULL, ic, TRUE);
6883 freeAsmop (result, NULL, ic, TRUE);
6888 /*-----------------------------------------------------------------*/
6889 /* genrshOne - right shift a one byte quantity by known count */
6890 /*-----------------------------------------------------------------*/
6892 genrshOne (operand * result, operand * left,
6893 int shCount, int sign)
6895 D (emitcode (";", "genrshOne");
6897 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6903 /*-----------------------------------------------------------------*/
6904 /* genrshTwo - right shift two bytes by known amount != 0 */
6905 /*-----------------------------------------------------------------*/
6907 genrshTwo (operand * result, operand * left,
6908 int shCount, int sign)
6910 D (emitcode (";", "genrshTwo");
6913 /* if shCount >= 8 */
6918 shiftR1Left2Result (left, MSB16, result, LSB,
6921 movLeft2Result (left, MSB16, result, LSB, sign);
6922 addSign (result, MSB16, sign);
6925 /* 1 <= shCount <= 7 */
6927 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6933 /*-----------------------------------------------------------------*/
6934 /* shiftRLong - shift right one long from left to result */
6935 /* offl = LSB or MSB16 */
6936 /*-----------------------------------------------------------------*/
6938 shiftRLong (operand * left, int offl,
6939 operand * result, int sign)
6942 emitcode ("clr", "c");
6943 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
6945 emitcode ("mov", "c,acc.7");
6946 emitcode ("rrc", "a");
6947 aopPut (AOP (result), "a", MSB32 - offl);
6949 /* add sign of "a" */
6950 addSign (result, MSB32, sign);
6952 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
6953 emitcode ("rrc", "a");
6954 aopPut (AOP (result), "a", MSB24 - offl);
6956 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
6957 emitcode ("rrc", "a");
6958 aopPut (AOP (result), "a", MSB16 - offl);
6962 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
6963 emitcode ("rrc", "a");
6964 aopPut (AOP (result), "a", LSB);
6971 /*-----------------------------------------------------------------*/
6972 /* genrshFour - shift four byte by a known amount != 0 */
6973 /*-----------------------------------------------------------------*/
6975 genrshFour (operand * result, operand * left,
6976 int shCount, int sign)
6978 D (emitcode (";", "genrshFour");
6981 /* if shifting more that 3 bytes */
6986 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6988 movLeft2Result (left, MSB32, result, LSB, sign);
6989 addSign (result, MSB16, sign);
6991 else if (shCount >= 16)
6995 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6998 movLeft2Result (left, MSB24, result, LSB, 0);
6999 movLeft2Result (left, MSB32, result, MSB16, sign);
7001 addSign (result, MSB24, sign);
7003 else if (shCount >= 8)
7007 shiftRLong (left, MSB16, result, sign);
7008 else if (shCount == 0)
7010 movLeft2Result (left, MSB16, result, LSB, 0);
7011 movLeft2Result (left, MSB24, result, MSB16, 0);
7012 movLeft2Result (left, MSB32, result, MSB24, sign);
7013 addSign (result, MSB32, sign);
7017 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7018 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7019 /* the last shift is signed */
7020 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7021 addSign (result, MSB32, sign);
7025 { /* 1 <= shCount <= 7 */
7028 shiftRLong (left, LSB, result, sign);
7030 shiftRLong (result, LSB, result, sign);
7034 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7035 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7036 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7044 /*-----------------------------------------------------------------*/
7045 /* genRightShiftLiteral - right shifting by known count */
7046 /*-----------------------------------------------------------------*/
7048 genRightShiftLiteral (operand * left,
7054 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7057 D (emitcode (";", "genRightShiftLiteral");
7060 freeAsmop (right, NULL, ic, TRUE);
7062 aopOp (left, ic, FALSE, FALSE);
7063 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7066 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7070 size = getDataSize (left);
7071 /* test the LEFT size !!! */
7073 /* I suppose that the left size >= result size */
7076 size = getDataSize (result);
7078 movLeft2Result (left, size, result, size, 0);
7081 else if (shCount >= (size * 8))
7084 /* get sign in acc.7 */
7085 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7086 addSign (result, LSB, sign);
7093 genrshOne (result, left, shCount, sign);
7097 genrshTwo (result, left, shCount, sign);
7101 genrshFour (result, left, shCount, sign);
7107 freeAsmop (left, NULL, ic, TRUE);
7108 freeAsmop (result, NULL, ic, TRUE);
7113 /*-----------------------------------------------------------------*/
7114 /* genSignedRightShift - right shift of signed number */
7115 /*-----------------------------------------------------------------*/
7117 genSignedRightShift (iCode * ic)
7119 operand *right, *left, *result;
7122 symbol *tlbl, *tlbl1;
7124 D (emitcode (";", "genSignedRightShift ");
7127 /* we do it the hard way put the shift count in b
7128 and loop thru preserving the sign */
7130 right = IC_RIGHT (ic);
7131 left = IC_LEFT (ic);
7132 result = IC_RESULT (ic);
7134 aopOp (right, ic, FALSE, FALSE);
7137 if (AOP_TYPE (right) == AOP_LIT)
7139 genRightShiftLiteral (left, right, result, ic, 1);
7143 /* shift count is unknown then we have to form
7144 a loop get the loop count in B : Note: we take
7145 only the lower order byte since shifting
7146 more that 32 bits make no sense anyway, ( the
7147 largest size of an object can be only 32 bits ) */
7149 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7150 emitcode ("inc", "b");
7151 freeAsmop (right, NULL, ic, TRUE);
7152 aopOp (left, ic, FALSE, FALSE);
7153 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7155 /* now move the left to the result if they are not the
7157 if (!sameRegs (AOP (left), AOP (result)) &&
7158 AOP_SIZE (result) > 1)
7161 size = AOP_SIZE (result);
7163 _startLazyDPSEvaluation ();
7166 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7167 if (*l == '@' && IS_AOP_PREG (result))
7170 emitcode ("mov", "a,%s", l);
7171 aopPut (AOP (result), "a", offset);
7174 aopPut (AOP (result), l, offset);
7177 _endLazyDPSEvaluation ();
7180 /* mov the highest order bit to OVR */
7181 tlbl = newiTempLabel (NULL);
7182 tlbl1 = newiTempLabel (NULL);
7184 size = AOP_SIZE (result);
7186 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7187 emitcode ("rlc", "a");
7188 emitcode ("mov", "ov,c");
7189 /* if it is only one byte then */
7192 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7194 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7195 emitcode ("", "%05d$:", tlbl->key + 100);
7196 emitcode ("mov", "c,ov");
7197 emitcode ("rrc", "a");
7198 emitcode ("", "%05d$:", tlbl1->key + 100);
7199 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7200 aopPut (AOP (result), "a", 0);
7204 reAdjustPreg (AOP (result));
7205 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7206 emitcode ("", "%05d$:", tlbl->key + 100);
7207 emitcode ("mov", "c,ov");
7208 _startLazyDPSEvaluation ();
7211 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7213 emitcode ("rrc", "a");
7214 aopPut (AOP (result), "a", offset--);
7216 _endLazyDPSEvaluation ();
7217 reAdjustPreg (AOP (result));
7218 emitcode ("", "%05d$:", tlbl1->key + 100);
7219 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7222 freeAsmop (left, NULL, ic, TRUE);
7223 freeAsmop (result, NULL, ic, TRUE);
7226 /*-----------------------------------------------------------------*/
7227 /* genRightShift - generate code for right shifting */
7228 /*-----------------------------------------------------------------*/
7230 genRightShift (iCode * ic)
7232 operand *right, *left, *result;
7236 symbol *tlbl, *tlbl1;
7238 D (emitcode (";", "genRightShift ");
7241 /* if signed then we do it the hard way preserve the
7242 sign bit moving it inwards */
7243 retype = getSpec (operandType (IC_RESULT (ic)));
7245 if (!SPEC_USIGN (retype))
7247 genSignedRightShift (ic);
7251 /* signed & unsigned types are treated the same : i.e. the
7252 signed is NOT propagated inwards : quoting from the
7253 ANSI - standard : "for E1 >> E2, is equivalent to division
7254 by 2**E2 if unsigned or if it has a non-negative value,
7255 otherwise the result is implementation defined ", MY definition
7256 is that the sign does not get propagated */
7258 right = IC_RIGHT (ic);
7259 left = IC_LEFT (ic);
7260 result = IC_RESULT (ic);
7262 aopOp (right, ic, FALSE, FALSE);
7265 /* if the shift count is known then do it
7266 as efficiently as possible */
7267 if (AOP_TYPE (right) == AOP_LIT)
7269 genRightShiftLiteral (left, right, result, ic, 0);
7274 /* shift count is unknown then we have to form
7275 a loop get the loop count in B : Note: we take
7276 only the lower order byte since shifting
7277 more that 32 bits make no sense anyway, ( the
7278 largest size of an object can be only 32 bits ) */
7280 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7281 emitcode ("inc", "b");
7282 freeAsmop (right, NULL, ic, TRUE);
7283 aopOp (left, ic, FALSE, FALSE);
7284 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7286 /* now move the left to the result if they are not the
7288 if (!sameRegs (AOP (left), AOP (result)) &&
7289 AOP_SIZE (result) > 1)
7292 size = AOP_SIZE (result);
7294 _startLazyDPSEvaluation ();
7297 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7298 if (*l == '@' && IS_AOP_PREG (result))
7301 emitcode ("mov", "a,%s", l);
7302 aopPut (AOP (result), "a", offset);
7305 aopPut (AOP (result), l, offset);
7308 _endLazyDPSEvaluation ();
7311 tlbl = newiTempLabel (NULL);
7312 tlbl1 = newiTempLabel (NULL);
7313 size = AOP_SIZE (result);
7316 /* if it is only one byte then */
7319 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7321 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7322 emitcode ("", "%05d$:", tlbl->key + 100);
7324 emitcode ("rrc", "a");
7325 emitcode ("", "%05d$:", tlbl1->key + 100);
7326 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7327 aopPut (AOP (result), "a", 0);
7331 reAdjustPreg (AOP (result));
7332 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7333 emitcode ("", "%05d$:", tlbl->key + 100);
7335 _startLazyDPSEvaluation ();
7338 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7340 emitcode ("rrc", "a");
7341 aopPut (AOP (result), "a", offset--);
7343 _endLazyDPSEvaluation ();
7344 reAdjustPreg (AOP (result));
7346 emitcode ("", "%05d$:", tlbl1->key + 100);
7347 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7350 freeAsmop (left, NULL, ic, TRUE);
7351 freeAsmop (result, NULL, ic, TRUE);
7354 /*-----------------------------------------------------------------*/
7355 /* genUnpackBits - generates code for unpacking bits */
7356 /*-----------------------------------------------------------------*/
7358 genUnpackBits (operand * result, char *rname, int ptype)
7365 D (emitcode (";", "genUnpackBits ");
7368 etype = getSpec (operandType (result));
7370 /* read the first byte */
7376 emitcode ("mov", "a,@%s", rname);
7380 emitcode ("movx", "a,@%s", rname);
7384 emitcode ("movx", "a,@dptr");
7388 emitcode ("clr", "a");
7389 emitcode ("movc", "a", "@a+dptr");
7393 emitcode ("lcall", "__gptrget");
7397 /* if we have bitdisplacement then it fits */
7398 /* into this byte completely or if length is */
7399 /* less than a byte */
7400 if ((shCnt = SPEC_BSTR (etype)) ||
7401 (SPEC_BLEN (etype) <= 8))
7404 /* shift right acc */
7407 emitcode ("anl", "a,#0x%02x",
7408 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7409 aopPut (AOP (result), "a", offset);
7413 /* bit field did not fit in a byte */
7414 rlen = SPEC_BLEN (etype) - 8;
7415 aopPut (AOP (result), "a", offset++);
7424 emitcode ("inc", "%s", rname);
7425 emitcode ("mov", "a,@%s", rname);
7429 emitcode ("inc", "%s", rname);
7430 emitcode ("movx", "a,@%s", rname);
7434 emitcode ("inc", "dptr");
7435 emitcode ("movx", "a,@dptr");
7439 emitcode ("clr", "a");
7440 emitcode ("inc", "dptr");
7441 emitcode ("movc", "a", "@a+dptr");
7445 emitcode ("inc", "dptr");
7446 emitcode ("lcall", "__gptrget");
7451 /* if we are done */
7455 aopPut (AOP (result), "a", offset++);
7461 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7462 aopPut (AOP (result), "a", offset);
7469 /*-----------------------------------------------------------------*/
7470 /* genDataPointerGet - generates code when ptr offset is known */
7471 /*-----------------------------------------------------------------*/
7473 genDataPointerGet (operand * left,
7479 int size, offset = 0;
7480 aopOp (result, ic, TRUE, FALSE);
7482 /* get the string representation of the name */
7483 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7484 size = AOP_SIZE (result);
7485 _startLazyDPSEvaluation ();
7489 sprintf (buffer, "(%s + %d)", l + 1, offset);
7491 sprintf (buffer, "%s", l + 1);
7492 aopPut (AOP (result), buffer, offset++);
7494 _endLazyDPSEvaluation ();
7496 freeAsmop (left, NULL, ic, TRUE);
7497 freeAsmop (result, NULL, ic, TRUE);
7500 /*-----------------------------------------------------------------*/
7501 /* genNearPointerGet - emitcode for near pointer fetch */
7502 /*-----------------------------------------------------------------*/
7504 genNearPointerGet (operand * left,
7511 sym_link *rtype, *retype, *letype;
7512 sym_link *ltype = operandType (left);
7515 rtype = operandType (result);
7516 retype = getSpec (rtype);
7517 letype = getSpec (ltype);
7519 aopOp (left, ic, FALSE, FALSE);
7521 /* if left is rematerialisable and
7522 result is not bit variable type and
7523 the left is pointer to data space i.e
7524 lower 128 bytes of space */
7525 if (AOP_TYPE (left) == AOP_IMMD &&
7526 !IS_BITVAR (retype) &&
7527 !IS_BITVAR (letype) &&
7528 DCL_TYPE (ltype) == POINTER)
7530 genDataPointerGet (left, result, ic);
7534 /* if the value is already in a pointer register
7535 then don't need anything more */
7536 if (!AOP_INPREG (AOP (left)))
7538 /* otherwise get a free pointer register */
7540 preg = getFreePtr (ic, &aop, FALSE);
7541 emitcode ("mov", "%s,%s",
7543 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7547 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7549 freeAsmop (left, NULL, ic, TRUE);
7550 aopOp (result, ic, FALSE, FALSE);
7552 /* if bitfield then unpack the bits */
7553 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7554 genUnpackBits (result, rname, POINTER);
7557 /* we have can just get the values */
7558 int size = AOP_SIZE (result);
7563 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7566 emitcode ("mov", "a,@%s", rname);
7567 aopPut (AOP (result), "a", offset);
7571 sprintf (buffer, "@%s", rname);
7572 aopPut (AOP (result), buffer, offset);
7576 emitcode ("inc", "%s", rname);
7580 /* now some housekeeping stuff */
7583 /* we had to allocate for this iCode */
7584 freeAsmop (NULL, aop, ic, TRUE);
7588 /* we did not allocate which means left
7589 already in a pointer register, then
7590 if size > 0 && this could be used again
7591 we have to point it back to where it
7593 if (AOP_SIZE (result) > 1 &&
7594 !OP_SYMBOL (left)->remat &&
7595 (OP_SYMBOL (left)->liveTo > ic->seq ||
7598 int size = AOP_SIZE (result) - 1;
7600 emitcode ("dec", "%s", rname);
7605 freeAsmop (result, NULL, ic, TRUE);
7609 /*-----------------------------------------------------------------*/
7610 /* genPagedPointerGet - emitcode for paged pointer fetch */
7611 /*-----------------------------------------------------------------*/
7613 genPagedPointerGet (operand * left,
7620 sym_link *rtype, *retype, *letype;
7622 rtype = operandType (result);
7623 retype = getSpec (rtype);
7624 letype = getSpec (operandType (left));
7625 aopOp (left, ic, FALSE, FALSE);
7627 /* if the value is already in a pointer register
7628 then don't need anything more */
7629 if (!AOP_INPREG (AOP (left)))
7631 /* otherwise get a free pointer register */
7633 preg = getFreePtr (ic, &aop, FALSE);
7634 emitcode ("mov", "%s,%s",
7636 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7640 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7642 freeAsmop (left, NULL, ic, TRUE);
7643 aopOp (result, ic, FALSE, FALSE);
7645 /* if bitfield then unpack the bits */
7646 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7647 genUnpackBits (result, rname, PPOINTER);
7650 /* we have can just get the values */
7651 int size = AOP_SIZE (result);
7657 emitcode ("movx", "a,@%s", rname);
7658 aopPut (AOP (result), "a", offset);
7663 emitcode ("inc", "%s", rname);
7667 /* now some housekeeping stuff */
7670 /* we had to allocate for this iCode */
7671 freeAsmop (NULL, aop, ic, TRUE);
7675 /* we did not allocate which means left
7676 already in a pointer register, then
7677 if size > 0 && this could be used again
7678 we have to point it back to where it
7680 if (AOP_SIZE (result) > 1 &&
7681 !OP_SYMBOL (left)->remat &&
7682 (OP_SYMBOL (left)->liveTo > ic->seq ||
7685 int size = AOP_SIZE (result) - 1;
7687 emitcode ("dec", "%s", rname);
7692 freeAsmop (result, NULL, ic, TRUE);
7697 /*-----------------------------------------------------------------*/
7698 /* genFarPointerGet - gget value from far space */
7699 /*-----------------------------------------------------------------*/
7701 genFarPointerGet (operand * left,
7702 operand * result, iCode * ic)
7705 sym_link *retype = getSpec (operandType (result));
7706 sym_link *letype = getSpec (operandType (left));
7707 D (emitcode (";", "genFarPointerGet");
7710 aopOp (left, ic, FALSE, FALSE);
7712 /* if the operand is already in dptr
7713 then we do nothing else we move the value to dptr */
7714 if (AOP_TYPE (left) != AOP_STR)
7716 /* if this is remateriazable */
7717 if (AOP_TYPE (left) == AOP_IMMD)
7719 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7723 /* we need to get it byte by byte */
7724 _startLazyDPSEvaluation ();
7725 if (AOP_TYPE (left) != AOP_DPTR)
7727 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7728 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7729 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7733 /* We need to generate a load to DPTR indirect through DPTR. */
7734 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7736 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7737 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7738 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7739 emitcode ("pop", "dph");
7740 emitcode ("pop", "dpl");
7742 _endLazyDPSEvaluation ();
7745 /* so dptr know contains the address */
7746 freeAsmop (left, NULL, ic, TRUE);
7747 aopOp (result, ic, FALSE, TRUE);
7749 /* if bit then unpack */
7750 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7751 genUnpackBits (result, "dptr", FPOINTER);
7754 size = AOP_SIZE (result);
7757 _startLazyDPSEvaluation ();
7764 emitcode ("movx", "a,@dptr");
7766 emitcode ("inc", "dptr");
7768 aopPut (AOP (result), "a", offset++);
7770 _endLazyDPSEvaluation ();
7773 freeAsmop (result, NULL, ic, TRUE);
7776 /*-----------------------------------------------------------------*/
7777 /* emitcodePointerGet - gget value from code space */
7778 /*-----------------------------------------------------------------*/
7780 emitcodePointerGet (operand * left,
7781 operand * result, iCode * ic)
7784 sym_link *retype = getSpec (operandType (result));
7786 aopOp (left, ic, FALSE, FALSE);
7788 /* if the operand is already in dptr
7789 then we do nothing else we move the value to dptr */
7790 if (AOP_TYPE (left) != AOP_STR)
7792 /* if this is remateriazable */
7793 if (AOP_TYPE (left) == AOP_IMMD)
7795 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7798 { /* we need to get it byte by byte */
7799 _startLazyDPSEvaluation ();
7800 if (AOP_TYPE (left) != AOP_DPTR)
7802 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7803 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7804 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7808 /* We need to generate a load to DPTR indirect through DPTR. */
7809 D (emitcode (";", "gencodePointerGet -- indirection special case.");
7811 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7812 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7813 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7814 emitcode ("pop", "dph");
7815 emitcode ("pop", "dpl");
7817 _endLazyDPSEvaluation ();
7820 /* so dptr know contains the address */
7821 freeAsmop (left, NULL, ic, TRUE);
7822 aopOp (result, ic, FALSE, TRUE);
7824 /* if bit then unpack */
7825 if (IS_BITVAR (retype))
7826 genUnpackBits (result, "dptr", CPOINTER);
7829 size = AOP_SIZE (result);
7832 _startLazyDPSEvaluation ();
7838 emitcode ("clr", "a");
7839 emitcode ("movc", "a,@a+dptr");
7841 emitcode ("inc", "dptr");
7842 aopPut (AOP (result), "a", offset++);
7844 _endLazyDPSEvaluation ();
7847 freeAsmop (result, NULL, ic, TRUE);
7850 /*-----------------------------------------------------------------*/
7851 /* genGenPointerGet - gget value from generic pointer space */
7852 /*-----------------------------------------------------------------*/
7854 genGenPointerGet (operand * left,
7855 operand * result, iCode * ic)
7858 sym_link *retype = getSpec (operandType (result));
7859 sym_link *letype = getSpec (operandType (left));
7861 D (emitcode (";", "genGenPointerGet "); );
7863 aopOp (left, ic, FALSE, TRUE);
7865 /* if the operand is already in dptr
7866 then we do nothing else we move the value to dptr */
7867 if (AOP_TYPE (left) != AOP_STR)
7869 /* if this is remateriazable */
7870 if (AOP_TYPE (left) == AOP_IMMD)
7872 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7873 emitcode ("mov", "b,#%d", pointerCode (retype));
7876 { /* we need to get it byte by byte */
7877 _startLazyDPSEvaluation ();
7878 if (AOP(left)->type==AOP_DPTR2) {
7880 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
7883 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
7884 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
7887 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
7888 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
7891 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
7892 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7894 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
7895 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
7896 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
7897 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
7899 _endLazyDPSEvaluation ();
7902 /* so dptr know contains the address */
7903 freeAsmop (left, NULL, ic, TRUE);
7904 aopOp (result, ic, FALSE, TRUE);
7906 /* if bit then unpack */
7907 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7908 genUnpackBits (result, "dptr", GPOINTER);
7911 size = AOP_SIZE (result);
7916 emitcode ("lcall", "__gptrget");
7917 aopPut (AOP (result), "a", offset++);
7919 emitcode ("inc", "dptr");
7923 freeAsmop (result, NULL, ic, TRUE);
7926 /*-----------------------------------------------------------------*/
7927 /* genPointerGet - generate code for pointer get */
7928 /*-----------------------------------------------------------------*/
7930 genPointerGet (iCode * ic)
7932 operand *left, *result;
7933 sym_link *type, *etype;
7936 D (emitcode (";", "genPointerGet ");
7939 left = IC_LEFT (ic);
7940 result = IC_RESULT (ic);
7942 /* depending on the type of pointer we need to
7943 move it to the correct pointer register */
7944 type = operandType (left);
7945 etype = getSpec (type);
7946 /* if left is of type of pointer then it is simple */
7947 if (IS_PTR (type) && !IS_FUNC (type->next))
7948 p_type = DCL_TYPE (type);
7951 /* we have to go by the storage class */
7952 p_type = PTR_TYPE (SPEC_OCLS (etype));
7955 /* now that we have the pointer type we assign
7956 the pointer values */
7962 genNearPointerGet (left, result, ic);
7966 genPagedPointerGet (left, result, ic);
7970 genFarPointerGet (left, result, ic);
7974 emitcodePointerGet (left, result, ic);
7978 genGenPointerGet (left, result, ic);
7984 /*-----------------------------------------------------------------*/
7985 /* genPackBits - generates code for packed bit storage */
7986 /*-----------------------------------------------------------------*/
7988 genPackBits (sym_link * etype,
7990 char *rname, int p_type)
7998 blen = SPEC_BLEN (etype);
7999 bstr = SPEC_BSTR (etype);
8001 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8004 /* if the bit lenth is less than or */
8005 /* it exactly fits a byte then */
8006 if (SPEC_BLEN (etype) <= 8)
8008 shCount = SPEC_BSTR (etype);
8010 /* shift left acc */
8013 if (SPEC_BLEN (etype) < 8)
8014 { /* if smaller than a byte */
8020 emitcode ("mov", "b,a");
8021 emitcode ("mov", "a,@%s", rname);
8025 emitcode ("mov", "b,a");
8026 emitcode ("movx", "a,@dptr");
8030 emitcode ("push", "b");
8031 emitcode ("push", "acc");
8032 emitcode ("lcall", "__gptrget");
8033 emitcode ("pop", "b");
8037 emitcode ("anl", "a,#0x%02x", (unsigned char)
8038 ((unsigned char) (0xFF << (blen + bstr)) |
8039 (unsigned char) (0xFF >> (8 - bstr))));
8040 emitcode ("orl", "a,b");
8041 if (p_type == GPOINTER)
8042 emitcode ("pop", "b");
8049 emitcode ("mov", "@%s,a", rname);
8053 emitcode ("movx", "@dptr,a");
8057 emitcode ("lcall", "__gptrput");
8062 if (SPEC_BLEN (etype) <= 8)
8065 emitcode ("inc", "%s", rname);
8066 rLen = SPEC_BLEN (etype);
8068 /* now generate for lengths greater than one byte */
8072 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8084 emitcode ("mov", "@%s,a", rname);
8087 emitcode ("mov", "@%s,%s", rname, l);
8092 emitcode ("movx", "@dptr,a");
8097 emitcode ("lcall", "__gptrput");
8100 emitcode ("inc", "%s", rname);
8105 /* last last was not complete */
8108 /* save the byte & read byte */
8112 emitcode ("mov", "b,a");
8113 emitcode ("mov", "a,@%s", rname);
8117 emitcode ("mov", "b,a");
8118 emitcode ("movx", "a,@dptr");
8122 emitcode ("push", "b");
8123 emitcode ("push", "acc");
8124 emitcode ("lcall", "__gptrget");
8125 emitcode ("pop", "b");
8129 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8130 emitcode ("orl", "a,b");
8133 if (p_type == GPOINTER)
8134 emitcode ("pop", "b");
8140 emitcode ("mov", "@%s,a", rname);
8144 emitcode ("movx", "@dptr,a");
8148 emitcode ("lcall", "__gptrput");
8152 /*-----------------------------------------------------------------*/
8153 /* genDataPointerSet - remat pointer to data space */
8154 /*-----------------------------------------------------------------*/
8156 genDataPointerSet (operand * right,
8160 int size, offset = 0;
8161 char *l, buffer[256];
8163 aopOp (right, ic, FALSE, FALSE);
8165 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8166 size = AOP_SIZE (right);
8170 sprintf (buffer, "(%s + %d)", l + 1, offset);
8172 sprintf (buffer, "%s", l + 1);
8173 emitcode ("mov", "%s,%s", buffer,
8174 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8177 freeAsmop (right, NULL, ic, TRUE);
8178 freeAsmop (result, NULL, ic, TRUE);
8181 /*-----------------------------------------------------------------*/
8182 /* genNearPointerSet - emitcode for near pointer put */
8183 /*-----------------------------------------------------------------*/
8185 genNearPointerSet (operand * right,
8192 sym_link *retype, *letype;
8193 sym_link *ptype = operandType (result);
8195 retype = getSpec (operandType (right));
8196 letype = getSpec (ptype);
8198 aopOp (result, ic, FALSE, FALSE);
8200 /* if the result is rematerializable &
8201 in data space & not a bit variable */
8202 if (AOP_TYPE (result) == AOP_IMMD &&
8203 DCL_TYPE (ptype) == POINTER &&
8204 !IS_BITVAR (retype) &&
8205 !IS_BITVAR (letype))
8207 genDataPointerSet (right, result, ic);
8211 /* if the value is already in a pointer register
8212 then don't need anything more */
8213 if (!AOP_INPREG (AOP (result)))
8215 /* otherwise get a free pointer register */
8217 preg = getFreePtr (ic, &aop, FALSE);
8218 emitcode ("mov", "%s,%s",
8220 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8224 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8226 freeAsmop (result, NULL, ic, TRUE);
8227 aopOp (right, ic, FALSE, FALSE);
8229 /* if bitfield then unpack the bits */
8230 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8231 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8234 /* we have can just get the values */
8235 int size = AOP_SIZE (right);
8240 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8244 emitcode ("mov", "@%s,a", rname);
8247 emitcode ("mov", "@%s,%s", rname, l);
8249 emitcode ("inc", "%s", rname);
8254 /* now some housekeeping stuff */
8257 /* we had to allocate for this iCode */
8258 freeAsmop (NULL, aop, ic, TRUE);
8262 /* we did not allocate which means left
8263 already in a pointer register, then
8264 if size > 0 && this could be used again
8265 we have to point it back to where it
8267 if (AOP_SIZE (right) > 1 &&
8268 !OP_SYMBOL (result)->remat &&
8269 (OP_SYMBOL (result)->liveTo > ic->seq ||
8272 int size = AOP_SIZE (right) - 1;
8274 emitcode ("dec", "%s", rname);
8279 freeAsmop (right, NULL, ic, TRUE);
8284 /*-----------------------------------------------------------------*/
8285 /* genPagedPointerSet - emitcode for Paged pointer put */
8286 /*-----------------------------------------------------------------*/
8288 genPagedPointerSet (operand * right,
8295 sym_link *retype, *letype;
8297 retype = getSpec (operandType (right));
8298 letype = getSpec (operandType (result));
8300 aopOp (result, ic, FALSE, FALSE);
8302 /* if the value is already in a pointer register
8303 then don't need anything more */
8304 if (!AOP_INPREG (AOP (result)))
8306 /* otherwise get a free pointer register */
8308 preg = getFreePtr (ic, &aop, FALSE);
8309 emitcode ("mov", "%s,%s",
8311 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8315 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8317 freeAsmop (result, NULL, ic, TRUE);
8318 aopOp (right, ic, FALSE, FALSE);
8320 /* if bitfield then unpack the bits */
8321 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8322 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8325 /* we have can just get the values */
8326 int size = AOP_SIZE (right);
8331 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8334 emitcode ("movx", "@%s,a", rname);
8337 emitcode ("inc", "%s", rname);
8343 /* now some housekeeping stuff */
8346 /* we had to allocate for this iCode */
8347 freeAsmop (NULL, aop, ic, TRUE);
8351 /* we did not allocate which means left
8352 already in a pointer register, then
8353 if size > 0 && this could be used again
8354 we have to point it back to where it
8356 if (AOP_SIZE (right) > 1 &&
8357 !OP_SYMBOL (result)->remat &&
8358 (OP_SYMBOL (result)->liveTo > ic->seq ||
8361 int size = AOP_SIZE (right) - 1;
8363 emitcode ("dec", "%s", rname);
8368 freeAsmop (right, NULL, ic, TRUE);
8373 /*-----------------------------------------------------------------*/
8374 /* genFarPointerSet - set value from far space */
8375 /*-----------------------------------------------------------------*/
8377 genFarPointerSet (operand * right,
8378 operand * result, iCode * ic)
8381 sym_link *retype = getSpec (operandType (right));
8382 sym_link *letype = getSpec (operandType (result));
8384 aopOp (result, ic, FALSE, FALSE);
8386 /* if the operand is already in dptr
8387 then we do nothing else we move the value to dptr */
8388 if (AOP_TYPE (result) != AOP_STR)
8390 /* if this is remateriazable */
8391 if (AOP_TYPE (result) == AOP_IMMD)
8392 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8395 /* we need to get it byte by byte */
8396 _startLazyDPSEvaluation ();
8397 if (AOP_TYPE (result) != AOP_DPTR)
8399 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8400 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8401 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8405 /* We need to generate a load to DPTR indirect through DPTR. */
8406 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8408 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8409 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8410 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8411 emitcode ("pop", "dph");
8412 emitcode ("pop", "dpl");
8414 _endLazyDPSEvaluation ();
8417 /* so dptr know contains the address */
8418 freeAsmop (result, NULL, ic, TRUE);
8419 aopOp (right, ic, FALSE, TRUE);
8421 /* if bit then unpack */
8422 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8423 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8426 size = AOP_SIZE (right);
8429 _startLazyDPSEvaluation ();
8432 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8438 emitcode ("movx", "@dptr,a");
8440 emitcode ("inc", "dptr");
8442 _endLazyDPSEvaluation ();
8445 freeAsmop (right, NULL, ic, TRUE);
8448 /*-----------------------------------------------------------------*/
8449 /* genGenPointerSet - set value from generic pointer space */
8450 /*-----------------------------------------------------------------*/
8452 genGenPointerSet (operand * right,
8453 operand * result, iCode * ic)
8456 sym_link *retype = getSpec (operandType (right));
8457 sym_link *letype = getSpec (operandType (result));
8459 aopOp (result, ic, FALSE, TRUE);
8461 /* if the operand is already in dptr
8462 then we do nothing else we move the value to dptr */
8463 if (AOP_TYPE (result) != AOP_STR)
8465 _startLazyDPSEvaluation ();
8466 /* if this is remateriazable */
8467 if (AOP_TYPE (result) == AOP_IMMD)
8469 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8470 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8473 { /* we need to get it byte by byte */
8474 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8475 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8476 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8477 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8479 _endLazyDPSEvaluation ();
8481 /* so dptr know contains the address */
8482 freeAsmop (result, NULL, ic, TRUE);
8483 aopOp (right, ic, FALSE, TRUE);
8485 /* if bit then unpack */
8486 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8487 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8490 size = AOP_SIZE (right);
8493 _startLazyDPSEvaluation ();
8496 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8502 emitcode ("lcall", "__gptrput");
8504 emitcode ("inc", "dptr");
8506 _endLazyDPSEvaluation ();
8509 freeAsmop (right, NULL, ic, TRUE);
8512 /*-----------------------------------------------------------------*/
8513 /* genPointerSet - stores the value into a pointer location */
8514 /*-----------------------------------------------------------------*/
8516 genPointerSet (iCode * ic)
8518 operand *right, *result;
8519 sym_link *type, *etype;
8522 D (emitcode (";", "genPointerSet ");
8525 right = IC_RIGHT (ic);
8526 result = IC_RESULT (ic);
8528 /* depending on the type of pointer we need to
8529 move it to the correct pointer register */
8530 type = operandType (result);
8531 etype = getSpec (type);
8532 /* if left is of type of pointer then it is simple */
8533 if (IS_PTR (type) && !IS_FUNC (type->next))
8535 p_type = DCL_TYPE (type);
8539 /* we have to go by the storage class */
8540 p_type = PTR_TYPE (SPEC_OCLS (etype));
8543 /* now that we have the pointer type we assign
8544 the pointer values */
8550 genNearPointerSet (right, result, ic);
8554 genPagedPointerSet (right, result, ic);
8558 genFarPointerSet (right, result, ic);
8562 genGenPointerSet (right, result, ic);
8568 /*-----------------------------------------------------------------*/
8569 /* genIfx - generate code for Ifx statement */
8570 /*-----------------------------------------------------------------*/
8572 genIfx (iCode * ic, iCode * popIc)
8574 operand *cond = IC_COND (ic);
8577 D (emitcode (";", "genIfx ");
8580 aopOp (cond, ic, FALSE, FALSE);
8582 /* get the value into acc */
8583 if (AOP_TYPE (cond) != AOP_CRY)
8587 /* the result is now in the accumulator */
8588 freeAsmop (cond, NULL, ic, TRUE);
8590 /* if there was something to be popped then do it */
8594 /* if the condition is a bit variable */
8595 if (isbit && IS_ITEMP (cond) &&
8597 genIfxJump (ic, SPIL_LOC (cond)->rname);
8598 else if (isbit && !IS_ITEMP (cond))
8599 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8601 genIfxJump (ic, "a");
8606 /*-----------------------------------------------------------------*/
8607 /* genAddrOf - generates code for address of */
8608 /*-----------------------------------------------------------------*/
8610 genAddrOf (iCode * ic)
8612 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8615 D (emitcode (";", "genAddrOf ");
8618 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8620 /* if the operand is on the stack then we
8621 need to get the stack offset of this
8625 /* if it has an offset then we need to compute
8629 emitcode ("mov", "a,_bp");
8630 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8631 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8635 /* we can just move _bp */
8636 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8638 /* fill the result with zero */
8639 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8642 if (options.stack10bit && size < (FPTRSIZE - 1))
8645 "*** warning: pointer to stack var truncated.\n");
8652 if (options.stack10bit && offset == 2)
8654 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8658 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8665 /* object not on stack then we need the name */
8666 size = AOP_SIZE (IC_RESULT (ic));
8671 char s[SDCC_NAME_MAX];
8673 sprintf (s, "#(%s >> %d)",
8677 sprintf (s, "#%s", sym->rname);
8678 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8682 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8686 /*-----------------------------------------------------------------*/
8687 /* genFarFarAssign - assignment when both are in far space */
8688 /*-----------------------------------------------------------------*/
8690 genFarFarAssign (operand * result, operand * right, iCode * ic)
8692 int size = AOP_SIZE (right);
8698 /* This is a net loss for size == 1, but a big gain
8701 D (emitcode (";", "genFarFarAssign (improved)");
8704 aopOp (result, ic, TRUE, TRUE);
8706 _startLazyDPSEvaluation ();
8709 aopPut (AOP (result),
8710 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8713 _endLazyDPSEvaluation ();
8714 freeAsmop (result, NULL, ic, FALSE);
8715 freeAsmop (right, NULL, ic, FALSE);
8719 D (emitcode (";", "genFarFarAssign ");
8722 /* first push the right side on to the stack */
8723 _startLazyDPSEvaluation ();
8726 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8728 emitcode ("push", "acc");
8731 freeAsmop (right, NULL, ic, FALSE);
8732 /* now assign DPTR to result */
8733 aopOp (result, ic, FALSE, FALSE);
8734 size = AOP_SIZE (result);
8737 emitcode ("pop", "acc");
8738 aopPut (AOP (result), "a", --offset);
8740 freeAsmop (result, NULL, ic, FALSE);
8741 _endLazyDPSEvaluation ();
8745 /*-----------------------------------------------------------------*/
8746 /* genAssign - generate code for assignment */
8747 /*-----------------------------------------------------------------*/
8749 genAssign (iCode * ic)
8751 operand *result, *right;
8753 unsigned long lit = 0L;
8755 D (emitcode (";", "genAssign ");
8758 result = IC_RESULT (ic);
8759 right = IC_RIGHT (ic);
8761 /* if they are the same */
8762 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8765 aopOp (right, ic, FALSE, FALSE);
8767 emitcode (";", "genAssign: resultIsFar = %s",
8768 isOperandInFarSpace (result) ?
8771 /* special case both in far space */
8772 if ((AOP_TYPE (right) == AOP_DPTR ||
8773 AOP_TYPE (right) == AOP_DPTR2) &&
8774 /* IS_TRUE_SYMOP(result) && */
8775 isOperandInFarSpace (result))
8777 genFarFarAssign (result, right, ic);
8781 aopOp (result, ic, TRUE, FALSE);
8783 /* if they are the same registers */
8784 if (sameRegs (AOP (right), AOP (result)))
8787 /* if the result is a bit */
8788 if (AOP_TYPE (result) == AOP_CRY)
8791 /* if the right size is a literal then
8792 we know what the value is */
8793 if (AOP_TYPE (right) == AOP_LIT)
8795 if (((int) operandLitValue (right)))
8796 aopPut (AOP (result), one, 0);
8798 aopPut (AOP (result), zero, 0);
8802 /* the right is also a bit variable */
8803 if (AOP_TYPE (right) == AOP_CRY)
8805 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8806 aopPut (AOP (result), "c", 0);
8812 aopPut (AOP (result), "a", 0);
8816 /* bit variables done */
8818 size = AOP_SIZE (result);
8820 if (AOP_TYPE (right) == AOP_LIT)
8821 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8824 (AOP_TYPE (result) != AOP_REG) &&
8825 (AOP_TYPE (right) == AOP_LIT) &&
8826 !IS_FLOAT (operandType (right)))
8828 D (emitcode (";", "Kevin's better literal load code");
8830 _startLazyDPSEvaluation ();
8831 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
8833 aopPut (AOP (result),
8834 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
8839 /* And now fill the rest with zeros. */
8842 emitcode ("clr", "a");
8846 aopPut (AOP (result), "a", offset++);
8848 _endLazyDPSEvaluation ();
8852 _startLazyDPSEvaluation ();
8855 aopPut (AOP (result),
8856 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8860 _endLazyDPSEvaluation ();
8864 freeAsmop (right, NULL, ic, FALSE);
8865 freeAsmop (result, NULL, ic, TRUE);
8868 /*-----------------------------------------------------------------*/
8869 /* genJumpTab - generates code for jump table */
8870 /*-----------------------------------------------------------------*/
8872 genJumpTab (iCode * ic)
8877 D (emitcode (";", "genJumpTab ");
8880 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
8881 /* get the condition into accumulator */
8882 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
8884 /* multiply by four! */
8885 emitcode ("add", "a,acc");
8886 emitcode ("add", "a,acc");
8887 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8889 jtab = newiTempLabel (NULL);
8890 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8891 emitcode ("jmp", "@a+dptr");
8892 emitcode ("", "%05d$:", jtab->key + 100);
8893 /* now generate the jump labels */
8894 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8895 jtab = setNextItem (IC_JTLABELS (ic)))
8896 emitcode ("ljmp", "%05d$", jtab->key + 100);
8900 /*-----------------------------------------------------------------*/
8901 /* genCast - gen code for casting */
8902 /*-----------------------------------------------------------------*/
8904 genCast (iCode * ic)
8906 operand *result = IC_RESULT (ic);
8907 sym_link *ctype = operandType (IC_LEFT (ic));
8908 sym_link *rtype = operandType (IC_RIGHT (ic));
8909 operand *right = IC_RIGHT (ic);
8912 D (emitcode (";", "genCast ");
8915 /* if they are equivalent then do nothing */
8916 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8919 aopOp (right, ic, FALSE, FALSE);
8920 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
8922 /* if the result is a bit */
8923 if (AOP_TYPE (result) == AOP_CRY)
8925 /* if the right size is a literal then
8926 we know what the value is */
8927 if (AOP_TYPE (right) == AOP_LIT)
8929 if (((int) operandLitValue (right)))
8930 aopPut (AOP (result), one, 0);
8932 aopPut (AOP (result), zero, 0);
8937 /* the right is also a bit variable */
8938 if (AOP_TYPE (right) == AOP_CRY)
8940 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8941 aopPut (AOP (result), "c", 0);
8947 aopPut (AOP (result), "a", 0);
8951 /* if they are the same size : or less */
8952 if (AOP_SIZE (result) <= AOP_SIZE (right))
8955 /* if they are in the same place */
8956 if (sameRegs (AOP (right), AOP (result)))
8959 /* if they in different places then copy */
8960 size = AOP_SIZE (result);
8962 _startLazyDPSEvaluation ();
8965 aopPut (AOP (result),
8966 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
8970 _endLazyDPSEvaluation ();
8975 /* if the result is of type pointer */
8980 sym_link *type = operandType (right);
8982 /* pointer to generic pointer */
8983 if (IS_GENPTR (ctype))
8989 p_type = DCL_TYPE (type);
8993 #if OLD_CAST_BEHAVIOR
8994 /* KV: we are converting a non-pointer type to
8995 * a generic pointer. This (ifdef'd out) code
8996 * says that the resulting generic pointer
8997 * should have the same class as the storage
8998 * location of the non-pointer variable.
9000 * For example, converting an int (which happens
9001 * to be stored in DATA space) to a pointer results
9002 * in a DATA generic pointer; if the original int
9003 * in XDATA space, so will be the resulting pointer.
9005 * I don't like that behavior, and thus this change:
9006 * all such conversions will be forced to XDATA and
9007 * throw a warning. If you want some non-XDATA
9008 * type, or you want to suppress the warning, you
9009 * must go through an intermediate cast, like so:
9011 * char _generic *gp = (char _xdata *)(intVar);
9013 sym_link *etype = getSpec (type);
9015 /* we have to go by the storage class */
9016 if (SPEC_OCLS (etype) != generic)
9018 p_type = PTR_TYPE (SPEC_OCLS (etype));
9023 /* Converting unknown class (i.e. register variable)
9024 * to generic pointer. This is not good, but
9025 * we'll make a guess (and throw a warning).
9028 werror (W_INT_TO_GEN_PTR_CAST);
9032 /* the first two bytes are known */
9033 size = GPTRSIZE - 1;
9035 _startLazyDPSEvaluation ();
9038 aopPut (AOP (result),
9039 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9043 _endLazyDPSEvaluation ();
9045 /* the last byte depending on type */
9063 /* this should never happen */
9064 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9065 "got unknown pointer type");
9068 aopPut (AOP (result), l, GPTRSIZE - 1);
9072 /* just copy the pointers */
9073 size = AOP_SIZE (result);
9075 _startLazyDPSEvaluation ();
9078 aopPut (AOP (result),
9079 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9083 _endLazyDPSEvaluation ();
9087 /* so we now know that the size of destination is greater
9088 than the size of the source */
9089 /* we move to result for the size of source */
9090 size = AOP_SIZE (right);
9092 _startLazyDPSEvaluation ();
9095 aopPut (AOP (result),
9096 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9100 _endLazyDPSEvaluation ();
9102 /* now depending on the sign of the source && destination */
9103 size = AOP_SIZE (result) - AOP_SIZE (right);
9104 /* if unsigned or not an integral type */
9105 /* also, if the source is a bit, we don't need to sign extend, because
9106 * it can't possibly have set the sign bit.
9108 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9112 aopPut (AOP (result), zero, offset++);
9117 /* we need to extend the sign :{ */
9118 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9119 FALSE, FALSE, TRUE);
9121 emitcode ("rlc", "a");
9122 emitcode ("subb", "a,acc");
9124 aopPut (AOP (result), "a", offset++);
9127 /* we are done hurray !!!! */
9130 freeAsmop (right, NULL, ic, TRUE);
9131 freeAsmop (result, NULL, ic, TRUE);
9135 /*-----------------------------------------------------------------*/
9136 /* genDjnz - generate decrement & jump if not zero instrucion */
9137 /*-----------------------------------------------------------------*/
9139 genDjnz (iCode * ic, iCode * ifx)
9145 /* if the if condition has a false label
9146 then we cannot save */
9150 /* if the minus is not of the form
9152 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9153 !IS_OP_LITERAL (IC_RIGHT (ic)))
9156 if (operandLitValue (IC_RIGHT (ic)) != 1)
9159 /* if the size of this greater than one then no
9161 if (getSize (operandType (IC_RESULT (ic))) > 1)
9164 /* otherwise we can save BIG */
9165 lbl = newiTempLabel (NULL);
9166 lbl1 = newiTempLabel (NULL);
9168 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9170 if (IS_AOP_PREG (IC_RESULT (ic)))
9172 emitcode ("dec", "%s",
9173 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9174 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9175 emitcode ("jnz", "%05d$", lbl->key + 100);
9179 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
9182 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9183 emitcode ("", "%05d$:", lbl->key + 100);
9184 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9185 emitcode ("", "%05d$:", lbl1->key + 100);
9187 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9192 /*-----------------------------------------------------------------*/
9193 /* genReceive - generate code for a receive iCode */
9194 /*-----------------------------------------------------------------*/
9196 genReceive (iCode * ic)
9199 D (emitcode (";", "genReceive ");
9202 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9203 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9204 IS_TRUE_SYMOP (IC_RESULT (ic))))
9206 int size = getSize (operandType (IC_RESULT (ic)));
9207 int offset = fReturnSizeDS390 - size;
9210 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9211 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9214 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9215 size = AOP_SIZE (IC_RESULT (ic));
9219 emitcode ("pop", "acc");
9220 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9227 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9229 assignResultValue (IC_RESULT (ic));
9232 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9235 /*-----------------------------------------------------------------*/
9236 /* gen390Code - generate code for Dallas 390 based controllers */
9237 /*-----------------------------------------------------------------*/
9239 gen390Code (iCode * lic)
9244 lineHead = lineCurr = NULL;
9248 /* print the allocation information */
9250 printAllocInfo (currFunc, codeOutFile);
9252 /* if debug information required */
9253 if (options.debug && currFunc)
9255 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9257 if (IS_STATIC (currFunc->etype))
9258 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9260 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9263 /* stack pointer name */
9264 if (options.useXstack)
9270 for (ic = lic; ic; ic = ic->next)
9273 if (cln != ic->lineno)
9278 emitcode ("", "C$%s$%d$%d$%d ==.",
9279 FileBaseName (ic->filename), ic->lineno,
9280 ic->level, ic->block);
9283 emitcode (";", "%s %d", ic->filename, ic->lineno);
9286 /* if the result is marked as
9287 spilt and rematerializable or code for
9288 this has already been generated then
9290 if (resultRemat (ic) || ic->generated)
9293 /* depending on the operation */
9313 /* IPOP happens only when trying to restore a
9314 spilt live range, if there is an ifx statement
9315 following this pop then the if statement might
9316 be using some of the registers being popped which
9317 would destory the contents of the register so
9318 we need to check for this condition and handle it */
9320 ic->next->op == IFX &&
9321 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9322 genIfx (ic->next, ic);
9340 genEndFunction (ic);
9360 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9377 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9381 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9388 /* note these two are xlated by algebraic equivalence
9389 during parsing SDCC.y */
9390 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9391 "got '>=' or '<=' shouldn't have come here");
9395 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9407 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9411 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9415 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9442 case GET_VALUE_AT_ADDRESS:
9447 if (POINTER_SET (ic))
9474 addSet (&_G.sendSet, ic);
9479 /* piCode(ic,stdout); */
9485 /* now we are ready to call the
9486 peep hole optimizer */
9487 if (!options.nopeep)
9488 peepHole (&lineHead);
9490 /* now do the actual printing */
9491 printLine (lineHead, codeOutFile);