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 // #define BETTER_LITERAL_SHIFT
53 char *aopLiteral (value * val, int offset);
55 /* this is the down and dirty file with all kinds of
56 kludgy & hacky stuff. This is what it is all about
57 CODE GENERATION for a specific MCU . some of the
58 routines may be reusable, will have to see */
60 static char *zero = "#0x00";
61 static char *one = "#0x01";
66 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
67 static char *fReturn[] =
68 {"dpl", "dph", "dpx", "b", "a"};
69 static char *accUse[] =
72 static short rbank = -1;
86 static void saverbank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
93 #define MOVA(x) { char *_mova_tmp = strdup(x); \
94 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96 emitcode("mov","a,%s",_mova_tmp); \
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
122 /*-----------------------------------------------------------------*/
123 /* emitcode - writes the code into a file : for now it is simple */
124 /*-----------------------------------------------------------------*/
126 emitcode (char *inst, char *fmt,...)
129 char lb[MAX_INLINEASM];
137 sprintf (lb, "%s\t", inst);
139 sprintf (lb, "%s", inst);
140 vsprintf (lb + (strlen (lb)), fmt, ap);
143 vsprintf (lb, fmt, ap);
145 while (isspace (*lbp))
149 lineCurr = (lineCurr ?
150 connectLine (lineCurr, newLineNode (lb)) :
151 (lineHead = newLineNode (lb)));
152 lineCurr->isInline = _G.inLine;
153 lineCurr->isDebug = _G.debugLine;
157 /*-----------------------------------------------------------------*/
158 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
159 /*-----------------------------------------------------------------*/
161 getFreePtr (iCode * ic, asmop ** aopp, bool result)
163 bool r0iu = FALSE, r1iu = FALSE;
164 bool r0ou = FALSE, r1ou = FALSE;
166 /* the logic: if r0 & r1 used in the instruction
167 then we are in trouble otherwise */
169 /* first check if r0 & r1 are used by this
170 instruction, in which case we are in trouble */
171 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
172 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
177 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
178 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
180 /* if no usage of r0 then return it */
183 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
184 (*aopp)->type = AOP_R0;
186 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
189 /* if no usage of r1 then return it */
192 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
193 (*aopp)->type = AOP_R1;
195 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
198 /* now we know they both have usage */
199 /* if r0 not used in this instruction */
202 /* push it if not already pushed */
205 emitcode ("push", "%s",
206 ds390_regWithIdx (R0_IDX)->dname);
210 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
211 (*aopp)->type = AOP_R0;
213 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
216 /* if r1 not used then */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 ds390_regWithIdx (R1_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
229 (*aopp)->type = AOP_R1;
230 return ds390_regWithIdx (R1_IDX);
234 /* I said end of world but not quite end of world yet */
235 /* if this is a result then we can push it on the stack */
238 (*aopp)->type = AOP_STK;
242 /* other wise this is true end of the world */
243 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
244 "getFreePtr should never reach here");
248 /*-----------------------------------------------------------------*/
249 /* newAsmop - creates a new asmOp */
250 /*-----------------------------------------------------------------*/
252 newAsmop (short type)
256 aop = Safe_calloc (1, sizeof (asmop));
261 static int _currentDPS; /* Current processor DPS. */
262 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
263 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
265 /*-----------------------------------------------------------------*/
266 /* genSetDPTR: generate code to select which DPTR is in use (zero */
267 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
268 /* alternate DPTR (DPL1/DPH1/DPX1). */
269 /*-----------------------------------------------------------------*/
274 /* If we are doing lazy evaluation, simply note the desired
275 * change, but don't emit any code yet.
285 emitcode ("mov", "dps, #0x00");
289 emitcode ("mov", "dps, #0x01");
293 /*-----------------------------------------------------------------*/
294 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
296 /* Any code that operates on DPTR (NB: not on the individual */
297 /* components, like DPH) *must* call _flushLazyDPS() before using */
298 /* DPTR within a lazy DPS evaluation block. */
300 /* Note that aopPut and aopGet already contain the proper calls to */
301 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
302 /* DPS evaluation block. */
304 /* Also, _flushLazyDPS must be called before any flow control */
305 /* operations that could potentially branch out of the block. */
307 /* Lazy DPS evaluation is simply an optimization (though an */
308 /* important one), so if in doubt, leave it out. */
309 /*-----------------------------------------------------------------*/
311 _startLazyDPSEvaluation (void)
318 /*-----------------------------------------------------------------*/
319 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
320 /* desired one. Call before using DPTR within a lazy DPS evaluation */
322 /*-----------------------------------------------------------------*/
332 if (_desiredDPS != _currentDPS)
336 emitcode ("inc", "dps");
340 emitcode ("dec", "dps");
342 _currentDPS = _desiredDPS;
346 /*-----------------------------------------------------------------*/
347 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
349 /* Forces us back to the safe state (standard DPTR selected). */
350 /*-----------------------------------------------------------------*/
352 _endLazyDPSEvaluation (void)
366 /*-----------------------------------------------------------------*/
367 /* pointerCode - returns the code for a pointer type */
368 /*-----------------------------------------------------------------*/
370 pointerCode (sym_link * etype)
373 return PTR_TYPE (SPEC_OCLS (etype));
377 /*-----------------------------------------------------------------*/
378 /* aopForSym - for a true symbol */
379 /*-----------------------------------------------------------------*/
381 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
384 memmap *space = SPEC_OCLS (sym->etype);
386 /* if already has one */
390 /* assign depending on the storage class */
391 /* if it is on the stack or indirectly addressable */
392 /* space we need to assign either r0 or r1 to it */
393 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
395 sym->aop = aop = newAsmop (0);
396 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
397 aop->size = getSize (sym->type);
399 /* now assign the address of the variable to
400 the pointer register */
401 if (aop->type != AOP_STK)
407 emitcode ("push", "acc");
409 emitcode ("mov", "a,_bp");
410 emitcode ("add", "a,#0x%02x",
412 ((char) (sym->stack - _G.nRegsSaved)) :
413 ((char) sym->stack)) & 0xff);
414 emitcode ("mov", "%s,a",
415 aop->aopu.aop_ptr->name);
418 emitcode ("pop", "acc");
421 emitcode ("mov", "%s,#%s",
422 aop->aopu.aop_ptr->name,
424 aop->paged = space->paged;
427 aop->aopu.aop_stk = sym->stack;
431 if (sym->onStack && options.stack10bit)
433 /* It's on the 10 bit stack, which is located in
438 emitcode ("push", "acc");
440 emitcode ("mov", "a,_bp");
441 emitcode ("add", "a,#0x%02x",
443 ((char) (sym->stack - _G.nRegsSaved)) :
444 ((char) sym->stack)) & 0xff);
449 emitcode ("mov", "dpx1,#0x40");
450 emitcode ("mov", "dph1,#0x00");
451 emitcode ("mov", "dpl1, a");
456 emitcode ("mov", "dpx,#0x40");
457 emitcode ("mov", "dph,#0x00");
458 emitcode ("mov", "dpl, a");
462 emitcode ("pop", "acc");
464 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
465 aop->size = getSize (sym->type);
469 /* if in bit space */
470 if (IN_BITSPACE (space))
472 sym->aop = aop = newAsmop (AOP_CRY);
473 aop->aopu.aop_dir = sym->rname;
474 aop->size = getSize (sym->type);
477 /* if it is in direct space */
478 if (IN_DIRSPACE (space))
480 sym->aop = aop = newAsmop (AOP_DIR);
481 aop->aopu.aop_dir = sym->rname;
482 aop->size = getSize (sym->type);
486 /* special case for a function */
487 if (IS_FUNC (sym->type))
489 sym->aop = aop = newAsmop (AOP_IMMD);
490 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
491 strcpy (aop->aopu.aop_immd, sym->rname);
492 aop->size = FPTRSIZE;
496 /* only remaining is far space */
497 /* in which case DPTR gets the address */
498 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
503 emitcode ("mov", "dptr,#%s", sym->rname);
508 emitcode ("mov", "dptr,#%s", sym->rname);
510 aop->size = getSize (sym->type);
512 /* if it is in code space */
513 if (IN_CODESPACE (space))
519 /*-----------------------------------------------------------------*/
520 /* aopForRemat - rematerialzes an object */
521 /*-----------------------------------------------------------------*/
523 aopForRemat (symbol * sym)
525 iCode *ic = sym->rematiCode;
526 asmop *aop = newAsmop (AOP_IMMD);
533 val += (int) operandLitValue (IC_RIGHT (ic));
534 else if (ic->op == '-')
535 val -= (int) operandLitValue (IC_RIGHT (ic));
539 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
543 sprintf (buffer, "(%s %c 0x%04x)",
544 OP_SYMBOL (IC_LEFT (ic))->rname,
545 val >= 0 ? '+' : '-',
548 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
550 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
551 strcpy (aop->aopu.aop_immd, buffer);
555 /*-----------------------------------------------------------------*/
556 /* regsInCommon - two operands have some registers in common */
557 /*-----------------------------------------------------------------*/
559 regsInCommon (operand * op1, operand * op2)
564 /* if they have registers in common */
565 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
568 sym1 = OP_SYMBOL (op1);
569 sym2 = OP_SYMBOL (op2);
571 if (sym1->nRegs == 0 || sym2->nRegs == 0)
574 for (i = 0; i < sym1->nRegs; i++)
580 for (j = 0; j < sym2->nRegs; j++)
585 if (sym2->regs[j] == sym1->regs[i])
593 /*-----------------------------------------------------------------*/
594 /* operandsEqu - equivalent */
595 /*-----------------------------------------------------------------*/
597 operandsEqu (operand * op1, operand * op2)
601 /* if they not symbols */
602 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
605 sym1 = OP_SYMBOL (op1);
606 sym2 = OP_SYMBOL (op2);
608 /* if both are itemps & one is spilt
609 and the other is not then false */
610 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
611 sym1->isspilt != sym2->isspilt)
614 /* if they are the same */
618 if (strcmp (sym1->rname, sym2->rname) == 0)
622 /* if left is a tmp & right is not */
623 if (IS_ITEMP (op1) &&
626 (sym1->usl.spillLoc == sym2))
629 if (IS_ITEMP (op2) &&
633 (sym2->usl.spillLoc == sym1))
639 /*-----------------------------------------------------------------*/
640 /* sameRegs - two asmops have the same registers */
641 /*-----------------------------------------------------------------*/
643 sameRegs (asmop * aop1, asmop * aop2)
649 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
656 if (aop1->type != AOP_REG ||
657 aop2->type != AOP_REG)
660 if (aop1->size != aop2->size)
663 for (i = 0; i < aop1->size; i++)
664 if (aop1->aopu.aop_reg[i] !=
665 aop2->aopu.aop_reg[i])
671 /*-----------------------------------------------------------------*/
672 /* aopOp - allocates an asmop for an operand : */
673 /*-----------------------------------------------------------------*/
675 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
684 /* if this a literal */
685 if (IS_OP_LITERAL (op))
687 op->aop = aop = newAsmop (AOP_LIT);
688 aop->aopu.aop_lit = op->operand.valOperand;
689 aop->size = getSize (operandType (op));
693 /* if already has a asmop then continue */
697 /* if the underlying symbol has a aop */
698 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
700 op->aop = OP_SYMBOL (op)->aop;
704 /* if this is a true symbol */
705 if (IS_TRUE_SYMOP (op))
707 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
711 /* this is a temporary : this has
717 e) can be a return use only */
719 sym = OP_SYMBOL (op);
722 /* if the type is a conditional */
723 if (sym->regType == REG_CND)
725 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
730 /* if it is spilt then two situations
732 b) has a spill location */
733 if (sym->isspilt || sym->nRegs == 0)
736 /* rematerialize it NOW */
739 sym->aop = op->aop = aop =
741 aop->size = getSize (sym->type);
748 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
749 aop->size = getSize (sym->type);
750 for (i = 0; i < 2; i++)
751 aop->aopu.aop_str[i] = accUse[i];
761 /* a AOP_STR uses DPTR, but DPTR is already in use;
764 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
767 aop = op->aop = sym->aop = newAsmop (AOP_STR);
768 aop->size = getSize (sym->type);
769 for (i = 0; i < (int) fReturnSizeDS390; i++)
770 aop->aopu.aop_str[i] = fReturn[i];
774 /* else spill location */
775 sym->aop = op->aop = aop =
776 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
777 aop->size = getSize (sym->type);
781 /* must be in a register */
782 sym->aop = op->aop = aop = newAsmop (AOP_REG);
783 aop->size = sym->nRegs;
784 for (i = 0; i < sym->nRegs; i++)
785 aop->aopu.aop_reg[i] = sym->regs[i];
788 /*-----------------------------------------------------------------*/
789 /* freeAsmop - free up the asmop given to an operand */
790 /*----------------------------------------------------------------*/
792 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
809 /* depending on the asmop type only three cases need work AOP_RO
810 , AOP_R1 && AOP_STK */
818 emitcode ("pop", "ar0");
822 bitVectUnSetBit (ic->rUsed, R0_IDX);
830 emitcode ("pop", "ar1");
834 bitVectUnSetBit (ic->rUsed, R1_IDX);
840 int stk = aop->aopu.aop_stk + aop->size;
841 bitVectUnSetBit (ic->rUsed, R0_IDX);
842 bitVectUnSetBit (ic->rUsed, R1_IDX);
844 getFreePtr (ic, &aop, FALSE);
846 if (options.stack10bit)
848 /* I'm not sure what to do here yet... */
851 "*** Warning: probably generating bad code for "
852 "10 bit stack mode.\n");
857 emitcode ("mov", "a,_bp");
858 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
859 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
863 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
868 emitcode ("pop", "acc");
869 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
872 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
875 freeAsmop (op, NULL, ic, TRUE);
878 emitcode ("pop", "ar0");
884 emitcode ("pop", "ar1");
891 /* all other cases just dealloc */
897 OP_SYMBOL (op)->aop = NULL;
898 /* if the symbol has a spill */
900 SPIL_LOC (op)->aop = NULL;
905 /*------------------------------------------------------------------*/
906 /* aopGet - for fetching value of the aop */
908 /* Set canClobberACC if you are sure it is OK to clobber the value */
909 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
910 /* just less efficient. */
911 /*------------------------------------------------------------------*/
923 /* offset is greater than
925 if (offset > (aop->size - 1) &&
926 aop->type != AOP_LIT)
929 /* depending on type */
935 /* if we need to increment it */
936 while (offset > aop->coff)
938 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
942 while (offset < aop->coff)
944 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
951 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
952 return (dname ? "acc" : "a");
954 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
955 rs = Safe_calloc (1, strlen (s) + 1);
962 if (aop->type == AOP_DPTR2)
967 emitcode ("xch", "a, %s", DP2_RESULT_REG);
973 while (offset > aop->coff)
975 emitcode ("inc", "dptr");
979 while (offset < aop->coff)
981 emitcode ("lcall", "__decdptr");
988 emitcode ("clr", "a");
989 emitcode ("movc", "a,@a+dptr");
993 emitcode ("movx", "a,@dptr");
996 if (aop->type == AOP_DPTR2)
1001 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1002 return DP2_RESULT_REG;
1005 return (dname ? "acc" : "a");
1009 sprintf (s, "#%s", aop->aopu.aop_immd);
1011 sprintf (s, "#(%s >> %d)",
1016 aop->aopu.aop_immd);
1017 rs = Safe_calloc (1, strlen (s) + 1);
1023 sprintf (s, "(%s + %d)",
1027 sprintf (s, "%s", aop->aopu.aop_dir);
1028 rs = Safe_calloc (1, strlen (s) + 1);
1034 return aop->aopu.aop_reg[offset]->dname;
1036 return aop->aopu.aop_reg[offset]->name;
1039 emitcode ("clr", "a");
1040 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1041 emitcode ("rlc", "a");
1042 return (dname ? "acc" : "a");
1045 if (!offset && dname)
1047 return aop->aopu.aop_str[offset];
1050 return aopLiteral (aop->aopu.aop_lit, offset);
1054 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1058 return aop->aopu.aop_str[offset];
1062 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1063 "aopget got unsupported aop->type");
1066 /*-----------------------------------------------------------------*/
1067 /* aopPut - puts a string for a aop */
1068 /*-----------------------------------------------------------------*/
1070 aopPut (asmop * aop, char *s, int offset)
1074 if (aop->size && offset > (aop->size - 1))
1076 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1077 "aopPut got offset > aop->size");
1081 /* will assign value to value */
1082 /* depending on where it is ofcourse */
1087 sprintf (d, "(%s + %d)",
1088 aop->aopu.aop_dir, offset);
1090 sprintf (d, "%s", aop->aopu.aop_dir);
1093 emitcode ("mov", "%s,%s", d, s);
1098 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1099 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1102 strcmp (s, "r0") == 0 ||
1103 strcmp (s, "r1") == 0 ||
1104 strcmp (s, "r2") == 0 ||
1105 strcmp (s, "r3") == 0 ||
1106 strcmp (s, "r4") == 0 ||
1107 strcmp (s, "r5") == 0 ||
1108 strcmp (s, "r6") == 0 ||
1109 strcmp (s, "r7") == 0)
1110 emitcode ("mov", "%s,%s",
1111 aop->aopu.aop_reg[offset]->dname, s);
1113 emitcode ("mov", "%s,%s",
1114 aop->aopu.aop_reg[offset]->name, s);
1121 if (aop->type == AOP_DPTR2)
1129 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1130 "aopPut writting to code space");
1134 while (offset > aop->coff)
1137 emitcode ("inc", "dptr");
1140 while (offset < aop->coff)
1143 emitcode ("lcall", "__decdptr");
1148 /* if not in accumulater */
1151 emitcode ("movx", "@dptr,a");
1153 if (aop->type == AOP_DPTR2)
1161 while (offset > aop->coff)
1164 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1166 while (offset < aop->coff)
1169 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1176 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1182 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1184 else if (strcmp (s, "r0") == 0 ||
1185 strcmp (s, "r1") == 0 ||
1186 strcmp (s, "r2") == 0 ||
1187 strcmp (s, "r3") == 0 ||
1188 strcmp (s, "r4") == 0 ||
1189 strcmp (s, "r5") == 0 ||
1190 strcmp (s, "r6") == 0 ||
1191 strcmp (s, "r7") == 0)
1194 sprintf (buffer, "a%s", s);
1195 emitcode ("mov", "@%s,%s",
1196 aop->aopu.aop_ptr->name, buffer);
1199 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1204 if (strcmp (s, "a") == 0)
1205 emitcode ("push", "acc");
1207 emitcode ("push", "%s", s);
1212 /* if bit variable */
1213 if (!aop->aopu.aop_dir)
1215 emitcode ("clr", "a");
1216 emitcode ("rlc", "a");
1221 emitcode ("clr", "%s", aop->aopu.aop_dir);
1223 emitcode ("setb", "%s", aop->aopu.aop_dir);
1224 else if (!strcmp (s, "c"))
1225 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1228 if (strcmp (s, "a"))
1233 symbol *lbl = newiTempLabel (NULL);
1234 emitcode ("clr", "c");
1235 emitcode ("jz", "%05d$", lbl->key + 100);
1236 emitcode ("cpl", "c");
1237 emitcode ("", "%05d$:", lbl->key + 100);
1238 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1246 if (strcmp (aop->aopu.aop_str[offset], s))
1247 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1252 if (!offset && (strcmp (s, "acc") == 0))
1255 if (strcmp (aop->aopu.aop_str[offset], s))
1256 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1260 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1261 "aopPut got unsupported aop->type");
1268 /*--------------------------------------------------------------------*/
1269 /* reAdjustPreg - points a register back to where it should (coff==0) */
1270 /*--------------------------------------------------------------------*/
1272 reAdjustPreg (asmop * aop)
1274 if ((aop->coff==0) || (aop->size <= 1)) {
1283 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1287 if (aop->type == AOP_DPTR2)
1294 emitcode ("lcall", "__decdptr");
1297 if (aop->type == AOP_DPTR2)
1307 #define AOP(op) op->aop
1308 #define AOP_TYPE(op) AOP(op)->type
1309 #define AOP_SIZE(op) AOP(op)->size
1310 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1311 AOP_TYPE(x) == AOP_R0))
1313 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1314 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1317 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1318 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1319 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1321 /* Workaround for DS80C390 bug: div ab may return bogus results
1322 * if A is accessed in instruction immediately before the div.
1324 * Will be fixed in B4 rev of processor, Dallas claims.
1327 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1328 if (!AOP_NEEDSACC(RIGHT)) \
1330 /* We can load A first, then B, since \
1331 * B (the RIGHT operand) won't clobber A, \
1332 * thus avoiding touching A right before the div. \
1334 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1335 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1337 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1341 /* Just stuff in a nop after loading A. */ \
1342 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1343 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1345 emitcode("nop", "; workaround for DS80C390 div bug."); \
1348 /*-----------------------------------------------------------------*/
1349 /* genNotFloat - generates not for float operations */
1350 /*-----------------------------------------------------------------*/
1352 genNotFloat (operand * op, operand * res)
1358 D (emitcode (";", "genNotFloat ");
1361 /* we will put 127 in the first byte of
1363 aopPut (AOP (res), "#127", 0);
1364 size = AOP_SIZE (op) - 1;
1367 _startLazyDPSEvaluation ();
1368 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1373 emitcode ("orl", "a,%s",
1375 offset++, FALSE, FALSE, FALSE));
1377 _endLazyDPSEvaluation ();
1379 tlbl = newiTempLabel (NULL);
1380 aopPut (res->aop, one, 1);
1381 emitcode ("jz", "%05d$", (tlbl->key + 100));
1382 aopPut (res->aop, zero, 1);
1383 emitcode ("", "%05d$:", (tlbl->key + 100));
1385 size = res->aop->size - 2;
1387 /* put zeros in the rest */
1389 aopPut (res->aop, zero, offset++);
1392 /*-----------------------------------------------------------------*/
1393 /* opIsGptr: returns non-zero if the passed operand is */
1394 /* a generic pointer type. */
1395 /*-----------------------------------------------------------------*/
1397 opIsGptr (operand * op)
1399 sym_link *type = operandType (op);
1401 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1408 /*-----------------------------------------------------------------*/
1409 /* getDataSize - get the operand data size */
1410 /*-----------------------------------------------------------------*/
1412 getDataSize (operand * op)
1415 size = AOP_SIZE (op);
1416 if (size == GPTRSIZE)
1418 sym_link *type = operandType (op);
1419 if (IS_GENPTR (type))
1421 /* generic pointer; arithmetic operations
1422 * should ignore the high byte (pointer type).
1430 /*-----------------------------------------------------------------*/
1431 /* outAcc - output Acc */
1432 /*-----------------------------------------------------------------*/
1434 outAcc (operand * result)
1437 size = getDataSize (result);
1440 aopPut (AOP (result), "a", 0);
1443 /* unsigned or positive */
1446 aopPut (AOP (result), zero, offset++);
1451 /*-----------------------------------------------------------------*/
1452 /* outBitC - output a bit C */
1453 /*-----------------------------------------------------------------*/
1455 outBitC (operand * result)
1457 /* if the result is bit */
1458 if (AOP_TYPE (result) == AOP_CRY)
1460 aopPut (AOP (result), "c", 0);
1464 emitcode ("clr", "a");
1465 emitcode ("rlc", "a");
1470 /*-----------------------------------------------------------------*/
1471 /* toBoolean - emit code for orl a,operator(sizeop) */
1472 /*-----------------------------------------------------------------*/
1474 toBoolean (operand * oper)
1476 int size = AOP_SIZE (oper) - 1;
1480 /* The generic part of a generic pointer should
1481 * not participate in it's truth value.
1483 * i.e. 0x10000000 is zero.
1485 if (opIsGptr (oper))
1487 D (emitcode (";", "toBoolean: generic ptr special case.");
1492 _startLazyDPSEvaluation ();
1493 if (AOP_NEEDSACC (oper) && size)
1496 emitcode ("push", "b");
1497 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1501 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1507 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1511 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1514 _endLazyDPSEvaluation ();
1518 emitcode ("mov", "a,b");
1519 emitcode ("pop", "b");
1524 /*-----------------------------------------------------------------*/
1525 /* genNot - generate code for ! operation */
1526 /*-----------------------------------------------------------------*/
1531 sym_link *optype = operandType (IC_LEFT (ic));
1533 D (emitcode (";", "genNot ");
1536 /* assign asmOps to operand & result */
1537 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1538 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1540 /* if in bit space then a special case */
1541 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1543 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1544 emitcode ("cpl", "c");
1545 outBitC (IC_RESULT (ic));
1549 /* if type float then do float */
1550 if (IS_FLOAT (optype))
1552 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1556 toBoolean (IC_LEFT (ic));
1558 tlbl = newiTempLabel (NULL);
1559 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1560 emitcode ("", "%05d$:", tlbl->key + 100);
1561 outBitC (IC_RESULT (ic));
1564 /* release the aops */
1565 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1566 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1570 /*-----------------------------------------------------------------*/
1571 /* genCpl - generate code for complement */
1572 /*-----------------------------------------------------------------*/
1579 D (emitcode (";", "genCpl ");
1583 /* assign asmOps to operand & result */
1584 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1585 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1587 /* if both are in bit space then
1589 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1590 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1593 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1594 emitcode ("cpl", "c");
1595 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1599 size = AOP_SIZE (IC_RESULT (ic));
1600 _startLazyDPSEvaluation ();
1603 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1605 emitcode ("cpl", "a");
1606 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1608 _endLazyDPSEvaluation ();
1612 /* release the aops */
1613 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1614 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1617 /*-----------------------------------------------------------------*/
1618 /* genUminusFloat - unary minus for floating points */
1619 /*-----------------------------------------------------------------*/
1621 genUminusFloat (operand * op, operand * result)
1623 int size, offset = 0;
1625 /* for this we just need to flip the
1626 first it then copy the rest in place */
1627 D (emitcode (";", "genUminusFloat");
1630 _startLazyDPSEvaluation ();
1631 size = AOP_SIZE (op) - 1;
1632 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1635 emitcode ("cpl", "acc.7");
1636 aopPut (AOP (result), "a", 3);
1640 aopPut (AOP (result),
1641 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1645 _endLazyDPSEvaluation ();
1648 /*-----------------------------------------------------------------*/
1649 /* genUminus - unary minus code generation */
1650 /*-----------------------------------------------------------------*/
1652 genUminus (iCode * ic)
1655 sym_link *optype, *rtype;
1657 D (emitcode (";", "genUminus ");
1662 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1663 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1665 /* if both in bit space then special
1667 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1668 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1671 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1672 emitcode ("cpl", "c");
1673 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1677 optype = operandType (IC_LEFT (ic));
1678 rtype = operandType (IC_RESULT (ic));
1680 /* if float then do float stuff */
1681 if (IS_FLOAT (optype))
1683 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1687 /* otherwise subtract from zero */
1688 size = AOP_SIZE (IC_LEFT (ic));
1690 _startLazyDPSEvaluation ();
1693 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1694 if (!strcmp (l, "a"))
1698 emitcode ("cpl", "a");
1699 emitcode ("addc", "a,#0");
1705 emitcode ("clr", "a");
1706 emitcode ("subb", "a,%s", l);
1708 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1710 _endLazyDPSEvaluation ();
1712 /* if any remaining bytes in the result */
1713 /* we just need to propagate the sign */
1714 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1716 emitcode ("rlc", "a");
1717 emitcode ("subb", "a,acc");
1719 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1723 /* release the aops */
1724 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1725 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1728 /*-----------------------------------------------------------------*/
1729 /* saveRegisters - will look for a call and save the registers */
1730 /*-----------------------------------------------------------------*/
1732 saveRegisters (iCode * lic)
1740 for (ic = lic; ic; ic = ic->next)
1741 if (ic->op == CALL || ic->op == PCALL)
1746 fprintf (stderr, "found parameter push with no function call\n");
1750 /* if the registers have been saved already then
1752 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1755 /* find the registers in use at this time
1756 and push them away to safety */
1757 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1761 if (options.useXstack)
1763 if (bitVectBitValue (rsave, R0_IDX))
1764 emitcode ("mov", "b,r0");
1765 emitcode ("mov", "r0,%s", spname);
1766 for (i = 0; i < ds390_nRegs; i++)
1768 if (bitVectBitValue (rsave, i))
1771 emitcode ("mov", "a,b");
1773 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1774 emitcode ("movx", "@r0,a");
1775 emitcode ("inc", "r0");
1778 emitcode ("mov", "%s,r0", spname);
1779 if (bitVectBitValue (rsave, R0_IDX))
1780 emitcode ("mov", "r0,b");
1783 for (i = 0; i < ds390_nRegs; i++)
1785 if (bitVectBitValue (rsave, i))
1786 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1789 detype = getSpec (operandType (IC_LEFT (ic)));
1791 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1792 IS_ISR (currFunc->etype) &&
1795 saverbank (SPEC_BANK (detype), ic, TRUE);
1798 /*-----------------------------------------------------------------*/
1799 /* unsaveRegisters - pop the pushed registers */
1800 /*-----------------------------------------------------------------*/
1802 unsaveRegisters (iCode * ic)
1806 /* find the registers in use at this time
1807 and push them away to safety */
1808 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1811 if (options.useXstack)
1813 emitcode ("mov", "r0,%s", spname);
1814 for (i = ds390_nRegs; i >= 0; i--)
1816 if (bitVectBitValue (rsave, i))
1818 emitcode ("dec", "r0");
1819 emitcode ("movx", "a,@r0");
1821 emitcode ("mov", "b,a");
1823 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1827 emitcode ("mov", "%s,r0", spname);
1828 if (bitVectBitValue (rsave, R0_IDX))
1829 emitcode ("mov", "r0,b");
1832 for (i = ds390_nRegs; i >= 0; i--)
1834 if (bitVectBitValue (rsave, i))
1835 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1841 /*-----------------------------------------------------------------*/
1843 /*-----------------------------------------------------------------*/
1845 pushSide (operand * oper, int size)
1848 _startLazyDPSEvaluation ();
1851 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1852 if (AOP_TYPE (oper) != AOP_REG &&
1853 AOP_TYPE (oper) != AOP_DIR &&
1856 emitcode ("mov", "a,%s", l);
1857 emitcode ("push", "acc");
1860 emitcode ("push", "%s", l);
1862 _endLazyDPSEvaluation ();
1865 /*-----------------------------------------------------------------*/
1866 /* assignResultValue - */
1867 /*-----------------------------------------------------------------*/
1869 assignResultValue (operand * oper)
1872 int size = AOP_SIZE (oper);
1874 _startLazyDPSEvaluation ();
1877 aopPut (AOP (oper), fReturn[offset], offset);
1880 _endLazyDPSEvaluation ();
1884 /*-----------------------------------------------------------------*/
1885 /* genXpush - pushes onto the external stack */
1886 /*-----------------------------------------------------------------*/
1888 genXpush (iCode * ic)
1890 asmop *aop = newAsmop (0);
1892 int size, offset = 0;
1894 D (emitcode (";", "genXpush ");
1897 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1898 r = getFreePtr (ic, &aop, FALSE);
1901 emitcode ("mov", "%s,_spx", r->name);
1903 size = AOP_SIZE (IC_LEFT (ic));
1904 _startLazyDPSEvaluation ();
1908 char *l = aopGet (AOP (IC_LEFT (ic)),
1909 offset++, FALSE, FALSE, TRUE);
1911 emitcode ("movx", "@%s,a", r->name);
1912 emitcode ("inc", "%s", r->name);
1915 _endLazyDPSEvaluation ();
1918 emitcode ("mov", "_spx,%s", r->name);
1920 freeAsmop (NULL, aop, ic, TRUE);
1921 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1924 /*-----------------------------------------------------------------*/
1925 /* genIpush - genrate code for pushing this gets a little complex */
1926 /*-----------------------------------------------------------------*/
1928 genIpush (iCode * ic)
1930 int size, offset = 0;
1933 D (emitcode (";", "genIpush ");
1936 /* if this is not a parm push : ie. it is spill push
1937 and spill push is always done on the local stack */
1941 /* and the item is spilt then do nothing */
1942 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1945 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1946 size = AOP_SIZE (IC_LEFT (ic));
1947 /* push it on the stack */
1948 _startLazyDPSEvaluation ();
1951 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1957 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1959 _endLazyDPSEvaluation ();
1963 /* this is a paramter push: in this case we call
1964 the routine to find the call and save those
1965 registers that need to be saved */
1968 /* if use external stack then call the external
1969 stack pushing routine */
1970 if (options.useXstack)
1976 /* then do the push */
1977 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1979 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1980 size = AOP_SIZE (IC_LEFT (ic));
1982 _startLazyDPSEvaluation ();
1985 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1986 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1987 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1990 emitcode ("mov", "a,%s", l);
1991 emitcode ("push", "acc");
1994 emitcode ("push", "%s ;jwk genIpush", l);
1996 _endLazyDPSEvaluation ();
1998 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2001 /*-----------------------------------------------------------------*/
2002 /* genIpop - recover the registers: can happen only for spilling */
2003 /*-----------------------------------------------------------------*/
2005 genIpop (iCode * ic)
2009 D (emitcode (";", "genIpop ");
2013 /* if the temp was not pushed then */
2014 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2017 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2018 size = AOP_SIZE (IC_LEFT (ic));
2019 offset = (size - 1);
2020 _startLazyDPSEvaluation ();
2023 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2024 FALSE, TRUE, TRUE));
2026 _endLazyDPSEvaluation ();
2028 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2031 /*-----------------------------------------------------------------*/
2032 /* unsaverbank - restores the resgister bank from stack */
2033 /*-----------------------------------------------------------------*/
2035 unsaverbank (int bank, iCode * ic, bool popPsw)
2043 if (options.useXstack)
2046 r = getFreePtr (ic, &aop, FALSE);
2049 emitcode ("mov", "%s,_spx", r->name);
2050 emitcode ("movx", "a,@%s", r->name);
2051 emitcode ("mov", "psw,a");
2052 emitcode ("dec", "%s", r->name);
2056 emitcode ("pop", "psw");
2059 for (i = (ds390_nRegs - 1); i >= 0; i--)
2061 if (options.useXstack)
2063 emitcode ("movx", "a,@%s", r->name);
2064 emitcode ("mov", "(%s+%d),a",
2065 regs390[i].base, 8 * bank + regs390[i].offset);
2066 emitcode ("dec", "%s", r->name);
2070 emitcode ("pop", "(%s+%d)",
2071 regs390[i].base, 8 * bank + regs390[i].offset);
2074 if (options.useXstack)
2077 emitcode ("mov", "_spx,%s", r->name);
2078 freeAsmop (NULL, aop, ic, TRUE);
2083 /*-----------------------------------------------------------------*/
2084 /* saverbank - saves an entire register bank on the stack */
2085 /*-----------------------------------------------------------------*/
2087 saverbank (int bank, iCode * ic, bool pushPsw)
2093 if (options.useXstack)
2097 r = getFreePtr (ic, &aop, FALSE);
2098 emitcode ("mov", "%s,_spx", r->name);
2102 for (i = 0; i < ds390_nRegs; i++)
2104 if (options.useXstack)
2106 emitcode ("inc", "%s", r->name);
2107 emitcode ("mov", "a,(%s+%d)",
2108 regs390[i].base, 8 * bank + regs390[i].offset);
2109 emitcode ("movx", "@%s,a", r->name);
2112 emitcode ("push", "(%s+%d)",
2113 regs390[i].base, 8 * bank + regs390[i].offset);
2118 if (options.useXstack)
2120 emitcode ("mov", "a,psw");
2121 emitcode ("movx", "@%s,a", r->name);
2122 emitcode ("inc", "%s", r->name);
2123 emitcode ("mov", "_spx,%s", r->name);
2124 freeAsmop (NULL, aop, ic, TRUE);
2128 emitcode ("push", "psw");
2130 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2136 /*-----------------------------------------------------------------*/
2137 /* genCall - generates a call statement */
2138 /*-----------------------------------------------------------------*/
2140 genCall (iCode * ic)
2144 D (emitcode (";", "genCall ");
2147 /* if caller saves & we have not saved then */
2151 /* if we are calling a function that is not using
2152 the same register bank then we need to save the
2153 destination registers on the stack */
2154 detype = getSpec (operandType (IC_LEFT (ic)));
2156 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2157 IS_ISR (currFunc->etype) &&
2160 saverbank (SPEC_BANK (detype), ic, TRUE);
2162 /* if send set is not empty the assign */
2167 for (sic = setFirstItem (_G.sendSet); sic;
2168 sic = setNextItem (_G.sendSet))
2170 int size, offset = 0;
2172 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2173 size = AOP_SIZE (IC_LEFT (sic));
2175 _startLazyDPSEvaluation ();
2178 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2179 FALSE, FALSE, TRUE);
2180 if (strcmp (l, fReturn[offset])) {
2183 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2189 _endLazyDPSEvaluation ();
2190 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2195 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2196 OP_SYMBOL (IC_LEFT (ic))->rname :
2197 OP_SYMBOL (IC_LEFT (ic))->name));
2199 /* if we need assign a result value */
2200 if ((IS_ITEMP (IC_RESULT (ic)) &&
2201 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2202 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2203 IS_TRUE_SYMOP (IC_RESULT (ic)))
2205 if (isOperandInFarSpace (IC_RESULT (ic))
2206 && getSize (operandType (IC_RESULT (ic))) <= 2)
2208 int size = getSize (operandType (IC_RESULT (ic)));
2210 /* Special case for 1 or 2 byte return in far space. */
2211 emitcode (";", "Kevin function call abuse #1");
2216 emitcode ("mov", "b,%s", fReturn[1]);
2219 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2220 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2224 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2226 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2231 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2234 assignResultValue (IC_RESULT (ic));
2236 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2240 /* adjust the stack for parameters if
2245 if (ic->parmBytes > 3)
2247 emitcode ("mov", "a,%s", spname);
2248 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2249 emitcode ("mov", "%s,a", spname);
2252 for (i = 0; i < ic->parmBytes; i++)
2253 emitcode ("dec", "%s", spname);
2257 /* if register bank was saved then pop them */
2259 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2261 /* if we hade saved some registers then unsave them */
2262 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2263 unsaveRegisters (ic);
2268 /*-----------------------------------------------------------------*/
2269 /* genPcall - generates a call by pointer statement */
2270 /*-----------------------------------------------------------------*/
2272 genPcall (iCode * ic)
2275 symbol *rlbl = newiTempLabel (NULL);
2277 D (emitcode (";", "genPcall ");
2281 /* if caller saves & we have not saved then */
2285 /* if we are calling a function that is not using
2286 the same register bank then we need to save the
2287 destination registers on the stack */
2288 detype = getSpec (operandType (IC_LEFT (ic)));
2290 IS_ISR (currFunc->etype) &&
2291 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2292 saverbank (SPEC_BANK (detype), ic, TRUE);
2295 /* push the return address on to the stack */
2296 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2297 emitcode ("push", "acc");
2298 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2299 emitcode ("push", "acc");
2301 if (options.model == MODEL_FLAT24)
2303 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2304 emitcode ("push", "acc");
2307 /* now push the calling address */
2308 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2310 pushSide (IC_LEFT (ic), FPTRSIZE);
2312 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2314 /* if send set is not empty the assign */
2319 for (sic = setFirstItem (_G.sendSet); sic;
2320 sic = setNextItem (_G.sendSet))
2322 int size, offset = 0;
2324 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2325 size = AOP_SIZE (IC_LEFT (sic));
2326 _startLazyDPSEvaluation ();
2329 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2330 FALSE, FALSE, TRUE);
2331 if (strcmp (l, fReturn[offset]))
2333 emitcode ("mov", "%s,%s",
2339 _endLazyDPSEvaluation ();
2340 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2345 emitcode ("ret", "");
2346 emitcode ("", "%05d$:", (rlbl->key + 100));
2349 /* if we need assign a result value */
2350 if ((IS_ITEMP (IC_RESULT (ic)) &&
2351 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2352 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2353 IS_TRUE_SYMOP (IC_RESULT (ic)))
2357 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2360 assignResultValue (IC_RESULT (ic));
2362 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2365 /* adjust the stack for parameters if
2370 if (ic->parmBytes > 3)
2372 emitcode ("mov", "a,%s", spname);
2373 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2374 emitcode ("mov", "%s,a", spname);
2377 for (i = 0; i < ic->parmBytes; i++)
2378 emitcode ("dec", "%s", spname);
2382 /* if register bank was saved then unsave them */
2384 (SPEC_BANK (currFunc->etype) !=
2385 SPEC_BANK (detype)))
2386 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2388 /* if we hade saved some registers then
2391 unsaveRegisters (ic);
2395 /*-----------------------------------------------------------------*/
2396 /* resultRemat - result is rematerializable */
2397 /*-----------------------------------------------------------------*/
2399 resultRemat (iCode * ic)
2401 if (SKIP_IC (ic) || ic->op == IFX)
2404 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2406 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2407 if (sym->remat && !POINTER_SET (ic))
2414 #if defined(__BORLANDC__) || defined(_MSC_VER)
2415 #define STRCASECMP stricmp
2417 #define STRCASECMP strcasecmp
2420 /*-----------------------------------------------------------------*/
2421 /* inExcludeList - return 1 if the string is in exclude Reg list */
2422 /*-----------------------------------------------------------------*/
2424 inExcludeList (char *s)
2428 if (options.excludeRegs[i] &&
2429 STRCASECMP (options.excludeRegs[i], "none") == 0)
2432 for (i = 0; options.excludeRegs[i]; i++)
2434 if (options.excludeRegs[i] &&
2435 STRCASECMP (s, options.excludeRegs[i]) == 0)
2441 /*-----------------------------------------------------------------*/
2442 /* genFunction - generated code for function entry */
2443 /*-----------------------------------------------------------------*/
2445 genFunction (iCode * ic)
2450 D (emitcode (";", "genFunction ");
2454 /* create the function header */
2455 emitcode (";", "-----------------------------------------");
2456 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2457 emitcode (";", "-----------------------------------------");
2459 emitcode ("", "%s:", sym->rname);
2460 fetype = getSpec (operandType (IC_LEFT (ic)));
2462 /* if critical function then turn interrupts off */
2463 if (SPEC_CRTCL (fetype))
2464 emitcode ("clr", "ea");
2466 /* here we need to generate the equates for the
2467 register bank if required */
2468 if (SPEC_BANK (fetype) != rbank)
2472 rbank = SPEC_BANK (fetype);
2473 for (i = 0; i < ds390_nRegs; i++)
2475 if (strcmp (regs390[i].base, "0") == 0)
2476 emitcode ("", "%s = 0x%02x",
2478 8 * rbank + regs390[i].offset);
2480 emitcode ("", "%s = %s + 0x%02x",
2483 8 * rbank + regs390[i].offset);
2487 /* if this is an interrupt service routine then
2488 save acc, b, dpl, dph */
2489 if (IS_ISR (sym->etype))
2492 if (!inExcludeList ("acc"))
2493 emitcode ("push", "acc");
2494 if (!inExcludeList ("b"))
2495 emitcode ("push", "b");
2496 if (!inExcludeList ("dpl"))
2497 emitcode ("push", "dpl");
2498 if (!inExcludeList ("dph"))
2499 emitcode ("push", "dph");
2500 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2502 emitcode ("push", "dpx");
2503 /* Make sure we're using standard DPTR */
2504 emitcode ("push", "dps");
2505 emitcode ("mov", "dps, #0x00");
2506 if (options.stack10bit)
2508 /* This ISR could conceivably use DPTR2. Better save it. */
2509 emitcode ("push", "dpl1");
2510 emitcode ("push", "dph1");
2511 emitcode ("push", "dpx1");
2512 emitcode ("push", DP2_RESULT_REG);
2515 /* if this isr has no bank i.e. is going to
2516 run with bank 0 , then we need to save more
2518 if (!SPEC_BANK (sym->etype))
2521 /* if this function does not call any other
2522 function then we can be economical and
2523 save only those registers that are used */
2528 /* if any registers used */
2531 /* save the registers used */
2532 for (i = 0; i < sym->regsUsed->size; i++)
2534 if (bitVectBitValue (sym->regsUsed, i) ||
2535 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2536 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2543 /* this function has a function call cannot
2544 determines register usage so we will have the
2546 saverbank (0, ic, FALSE);
2552 /* if callee-save to be used for this function
2553 then save the registers being used in this function */
2554 if (sym->calleeSave)
2558 /* if any registers used */
2561 /* save the registers used */
2562 for (i = 0; i < sym->regsUsed->size; i++)
2564 if (bitVectBitValue (sym->regsUsed, i) ||
2565 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2567 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2575 /* set the register bank to the desired value */
2576 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2578 emitcode ("push", "psw");
2579 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2582 if (IS_RENT (sym->etype) || options.stackAuto)
2585 if (options.useXstack)
2587 emitcode ("mov", "r0,%s", spname);
2588 emitcode ("mov", "a,_bp");
2589 emitcode ("movx", "@r0,a");
2590 emitcode ("inc", "%s", spname);
2594 /* set up the stack */
2595 emitcode ("push", "_bp"); /* save the callers stack */
2597 emitcode ("mov", "_bp,%s", spname);
2600 /* adjust the stack for the function */
2606 werror (W_STACK_OVERFLOW, sym->name);
2608 if (i > 3 && sym->recvSize < 4)
2611 emitcode ("mov", "a,sp");
2612 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2613 emitcode ("mov", "sp,a");
2618 emitcode ("inc", "sp");
2624 emitcode ("mov", "a,_spx");
2625 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2626 emitcode ("mov", "_spx,a");
2631 /*-----------------------------------------------------------------*/
2632 /* genEndFunction - generates epilogue for functions */
2633 /*-----------------------------------------------------------------*/
2635 genEndFunction (iCode * ic)
2637 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2639 D (emitcode (";", "genEndFunction ");
2642 if (IS_RENT (sym->etype) || options.stackAuto)
2644 emitcode ("mov", "%s,_bp", spname);
2647 /* if use external stack but some variables were
2648 added to the local stack then decrement the
2650 if (options.useXstack && sym->stack)
2652 emitcode ("mov", "a,sp");
2653 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2654 emitcode ("mov", "sp,a");
2658 if ((IS_RENT (sym->etype) || options.stackAuto))
2660 if (options.useXstack)
2662 emitcode ("mov", "r0,%s", spname);
2663 emitcode ("movx", "a,@r0");
2664 emitcode ("mov", "_bp,a");
2665 emitcode ("dec", "%s", spname);
2669 emitcode ("pop", "_bp");
2673 /* restore the register bank */
2674 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2675 emitcode ("pop", "psw");
2677 if (IS_ISR (sym->etype))
2680 /* now we need to restore the registers */
2681 /* if this isr has no bank i.e. is going to
2682 run with bank 0 , then we need to save more
2684 if (!SPEC_BANK (sym->etype))
2687 /* if this function does not call any other
2688 function then we can be economical and
2689 save only those registers that are used */
2694 /* if any registers used */
2697 /* save the registers used */
2698 for (i = sym->regsUsed->size; i >= 0; i--)
2700 if (bitVectBitValue (sym->regsUsed, i) ||
2701 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2702 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2709 /* this function has a function call cannot
2710 determines register usage so we will have the
2712 unsaverbank (0, ic, FALSE);
2716 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2718 if (options.stack10bit)
2720 emitcode ("pop", DP2_RESULT_REG);
2721 emitcode ("pop", "dpx1");
2722 emitcode ("pop", "dph1");
2723 emitcode ("pop", "dpl1");
2725 emitcode ("pop", "dps");
2726 emitcode ("pop", "dpx");
2728 if (!inExcludeList ("dph"))
2729 emitcode ("pop", "dph");
2730 if (!inExcludeList ("dpl"))
2731 emitcode ("pop", "dpl");
2732 if (!inExcludeList ("b"))
2733 emitcode ("pop", "b");
2734 if (!inExcludeList ("acc"))
2735 emitcode ("pop", "acc");
2737 if (SPEC_CRTCL (sym->etype))
2738 emitcode ("setb", "ea");
2740 /* if debug then send end of function */
2741 /* if (options.debug && currFunc) { */
2745 emitcode ("", "C$%s$%d$%d$%d ==.",
2746 FileBaseName (ic->filename), currFunc->lastLine,
2747 ic->level, ic->block);
2748 if (IS_STATIC (currFunc->etype))
2749 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2751 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2755 emitcode ("reti", "");
2759 if (SPEC_CRTCL (sym->etype))
2760 emitcode ("setb", "ea");
2762 if (sym->calleeSave)
2766 /* if any registers used */
2769 /* save the registers used */
2770 for (i = sym->regsUsed->size; i >= 0; i--)
2772 if (bitVectBitValue (sym->regsUsed, i) ||
2773 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2774 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2780 /* if debug then send end of function */
2784 emitcode ("", "C$%s$%d$%d$%d ==.",
2785 FileBaseName (ic->filename), currFunc->lastLine,
2786 ic->level, ic->block);
2787 if (IS_STATIC (currFunc->etype))
2788 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2790 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2794 emitcode ("ret", "");
2799 /*-----------------------------------------------------------------*/
2800 /* genRet - generate code for return statement */
2801 /*-----------------------------------------------------------------*/
2805 int size, offset = 0, pushed = 0;
2807 D (emitcode (";", "genRet ");
2810 /* if we have no return value then
2811 just generate the "ret" */
2815 /* we have something to return then
2816 move the return value into place */
2817 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2818 size = AOP_SIZE (IC_LEFT (ic));
2820 _startLazyDPSEvaluation ();
2824 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2826 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2827 FALSE, TRUE, FALSE);
2828 emitcode ("push", "%s", l);
2833 l = aopGet (AOP (IC_LEFT (ic)), offset,
2834 FALSE, FALSE, FALSE);
2835 if (strcmp (fReturn[offset], l))
2836 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2839 _endLazyDPSEvaluation ();
2846 if (strcmp (fReturn[pushed], "a"))
2847 emitcode ("pop", fReturn[pushed]);
2849 emitcode ("pop", "acc");
2852 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2855 /* generate a jump to the return label
2856 if the next is not the return statement */
2857 if (!(ic->next && ic->next->op == LABEL &&
2858 IC_LABEL (ic->next) == returnLabel))
2860 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2864 /*-----------------------------------------------------------------*/
2865 /* genLabel - generates a label */
2866 /*-----------------------------------------------------------------*/
2868 genLabel (iCode * ic)
2870 /* special case never generate */
2871 if (IC_LABEL (ic) == entryLabel)
2874 D (emitcode (";", "genLabel ");
2877 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2880 /*-----------------------------------------------------------------*/
2881 /* genGoto - generates a ljmp */
2882 /*-----------------------------------------------------------------*/
2884 genGoto (iCode * ic)
2886 D (emitcode (";", "genGoto ");
2888 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2891 /*-----------------------------------------------------------------*/
2892 /* findLabelBackwards: walks back through the iCode chain looking */
2893 /* for the given label. Returns number of iCode instructions */
2894 /* between that label and given ic. */
2895 /* Returns zero if label not found. */
2896 /*-----------------------------------------------------------------*/
2898 findLabelBackwards (iCode * ic, int key)
2907 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2909 /* printf("findLabelBackwards = %d\n", count); */
2917 /*-----------------------------------------------------------------*/
2918 /* genPlusIncr :- does addition with increment if possible */
2919 /*-----------------------------------------------------------------*/
2921 genPlusIncr (iCode * ic)
2923 unsigned int icount;
2924 unsigned int size = getDataSize (IC_RESULT (ic));
2926 /* will try to generate an increment */
2927 /* if the right side is not a literal
2929 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2932 /* if the literal value of the right hand side
2933 is greater than 4 then it is not worth it */
2934 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2937 /* if increment 16 bits in register */
2939 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2940 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2941 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2949 /* If the next instruction is a goto and the goto target
2950 * is <= 5 instructions previous to this, we can generate
2951 * jumps straight to that target.
2953 if (ic->next && ic->next->op == GOTO
2954 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2957 emitcode (";", "tail increment optimized (range %d)", labelRange);
2958 tlbl = IC_LABEL (ic->next);
2963 tlbl = newiTempLabel (NULL);
2966 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2967 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2968 IS_AOP_PREG (IC_RESULT (ic)))
2969 emitcode ("cjne", "%s,#0x00,%05d$"
2970 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2974 emitcode ("clr", "a");
2975 emitcode ("cjne", "a,%s,%05d$"
2976 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2980 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2983 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2984 IS_AOP_PREG (IC_RESULT (ic)))
2985 emitcode ("cjne", "%s,#0x00,%05d$"
2986 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2989 emitcode ("cjne", "a,%s,%05d$"
2990 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2993 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
2997 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2998 IS_AOP_PREG (IC_RESULT (ic)))
2999 emitcode ("cjne", "%s,#0x00,%05d$"
3000 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3004 emitcode ("cjne", "a,%s,%05d$"
3005 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3008 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3013 emitcode ("", "%05d$:", tlbl->key + 100);
3018 /* if the sizes are greater than 1 then we cannot */
3019 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3020 AOP_SIZE (IC_LEFT (ic)) > 1)
3023 /* we can if the aops of the left & result match or
3024 if they are in registers and the registers are the
3027 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3028 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3029 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3034 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3035 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3036 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3041 _startLazyDPSEvaluation ();
3044 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3046 _endLazyDPSEvaluation ();
3055 /*-----------------------------------------------------------------*/
3056 /* outBitAcc - output a bit in acc */
3057 /*-----------------------------------------------------------------*/
3059 outBitAcc (operand * result)
3061 symbol *tlbl = newiTempLabel (NULL);
3062 /* if the result is a bit */
3063 if (AOP_TYPE (result) == AOP_CRY)
3065 aopPut (AOP (result), "a", 0);
3069 emitcode ("jz", "%05d$", tlbl->key + 100);
3070 emitcode ("mov", "a,%s", one);
3071 emitcode ("", "%05d$:", tlbl->key + 100);
3076 /*-----------------------------------------------------------------*/
3077 /* genPlusBits - generates code for addition of two bits */
3078 /*-----------------------------------------------------------------*/
3080 genPlusBits (iCode * ic)
3082 D (emitcode (";", "genPlusBits ");
3084 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3086 symbol *lbl = newiTempLabel (NULL);
3087 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3088 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3089 emitcode ("cpl", "c");
3090 emitcode ("", "%05d$:", (lbl->key + 100));
3091 outBitC (IC_RESULT (ic));
3095 emitcode ("clr", "a");
3096 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3097 emitcode ("rlc", "a");
3098 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3099 emitcode ("addc", "a,#0x00");
3100 outAcc (IC_RESULT (ic));
3105 adjustArithmeticResult (iCode * ic)
3107 if (opIsGptr (IC_RESULT (ic)) &&
3108 opIsGptr (IC_LEFT (ic)) &&
3109 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3111 aopPut (AOP (IC_RESULT (ic)),
3112 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3116 if (opIsGptr (IC_RESULT (ic)) &&
3117 opIsGptr (IC_RIGHT (ic)) &&
3118 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3120 aopPut (AOP (IC_RESULT (ic)),
3121 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3125 if (opIsGptr (IC_RESULT (ic)) &&
3126 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3127 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3128 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3129 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3132 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3133 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3137 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3138 // (because all three operands are in far space).
3139 #define AOP_OP_3(ic) \
3140 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3141 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3142 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3143 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3144 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3145 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3147 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3149 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3152 // Macro to aopOp all three operands of an ic. If this cannot be done,
3153 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3154 // will be set TRUE. The caller must then handle the case specially, noting
3155 // that the IC_RESULT operand is not aopOp'd.
3156 #define AOP_OP_3_NOFATAL(ic, rc) \
3157 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3158 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3159 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3160 isOperandInFarSpace(IC_RESULT(ic))) \
3162 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3167 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3168 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3170 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3171 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3173 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3175 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3179 // aopOp the left & right operands of an ic.
3180 #define AOP_OP_2(ic) \
3181 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3182 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3184 // convienience macro.
3185 #define AOP_SET_LOCALS(ic) \
3186 left = IC_LEFT(ic); \
3187 right = IC_RIGHT(ic); \
3188 result = IC_RESULT(ic);
3191 // Given an integer value of pushedSize bytes on the stack,
3192 // adjust it to be resultSize bytes, either by discarding
3193 // the most significant bytes or by zero-padding.
3195 // On exit from this macro, pushedSize will have been adjusted to
3196 // equal resultSize, and ACC may be trashed.
3197 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3198 /* If the pushed data is bigger than the result, \
3199 * simply discard unused bytes. Icky, but works. \
3201 while (pushedSize > resultSize) \
3203 D (emitcode (";", "discarding unused result byte."););\
3204 emitcode ("pop", "acc"); \
3207 if (pushedSize < resultSize) \
3209 emitcode ("clr", "a"); \
3210 /* Conversly, we haven't pushed enough here. \
3211 * just zero-pad, and all is well. \
3213 while (pushedSize < resultSize) \
3215 emitcode("push", "acc"); \
3219 assert(pushedSize == resultSize);
3221 /*-----------------------------------------------------------------*/
3222 /* genPlus - generates code for addition */
3223 /*-----------------------------------------------------------------*/
3225 genPlus (iCode * ic)
3227 int size, offset = 0;
3228 bool pushResult = FALSE;
3231 D (emitcode (";", "genPlus "););
3233 /* special cases :- */
3235 AOP_OP_3_NOFATAL (ic, pushResult);
3238 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3243 /* if literal, literal on the right or
3244 if left requires ACC or right is already
3246 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3247 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3248 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3250 operand *t = IC_RIGHT (ic);
3251 IC_RIGHT (ic) = IC_LEFT (ic);
3253 emitcode (";", "Swapped plus args.");
3256 /* if both left & right are in bit
3258 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3259 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3265 /* if left in bit space & right literal */
3266 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3267 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3269 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3270 /* if result in bit space */
3271 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3273 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3274 emitcode ("cpl", "c");
3275 outBitC (IC_RESULT (ic));
3279 size = getDataSize (IC_RESULT (ic));
3280 _startLazyDPSEvaluation ();
3283 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3284 emitcode ("addc", "a,#00");
3285 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3287 _endLazyDPSEvaluation ();
3292 /* if I can do an increment instead
3293 of add then GOOD for ME */
3294 if (genPlusIncr (ic) == TRUE)
3296 emitcode (";", "did genPlusIncr");
3301 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3303 _startLazyDPSEvaluation ();
3306 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3308 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3310 emitcode ("add", "a,%s",
3311 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3313 emitcode ("addc", "a,%s",
3314 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3318 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3320 emitcode ("add", "a,%s",
3321 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3323 emitcode ("addc", "a,%s",
3324 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3328 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3332 emitcode ("push", "acc");
3336 _endLazyDPSEvaluation ();
3340 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3342 size = getDataSize (IC_LEFT (ic));
3343 rSize = getDataSize (IC_RESULT (ic));
3345 ADJUST_PUSHED_RESULT(size, rSize);
3347 _startLazyDPSEvaluation ();
3350 emitcode ("pop", "acc");
3351 aopPut (AOP (IC_RESULT (ic)), "a", size);
3353 _endLazyDPSEvaluation ();
3356 adjustArithmeticResult (ic);
3359 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3360 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3361 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3364 /*-----------------------------------------------------------------*/
3365 /* genMinusDec :- does subtraction with deccrement if possible */
3366 /*-----------------------------------------------------------------*/
3368 genMinusDec (iCode * ic)
3370 unsigned int icount;
3371 unsigned int size = getDataSize (IC_RESULT (ic));
3373 /* will try to generate an increment */
3374 /* if the right side is not a literal
3376 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3379 /* if the literal value of the right hand side
3380 is greater than 4 then it is not worth it */
3381 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3384 /* if decrement 16 bits in register */
3385 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3386 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3387 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3395 /* If the next instruction is a goto and the goto target
3396 * is <= 5 instructions previous to this, we can generate
3397 * jumps straight to that target.
3399 if (ic->next && ic->next->op == GOTO
3400 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3403 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3404 tlbl = IC_LABEL (ic->next);
3409 tlbl = newiTempLabel (NULL);
3413 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3414 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3415 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3416 IS_AOP_PREG (IC_RESULT (ic)))
3417 emitcode ("cjne", "%s,#0xff,%05d$"
3418 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3422 emitcode ("mov", "a,#0xff");
3423 emitcode ("cjne", "a,%s,%05d$"
3424 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3427 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3430 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3431 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3432 IS_AOP_PREG (IC_RESULT (ic)))
3433 emitcode ("cjne", "%s,#0xff,%05d$"
3434 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3438 emitcode ("cjne", "a,%s,%05d$"
3439 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3442 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3446 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3447 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3448 IS_AOP_PREG (IC_RESULT (ic)))
3449 emitcode ("cjne", "%s,#0xff,%05d$"
3450 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3454 emitcode ("cjne", "a,%s,%05d$"
3455 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3458 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3462 emitcode ("", "%05d$:", tlbl->key + 100);
3467 /* if the sizes are greater than 1 then we cannot */
3468 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3469 AOP_SIZE (IC_LEFT (ic)) > 1)
3472 /* we can if the aops of the left & result match or
3473 if they are in registers and the registers are the
3476 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3477 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3478 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3481 _startLazyDPSEvaluation ();
3484 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3486 _endLazyDPSEvaluation ();
3494 /*-----------------------------------------------------------------*/
3495 /* addSign - complete with sign */
3496 /*-----------------------------------------------------------------*/
3498 addSign (operand * result, int offset, int sign)
3500 int size = (getDataSize (result) - offset);
3505 emitcode ("rlc", "a");
3506 emitcode ("subb", "a,acc");
3508 aopPut (AOP (result), "a", offset++);
3512 aopPut (AOP (result), zero, offset++);
3516 /*-----------------------------------------------------------------*/
3517 /* genMinusBits - generates code for subtraction of two bits */
3518 /*-----------------------------------------------------------------*/
3520 genMinusBits (iCode * ic)
3522 symbol *lbl = newiTempLabel (NULL);
3524 D (emitcode (";", "genMinusBits ");
3527 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3529 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3530 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3531 emitcode ("cpl", "c");
3532 emitcode ("", "%05d$:", (lbl->key + 100));
3533 outBitC (IC_RESULT (ic));
3537 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3538 emitcode ("subb", "a,acc");
3539 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3540 emitcode ("inc", "a");
3541 emitcode ("", "%05d$:", (lbl->key + 100));
3542 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3543 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3547 /*-----------------------------------------------------------------*/
3548 /* genMinus - generates code for subtraction */
3549 /*-----------------------------------------------------------------*/
3551 genMinus (iCode * ic)
3553 int size, offset = 0;
3555 unsigned long lit = 0L;
3556 bool pushResult = FALSE;
3558 D (emitcode (";", "genMinus "););
3560 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3561 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3562 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3563 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3569 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3571 /* special cases :- */
3572 /* if both left & right are in bit space */
3573 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3574 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3580 /* if I can do an decrement instead
3581 of subtract then GOOD for ME */
3582 if (genMinusDec (ic) == TRUE)
3587 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3589 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3595 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3600 /* if literal, add a,#-lit, else normal subb */
3601 _startLazyDPSEvaluation ();
3604 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3605 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3606 emitcode ("subb", "a,%s",
3607 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3610 /* first add without previous c */
3612 emitcode ("add", "a,#0x%02x",
3613 (unsigned int) (lit & 0x0FFL));
3615 emitcode ("addc", "a,#0x%02x",
3616 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3621 emitcode ("push", "acc");
3625 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3629 _endLazyDPSEvaluation ();
3633 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3635 size = getDataSize (IC_LEFT (ic));
3636 rSize = getDataSize (IC_RESULT (ic));
3638 ADJUST_PUSHED_RESULT(size, rSize);
3640 _startLazyDPSEvaluation ();
3643 emitcode ("pop", "acc");
3644 aopPut (AOP (IC_RESULT (ic)), "a", size);
3646 _endLazyDPSEvaluation ();
3649 adjustArithmeticResult (ic);
3652 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3653 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3654 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3658 /*-----------------------------------------------------------------*/
3659 /* genMultbits :- multiplication of bits */
3660 /*-----------------------------------------------------------------*/
3662 genMultbits (operand * left,
3666 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3667 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3672 /*-----------------------------------------------------------------*/
3673 /* genMultOneByte : 8*8=8/16 bit multiplication */
3674 /*-----------------------------------------------------------------*/
3676 genMultOneByte (operand * left,
3680 sym_link *opetype = operandType (result);
3682 int size=AOP_SIZE(result);
3684 emitcode (";",__FUNCTION__);
3685 if (size<1 || size>2) {
3686 // this should never happen
3687 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3688 AOP_SIZE(result), __FUNCTION__, lineno);
3692 /* (if two literals: the value is computed before) */
3693 /* if one literal, literal on the right */
3694 if (AOP_TYPE (left) == AOP_LIT)
3699 emitcode (";", "swapped left and right");
3702 if (SPEC_USIGN(opetype)
3703 // ignore the sign of left and right, what else can we do?
3704 || (SPEC_USIGN(operandType(left)) &&
3705 SPEC_USIGN(operandType(right)))) {
3706 // just an unsigned 8*8=8/16 multiply
3707 //emitcode (";","unsigned");
3708 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3709 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3710 emitcode ("mul", "ab");
3711 aopPut (AOP (result), "a", 0);
3713 aopPut (AOP (result), "b", 1);
3718 // we have to do a signed multiply
3720 emitcode (";", "signed");
3721 emitcode ("clr", "F0"); // reset sign flag
3722 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3723 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3725 lbl=newiTempLabel(NULL);
3726 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3727 // left side is negative, 8-bit two's complement, this fails for -128
3728 emitcode ("setb", "F0"); // set sign flag
3729 emitcode ("cpl", "a");
3730 emitcode ("inc", "a");
3732 emitcode ("", "%05d$:", lbl->key+100);
3733 emitcode ("xch", "a,b");
3736 if (AOP_TYPE(right)==AOP_LIT) {
3737 /* AND literal negative */
3738 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3739 // two's complement for literal<0
3740 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3741 emitcode ("cpl", "a");
3742 emitcode ("inc", "a");
3745 lbl=newiTempLabel(NULL);
3746 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3747 // right side is negative, 8-bit two's complement
3748 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3749 emitcode ("cpl", "a");
3750 emitcode ("inc", "a");
3751 emitcode ("", "%05d$:", lbl->key+100);
3753 emitcode ("mul", "ab");
3755 lbl=newiTempLabel(NULL);
3756 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3757 // only ONE op was negative, we have to do a 8/16-bit two's complement
3758 emitcode ("cpl", "a"); // lsb
3760 emitcode ("inc", "a");
3762 emitcode ("add", "a,#1");
3763 emitcode ("xch", "a,b");
3764 emitcode ("cpl", "a"); // msb
3765 emitcode ("addc", "a,#0");
3766 emitcode ("xch", "a,b");
3769 emitcode ("", "%05d$:", lbl->key+100);
3770 aopPut (AOP (result), "a", 0);
3772 aopPut (AOP (result), "b", 1);
3776 /*-----------------------------------------------------------------*/
3777 /* genMult - generates code for multiplication */
3778 /*-----------------------------------------------------------------*/
3780 genMult (iCode * ic)
3782 operand *left = IC_LEFT (ic);
3783 operand *right = IC_RIGHT (ic);
3784 operand *result = IC_RESULT (ic);
3786 D (emitcode (";", "genMult "););
3788 /* assign the amsops */
3791 /* special cases first */
3793 if (AOP_TYPE (left) == AOP_CRY &&
3794 AOP_TYPE (right) == AOP_CRY)
3796 genMultbits (left, right, result);
3800 /* if both are of size == 1 */
3801 if (AOP_SIZE (left) == 1 &&
3802 AOP_SIZE (right) == 1)
3804 genMultOneByte (left, right, result);
3808 /* should have been converted to function call */
3812 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3813 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3814 freeAsmop (result, NULL, ic, TRUE);
3817 /*-----------------------------------------------------------------*/
3818 /* genDivbits :- division of bits */
3819 /*-----------------------------------------------------------------*/
3821 genDivbits (operand * left,
3828 /* the result must be bit */
3829 LOAD_AB_FOR_DIV (left, right, l);
3830 emitcode ("div", "ab");
3831 emitcode ("rrc", "a");
3832 aopPut (AOP (result), "c", 0);
3835 /*-----------------------------------------------------------------*/
3836 /* genDivOneByte : 8 bit division */
3837 /*-----------------------------------------------------------------*/
3839 genDivOneByte (operand * left,
3843 sym_link *opetype = operandType (result);
3848 size = AOP_SIZE (result) - 1;
3850 /* signed or unsigned */
3851 if (SPEC_USIGN (opetype))
3853 /* unsigned is easy */
3854 LOAD_AB_FOR_DIV (left, right, l);
3855 emitcode ("div", "ab");
3856 aopPut (AOP (result), "a", 0);
3858 aopPut (AOP (result), zero, offset++);
3862 /* signed is a little bit more difficult */
3864 /* save the signs of the operands */
3865 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3867 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3868 emitcode ("push", "acc"); /* save it on the stack */
3870 /* now sign adjust for both left & right */
3871 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3873 lbl = newiTempLabel (NULL);
3874 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3875 emitcode ("cpl", "a");
3876 emitcode ("inc", "a");
3877 emitcode ("", "%05d$:", (lbl->key + 100));
3878 emitcode ("mov", "b,a");
3880 /* sign adjust left side */
3881 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3884 lbl = newiTempLabel (NULL);
3885 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3886 emitcode ("cpl", "a");
3887 emitcode ("inc", "a");
3888 emitcode ("", "%05d$:", (lbl->key + 100));
3890 /* now the division */
3891 emitcode ("nop", "; workaround for DS80C390 div bug.");
3892 emitcode ("div", "ab");
3893 /* we are interested in the lower order
3895 emitcode ("mov", "b,a");
3896 lbl = newiTempLabel (NULL);
3897 emitcode ("pop", "acc");
3898 /* if there was an over flow we don't
3899 adjust the sign of the result */
3900 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3901 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3903 emitcode ("clr", "a");
3904 emitcode ("subb", "a,b");
3905 emitcode ("mov", "b,a");
3906 emitcode ("", "%05d$:", (lbl->key + 100));
3908 /* now we are done */
3909 aopPut (AOP (result), "b", 0);
3912 emitcode ("mov", "c,b.7");
3913 emitcode ("subb", "a,acc");
3916 aopPut (AOP (result), "a", offset++);
3920 /*-----------------------------------------------------------------*/
3921 /* genDiv - generates code for division */
3922 /*-----------------------------------------------------------------*/
3926 operand *left = IC_LEFT (ic);
3927 operand *right = IC_RIGHT (ic);
3928 operand *result = IC_RESULT (ic);
3930 D (emitcode (";", "genDiv ");
3933 /* assign the amsops */
3936 /* special cases first */
3938 if (AOP_TYPE (left) == AOP_CRY &&
3939 AOP_TYPE (right) == AOP_CRY)
3941 genDivbits (left, right, result);
3945 /* if both are of size == 1 */
3946 if (AOP_SIZE (left) == 1 &&
3947 AOP_SIZE (right) == 1)
3949 genDivOneByte (left, right, result);
3953 /* should have been converted to function call */
3956 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3957 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3958 freeAsmop (result, NULL, ic, TRUE);
3961 /*-----------------------------------------------------------------*/
3962 /* genModbits :- modulus of bits */
3963 /*-----------------------------------------------------------------*/
3965 genModbits (operand * left,
3972 /* the result must be bit */
3973 LOAD_AB_FOR_DIV (left, right, l);
3974 emitcode ("div", "ab");
3975 emitcode ("mov", "a,b");
3976 emitcode ("rrc", "a");
3977 aopPut (AOP (result), "c", 0);
3980 /*-----------------------------------------------------------------*/
3981 /* genModOneByte : 8 bit modulus */
3982 /*-----------------------------------------------------------------*/
3984 genModOneByte (operand * left,
3988 sym_link *opetype = operandType (result);
3992 /* signed or unsigned */
3993 if (SPEC_USIGN (opetype))
3995 /* unsigned is easy */
3996 LOAD_AB_FOR_DIV (left, right, l);
3997 emitcode ("div", "ab");
3998 aopPut (AOP (result), "b", 0);
4002 /* signed is a little bit more difficult */
4004 /* save the signs of the operands */
4005 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4008 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4009 emitcode ("push", "acc"); /* save it on the stack */
4011 /* now sign adjust for both left & right */
4012 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4015 lbl = newiTempLabel (NULL);
4016 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4017 emitcode ("cpl", "a");
4018 emitcode ("inc", "a");
4019 emitcode ("", "%05d$:", (lbl->key + 100));
4020 emitcode ("mov", "b,a");
4022 /* sign adjust left side */
4023 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4026 lbl = newiTempLabel (NULL);
4027 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4028 emitcode ("cpl", "a");
4029 emitcode ("inc", "a");
4030 emitcode ("", "%05d$:", (lbl->key + 100));
4032 /* now the multiplication */
4033 emitcode ("nop", "; workaround for DS80C390 div bug.");
4034 emitcode ("div", "ab");
4035 /* we are interested in the lower order
4037 lbl = newiTempLabel (NULL);
4038 emitcode ("pop", "acc");
4039 /* if there was an over flow we don't
4040 adjust the sign of the result */
4041 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4042 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4044 emitcode ("clr", "a");
4045 emitcode ("subb", "a,b");
4046 emitcode ("mov", "b,a");
4047 emitcode ("", "%05d$:", (lbl->key + 100));
4049 /* now we are done */
4050 aopPut (AOP (result), "b", 0);
4054 /*-----------------------------------------------------------------*/
4055 /* genMod - generates code for division */
4056 /*-----------------------------------------------------------------*/
4060 operand *left = IC_LEFT (ic);
4061 operand *right = IC_RIGHT (ic);
4062 operand *result = IC_RESULT (ic);
4064 D (emitcode (";", "genMod ");
4067 /* assign the amsops */
4070 /* special cases first */
4072 if (AOP_TYPE (left) == AOP_CRY &&
4073 AOP_TYPE (right) == AOP_CRY)
4075 genModbits (left, right, result);
4079 /* if both are of size == 1 */
4080 if (AOP_SIZE (left) == 1 &&
4081 AOP_SIZE (right) == 1)
4083 genModOneByte (left, right, result);
4087 /* should have been converted to function call */
4091 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4092 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4093 freeAsmop (result, NULL, ic, TRUE);
4096 /*-----------------------------------------------------------------*/
4097 /* genIfxJump :- will create a jump depending on the ifx */
4098 /*-----------------------------------------------------------------*/
4100 genIfxJump (iCode * ic, char *jval)
4103 symbol *tlbl = newiTempLabel (NULL);
4106 D (emitcode (";", "genIfxJump ");
4109 /* if true label then we jump if condition
4113 jlbl = IC_TRUE (ic);
4114 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4115 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4119 /* false label is present */
4120 jlbl = IC_FALSE (ic);
4121 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4122 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4124 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4125 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4127 emitcode (inst, "%05d$", tlbl->key + 100);
4128 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4129 emitcode ("", "%05d$:", tlbl->key + 100);
4131 /* mark the icode as generated */
4135 /*-----------------------------------------------------------------*/
4136 /* genCmp :- greater or less than comparison */
4137 /*-----------------------------------------------------------------*/
4139 genCmp (operand * left, operand * right,
4140 iCode * ic, iCode * ifx, int sign)
4142 int size, offset = 0;
4143 unsigned long lit = 0L;
4146 D (emitcode (";", "genCmp");
4149 result = IC_RESULT (ic);
4151 /* if left & right are bit variables */
4152 if (AOP_TYPE (left) == AOP_CRY &&
4153 AOP_TYPE (right) == AOP_CRY)
4155 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4156 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4160 /* subtract right from left if at the
4161 end the carry flag is set then we know that
4162 left is greater than right */
4163 size = max (AOP_SIZE (left), AOP_SIZE (right));
4165 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4166 if ((size == 1) && !sign &&
4167 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4169 symbol *lbl = newiTempLabel (NULL);
4170 emitcode ("cjne", "%s,%s,%05d$",
4171 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4172 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4174 emitcode ("", "%05d$:", lbl->key + 100);
4178 if (AOP_TYPE (right) == AOP_LIT)
4180 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4181 /* optimize if(x < 0) or if(x >= 0) */
4190 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4192 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4193 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4195 aopOp (result, ic, FALSE, FALSE);
4197 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4199 freeAsmop (result, NULL, ic, TRUE);
4200 genIfxJump (ifx, "acc.7");
4205 emitcode ("rlc", "a");
4207 goto release_freedLR;
4215 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4216 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4217 emitcode (";", "genCmp #2");
4218 if (sign && (size == 0))
4220 emitcode (";", "genCmp #3");
4221 emitcode ("xrl", "a,#0x80");
4222 if (AOP_TYPE (right) == AOP_LIT)
4224 unsigned long lit = (unsigned long)
4225 floatFromVal (AOP (right)->aopu.aop_lit);
4226 emitcode (";", "genCmp #3.1");
4227 emitcode ("subb", "a,#0x%02x",
4228 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4232 emitcode (";", "genCmp #3.2");
4233 if (AOP_NEEDSACC (right))
4235 emitcode ("push", "acc");
4237 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4238 FALSE, FALSE, FALSE));
4239 emitcode ("xrl", "b,#0x80");
4240 if (AOP_NEEDSACC (right))
4242 emitcode ("pop", "acc");
4244 emitcode ("subb", "a,b");
4251 emitcode (";", "genCmp #4");
4252 if (AOP_NEEDSACC (right))
4255 emitcode (";", "genCmp #4.1");
4256 emitcode ("xch", "a, b");
4257 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4258 emitcode ("xch", "a, b");
4263 emitcode (";", "genCmp #4.2");
4264 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4267 emitcode ("subb", "a,%s", s);
4274 /* Don't need the left & right operands any more; do need the result. */
4275 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4276 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4278 aopOp (result, ic, FALSE, FALSE);
4282 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4288 /* if the result is used in the next
4289 ifx conditional branch then generate
4290 code a little differently */
4293 genIfxJump (ifx, "c");
4299 /* leave the result in acc */
4301 freeAsmop (result, NULL, ic, TRUE);
4304 /*-----------------------------------------------------------------*/
4305 /* genCmpGt :- greater than comparison */
4306 /*-----------------------------------------------------------------*/
4308 genCmpGt (iCode * ic, iCode * ifx)
4310 operand *left, *right;
4311 sym_link *letype, *retype;
4314 D (emitcode (";", "genCmpGt ");
4317 left = IC_LEFT (ic);
4318 right = IC_RIGHT (ic);
4320 letype = getSpec (operandType (left));
4321 retype = getSpec (operandType (right));
4322 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4324 /* assign the left & right amsops */
4327 genCmp (right, left, ic, ifx, sign);
4330 /*-----------------------------------------------------------------*/
4331 /* genCmpLt - less than comparisons */
4332 /*-----------------------------------------------------------------*/
4334 genCmpLt (iCode * ic, iCode * ifx)
4336 operand *left, *right;
4337 sym_link *letype, *retype;
4340 D (emitcode (";", "genCmpLt "););
4342 left = IC_LEFT (ic);
4343 right = IC_RIGHT (ic);
4345 letype = getSpec (operandType (left));
4346 retype = getSpec (operandType (right));
4347 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4349 /* assign the left & right amsops */
4352 genCmp (left, right, ic, ifx, sign);
4355 /*-----------------------------------------------------------------*/
4356 /* gencjneshort - compare and jump if not equal */
4357 /*-----------------------------------------------------------------*/
4359 gencjneshort (operand * left, operand * right, symbol * lbl)
4361 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4363 unsigned long lit = 0L;
4365 D (emitcode (";", "gencjneshort");
4368 /* if the left side is a literal or
4369 if the right is in a pointer register and left
4371 if ((AOP_TYPE (left) == AOP_LIT) ||
4372 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4379 if (AOP_TYPE (right) == AOP_LIT)
4380 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4382 if (opIsGptr (left) || opIsGptr (right))
4384 /* We are comparing a generic pointer to something.
4385 * Exclude the generic type byte from the comparison.
4388 D (emitcode (";", "cjneshort: generic ptr special case.");
4393 /* if the right side is a literal then anything goes */
4394 if (AOP_TYPE (right) == AOP_LIT &&
4395 AOP_TYPE (left) != AOP_DIR)
4399 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4401 emitcode ("cjne", "a,%s,%05d$",
4402 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4408 /* if the right side is in a register or in direct space or
4409 if the left is a pointer register & right is not */
4410 else if (AOP_TYPE (right) == AOP_REG ||
4411 AOP_TYPE (right) == AOP_DIR ||
4412 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4413 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4417 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4418 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4419 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4420 emitcode ("jnz", "%05d$", lbl->key + 100);
4422 emitcode ("cjne", "a,%s,%05d$",
4423 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4430 /* right is a pointer reg need both a & b */
4433 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4434 if (strcmp (l, "b"))
4435 emitcode ("mov", "b,%s", l);
4436 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4437 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4443 /*-----------------------------------------------------------------*/
4444 /* gencjne - compare and jump if not equal */
4445 /*-----------------------------------------------------------------*/
4447 gencjne (operand * left, operand * right, symbol * lbl)
4449 symbol *tlbl = newiTempLabel (NULL);
4451 D (emitcode (";", "gencjne");
4454 gencjneshort (left, right, lbl);
4456 emitcode ("mov", "a,%s", one);
4457 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4458 emitcode ("", "%05d$:", lbl->key + 100);
4459 emitcode ("clr", "a");
4460 emitcode ("", "%05d$:", tlbl->key + 100);
4463 /*-----------------------------------------------------------------*/
4464 /* genCmpEq - generates code for equal to */
4465 /*-----------------------------------------------------------------*/
4467 genCmpEq (iCode * ic, iCode * ifx)
4469 operand *left, *right, *result;
4471 D (emitcode (";", "genCmpEq ");
4475 AOP_SET_LOCALS (ic);
4477 /* if literal, literal on the right or
4478 if the right is in a pointer register and left
4480 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4481 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4483 operand *t = IC_RIGHT (ic);
4484 IC_RIGHT (ic) = IC_LEFT (ic);
4488 if (ifx && /* !AOP_SIZE(result) */
4489 OP_SYMBOL (result) &&
4490 OP_SYMBOL (result)->regType == REG_CND)
4493 /* if they are both bit variables */
4494 if (AOP_TYPE (left) == AOP_CRY &&
4495 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4497 if (AOP_TYPE (right) == AOP_LIT)
4499 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4502 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4503 emitcode ("cpl", "c");
4507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4511 emitcode ("clr", "c");
4513 /* AOP_TYPE(right) == AOP_CRY */
4517 symbol *lbl = newiTempLabel (NULL);
4518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4519 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4520 emitcode ("cpl", "c");
4521 emitcode ("", "%05d$:", (lbl->key + 100));
4523 /* if true label then we jump if condition
4525 tlbl = newiTempLabel (NULL);
4528 emitcode ("jnc", "%05d$", tlbl->key + 100);
4529 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4533 emitcode ("jc", "%05d$", tlbl->key + 100);
4534 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4536 emitcode ("", "%05d$:", tlbl->key + 100);
4540 tlbl = newiTempLabel (NULL);
4541 gencjneshort (left, right, tlbl);
4544 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4545 emitcode ("", "%05d$:", tlbl->key + 100);
4549 symbol *lbl = newiTempLabel (NULL);
4550 emitcode ("sjmp", "%05d$", lbl->key + 100);
4551 emitcode ("", "%05d$:", tlbl->key + 100);
4552 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4553 emitcode ("", "%05d$:", lbl->key + 100);
4556 /* mark the icode as generated */
4559 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4560 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4564 /* if they are both bit variables */
4565 if (AOP_TYPE (left) == AOP_CRY &&
4566 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4568 if (AOP_TYPE (right) == AOP_LIT)
4570 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4573 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4574 emitcode ("cpl", "c");
4578 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4582 emitcode ("clr", "c");
4584 /* AOP_TYPE(right) == AOP_CRY */
4588 symbol *lbl = newiTempLabel (NULL);
4589 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4590 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4591 emitcode ("cpl", "c");
4592 emitcode ("", "%05d$:", (lbl->key + 100));
4595 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4596 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598 aopOp (result, ic, TRUE, FALSE);
4601 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4608 genIfxJump (ifx, "c");
4611 /* if the result is used in an arithmetic operation
4612 then put the result in place */
4617 gencjne (left, right, newiTempLabel (NULL));
4619 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4622 aopOp (result, ic, TRUE, FALSE);
4624 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4626 aopPut (AOP (result), "a", 0);
4631 genIfxJump (ifx, "a");
4634 /* if the result is used in an arithmetic operation
4635 then put the result in place */
4636 if (AOP_TYPE (result) != AOP_CRY)
4638 /* leave the result in acc */
4642 freeAsmop (result, NULL, ic, TRUE);
4645 /*-----------------------------------------------------------------*/
4646 /* ifxForOp - returns the icode containing the ifx for operand */
4647 /*-----------------------------------------------------------------*/
4649 ifxForOp (operand * op, iCode * ic)
4651 /* if true symbol then needs to be assigned */
4652 if (IS_TRUE_SYMOP (op))
4655 /* if this has register type condition and
4656 the next instruction is ifx with the same operand
4657 and live to of the operand is upto the ifx only then */
4659 ic->next->op == IFX &&
4660 IC_COND (ic->next)->key == op->key &&
4661 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4666 /*-----------------------------------------------------------------*/
4667 /* genAndOp - for && operation */
4668 /*-----------------------------------------------------------------*/
4670 genAndOp (iCode * ic)
4672 operand *left, *right, *result;
4675 D (emitcode (";", "genAndOp "););
4677 /* note here that && operations that are in an
4678 if statement are taken away by backPatchLabels
4679 only those used in arthmetic operations remain */
4681 AOP_SET_LOCALS (ic);
4683 /* if both are bit variables */
4684 if (AOP_TYPE (left) == AOP_CRY &&
4685 AOP_TYPE (right) == AOP_CRY)
4687 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4688 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4689 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4690 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4692 aopOp (result,ic,FALSE, FALSE);
4697 tlbl = newiTempLabel (NULL);
4699 emitcode ("jz", "%05d$", tlbl->key + 100);
4701 emitcode ("", "%05d$:", tlbl->key + 100);
4702 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4703 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4705 aopOp (result,ic,FALSE, FALSE);
4708 freeAsmop (result, NULL, ic, TRUE);
4712 /*-----------------------------------------------------------------*/
4713 /* genOrOp - for || operation */
4714 /*-----------------------------------------------------------------*/
4716 genOrOp (iCode * ic)
4718 operand *left, *right, *result;
4721 D (emitcode (";", "genOrOp "););
4723 /* note here that || operations that are in an
4724 if statement are taken away by backPatchLabels
4725 only those used in arthmetic operations remain */
4727 AOP_SET_LOCALS (ic);
4729 /* if both are bit variables */
4730 if (AOP_TYPE (left) == AOP_CRY &&
4731 AOP_TYPE (right) == AOP_CRY)
4733 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4734 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4735 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4736 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4738 aopOp (result,ic,FALSE, FALSE);
4744 tlbl = newiTempLabel (NULL);
4746 emitcode ("jnz", "%05d$", tlbl->key + 100);
4748 emitcode ("", "%05d$:", tlbl->key + 100);
4749 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4752 aopOp (result,ic,FALSE, FALSE);
4757 freeAsmop (result, NULL, ic, TRUE);
4760 /*-----------------------------------------------------------------*/
4761 /* isLiteralBit - test if lit == 2^n */
4762 /*-----------------------------------------------------------------*/
4764 isLiteralBit (unsigned long lit)
4766 unsigned long pw[32] =
4767 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4768 0x100L, 0x200L, 0x400L, 0x800L,
4769 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4770 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4771 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4772 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4773 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4776 for (idx = 0; idx < 32; idx++)
4782 /*-----------------------------------------------------------------*/
4783 /* continueIfTrue - */
4784 /*-----------------------------------------------------------------*/
4786 continueIfTrue (iCode * ic)
4789 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4793 /*-----------------------------------------------------------------*/
4795 /*-----------------------------------------------------------------*/
4797 jumpIfTrue (iCode * ic)
4800 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4804 /*-----------------------------------------------------------------*/
4805 /* jmpTrueOrFalse - */
4806 /*-----------------------------------------------------------------*/
4808 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4810 // ugly but optimized by peephole
4813 symbol *nlbl = newiTempLabel (NULL);
4814 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4815 emitcode ("", "%05d$:", tlbl->key + 100);
4816 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4817 emitcode ("", "%05d$:", nlbl->key + 100);
4821 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4822 emitcode ("", "%05d$:", tlbl->key + 100);
4827 // Generate code to perform a bit-wise logic operation
4828 // on two operands in far space (assumed to already have been
4829 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4830 // in far space. This requires pushing the result on the stack
4831 // then popping it into the result.
4833 genFarFarLogicOp(iCode *ic, char *logicOp)
4835 int size, resultSize, compSize;
4838 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4839 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4840 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4842 _startLazyDPSEvaluation();
4843 for (size = compSize; (size--); offset++)
4845 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4846 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4847 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4849 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4850 emitcode ("push", "acc");
4852 _endLazyDPSEvaluation();
4854 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4855 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4856 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4858 resultSize = AOP_SIZE(IC_RESULT(ic));
4860 ADJUST_PUSHED_RESULT(compSize, resultSize);
4862 _startLazyDPSEvaluation();
4865 emitcode ("pop", "acc");
4866 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4868 _endLazyDPSEvaluation();
4869 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4873 /*-----------------------------------------------------------------*/
4874 /* genAnd - code for and */
4875 /*-----------------------------------------------------------------*/
4877 genAnd (iCode * ic, iCode * ifx)
4879 operand *left, *right, *result;
4880 int size, offset = 0;
4881 unsigned long lit = 0L;
4886 D (emitcode (";", "genAnd "););
4888 AOP_OP_3_NOFATAL (ic, pushResult);
4889 AOP_SET_LOCALS (ic);
4893 genFarFarLogicOp(ic, "anl");
4898 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4900 AOP_TYPE (left), AOP_TYPE (right));
4901 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4903 AOP_SIZE (left), AOP_SIZE (right));
4906 /* if left is a literal & right is not then exchange them */
4907 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4908 AOP_NEEDSACC (left))
4910 operand *tmp = right;
4915 /* if result = right then exchange them */
4916 if (sameRegs (AOP (result), AOP (right)))
4918 operand *tmp = right;
4923 /* if right is bit then exchange them */
4924 if (AOP_TYPE (right) == AOP_CRY &&
4925 AOP_TYPE (left) != AOP_CRY)
4927 operand *tmp = right;
4931 if (AOP_TYPE (right) == AOP_LIT)
4932 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4934 size = AOP_SIZE (result);
4937 // result = bit & yy;
4938 if (AOP_TYPE (left) == AOP_CRY)
4940 // c = bit & literal;
4941 if (AOP_TYPE (right) == AOP_LIT)
4945 if (size && sameRegs (AOP (result), AOP (left)))
4948 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4953 if (size && (AOP_TYPE (result) == AOP_CRY))
4955 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4958 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4963 emitcode ("clr", "c");
4968 if (AOP_TYPE (right) == AOP_CRY)
4971 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4972 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4977 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4979 emitcode ("rrc", "a");
4980 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4988 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4989 genIfxJump (ifx, "c");
4993 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4994 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4995 if ((AOP_TYPE (right) == AOP_LIT) &&
4996 (AOP_TYPE (result) == AOP_CRY) &&
4997 (AOP_TYPE (left) != AOP_CRY))
4999 int posbit = isLiteralBit (lit);
5004 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5007 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5013 sprintf (buffer, "acc.%d", posbit & 0x07);
5014 genIfxJump (ifx, buffer);
5021 symbol *tlbl = newiTempLabel (NULL);
5022 int sizel = AOP_SIZE (left);
5024 emitcode ("setb", "c");
5027 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5029 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5031 if ((posbit = isLiteralBit (bytelit)) != 0)
5032 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5035 if (bytelit != 0x0FFL)
5036 emitcode ("anl", "a,%s",
5037 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5038 emitcode ("jnz", "%05d$", tlbl->key + 100);
5043 // bit = left & literal
5046 emitcode ("clr", "c");
5047 emitcode ("", "%05d$:", tlbl->key + 100);
5049 // if(left & literal)
5053 jmpTrueOrFalse (ifx, tlbl);
5061 /* if left is same as result */
5062 if (sameRegs (AOP (result), AOP (left)))
5064 for (; size--; offset++)
5066 if (AOP_TYPE (right) == AOP_LIT)
5068 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5070 else if (bytelit == 0)
5071 aopPut (AOP (result), zero, offset);
5072 else if (IS_AOP_PREG (result))
5074 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5075 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5076 aopPut (AOP (result), "a", offset);
5079 emitcode ("anl", "%s,%s",
5080 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5081 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5085 if (AOP_TYPE (left) == AOP_ACC)
5086 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5089 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5090 if (IS_AOP_PREG (result))
5092 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5093 aopPut (AOP (result), "a", offset);
5097 emitcode ("anl", "%s,a",
5098 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5105 // left & result in different registers
5106 if (AOP_TYPE (result) == AOP_CRY)
5109 // if(size), result in bit
5110 // if(!size && ifx), conditional oper: if(left & right)
5111 symbol *tlbl = newiTempLabel (NULL);
5112 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5114 emitcode ("setb", "c");
5117 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5118 emitcode ("anl", "a,%s",
5119 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5120 emitcode ("jnz", "%05d$", tlbl->key + 100);
5126 emitcode ("", "%05d$:", tlbl->key + 100);
5130 jmpTrueOrFalse (ifx, tlbl);
5134 for (; (size--); offset++)
5137 // result = left & right
5138 if (AOP_TYPE (right) == AOP_LIT)
5140 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5142 aopPut (AOP (result),
5143 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5147 else if (bytelit == 0)
5149 aopPut (AOP (result), zero, offset);
5152 D (emitcode (";", "better literal AND.");
5154 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5155 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5156 FALSE, FALSE, FALSE));
5161 // faster than result <- left, anl result,right
5162 // and better if result is SFR
5163 if (AOP_TYPE (left) == AOP_ACC)
5165 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5166 FALSE, FALSE, FALSE));
5170 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5171 emitcode ("anl", "a,%s",
5172 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5175 aopPut (AOP (result), "a", offset);
5181 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5182 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5183 freeAsmop (result, NULL, ic, TRUE);
5187 /*-----------------------------------------------------------------*/
5188 /* genOr - code for or */
5189 /*-----------------------------------------------------------------*/
5191 genOr (iCode * ic, iCode * ifx)
5193 operand *left, *right, *result;
5194 int size, offset = 0;
5195 unsigned long lit = 0L;
5198 D (emitcode (";", "genOr "););
5200 AOP_OP_3_NOFATAL (ic, pushResult);
5201 AOP_SET_LOCALS (ic);
5205 genFarFarLogicOp(ic, "orl");
5211 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5213 AOP_TYPE (left), AOP_TYPE (right));
5214 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5216 AOP_SIZE (left), AOP_SIZE (right));
5219 /* if left is a literal & right is not then exchange them */
5220 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5221 AOP_NEEDSACC (left))
5223 operand *tmp = right;
5228 /* if result = right then exchange them */
5229 if (sameRegs (AOP (result), AOP (right)))
5231 operand *tmp = right;
5236 /* if right is bit then exchange them */
5237 if (AOP_TYPE (right) == AOP_CRY &&
5238 AOP_TYPE (left) != AOP_CRY)
5240 operand *tmp = right;
5244 if (AOP_TYPE (right) == AOP_LIT)
5245 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5247 size = AOP_SIZE (result);
5251 if (AOP_TYPE (left) == AOP_CRY)
5253 if (AOP_TYPE (right) == AOP_LIT)
5255 // c = bit & literal;
5258 // lit != 0 => result = 1
5259 if (AOP_TYPE (result) == AOP_CRY)
5262 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5264 continueIfTrue (ifx);
5267 emitcode ("setb", "c");
5271 // lit == 0 => result = left
5272 if (size && sameRegs (AOP (result), AOP (left)))
5274 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5279 if (AOP_TYPE (right) == AOP_CRY)
5282 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5283 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5288 symbol *tlbl = newiTempLabel (NULL);
5289 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5290 emitcode ("setb", "c");
5291 emitcode ("jb", "%s,%05d$",
5292 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5294 emitcode ("jnz", "%05d$", tlbl->key + 100);
5295 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5297 jmpTrueOrFalse (ifx, tlbl);
5303 emitcode ("", "%05d$:", tlbl->key + 100);
5312 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5313 genIfxJump (ifx, "c");
5317 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5318 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5319 if ((AOP_TYPE (right) == AOP_LIT) &&
5320 (AOP_TYPE (result) == AOP_CRY) &&
5321 (AOP_TYPE (left) != AOP_CRY))
5327 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5329 continueIfTrue (ifx);
5334 // lit = 0, result = boolean(left)
5336 emitcode ("setb", "c");
5340 symbol *tlbl = newiTempLabel (NULL);
5341 emitcode ("jnz", "%05d$", tlbl->key + 100);
5343 emitcode ("", "%05d$:", tlbl->key + 100);
5347 genIfxJump (ifx, "a");
5355 /* if left is same as result */
5356 if (sameRegs (AOP (result), AOP (left)))
5358 for (; size--; offset++)
5360 if (AOP_TYPE (right) == AOP_LIT)
5362 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5368 if (IS_AOP_PREG (left))
5370 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5371 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5372 aopPut (AOP (result), "a", offset);
5376 emitcode ("orl", "%s,%s",
5377 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5378 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5384 if (AOP_TYPE (left) == AOP_ACC)
5386 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5390 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5391 if (IS_AOP_PREG (left))
5393 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5394 aopPut (AOP (result), "a", offset);
5398 emitcode ("orl", "%s,a",
5399 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5407 // left & result in different registers
5408 if (AOP_TYPE (result) == AOP_CRY)
5411 // if(size), result in bit
5412 // if(!size && ifx), conditional oper: if(left | right)
5413 symbol *tlbl = newiTempLabel (NULL);
5414 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5416 emitcode ("setb", "c");
5419 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5420 emitcode ("orl", "a,%s",
5421 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5422 emitcode ("jnz", "%05d$", tlbl->key + 100);
5428 emitcode ("", "%05d$:", tlbl->key + 100);
5432 jmpTrueOrFalse (ifx, tlbl);
5436 for (; (size--); offset++)
5439 // result = left & right
5440 if (AOP_TYPE (right) == AOP_LIT)
5442 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5444 aopPut (AOP (result),
5445 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5449 D (emitcode (";", "better literal OR.");
5451 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5452 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5453 FALSE, FALSE, FALSE));
5458 // faster than result <- left, anl result,right
5459 // and better if result is SFR
5460 if (AOP_TYPE (left) == AOP_ACC)
5462 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5463 FALSE, FALSE, FALSE));
5467 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5468 emitcode ("orl", "a,%s",
5469 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5472 aopPut (AOP (result), "a", offset);
5478 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5479 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5480 freeAsmop (result, NULL, ic, TRUE);
5483 /*-----------------------------------------------------------------*/
5484 /* genXor - code for xclusive or */
5485 /*-----------------------------------------------------------------*/
5487 genXor (iCode * ic, iCode * ifx)
5489 operand *left, *right, *result;
5490 int size, offset = 0;
5491 unsigned long lit = 0L;
5494 D (emitcode (";", "genXor "););
5496 AOP_OP_3_NOFATAL (ic, pushResult);
5497 AOP_SET_LOCALS (ic);
5501 genFarFarLogicOp(ic, "xrl");
5506 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5508 AOP_TYPE (left), AOP_TYPE (right));
5509 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5511 AOP_SIZE (left), AOP_SIZE (right));
5514 /* if left is a literal & right is not ||
5515 if left needs acc & right does not */
5516 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5517 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5519 operand *tmp = right;
5524 /* if result = right then exchange them */
5525 if (sameRegs (AOP (result), AOP (right)))
5527 operand *tmp = right;
5532 /* if right is bit then exchange them */
5533 if (AOP_TYPE (right) == AOP_CRY &&
5534 AOP_TYPE (left) != AOP_CRY)
5536 operand *tmp = right;
5540 if (AOP_TYPE (right) == AOP_LIT)
5541 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5543 size = AOP_SIZE (result);
5547 if (AOP_TYPE (left) == AOP_CRY)
5549 if (AOP_TYPE (right) == AOP_LIT)
5551 // c = bit & literal;
5554 // lit>>1 != 0 => result = 1
5555 if (AOP_TYPE (result) == AOP_CRY)
5558 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5560 continueIfTrue (ifx);
5563 emitcode ("setb", "c");
5570 // lit == 0, result = left
5571 if (size && sameRegs (AOP (result), AOP (left)))
5573 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5577 // lit == 1, result = not(left)
5578 if (size && sameRegs (AOP (result), AOP (left)))
5580 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5585 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5586 emitcode ("cpl", "c");
5595 symbol *tlbl = newiTempLabel (NULL);
5596 if (AOP_TYPE (right) == AOP_CRY)
5599 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5603 int sizer = AOP_SIZE (right);
5605 // if val>>1 != 0, result = 1
5606 emitcode ("setb", "c");
5609 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5611 // test the msb of the lsb
5612 emitcode ("anl", "a,#0xfe");
5613 emitcode ("jnz", "%05d$", tlbl->key + 100);
5617 emitcode ("rrc", "a");
5619 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5620 emitcode ("cpl", "c");
5621 emitcode ("", "%05d$:", (tlbl->key + 100));
5628 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5629 genIfxJump (ifx, "c");
5633 if (sameRegs (AOP (result), AOP (left)))
5635 /* if left is same as result */
5636 for (; size--; offset++)
5638 if (AOP_TYPE (right) == AOP_LIT)
5640 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5642 else if (IS_AOP_PREG (left))
5644 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5645 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5646 aopPut (AOP (result), "a", offset);
5649 emitcode ("xrl", "%s,%s",
5650 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5651 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5655 if (AOP_TYPE (left) == AOP_ACC)
5656 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5659 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5660 if (IS_AOP_PREG (left))
5662 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5663 aopPut (AOP (result), "a", offset);
5666 emitcode ("xrl", "%s,a",
5667 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5674 // left & result in different registers
5675 if (AOP_TYPE (result) == AOP_CRY)
5678 // if(size), result in bit
5679 // if(!size && ifx), conditional oper: if(left ^ right)
5680 symbol *tlbl = newiTempLabel (NULL);
5681 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5683 emitcode ("setb", "c");
5686 if ((AOP_TYPE (right) == AOP_LIT) &&
5687 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5689 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5693 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5694 emitcode ("xrl", "a,%s",
5695 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5697 emitcode ("jnz", "%05d$", tlbl->key + 100);
5703 emitcode ("", "%05d$:", tlbl->key + 100);
5707 jmpTrueOrFalse (ifx, tlbl);
5710 for (; (size--); offset++)
5713 // result = left & right
5714 if (AOP_TYPE (right) == AOP_LIT)
5716 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5718 aopPut (AOP (result),
5719 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5723 D (emitcode (";", "better literal XOR.");
5725 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5726 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5727 FALSE, FALSE, FALSE));
5731 // faster than result <- left, anl result,right
5732 // and better if result is SFR
5733 if (AOP_TYPE (left) == AOP_ACC)
5735 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5736 FALSE, FALSE, FALSE));
5740 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5741 emitcode ("xrl", "a,%s",
5742 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5745 aopPut (AOP (result), "a", offset);
5750 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5751 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5752 freeAsmop (result, NULL, ic, TRUE);
5755 /*-----------------------------------------------------------------*/
5756 /* genInline - write the inline code out */
5757 /*-----------------------------------------------------------------*/
5759 genInline (iCode * ic)
5761 char buffer[MAX_INLINEASM];
5765 D (emitcode (";", "genInline ");
5768 _G.inLine += (!options.asmpeep);
5769 strcpy (buffer, IC_INLINE (ic));
5771 /* emit each line as a code */
5796 /* emitcode("",buffer); */
5797 _G.inLine -= (!options.asmpeep);
5800 /*-----------------------------------------------------------------*/
5801 /* genRRC - rotate right with carry */
5802 /*-----------------------------------------------------------------*/
5806 operand *left, *result;
5807 int size, offset = 0;
5810 D (emitcode (";", "genRRC ");
5813 /* rotate right with carry */
5814 left = IC_LEFT (ic);
5815 result = IC_RESULT (ic);
5816 aopOp (left, ic, FALSE, FALSE);
5817 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5819 /* move it to the result */
5820 size = AOP_SIZE (result);
5824 _startLazyDPSEvaluation ();
5827 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5829 emitcode ("rrc", "a");
5830 if (AOP_SIZE (result) > 1)
5831 aopPut (AOP (result), "a", offset--);
5833 _endLazyDPSEvaluation ();
5835 /* now we need to put the carry into the
5836 highest order byte of the result */
5837 if (AOP_SIZE (result) > 1)
5839 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5842 emitcode ("mov", "acc.7,c");
5843 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5844 freeAsmop (left, NULL, ic, TRUE);
5845 freeAsmop (result, NULL, ic, TRUE);
5848 /*-----------------------------------------------------------------*/
5849 /* genRLC - generate code for rotate left with carry */
5850 /*-----------------------------------------------------------------*/
5854 operand *left, *result;
5855 int size, offset = 0;
5858 D (emitcode (";", "genRLC ");
5861 /* rotate right with carry */
5862 left = IC_LEFT (ic);
5863 result = IC_RESULT (ic);
5864 aopOp (left, ic, FALSE, FALSE);
5865 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5867 /* move it to the result */
5868 size = AOP_SIZE (result);
5872 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5874 emitcode ("add", "a,acc");
5875 if (AOP_SIZE (result) > 1)
5877 aopPut (AOP (result), "a", offset++);
5880 _startLazyDPSEvaluation ();
5883 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5885 emitcode ("rlc", "a");
5886 if (AOP_SIZE (result) > 1)
5887 aopPut (AOP (result), "a", offset++);
5889 _endLazyDPSEvaluation ();
5891 /* now we need to put the carry into the
5892 highest order byte of the result */
5893 if (AOP_SIZE (result) > 1)
5895 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5898 emitcode ("mov", "acc.0,c");
5899 aopPut (AOP (result), "a", 0);
5900 freeAsmop (left, NULL, ic, TRUE);
5901 freeAsmop (result, NULL, ic, TRUE);
5904 /*-----------------------------------------------------------------*/
5905 /* genGetHbit - generates code get highest order bit */
5906 /*-----------------------------------------------------------------*/
5908 genGetHbit (iCode * ic)
5910 operand *left, *result;
5911 left = IC_LEFT (ic);
5912 result = IC_RESULT (ic);
5913 aopOp (left, ic, FALSE, FALSE);
5914 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5916 D (emitcode (";", "genGetHbit ");
5919 /* get the highest order byte into a */
5920 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5921 if (AOP_TYPE (result) == AOP_CRY)
5923 emitcode ("rlc", "a");
5928 emitcode ("rl", "a");
5929 emitcode ("anl", "a,#0x01");
5934 freeAsmop (left, NULL, ic, TRUE);
5935 freeAsmop (result, NULL, ic, TRUE);
5938 /*-----------------------------------------------------------------*/
5939 /* AccRol - rotate left accumulator by known count */
5940 /*-----------------------------------------------------------------*/
5942 AccRol (int shCount)
5944 shCount &= 0x0007; // shCount : 0..7
5951 emitcode ("rl", "a");
5954 emitcode ("rl", "a");
5955 emitcode ("rl", "a");
5958 emitcode ("swap", "a");
5959 emitcode ("rr", "a");
5962 emitcode ("swap", "a");
5965 emitcode ("swap", "a");
5966 emitcode ("rl", "a");
5969 emitcode ("rr", "a");
5970 emitcode ("rr", "a");
5973 emitcode ("rr", "a");
5978 /*-----------------------------------------------------------------*/
5979 /* AccLsh - left shift accumulator by known count */
5980 /*-----------------------------------------------------------------*/
5982 AccLsh (int shCount)
5987 emitcode ("add", "a,acc");
5988 else if (shCount == 2)
5990 emitcode ("add", "a,acc");
5991 emitcode ("add", "a,acc");
5995 /* rotate left accumulator */
5997 /* and kill the lower order bits */
5998 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6003 /*-----------------------------------------------------------------*/
6004 /* AccRsh - right shift accumulator by known count */
6005 /*-----------------------------------------------------------------*/
6007 AccRsh (int shCount)
6014 emitcode ("rrc", "a");
6018 /* rotate right accumulator */
6019 AccRol (8 - shCount);
6020 /* and kill the higher order bits */
6021 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6028 /*-----------------------------------------------------------------*/
6029 /* AccSRsh - signed right shift accumulator by known count */
6030 /*-----------------------------------------------------------------*/
6032 AccSRsh (int shCount)
6039 emitcode ("mov", "c,acc.7");
6040 emitcode ("rrc", "a");
6042 else if (shCount == 2)
6044 emitcode ("mov", "c,acc.7");
6045 emitcode ("rrc", "a");
6046 emitcode ("mov", "c,acc.7");
6047 emitcode ("rrc", "a");
6051 tlbl = newiTempLabel (NULL);
6052 /* rotate right accumulator */
6053 AccRol (8 - shCount);
6054 /* and kill the higher order bits */
6055 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6056 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6057 emitcode ("orl", "a,#0x%02x",
6058 (unsigned char) ~SRMask[shCount]);
6059 emitcode ("", "%05d$:", tlbl->key + 100);
6067 /*-----------------------------------------------------------------*/
6068 /* shiftR1Left2Result - shift right one byte from left to result */
6069 /*-----------------------------------------------------------------*/
6071 shiftR1Left2Result (operand * left, int offl,
6072 operand * result, int offr,
6073 int shCount, int sign)
6075 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6076 /* shift right accumulator */
6081 aopPut (AOP (result), "a", offr);
6085 #ifdef BETTER_LITERAL_SHIFT
6086 /*-----------------------------------------------------------------*/
6087 /* shiftL1Left2Result - shift left one byte from left to result */
6088 /*-----------------------------------------------------------------*/
6090 shiftL1Left2Result (operand * left, int offl,
6091 operand * result, int offr, int shCount)
6093 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6094 /* shift left accumulator */
6096 aopPut (AOP (result), "a", offr);
6100 #ifdef BETTER_LITERAL_SHIFT
6101 /*-----------------------------------------------------------------*/
6102 /* movLeft2Result - move byte from left to result */
6103 /*-----------------------------------------------------------------*/
6105 movLeft2Result (operand * left, int offl,
6106 operand * result, int offr, int sign)
6109 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6111 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6113 if (*l == '@' && (IS_AOP_PREG (result)))
6115 emitcode ("mov", "a,%s", l);
6116 aopPut (AOP (result), "a", offr);
6122 aopPut (AOP (result), l, offr);
6126 /* MSB sign in acc.7 ! */
6127 if (getDataSize (left) == offl + 1)
6129 emitcode ("mov", "a,%s", l);
6130 aopPut (AOP (result), "a", offr);
6138 #ifdef BETTER_LITERAL_SHIFT
6139 /*-----------------------------------------------------------------*/
6140 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6141 /*-----------------------------------------------------------------*/
6145 emitcode ("rrc", "a");
6146 emitcode ("xch", "a,%s", x);
6147 emitcode ("rrc", "a");
6148 emitcode ("xch", "a,%s", x);
6154 /*-----------------------------------------------------------------*/
6155 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6156 /*-----------------------------------------------------------------*/
6160 emitcode ("xch", "a,%s", x);
6161 emitcode ("rlc", "a");
6162 emitcode ("xch", "a,%s", x);
6163 emitcode ("rlc", "a");
6167 #ifdef BETTER_LITERAL_SHIFT
6168 /*-----------------------------------------------------------------*/
6169 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6170 /*-----------------------------------------------------------------*/
6174 emitcode ("xch", "a,%s", x);
6175 emitcode ("add", "a,acc");
6176 emitcode ("xch", "a,%s", x);
6177 emitcode ("rlc", "a");
6181 #ifdef BETTER_LITERAL_SHIFT
6182 /*-----------------------------------------------------------------*/
6183 /* AccAXLsh - left shift a:x by known count (0..7) */
6184 /*-----------------------------------------------------------------*/
6186 AccAXLsh (char *x, int shCount)
6201 case 5: // AAAAABBB:CCCCCDDD
6203 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6205 emitcode ("anl", "a,#0x%02x",
6206 SLMask[shCount]); // BBB00000:CCCCCDDD
6208 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6210 AccRol (shCount); // DDDCCCCC:BBB00000
6212 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6214 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6216 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6218 emitcode ("anl", "a,#0x%02x",
6219 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6221 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6223 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6226 case 6: // AAAAAABB:CCCCCCDD
6227 emitcode ("anl", "a,#0x%02x",
6228 SRMask[shCount]); // 000000BB:CCCCCCDD
6229 emitcode ("mov", "c,acc.0"); // c = B
6230 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6232 AccAXRrl1 (x); // BCCCCCCD:D000000B
6233 AccAXRrl1 (x); // BBCCCCCC:DD000000
6235 emitcode("rrc","a");
6236 emitcode("xch","a,%s", x);
6237 emitcode("rrc","a");
6238 emitcode("mov","c,acc.0"); //<< get correct bit
6239 emitcode("xch","a,%s", x);
6241 emitcode("rrc","a");
6242 emitcode("xch","a,%s", x);
6243 emitcode("rrc","a");
6244 emitcode("xch","a,%s", x);
6247 case 7: // a:x <<= 7
6249 emitcode ("anl", "a,#0x%02x",
6250 SRMask[shCount]); // 0000000B:CCCCCCCD
6252 emitcode ("mov", "c,acc.0"); // c = B
6254 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6256 AccAXRrl1 (x); // BCCCCCCC:D0000000
6267 /*-----------------------------------------------------------------*/
6268 /* AccAXRsh - right shift a:x known count (0..7) */
6269 /*-----------------------------------------------------------------*/
6271 AccAXRsh (char *x, int shCount)
6279 AccAXRrl1 (x); // 0->a:x
6284 AccAXRrl1 (x); // 0->a:x
6287 AccAXRrl1 (x); // 0->a:x
6292 case 5: // AAAAABBB:CCCCCDDD = a:x
6294 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6296 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6298 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6300 emitcode ("anl", "a,#0x%02x",
6301 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6303 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6305 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6307 emitcode ("anl", "a,#0x%02x",
6308 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6310 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6312 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6314 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6317 case 6: // AABBBBBB:CCDDDDDD
6319 emitcode ("mov", "c,acc.7");
6320 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6322 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6324 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6326 emitcode ("anl", "a,#0x%02x",
6327 SRMask[shCount]); // 000000AA:BBBBBBCC
6330 case 7: // ABBBBBBB:CDDDDDDD
6332 emitcode ("mov", "c,acc.7"); // c = A
6334 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6336 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6338 emitcode ("anl", "a,#0x%02x",
6339 SRMask[shCount]); // 0000000A:BBBBBBBC
6350 /*-----------------------------------------------------------------*/
6351 /* AccAXRshS - right shift signed a:x known count (0..7) */
6352 /*-----------------------------------------------------------------*/
6354 AccAXRshS (char *x, int shCount)
6362 emitcode ("mov", "c,acc.7");
6363 AccAXRrl1 (x); // s->a:x
6367 emitcode ("mov", "c,acc.7");
6368 AccAXRrl1 (x); // s->a:x
6370 emitcode ("mov", "c,acc.7");
6371 AccAXRrl1 (x); // s->a:x
6376 case 5: // AAAAABBB:CCCCCDDD = a:x
6378 tlbl = newiTempLabel (NULL);
6379 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6381 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6383 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6385 emitcode ("anl", "a,#0x%02x",
6386 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6388 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6390 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6392 emitcode ("anl", "a,#0x%02x",
6393 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6395 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6397 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6399 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6401 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6402 emitcode ("orl", "a,#0x%02x",
6403 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6405 emitcode ("", "%05d$:", tlbl->key + 100);
6406 break; // SSSSAAAA:BBBCCCCC
6408 case 6: // AABBBBBB:CCDDDDDD
6410 tlbl = newiTempLabel (NULL);
6411 emitcode ("mov", "c,acc.7");
6412 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6414 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6416 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6418 emitcode ("anl", "a,#0x%02x",
6419 SRMask[shCount]); // 000000AA:BBBBBBCC
6421 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6422 emitcode ("orl", "a,#0x%02x",
6423 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6425 emitcode ("", "%05d$:", tlbl->key + 100);
6427 case 7: // ABBBBBBB:CDDDDDDD
6429 tlbl = newiTempLabel (NULL);
6430 emitcode ("mov", "c,acc.7"); // c = A
6432 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6434 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6436 emitcode ("anl", "a,#0x%02x",
6437 SRMask[shCount]); // 0000000A:BBBBBBBC
6439 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6440 emitcode ("orl", "a,#0x%02x",
6441 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6443 emitcode ("", "%05d$:", tlbl->key + 100);
6451 #ifdef BETTER_LITERAL_SHIFT
6452 /*-----------------------------------------------------------------*/
6453 /* shiftL2Left2Result - shift left two bytes from left to result */
6454 /*-----------------------------------------------------------------*/
6456 shiftL2Left2Result (operand * left, int offl,
6457 operand * result, int offr, int shCount)
6461 // Get the initial value from left into a pair of registers.
6462 // MSB must be in A, LSB can be any register.
6464 // If the result is held in registers, it is an optimization
6465 // if the LSB can be held in the register which will hold the,
6466 // result LSB since this saves us from having to copy it into
6467 // the result following AccAXLsh.
6469 // If the result is addressed indirectly, this is not a gain.
6470 if (AOP_NEEDSACC(result))
6474 D(emitcode(";", "watch me do the hambone!"););
6475 _startLazyDPSEvaluation();
6476 if (AOP_TYPE(left) == AOP_DPTR2)
6479 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6480 // get LSB in DP2_RESULT_REG.
6481 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6482 assert(!strcmp(leftByte, DP2_RESULT_REG));
6486 // get LSB into DP2_RESULT_REG
6487 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6488 if (strcmp(leftByte, DP2_RESULT_REG))
6490 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6493 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6494 assert(strcmp(leftByte, DP2_RESULT_REG));
6497 _endLazyDPSEvaluation();
6498 lsb = DP2_RESULT_REG;
6502 if (sameRegs (AOP (result), AOP (left)) &&
6503 ((offl + MSB16) == offr))
6505 /* don't crash result[offr] */
6506 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6507 emitcode ("xch", "a,%s",
6508 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6512 movLeft2Result (left, offl, result, offr, 0);
6513 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6515 lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6516 assert(strcmp(lsb,"a"));
6518 AccAXLsh (lsb, shCount);
6520 _startLazyDPSEvaluation();
6521 if (AOP_NEEDSACC(result))
6523 /* We have to explicitly update the result LSB.
6525 emitcode("xch","a,%s", lsb);
6526 aopPut(AOP(result), "a", offr);
6527 emitcode("mov","a,%s", lsb);
6529 aopPut (AOP (result), "a", offr + MSB16);
6530 _endLazyDPSEvaluation();
6536 /*-----------------------------------------------------------------*/
6537 /* shiftR2Left2Result - shift right two bytes from left to result */
6538 /*-----------------------------------------------------------------*/
6540 shiftR2Left2Result (operand * left, int offl,
6541 operand * result, int offr,
6542 int shCount, int sign)
6544 if (sameRegs (AOP (result), AOP (left)) &&
6545 ((offl + MSB16) == offr))
6547 /* don't crash result[offr] */
6548 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6549 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
6553 movLeft2Result (left, offl, result, offr, 0);
6554 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6556 /* a:x >> shCount (x = lsb(result)) */
6558 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6560 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
6561 if (getDataSize (result) > 1)
6562 aopPut (AOP (result), "a", offr + MSB16);
6568 /*-----------------------------------------------------------------*/
6569 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6570 /*-----------------------------------------------------------------*/
6572 shiftLLeftOrResult (operand * left, int offl,
6573 operand * result, int offr, int shCount)
6575 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6576 /* shift left accumulator */
6578 /* or with result */
6579 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6580 /* back to result */
6581 aopPut (AOP (result), "a", offr);
6587 /*-----------------------------------------------------------------*/
6588 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6589 /*-----------------------------------------------------------------*/
6591 shiftRLeftOrResult (operand * left, int offl,
6592 operand * result, int offr, int shCount)
6594 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6595 /* shift right accumulator */
6597 /* or with result */
6598 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6599 /* back to result */
6600 aopPut (AOP (result), "a", offr);
6604 #ifdef BETTER_LITERAL_SHIFT
6605 /*-----------------------------------------------------------------*/
6606 /* genlshOne - left shift a one byte quantity by known count */
6607 /*-----------------------------------------------------------------*/
6609 genlshOne (operand * result, operand * left, int shCount)
6611 D (emitcode (";", "genlshOne "););
6612 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6616 #ifdef BETTER_LITERAL_SHIFT
6617 /*-----------------------------------------------------------------*/
6618 /* genlshTwo - left shift two bytes by known amount != 0 */
6619 /*-----------------------------------------------------------------*/
6621 genlshTwo (operand * result, operand * left, int shCount)
6625 D (emitcode (";", "genlshTwo "););
6627 size = getDataSize (result);
6629 /* if shCount >= 8 */
6634 _startLazyDPSEvaluation();
6635 aopPut (AOP (result), zero, LSB);
6640 _endLazyDPSEvaluation();
6641 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6645 movLeft2Result (left, LSB, result, MSB16, 0);
6646 _endLazyDPSEvaluation();
6651 _endLazyDPSEvaluation();
6655 /* 1 <= shCount <= 7 */
6660 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6664 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6672 /*-----------------------------------------------------------------*/
6673 /* shiftLLong - shift left one long from left to result */
6674 /* offl = LSB or MSB16 */
6675 /*-----------------------------------------------------------------*/
6677 shiftLLong (operand * left, operand * result, int offr)
6680 int size = AOP_SIZE (result);
6682 if (size >= LSB + offr)
6684 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6686 emitcode ("add", "a,acc");
6687 if (sameRegs (AOP (left), AOP (result)) &&
6688 size >= MSB16 + offr && offr != LSB)
6689 emitcode ("xch", "a,%s",
6690 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6692 aopPut (AOP (result), "a", LSB + offr);
6695 if (size >= MSB16 + offr)
6697 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6699 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6702 emitcode ("rlc", "a");
6703 if (sameRegs (AOP (left), AOP (result)) &&
6704 size >= MSB24 + offr && offr != LSB)
6705 emitcode ("xch", "a,%s",
6706 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6708 aopPut (AOP (result), "a", MSB16 + offr);
6711 if (size >= MSB24 + offr)
6713 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6715 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6718 emitcode ("rlc", "a");
6719 if (sameRegs (AOP (left), AOP (result)) &&
6720 size >= MSB32 + offr && offr != LSB)
6721 emitcode ("xch", "a,%s",
6722 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6724 aopPut (AOP (result), "a", MSB24 + offr);
6727 if (size > MSB32 + offr)
6729 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6731 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6734 emitcode ("rlc", "a");
6735 aopPut (AOP (result), "a", MSB32 + offr);
6738 aopPut (AOP (result), zero, LSB);
6744 /*-----------------------------------------------------------------*/
6745 /* genlshFour - shift four byte by a known amount != 0 */
6746 /*-----------------------------------------------------------------*/
6748 genlshFour (operand * result, operand * left, int shCount)
6752 D (emitcode (";", "genlshFour ");
6755 size = AOP_SIZE (result);
6757 /* if shifting more that 3 bytes */
6762 /* lowest order of left goes to the highest
6763 order of the destination */
6764 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6766 movLeft2Result (left, LSB, result, MSB32, 0);
6767 aopPut (AOP (result), zero, LSB);
6768 aopPut (AOP (result), zero, MSB16);
6769 aopPut (AOP (result), zero, MSB24);
6773 /* more than two bytes */
6774 else if (shCount >= 16)
6776 /* lower order two bytes goes to higher order two bytes */
6778 /* if some more remaining */
6780 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6783 movLeft2Result (left, MSB16, result, MSB32, 0);
6784 movLeft2Result (left, LSB, result, MSB24, 0);
6786 aopPut (AOP (result), zero, MSB16);
6787 aopPut (AOP (result), zero, LSB);
6791 /* if more than 1 byte */
6792 else if (shCount >= 8)
6794 /* lower order three bytes goes to higher order three bytes */
6799 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6801 movLeft2Result (left, LSB, result, MSB16, 0);
6807 movLeft2Result (left, MSB24, result, MSB32, 0);
6808 movLeft2Result (left, MSB16, result, MSB24, 0);
6809 movLeft2Result (left, LSB, result, MSB16, 0);
6810 aopPut (AOP (result), zero, LSB);
6812 else if (shCount == 1)
6813 shiftLLong (left, result, MSB16);
6816 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6817 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6818 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6819 aopPut (AOP (result), zero, LSB);
6824 /* 1 <= shCount <= 7 */
6825 else if (shCount <= 2)
6827 shiftLLong (left, result, LSB);
6829 shiftLLong (result, result, LSB);
6831 /* 3 <= shCount <= 7, optimize */
6834 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6835 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6836 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6841 #ifdef BETTER_LITERAL_SHIFT
6842 /*-----------------------------------------------------------------*/
6843 /* genLeftShiftLiteral - left shifting by known count */
6844 /*-----------------------------------------------------------------*/
6846 genLeftShiftLiteral (operand * left,
6851 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6854 size = getSize (operandType (result));
6856 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6858 /* We only handle certain easy cases so far. */
6860 && (shCount < (size * 8))
6864 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6868 freeAsmop (right, NULL, ic, TRUE);
6870 aopOp(left, ic, FALSE, FALSE);
6871 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6874 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6876 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6877 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6879 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6882 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6884 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6885 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6887 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6893 emitcode ("; shift left ", "result %d, left %d", size,
6897 /* I suppose that the left size >= result size */
6900 _startLazyDPSEvaluation();
6903 movLeft2Result (left, size, result, size, 0);
6905 _endLazyDPSEvaluation();
6907 else if (shCount >= (size * 8))
6909 _startLazyDPSEvaluation();
6912 aopPut (AOP (result), zero, size);
6914 _endLazyDPSEvaluation();
6921 genlshOne (result, left, shCount);
6925 genlshTwo (result, left, shCount);
6929 genlshFour (result, left, shCount);
6933 fprintf(stderr, "*** ack! mystery literal shift!\n");
6937 freeAsmop (left, NULL, ic, TRUE);
6938 freeAsmop (result, NULL, ic, TRUE);
6943 /*-----------------------------------------------------------------*/
6944 /* genLeftShift - generates code for left shifting */
6945 /*-----------------------------------------------------------------*/
6947 genLeftShift (iCode * ic)
6949 operand *left, *right, *result;
6952 symbol *tlbl, *tlbl1;
6954 D (emitcode (";", "genLeftShift "););
6956 right = IC_RIGHT (ic);
6957 left = IC_LEFT (ic);
6958 result = IC_RESULT (ic);
6960 aopOp (right, ic, FALSE, FALSE);
6963 #ifdef BETTER_LITERAL_SHIFT
6964 /* if the shift count is known then do it
6965 as efficiently as possible */
6966 if (AOP_TYPE (right) == AOP_LIT)
6968 if (genLeftShiftLiteral (left, right, result, ic))
6975 /* shift count is unknown then we have to form
6976 a loop get the loop count in B : Note: we take
6977 only the lower order byte since shifting
6978 more that 32 bits make no sense anyway, ( the
6979 largest size of an object can be only 32 bits ) */
6981 if (AOP_TYPE (right) == AOP_LIT)
6983 /* Really should be handled by genLeftShiftLiteral,
6984 * but since I'm too lazy to fix that today, at least we can make
6985 * some small improvement.
6987 emitcode("mov", "b,#0x%02x",
6988 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
6992 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
6993 emitcode ("inc", "b");
6995 freeAsmop (right, NULL, ic, TRUE);
6996 aopOp (left, ic, FALSE, FALSE);
6997 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6999 /* now move the left to the result if they are not the
7001 if (!sameRegs (AOP (left), AOP (result)) &&
7002 AOP_SIZE (result) > 1)
7005 size = AOP_SIZE (result);
7007 _startLazyDPSEvaluation ();
7010 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7011 if (*l == '@' && (IS_AOP_PREG (result)))
7014 emitcode ("mov", "a,%s", l);
7015 aopPut (AOP (result), "a", offset);
7018 aopPut (AOP (result), l, offset);
7021 _endLazyDPSEvaluation ();
7024 tlbl = newiTempLabel (NULL);
7025 size = AOP_SIZE (result);
7027 tlbl1 = newiTempLabel (NULL);
7029 /* if it is only one byte then */
7032 symbol *tlbl1 = newiTempLabel (NULL);
7034 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7036 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7037 emitcode ("", "%05d$:", tlbl->key + 100);
7038 emitcode ("add", "a,acc");
7039 emitcode ("", "%05d$:", tlbl1->key + 100);
7040 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7041 aopPut (AOP (result), "a", 0);
7045 reAdjustPreg (AOP (result));
7047 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7048 emitcode ("", "%05d$:", tlbl->key + 100);
7049 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7051 emitcode ("add", "a,acc");
7052 aopPut (AOP (result), "a", offset++);
7053 _startLazyDPSEvaluation ();
7056 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7058 emitcode ("rlc", "a");
7059 aopPut (AOP (result), "a", offset++);
7061 _endLazyDPSEvaluation ();
7062 reAdjustPreg (AOP (result));
7064 emitcode ("", "%05d$:", tlbl1->key + 100);
7065 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7067 freeAsmop (left, NULL, ic, TRUE);
7068 freeAsmop (result, NULL, ic, TRUE);
7073 /*-----------------------------------------------------------------*/
7074 /* genrshOne - right shift a one byte quantity by known count */
7075 /*-----------------------------------------------------------------*/
7077 genrshOne (operand * result, operand * left,
7078 int shCount, int sign)
7080 D (emitcode (";", "genrshOne");
7082 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7088 /*-----------------------------------------------------------------*/
7089 /* genrshTwo - right shift two bytes by known amount != 0 */
7090 /*-----------------------------------------------------------------*/
7092 genrshTwo (operand * result, operand * left,
7093 int shCount, int sign)
7095 D (emitcode (";", "genrshTwo");
7098 /* if shCount >= 8 */
7103 shiftR1Left2Result (left, MSB16, result, LSB,
7106 movLeft2Result (left, MSB16, result, LSB, sign);
7107 addSign (result, MSB16, sign);
7110 /* 1 <= shCount <= 7 */
7112 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7118 /*-----------------------------------------------------------------*/
7119 /* shiftRLong - shift right one long from left to result */
7120 /* offl = LSB or MSB16 */
7121 /*-----------------------------------------------------------------*/
7123 shiftRLong (operand * left, int offl,
7124 operand * result, int sign)
7127 emitcode ("clr", "c");
7128 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7130 emitcode ("mov", "c,acc.7");
7131 emitcode ("rrc", "a");
7132 aopPut (AOP (result), "a", MSB32 - offl);
7134 /* add sign of "a" */
7135 addSign (result, MSB32, sign);
7137 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7138 emitcode ("rrc", "a");
7139 aopPut (AOP (result), "a", MSB24 - offl);
7141 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7142 emitcode ("rrc", "a");
7143 aopPut (AOP (result), "a", MSB16 - offl);
7147 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7148 emitcode ("rrc", "a");
7149 aopPut (AOP (result), "a", LSB);
7156 /*-----------------------------------------------------------------*/
7157 /* genrshFour - shift four byte by a known amount != 0 */
7158 /*-----------------------------------------------------------------*/
7160 genrshFour (operand * result, operand * left,
7161 int shCount, int sign)
7163 D (emitcode (";", "genrshFour");
7166 /* if shifting more that 3 bytes */
7171 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7173 movLeft2Result (left, MSB32, result, LSB, sign);
7174 addSign (result, MSB16, sign);
7176 else if (shCount >= 16)
7180 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7183 movLeft2Result (left, MSB24, result, LSB, 0);
7184 movLeft2Result (left, MSB32, result, MSB16, sign);
7186 addSign (result, MSB24, sign);
7188 else if (shCount >= 8)
7192 shiftRLong (left, MSB16, result, sign);
7193 else if (shCount == 0)
7195 movLeft2Result (left, MSB16, result, LSB, 0);
7196 movLeft2Result (left, MSB24, result, MSB16, 0);
7197 movLeft2Result (left, MSB32, result, MSB24, sign);
7198 addSign (result, MSB32, sign);
7202 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7203 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7204 /* the last shift is signed */
7205 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7206 addSign (result, MSB32, sign);
7210 { /* 1 <= shCount <= 7 */
7213 shiftRLong (left, LSB, result, sign);
7215 shiftRLong (result, LSB, result, sign);
7219 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7220 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7221 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7229 /*-----------------------------------------------------------------*/
7230 /* genRightShiftLiteral - right shifting by known count */
7231 /*-----------------------------------------------------------------*/
7233 genRightShiftLiteral (operand * left,
7239 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7242 D (emitcode (";", "genRightShiftLiteral");
7245 freeAsmop (right, NULL, ic, TRUE);
7247 aopOp (left, ic, FALSE, FALSE);
7248 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7251 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7255 size = getDataSize (left);
7256 /* test the LEFT size !!! */
7258 /* I suppose that the left size >= result size */
7261 size = getDataSize (result);
7263 movLeft2Result (left, size, result, size, 0);
7266 else if (shCount >= (size * 8))
7269 /* get sign in acc.7 */
7270 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7271 addSign (result, LSB, sign);
7278 genrshOne (result, left, shCount, sign);
7282 genrshTwo (result, left, shCount, sign);
7286 genrshFour (result, left, shCount, sign);
7292 freeAsmop (left, NULL, ic, TRUE);
7293 freeAsmop (result, NULL, ic, TRUE);
7298 /*-----------------------------------------------------------------*/
7299 /* genSignedRightShift - right shift of signed number */
7300 /*-----------------------------------------------------------------*/
7302 genSignedRightShift (iCode * ic)
7304 operand *right, *left, *result;
7307 symbol *tlbl, *tlbl1;
7309 D (emitcode (";", "genSignedRightShift "););
7311 /* we do it the hard way put the shift count in b
7312 and loop thru preserving the sign */
7314 right = IC_RIGHT (ic);
7315 left = IC_LEFT (ic);
7316 result = IC_RESULT (ic);
7318 aopOp (right, ic, FALSE, FALSE);
7321 if (AOP_TYPE (right) == AOP_LIT)
7323 genRightShiftLiteral (left, right, result, ic, 1);
7327 /* shift count is unknown then we have to form
7328 a loop get the loop count in B : Note: we take
7329 only the lower order byte since shifting
7330 more that 32 bits make no sense anyway, ( the
7331 largest size of an object can be only 32 bits ) */
7333 if (AOP_TYPE (right) == AOP_LIT)
7335 /* Really should be handled by genRightShiftLiteral,
7336 * but since I'm too lazy to fix that today, at least we can make
7337 * some small improvement.
7339 emitcode("mov", "b,#0x%02x",
7340 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7344 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7345 emitcode ("inc", "b");
7347 freeAsmop (right, NULL, ic, TRUE);
7348 aopOp (left, ic, FALSE, FALSE);
7349 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7351 /* now move the left to the result if they are not the
7353 if (!sameRegs (AOP (left), AOP (result)) &&
7354 AOP_SIZE (result) > 1)
7357 size = AOP_SIZE (result);
7359 _startLazyDPSEvaluation ();
7362 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7363 if (*l == '@' && IS_AOP_PREG (result))
7366 emitcode ("mov", "a,%s", l);
7367 aopPut (AOP (result), "a", offset);
7370 aopPut (AOP (result), l, offset);
7373 _endLazyDPSEvaluation ();
7376 /* mov the highest order bit to OVR */
7377 tlbl = newiTempLabel (NULL);
7378 tlbl1 = newiTempLabel (NULL);
7380 size = AOP_SIZE (result);
7382 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7383 emitcode ("rlc", "a");
7384 emitcode ("mov", "ov,c");
7385 /* if it is only one byte then */
7388 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7390 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7391 emitcode ("", "%05d$:", tlbl->key + 100);
7392 emitcode ("mov", "c,ov");
7393 emitcode ("rrc", "a");
7394 emitcode ("", "%05d$:", tlbl1->key + 100);
7395 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7396 aopPut (AOP (result), "a", 0);
7400 reAdjustPreg (AOP (result));
7401 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7402 emitcode ("", "%05d$:", tlbl->key + 100);
7403 emitcode ("mov", "c,ov");
7404 _startLazyDPSEvaluation ();
7407 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7409 emitcode ("rrc", "a");
7410 aopPut (AOP (result), "a", offset--);
7412 _endLazyDPSEvaluation ();
7413 reAdjustPreg (AOP (result));
7414 emitcode ("", "%05d$:", tlbl1->key + 100);
7415 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7418 freeAsmop (left, NULL, ic, TRUE);
7419 freeAsmop (result, NULL, ic, TRUE);
7422 /*-----------------------------------------------------------------*/
7423 /* genRightShift - generate code for right shifting */
7424 /*-----------------------------------------------------------------*/
7426 genRightShift (iCode * ic)
7428 operand *right, *left, *result;
7432 symbol *tlbl, *tlbl1;
7434 D (emitcode (";", "genRightShift "););
7436 /* if signed then we do it the hard way preserve the
7437 sign bit moving it inwards */
7438 retype = getSpec (operandType (IC_RESULT (ic)));
7440 if (!SPEC_USIGN (retype))
7442 genSignedRightShift (ic);
7446 /* signed & unsigned types are treated the same : i.e. the
7447 signed is NOT propagated inwards : quoting from the
7448 ANSI - standard : "for E1 >> E2, is equivalent to division
7449 by 2**E2 if unsigned or if it has a non-negative value,
7450 otherwise the result is implementation defined ", MY definition
7451 is that the sign does not get propagated */
7453 right = IC_RIGHT (ic);
7454 left = IC_LEFT (ic);
7455 result = IC_RESULT (ic);
7457 aopOp (right, ic, FALSE, FALSE);
7460 /* if the shift count is known then do it
7461 as efficiently as possible */
7462 if (AOP_TYPE (right) == AOP_LIT)
7464 genRightShiftLiteral (left, right, result, ic, 0);
7469 /* shift count is unknown then we have to form
7470 a loop get the loop count in B : Note: we take
7471 only the lower order byte since shifting
7472 more that 32 bits make no sense anyway, ( the
7473 largest size of an object can be only 32 bits ) */
7475 if (AOP_TYPE (right) == AOP_LIT)
7477 /* Really should be handled by genRightShiftLiteral,
7478 * but since I'm too lazy to fix that today, at least we can make
7479 * some small improvement.
7481 emitcode("mov", "b,#0x%02x",
7482 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7486 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7487 emitcode ("inc", "b");
7489 freeAsmop (right, NULL, ic, TRUE);
7490 aopOp (left, ic, FALSE, FALSE);
7491 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7493 /* now move the left to the result if they are not the
7495 if (!sameRegs (AOP (left), AOP (result)) &&
7496 AOP_SIZE (result) > 1)
7499 size = AOP_SIZE (result);
7501 _startLazyDPSEvaluation ();
7504 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7505 if (*l == '@' && IS_AOP_PREG (result))
7508 emitcode ("mov", "a,%s", l);
7509 aopPut (AOP (result), "a", offset);
7512 aopPut (AOP (result), l, offset);
7515 _endLazyDPSEvaluation ();
7518 tlbl = newiTempLabel (NULL);
7519 tlbl1 = newiTempLabel (NULL);
7520 size = AOP_SIZE (result);
7523 /* if it is only one byte then */
7526 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7528 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7529 emitcode ("", "%05d$:", tlbl->key + 100);
7531 emitcode ("rrc", "a");
7532 emitcode ("", "%05d$:", tlbl1->key + 100);
7533 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7534 aopPut (AOP (result), "a", 0);
7538 reAdjustPreg (AOP (result));
7539 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7540 emitcode ("", "%05d$:", tlbl->key + 100);
7542 _startLazyDPSEvaluation ();
7545 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7547 emitcode ("rrc", "a");
7548 aopPut (AOP (result), "a", offset--);
7550 _endLazyDPSEvaluation ();
7551 reAdjustPreg (AOP (result));
7553 emitcode ("", "%05d$:", tlbl1->key + 100);
7554 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7557 freeAsmop (left, NULL, ic, TRUE);
7558 freeAsmop (result, NULL, ic, TRUE);
7561 /*-----------------------------------------------------------------*/
7562 /* genUnpackBits - generates code for unpacking bits */
7563 /*-----------------------------------------------------------------*/
7565 genUnpackBits (operand * result, char *rname, int ptype)
7572 D (emitcode (";", "genUnpackBits ");
7575 etype = getSpec (operandType (result));
7577 /* read the first byte */
7583 emitcode ("mov", "a,@%s", rname);
7587 emitcode ("movx", "a,@%s", rname);
7591 emitcode ("movx", "a,@dptr");
7595 emitcode ("clr", "a");
7596 emitcode ("movc", "a", "@a+dptr");
7600 emitcode ("lcall", "__gptrget");
7604 /* if we have bitdisplacement then it fits */
7605 /* into this byte completely or if length is */
7606 /* less than a byte */
7607 if ((shCnt = SPEC_BSTR (etype)) ||
7608 (SPEC_BLEN (etype) <= 8))
7611 /* shift right acc */
7614 emitcode ("anl", "a,#0x%02x",
7615 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7616 aopPut (AOP (result), "a", offset);
7620 /* bit field did not fit in a byte */
7621 rlen = SPEC_BLEN (etype) - 8;
7622 aopPut (AOP (result), "a", offset++);
7631 emitcode ("inc", "%s", rname);
7632 emitcode ("mov", "a,@%s", rname);
7636 emitcode ("inc", "%s", rname);
7637 emitcode ("movx", "a,@%s", rname);
7641 emitcode ("inc", "dptr");
7642 emitcode ("movx", "a,@dptr");
7646 emitcode ("clr", "a");
7647 emitcode ("inc", "dptr");
7648 emitcode ("movc", "a", "@a+dptr");
7652 emitcode ("inc", "dptr");
7653 emitcode ("lcall", "__gptrget");
7658 /* if we are done */
7662 aopPut (AOP (result), "a", offset++);
7668 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7669 aopPut (AOP (result), "a", offset);
7676 /*-----------------------------------------------------------------*/
7677 /* genDataPointerGet - generates code when ptr offset is known */
7678 /*-----------------------------------------------------------------*/
7680 genDataPointerGet (operand * left,
7686 int size, offset = 0;
7687 aopOp (result, ic, TRUE, FALSE);
7689 /* get the string representation of the name */
7690 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7691 size = AOP_SIZE (result);
7692 _startLazyDPSEvaluation ();
7696 sprintf (buffer, "(%s + %d)", l + 1, offset);
7698 sprintf (buffer, "%s", l + 1);
7699 aopPut (AOP (result), buffer, offset++);
7701 _endLazyDPSEvaluation ();
7703 freeAsmop (left, NULL, ic, TRUE);
7704 freeAsmop (result, NULL, ic, TRUE);
7707 /*-----------------------------------------------------------------*/
7708 /* genNearPointerGet - emitcode for near pointer fetch */
7709 /*-----------------------------------------------------------------*/
7711 genNearPointerGet (operand * left,
7718 sym_link *rtype, *retype, *letype;
7719 sym_link *ltype = operandType (left);
7722 rtype = operandType (result);
7723 retype = getSpec (rtype);
7724 letype = getSpec (ltype);
7726 aopOp (left, ic, FALSE, FALSE);
7728 /* if left is rematerialisable and
7729 result is not bit variable type and
7730 the left is pointer to data space i.e
7731 lower 128 bytes of space */
7732 if (AOP_TYPE (left) == AOP_IMMD &&
7733 !IS_BITVAR (retype) &&
7734 !IS_BITVAR (letype) &&
7735 DCL_TYPE (ltype) == POINTER)
7737 genDataPointerGet (left, result, ic);
7741 /* if the value is already in a pointer register
7742 then don't need anything more */
7743 if (!AOP_INPREG (AOP (left)))
7745 /* otherwise get a free pointer register */
7747 preg = getFreePtr (ic, &aop, FALSE);
7748 emitcode ("mov", "%s,%s",
7750 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7754 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7756 freeAsmop (left, NULL, ic, TRUE);
7757 aopOp (result, ic, FALSE, FALSE);
7759 /* if bitfield then unpack the bits */
7760 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7761 genUnpackBits (result, rname, POINTER);
7764 /* we have can just get the values */
7765 int size = AOP_SIZE (result);
7770 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7773 emitcode ("mov", "a,@%s", rname);
7774 aopPut (AOP (result), "a", offset);
7778 sprintf (buffer, "@%s", rname);
7779 aopPut (AOP (result), buffer, offset);
7783 emitcode ("inc", "%s", rname);
7787 /* now some housekeeping stuff */
7790 /* we had to allocate for this iCode */
7791 freeAsmop (NULL, aop, ic, TRUE);
7795 /* we did not allocate which means left
7796 already in a pointer register, then
7797 if size > 0 && this could be used again
7798 we have to point it back to where it
7800 if (AOP_SIZE (result) > 1 &&
7801 !OP_SYMBOL (left)->remat &&
7802 (OP_SYMBOL (left)->liveTo > ic->seq ||
7805 int size = AOP_SIZE (result) - 1;
7807 emitcode ("dec", "%s", rname);
7812 freeAsmop (result, NULL, ic, TRUE);
7816 /*-----------------------------------------------------------------*/
7817 /* genPagedPointerGet - emitcode for paged pointer fetch */
7818 /*-----------------------------------------------------------------*/
7820 genPagedPointerGet (operand * left,
7827 sym_link *rtype, *retype, *letype;
7829 rtype = operandType (result);
7830 retype = getSpec (rtype);
7831 letype = getSpec (operandType (left));
7832 aopOp (left, ic, FALSE, FALSE);
7834 /* if the value is already in a pointer register
7835 then don't need anything more */
7836 if (!AOP_INPREG (AOP (left)))
7838 /* otherwise get a free pointer register */
7840 preg = getFreePtr (ic, &aop, FALSE);
7841 emitcode ("mov", "%s,%s",
7843 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7847 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7849 freeAsmop (left, NULL, ic, TRUE);
7850 aopOp (result, ic, FALSE, FALSE);
7852 /* if bitfield then unpack the bits */
7853 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7854 genUnpackBits (result, rname, PPOINTER);
7857 /* we have can just get the values */
7858 int size = AOP_SIZE (result);
7864 emitcode ("movx", "a,@%s", rname);
7865 aopPut (AOP (result), "a", offset);
7870 emitcode ("inc", "%s", rname);
7874 /* now some housekeeping stuff */
7877 /* we had to allocate for this iCode */
7878 freeAsmop (NULL, aop, ic, TRUE);
7882 /* we did not allocate which means left
7883 already in a pointer register, then
7884 if size > 0 && this could be used again
7885 we have to point it back to where it
7887 if (AOP_SIZE (result) > 1 &&
7888 !OP_SYMBOL (left)->remat &&
7889 (OP_SYMBOL (left)->liveTo > ic->seq ||
7892 int size = AOP_SIZE (result) - 1;
7894 emitcode ("dec", "%s", rname);
7899 freeAsmop (result, NULL, ic, TRUE);
7904 /*-----------------------------------------------------------------*/
7905 /* genFarPointerGet - gget value from far space */
7906 /*-----------------------------------------------------------------*/
7908 genFarPointerGet (operand * left,
7909 operand * result, iCode * ic)
7912 sym_link *retype = getSpec (operandType (result));
7913 sym_link *letype = getSpec (operandType (left));
7914 D (emitcode (";", "genFarPointerGet");
7917 aopOp (left, ic, FALSE, FALSE);
7919 /* if the operand is already in dptr
7920 then we do nothing else we move the value to dptr */
7921 if (AOP_TYPE (left) != AOP_STR)
7923 /* if this is remateriazable */
7924 if (AOP_TYPE (left) == AOP_IMMD)
7926 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7930 /* we need to get it byte by byte */
7931 _startLazyDPSEvaluation ();
7932 if (AOP_TYPE (left) != AOP_DPTR)
7934 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7935 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7936 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7940 /* We need to generate a load to DPTR indirect through DPTR. */
7941 D (emitcode (";", "genFarPointerGet -- indirection special case.");
7943 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7944 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
7945 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7946 emitcode ("pop", "dph");
7947 emitcode ("pop", "dpl");
7949 _endLazyDPSEvaluation ();
7952 /* so dptr know contains the address */
7953 freeAsmop (left, NULL, ic, TRUE);
7954 aopOp (result, ic, FALSE, TRUE);
7956 /* if bit then unpack */
7957 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7958 genUnpackBits (result, "dptr", FPOINTER);
7961 size = AOP_SIZE (result);
7964 _startLazyDPSEvaluation ();
7971 emitcode ("movx", "a,@dptr");
7973 emitcode ("inc", "dptr");
7975 aopPut (AOP (result), "a", offset++);
7977 _endLazyDPSEvaluation ();
7980 freeAsmop (result, NULL, ic, TRUE);
7983 /*-----------------------------------------------------------------*/
7984 /* emitcodePointerGet - gget value from code space */
7985 /*-----------------------------------------------------------------*/
7987 emitcodePointerGet (operand * left,
7988 operand * result, iCode * ic)
7991 sym_link *retype = getSpec (operandType (result));
7993 aopOp (left, ic, FALSE, FALSE);
7995 /* if the operand is already in dptr
7996 then we do nothing else we move the value to dptr */
7997 if (AOP_TYPE (left) != AOP_STR)
7999 /* if this is remateriazable */
8000 if (AOP_TYPE (left) == AOP_IMMD)
8002 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8005 { /* we need to get it byte by byte */
8006 _startLazyDPSEvaluation ();
8007 if (AOP_TYPE (left) != AOP_DPTR)
8009 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8010 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8011 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8015 /* We need to generate a load to DPTR indirect through DPTR. */
8016 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8018 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8019 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8020 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8021 emitcode ("pop", "dph");
8022 emitcode ("pop", "dpl");
8024 _endLazyDPSEvaluation ();
8027 /* so dptr know contains the address */
8028 freeAsmop (left, NULL, ic, TRUE);
8029 aopOp (result, ic, FALSE, TRUE);
8031 /* if bit then unpack */
8032 if (IS_BITVAR (retype))
8033 genUnpackBits (result, "dptr", CPOINTER);
8036 size = AOP_SIZE (result);
8039 _startLazyDPSEvaluation ();
8045 emitcode ("clr", "a");
8046 emitcode ("movc", "a,@a+dptr");
8048 emitcode ("inc", "dptr");
8049 aopPut (AOP (result), "a", offset++);
8051 _endLazyDPSEvaluation ();
8054 freeAsmop (result, NULL, ic, TRUE);
8057 /*-----------------------------------------------------------------*/
8058 /* genGenPointerGet - gget value from generic pointer space */
8059 /*-----------------------------------------------------------------*/
8061 genGenPointerGet (operand * left,
8062 operand * result, iCode * ic)
8065 sym_link *retype = getSpec (operandType (result));
8066 sym_link *letype = getSpec (operandType (left));
8068 D (emitcode (";", "genGenPointerGet "); );
8070 aopOp (left, ic, FALSE, TRUE);
8072 /* if the operand is already in dptr
8073 then we do nothing else we move the value to dptr */
8074 if (AOP_TYPE (left) != AOP_STR)
8076 /* if this is remateriazable */
8077 if (AOP_TYPE (left) == AOP_IMMD)
8079 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8080 emitcode ("mov", "b,#%d", pointerCode (retype));
8083 { /* we need to get it byte by byte */
8084 _startLazyDPSEvaluation ();
8085 if (AOP(left)->type==AOP_DPTR2) {
8087 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8090 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
8091 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8094 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
8095 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8098 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
8099 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8101 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8102 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8103 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8104 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8106 _endLazyDPSEvaluation ();
8109 /* so dptr know contains the address */
8110 freeAsmop (left, NULL, ic, TRUE);
8111 aopOp (result, ic, FALSE, TRUE);
8113 /* if bit then unpack */
8114 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8115 genUnpackBits (result, "dptr", GPOINTER);
8118 size = AOP_SIZE (result);
8123 emitcode ("lcall", "__gptrget");
8124 aopPut (AOP (result), "a", offset++);
8126 emitcode ("inc", "dptr");
8130 freeAsmop (result, NULL, ic, TRUE);
8133 /*-----------------------------------------------------------------*/
8134 /* genPointerGet - generate code for pointer get */
8135 /*-----------------------------------------------------------------*/
8137 genPointerGet (iCode * ic)
8139 operand *left, *result;
8140 sym_link *type, *etype;
8143 D (emitcode (";", "genPointerGet ");
8146 left = IC_LEFT (ic);
8147 result = IC_RESULT (ic);
8149 /* depending on the type of pointer we need to
8150 move it to the correct pointer register */
8151 type = operandType (left);
8152 etype = getSpec (type);
8153 /* if left is of type of pointer then it is simple */
8154 if (IS_PTR (type) && !IS_FUNC (type->next))
8155 p_type = DCL_TYPE (type);
8158 /* we have to go by the storage class */
8159 p_type = PTR_TYPE (SPEC_OCLS (etype));
8162 /* now that we have the pointer type we assign
8163 the pointer values */
8169 genNearPointerGet (left, result, ic);
8173 genPagedPointerGet (left, result, ic);
8177 genFarPointerGet (left, result, ic);
8181 emitcodePointerGet (left, result, ic);
8185 genGenPointerGet (left, result, ic);
8191 /*-----------------------------------------------------------------*/
8192 /* genPackBits - generates code for packed bit storage */
8193 /*-----------------------------------------------------------------*/
8195 genPackBits (sym_link * etype,
8197 char *rname, int p_type)
8205 blen = SPEC_BLEN (etype);
8206 bstr = SPEC_BSTR (etype);
8208 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8211 /* if the bit lenth is less than or */
8212 /* it exactly fits a byte then */
8213 if (SPEC_BLEN (etype) <= 8)
8215 shCount = SPEC_BSTR (etype);
8217 /* shift left acc */
8220 if (SPEC_BLEN (etype) < 8)
8221 { /* if smaller than a byte */
8227 emitcode ("mov", "b,a");
8228 emitcode ("mov", "a,@%s", rname);
8232 emitcode ("mov", "b,a");
8233 emitcode ("movx", "a,@dptr");
8237 emitcode ("push", "b");
8238 emitcode ("push", "acc");
8239 emitcode ("lcall", "__gptrget");
8240 emitcode ("pop", "b");
8244 emitcode ("anl", "a,#0x%02x", (unsigned char)
8245 ((unsigned char) (0xFF << (blen + bstr)) |
8246 (unsigned char) (0xFF >> (8 - bstr))));
8247 emitcode ("orl", "a,b");
8248 if (p_type == GPOINTER)
8249 emitcode ("pop", "b");
8256 emitcode ("mov", "@%s,a", rname);
8260 emitcode ("movx", "@dptr,a");
8264 emitcode ("lcall", "__gptrput");
8269 if (SPEC_BLEN (etype) <= 8)
8272 emitcode ("inc", "%s", rname);
8273 rLen = SPEC_BLEN (etype);
8275 /* now generate for lengths greater than one byte */
8279 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8291 emitcode ("mov", "@%s,a", rname);
8294 emitcode ("mov", "@%s,%s", rname, l);
8299 emitcode ("movx", "@dptr,a");
8304 emitcode ("lcall", "__gptrput");
8307 emitcode ("inc", "%s", rname);
8312 /* last last was not complete */
8315 /* save the byte & read byte */
8319 emitcode ("mov", "b,a");
8320 emitcode ("mov", "a,@%s", rname);
8324 emitcode ("mov", "b,a");
8325 emitcode ("movx", "a,@dptr");
8329 emitcode ("push", "b");
8330 emitcode ("push", "acc");
8331 emitcode ("lcall", "__gptrget");
8332 emitcode ("pop", "b");
8336 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8337 emitcode ("orl", "a,b");
8340 if (p_type == GPOINTER)
8341 emitcode ("pop", "b");
8347 emitcode ("mov", "@%s,a", rname);
8351 emitcode ("movx", "@dptr,a");
8355 emitcode ("lcall", "__gptrput");
8359 /*-----------------------------------------------------------------*/
8360 /* genDataPointerSet - remat pointer to data space */
8361 /*-----------------------------------------------------------------*/
8363 genDataPointerSet (operand * right,
8367 int size, offset = 0;
8368 char *l, buffer[256];
8370 aopOp (right, ic, FALSE, FALSE);
8372 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8373 size = AOP_SIZE (right);
8377 sprintf (buffer, "(%s + %d)", l + 1, offset);
8379 sprintf (buffer, "%s", l + 1);
8380 emitcode ("mov", "%s,%s", buffer,
8381 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8384 freeAsmop (right, NULL, ic, TRUE);
8385 freeAsmop (result, NULL, ic, TRUE);
8388 /*-----------------------------------------------------------------*/
8389 /* genNearPointerSet - emitcode for near pointer put */
8390 /*-----------------------------------------------------------------*/
8392 genNearPointerSet (operand * right,
8399 sym_link *retype, *letype;
8400 sym_link *ptype = operandType (result);
8402 retype = getSpec (operandType (right));
8403 letype = getSpec (ptype);
8405 aopOp (result, ic, FALSE, FALSE);
8407 /* if the result is rematerializable &
8408 in data space & not a bit variable */
8409 if (AOP_TYPE (result) == AOP_IMMD &&
8410 DCL_TYPE (ptype) == POINTER &&
8411 !IS_BITVAR (retype) &&
8412 !IS_BITVAR (letype))
8414 genDataPointerSet (right, result, ic);
8418 /* if the value is already in a pointer register
8419 then don't need anything more */
8420 if (!AOP_INPREG (AOP (result)))
8422 /* otherwise get a free pointer register */
8424 preg = getFreePtr (ic, &aop, FALSE);
8425 emitcode ("mov", "%s,%s",
8427 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8431 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8433 freeAsmop (result, NULL, ic, TRUE);
8434 aopOp (right, ic, FALSE, FALSE);
8436 /* if bitfield then unpack the bits */
8437 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8438 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8441 /* we have can just get the values */
8442 int size = AOP_SIZE (right);
8447 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8451 emitcode ("mov", "@%s,a", rname);
8454 emitcode ("mov", "@%s,%s", rname, l);
8456 emitcode ("inc", "%s", rname);
8461 /* now some housekeeping stuff */
8464 /* we had to allocate for this iCode */
8465 freeAsmop (NULL, aop, ic, TRUE);
8469 /* we did not allocate which means left
8470 already in a pointer register, then
8471 if size > 0 && this could be used again
8472 we have to point it back to where it
8474 if (AOP_SIZE (right) > 1 &&
8475 !OP_SYMBOL (result)->remat &&
8476 (OP_SYMBOL (result)->liveTo > ic->seq ||
8479 int size = AOP_SIZE (right) - 1;
8481 emitcode ("dec", "%s", rname);
8486 freeAsmop (right, NULL, ic, TRUE);
8491 /*-----------------------------------------------------------------*/
8492 /* genPagedPointerSet - emitcode for Paged pointer put */
8493 /*-----------------------------------------------------------------*/
8495 genPagedPointerSet (operand * right,
8502 sym_link *retype, *letype;
8504 retype = getSpec (operandType (right));
8505 letype = getSpec (operandType (result));
8507 aopOp (result, ic, FALSE, FALSE);
8509 /* if the value is already in a pointer register
8510 then don't need anything more */
8511 if (!AOP_INPREG (AOP (result)))
8513 /* otherwise get a free pointer register */
8515 preg = getFreePtr (ic, &aop, FALSE);
8516 emitcode ("mov", "%s,%s",
8518 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8522 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8524 freeAsmop (result, NULL, ic, TRUE);
8525 aopOp (right, ic, FALSE, FALSE);
8527 /* if bitfield then unpack the bits */
8528 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8529 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8532 /* we have can just get the values */
8533 int size = AOP_SIZE (right);
8538 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8541 emitcode ("movx", "@%s,a", rname);
8544 emitcode ("inc", "%s", rname);
8550 /* now some housekeeping stuff */
8553 /* we had to allocate for this iCode */
8554 freeAsmop (NULL, aop, ic, TRUE);
8558 /* we did not allocate which means left
8559 already in a pointer register, then
8560 if size > 0 && this could be used again
8561 we have to point it back to where it
8563 if (AOP_SIZE (right) > 1 &&
8564 !OP_SYMBOL (result)->remat &&
8565 (OP_SYMBOL (result)->liveTo > ic->seq ||
8568 int size = AOP_SIZE (right) - 1;
8570 emitcode ("dec", "%s", rname);
8575 freeAsmop (right, NULL, ic, TRUE);
8580 /*-----------------------------------------------------------------*/
8581 /* genFarPointerSet - set value from far space */
8582 /*-----------------------------------------------------------------*/
8584 genFarPointerSet (operand * right,
8585 operand * result, iCode * ic)
8588 sym_link *retype = getSpec (operandType (right));
8589 sym_link *letype = getSpec (operandType (result));
8591 aopOp (result, ic, FALSE, FALSE);
8593 /* if the operand is already in dptr
8594 then we do nothing else we move the value to dptr */
8595 if (AOP_TYPE (result) != AOP_STR)
8597 /* if this is remateriazable */
8598 if (AOP_TYPE (result) == AOP_IMMD)
8599 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8602 /* we need to get it byte by byte */
8603 _startLazyDPSEvaluation ();
8604 if (AOP_TYPE (result) != AOP_DPTR)
8606 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8607 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8608 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8612 /* We need to generate a load to DPTR indirect through DPTR. */
8613 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8615 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8616 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8617 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8618 emitcode ("pop", "dph");
8619 emitcode ("pop", "dpl");
8621 _endLazyDPSEvaluation ();
8624 /* so dptr know contains the address */
8625 freeAsmop (result, NULL, ic, TRUE);
8626 aopOp (right, ic, FALSE, TRUE);
8628 /* if bit then unpack */
8629 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8630 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8633 size = AOP_SIZE (right);
8636 _startLazyDPSEvaluation ();
8639 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8645 emitcode ("movx", "@dptr,a");
8647 emitcode ("inc", "dptr");
8649 _endLazyDPSEvaluation ();
8652 freeAsmop (right, NULL, ic, TRUE);
8655 /*-----------------------------------------------------------------*/
8656 /* genGenPointerSet - set value from generic pointer space */
8657 /*-----------------------------------------------------------------*/
8659 genGenPointerSet (operand * right,
8660 operand * result, iCode * ic)
8663 sym_link *retype = getSpec (operandType (right));
8664 sym_link *letype = getSpec (operandType (result));
8666 aopOp (result, ic, FALSE, TRUE);
8668 /* if the operand is already in dptr
8669 then we do nothing else we move the value to dptr */
8670 if (AOP_TYPE (result) != AOP_STR)
8672 _startLazyDPSEvaluation ();
8673 /* if this is remateriazable */
8674 if (AOP_TYPE (result) == AOP_IMMD)
8676 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8677 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8680 { /* we need to get it byte by byte */
8681 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8682 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8683 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8684 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8686 _endLazyDPSEvaluation ();
8688 /* so dptr know contains the address */
8689 freeAsmop (result, NULL, ic, TRUE);
8690 aopOp (right, ic, FALSE, TRUE);
8692 /* if bit then unpack */
8693 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8694 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8697 size = AOP_SIZE (right);
8700 _startLazyDPSEvaluation ();
8703 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8709 emitcode ("lcall", "__gptrput");
8711 emitcode ("inc", "dptr");
8713 _endLazyDPSEvaluation ();
8716 freeAsmop (right, NULL, ic, TRUE);
8719 /*-----------------------------------------------------------------*/
8720 /* genPointerSet - stores the value into a pointer location */
8721 /*-----------------------------------------------------------------*/
8723 genPointerSet (iCode * ic)
8725 operand *right, *result;
8726 sym_link *type, *etype;
8729 D (emitcode (";", "genPointerSet ");
8732 right = IC_RIGHT (ic);
8733 result = IC_RESULT (ic);
8735 /* depending on the type of pointer we need to
8736 move it to the correct pointer register */
8737 type = operandType (result);
8738 etype = getSpec (type);
8739 /* if left is of type of pointer then it is simple */
8740 if (IS_PTR (type) && !IS_FUNC (type->next))
8742 p_type = DCL_TYPE (type);
8746 /* we have to go by the storage class */
8747 p_type = PTR_TYPE (SPEC_OCLS (etype));
8750 /* now that we have the pointer type we assign
8751 the pointer values */
8757 genNearPointerSet (right, result, ic);
8761 genPagedPointerSet (right, result, ic);
8765 genFarPointerSet (right, result, ic);
8769 genGenPointerSet (right, result, ic);
8775 /*-----------------------------------------------------------------*/
8776 /* genIfx - generate code for Ifx statement */
8777 /*-----------------------------------------------------------------*/
8779 genIfx (iCode * ic, iCode * popIc)
8781 operand *cond = IC_COND (ic);
8784 D (emitcode (";", "genIfx "););
8786 aopOp (cond, ic, FALSE, FALSE);
8788 /* get the value into acc */
8789 if (AOP_TYPE (cond) != AOP_CRY)
8793 /* the result is now in the accumulator */
8794 freeAsmop (cond, NULL, ic, TRUE);
8796 /* if there was something to be popped then do it */
8800 /* if the condition is a bit variable */
8801 if (isbit && IS_ITEMP (cond) &&
8803 genIfxJump (ic, SPIL_LOC (cond)->rname);
8804 else if (isbit && !IS_ITEMP (cond))
8805 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8807 genIfxJump (ic, "a");
8812 /*-----------------------------------------------------------------*/
8813 /* genAddrOf - generates code for address of */
8814 /*-----------------------------------------------------------------*/
8816 genAddrOf (iCode * ic)
8818 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8821 D (emitcode (";", "genAddrOf ");
8824 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8826 /* if the operand is on the stack then we
8827 need to get the stack offset of this
8831 /* if it has an offset then we need to compute
8835 emitcode ("mov", "a,_bp");
8836 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8837 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8841 /* we can just move _bp */
8842 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8844 /* fill the result with zero */
8845 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8848 if (options.stack10bit && size < (FPTRSIZE - 1))
8851 "*** warning: pointer to stack var truncated.\n");
8858 if (options.stack10bit && offset == 2)
8860 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8864 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8871 /* object not on stack then we need the name */
8872 size = AOP_SIZE (IC_RESULT (ic));
8877 char s[SDCC_NAME_MAX];
8879 sprintf (s, "#(%s >> %d)",
8883 sprintf (s, "#%s", sym->rname);
8884 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8888 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8892 /*-----------------------------------------------------------------*/
8893 /* genFarFarAssign - assignment when both are in far space */
8894 /*-----------------------------------------------------------------*/
8896 genFarFarAssign (operand * result, operand * right, iCode * ic)
8898 int size = AOP_SIZE (right);
8904 /* This is a net loss for size == 1, but a big gain
8907 D (emitcode (";", "genFarFarAssign (improved)");
8910 aopOp (result, ic, TRUE, TRUE);
8912 _startLazyDPSEvaluation ();
8915 aopPut (AOP (result),
8916 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8919 _endLazyDPSEvaluation ();
8920 freeAsmop (result, NULL, ic, FALSE);
8921 freeAsmop (right, NULL, ic, FALSE);
8925 D (emitcode (";", "genFarFarAssign ");
8928 /* first push the right side on to the stack */
8929 _startLazyDPSEvaluation ();
8932 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8934 emitcode ("push", "acc");
8937 freeAsmop (right, NULL, ic, FALSE);
8938 /* now assign DPTR to result */
8939 aopOp (result, ic, FALSE, FALSE);
8940 size = AOP_SIZE (result);
8943 emitcode ("pop", "acc");
8944 aopPut (AOP (result), "a", --offset);
8946 freeAsmop (result, NULL, ic, FALSE);
8947 _endLazyDPSEvaluation ();
8951 /*-----------------------------------------------------------------*/
8952 /* genAssign - generate code for assignment */
8953 /*-----------------------------------------------------------------*/
8955 genAssign (iCode * ic)
8957 operand *result, *right;
8959 unsigned long lit = 0L;
8961 D (emitcode (";", "genAssign ");
8964 result = IC_RESULT (ic);
8965 right = IC_RIGHT (ic);
8967 /* if they are the same */
8968 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8971 aopOp (right, ic, FALSE, FALSE);
8973 emitcode (";", "genAssign: resultIsFar = %s",
8974 isOperandInFarSpace (result) ?
8977 /* special case both in far space */
8978 if ((AOP_TYPE (right) == AOP_DPTR ||
8979 AOP_TYPE (right) == AOP_DPTR2) &&
8980 /* IS_TRUE_SYMOP(result) && */
8981 isOperandInFarSpace (result))
8983 genFarFarAssign (result, right, ic);
8987 aopOp (result, ic, TRUE, FALSE);
8989 /* if they are the same registers */
8990 if (sameRegs (AOP (right), AOP (result)))
8993 /* if the result is a bit */
8994 if (AOP_TYPE (result) == AOP_CRY)
8997 /* if the right size is a literal then
8998 we know what the value is */
8999 if (AOP_TYPE (right) == AOP_LIT)
9001 if (((int) operandLitValue (right)))
9002 aopPut (AOP (result), one, 0);
9004 aopPut (AOP (result), zero, 0);
9008 /* the right is also a bit variable */
9009 if (AOP_TYPE (right) == AOP_CRY)
9011 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9012 aopPut (AOP (result), "c", 0);
9018 aopPut (AOP (result), "a", 0);
9022 /* bit variables done */
9024 size = AOP_SIZE (result);
9026 if (AOP_TYPE (right) == AOP_LIT)
9027 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9030 (AOP_TYPE (result) != AOP_REG) &&
9031 (AOP_TYPE (right) == AOP_LIT) &&
9032 !IS_FLOAT (operandType (right)))
9034 D (emitcode (";", "Kevin's better literal load code");
9036 _startLazyDPSEvaluation ();
9037 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9039 aopPut (AOP (result),
9040 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9045 /* And now fill the rest with zeros. */
9048 emitcode ("clr", "a");
9052 aopPut (AOP (result), "a", offset++);
9054 _endLazyDPSEvaluation ();
9058 _startLazyDPSEvaluation ();
9061 aopPut (AOP (result),
9062 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9066 _endLazyDPSEvaluation ();
9070 freeAsmop (right, NULL, ic, FALSE);
9071 freeAsmop (result, NULL, ic, TRUE);
9074 /*-----------------------------------------------------------------*/
9075 /* genJumpTab - generates code for jump table */
9076 /*-----------------------------------------------------------------*/
9078 genJumpTab (iCode * ic)
9083 D (emitcode (";", "genJumpTab ");
9086 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9087 /* get the condition into accumulator */
9088 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9090 /* multiply by four! */
9091 emitcode ("add", "a,acc");
9092 emitcode ("add", "a,acc");
9093 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9095 jtab = newiTempLabel (NULL);
9096 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9097 emitcode ("jmp", "@a+dptr");
9098 emitcode ("", "%05d$:", jtab->key + 100);
9099 /* now generate the jump labels */
9100 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9101 jtab = setNextItem (IC_JTLABELS (ic)))
9102 emitcode ("ljmp", "%05d$", jtab->key + 100);
9106 /*-----------------------------------------------------------------*/
9107 /* genCast - gen code for casting */
9108 /*-----------------------------------------------------------------*/
9110 genCast (iCode * ic)
9112 operand *result = IC_RESULT (ic);
9113 sym_link *ctype = operandType (IC_LEFT (ic));
9114 sym_link *rtype = operandType (IC_RIGHT (ic));
9115 operand *right = IC_RIGHT (ic);
9118 D (emitcode (";", "genCast ");
9121 /* if they are equivalent then do nothing */
9122 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9125 aopOp (right, ic, FALSE, FALSE);
9126 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9128 /* if the result is a bit */
9129 if (AOP_TYPE (result) == AOP_CRY)
9131 /* if the right size is a literal then
9132 we know what the value is */
9133 if (AOP_TYPE (right) == AOP_LIT)
9135 if (((int) operandLitValue (right)))
9136 aopPut (AOP (result), one, 0);
9138 aopPut (AOP (result), zero, 0);
9143 /* the right is also a bit variable */
9144 if (AOP_TYPE (right) == AOP_CRY)
9146 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9147 aopPut (AOP (result), "c", 0);
9153 aopPut (AOP (result), "a", 0);
9157 /* if they are the same size : or less */
9158 if (AOP_SIZE (result) <= AOP_SIZE (right))
9161 /* if they are in the same place */
9162 if (sameRegs (AOP (right), AOP (result)))
9165 /* if they in different places then copy */
9166 size = AOP_SIZE (result);
9168 _startLazyDPSEvaluation ();
9171 aopPut (AOP (result),
9172 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9176 _endLazyDPSEvaluation ();
9181 /* if the result is of type pointer */
9186 sym_link *type = operandType (right);
9188 /* pointer to generic pointer */
9189 if (IS_GENPTR (ctype))
9195 p_type = DCL_TYPE (type);
9199 #if OLD_CAST_BEHAVIOR
9200 /* KV: we are converting a non-pointer type to
9201 * a generic pointer. This (ifdef'd out) code
9202 * says that the resulting generic pointer
9203 * should have the same class as the storage
9204 * location of the non-pointer variable.
9206 * For example, converting an int (which happens
9207 * to be stored in DATA space) to a pointer results
9208 * in a DATA generic pointer; if the original int
9209 * in XDATA space, so will be the resulting pointer.
9211 * I don't like that behavior, and thus this change:
9212 * all such conversions will be forced to XDATA and
9213 * throw a warning. If you want some non-XDATA
9214 * type, or you want to suppress the warning, you
9215 * must go through an intermediate cast, like so:
9217 * char _generic *gp = (char _xdata *)(intVar);
9219 sym_link *etype = getSpec (type);
9221 /* we have to go by the storage class */
9222 if (SPEC_OCLS (etype) != generic)
9224 p_type = PTR_TYPE (SPEC_OCLS (etype));
9229 /* Converting unknown class (i.e. register variable)
9230 * to generic pointer. This is not good, but
9231 * we'll make a guess (and throw a warning).
9234 werror (W_INT_TO_GEN_PTR_CAST);
9238 /* the first two bytes are known */
9239 size = GPTRSIZE - 1;
9241 _startLazyDPSEvaluation ();
9244 aopPut (AOP (result),
9245 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9249 _endLazyDPSEvaluation ();
9251 /* the last byte depending on type */
9269 /* this should never happen */
9270 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9271 "got unknown pointer type");
9274 aopPut (AOP (result), l, GPTRSIZE - 1);
9278 /* just copy the pointers */
9279 size = AOP_SIZE (result);
9281 _startLazyDPSEvaluation ();
9284 aopPut (AOP (result),
9285 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9289 _endLazyDPSEvaluation ();
9293 /* so we now know that the size of destination is greater
9294 than the size of the source */
9295 /* we move to result for the size of source */
9296 size = AOP_SIZE (right);
9298 _startLazyDPSEvaluation ();
9301 aopPut (AOP (result),
9302 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9306 _endLazyDPSEvaluation ();
9308 /* now depending on the sign of the source && destination */
9309 size = AOP_SIZE (result) - AOP_SIZE (right);
9310 /* if unsigned or not an integral type */
9311 /* also, if the source is a bit, we don't need to sign extend, because
9312 * it can't possibly have set the sign bit.
9314 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9318 aopPut (AOP (result), zero, offset++);
9323 /* we need to extend the sign :{ */
9324 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9325 FALSE, FALSE, TRUE);
9327 emitcode ("rlc", "a");
9328 emitcode ("subb", "a,acc");
9330 aopPut (AOP (result), "a", offset++);
9333 /* we are done hurray !!!! */
9336 freeAsmop (right, NULL, ic, TRUE);
9337 freeAsmop (result, NULL, ic, TRUE);
9341 /*-----------------------------------------------------------------*/
9342 /* genDjnz - generate decrement & jump if not zero instrucion */
9343 /*-----------------------------------------------------------------*/
9345 genDjnz (iCode * ic, iCode * ifx)
9351 /* if the if condition has a false label
9352 then we cannot save */
9356 /* if the minus is not of the form
9358 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9359 !IS_OP_LITERAL (IC_RIGHT (ic)))
9362 if (operandLitValue (IC_RIGHT (ic)) != 1)
9365 /* if the size of this greater than one then no
9367 if (getSize (operandType (IC_RESULT (ic))) > 1)
9370 /* otherwise we can save BIG */
9371 D(emitcode(";", "genDjnz"););
9373 lbl = newiTempLabel (NULL);
9374 lbl1 = newiTempLabel (NULL);
9376 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9378 if (AOP_NEEDSACC(IC_RESULT(ic)))
9380 /* If the result is accessed indirectly via
9381 * the accumulator, we must explicitly write
9382 * it back after the decrement.
9384 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9386 if (strcmp(rByte, "a"))
9388 /* Something is hopelessly wrong */
9389 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9390 __FILE__, __LINE__);
9391 /* We can just give up; the generated code will be inefficient,
9394 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9397 emitcode ("dec", "%s", rByte);
9398 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9399 emitcode ("jnz", "%05d$", lbl->key + 100);
9401 else if (IS_AOP_PREG (IC_RESULT (ic)))
9403 emitcode ("dec", "%s",
9404 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9405 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9406 emitcode ("jnz", "%05d$", lbl->key + 100);
9410 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9413 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9414 emitcode ("", "%05d$:", lbl->key + 100);
9415 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9416 emitcode ("", "%05d$:", lbl1->key + 100);
9418 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9423 /*-----------------------------------------------------------------*/
9424 /* genReceive - generate code for a receive iCode */
9425 /*-----------------------------------------------------------------*/
9427 genReceive (iCode * ic)
9430 D (emitcode (";", "genReceive ");
9433 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9434 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9435 IS_TRUE_SYMOP (IC_RESULT (ic))))
9437 int size = getSize (operandType (IC_RESULT (ic)));
9438 int offset = fReturnSizeDS390 - size;
9441 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9442 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9445 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9446 size = AOP_SIZE (IC_RESULT (ic));
9450 emitcode ("pop", "acc");
9451 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9458 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9460 assignResultValue (IC_RESULT (ic));
9463 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9466 /*-----------------------------------------------------------------*/
9467 /* gen390Code - generate code for Dallas 390 based controllers */
9468 /*-----------------------------------------------------------------*/
9470 gen390Code (iCode * lic)
9475 lineHead = lineCurr = NULL;
9479 /* print the allocation information */
9481 printAllocInfo (currFunc, codeOutFile);
9483 /* if debug information required */
9484 if (options.debug && currFunc)
9486 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9488 if (IS_STATIC (currFunc->etype))
9489 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9491 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9494 /* stack pointer name */
9495 if (options.useXstack)
9501 for (ic = lic; ic; ic = ic->next)
9504 if (cln != ic->lineno)
9509 emitcode ("", "C$%s$%d$%d$%d ==.",
9510 FileBaseName (ic->filename), ic->lineno,
9511 ic->level, ic->block);
9514 emitcode (";", "%s %d", ic->filename, ic->lineno);
9517 /* if the result is marked as
9518 spilt and rematerializable or code for
9519 this has already been generated then
9521 if (resultRemat (ic) || ic->generated)
9524 /* depending on the operation */
9544 /* IPOP happens only when trying to restore a
9545 spilt live range, if there is an ifx statement
9546 following this pop then the if statement might
9547 be using some of the registers being popped which
9548 would destory the contents of the register so
9549 we need to check for this condition and handle it */
9551 ic->next->op == IFX &&
9552 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9553 genIfx (ic->next, ic);
9571 genEndFunction (ic);
9591 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9608 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9612 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9619 /* note these two are xlated by algebraic equivalence
9620 during parsing SDCC.y */
9621 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9622 "got '>=' or '<=' shouldn't have come here");
9626 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9638 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9642 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9646 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9673 case GET_VALUE_AT_ADDRESS:
9678 if (POINTER_SET (ic))
9705 addSet (&_G.sendSet, ic);
9714 /* now we are ready to call the
9715 peep hole optimizer */
9716 if (!options.nopeep)
9717 peepHole (&lineHead);
9719 /* now do the actual printing */
9720 printLine (lineHead, codeOutFile);