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)
315 #ifdef BETTER_LITERAL_SHIFT
322 /*-----------------------------------------------------------------*/
323 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
324 /* desired one. Call before using DPTR within a lazy DPS evaluation */
326 /*-----------------------------------------------------------------*/
336 if (_desiredDPS != _currentDPS)
340 emitcode ("inc", "dps");
344 emitcode ("dec", "dps");
346 _currentDPS = _desiredDPS;
350 /*-----------------------------------------------------------------*/
351 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
353 /* Forces us back to the safe state (standard DPTR selected). */
354 /*-----------------------------------------------------------------*/
356 _endLazyDPSEvaluation (void)
358 #ifdef BETTER_LITERAL_SHIFT
377 /*-----------------------------------------------------------------*/
378 /* pointerCode - returns the code for a pointer type */
379 /*-----------------------------------------------------------------*/
381 pointerCode (sym_link * etype)
384 return PTR_TYPE (SPEC_OCLS (etype));
388 /*-----------------------------------------------------------------*/
389 /* aopForSym - for a true symbol */
390 /*-----------------------------------------------------------------*/
392 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
395 memmap *space = SPEC_OCLS (sym->etype);
397 /* if already has one */
401 /* assign depending on the storage class */
402 /* if it is on the stack or indirectly addressable */
403 /* space we need to assign either r0 or r1 to it */
404 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
406 sym->aop = aop = newAsmop (0);
407 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
408 aop->size = getSize (sym->type);
410 /* now assign the address of the variable to
411 the pointer register */
412 if (aop->type != AOP_STK)
418 emitcode ("push", "acc");
420 emitcode ("mov", "a,_bp");
421 emitcode ("add", "a,#0x%02x",
423 ((char) (sym->stack - _G.nRegsSaved)) :
424 ((char) sym->stack)) & 0xff);
425 emitcode ("mov", "%s,a",
426 aop->aopu.aop_ptr->name);
429 emitcode ("pop", "acc");
432 emitcode ("mov", "%s,#%s",
433 aop->aopu.aop_ptr->name,
435 aop->paged = space->paged;
438 aop->aopu.aop_stk = sym->stack;
442 if (sym->onStack && options.stack10bit)
444 /* It's on the 10 bit stack, which is located in
449 emitcode ("push", "acc");
451 emitcode ("mov", "a,_bp");
452 emitcode ("add", "a,#0x%02x",
454 ((char) (sym->stack - _G.nRegsSaved)) :
455 ((char) sym->stack)) & 0xff);
460 emitcode ("mov", "dpx1,#0x40");
461 emitcode ("mov", "dph1,#0x00");
462 emitcode ("mov", "dpl1, a");
467 emitcode ("mov", "dpx,#0x40");
468 emitcode ("mov", "dph,#0x00");
469 emitcode ("mov", "dpl, a");
473 emitcode ("pop", "acc");
475 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
476 aop->size = getSize (sym->type);
480 /* if in bit space */
481 if (IN_BITSPACE (space))
483 sym->aop = aop = newAsmop (AOP_CRY);
484 aop->aopu.aop_dir = sym->rname;
485 aop->size = getSize (sym->type);
488 /* if it is in direct space */
489 if (IN_DIRSPACE (space))
491 sym->aop = aop = newAsmop (AOP_DIR);
492 aop->aopu.aop_dir = sym->rname;
493 aop->size = getSize (sym->type);
497 /* special case for a function */
498 if (IS_FUNC (sym->type))
500 sym->aop = aop = newAsmop (AOP_IMMD);
501 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
502 strcpy (aop->aopu.aop_immd, sym->rname);
503 aop->size = FPTRSIZE;
507 /* only remaining is far space */
508 /* in which case DPTR gets the address */
509 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
514 emitcode ("mov", "dptr,#%s", sym->rname);
519 emitcode ("mov", "dptr,#%s", sym->rname);
521 aop->size = getSize (sym->type);
523 /* if it is in code space */
524 if (IN_CODESPACE (space))
530 /*-----------------------------------------------------------------*/
531 /* aopForRemat - rematerialzes an object */
532 /*-----------------------------------------------------------------*/
534 aopForRemat (symbol * sym)
536 iCode *ic = sym->rematiCode;
537 asmop *aop = newAsmop (AOP_IMMD);
544 val += (int) operandLitValue (IC_RIGHT (ic));
545 else if (ic->op == '-')
546 val -= (int) operandLitValue (IC_RIGHT (ic));
550 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
554 sprintf (buffer, "(%s %c 0x%04x)",
555 OP_SYMBOL (IC_LEFT (ic))->rname,
556 val >= 0 ? '+' : '-',
559 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
561 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
562 strcpy (aop->aopu.aop_immd, buffer);
566 /*-----------------------------------------------------------------*/
567 /* regsInCommon - two operands have some registers in common */
568 /*-----------------------------------------------------------------*/
570 regsInCommon (operand * op1, operand * op2)
575 /* if they have registers in common */
576 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
579 sym1 = OP_SYMBOL (op1);
580 sym2 = OP_SYMBOL (op2);
582 if (sym1->nRegs == 0 || sym2->nRegs == 0)
585 for (i = 0; i < sym1->nRegs; i++)
591 for (j = 0; j < sym2->nRegs; j++)
596 if (sym2->regs[j] == sym1->regs[i])
604 /*-----------------------------------------------------------------*/
605 /* operandsEqu - equivalent */
606 /*-----------------------------------------------------------------*/
608 operandsEqu (operand * op1, operand * op2)
612 /* if they not symbols */
613 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
616 sym1 = OP_SYMBOL (op1);
617 sym2 = OP_SYMBOL (op2);
619 /* if both are itemps & one is spilt
620 and the other is not then false */
621 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
622 sym1->isspilt != sym2->isspilt)
625 /* if they are the same */
629 if (strcmp (sym1->rname, sym2->rname) == 0)
633 /* if left is a tmp & right is not */
634 if (IS_ITEMP (op1) &&
637 (sym1->usl.spillLoc == sym2))
640 if (IS_ITEMP (op2) &&
644 (sym2->usl.spillLoc == sym1))
650 /*-----------------------------------------------------------------*/
651 /* sameRegs - two asmops have the same registers */
652 /*-----------------------------------------------------------------*/
654 sameRegs (asmop * aop1, asmop * aop2)
660 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
667 if (aop1->type != AOP_REG ||
668 aop2->type != AOP_REG)
671 if (aop1->size != aop2->size)
674 for (i = 0; i < aop1->size; i++)
675 if (aop1->aopu.aop_reg[i] !=
676 aop2->aopu.aop_reg[i])
682 /*-----------------------------------------------------------------*/
683 /* aopOp - allocates an asmop for an operand : */
684 /*-----------------------------------------------------------------*/
686 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
695 /* if this a literal */
696 if (IS_OP_LITERAL (op))
698 op->aop = aop = newAsmop (AOP_LIT);
699 aop->aopu.aop_lit = op->operand.valOperand;
700 aop->size = getSize (operandType (op));
704 /* if already has a asmop then continue */
708 /* if the underlying symbol has a aop */
709 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
711 op->aop = OP_SYMBOL (op)->aop;
715 /* if this is a true symbol */
716 if (IS_TRUE_SYMOP (op))
718 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
722 /* this is a temporary : this has
728 e) can be a return use only */
730 sym = OP_SYMBOL (op);
733 /* if the type is a conditional */
734 if (sym->regType == REG_CND)
736 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
741 /* if it is spilt then two situations
743 b) has a spill location */
744 if (sym->isspilt || sym->nRegs == 0)
747 /* rematerialize it NOW */
750 sym->aop = op->aop = aop =
752 aop->size = getSize (sym->type);
759 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
760 aop->size = getSize (sym->type);
761 for (i = 0; i < 2; i++)
762 aop->aopu.aop_str[i] = accUse[i];
772 /* a AOP_STR uses DPTR, but DPTR is already in use;
775 fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
778 aop = op->aop = sym->aop = newAsmop (AOP_STR);
779 aop->size = getSize (sym->type);
780 for (i = 0; i < (int) fReturnSizeDS390; i++)
781 aop->aopu.aop_str[i] = fReturn[i];
785 /* else spill location */
786 sym->aop = op->aop = aop =
787 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
788 aop->size = getSize (sym->type);
792 /* must be in a register */
793 sym->aop = op->aop = aop = newAsmop (AOP_REG);
794 aop->size = sym->nRegs;
795 for (i = 0; i < sym->nRegs; i++)
796 aop->aopu.aop_reg[i] = sym->regs[i];
799 /*-----------------------------------------------------------------*/
800 /* freeAsmop - free up the asmop given to an operand */
801 /*----------------------------------------------------------------*/
803 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
820 /* depending on the asmop type only three cases need work AOP_RO
821 , AOP_R1 && AOP_STK */
829 emitcode ("pop", "ar0");
833 bitVectUnSetBit (ic->rUsed, R0_IDX);
841 emitcode ("pop", "ar1");
845 bitVectUnSetBit (ic->rUsed, R1_IDX);
851 int stk = aop->aopu.aop_stk + aop->size;
852 bitVectUnSetBit (ic->rUsed, R0_IDX);
853 bitVectUnSetBit (ic->rUsed, R1_IDX);
855 getFreePtr (ic, &aop, FALSE);
857 if (options.stack10bit)
859 /* I'm not sure what to do here yet... */
862 "*** Warning: probably generating bad code for "
863 "10 bit stack mode.\n");
868 emitcode ("mov", "a,_bp");
869 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
870 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
874 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
879 emitcode ("pop", "acc");
880 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
883 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
886 freeAsmop (op, NULL, ic, TRUE);
889 emitcode ("pop", "ar0");
895 emitcode ("pop", "ar1");
902 /* all other cases just dealloc */
908 OP_SYMBOL (op)->aop = NULL;
909 /* if the symbol has a spill */
911 SPIL_LOC (op)->aop = NULL;
916 /*------------------------------------------------------------------*/
917 /* aopGet - for fetching value of the aop */
919 /* Set canClobberACC if you are sure it is OK to clobber the value */
920 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
921 /* just less efficient. */
922 /*------------------------------------------------------------------*/
934 /* offset is greater than
936 if (offset > (aop->size - 1) &&
937 aop->type != AOP_LIT)
940 /* depending on type */
946 /* if we need to increment it */
947 while (offset > aop->coff)
949 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
953 while (offset < aop->coff)
955 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
962 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
963 return (dname ? "acc" : "a");
965 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
966 rs = Safe_calloc (1, strlen (s) + 1);
973 if (aop->type == AOP_DPTR2)
978 emitcode ("xch", "a, %s", DP2_RESULT_REG);
984 while (offset > aop->coff)
986 emitcode ("inc", "dptr");
990 while (offset < aop->coff)
992 emitcode ("lcall", "__decdptr");
999 emitcode ("clr", "a");
1000 emitcode ("movc", "a,@a+dptr");
1004 emitcode ("movx", "a,@dptr");
1007 if (aop->type == AOP_DPTR2)
1012 emitcode ("xch", "a, %s", DP2_RESULT_REG);
1013 return DP2_RESULT_REG;
1016 return (dname ? "acc" : "a");
1020 sprintf (s, "#%s", aop->aopu.aop_immd);
1022 sprintf (s, "#(%s >> %d)",
1027 aop->aopu.aop_immd);
1028 rs = Safe_calloc (1, strlen (s) + 1);
1034 sprintf (s, "(%s + %d)",
1038 sprintf (s, "%s", aop->aopu.aop_dir);
1039 rs = Safe_calloc (1, strlen (s) + 1);
1045 return aop->aopu.aop_reg[offset]->dname;
1047 return aop->aopu.aop_reg[offset]->name;
1050 emitcode ("clr", "a");
1051 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1052 emitcode ("rlc", "a");
1053 return (dname ? "acc" : "a");
1056 if (!offset && dname)
1058 return aop->aopu.aop_str[offset];
1061 return aopLiteral (aop->aopu.aop_lit, offset);
1065 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1069 return aop->aopu.aop_str[offset];
1073 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1074 "aopget got unsupported aop->type");
1077 /*-----------------------------------------------------------------*/
1078 /* aopPut - puts a string for a aop */
1079 /*-----------------------------------------------------------------*/
1081 aopPut (asmop * aop, char *s, int offset)
1085 if (aop->size && offset > (aop->size - 1))
1087 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1088 "aopPut got offset > aop->size");
1092 /* will assign value to value */
1093 /* depending on where it is ofcourse */
1098 sprintf (d, "(%s + %d)",
1099 aop->aopu.aop_dir, offset);
1101 sprintf (d, "%s", aop->aopu.aop_dir);
1104 emitcode ("mov", "%s,%s", d, s);
1109 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1110 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1113 strcmp (s, "r0") == 0 ||
1114 strcmp (s, "r1") == 0 ||
1115 strcmp (s, "r2") == 0 ||
1116 strcmp (s, "r3") == 0 ||
1117 strcmp (s, "r4") == 0 ||
1118 strcmp (s, "r5") == 0 ||
1119 strcmp (s, "r6") == 0 ||
1120 strcmp (s, "r7") == 0)
1121 emitcode ("mov", "%s,%s",
1122 aop->aopu.aop_reg[offset]->dname, s);
1124 emitcode ("mov", "%s,%s",
1125 aop->aopu.aop_reg[offset]->name, s);
1132 if (aop->type == AOP_DPTR2)
1140 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1141 "aopPut writting to code space");
1145 while (offset > aop->coff)
1148 emitcode ("inc", "dptr");
1151 while (offset < aop->coff)
1154 emitcode ("lcall", "__decdptr");
1159 /* if not in accumulater */
1162 emitcode ("movx", "@dptr,a");
1164 if (aop->type == AOP_DPTR2)
1172 while (offset > aop->coff)
1175 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1177 while (offset < aop->coff)
1180 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1187 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1193 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1195 else if (strcmp (s, "r0") == 0 ||
1196 strcmp (s, "r1") == 0 ||
1197 strcmp (s, "r2") == 0 ||
1198 strcmp (s, "r3") == 0 ||
1199 strcmp (s, "r4") == 0 ||
1200 strcmp (s, "r5") == 0 ||
1201 strcmp (s, "r6") == 0 ||
1202 strcmp (s, "r7") == 0)
1205 sprintf (buffer, "a%s", s);
1206 emitcode ("mov", "@%s,%s",
1207 aop->aopu.aop_ptr->name, buffer);
1210 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1215 if (strcmp (s, "a") == 0)
1216 emitcode ("push", "acc");
1218 emitcode ("push", "%s", s);
1223 /* if bit variable */
1224 if (!aop->aopu.aop_dir)
1226 emitcode ("clr", "a");
1227 emitcode ("rlc", "a");
1232 emitcode ("clr", "%s", aop->aopu.aop_dir);
1234 emitcode ("setb", "%s", aop->aopu.aop_dir);
1235 else if (!strcmp (s, "c"))
1236 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1239 if (strcmp (s, "a"))
1244 symbol *lbl = newiTempLabel (NULL);
1245 emitcode ("clr", "c");
1246 emitcode ("jz", "%05d$", lbl->key + 100);
1247 emitcode ("cpl", "c");
1248 emitcode ("", "%05d$:", lbl->key + 100);
1249 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1257 if (strcmp (aop->aopu.aop_str[offset], s))
1258 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1263 if (!offset && (strcmp (s, "acc") == 0))
1266 if (strcmp (aop->aopu.aop_str[offset], s))
1267 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1271 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1272 "aopPut got unsupported aop->type");
1279 /*--------------------------------------------------------------------*/
1280 /* reAdjustPreg - points a register back to where it should (coff==0) */
1281 /*--------------------------------------------------------------------*/
1283 reAdjustPreg (asmop * aop)
1285 if ((aop->coff==0) || (aop->size <= 1)) {
1294 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1298 if (aop->type == AOP_DPTR2)
1305 emitcode ("lcall", "__decdptr");
1308 if (aop->type == AOP_DPTR2)
1318 #define AOP(op) op->aop
1319 #define AOP_TYPE(op) AOP(op)->type
1320 #define AOP_SIZE(op) AOP(op)->size
1321 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1322 AOP_TYPE(x) == AOP_R0))
1324 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1325 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1328 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1329 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1330 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1332 /* Workaround for DS80C390 bug: div ab may return bogus results
1333 * if A is accessed in instruction immediately before the div.
1335 * Will be fixed in B4 rev of processor, Dallas claims.
1338 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1339 if (!AOP_NEEDSACC(RIGHT)) \
1341 /* We can load A first, then B, since \
1342 * B (the RIGHT operand) won't clobber A, \
1343 * thus avoiding touching A right before the div. \
1345 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1346 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1348 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1352 /* Just stuff in a nop after loading A. */ \
1353 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1354 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1356 emitcode("nop", "; workaround for DS80C390 div bug."); \
1359 /*-----------------------------------------------------------------*/
1360 /* genNotFloat - generates not for float operations */
1361 /*-----------------------------------------------------------------*/
1363 genNotFloat (operand * op, operand * res)
1369 D (emitcode (";", "genNotFloat ");
1372 /* we will put 127 in the first byte of
1374 aopPut (AOP (res), "#127", 0);
1375 size = AOP_SIZE (op) - 1;
1378 _startLazyDPSEvaluation ();
1379 l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1384 emitcode ("orl", "a,%s",
1386 offset++, FALSE, FALSE, FALSE));
1388 _endLazyDPSEvaluation ();
1390 tlbl = newiTempLabel (NULL);
1391 aopPut (res->aop, one, 1);
1392 emitcode ("jz", "%05d$", (tlbl->key + 100));
1393 aopPut (res->aop, zero, 1);
1394 emitcode ("", "%05d$:", (tlbl->key + 100));
1396 size = res->aop->size - 2;
1398 /* put zeros in the rest */
1400 aopPut (res->aop, zero, offset++);
1403 /*-----------------------------------------------------------------*/
1404 /* opIsGptr: returns non-zero if the passed operand is */
1405 /* a generic pointer type. */
1406 /*-----------------------------------------------------------------*/
1408 opIsGptr (operand * op)
1410 sym_link *type = operandType (op);
1412 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1419 /*-----------------------------------------------------------------*/
1420 /* getDataSize - get the operand data size */
1421 /*-----------------------------------------------------------------*/
1423 getDataSize (operand * op)
1426 size = AOP_SIZE (op);
1427 if (size == GPTRSIZE)
1429 sym_link *type = operandType (op);
1430 if (IS_GENPTR (type))
1432 /* generic pointer; arithmetic operations
1433 * should ignore the high byte (pointer type).
1441 /*-----------------------------------------------------------------*/
1442 /* outAcc - output Acc */
1443 /*-----------------------------------------------------------------*/
1445 outAcc (operand * result)
1448 size = getDataSize (result);
1451 aopPut (AOP (result), "a", 0);
1454 /* unsigned or positive */
1457 aopPut (AOP (result), zero, offset++);
1462 /*-----------------------------------------------------------------*/
1463 /* outBitC - output a bit C */
1464 /*-----------------------------------------------------------------*/
1466 outBitC (operand * result)
1468 /* if the result is bit */
1469 if (AOP_TYPE (result) == AOP_CRY)
1471 aopPut (AOP (result), "c", 0);
1475 emitcode ("clr", "a");
1476 emitcode ("rlc", "a");
1481 /*-----------------------------------------------------------------*/
1482 /* toBoolean - emit code for orl a,operator(sizeop) */
1483 /*-----------------------------------------------------------------*/
1485 toBoolean (operand * oper)
1487 int size = AOP_SIZE (oper) - 1;
1491 /* The generic part of a generic pointer should
1492 * not participate in it's truth value.
1494 * i.e. 0x10000000 is zero.
1496 if (opIsGptr (oper))
1498 D (emitcode (";", "toBoolean: generic ptr special case.");
1503 _startLazyDPSEvaluation ();
1504 if (AOP_NEEDSACC (oper) && size)
1507 emitcode ("push", "b");
1508 emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1512 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1518 emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1522 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1525 _endLazyDPSEvaluation ();
1529 emitcode ("mov", "a,b");
1530 emitcode ("pop", "b");
1535 /*-----------------------------------------------------------------*/
1536 /* genNot - generate code for ! operation */
1537 /*-----------------------------------------------------------------*/
1542 sym_link *optype = operandType (IC_LEFT (ic));
1544 D (emitcode (";", "genNot ");
1547 /* assign asmOps to operand & result */
1548 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1549 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1551 /* if in bit space then a special case */
1552 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1554 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1555 emitcode ("cpl", "c");
1556 outBitC (IC_RESULT (ic));
1560 /* if type float then do float */
1561 if (IS_FLOAT (optype))
1563 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1567 toBoolean (IC_LEFT (ic));
1569 tlbl = newiTempLabel (NULL);
1570 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1571 emitcode ("", "%05d$:", tlbl->key + 100);
1572 outBitC (IC_RESULT (ic));
1575 /* release the aops */
1576 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1577 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1581 /*-----------------------------------------------------------------*/
1582 /* genCpl - generate code for complement */
1583 /*-----------------------------------------------------------------*/
1590 D (emitcode (";", "genCpl ");
1594 /* assign asmOps to operand & result */
1595 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1596 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1598 /* if both are in bit space then
1600 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1601 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1604 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1605 emitcode ("cpl", "c");
1606 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1610 size = AOP_SIZE (IC_RESULT (ic));
1611 _startLazyDPSEvaluation ();
1614 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1616 emitcode ("cpl", "a");
1617 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1619 _endLazyDPSEvaluation ();
1623 /* release the aops */
1624 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1625 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1628 /*-----------------------------------------------------------------*/
1629 /* genUminusFloat - unary minus for floating points */
1630 /*-----------------------------------------------------------------*/
1632 genUminusFloat (operand * op, operand * result)
1634 int size, offset = 0;
1636 /* for this we just need to flip the
1637 first it then copy the rest in place */
1638 D (emitcode (";", "genUminusFloat");
1641 _startLazyDPSEvaluation ();
1642 size = AOP_SIZE (op) - 1;
1643 l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1646 emitcode ("cpl", "acc.7");
1647 aopPut (AOP (result), "a", 3);
1651 aopPut (AOP (result),
1652 aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1656 _endLazyDPSEvaluation ();
1659 /*-----------------------------------------------------------------*/
1660 /* genUminus - unary minus code generation */
1661 /*-----------------------------------------------------------------*/
1663 genUminus (iCode * ic)
1666 sym_link *optype, *rtype;
1668 D (emitcode (";", "genUminus ");
1673 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1674 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1676 /* if both in bit space then special
1678 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1679 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1682 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1683 emitcode ("cpl", "c");
1684 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1688 optype = operandType (IC_LEFT (ic));
1689 rtype = operandType (IC_RESULT (ic));
1691 /* if float then do float stuff */
1692 if (IS_FLOAT (optype))
1694 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1698 /* otherwise subtract from zero */
1699 size = AOP_SIZE (IC_LEFT (ic));
1701 _startLazyDPSEvaluation ();
1704 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1705 if (!strcmp (l, "a"))
1709 emitcode ("cpl", "a");
1710 emitcode ("addc", "a,#0");
1716 emitcode ("clr", "a");
1717 emitcode ("subb", "a,%s", l);
1719 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1721 _endLazyDPSEvaluation ();
1723 /* if any remaining bytes in the result */
1724 /* we just need to propagate the sign */
1725 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1727 emitcode ("rlc", "a");
1728 emitcode ("subb", "a,acc");
1730 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1734 /* release the aops */
1735 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1736 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1739 /*-----------------------------------------------------------------*/
1740 /* saveRegisters - will look for a call and save the registers */
1741 /*-----------------------------------------------------------------*/
1743 saveRegisters (iCode * lic)
1751 for (ic = lic; ic; ic = ic->next)
1752 if (ic->op == CALL || ic->op == PCALL)
1757 fprintf (stderr, "found parameter push with no function call\n");
1761 /* if the registers have been saved already then
1763 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1766 /* find the registers in use at this time
1767 and push them away to safety */
1768 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1772 if (options.useXstack)
1774 if (bitVectBitValue (rsave, R0_IDX))
1775 emitcode ("mov", "b,r0");
1776 emitcode ("mov", "r0,%s", spname);
1777 for (i = 0; i < ds390_nRegs; i++)
1779 if (bitVectBitValue (rsave, i))
1782 emitcode ("mov", "a,b");
1784 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1785 emitcode ("movx", "@r0,a");
1786 emitcode ("inc", "r0");
1789 emitcode ("mov", "%s,r0", spname);
1790 if (bitVectBitValue (rsave, R0_IDX))
1791 emitcode ("mov", "r0,b");
1794 for (i = 0; i < ds390_nRegs; i++)
1796 if (bitVectBitValue (rsave, i))
1797 emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1800 detype = getSpec (operandType (IC_LEFT (ic)));
1802 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1803 IS_ISR (currFunc->etype) &&
1806 saverbank (SPEC_BANK (detype), ic, TRUE);
1809 /*-----------------------------------------------------------------*/
1810 /* unsaveRegisters - pop the pushed registers */
1811 /*-----------------------------------------------------------------*/
1813 unsaveRegisters (iCode * ic)
1817 /* find the registers in use at this time
1818 and push them away to safety */
1819 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1822 if (options.useXstack)
1824 emitcode ("mov", "r0,%s", spname);
1825 for (i = ds390_nRegs; i >= 0; i--)
1827 if (bitVectBitValue (rsave, i))
1829 emitcode ("dec", "r0");
1830 emitcode ("movx", "a,@r0");
1832 emitcode ("mov", "b,a");
1834 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1838 emitcode ("mov", "%s,r0", spname);
1839 if (bitVectBitValue (rsave, R0_IDX))
1840 emitcode ("mov", "r0,b");
1843 for (i = ds390_nRegs; i >= 0; i--)
1845 if (bitVectBitValue (rsave, i))
1846 emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
1852 /*-----------------------------------------------------------------*/
1854 /*-----------------------------------------------------------------*/
1856 pushSide (operand * oper, int size)
1859 _startLazyDPSEvaluation ();
1862 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1863 if (AOP_TYPE (oper) != AOP_REG &&
1864 AOP_TYPE (oper) != AOP_DIR &&
1867 emitcode ("mov", "a,%s", l);
1868 emitcode ("push", "acc");
1871 emitcode ("push", "%s", l);
1873 _endLazyDPSEvaluation ();
1876 /*-----------------------------------------------------------------*/
1877 /* assignResultValue - */
1878 /*-----------------------------------------------------------------*/
1880 assignResultValue (operand * oper)
1883 int size = AOP_SIZE (oper);
1885 _startLazyDPSEvaluation ();
1888 aopPut (AOP (oper), fReturn[offset], offset);
1891 _endLazyDPSEvaluation ();
1895 /*-----------------------------------------------------------------*/
1896 /* genXpush - pushes onto the external stack */
1897 /*-----------------------------------------------------------------*/
1899 genXpush (iCode * ic)
1901 asmop *aop = newAsmop (0);
1903 int size, offset = 0;
1905 D (emitcode (";", "genXpush ");
1908 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1909 r = getFreePtr (ic, &aop, FALSE);
1912 emitcode ("mov", "%s,_spx", r->name);
1914 size = AOP_SIZE (IC_LEFT (ic));
1915 _startLazyDPSEvaluation ();
1919 char *l = aopGet (AOP (IC_LEFT (ic)),
1920 offset++, FALSE, FALSE, TRUE);
1922 emitcode ("movx", "@%s,a", r->name);
1923 emitcode ("inc", "%s", r->name);
1926 _endLazyDPSEvaluation ();
1929 emitcode ("mov", "_spx,%s", r->name);
1931 freeAsmop (NULL, aop, ic, TRUE);
1932 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1935 /*-----------------------------------------------------------------*/
1936 /* genIpush - genrate code for pushing this gets a little complex */
1937 /*-----------------------------------------------------------------*/
1939 genIpush (iCode * ic)
1941 int size, offset = 0;
1944 D (emitcode (";", "genIpush ");
1947 /* if this is not a parm push : ie. it is spill push
1948 and spill push is always done on the local stack */
1952 /* and the item is spilt then do nothing */
1953 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1956 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1957 size = AOP_SIZE (IC_LEFT (ic));
1958 /* push it on the stack */
1959 _startLazyDPSEvaluation ();
1962 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1968 emitcode ("push", "%s ;jwk genIpush: !parm", l);
1970 _endLazyDPSEvaluation ();
1974 /* this is a paramter push: in this case we call
1975 the routine to find the call and save those
1976 registers that need to be saved */
1979 /* if use external stack then call the external
1980 stack pushing routine */
1981 if (options.useXstack)
1987 /* then do the push */
1988 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1990 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1991 size = AOP_SIZE (IC_LEFT (ic));
1993 _startLazyDPSEvaluation ();
1996 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
1997 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1998 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2001 emitcode ("mov", "a,%s", l);
2002 emitcode ("push", "acc");
2005 emitcode ("push", "%s ;jwk genIpush", l);
2007 _endLazyDPSEvaluation ();
2009 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genIpop - recover the registers: can happen only for spilling */
2014 /*-----------------------------------------------------------------*/
2016 genIpop (iCode * ic)
2020 D (emitcode (";", "genIpop ");
2024 /* if the temp was not pushed then */
2025 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2028 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2029 size = AOP_SIZE (IC_LEFT (ic));
2030 offset = (size - 1);
2031 _startLazyDPSEvaluation ();
2034 emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
2035 FALSE, TRUE, TRUE));
2037 _endLazyDPSEvaluation ();
2039 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2042 /*-----------------------------------------------------------------*/
2043 /* unsaverbank - restores the resgister bank from stack */
2044 /*-----------------------------------------------------------------*/
2046 unsaverbank (int bank, iCode * ic, bool popPsw)
2054 if (options.useXstack)
2057 r = getFreePtr (ic, &aop, FALSE);
2060 emitcode ("mov", "%s,_spx", r->name);
2061 emitcode ("movx", "a,@%s", r->name);
2062 emitcode ("mov", "psw,a");
2063 emitcode ("dec", "%s", r->name);
2067 emitcode ("pop", "psw");
2070 for (i = (ds390_nRegs - 1); i >= 0; i--)
2072 if (options.useXstack)
2074 emitcode ("movx", "a,@%s", r->name);
2075 emitcode ("mov", "(%s+%d),a",
2076 regs390[i].base, 8 * bank + regs390[i].offset);
2077 emitcode ("dec", "%s", r->name);
2081 emitcode ("pop", "(%s+%d)",
2082 regs390[i].base, 8 * bank + regs390[i].offset);
2085 if (options.useXstack)
2088 emitcode ("mov", "_spx,%s", r->name);
2089 freeAsmop (NULL, aop, ic, TRUE);
2094 /*-----------------------------------------------------------------*/
2095 /* saverbank - saves an entire register bank on the stack */
2096 /*-----------------------------------------------------------------*/
2098 saverbank (int bank, iCode * ic, bool pushPsw)
2104 if (options.useXstack)
2108 r = getFreePtr (ic, &aop, FALSE);
2109 emitcode ("mov", "%s,_spx", r->name);
2113 for (i = 0; i < ds390_nRegs; i++)
2115 if (options.useXstack)
2117 emitcode ("inc", "%s", r->name);
2118 emitcode ("mov", "a,(%s+%d)",
2119 regs390[i].base, 8 * bank + regs390[i].offset);
2120 emitcode ("movx", "@%s,a", r->name);
2123 emitcode ("push", "(%s+%d)",
2124 regs390[i].base, 8 * bank + regs390[i].offset);
2129 if (options.useXstack)
2131 emitcode ("mov", "a,psw");
2132 emitcode ("movx", "@%s,a", r->name);
2133 emitcode ("inc", "%s", r->name);
2134 emitcode ("mov", "_spx,%s", r->name);
2135 freeAsmop (NULL, aop, ic, TRUE);
2139 emitcode ("push", "psw");
2141 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2147 /*-----------------------------------------------------------------*/
2148 /* genCall - generates a call statement */
2149 /*-----------------------------------------------------------------*/
2151 genCall (iCode * ic)
2155 D (emitcode (";", "genCall ");
2158 /* if caller saves & we have not saved then */
2162 /* if we are calling a function that is not using
2163 the same register bank then we need to save the
2164 destination registers on the stack */
2165 detype = getSpec (operandType (IC_LEFT (ic)));
2167 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2168 IS_ISR (currFunc->etype) &&
2171 saverbank (SPEC_BANK (detype), ic, TRUE);
2173 /* if send set is not empty the assign */
2178 for (sic = setFirstItem (_G.sendSet); sic;
2179 sic = setNextItem (_G.sendSet))
2181 int size, offset = 0;
2183 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2184 size = AOP_SIZE (IC_LEFT (sic));
2186 _startLazyDPSEvaluation ();
2189 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2190 FALSE, FALSE, TRUE);
2191 if (strcmp (l, fReturn[offset])) {
2194 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2200 _endLazyDPSEvaluation ();
2201 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2206 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2207 OP_SYMBOL (IC_LEFT (ic))->rname :
2208 OP_SYMBOL (IC_LEFT (ic))->name));
2210 /* if we need assign a result value */
2211 if ((IS_ITEMP (IC_RESULT (ic)) &&
2212 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2213 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2214 IS_TRUE_SYMOP (IC_RESULT (ic)))
2216 if (isOperandInFarSpace (IC_RESULT (ic))
2217 && getSize (operandType (IC_RESULT (ic))) <= 2)
2219 int size = getSize (operandType (IC_RESULT (ic)));
2221 /* Special case for 1 or 2 byte return in far space. */
2222 emitcode (";", "Kevin function call abuse #1");
2227 emitcode ("mov", "b,%s", fReturn[1]);
2230 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2231 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2235 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2237 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2242 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2245 assignResultValue (IC_RESULT (ic));
2247 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2251 /* adjust the stack for parameters if
2256 if (ic->parmBytes > 3)
2258 emitcode ("mov", "a,%s", spname);
2259 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2260 emitcode ("mov", "%s,a", spname);
2263 for (i = 0; i < ic->parmBytes; i++)
2264 emitcode ("dec", "%s", spname);
2268 /* if register bank was saved then pop them */
2270 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2272 /* if we hade saved some registers then unsave them */
2273 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2274 unsaveRegisters (ic);
2279 /*-----------------------------------------------------------------*/
2280 /* genPcall - generates a call by pointer statement */
2281 /*-----------------------------------------------------------------*/
2283 genPcall (iCode * ic)
2286 symbol *rlbl = newiTempLabel (NULL);
2288 D (emitcode (";", "genPcall ");
2292 /* if caller saves & we have not saved then */
2296 /* if we are calling a function that is not using
2297 the same register bank then we need to save the
2298 destination registers on the stack */
2299 detype = getSpec (operandType (IC_LEFT (ic)));
2301 IS_ISR (currFunc->etype) &&
2302 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2303 saverbank (SPEC_BANK (detype), ic, TRUE);
2306 /* push the return address on to the stack */
2307 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2308 emitcode ("push", "acc");
2309 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2310 emitcode ("push", "acc");
2312 if (options.model == MODEL_FLAT24)
2314 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2315 emitcode ("push", "acc");
2318 /* now push the calling address */
2319 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2321 pushSide (IC_LEFT (ic), FPTRSIZE);
2323 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2325 /* if send set is not empty the assign */
2330 for (sic = setFirstItem (_G.sendSet); sic;
2331 sic = setNextItem (_G.sendSet))
2333 int size, offset = 0;
2335 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2336 size = AOP_SIZE (IC_LEFT (sic));
2337 _startLazyDPSEvaluation ();
2340 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2341 FALSE, FALSE, TRUE);
2342 if (strcmp (l, fReturn[offset]))
2344 emitcode ("mov", "%s,%s",
2350 _endLazyDPSEvaluation ();
2351 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2356 emitcode ("ret", "");
2357 emitcode ("", "%05d$:", (rlbl->key + 100));
2360 /* if we need assign a result value */
2361 if ((IS_ITEMP (IC_RESULT (ic)) &&
2362 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2363 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2364 IS_TRUE_SYMOP (IC_RESULT (ic)))
2368 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2371 assignResultValue (IC_RESULT (ic));
2373 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2376 /* adjust the stack for parameters if
2381 if (ic->parmBytes > 3)
2383 emitcode ("mov", "a,%s", spname);
2384 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2385 emitcode ("mov", "%s,a", spname);
2388 for (i = 0; i < ic->parmBytes; i++)
2389 emitcode ("dec", "%s", spname);
2393 /* if register bank was saved then unsave them */
2395 (SPEC_BANK (currFunc->etype) !=
2396 SPEC_BANK (detype)))
2397 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2399 /* if we hade saved some registers then
2402 unsaveRegisters (ic);
2406 /*-----------------------------------------------------------------*/
2407 /* resultRemat - result is rematerializable */
2408 /*-----------------------------------------------------------------*/
2410 resultRemat (iCode * ic)
2412 if (SKIP_IC (ic) || ic->op == IFX)
2415 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2417 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2418 if (sym->remat && !POINTER_SET (ic))
2425 #if defined(__BORLANDC__) || defined(_MSC_VER)
2426 #define STRCASECMP stricmp
2428 #define STRCASECMP strcasecmp
2431 /*-----------------------------------------------------------------*/
2432 /* inExcludeList - return 1 if the string is in exclude Reg list */
2433 /*-----------------------------------------------------------------*/
2435 inExcludeList (char *s)
2439 if (options.excludeRegs[i] &&
2440 STRCASECMP (options.excludeRegs[i], "none") == 0)
2443 for (i = 0; options.excludeRegs[i]; i++)
2445 if (options.excludeRegs[i] &&
2446 STRCASECMP (s, options.excludeRegs[i]) == 0)
2452 /*-----------------------------------------------------------------*/
2453 /* genFunction - generated code for function entry */
2454 /*-----------------------------------------------------------------*/
2456 genFunction (iCode * ic)
2461 D (emitcode (";", "genFunction ");
2465 /* create the function header */
2466 emitcode (";", "-----------------------------------------");
2467 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2468 emitcode (";", "-----------------------------------------");
2470 emitcode ("", "%s:", sym->rname);
2471 fetype = getSpec (operandType (IC_LEFT (ic)));
2473 /* if critical function then turn interrupts off */
2474 if (SPEC_CRTCL (fetype))
2475 emitcode ("clr", "ea");
2477 /* here we need to generate the equates for the
2478 register bank if required */
2479 if (SPEC_BANK (fetype) != rbank)
2483 rbank = SPEC_BANK (fetype);
2484 for (i = 0; i < ds390_nRegs; i++)
2486 if (strcmp (regs390[i].base, "0") == 0)
2487 emitcode ("", "%s = 0x%02x",
2489 8 * rbank + regs390[i].offset);
2491 emitcode ("", "%s = %s + 0x%02x",
2494 8 * rbank + regs390[i].offset);
2498 /* if this is an interrupt service routine then
2499 save acc, b, dpl, dph */
2500 if (IS_ISR (sym->etype))
2503 if (!inExcludeList ("acc"))
2504 emitcode ("push", "acc");
2505 if (!inExcludeList ("b"))
2506 emitcode ("push", "b");
2507 if (!inExcludeList ("dpl"))
2508 emitcode ("push", "dpl");
2509 if (!inExcludeList ("dph"))
2510 emitcode ("push", "dph");
2511 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2513 emitcode ("push", "dpx");
2514 /* Make sure we're using standard DPTR */
2515 emitcode ("push", "dps");
2516 emitcode ("mov", "dps, #0x00");
2517 if (options.stack10bit)
2519 /* This ISR could conceivably use DPTR2. Better save it. */
2520 emitcode ("push", "dpl1");
2521 emitcode ("push", "dph1");
2522 emitcode ("push", "dpx1");
2523 emitcode ("push", DP2_RESULT_REG);
2526 /* if this isr has no bank i.e. is going to
2527 run with bank 0 , then we need to save more
2529 if (!SPEC_BANK (sym->etype))
2532 /* if this function does not call any other
2533 function then we can be economical and
2534 save only those registers that are used */
2539 /* if any registers used */
2542 /* save the registers used */
2543 for (i = 0; i < sym->regsUsed->size; i++)
2545 if (bitVectBitValue (sym->regsUsed, i) ||
2546 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2547 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2554 /* this function has a function call cannot
2555 determines register usage so we will have the
2557 saverbank (0, ic, FALSE);
2563 /* if callee-save to be used for this function
2564 then save the registers being used in this function */
2565 if (sym->calleeSave)
2569 /* if any registers used */
2572 /* save the registers used */
2573 for (i = 0; i < sym->regsUsed->size; i++)
2575 if (bitVectBitValue (sym->regsUsed, i) ||
2576 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2578 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2586 /* set the register bank to the desired value */
2587 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2589 emitcode ("push", "psw");
2590 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2593 if (IS_RENT (sym->etype) || options.stackAuto)
2596 if (options.useXstack)
2598 emitcode ("mov", "r0,%s", spname);
2599 emitcode ("mov", "a,_bp");
2600 emitcode ("movx", "@r0,a");
2601 emitcode ("inc", "%s", spname);
2605 /* set up the stack */
2606 emitcode ("push", "_bp"); /* save the callers stack */
2608 emitcode ("mov", "_bp,%s", spname);
2611 /* adjust the stack for the function */
2617 werror (W_STACK_OVERFLOW, sym->name);
2619 if (i > 3 && sym->recvSize < 4)
2622 emitcode ("mov", "a,sp");
2623 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2624 emitcode ("mov", "sp,a");
2629 emitcode ("inc", "sp");
2635 emitcode ("mov", "a,_spx");
2636 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2637 emitcode ("mov", "_spx,a");
2642 /*-----------------------------------------------------------------*/
2643 /* genEndFunction - generates epilogue for functions */
2644 /*-----------------------------------------------------------------*/
2646 genEndFunction (iCode * ic)
2648 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2650 D (emitcode (";", "genEndFunction ");
2653 if (IS_RENT (sym->etype) || options.stackAuto)
2655 emitcode ("mov", "%s,_bp", spname);
2658 /* if use external stack but some variables were
2659 added to the local stack then decrement the
2661 if (options.useXstack && sym->stack)
2663 emitcode ("mov", "a,sp");
2664 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2665 emitcode ("mov", "sp,a");
2669 if ((IS_RENT (sym->etype) || options.stackAuto))
2671 if (options.useXstack)
2673 emitcode ("mov", "r0,%s", spname);
2674 emitcode ("movx", "a,@r0");
2675 emitcode ("mov", "_bp,a");
2676 emitcode ("dec", "%s", spname);
2680 emitcode ("pop", "_bp");
2684 /* restore the register bank */
2685 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2686 emitcode ("pop", "psw");
2688 if (IS_ISR (sym->etype))
2691 /* now we need to restore the registers */
2692 /* if this isr has no bank i.e. is going to
2693 run with bank 0 , then we need to save more
2695 if (!SPEC_BANK (sym->etype))
2698 /* if this function does not call any other
2699 function then we can be economical and
2700 save only those registers that are used */
2705 /* if any registers used */
2708 /* save the registers used */
2709 for (i = sym->regsUsed->size; i >= 0; i--)
2711 if (bitVectBitValue (sym->regsUsed, i) ||
2712 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2713 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2720 /* this function has a function call cannot
2721 determines register usage so we will have the
2723 unsaverbank (0, ic, FALSE);
2727 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2729 if (options.stack10bit)
2731 emitcode ("pop", DP2_RESULT_REG);
2732 emitcode ("pop", "dpx1");
2733 emitcode ("pop", "dph1");
2734 emitcode ("pop", "dpl1");
2736 emitcode ("pop", "dps");
2737 emitcode ("pop", "dpx");
2739 if (!inExcludeList ("dph"))
2740 emitcode ("pop", "dph");
2741 if (!inExcludeList ("dpl"))
2742 emitcode ("pop", "dpl");
2743 if (!inExcludeList ("b"))
2744 emitcode ("pop", "b");
2745 if (!inExcludeList ("acc"))
2746 emitcode ("pop", "acc");
2748 if (SPEC_CRTCL (sym->etype))
2749 emitcode ("setb", "ea");
2751 /* if debug then send end of function */
2752 /* if (options.debug && currFunc) { */
2756 emitcode ("", "C$%s$%d$%d$%d ==.",
2757 FileBaseName (ic->filename), currFunc->lastLine,
2758 ic->level, ic->block);
2759 if (IS_STATIC (currFunc->etype))
2760 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2762 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2766 emitcode ("reti", "");
2770 if (SPEC_CRTCL (sym->etype))
2771 emitcode ("setb", "ea");
2773 if (sym->calleeSave)
2777 /* if any registers used */
2780 /* save the registers used */
2781 for (i = sym->regsUsed->size; i >= 0; i--)
2783 if (bitVectBitValue (sym->regsUsed, i) ||
2784 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2785 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2791 /* if debug then send end of function */
2795 emitcode ("", "C$%s$%d$%d$%d ==.",
2796 FileBaseName (ic->filename), currFunc->lastLine,
2797 ic->level, ic->block);
2798 if (IS_STATIC (currFunc->etype))
2799 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2801 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2805 emitcode ("ret", "");
2810 /*-----------------------------------------------------------------*/
2811 /* genRet - generate code for return statement */
2812 /*-----------------------------------------------------------------*/
2816 int size, offset = 0, pushed = 0;
2818 D (emitcode (";", "genRet ");
2821 /* if we have no return value then
2822 just generate the "ret" */
2826 /* we have something to return then
2827 move the return value into place */
2828 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2829 size = AOP_SIZE (IC_LEFT (ic));
2831 _startLazyDPSEvaluation ();
2835 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2837 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2838 FALSE, TRUE, FALSE);
2839 emitcode ("push", "%s", l);
2844 l = aopGet (AOP (IC_LEFT (ic)), offset,
2845 FALSE, FALSE, FALSE);
2846 if (strcmp (fReturn[offset], l))
2847 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2850 _endLazyDPSEvaluation ();
2857 if (strcmp (fReturn[pushed], "a"))
2858 emitcode ("pop", fReturn[pushed]);
2860 emitcode ("pop", "acc");
2863 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2866 /* generate a jump to the return label
2867 if the next is not the return statement */
2868 if (!(ic->next && ic->next->op == LABEL &&
2869 IC_LABEL (ic->next) == returnLabel))
2871 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2875 /*-----------------------------------------------------------------*/
2876 /* genLabel - generates a label */
2877 /*-----------------------------------------------------------------*/
2879 genLabel (iCode * ic)
2881 /* special case never generate */
2882 if (IC_LABEL (ic) == entryLabel)
2885 D (emitcode (";", "genLabel ");
2888 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2891 /*-----------------------------------------------------------------*/
2892 /* genGoto - generates a ljmp */
2893 /*-----------------------------------------------------------------*/
2895 genGoto (iCode * ic)
2897 D (emitcode (";", "genGoto ");
2899 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2902 /*-----------------------------------------------------------------*/
2903 /* findLabelBackwards: walks back through the iCode chain looking */
2904 /* for the given label. Returns number of iCode instructions */
2905 /* between that label and given ic. */
2906 /* Returns zero if label not found. */
2907 /*-----------------------------------------------------------------*/
2909 findLabelBackwards (iCode * ic, int key)
2918 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2920 /* printf("findLabelBackwards = %d\n", count); */
2928 /*-----------------------------------------------------------------*/
2929 /* genPlusIncr :- does addition with increment if possible */
2930 /*-----------------------------------------------------------------*/
2932 genPlusIncr (iCode * ic)
2934 unsigned int icount;
2935 unsigned int size = getDataSize (IC_RESULT (ic));
2937 /* will try to generate an increment */
2938 /* if the right side is not a literal
2940 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2943 /* if the literal value of the right hand side
2944 is greater than 4 then it is not worth it */
2945 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2948 /* if increment 16 bits in register */
2950 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2951 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2952 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2960 /* If the next instruction is a goto and the goto target
2961 * is <= 5 instructions previous to this, we can generate
2962 * jumps straight to that target.
2964 if (ic->next && ic->next->op == GOTO
2965 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2968 emitcode (";", "tail increment optimized (range %d)", labelRange);
2969 tlbl = IC_LABEL (ic->next);
2974 tlbl = newiTempLabel (NULL);
2977 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2978 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2979 IS_AOP_PREG (IC_RESULT (ic)))
2980 emitcode ("cjne", "%s,#0x00,%05d$"
2981 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2985 emitcode ("clr", "a");
2986 emitcode ("cjne", "a,%s,%05d$"
2987 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2991 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2994 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2995 IS_AOP_PREG (IC_RESULT (ic)))
2996 emitcode ("cjne", "%s,#0x00,%05d$"
2997 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3000 emitcode ("cjne", "a,%s,%05d$"
3001 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3004 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3008 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3009 IS_AOP_PREG (IC_RESULT (ic)))
3010 emitcode ("cjne", "%s,#0x00,%05d$"
3011 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3015 emitcode ("cjne", "a,%s,%05d$"
3016 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3019 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3024 emitcode ("", "%05d$:", tlbl->key + 100);
3029 /* if the sizes are greater than 1 then we cannot */
3030 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3031 AOP_SIZE (IC_LEFT (ic)) > 1)
3034 /* we can if the aops of the left & result match or
3035 if they are in registers and the registers are the
3038 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3039 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3040 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3045 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3046 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3047 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3052 _startLazyDPSEvaluation ();
3055 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3057 _endLazyDPSEvaluation ();
3066 /*-----------------------------------------------------------------*/
3067 /* outBitAcc - output a bit in acc */
3068 /*-----------------------------------------------------------------*/
3070 outBitAcc (operand * result)
3072 symbol *tlbl = newiTempLabel (NULL);
3073 /* if the result is a bit */
3074 if (AOP_TYPE (result) == AOP_CRY)
3076 aopPut (AOP (result), "a", 0);
3080 emitcode ("jz", "%05d$", tlbl->key + 100);
3081 emitcode ("mov", "a,%s", one);
3082 emitcode ("", "%05d$:", tlbl->key + 100);
3087 /*-----------------------------------------------------------------*/
3088 /* genPlusBits - generates code for addition of two bits */
3089 /*-----------------------------------------------------------------*/
3091 genPlusBits (iCode * ic)
3093 D (emitcode (";", "genPlusBits ");
3095 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3097 symbol *lbl = newiTempLabel (NULL);
3098 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3099 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3100 emitcode ("cpl", "c");
3101 emitcode ("", "%05d$:", (lbl->key + 100));
3102 outBitC (IC_RESULT (ic));
3106 emitcode ("clr", "a");
3107 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3108 emitcode ("rlc", "a");
3109 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3110 emitcode ("addc", "a,#0x00");
3111 outAcc (IC_RESULT (ic));
3116 adjustArithmeticResult (iCode * ic)
3118 if (opIsGptr (IC_RESULT (ic)) &&
3119 opIsGptr (IC_LEFT (ic)) &&
3120 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3122 aopPut (AOP (IC_RESULT (ic)),
3123 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3127 if (opIsGptr (IC_RESULT (ic)) &&
3128 opIsGptr (IC_RIGHT (ic)) &&
3129 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3131 aopPut (AOP (IC_RESULT (ic)),
3132 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3136 if (opIsGptr (IC_RESULT (ic)) &&
3137 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3138 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3139 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3140 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3143 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3144 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3148 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3149 // (because all three operands are in far space).
3150 #define AOP_OP_3(ic) \
3151 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3152 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3153 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3154 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3155 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3156 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3158 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3160 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3163 // Macro to aopOp all three operands of an ic. If this cannot be done,
3164 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3165 // will be set TRUE. The caller must then handle the case specially, noting
3166 // that the IC_RESULT operand is not aopOp'd.
3167 #define AOP_OP_3_NOFATAL(ic, rc) \
3168 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3169 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3170 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3171 isOperandInFarSpace(IC_RESULT(ic))) \
3173 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3178 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3179 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3181 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3182 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3184 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3186 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3190 // aopOp the left & right operands of an ic.
3191 #define AOP_OP_2(ic) \
3192 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3193 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3195 // convienience macro.
3196 #define AOP_SET_LOCALS(ic) \
3197 left = IC_LEFT(ic); \
3198 right = IC_RIGHT(ic); \
3199 result = IC_RESULT(ic);
3202 // Given an integer value of pushedSize bytes on the stack,
3203 // adjust it to be resultSize bytes, either by discarding
3204 // the most significant bytes or by zero-padding.
3206 // On exit from this macro, pushedSize will have been adjusted to
3207 // equal resultSize, and ACC may be trashed.
3208 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3209 /* If the pushed data is bigger than the result, \
3210 * simply discard unused bytes. Icky, but works. \
3212 while (pushedSize > resultSize) \
3214 D (emitcode (";", "discarding unused result byte."););\
3215 emitcode ("pop", "acc"); \
3218 if (pushedSize < resultSize) \
3220 emitcode ("clr", "a"); \
3221 /* Conversly, we haven't pushed enough here. \
3222 * just zero-pad, and all is well. \
3224 while (pushedSize < resultSize) \
3226 emitcode("push", "acc"); \
3230 assert(pushedSize == resultSize);
3232 /*-----------------------------------------------------------------*/
3233 /* genPlus - generates code for addition */
3234 /*-----------------------------------------------------------------*/
3236 genPlus (iCode * ic)
3238 int size, offset = 0;
3239 bool pushResult = FALSE;
3242 D (emitcode (";", "genPlus "););
3244 /* special cases :- */
3246 AOP_OP_3_NOFATAL (ic, pushResult);
3249 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3254 /* if literal, literal on the right or
3255 if left requires ACC or right is already
3257 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3258 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3259 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3261 operand *t = IC_RIGHT (ic);
3262 IC_RIGHT (ic) = IC_LEFT (ic);
3264 emitcode (";", "Swapped plus args.");
3267 /* if both left & right are in bit
3269 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3270 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3276 /* if left in bit space & right literal */
3277 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3278 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3280 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3281 /* if result in bit space */
3282 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3284 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3285 emitcode ("cpl", "c");
3286 outBitC (IC_RESULT (ic));
3290 size = getDataSize (IC_RESULT (ic));
3291 _startLazyDPSEvaluation ();
3294 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3295 emitcode ("addc", "a,#00");
3296 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3298 _endLazyDPSEvaluation ();
3303 /* if I can do an increment instead
3304 of add then GOOD for ME */
3305 if (genPlusIncr (ic) == TRUE)
3307 emitcode (";", "did genPlusIncr");
3312 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3314 _startLazyDPSEvaluation ();
3317 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3319 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3321 emitcode ("add", "a,%s",
3322 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3324 emitcode ("addc", "a,%s",
3325 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3329 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3331 emitcode ("add", "a,%s",
3332 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3334 emitcode ("addc", "a,%s",
3335 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3339 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3343 emitcode ("push", "acc");
3347 _endLazyDPSEvaluation ();
3351 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3353 size = getDataSize (IC_LEFT (ic));
3354 rSize = getDataSize (IC_RESULT (ic));
3356 ADJUST_PUSHED_RESULT(size, rSize);
3358 _startLazyDPSEvaluation ();
3361 emitcode ("pop", "acc");
3362 aopPut (AOP (IC_RESULT (ic)), "a", size);
3364 _endLazyDPSEvaluation ();
3367 adjustArithmeticResult (ic);
3370 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3371 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3372 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3375 /*-----------------------------------------------------------------*/
3376 /* genMinusDec :- does subtraction with deccrement if possible */
3377 /*-----------------------------------------------------------------*/
3379 genMinusDec (iCode * ic)
3381 unsigned int icount;
3382 unsigned int size = getDataSize (IC_RESULT (ic));
3384 /* will try to generate an increment */
3385 /* if the right side is not a literal
3387 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3390 /* if the literal value of the right hand side
3391 is greater than 4 then it is not worth it */
3392 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3395 /* if decrement 16 bits in register */
3396 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3397 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3398 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3406 /* If the next instruction is a goto and the goto target
3407 * is <= 5 instructions previous to this, we can generate
3408 * jumps straight to that target.
3410 if (ic->next && ic->next->op == GOTO
3411 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3414 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3415 tlbl = IC_LABEL (ic->next);
3420 tlbl = newiTempLabel (NULL);
3424 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3425 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3426 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3427 IS_AOP_PREG (IC_RESULT (ic)))
3428 emitcode ("cjne", "%s,#0xff,%05d$"
3429 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3433 emitcode ("mov", "a,#0xff");
3434 emitcode ("cjne", "a,%s,%05d$"
3435 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3438 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3441 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3442 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3443 IS_AOP_PREG (IC_RESULT (ic)))
3444 emitcode ("cjne", "%s,#0xff,%05d$"
3445 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3449 emitcode ("cjne", "a,%s,%05d$"
3450 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3453 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3457 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3458 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3459 IS_AOP_PREG (IC_RESULT (ic)))
3460 emitcode ("cjne", "%s,#0xff,%05d$"
3461 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3465 emitcode ("cjne", "a,%s,%05d$"
3466 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3469 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3473 emitcode ("", "%05d$:", tlbl->key + 100);
3478 /* if the sizes are greater than 1 then we cannot */
3479 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3480 AOP_SIZE (IC_LEFT (ic)) > 1)
3483 /* we can if the aops of the left & result match or
3484 if they are in registers and the registers are the
3487 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3488 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3489 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3492 _startLazyDPSEvaluation ();
3495 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3497 _endLazyDPSEvaluation ();
3505 /*-----------------------------------------------------------------*/
3506 /* addSign - complete with sign */
3507 /*-----------------------------------------------------------------*/
3509 addSign (operand * result, int offset, int sign)
3511 int size = (getDataSize (result) - offset);
3514 _startLazyDPSEvaluation();
3517 emitcode ("rlc", "a");
3518 emitcode ("subb", "a,acc");
3521 aopPut (AOP (result), "a", offset++);
3528 aopPut (AOP (result), zero, offset++);
3531 _endLazyDPSEvaluation();
3535 /*-----------------------------------------------------------------*/
3536 /* genMinusBits - generates code for subtraction of two bits */
3537 /*-----------------------------------------------------------------*/
3539 genMinusBits (iCode * ic)
3541 symbol *lbl = newiTempLabel (NULL);
3543 D (emitcode (";", "genMinusBits "););
3545 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3547 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3548 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3549 emitcode ("cpl", "c");
3550 emitcode ("", "%05d$:", (lbl->key + 100));
3551 outBitC (IC_RESULT (ic));
3555 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3556 emitcode ("subb", "a,acc");
3557 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3558 emitcode ("inc", "a");
3559 emitcode ("", "%05d$:", (lbl->key + 100));
3560 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3561 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3565 /*-----------------------------------------------------------------*/
3566 /* genMinus - generates code for subtraction */
3567 /*-----------------------------------------------------------------*/
3569 genMinus (iCode * ic)
3571 int size, offset = 0;
3573 unsigned long lit = 0L;
3574 bool pushResult = FALSE;
3576 D (emitcode (";", "genMinus "););
3578 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3579 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3580 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3581 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3587 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3589 /* special cases :- */
3590 /* if both left & right are in bit space */
3591 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3592 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3598 /* if I can do an decrement instead
3599 of subtract then GOOD for ME */
3600 if (genMinusDec (ic) == TRUE)
3605 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3607 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3613 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3618 /* if literal, add a,#-lit, else normal subb */
3619 _startLazyDPSEvaluation ();
3622 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3623 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3624 emitcode ("subb", "a,%s",
3625 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3628 /* first add without previous c */
3630 emitcode ("add", "a,#0x%02x",
3631 (unsigned int) (lit & 0x0FFL));
3633 emitcode ("addc", "a,#0x%02x",
3634 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3639 emitcode ("push", "acc");
3643 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3647 _endLazyDPSEvaluation ();
3651 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3653 size = getDataSize (IC_LEFT (ic));
3654 rSize = getDataSize (IC_RESULT (ic));
3656 ADJUST_PUSHED_RESULT(size, rSize);
3658 _startLazyDPSEvaluation ();
3661 emitcode ("pop", "acc");
3662 aopPut (AOP (IC_RESULT (ic)), "a", size);
3664 _endLazyDPSEvaluation ();
3667 adjustArithmeticResult (ic);
3670 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3671 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3672 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3676 /*-----------------------------------------------------------------*/
3677 /* genMultbits :- multiplication of bits */
3678 /*-----------------------------------------------------------------*/
3680 genMultbits (operand * left,
3684 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3685 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3690 /*-----------------------------------------------------------------*/
3691 /* genMultOneByte : 8*8=8/16 bit multiplication */
3692 /*-----------------------------------------------------------------*/
3694 genMultOneByte (operand * left,
3698 sym_link *opetype = operandType (result);
3700 int size=AOP_SIZE(result);
3702 emitcode (";",__FUNCTION__);
3703 if (size<1 || size>2) {
3704 // this should never happen
3705 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3706 AOP_SIZE(result), __FUNCTION__, lineno);
3710 /* (if two literals: the value is computed before) */
3711 /* if one literal, literal on the right */
3712 if (AOP_TYPE (left) == AOP_LIT)
3717 emitcode (";", "swapped left and right");
3720 if (SPEC_USIGN(opetype)
3721 // ignore the sign of left and right, what else can we do?
3722 || (SPEC_USIGN(operandType(left)) &&
3723 SPEC_USIGN(operandType(right)))) {
3724 // just an unsigned 8*8=8/16 multiply
3725 //emitcode (";","unsigned");
3726 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3727 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3728 emitcode ("mul", "ab");
3729 aopPut (AOP (result), "a", 0);
3731 aopPut (AOP (result), "b", 1);
3736 // we have to do a signed multiply
3738 emitcode (";", "signed");
3739 emitcode ("clr", "F0"); // reset sign flag
3740 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3741 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3743 lbl=newiTempLabel(NULL);
3744 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3745 // left side is negative, 8-bit two's complement, this fails for -128
3746 emitcode ("setb", "F0"); // set sign flag
3747 emitcode ("cpl", "a");
3748 emitcode ("inc", "a");
3750 emitcode ("", "%05d$:", lbl->key+100);
3751 emitcode ("xch", "a,b");
3754 if (AOP_TYPE(right)==AOP_LIT) {
3755 /* AND literal negative */
3756 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3757 // two's complement for literal<0
3758 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3759 emitcode ("cpl", "a");
3760 emitcode ("inc", "a");
3763 lbl=newiTempLabel(NULL);
3764 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3765 // right side is negative, 8-bit two's complement
3766 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3767 emitcode ("cpl", "a");
3768 emitcode ("inc", "a");
3769 emitcode ("", "%05d$:", lbl->key+100);
3771 emitcode ("mul", "ab");
3773 lbl=newiTempLabel(NULL);
3774 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3775 // only ONE op was negative, we have to do a 8/16-bit two's complement
3776 emitcode ("cpl", "a"); // lsb
3778 emitcode ("inc", "a");
3780 emitcode ("add", "a,#1");
3781 emitcode ("xch", "a,b");
3782 emitcode ("cpl", "a"); // msb
3783 emitcode ("addc", "a,#0");
3784 emitcode ("xch", "a,b");
3787 emitcode ("", "%05d$:", lbl->key+100);
3788 aopPut (AOP (result), "a", 0);
3790 aopPut (AOP (result), "b", 1);
3794 /*-----------------------------------------------------------------*/
3795 /* genMult - generates code for multiplication */
3796 /*-----------------------------------------------------------------*/
3798 genMult (iCode * ic)
3800 operand *left = IC_LEFT (ic);
3801 operand *right = IC_RIGHT (ic);
3802 operand *result = IC_RESULT (ic);
3804 D (emitcode (";", "genMult "););
3806 /* assign the amsops */
3809 /* special cases first */
3811 if (AOP_TYPE (left) == AOP_CRY &&
3812 AOP_TYPE (right) == AOP_CRY)
3814 genMultbits (left, right, result);
3818 /* if both are of size == 1 */
3819 if (AOP_SIZE (left) == 1 &&
3820 AOP_SIZE (right) == 1)
3822 genMultOneByte (left, right, result);
3826 /* should have been converted to function call */
3830 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3831 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3832 freeAsmop (result, NULL, ic, TRUE);
3835 /*-----------------------------------------------------------------*/
3836 /* genDivbits :- division of bits */
3837 /*-----------------------------------------------------------------*/
3839 genDivbits (operand * left,
3846 /* the result must be bit */
3847 LOAD_AB_FOR_DIV (left, right, l);
3848 emitcode ("div", "ab");
3849 emitcode ("rrc", "a");
3850 aopPut (AOP (result), "c", 0);
3853 /*-----------------------------------------------------------------*/
3854 /* genDivOneByte : 8 bit division */
3855 /*-----------------------------------------------------------------*/
3857 genDivOneByte (operand * left,
3861 sym_link *opetype = operandType (result);
3866 size = AOP_SIZE (result) - 1;
3868 /* signed or unsigned */
3869 if (SPEC_USIGN (opetype))
3871 /* unsigned is easy */
3872 LOAD_AB_FOR_DIV (left, right, l);
3873 emitcode ("div", "ab");
3874 aopPut (AOP (result), "a", 0);
3876 aopPut (AOP (result), zero, offset++);
3880 /* signed is a little bit more difficult */
3882 /* save the signs of the operands */
3883 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3885 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3886 emitcode ("push", "acc"); /* save it on the stack */
3888 /* now sign adjust for both left & right */
3889 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3891 lbl = newiTempLabel (NULL);
3892 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3893 emitcode ("cpl", "a");
3894 emitcode ("inc", "a");
3895 emitcode ("", "%05d$:", (lbl->key + 100));
3896 emitcode ("mov", "b,a");
3898 /* sign adjust left side */
3899 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3902 lbl = newiTempLabel (NULL);
3903 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3904 emitcode ("cpl", "a");
3905 emitcode ("inc", "a");
3906 emitcode ("", "%05d$:", (lbl->key + 100));
3908 /* now the division */
3909 emitcode ("nop", "; workaround for DS80C390 div bug.");
3910 emitcode ("div", "ab");
3911 /* we are interested in the lower order
3913 emitcode ("mov", "b,a");
3914 lbl = newiTempLabel (NULL);
3915 emitcode ("pop", "acc");
3916 /* if there was an over flow we don't
3917 adjust the sign of the result */
3918 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3919 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3921 emitcode ("clr", "a");
3922 emitcode ("subb", "a,b");
3923 emitcode ("mov", "b,a");
3924 emitcode ("", "%05d$:", (lbl->key + 100));
3926 /* now we are done */
3927 aopPut (AOP (result), "b", 0);
3930 emitcode ("mov", "c,b.7");
3931 emitcode ("subb", "a,acc");
3934 aopPut (AOP (result), "a", offset++);
3938 /*-----------------------------------------------------------------*/
3939 /* genDiv - generates code for division */
3940 /*-----------------------------------------------------------------*/
3944 operand *left = IC_LEFT (ic);
3945 operand *right = IC_RIGHT (ic);
3946 operand *result = IC_RESULT (ic);
3948 D (emitcode (";", "genDiv ");
3951 /* assign the amsops */
3954 /* special cases first */
3956 if (AOP_TYPE (left) == AOP_CRY &&
3957 AOP_TYPE (right) == AOP_CRY)
3959 genDivbits (left, right, result);
3963 /* if both are of size == 1 */
3964 if (AOP_SIZE (left) == 1 &&
3965 AOP_SIZE (right) == 1)
3967 genDivOneByte (left, right, result);
3971 /* should have been converted to function call */
3974 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3975 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3976 freeAsmop (result, NULL, ic, TRUE);
3979 /*-----------------------------------------------------------------*/
3980 /* genModbits :- modulus of bits */
3981 /*-----------------------------------------------------------------*/
3983 genModbits (operand * left,
3990 /* the result must be bit */
3991 LOAD_AB_FOR_DIV (left, right, l);
3992 emitcode ("div", "ab");
3993 emitcode ("mov", "a,b");
3994 emitcode ("rrc", "a");
3995 aopPut (AOP (result), "c", 0);
3998 /*-----------------------------------------------------------------*/
3999 /* genModOneByte : 8 bit modulus */
4000 /*-----------------------------------------------------------------*/
4002 genModOneByte (operand * left,
4006 sym_link *opetype = operandType (result);
4010 /* signed or unsigned */
4011 if (SPEC_USIGN (opetype))
4013 /* unsigned is easy */
4014 LOAD_AB_FOR_DIV (left, right, l);
4015 emitcode ("div", "ab");
4016 aopPut (AOP (result), "b", 0);
4020 /* signed is a little bit more difficult */
4022 /* save the signs of the operands */
4023 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4026 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4027 emitcode ("push", "acc"); /* save it on the stack */
4029 /* now sign adjust for both left & right */
4030 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4033 lbl = newiTempLabel (NULL);
4034 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4035 emitcode ("cpl", "a");
4036 emitcode ("inc", "a");
4037 emitcode ("", "%05d$:", (lbl->key + 100));
4038 emitcode ("mov", "b,a");
4040 /* sign adjust left side */
4041 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4044 lbl = newiTempLabel (NULL);
4045 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4046 emitcode ("cpl", "a");
4047 emitcode ("inc", "a");
4048 emitcode ("", "%05d$:", (lbl->key + 100));
4050 /* now the multiplication */
4051 emitcode ("nop", "; workaround for DS80C390 div bug.");
4052 emitcode ("div", "ab");
4053 /* we are interested in the lower order
4055 lbl = newiTempLabel (NULL);
4056 emitcode ("pop", "acc");
4057 /* if there was an over flow we don't
4058 adjust the sign of the result */
4059 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4060 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4062 emitcode ("clr", "a");
4063 emitcode ("subb", "a,b");
4064 emitcode ("mov", "b,a");
4065 emitcode ("", "%05d$:", (lbl->key + 100));
4067 /* now we are done */
4068 aopPut (AOP (result), "b", 0);
4072 /*-----------------------------------------------------------------*/
4073 /* genMod - generates code for division */
4074 /*-----------------------------------------------------------------*/
4078 operand *left = IC_LEFT (ic);
4079 operand *right = IC_RIGHT (ic);
4080 operand *result = IC_RESULT (ic);
4082 D (emitcode (";", "genMod ");
4085 /* assign the amsops */
4088 /* special cases first */
4090 if (AOP_TYPE (left) == AOP_CRY &&
4091 AOP_TYPE (right) == AOP_CRY)
4093 genModbits (left, right, result);
4097 /* if both are of size == 1 */
4098 if (AOP_SIZE (left) == 1 &&
4099 AOP_SIZE (right) == 1)
4101 genModOneByte (left, right, result);
4105 /* should have been converted to function call */
4109 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4110 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4111 freeAsmop (result, NULL, ic, TRUE);
4114 /*-----------------------------------------------------------------*/
4115 /* genIfxJump :- will create a jump depending on the ifx */
4116 /*-----------------------------------------------------------------*/
4118 genIfxJump (iCode * ic, char *jval)
4121 symbol *tlbl = newiTempLabel (NULL);
4124 D (emitcode (";", "genIfxJump ");
4127 /* if true label then we jump if condition
4131 jlbl = IC_TRUE (ic);
4132 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4133 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4137 /* false label is present */
4138 jlbl = IC_FALSE (ic);
4139 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4140 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4142 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4143 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4145 emitcode (inst, "%05d$", tlbl->key + 100);
4146 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4147 emitcode ("", "%05d$:", tlbl->key + 100);
4149 /* mark the icode as generated */
4153 /*-----------------------------------------------------------------*/
4154 /* genCmp :- greater or less than comparison */
4155 /*-----------------------------------------------------------------*/
4157 genCmp (operand * left, operand * right,
4158 iCode * ic, iCode * ifx, int sign)
4160 int size, offset = 0;
4161 unsigned long lit = 0L;
4164 D (emitcode (";", "genCmp");
4167 result = IC_RESULT (ic);
4169 /* if left & right are bit variables */
4170 if (AOP_TYPE (left) == AOP_CRY &&
4171 AOP_TYPE (right) == AOP_CRY)
4173 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4174 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4178 /* subtract right from left if at the
4179 end the carry flag is set then we know that
4180 left is greater than right */
4181 size = max (AOP_SIZE (left), AOP_SIZE (right));
4183 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4184 if ((size == 1) && !sign &&
4185 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4187 symbol *lbl = newiTempLabel (NULL);
4188 emitcode ("cjne", "%s,%s,%05d$",
4189 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4190 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4192 emitcode ("", "%05d$:", lbl->key + 100);
4196 if (AOP_TYPE (right) == AOP_LIT)
4198 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4199 /* optimize if(x < 0) or if(x >= 0) */
4208 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4210 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4211 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4213 aopOp (result, ic, FALSE, FALSE);
4215 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4217 freeAsmop (result, NULL, ic, TRUE);
4218 genIfxJump (ifx, "acc.7");
4223 emitcode ("rlc", "a");
4225 goto release_freedLR;
4233 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4234 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4235 emitcode (";", "genCmp #2");
4236 if (sign && (size == 0))
4238 emitcode (";", "genCmp #3");
4239 emitcode ("xrl", "a,#0x80");
4240 if (AOP_TYPE (right) == AOP_LIT)
4242 unsigned long lit = (unsigned long)
4243 floatFromVal (AOP (right)->aopu.aop_lit);
4244 emitcode (";", "genCmp #3.1");
4245 emitcode ("subb", "a,#0x%02x",
4246 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4250 emitcode (";", "genCmp #3.2");
4251 if (AOP_NEEDSACC (right))
4253 emitcode ("push", "acc");
4255 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4256 FALSE, FALSE, FALSE));
4257 emitcode ("xrl", "b,#0x80");
4258 if (AOP_NEEDSACC (right))
4260 emitcode ("pop", "acc");
4262 emitcode ("subb", "a,b");
4269 emitcode (";", "genCmp #4");
4270 if (AOP_NEEDSACC (right))
4273 emitcode (";", "genCmp #4.1");
4274 emitcode ("xch", "a, b");
4275 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4276 emitcode ("xch", "a, b");
4281 emitcode (";", "genCmp #4.2");
4282 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4285 emitcode ("subb", "a,%s", s);
4292 /* Don't need the left & right operands any more; do need the result. */
4293 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4294 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4296 aopOp (result, ic, FALSE, FALSE);
4300 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4306 /* if the result is used in the next
4307 ifx conditional branch then generate
4308 code a little differently */
4311 genIfxJump (ifx, "c");
4317 /* leave the result in acc */
4319 freeAsmop (result, NULL, ic, TRUE);
4322 /*-----------------------------------------------------------------*/
4323 /* genCmpGt :- greater than comparison */
4324 /*-----------------------------------------------------------------*/
4326 genCmpGt (iCode * ic, iCode * ifx)
4328 operand *left, *right;
4329 sym_link *letype, *retype;
4332 D (emitcode (";", "genCmpGt ");
4335 left = IC_LEFT (ic);
4336 right = IC_RIGHT (ic);
4338 letype = getSpec (operandType (left));
4339 retype = getSpec (operandType (right));
4340 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4342 /* assign the left & right amsops */
4345 genCmp (right, left, ic, ifx, sign);
4348 /*-----------------------------------------------------------------*/
4349 /* genCmpLt - less than comparisons */
4350 /*-----------------------------------------------------------------*/
4352 genCmpLt (iCode * ic, iCode * ifx)
4354 operand *left, *right;
4355 sym_link *letype, *retype;
4358 D (emitcode (";", "genCmpLt "););
4360 left = IC_LEFT (ic);
4361 right = IC_RIGHT (ic);
4363 letype = getSpec (operandType (left));
4364 retype = getSpec (operandType (right));
4365 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4367 /* assign the left & right amsops */
4370 genCmp (left, right, ic, ifx, sign);
4373 /*-----------------------------------------------------------------*/
4374 /* gencjneshort - compare and jump if not equal */
4375 /*-----------------------------------------------------------------*/
4377 gencjneshort (operand * left, operand * right, symbol * lbl)
4379 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4381 unsigned long lit = 0L;
4383 D (emitcode (";", "gencjneshort");
4386 /* if the left side is a literal or
4387 if the right is in a pointer register and left
4389 if ((AOP_TYPE (left) == AOP_LIT) ||
4390 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4397 if (AOP_TYPE (right) == AOP_LIT)
4398 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4400 if (opIsGptr (left) || opIsGptr (right))
4402 /* We are comparing a generic pointer to something.
4403 * Exclude the generic type byte from the comparison.
4406 D (emitcode (";", "cjneshort: generic ptr special case.");
4411 /* if the right side is a literal then anything goes */
4412 if (AOP_TYPE (right) == AOP_LIT &&
4413 AOP_TYPE (left) != AOP_DIR)
4417 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4419 emitcode ("cjne", "a,%s,%05d$",
4420 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4426 /* if the right side is in a register or in direct space or
4427 if the left is a pointer register & right is not */
4428 else if (AOP_TYPE (right) == AOP_REG ||
4429 AOP_TYPE (right) == AOP_DIR ||
4430 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4431 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4435 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4436 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4437 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4438 emitcode ("jnz", "%05d$", lbl->key + 100);
4440 emitcode ("cjne", "a,%s,%05d$",
4441 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4448 /* right is a pointer reg need both a & b */
4451 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4452 if (strcmp (l, "b"))
4453 emitcode ("mov", "b,%s", l);
4454 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4455 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4461 /*-----------------------------------------------------------------*/
4462 /* gencjne - compare and jump if not equal */
4463 /*-----------------------------------------------------------------*/
4465 gencjne (operand * left, operand * right, symbol * lbl)
4467 symbol *tlbl = newiTempLabel (NULL);
4469 D (emitcode (";", "gencjne");
4472 gencjneshort (left, right, lbl);
4474 emitcode ("mov", "a,%s", one);
4475 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4476 emitcode ("", "%05d$:", lbl->key + 100);
4477 emitcode ("clr", "a");
4478 emitcode ("", "%05d$:", tlbl->key + 100);
4481 /*-----------------------------------------------------------------*/
4482 /* genCmpEq - generates code for equal to */
4483 /*-----------------------------------------------------------------*/
4485 genCmpEq (iCode * ic, iCode * ifx)
4487 operand *left, *right, *result;
4489 D (emitcode (";", "genCmpEq ");
4493 AOP_SET_LOCALS (ic);
4495 /* if literal, literal on the right or
4496 if the right is in a pointer register and left
4498 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4499 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4501 operand *t = IC_RIGHT (ic);
4502 IC_RIGHT (ic) = IC_LEFT (ic);
4506 if (ifx && /* !AOP_SIZE(result) */
4507 OP_SYMBOL (result) &&
4508 OP_SYMBOL (result)->regType == REG_CND)
4511 /* if they are both bit variables */
4512 if (AOP_TYPE (left) == AOP_CRY &&
4513 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4515 if (AOP_TYPE (right) == AOP_LIT)
4517 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4520 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4521 emitcode ("cpl", "c");
4525 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4529 emitcode ("clr", "c");
4531 /* AOP_TYPE(right) == AOP_CRY */
4535 symbol *lbl = newiTempLabel (NULL);
4536 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4537 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4538 emitcode ("cpl", "c");
4539 emitcode ("", "%05d$:", (lbl->key + 100));
4541 /* if true label then we jump if condition
4543 tlbl = newiTempLabel (NULL);
4546 emitcode ("jnc", "%05d$", tlbl->key + 100);
4547 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4551 emitcode ("jc", "%05d$", tlbl->key + 100);
4552 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4554 emitcode ("", "%05d$:", tlbl->key + 100);
4558 tlbl = newiTempLabel (NULL);
4559 gencjneshort (left, right, tlbl);
4562 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4563 emitcode ("", "%05d$:", tlbl->key + 100);
4567 symbol *lbl = newiTempLabel (NULL);
4568 emitcode ("sjmp", "%05d$", lbl->key + 100);
4569 emitcode ("", "%05d$:", tlbl->key + 100);
4570 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4571 emitcode ("", "%05d$:", lbl->key + 100);
4574 /* mark the icode as generated */
4577 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4582 /* if they are both bit variables */
4583 if (AOP_TYPE (left) == AOP_CRY &&
4584 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4586 if (AOP_TYPE (right) == AOP_LIT)
4588 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4591 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4592 emitcode ("cpl", "c");
4596 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4600 emitcode ("clr", "c");
4602 /* AOP_TYPE(right) == AOP_CRY */
4606 symbol *lbl = newiTempLabel (NULL);
4607 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4608 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4609 emitcode ("cpl", "c");
4610 emitcode ("", "%05d$:", (lbl->key + 100));
4613 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616 aopOp (result, ic, TRUE, FALSE);
4619 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4626 genIfxJump (ifx, "c");
4629 /* if the result is used in an arithmetic operation
4630 then put the result in place */
4635 gencjne (left, right, newiTempLabel (NULL));
4637 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4638 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4640 aopOp (result, ic, TRUE, FALSE);
4642 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4644 aopPut (AOP (result), "a", 0);
4649 genIfxJump (ifx, "a");
4652 /* if the result is used in an arithmetic operation
4653 then put the result in place */
4654 if (AOP_TYPE (result) != AOP_CRY)
4656 /* leave the result in acc */
4660 freeAsmop (result, NULL, ic, TRUE);
4663 /*-----------------------------------------------------------------*/
4664 /* ifxForOp - returns the icode containing the ifx for operand */
4665 /*-----------------------------------------------------------------*/
4667 ifxForOp (operand * op, iCode * ic)
4669 /* if true symbol then needs to be assigned */
4670 if (IS_TRUE_SYMOP (op))
4673 /* if this has register type condition and
4674 the next instruction is ifx with the same operand
4675 and live to of the operand is upto the ifx only then */
4677 ic->next->op == IFX &&
4678 IC_COND (ic->next)->key == op->key &&
4679 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4684 /*-----------------------------------------------------------------*/
4685 /* genAndOp - for && operation */
4686 /*-----------------------------------------------------------------*/
4688 genAndOp (iCode * ic)
4690 operand *left, *right, *result;
4693 D (emitcode (";", "genAndOp "););
4695 /* note here that && operations that are in an
4696 if statement are taken away by backPatchLabels
4697 only those used in arthmetic operations remain */
4699 AOP_SET_LOCALS (ic);
4701 /* if both are bit variables */
4702 if (AOP_TYPE (left) == AOP_CRY &&
4703 AOP_TYPE (right) == AOP_CRY)
4705 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4706 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4707 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4708 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4710 aopOp (result,ic,FALSE, FALSE);
4715 tlbl = newiTempLabel (NULL);
4717 emitcode ("jz", "%05d$", tlbl->key + 100);
4719 emitcode ("", "%05d$:", tlbl->key + 100);
4720 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4721 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4723 aopOp (result,ic,FALSE, FALSE);
4726 freeAsmop (result, NULL, ic, TRUE);
4730 /*-----------------------------------------------------------------*/
4731 /* genOrOp - for || operation */
4732 /*-----------------------------------------------------------------*/
4734 genOrOp (iCode * ic)
4736 operand *left, *right, *result;
4739 D (emitcode (";", "genOrOp "););
4741 /* note here that || operations that are in an
4742 if statement are taken away by backPatchLabels
4743 only those used in arthmetic operations remain */
4745 AOP_SET_LOCALS (ic);
4747 /* if both are bit variables */
4748 if (AOP_TYPE (left) == AOP_CRY &&
4749 AOP_TYPE (right) == AOP_CRY)
4751 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4752 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4753 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4754 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4756 aopOp (result,ic,FALSE, FALSE);
4762 tlbl = newiTempLabel (NULL);
4764 emitcode ("jnz", "%05d$", tlbl->key + 100);
4766 emitcode ("", "%05d$:", tlbl->key + 100);
4767 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4768 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4770 aopOp (result,ic,FALSE, FALSE);
4775 freeAsmop (result, NULL, ic, TRUE);
4778 /*-----------------------------------------------------------------*/
4779 /* isLiteralBit - test if lit == 2^n */
4780 /*-----------------------------------------------------------------*/
4782 isLiteralBit (unsigned long lit)
4784 unsigned long pw[32] =
4785 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4786 0x100L, 0x200L, 0x400L, 0x800L,
4787 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4788 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4789 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4790 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4791 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4794 for (idx = 0; idx < 32; idx++)
4800 /*-----------------------------------------------------------------*/
4801 /* continueIfTrue - */
4802 /*-----------------------------------------------------------------*/
4804 continueIfTrue (iCode * ic)
4807 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4811 /*-----------------------------------------------------------------*/
4813 /*-----------------------------------------------------------------*/
4815 jumpIfTrue (iCode * ic)
4818 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4822 /*-----------------------------------------------------------------*/
4823 /* jmpTrueOrFalse - */
4824 /*-----------------------------------------------------------------*/
4826 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4828 // ugly but optimized by peephole
4831 symbol *nlbl = newiTempLabel (NULL);
4832 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4833 emitcode ("", "%05d$:", tlbl->key + 100);
4834 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4835 emitcode ("", "%05d$:", nlbl->key + 100);
4839 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4840 emitcode ("", "%05d$:", tlbl->key + 100);
4845 // Generate code to perform a bit-wise logic operation
4846 // on two operands in far space (assumed to already have been
4847 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4848 // in far space. This requires pushing the result on the stack
4849 // then popping it into the result.
4851 genFarFarLogicOp(iCode *ic, char *logicOp)
4853 int size, resultSize, compSize;
4856 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4857 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4858 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4860 _startLazyDPSEvaluation();
4861 for (size = compSize; (size--); offset++)
4863 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4864 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4865 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4867 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4868 emitcode ("push", "acc");
4870 _endLazyDPSEvaluation();
4872 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4873 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4874 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4876 resultSize = AOP_SIZE(IC_RESULT(ic));
4878 ADJUST_PUSHED_RESULT(compSize, resultSize);
4880 _startLazyDPSEvaluation();
4883 emitcode ("pop", "acc");
4884 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4886 _endLazyDPSEvaluation();
4887 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4891 /*-----------------------------------------------------------------*/
4892 /* genAnd - code for and */
4893 /*-----------------------------------------------------------------*/
4895 genAnd (iCode * ic, iCode * ifx)
4897 operand *left, *right, *result;
4898 int size, offset = 0;
4899 unsigned long lit = 0L;
4904 D (emitcode (";", "genAnd "););
4906 AOP_OP_3_NOFATAL (ic, pushResult);
4907 AOP_SET_LOCALS (ic);
4911 genFarFarLogicOp(ic, "anl");
4916 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4918 AOP_TYPE (left), AOP_TYPE (right));
4919 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4921 AOP_SIZE (left), AOP_SIZE (right));
4924 /* if left is a literal & right is not then exchange them */
4925 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4926 AOP_NEEDSACC (left))
4928 operand *tmp = right;
4933 /* if result = right then exchange them */
4934 if (sameRegs (AOP (result), AOP (right)))
4936 operand *tmp = right;
4941 /* if right is bit then exchange them */
4942 if (AOP_TYPE (right) == AOP_CRY &&
4943 AOP_TYPE (left) != AOP_CRY)
4945 operand *tmp = right;
4949 if (AOP_TYPE (right) == AOP_LIT)
4950 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4952 size = AOP_SIZE (result);
4955 // result = bit & yy;
4956 if (AOP_TYPE (left) == AOP_CRY)
4958 // c = bit & literal;
4959 if (AOP_TYPE (right) == AOP_LIT)
4963 if (size && sameRegs (AOP (result), AOP (left)))
4966 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4971 if (size && (AOP_TYPE (result) == AOP_CRY))
4973 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4976 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4981 emitcode ("clr", "c");
4986 if (AOP_TYPE (right) == AOP_CRY)
4989 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4990 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4995 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4997 emitcode ("rrc", "a");
4998 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5006 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5007 genIfxJump (ifx, "c");
5011 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5012 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5013 if ((AOP_TYPE (right) == AOP_LIT) &&
5014 (AOP_TYPE (result) == AOP_CRY) &&
5015 (AOP_TYPE (left) != AOP_CRY))
5017 int posbit = isLiteralBit (lit);
5022 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5025 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5031 sprintf (buffer, "acc.%d", posbit & 0x07);
5032 genIfxJump (ifx, buffer);
5039 symbol *tlbl = newiTempLabel (NULL);
5040 int sizel = AOP_SIZE (left);
5042 emitcode ("setb", "c");
5045 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5047 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5049 if ((posbit = isLiteralBit (bytelit)) != 0)
5050 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5053 if (bytelit != 0x0FFL)
5054 emitcode ("anl", "a,%s",
5055 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5056 emitcode ("jnz", "%05d$", tlbl->key + 100);
5061 // bit = left & literal
5064 emitcode ("clr", "c");
5065 emitcode ("", "%05d$:", tlbl->key + 100);
5067 // if(left & literal)
5071 jmpTrueOrFalse (ifx, tlbl);
5079 /* if left is same as result */
5080 if (sameRegs (AOP (result), AOP (left)))
5082 for (; size--; offset++)
5084 if (AOP_TYPE (right) == AOP_LIT)
5086 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5088 else if (bytelit == 0)
5089 aopPut (AOP (result), zero, offset);
5090 else if (IS_AOP_PREG (result))
5092 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5093 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5094 aopPut (AOP (result), "a", offset);
5097 emitcode ("anl", "%s,%s",
5098 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5099 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5103 if (AOP_TYPE (left) == AOP_ACC)
5104 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5107 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5108 if (IS_AOP_PREG (result))
5110 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5111 aopPut (AOP (result), "a", offset);
5115 emitcode ("anl", "%s,a",
5116 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5123 // left & result in different registers
5124 if (AOP_TYPE (result) == AOP_CRY)
5127 // if(size), result in bit
5128 // if(!size && ifx), conditional oper: if(left & right)
5129 symbol *tlbl = newiTempLabel (NULL);
5130 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5132 emitcode ("setb", "c");
5135 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5136 emitcode ("anl", "a,%s",
5137 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5138 emitcode ("jnz", "%05d$", tlbl->key + 100);
5144 emitcode ("", "%05d$:", tlbl->key + 100);
5148 jmpTrueOrFalse (ifx, tlbl);
5152 for (; (size--); offset++)
5155 // result = left & right
5156 if (AOP_TYPE (right) == AOP_LIT)
5158 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5160 aopPut (AOP (result),
5161 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5165 else if (bytelit == 0)
5167 aopPut (AOP (result), zero, offset);
5170 D (emitcode (";", "better literal AND.");
5172 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5173 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5174 FALSE, FALSE, FALSE));
5179 // faster than result <- left, anl result,right
5180 // and better if result is SFR
5181 if (AOP_TYPE (left) == AOP_ACC)
5183 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5184 FALSE, FALSE, FALSE));
5188 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5189 emitcode ("anl", "a,%s",
5190 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5193 aopPut (AOP (result), "a", offset);
5199 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5200 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5201 freeAsmop (result, NULL, ic, TRUE);
5205 /*-----------------------------------------------------------------*/
5206 /* genOr - code for or */
5207 /*-----------------------------------------------------------------*/
5209 genOr (iCode * ic, iCode * ifx)
5211 operand *left, *right, *result;
5212 int size, offset = 0;
5213 unsigned long lit = 0L;
5216 D (emitcode (";", "genOr "););
5218 AOP_OP_3_NOFATAL (ic, pushResult);
5219 AOP_SET_LOCALS (ic);
5223 genFarFarLogicOp(ic, "orl");
5229 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5231 AOP_TYPE (left), AOP_TYPE (right));
5232 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5234 AOP_SIZE (left), AOP_SIZE (right));
5237 /* if left is a literal & right is not then exchange them */
5238 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5239 AOP_NEEDSACC (left))
5241 operand *tmp = right;
5246 /* if result = right then exchange them */
5247 if (sameRegs (AOP (result), AOP (right)))
5249 operand *tmp = right;
5254 /* if right is bit then exchange them */
5255 if (AOP_TYPE (right) == AOP_CRY &&
5256 AOP_TYPE (left) != AOP_CRY)
5258 operand *tmp = right;
5262 if (AOP_TYPE (right) == AOP_LIT)
5263 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5265 size = AOP_SIZE (result);
5269 if (AOP_TYPE (left) == AOP_CRY)
5271 if (AOP_TYPE (right) == AOP_LIT)
5273 // c = bit & literal;
5276 // lit != 0 => result = 1
5277 if (AOP_TYPE (result) == AOP_CRY)
5280 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5282 continueIfTrue (ifx);
5285 emitcode ("setb", "c");
5289 // lit == 0 => result = left
5290 if (size && sameRegs (AOP (result), AOP (left)))
5292 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5297 if (AOP_TYPE (right) == AOP_CRY)
5300 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5301 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5306 symbol *tlbl = newiTempLabel (NULL);
5307 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5308 emitcode ("setb", "c");
5309 emitcode ("jb", "%s,%05d$",
5310 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5312 emitcode ("jnz", "%05d$", tlbl->key + 100);
5313 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5315 jmpTrueOrFalse (ifx, tlbl);
5321 emitcode ("", "%05d$:", tlbl->key + 100);
5330 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5331 genIfxJump (ifx, "c");
5335 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5336 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5337 if ((AOP_TYPE (right) == AOP_LIT) &&
5338 (AOP_TYPE (result) == AOP_CRY) &&
5339 (AOP_TYPE (left) != AOP_CRY))
5345 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5347 continueIfTrue (ifx);
5352 // lit = 0, result = boolean(left)
5354 emitcode ("setb", "c");
5358 symbol *tlbl = newiTempLabel (NULL);
5359 emitcode ("jnz", "%05d$", tlbl->key + 100);
5361 emitcode ("", "%05d$:", tlbl->key + 100);
5365 genIfxJump (ifx, "a");
5373 /* if left is same as result */
5374 if (sameRegs (AOP (result), AOP (left)))
5376 for (; size--; offset++)
5378 if (AOP_TYPE (right) == AOP_LIT)
5380 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5386 if (IS_AOP_PREG (left))
5388 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5389 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5390 aopPut (AOP (result), "a", offset);
5394 emitcode ("orl", "%s,%s",
5395 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5396 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5402 if (AOP_TYPE (left) == AOP_ACC)
5404 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5408 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5409 if (IS_AOP_PREG (left))
5411 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5412 aopPut (AOP (result), "a", offset);
5416 emitcode ("orl", "%s,a",
5417 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5425 // left & result in different registers
5426 if (AOP_TYPE (result) == AOP_CRY)
5429 // if(size), result in bit
5430 // if(!size && ifx), conditional oper: if(left | right)
5431 symbol *tlbl = newiTempLabel (NULL);
5432 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5434 emitcode ("setb", "c");
5437 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5438 emitcode ("orl", "a,%s",
5439 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5440 emitcode ("jnz", "%05d$", tlbl->key + 100);
5446 emitcode ("", "%05d$:", tlbl->key + 100);
5450 jmpTrueOrFalse (ifx, tlbl);
5454 for (; (size--); offset++)
5457 // result = left & right
5458 if (AOP_TYPE (right) == AOP_LIT)
5460 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5462 aopPut (AOP (result),
5463 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5467 D (emitcode (";", "better literal OR.");
5469 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5470 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5471 FALSE, FALSE, FALSE));
5476 // faster than result <- left, anl result,right
5477 // and better if result is SFR
5478 if (AOP_TYPE (left) == AOP_ACC)
5480 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5481 FALSE, FALSE, FALSE));
5485 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5486 emitcode ("orl", "a,%s",
5487 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5490 aopPut (AOP (result), "a", offset);
5496 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5497 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5498 freeAsmop (result, NULL, ic, TRUE);
5501 /*-----------------------------------------------------------------*/
5502 /* genXor - code for xclusive or */
5503 /*-----------------------------------------------------------------*/
5505 genXor (iCode * ic, iCode * ifx)
5507 operand *left, *right, *result;
5508 int size, offset = 0;
5509 unsigned long lit = 0L;
5512 D (emitcode (";", "genXor "););
5514 AOP_OP_3_NOFATAL (ic, pushResult);
5515 AOP_SET_LOCALS (ic);
5519 genFarFarLogicOp(ic, "xrl");
5524 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5526 AOP_TYPE (left), AOP_TYPE (right));
5527 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5529 AOP_SIZE (left), AOP_SIZE (right));
5532 /* if left is a literal & right is not ||
5533 if left needs acc & right does not */
5534 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5535 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5537 operand *tmp = right;
5542 /* if result = right then exchange them */
5543 if (sameRegs (AOP (result), AOP (right)))
5545 operand *tmp = right;
5550 /* if right is bit then exchange them */
5551 if (AOP_TYPE (right) == AOP_CRY &&
5552 AOP_TYPE (left) != AOP_CRY)
5554 operand *tmp = right;
5558 if (AOP_TYPE (right) == AOP_LIT)
5559 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5561 size = AOP_SIZE (result);
5565 if (AOP_TYPE (left) == AOP_CRY)
5567 if (AOP_TYPE (right) == AOP_LIT)
5569 // c = bit & literal;
5572 // lit>>1 != 0 => result = 1
5573 if (AOP_TYPE (result) == AOP_CRY)
5576 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5578 continueIfTrue (ifx);
5581 emitcode ("setb", "c");
5588 // lit == 0, result = left
5589 if (size && sameRegs (AOP (result), AOP (left)))
5591 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5595 // lit == 1, result = not(left)
5596 if (size && sameRegs (AOP (result), AOP (left)))
5598 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5603 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5604 emitcode ("cpl", "c");
5613 symbol *tlbl = newiTempLabel (NULL);
5614 if (AOP_TYPE (right) == AOP_CRY)
5617 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5621 int sizer = AOP_SIZE (right);
5623 // if val>>1 != 0, result = 1
5624 emitcode ("setb", "c");
5627 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5629 // test the msb of the lsb
5630 emitcode ("anl", "a,#0xfe");
5631 emitcode ("jnz", "%05d$", tlbl->key + 100);
5635 emitcode ("rrc", "a");
5637 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5638 emitcode ("cpl", "c");
5639 emitcode ("", "%05d$:", (tlbl->key + 100));
5646 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5647 genIfxJump (ifx, "c");
5651 if (sameRegs (AOP (result), AOP (left)))
5653 /* if left is same as result */
5654 for (; size--; offset++)
5656 if (AOP_TYPE (right) == AOP_LIT)
5658 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5660 else if (IS_AOP_PREG (left))
5662 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5663 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5664 aopPut (AOP (result), "a", offset);
5667 emitcode ("xrl", "%s,%s",
5668 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5669 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5673 if (AOP_TYPE (left) == AOP_ACC)
5674 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5677 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5678 if (IS_AOP_PREG (left))
5680 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5681 aopPut (AOP (result), "a", offset);
5684 emitcode ("xrl", "%s,a",
5685 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5692 // left & result in different registers
5693 if (AOP_TYPE (result) == AOP_CRY)
5696 // if(size), result in bit
5697 // if(!size && ifx), conditional oper: if(left ^ right)
5698 symbol *tlbl = newiTempLabel (NULL);
5699 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5701 emitcode ("setb", "c");
5704 if ((AOP_TYPE (right) == AOP_LIT) &&
5705 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5707 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5711 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5712 emitcode ("xrl", "a,%s",
5713 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5715 emitcode ("jnz", "%05d$", tlbl->key + 100);
5721 emitcode ("", "%05d$:", tlbl->key + 100);
5725 jmpTrueOrFalse (ifx, tlbl);
5728 for (; (size--); offset++)
5731 // result = left & right
5732 if (AOP_TYPE (right) == AOP_LIT)
5734 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5736 aopPut (AOP (result),
5737 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5741 D (emitcode (";", "better literal XOR.");
5743 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5744 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5745 FALSE, FALSE, FALSE));
5749 // faster than result <- left, anl result,right
5750 // and better if result is SFR
5751 if (AOP_TYPE (left) == AOP_ACC)
5753 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5754 FALSE, FALSE, FALSE));
5758 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5759 emitcode ("xrl", "a,%s",
5760 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5763 aopPut (AOP (result), "a", offset);
5768 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5769 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5770 freeAsmop (result, NULL, ic, TRUE);
5773 /*-----------------------------------------------------------------*/
5774 /* genInline - write the inline code out */
5775 /*-----------------------------------------------------------------*/
5777 genInline (iCode * ic)
5779 char buffer[MAX_INLINEASM];
5783 D (emitcode (";", "genInline ");
5786 _G.inLine += (!options.asmpeep);
5787 strcpy (buffer, IC_INLINE (ic));
5789 /* emit each line as a code */
5814 /* emitcode("",buffer); */
5815 _G.inLine -= (!options.asmpeep);
5818 /*-----------------------------------------------------------------*/
5819 /* genRRC - rotate right with carry */
5820 /*-----------------------------------------------------------------*/
5824 operand *left, *result;
5825 int size, offset = 0;
5828 D (emitcode (";", "genRRC ");
5831 /* rotate right with carry */
5832 left = IC_LEFT (ic);
5833 result = IC_RESULT (ic);
5834 aopOp (left, ic, FALSE, FALSE);
5835 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5837 /* move it to the result */
5838 size = AOP_SIZE (result);
5842 _startLazyDPSEvaluation ();
5845 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5847 emitcode ("rrc", "a");
5848 if (AOP_SIZE (result) > 1)
5849 aopPut (AOP (result), "a", offset--);
5851 _endLazyDPSEvaluation ();
5853 /* now we need to put the carry into the
5854 highest order byte of the result */
5855 if (AOP_SIZE (result) > 1)
5857 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5860 emitcode ("mov", "acc.7,c");
5861 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5862 freeAsmop (left, NULL, ic, TRUE);
5863 freeAsmop (result, NULL, ic, TRUE);
5866 /*-----------------------------------------------------------------*/
5867 /* genRLC - generate code for rotate left with carry */
5868 /*-----------------------------------------------------------------*/
5872 operand *left, *result;
5873 int size, offset = 0;
5876 D (emitcode (";", "genRLC ");
5879 /* rotate right with carry */
5880 left = IC_LEFT (ic);
5881 result = IC_RESULT (ic);
5882 aopOp (left, ic, FALSE, FALSE);
5883 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5885 /* move it to the result */
5886 size = AOP_SIZE (result);
5890 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5892 emitcode ("add", "a,acc");
5893 if (AOP_SIZE (result) > 1)
5895 aopPut (AOP (result), "a", offset++);
5898 _startLazyDPSEvaluation ();
5901 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5903 emitcode ("rlc", "a");
5904 if (AOP_SIZE (result) > 1)
5905 aopPut (AOP (result), "a", offset++);
5907 _endLazyDPSEvaluation ();
5909 /* now we need to put the carry into the
5910 highest order byte of the result */
5911 if (AOP_SIZE (result) > 1)
5913 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5916 emitcode ("mov", "acc.0,c");
5917 aopPut (AOP (result), "a", 0);
5918 freeAsmop (left, NULL, ic, TRUE);
5919 freeAsmop (result, NULL, ic, TRUE);
5922 /*-----------------------------------------------------------------*/
5923 /* genGetHbit - generates code get highest order bit */
5924 /*-----------------------------------------------------------------*/
5926 genGetHbit (iCode * ic)
5928 operand *left, *result;
5929 left = IC_LEFT (ic);
5930 result = IC_RESULT (ic);
5931 aopOp (left, ic, FALSE, FALSE);
5932 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5934 D (emitcode (";", "genGetHbit ");
5937 /* get the highest order byte into a */
5938 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5939 if (AOP_TYPE (result) == AOP_CRY)
5941 emitcode ("rlc", "a");
5946 emitcode ("rl", "a");
5947 emitcode ("anl", "a,#0x01");
5952 freeAsmop (left, NULL, ic, TRUE);
5953 freeAsmop (result, NULL, ic, TRUE);
5956 /*-----------------------------------------------------------------*/
5957 /* AccRol - rotate left accumulator by known count */
5958 /*-----------------------------------------------------------------*/
5960 AccRol (int shCount)
5962 shCount &= 0x0007; // shCount : 0..7
5969 emitcode ("rl", "a");
5972 emitcode ("rl", "a");
5973 emitcode ("rl", "a");
5976 emitcode ("swap", "a");
5977 emitcode ("rr", "a");
5980 emitcode ("swap", "a");
5983 emitcode ("swap", "a");
5984 emitcode ("rl", "a");
5987 emitcode ("rr", "a");
5988 emitcode ("rr", "a");
5991 emitcode ("rr", "a");
5996 /*-----------------------------------------------------------------*/
5997 /* AccLsh - left shift accumulator by known count */
5998 /*-----------------------------------------------------------------*/
6000 AccLsh (int shCount)
6005 emitcode ("add", "a,acc");
6006 else if (shCount == 2)
6008 emitcode ("add", "a,acc");
6009 emitcode ("add", "a,acc");
6013 /* rotate left accumulator */
6015 /* and kill the lower order bits */
6016 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6021 /*-----------------------------------------------------------------*/
6022 /* AccRsh - right shift accumulator by known count */
6023 /*-----------------------------------------------------------------*/
6025 AccRsh (int shCount)
6032 emitcode ("rrc", "a");
6036 /* rotate right accumulator */
6037 AccRol (8 - shCount);
6038 /* and kill the higher order bits */
6039 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6044 #ifdef BETTER_LITERAL_SHIFT
6045 /*-----------------------------------------------------------------*/
6046 /* AccSRsh - signed right shift accumulator by known count */
6047 /*-----------------------------------------------------------------*/
6049 AccSRsh (int shCount)
6056 emitcode ("mov", "c,acc.7");
6057 emitcode ("rrc", "a");
6059 else if (shCount == 2)
6061 emitcode ("mov", "c,acc.7");
6062 emitcode ("rrc", "a");
6063 emitcode ("mov", "c,acc.7");
6064 emitcode ("rrc", "a");
6068 tlbl = newiTempLabel (NULL);
6069 /* rotate right accumulator */
6070 AccRol (8 - shCount);
6071 /* and kill the higher order bits */
6072 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6073 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6074 emitcode ("orl", "a,#0x%02x",
6075 (unsigned char) ~SRMask[shCount]);
6076 emitcode ("", "%05d$:", tlbl->key + 100);
6082 #ifdef BETTER_LITERAL_SHIFT
6083 /*-----------------------------------------------------------------*/
6084 /* shiftR1Left2Result - shift right one byte from left to result */
6085 /*-----------------------------------------------------------------*/
6087 shiftR1Left2Result (operand * left, int offl,
6088 operand * result, int offr,
6089 int shCount, int sign)
6091 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6092 /* shift right accumulator */
6097 aopPut (AOP (result), "a", offr);
6101 #ifdef BETTER_LITERAL_SHIFT
6102 /*-----------------------------------------------------------------*/
6103 /* shiftL1Left2Result - shift left one byte from left to result */
6104 /*-----------------------------------------------------------------*/
6106 shiftL1Left2Result (operand * left, int offl,
6107 operand * result, int offr, int shCount)
6109 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6110 /* shift left accumulator */
6112 aopPut (AOP (result), "a", offr);
6116 #ifdef BETTER_LITERAL_SHIFT
6117 /*-----------------------------------------------------------------*/
6118 /* movLeft2Result - move byte from left to result */
6119 /*-----------------------------------------------------------------*/
6121 movLeft2Result (operand * left, int offl,
6122 operand * result, int offr, int sign)
6125 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6127 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6129 if (*l == '@' && (IS_AOP_PREG (result)))
6131 emitcode ("mov", "a,%s", l);
6132 aopPut (AOP (result), "a", offr);
6138 aopPut (AOP (result), l, offr);
6142 /* MSB sign in acc.7 ! */
6143 if (getDataSize (left) == offl + 1)
6145 emitcode ("mov", "a,%s", l);
6146 aopPut (AOP (result), "a", offr);
6154 #ifdef BETTER_LITERAL_SHIFT
6155 /*-----------------------------------------------------------------*/
6156 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6157 /*-----------------------------------------------------------------*/
6161 emitcode ("rrc", "a");
6162 emitcode ("xch", "a,%s", x);
6163 emitcode ("rrc", "a");
6164 emitcode ("xch", "a,%s", x);
6168 #ifdef BETTER_LITERAL_SHIFT
6170 /*-----------------------------------------------------------------*/
6171 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6172 /*-----------------------------------------------------------------*/
6176 emitcode ("xch", "a,%s", x);
6177 emitcode ("rlc", "a");
6178 emitcode ("xch", "a,%s", x);
6179 emitcode ("rlc", "a");
6183 #ifdef BETTER_LITERAL_SHIFT
6184 /*-----------------------------------------------------------------*/
6185 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6186 /*-----------------------------------------------------------------*/
6190 emitcode ("xch", "a,%s", x);
6191 emitcode ("add", "a,acc");
6192 emitcode ("xch", "a,%s", x);
6193 emitcode ("rlc", "a");
6197 #ifdef BETTER_LITERAL_SHIFT
6198 /*-----------------------------------------------------------------*/
6199 /* AccAXLsh - left shift a:x by known count (0..7) */
6200 /*-----------------------------------------------------------------*/
6202 AccAXLsh (char *x, int shCount)
6217 case 5: // AAAAABBB:CCCCCDDD
6219 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6221 emitcode ("anl", "a,#0x%02x",
6222 SLMask[shCount]); // BBB00000:CCCCCDDD
6224 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6226 AccRol (shCount); // DDDCCCCC:BBB00000
6228 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6230 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6232 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6234 emitcode ("anl", "a,#0x%02x",
6235 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6237 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6239 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6242 case 6: // AAAAAABB:CCCCCCDD
6243 emitcode ("anl", "a,#0x%02x",
6244 SRMask[shCount]); // 000000BB:CCCCCCDD
6245 emitcode ("mov", "c,acc.0"); // c = B
6246 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6248 AccAXRrl1 (x); // BCCCCCCD:D000000B
6249 AccAXRrl1 (x); // BBCCCCCC:DD000000
6251 emitcode("rrc","a");
6252 emitcode("xch","a,%s", x);
6253 emitcode("rrc","a");
6254 emitcode("mov","c,acc.0"); //<< get correct bit
6255 emitcode("xch","a,%s", x);
6257 emitcode("rrc","a");
6258 emitcode("xch","a,%s", x);
6259 emitcode("rrc","a");
6260 emitcode("xch","a,%s", x);
6263 case 7: // a:x <<= 7
6265 emitcode ("anl", "a,#0x%02x",
6266 SRMask[shCount]); // 0000000B:CCCCCCCD
6268 emitcode ("mov", "c,acc.0"); // c = B
6270 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6272 AccAXRrl1 (x); // BCCCCCCC:D0000000
6281 #ifdef BETTER_LITERAL_SHIFT
6283 /*-----------------------------------------------------------------*/
6284 /* AccAXRsh - right shift a:x known count (0..7) */
6285 /*-----------------------------------------------------------------*/
6287 AccAXRsh (char *x, int shCount)
6295 AccAXRrl1 (x); // 0->a:x
6300 AccAXRrl1 (x); // 0->a:x
6303 AccAXRrl1 (x); // 0->a:x
6308 case 5: // AAAAABBB:CCCCCDDD = a:x
6310 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6312 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6314 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6316 emitcode ("anl", "a,#0x%02x",
6317 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6319 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6321 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6323 emitcode ("anl", "a,#0x%02x",
6324 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6326 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6328 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6330 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6333 case 6: // AABBBBBB:CCDDDDDD
6335 emitcode ("mov", "c,acc.7");
6336 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6338 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6340 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6342 emitcode ("anl", "a,#0x%02x",
6343 SRMask[shCount]); // 000000AA:BBBBBBCC
6346 case 7: // ABBBBBBB:CDDDDDDD
6348 emitcode ("mov", "c,acc.7"); // c = A
6350 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6352 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6354 emitcode ("anl", "a,#0x%02x",
6355 SRMask[shCount]); // 0000000A:BBBBBBBC
6364 #ifdef BETTER_LITERAL_SHIFT
6366 /*-----------------------------------------------------------------*/
6367 /* AccAXRshS - right shift signed a:x known count (0..7) */
6368 /*-----------------------------------------------------------------*/
6370 AccAXRshS (char *x, int shCount)
6378 emitcode ("mov", "c,acc.7");
6379 AccAXRrl1 (x); // s->a:x
6383 emitcode ("mov", "c,acc.7");
6384 AccAXRrl1 (x); // s->a:x
6386 emitcode ("mov", "c,acc.7");
6387 AccAXRrl1 (x); // s->a:x
6392 case 5: // AAAAABBB:CCCCCDDD = a:x
6394 tlbl = newiTempLabel (NULL);
6395 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6397 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6399 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6401 emitcode ("anl", "a,#0x%02x",
6402 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6404 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6406 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6408 emitcode ("anl", "a,#0x%02x",
6409 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6411 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6413 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6415 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6417 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6418 emitcode ("orl", "a,#0x%02x",
6419 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6421 emitcode ("", "%05d$:", tlbl->key + 100);
6422 break; // SSSSAAAA:BBBCCCCC
6424 case 6: // AABBBBBB:CCDDDDDD
6426 tlbl = newiTempLabel (NULL);
6427 emitcode ("mov", "c,acc.7");
6428 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6430 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6432 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6434 emitcode ("anl", "a,#0x%02x",
6435 SRMask[shCount]); // 000000AA:BBBBBBCC
6437 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6438 emitcode ("orl", "a,#0x%02x",
6439 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6441 emitcode ("", "%05d$:", tlbl->key + 100);
6443 case 7: // ABBBBBBB:CDDDDDDD
6445 tlbl = newiTempLabel (NULL);
6446 emitcode ("mov", "c,acc.7"); // c = A
6448 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6450 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6452 emitcode ("anl", "a,#0x%02x",
6453 SRMask[shCount]); // 0000000A:BBBBBBBC
6455 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6456 emitcode ("orl", "a,#0x%02x",
6457 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6459 emitcode ("", "%05d$:", tlbl->key + 100);
6467 #ifdef BETTER_LITERAL_SHIFT
6469 _loadLeftIntoAx(char **lsb,
6475 // Get the initial value from left into a pair of registers.
6476 // MSB must be in A, LSB can be any register.
6478 // If the result is held in registers, it is an optimization
6479 // if the LSB can be held in the register which will hold the,
6480 // result LSB since this saves us from having to copy it into
6481 // the result following AccAXLsh.
6483 // If the result is addressed indirectly, this is not a gain.
6484 if (AOP_NEEDSACC(result))
6488 D(emitcode(";", "watch me do the hambone!"););
6489 _startLazyDPSEvaluation();
6490 if (AOP_TYPE(left) == AOP_DPTR2)
6493 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6494 // get LSB in DP2_RESULT_REG.
6495 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6496 assert(!strcmp(leftByte, DP2_RESULT_REG));
6500 // get LSB into DP2_RESULT_REG
6501 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6502 if (strcmp(leftByte, DP2_RESULT_REG))
6504 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6507 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6508 assert(strcmp(leftByte, DP2_RESULT_REG));
6511 _endLazyDPSEvaluation();
6512 *lsb = DP2_RESULT_REG;
6516 if (sameRegs (AOP (result), AOP (left)) &&
6517 ((offl + MSB16) == offr))
6519 /* don't crash result[offr] */
6520 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6521 emitcode ("xch", "a,%s",
6522 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6526 movLeft2Result (left, offl, result, offr, 0);
6527 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6529 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6530 assert(strcmp(*lsb,"a"));
6535 _storeAxResults(char *lsb,
6539 _startLazyDPSEvaluation();
6540 if (AOP_NEEDSACC(result))
6542 /* We have to explicitly update the result LSB.
6544 emitcode("xch","a,%s", lsb);
6545 aopPut(AOP(result), "a", offr);
6546 emitcode("mov","a,%s", lsb);
6548 if (getDataSize (result) > 1)
6550 aopPut (AOP (result), "a", offr + MSB16);
6552 _endLazyDPSEvaluation();
6555 /*-----------------------------------------------------------------*/
6556 /* shiftL2Left2Result - shift left two bytes from left to result */
6557 /*-----------------------------------------------------------------*/
6559 shiftL2Left2Result (operand * left, int offl,
6560 operand * result, int offr, int shCount)
6564 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6566 AccAXLsh (lsb, shCount);
6568 _storeAxResults(lsb, result, offr);
6572 #ifdef BETTER_LITERAL_SHIFT
6573 /*-----------------------------------------------------------------*/
6574 /* shiftR2Left2Result - shift right two bytes from left to result */
6575 /*-----------------------------------------------------------------*/
6577 shiftR2Left2Result (operand * left, int offl,
6578 operand * result, int offr,
6579 int shCount, int sign)
6583 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6585 /* a:x >> shCount (x = lsb(result)) */
6588 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6592 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6595 _storeAxResults(lsb, result, offr);
6601 /*-----------------------------------------------------------------*/
6602 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6603 /*-----------------------------------------------------------------*/
6605 shiftLLeftOrResult (operand * left, int offl,
6606 operand * result, int offr, int shCount)
6608 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6609 /* shift left accumulator */
6611 /* or with result */
6612 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6613 /* back to result */
6614 aopPut (AOP (result), "a", offr);
6620 /*-----------------------------------------------------------------*/
6621 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6622 /*-----------------------------------------------------------------*/
6624 shiftRLeftOrResult (operand * left, int offl,
6625 operand * result, int offr, int shCount)
6627 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6628 /* shift right accumulator */
6630 /* or with result */
6631 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6632 /* back to result */
6633 aopPut (AOP (result), "a", offr);
6637 #ifdef BETTER_LITERAL_SHIFT
6638 /*-----------------------------------------------------------------*/
6639 /* genlshOne - left shift a one byte quantity by known count */
6640 /*-----------------------------------------------------------------*/
6642 genlshOne (operand * result, operand * left, int shCount)
6644 D (emitcode (";", "genlshOne "););
6645 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6649 #ifdef BETTER_LITERAL_SHIFT
6650 /*-----------------------------------------------------------------*/
6651 /* genlshTwo - left shift two bytes by known amount != 0 */
6652 /*-----------------------------------------------------------------*/
6654 genlshTwo (operand * result, operand * left, int shCount)
6658 D (emitcode (";", "genlshTwo "););
6660 size = getDataSize (result);
6662 /* if shCount >= 8 */
6667 _startLazyDPSEvaluation();
6673 _endLazyDPSEvaluation();
6674 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6675 aopPut (AOP (result), zero, LSB);
6679 movLeft2Result (left, LSB, result, MSB16, 0);
6680 aopPut (AOP (result), zero, LSB);
6681 _endLazyDPSEvaluation();
6686 aopPut (AOP (result), zero, LSB);
6687 _endLazyDPSEvaluation();
6691 /* 1 <= shCount <= 7 */
6696 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6700 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6708 /*-----------------------------------------------------------------*/
6709 /* shiftLLong - shift left one long from left to result */
6710 /* offl = LSB or MSB16 */
6711 /*-----------------------------------------------------------------*/
6713 shiftLLong (operand * left, operand * result, int offr)
6716 int size = AOP_SIZE (result);
6718 if (size >= LSB + offr)
6720 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6722 emitcode ("add", "a,acc");
6723 if (sameRegs (AOP (left), AOP (result)) &&
6724 size >= MSB16 + offr && offr != LSB)
6725 emitcode ("xch", "a,%s",
6726 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6728 aopPut (AOP (result), "a", LSB + offr);
6731 if (size >= MSB16 + offr)
6733 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6735 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6738 emitcode ("rlc", "a");
6739 if (sameRegs (AOP (left), AOP (result)) &&
6740 size >= MSB24 + offr && offr != LSB)
6741 emitcode ("xch", "a,%s",
6742 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6744 aopPut (AOP (result), "a", MSB16 + offr);
6747 if (size >= MSB24 + offr)
6749 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6751 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6754 emitcode ("rlc", "a");
6755 if (sameRegs (AOP (left), AOP (result)) &&
6756 size >= MSB32 + offr && offr != LSB)
6757 emitcode ("xch", "a,%s",
6758 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6760 aopPut (AOP (result), "a", MSB24 + offr);
6763 if (size > MSB32 + offr)
6765 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6767 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6770 emitcode ("rlc", "a");
6771 aopPut (AOP (result), "a", MSB32 + offr);
6774 aopPut (AOP (result), zero, LSB);
6780 /*-----------------------------------------------------------------*/
6781 /* genlshFour - shift four byte by a known amount != 0 */
6782 /*-----------------------------------------------------------------*/
6784 genlshFour (operand * result, operand * left, int shCount)
6788 D (emitcode (";", "genlshFour ");
6791 size = AOP_SIZE (result);
6793 /* if shifting more that 3 bytes */
6798 /* lowest order of left goes to the highest
6799 order of the destination */
6800 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6802 movLeft2Result (left, LSB, result, MSB32, 0);
6803 aopPut (AOP (result), zero, LSB);
6804 aopPut (AOP (result), zero, MSB16);
6805 aopPut (AOP (result), zero, MSB24);
6809 /* more than two bytes */
6810 else if (shCount >= 16)
6812 /* lower order two bytes goes to higher order two bytes */
6814 /* if some more remaining */
6816 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6819 movLeft2Result (left, MSB16, result, MSB32, 0);
6820 movLeft2Result (left, LSB, result, MSB24, 0);
6822 aopPut (AOP (result), zero, MSB16);
6823 aopPut (AOP (result), zero, LSB);
6827 /* if more than 1 byte */
6828 else if (shCount >= 8)
6830 /* lower order three bytes goes to higher order three bytes */
6835 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6837 movLeft2Result (left, LSB, result, MSB16, 0);
6843 movLeft2Result (left, MSB24, result, MSB32, 0);
6844 movLeft2Result (left, MSB16, result, MSB24, 0);
6845 movLeft2Result (left, LSB, result, MSB16, 0);
6846 aopPut (AOP (result), zero, LSB);
6848 else if (shCount == 1)
6849 shiftLLong (left, result, MSB16);
6852 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6853 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6854 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6855 aopPut (AOP (result), zero, LSB);
6860 /* 1 <= shCount <= 7 */
6861 else if (shCount <= 2)
6863 shiftLLong (left, result, LSB);
6865 shiftLLong (result, result, LSB);
6867 /* 3 <= shCount <= 7, optimize */
6870 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6871 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6872 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6877 #ifdef BETTER_LITERAL_SHIFT
6878 /*-----------------------------------------------------------------*/
6879 /* genLeftShiftLiteral - left shifting by known count */
6880 /*-----------------------------------------------------------------*/
6882 genLeftShiftLiteral (operand * left,
6887 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6890 size = getSize (operandType (result));
6892 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6894 /* We only handle certain easy cases so far. */
6896 && (shCount < (size * 8))
6900 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6904 freeAsmop (right, NULL, ic, TRUE);
6906 aopOp(left, ic, FALSE, FALSE);
6907 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6910 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6912 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6913 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6915 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6918 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6920 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6921 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6923 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6929 emitcode ("; shift left ", "result %d, left %d", size,
6933 /* I suppose that the left size >= result size */
6936 _startLazyDPSEvaluation();
6939 movLeft2Result (left, size, result, size, 0);
6941 _endLazyDPSEvaluation();
6943 else if (shCount >= (size * 8))
6945 _startLazyDPSEvaluation();
6948 aopPut (AOP (result), zero, size);
6950 _endLazyDPSEvaluation();
6957 genlshOne (result, left, shCount);
6961 genlshTwo (result, left, shCount);
6965 genlshFour (result, left, shCount);
6969 fprintf(stderr, "*** ack! mystery literal shift!\n");
6973 freeAsmop (left, NULL, ic, TRUE);
6974 freeAsmop (result, NULL, ic, TRUE);
6979 /*-----------------------------------------------------------------*/
6980 /* genLeftShift - generates code for left shifting */
6981 /*-----------------------------------------------------------------*/
6983 genLeftShift (iCode * ic)
6985 operand *left, *right, *result;
6988 symbol *tlbl, *tlbl1;
6990 D (emitcode (";", "genLeftShift "););
6992 right = IC_RIGHT (ic);
6993 left = IC_LEFT (ic);
6994 result = IC_RESULT (ic);
6996 aopOp (right, ic, FALSE, FALSE);
6999 #ifdef BETTER_LITERAL_SHIFT
7000 /* if the shift count is known then do it
7001 as efficiently as possible */
7002 if (AOP_TYPE (right) == AOP_LIT)
7004 if (genLeftShiftLiteral (left, right, result, ic))
7011 /* shift count is unknown then we have to form
7012 a loop get the loop count in B : Note: we take
7013 only the lower order byte since shifting
7014 more that 32 bits make no sense anyway, ( the
7015 largest size of an object can be only 32 bits ) */
7017 if (AOP_TYPE (right) == AOP_LIT)
7019 /* Really should be handled by genLeftShiftLiteral,
7020 * but since I'm too lazy to fix that today, at least we can make
7021 * some small improvement.
7023 emitcode("mov", "b,#0x%02x",
7024 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7028 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7029 emitcode ("inc", "b");
7031 freeAsmop (right, NULL, ic, TRUE);
7032 aopOp (left, ic, FALSE, FALSE);
7033 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7035 /* now move the left to the result if they are not the
7037 if (!sameRegs (AOP (left), AOP (result)) &&
7038 AOP_SIZE (result) > 1)
7041 size = AOP_SIZE (result);
7043 _startLazyDPSEvaluation ();
7046 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7047 if (*l == '@' && (IS_AOP_PREG (result)))
7050 emitcode ("mov", "a,%s", l);
7051 aopPut (AOP (result), "a", offset);
7054 aopPut (AOP (result), l, offset);
7057 _endLazyDPSEvaluation ();
7060 tlbl = newiTempLabel (NULL);
7061 size = AOP_SIZE (result);
7063 tlbl1 = newiTempLabel (NULL);
7065 /* if it is only one byte then */
7068 symbol *tlbl1 = newiTempLabel (NULL);
7070 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7072 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7073 emitcode ("", "%05d$:", tlbl->key + 100);
7074 emitcode ("add", "a,acc");
7075 emitcode ("", "%05d$:", tlbl1->key + 100);
7076 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7077 aopPut (AOP (result), "a", 0);
7081 reAdjustPreg (AOP (result));
7083 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7084 emitcode ("", "%05d$:", tlbl->key + 100);
7085 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7087 emitcode ("add", "a,acc");
7088 aopPut (AOP (result), "a", offset++);
7089 _startLazyDPSEvaluation ();
7092 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7094 emitcode ("rlc", "a");
7095 aopPut (AOP (result), "a", offset++);
7097 _endLazyDPSEvaluation ();
7098 reAdjustPreg (AOP (result));
7100 emitcode ("", "%05d$:", tlbl1->key + 100);
7101 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7103 freeAsmop (left, NULL, ic, TRUE);
7104 freeAsmop (result, NULL, ic, TRUE);
7107 #ifdef BETTER_LITERAL_SHIFT
7108 /*-----------------------------------------------------------------*/
7109 /* genrshOne - right shift a one byte quantity by known count */
7110 /*-----------------------------------------------------------------*/
7112 genrshOne (operand * result, operand * left,
7113 int shCount, int sign)
7115 D (emitcode (";", "genrshOne"););
7116 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7120 #ifdef BETTER_LITERAL_SHIFT
7121 /*-----------------------------------------------------------------*/
7122 /* genrshTwo - right shift two bytes by known amount != 0 */
7123 /*-----------------------------------------------------------------*/
7125 genrshTwo (operand * result, operand * left,
7126 int shCount, int sign)
7128 D (emitcode (";", "genrshTwo"););
7130 /* if shCount >= 8 */
7134 _startLazyDPSEvaluation();
7137 shiftR1Left2Result (left, MSB16, result, LSB,
7142 movLeft2Result (left, MSB16, result, LSB, sign);
7144 addSign (result, MSB16, sign);
7145 _endLazyDPSEvaluation();
7148 /* 1 <= shCount <= 7 */
7151 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7158 /*-----------------------------------------------------------------*/
7159 /* shiftRLong - shift right one long from left to result */
7160 /* offl = LSB or MSB16 */
7161 /*-----------------------------------------------------------------*/
7163 shiftRLong (operand * left, int offl,
7164 operand * result, int sign)
7167 emitcode ("clr", "c");
7168 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7170 emitcode ("mov", "c,acc.7");
7171 emitcode ("rrc", "a");
7172 aopPut (AOP (result), "a", MSB32 - offl);
7174 /* add sign of "a" */
7175 addSign (result, MSB32, sign);
7177 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7178 emitcode ("rrc", "a");
7179 aopPut (AOP (result), "a", MSB24 - offl);
7181 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7182 emitcode ("rrc", "a");
7183 aopPut (AOP (result), "a", MSB16 - offl);
7187 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7188 emitcode ("rrc", "a");
7189 aopPut (AOP (result), "a", LSB);
7196 /*-----------------------------------------------------------------*/
7197 /* genrshFour - shift four byte by a known amount != 0 */
7198 /*-----------------------------------------------------------------*/
7200 genrshFour (operand * result, operand * left,
7201 int shCount, int sign)
7203 D (emitcode (";", "genrshFour");
7206 /* if shifting more that 3 bytes */
7211 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7213 movLeft2Result (left, MSB32, result, LSB, sign);
7214 addSign (result, MSB16, sign);
7216 else if (shCount >= 16)
7220 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7223 movLeft2Result (left, MSB24, result, LSB, 0);
7224 movLeft2Result (left, MSB32, result, MSB16, sign);
7226 addSign (result, MSB24, sign);
7228 else if (shCount >= 8)
7232 shiftRLong (left, MSB16, result, sign);
7233 else if (shCount == 0)
7235 movLeft2Result (left, MSB16, result, LSB, 0);
7236 movLeft2Result (left, MSB24, result, MSB16, 0);
7237 movLeft2Result (left, MSB32, result, MSB24, sign);
7238 addSign (result, MSB32, sign);
7242 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7243 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7244 /* the last shift is signed */
7245 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7246 addSign (result, MSB32, sign);
7250 { /* 1 <= shCount <= 7 */
7253 shiftRLong (left, LSB, result, sign);
7255 shiftRLong (result, LSB, result, sign);
7259 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7260 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7261 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7267 #ifdef BETTER_LITERAL_SHIFT
7268 /*-----------------------------------------------------------------*/
7269 /* genRightShiftLiteral - right shifting by known count */
7270 /*-----------------------------------------------------------------*/
7272 genRightShiftLiteral (operand * left,
7278 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7281 size = getSize (operandType (result));
7283 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7285 /* We only handle certain easy cases so far. */
7287 && (shCount < (size * 8))
7291 D(emitcode (";", "genRightShiftLiteral wimping out"););
7295 freeAsmop (right, NULL, ic, TRUE);
7297 aopOp (left, ic, FALSE, FALSE);
7298 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7301 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7305 /* test the LEFT size !!! */
7307 /* I suppose that the left size >= result size */
7310 size = getDataSize (result);
7311 _startLazyDPSEvaluation();
7314 movLeft2Result (left, size, result, size, 0);
7316 _endLazyDPSEvaluation();
7318 else if (shCount >= (size * 8))
7322 /* get sign in acc.7 */
7323 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7325 addSign (result, LSB, sign);
7332 genrshOne (result, left, shCount, sign);
7336 genrshTwo (result, left, shCount, sign);
7340 genrshFour (result, left, shCount, sign);
7347 freeAsmop (left, NULL, ic, TRUE);
7348 freeAsmop (result, NULL, ic, TRUE);
7354 /*-----------------------------------------------------------------*/
7355 /* genSignedRightShift - right shift of signed number */
7356 /*-----------------------------------------------------------------*/
7358 genSignedRightShift (iCode * ic)
7360 operand *right, *left, *result;
7363 symbol *tlbl, *tlbl1;
7365 D (emitcode (";", "genSignedRightShift "););
7367 /* we do it the hard way put the shift count in b
7368 and loop thru preserving the sign */
7370 right = IC_RIGHT (ic);
7371 left = IC_LEFT (ic);
7372 result = IC_RESULT (ic);
7374 aopOp (right, ic, FALSE, FALSE);
7376 #ifdef BETTER_LITERAL_SHIFT
7377 if (AOP_TYPE (right) == AOP_LIT)
7379 if (genRightShiftLiteral (left, right, result, ic, 1))
7385 /* shift count is unknown then we have to form
7386 a loop get the loop count in B : Note: we take
7387 only the lower order byte since shifting
7388 more that 32 bits make no sense anyway, ( the
7389 largest size of an object can be only 32 bits ) */
7391 if (AOP_TYPE (right) == AOP_LIT)
7393 /* Really should be handled by genRightShiftLiteral,
7394 * but since I'm too lazy to fix that today, at least we can make
7395 * some small improvement.
7397 emitcode("mov", "b,#0x%02x",
7398 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7402 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7403 emitcode ("inc", "b");
7405 freeAsmop (right, NULL, ic, TRUE);
7406 aopOp (left, ic, FALSE, FALSE);
7407 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7409 /* now move the left to the result if they are not the
7411 if (!sameRegs (AOP (left), AOP (result)) &&
7412 AOP_SIZE (result) > 1)
7415 size = AOP_SIZE (result);
7417 _startLazyDPSEvaluation ();
7420 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7421 if (*l == '@' && IS_AOP_PREG (result))
7424 emitcode ("mov", "a,%s", l);
7425 aopPut (AOP (result), "a", offset);
7428 aopPut (AOP (result), l, offset);
7431 _endLazyDPSEvaluation ();
7434 /* mov the highest order bit to OVR */
7435 tlbl = newiTempLabel (NULL);
7436 tlbl1 = newiTempLabel (NULL);
7438 size = AOP_SIZE (result);
7440 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7441 emitcode ("rlc", "a");
7442 emitcode ("mov", "ov,c");
7443 /* if it is only one byte then */
7446 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7448 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7449 emitcode ("", "%05d$:", tlbl->key + 100);
7450 emitcode ("mov", "c,ov");
7451 emitcode ("rrc", "a");
7452 emitcode ("", "%05d$:", tlbl1->key + 100);
7453 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7454 aopPut (AOP (result), "a", 0);
7458 reAdjustPreg (AOP (result));
7459 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7460 emitcode ("", "%05d$:", tlbl->key + 100);
7461 emitcode ("mov", "c,ov");
7462 _startLazyDPSEvaluation ();
7465 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7467 emitcode ("rrc", "a");
7468 aopPut (AOP (result), "a", offset--);
7470 _endLazyDPSEvaluation ();
7471 reAdjustPreg (AOP (result));
7472 emitcode ("", "%05d$:", tlbl1->key + 100);
7473 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7476 freeAsmop (left, NULL, ic, TRUE);
7477 freeAsmop (result, NULL, ic, TRUE);
7480 /*-----------------------------------------------------------------*/
7481 /* genRightShift - generate code for right shifting */
7482 /*-----------------------------------------------------------------*/
7484 genRightShift (iCode * ic)
7486 operand *right, *left, *result;
7490 symbol *tlbl, *tlbl1;
7492 D (emitcode (";", "genRightShift "););
7494 /* if signed then we do it the hard way preserve the
7495 sign bit moving it inwards */
7496 retype = getSpec (operandType (IC_RESULT (ic)));
7498 if (!SPEC_USIGN (retype))
7500 genSignedRightShift (ic);
7504 /* signed & unsigned types are treated the same : i.e. the
7505 signed is NOT propagated inwards : quoting from the
7506 ANSI - standard : "for E1 >> E2, is equivalent to division
7507 by 2**E2 if unsigned or if it has a non-negative value,
7508 otherwise the result is implementation defined ", MY definition
7509 is that the sign does not get propagated */
7511 right = IC_RIGHT (ic);
7512 left = IC_LEFT (ic);
7513 result = IC_RESULT (ic);
7515 aopOp (right, ic, FALSE, FALSE);
7517 #ifdef BETTER_LITERAL_SHIFT
7518 /* if the shift count is known then do it
7519 as efficiently as possible */
7520 if (AOP_TYPE (right) == AOP_LIT)
7522 if (genRightShiftLiteral (left, right, result, ic, 0))
7529 /* shift count is unknown then we have to form
7530 a loop get the loop count in B : Note: we take
7531 only the lower order byte since shifting
7532 more that 32 bits make no sense anyway, ( the
7533 largest size of an object can be only 32 bits ) */
7535 if (AOP_TYPE (right) == AOP_LIT)
7537 /* Really should be handled by genRightShiftLiteral,
7538 * but since I'm too lazy to fix that today, at least we can make
7539 * some small improvement.
7541 emitcode("mov", "b,#0x%02x",
7542 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7546 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7547 emitcode ("inc", "b");
7549 freeAsmop (right, NULL, ic, TRUE);
7550 aopOp (left, ic, FALSE, FALSE);
7551 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7553 /* now move the left to the result if they are not the
7555 if (!sameRegs (AOP (left), AOP (result)) &&
7556 AOP_SIZE (result) > 1)
7559 size = AOP_SIZE (result);
7561 _startLazyDPSEvaluation ();
7564 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7565 if (*l == '@' && IS_AOP_PREG (result))
7568 emitcode ("mov", "a,%s", l);
7569 aopPut (AOP (result), "a", offset);
7572 aopPut (AOP (result), l, offset);
7575 _endLazyDPSEvaluation ();
7578 tlbl = newiTempLabel (NULL);
7579 tlbl1 = newiTempLabel (NULL);
7580 size = AOP_SIZE (result);
7583 /* if it is only one byte then */
7586 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7588 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7589 emitcode ("", "%05d$:", tlbl->key + 100);
7591 emitcode ("rrc", "a");
7592 emitcode ("", "%05d$:", tlbl1->key + 100);
7593 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7594 aopPut (AOP (result), "a", 0);
7598 reAdjustPreg (AOP (result));
7599 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7600 emitcode ("", "%05d$:", tlbl->key + 100);
7602 _startLazyDPSEvaluation ();
7605 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7607 emitcode ("rrc", "a");
7608 aopPut (AOP (result), "a", offset--);
7610 _endLazyDPSEvaluation ();
7611 reAdjustPreg (AOP (result));
7613 emitcode ("", "%05d$:", tlbl1->key + 100);
7614 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7617 freeAsmop (left, NULL, ic, TRUE);
7618 freeAsmop (result, NULL, ic, TRUE);
7621 /*-----------------------------------------------------------------*/
7622 /* genUnpackBits - generates code for unpacking bits */
7623 /*-----------------------------------------------------------------*/
7625 genUnpackBits (operand * result, char *rname, int ptype)
7632 D (emitcode (";", "genUnpackBits ");
7635 etype = getSpec (operandType (result));
7637 /* read the first byte */
7643 emitcode ("mov", "a,@%s", rname);
7647 emitcode ("movx", "a,@%s", rname);
7651 emitcode ("movx", "a,@dptr");
7655 emitcode ("clr", "a");
7656 emitcode ("movc", "a", "@a+dptr");
7660 emitcode ("lcall", "__gptrget");
7664 /* if we have bitdisplacement then it fits */
7665 /* into this byte completely or if length is */
7666 /* less than a byte */
7667 if ((shCnt = SPEC_BSTR (etype)) ||
7668 (SPEC_BLEN (etype) <= 8))
7671 /* shift right acc */
7674 emitcode ("anl", "a,#0x%02x",
7675 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7676 aopPut (AOP (result), "a", offset);
7680 /* bit field did not fit in a byte */
7681 rlen = SPEC_BLEN (etype) - 8;
7682 aopPut (AOP (result), "a", offset++);
7691 emitcode ("inc", "%s", rname);
7692 emitcode ("mov", "a,@%s", rname);
7696 emitcode ("inc", "%s", rname);
7697 emitcode ("movx", "a,@%s", rname);
7701 emitcode ("inc", "dptr");
7702 emitcode ("movx", "a,@dptr");
7706 emitcode ("clr", "a");
7707 emitcode ("inc", "dptr");
7708 emitcode ("movc", "a", "@a+dptr");
7712 emitcode ("inc", "dptr");
7713 emitcode ("lcall", "__gptrget");
7718 /* if we are done */
7722 aopPut (AOP (result), "a", offset++);
7728 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7729 aopPut (AOP (result), "a", offset);
7736 /*-----------------------------------------------------------------*/
7737 /* genDataPointerGet - generates code when ptr offset is known */
7738 /*-----------------------------------------------------------------*/
7740 genDataPointerGet (operand * left,
7746 int size, offset = 0;
7747 aopOp (result, ic, TRUE, FALSE);
7749 /* get the string representation of the name */
7750 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7751 size = AOP_SIZE (result);
7752 _startLazyDPSEvaluation ();
7756 sprintf (buffer, "(%s + %d)", l + 1, offset);
7758 sprintf (buffer, "%s", l + 1);
7759 aopPut (AOP (result), buffer, offset++);
7761 _endLazyDPSEvaluation ();
7763 freeAsmop (left, NULL, ic, TRUE);
7764 freeAsmop (result, NULL, ic, TRUE);
7767 /*-----------------------------------------------------------------*/
7768 /* genNearPointerGet - emitcode for near pointer fetch */
7769 /*-----------------------------------------------------------------*/
7771 genNearPointerGet (operand * left,
7778 sym_link *rtype, *retype, *letype;
7779 sym_link *ltype = operandType (left);
7782 rtype = operandType (result);
7783 retype = getSpec (rtype);
7784 letype = getSpec (ltype);
7786 aopOp (left, ic, FALSE, FALSE);
7788 /* if left is rematerialisable and
7789 result is not bit variable type and
7790 the left is pointer to data space i.e
7791 lower 128 bytes of space */
7792 if (AOP_TYPE (left) == AOP_IMMD &&
7793 !IS_BITVAR (retype) &&
7794 !IS_BITVAR (letype) &&
7795 DCL_TYPE (ltype) == POINTER)
7797 genDataPointerGet (left, result, ic);
7801 /* if the value is already in a pointer register
7802 then don't need anything more */
7803 if (!AOP_INPREG (AOP (left)))
7805 /* otherwise get a free pointer register */
7807 preg = getFreePtr (ic, &aop, FALSE);
7808 emitcode ("mov", "%s,%s",
7810 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7814 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7816 freeAsmop (left, NULL, ic, TRUE);
7817 aopOp (result, ic, FALSE, FALSE);
7819 /* if bitfield then unpack the bits */
7820 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7821 genUnpackBits (result, rname, POINTER);
7824 /* we have can just get the values */
7825 int size = AOP_SIZE (result);
7830 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7833 emitcode ("mov", "a,@%s", rname);
7834 aopPut (AOP (result), "a", offset);
7838 sprintf (buffer, "@%s", rname);
7839 aopPut (AOP (result), buffer, offset);
7843 emitcode ("inc", "%s", rname);
7847 /* now some housekeeping stuff */
7850 /* we had to allocate for this iCode */
7851 freeAsmop (NULL, aop, ic, TRUE);
7855 /* we did not allocate which means left
7856 already in a pointer register, then
7857 if size > 0 && this could be used again
7858 we have to point it back to where it
7860 if (AOP_SIZE (result) > 1 &&
7861 !OP_SYMBOL (left)->remat &&
7862 (OP_SYMBOL (left)->liveTo > ic->seq ||
7865 int size = AOP_SIZE (result) - 1;
7867 emitcode ("dec", "%s", rname);
7872 freeAsmop (result, NULL, ic, TRUE);
7876 /*-----------------------------------------------------------------*/
7877 /* genPagedPointerGet - emitcode for paged pointer fetch */
7878 /*-----------------------------------------------------------------*/
7880 genPagedPointerGet (operand * left,
7887 sym_link *rtype, *retype, *letype;
7889 rtype = operandType (result);
7890 retype = getSpec (rtype);
7891 letype = getSpec (operandType (left));
7892 aopOp (left, ic, FALSE, FALSE);
7894 /* if the value is already in a pointer register
7895 then don't need anything more */
7896 if (!AOP_INPREG (AOP (left)))
7898 /* otherwise get a free pointer register */
7900 preg = getFreePtr (ic, &aop, FALSE);
7901 emitcode ("mov", "%s,%s",
7903 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7907 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7909 freeAsmop (left, NULL, ic, TRUE);
7910 aopOp (result, ic, FALSE, FALSE);
7912 /* if bitfield then unpack the bits */
7913 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7914 genUnpackBits (result, rname, PPOINTER);
7917 /* we have can just get the values */
7918 int size = AOP_SIZE (result);
7924 emitcode ("movx", "a,@%s", rname);
7925 aopPut (AOP (result), "a", offset);
7930 emitcode ("inc", "%s", rname);
7934 /* now some housekeeping stuff */
7937 /* we had to allocate for this iCode */
7938 freeAsmop (NULL, aop, ic, TRUE);
7942 /* we did not allocate which means left
7943 already in a pointer register, then
7944 if size > 0 && this could be used again
7945 we have to point it back to where it
7947 if (AOP_SIZE (result) > 1 &&
7948 !OP_SYMBOL (left)->remat &&
7949 (OP_SYMBOL (left)->liveTo > ic->seq ||
7952 int size = AOP_SIZE (result) - 1;
7954 emitcode ("dec", "%s", rname);
7959 freeAsmop (result, NULL, ic, TRUE);
7964 /*-----------------------------------------------------------------*/
7965 /* genFarPointerGet - gget value from far space */
7966 /*-----------------------------------------------------------------*/
7968 genFarPointerGet (operand * left,
7969 operand * result, iCode * ic)
7972 sym_link *retype = getSpec (operandType (result));
7973 sym_link *letype = getSpec (operandType (left));
7974 D (emitcode (";", "genFarPointerGet");
7977 aopOp (left, ic, FALSE, FALSE);
7979 /* if the operand is already in dptr
7980 then we do nothing else we move the value to dptr */
7981 if (AOP_TYPE (left) != AOP_STR)
7983 /* if this is remateriazable */
7984 if (AOP_TYPE (left) == AOP_IMMD)
7986 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7990 /* we need to get it byte by byte */
7991 _startLazyDPSEvaluation ();
7992 if (AOP_TYPE (left) != AOP_DPTR)
7994 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7995 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7996 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8000 /* We need to generate a load to DPTR indirect through DPTR. */
8001 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8003 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8004 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8005 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8006 emitcode ("pop", "dph");
8007 emitcode ("pop", "dpl");
8009 _endLazyDPSEvaluation ();
8012 /* so dptr know contains the address */
8013 freeAsmop (left, NULL, ic, TRUE);
8014 aopOp (result, ic, FALSE, TRUE);
8016 /* if bit then unpack */
8017 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8018 genUnpackBits (result, "dptr", FPOINTER);
8021 size = AOP_SIZE (result);
8024 _startLazyDPSEvaluation ();
8031 emitcode ("movx", "a,@dptr");
8033 emitcode ("inc", "dptr");
8035 aopPut (AOP (result), "a", offset++);
8037 _endLazyDPSEvaluation ();
8040 freeAsmop (result, NULL, ic, TRUE);
8043 /*-----------------------------------------------------------------*/
8044 /* emitcodePointerGet - gget value from code space */
8045 /*-----------------------------------------------------------------*/
8047 emitcodePointerGet (operand * left,
8048 operand * result, iCode * ic)
8051 sym_link *retype = getSpec (operandType (result));
8053 aopOp (left, ic, FALSE, FALSE);
8055 /* if the operand is already in dptr
8056 then we do nothing else we move the value to dptr */
8057 if (AOP_TYPE (left) != AOP_STR)
8059 /* if this is remateriazable */
8060 if (AOP_TYPE (left) == AOP_IMMD)
8062 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8065 { /* we need to get it byte by byte */
8066 _startLazyDPSEvaluation ();
8067 if (AOP_TYPE (left) != AOP_DPTR)
8069 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8070 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8071 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8075 /* We need to generate a load to DPTR indirect through DPTR. */
8076 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8078 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8079 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8080 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8081 emitcode ("pop", "dph");
8082 emitcode ("pop", "dpl");
8084 _endLazyDPSEvaluation ();
8087 /* so dptr know contains the address */
8088 freeAsmop (left, NULL, ic, TRUE);
8089 aopOp (result, ic, FALSE, TRUE);
8091 /* if bit then unpack */
8092 if (IS_BITVAR (retype))
8093 genUnpackBits (result, "dptr", CPOINTER);
8096 size = AOP_SIZE (result);
8099 _startLazyDPSEvaluation ();
8105 emitcode ("clr", "a");
8106 emitcode ("movc", "a,@a+dptr");
8108 emitcode ("inc", "dptr");
8109 aopPut (AOP (result), "a", offset++);
8111 _endLazyDPSEvaluation ();
8114 freeAsmop (result, NULL, ic, TRUE);
8117 /*-----------------------------------------------------------------*/
8118 /* genGenPointerGet - gget value from generic pointer space */
8119 /*-----------------------------------------------------------------*/
8121 genGenPointerGet (operand * left,
8122 operand * result, iCode * ic)
8125 sym_link *retype = getSpec (operandType (result));
8126 sym_link *letype = getSpec (operandType (left));
8128 D (emitcode (";", "genGenPointerGet "); );
8130 aopOp (left, ic, FALSE, TRUE);
8132 /* if the operand is already in dptr
8133 then we do nothing else we move the value to dptr */
8134 if (AOP_TYPE (left) != AOP_STR)
8136 /* if this is remateriazable */
8137 if (AOP_TYPE (left) == AOP_IMMD)
8139 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8140 emitcode ("mov", "b,#%d", pointerCode (retype));
8143 { /* we need to get it byte by byte */
8144 _startLazyDPSEvaluation ();
8145 if (AOP(left)->type==AOP_DPTR2) {
8147 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8150 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
8151 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8154 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
8155 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8158 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
8159 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8161 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8162 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8163 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8164 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8166 _endLazyDPSEvaluation ();
8169 /* so dptr know contains the address */
8170 freeAsmop (left, NULL, ic, TRUE);
8171 aopOp (result, ic, FALSE, TRUE);
8173 /* if bit then unpack */
8174 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8175 genUnpackBits (result, "dptr", GPOINTER);
8178 size = AOP_SIZE (result);
8183 emitcode ("lcall", "__gptrget");
8184 aopPut (AOP (result), "a", offset++);
8186 emitcode ("inc", "dptr");
8190 freeAsmop (result, NULL, ic, TRUE);
8193 /*-----------------------------------------------------------------*/
8194 /* genPointerGet - generate code for pointer get */
8195 /*-----------------------------------------------------------------*/
8197 genPointerGet (iCode * ic)
8199 operand *left, *result;
8200 sym_link *type, *etype;
8203 D (emitcode (";", "genPointerGet ");
8206 left = IC_LEFT (ic);
8207 result = IC_RESULT (ic);
8209 /* depending on the type of pointer we need to
8210 move it to the correct pointer register */
8211 type = operandType (left);
8212 etype = getSpec (type);
8213 /* if left is of type of pointer then it is simple */
8214 if (IS_PTR (type) && !IS_FUNC (type->next))
8215 p_type = DCL_TYPE (type);
8218 /* we have to go by the storage class */
8219 p_type = PTR_TYPE (SPEC_OCLS (etype));
8222 /* now that we have the pointer type we assign
8223 the pointer values */
8229 genNearPointerGet (left, result, ic);
8233 genPagedPointerGet (left, result, ic);
8237 genFarPointerGet (left, result, ic);
8241 emitcodePointerGet (left, result, ic);
8245 genGenPointerGet (left, result, ic);
8251 /*-----------------------------------------------------------------*/
8252 /* genPackBits - generates code for packed bit storage */
8253 /*-----------------------------------------------------------------*/
8255 genPackBits (sym_link * etype,
8257 char *rname, int p_type)
8265 blen = SPEC_BLEN (etype);
8266 bstr = SPEC_BSTR (etype);
8268 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8271 /* if the bit lenth is less than or */
8272 /* it exactly fits a byte then */
8273 if (SPEC_BLEN (etype) <= 8)
8275 shCount = SPEC_BSTR (etype);
8277 /* shift left acc */
8280 if (SPEC_BLEN (etype) < 8)
8281 { /* if smaller than a byte */
8287 emitcode ("mov", "b,a");
8288 emitcode ("mov", "a,@%s", rname);
8292 emitcode ("mov", "b,a");
8293 emitcode ("movx", "a,@dptr");
8297 emitcode ("push", "b");
8298 emitcode ("push", "acc");
8299 emitcode ("lcall", "__gptrget");
8300 emitcode ("pop", "b");
8304 emitcode ("anl", "a,#0x%02x", (unsigned char)
8305 ((unsigned char) (0xFF << (blen + bstr)) |
8306 (unsigned char) (0xFF >> (8 - bstr))));
8307 emitcode ("orl", "a,b");
8308 if (p_type == GPOINTER)
8309 emitcode ("pop", "b");
8316 emitcode ("mov", "@%s,a", rname);
8320 emitcode ("movx", "@dptr,a");
8324 emitcode ("lcall", "__gptrput");
8329 if (SPEC_BLEN (etype) <= 8)
8332 emitcode ("inc", "%s", rname);
8333 rLen = SPEC_BLEN (etype);
8335 /* now generate for lengths greater than one byte */
8339 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8351 emitcode ("mov", "@%s,a", rname);
8354 emitcode ("mov", "@%s,%s", rname, l);
8359 emitcode ("movx", "@dptr,a");
8364 emitcode ("lcall", "__gptrput");
8367 emitcode ("inc", "%s", rname);
8372 /* last last was not complete */
8375 /* save the byte & read byte */
8379 emitcode ("mov", "b,a");
8380 emitcode ("mov", "a,@%s", rname);
8384 emitcode ("mov", "b,a");
8385 emitcode ("movx", "a,@dptr");
8389 emitcode ("push", "b");
8390 emitcode ("push", "acc");
8391 emitcode ("lcall", "__gptrget");
8392 emitcode ("pop", "b");
8396 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8397 emitcode ("orl", "a,b");
8400 if (p_type == GPOINTER)
8401 emitcode ("pop", "b");
8407 emitcode ("mov", "@%s,a", rname);
8411 emitcode ("movx", "@dptr,a");
8415 emitcode ("lcall", "__gptrput");
8419 /*-----------------------------------------------------------------*/
8420 /* genDataPointerSet - remat pointer to data space */
8421 /*-----------------------------------------------------------------*/
8423 genDataPointerSet (operand * right,
8427 int size, offset = 0;
8428 char *l, buffer[256];
8430 aopOp (right, ic, FALSE, FALSE);
8432 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8433 size = AOP_SIZE (right);
8437 sprintf (buffer, "(%s + %d)", l + 1, offset);
8439 sprintf (buffer, "%s", l + 1);
8440 emitcode ("mov", "%s,%s", buffer,
8441 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8444 freeAsmop (right, NULL, ic, TRUE);
8445 freeAsmop (result, NULL, ic, TRUE);
8448 /*-----------------------------------------------------------------*/
8449 /* genNearPointerSet - emitcode for near pointer put */
8450 /*-----------------------------------------------------------------*/
8452 genNearPointerSet (operand * right,
8459 sym_link *retype, *letype;
8460 sym_link *ptype = operandType (result);
8462 retype = getSpec (operandType (right));
8463 letype = getSpec (ptype);
8465 aopOp (result, ic, FALSE, FALSE);
8467 /* if the result is rematerializable &
8468 in data space & not a bit variable */
8469 if (AOP_TYPE (result) == AOP_IMMD &&
8470 DCL_TYPE (ptype) == POINTER &&
8471 !IS_BITVAR (retype) &&
8472 !IS_BITVAR (letype))
8474 genDataPointerSet (right, result, ic);
8478 /* if the value is already in a pointer register
8479 then don't need anything more */
8480 if (!AOP_INPREG (AOP (result)))
8482 /* otherwise get a free pointer register */
8484 preg = getFreePtr (ic, &aop, FALSE);
8485 emitcode ("mov", "%s,%s",
8487 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8491 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8493 freeAsmop (result, NULL, ic, TRUE);
8494 aopOp (right, ic, FALSE, FALSE);
8496 /* if bitfield then unpack the bits */
8497 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8498 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8501 /* we have can just get the values */
8502 int size = AOP_SIZE (right);
8507 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8511 emitcode ("mov", "@%s,a", rname);
8514 emitcode ("mov", "@%s,%s", rname, l);
8516 emitcode ("inc", "%s", rname);
8521 /* now some housekeeping stuff */
8524 /* we had to allocate for this iCode */
8525 freeAsmop (NULL, aop, ic, TRUE);
8529 /* we did not allocate which means left
8530 already in a pointer register, then
8531 if size > 0 && this could be used again
8532 we have to point it back to where it
8534 if (AOP_SIZE (right) > 1 &&
8535 !OP_SYMBOL (result)->remat &&
8536 (OP_SYMBOL (result)->liveTo > ic->seq ||
8539 int size = AOP_SIZE (right) - 1;
8541 emitcode ("dec", "%s", rname);
8546 freeAsmop (right, NULL, ic, TRUE);
8551 /*-----------------------------------------------------------------*/
8552 /* genPagedPointerSet - emitcode for Paged pointer put */
8553 /*-----------------------------------------------------------------*/
8555 genPagedPointerSet (operand * right,
8562 sym_link *retype, *letype;
8564 retype = getSpec (operandType (right));
8565 letype = getSpec (operandType (result));
8567 aopOp (result, ic, FALSE, FALSE);
8569 /* if the value is already in a pointer register
8570 then don't need anything more */
8571 if (!AOP_INPREG (AOP (result)))
8573 /* otherwise get a free pointer register */
8575 preg = getFreePtr (ic, &aop, FALSE);
8576 emitcode ("mov", "%s,%s",
8578 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8582 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8584 freeAsmop (result, NULL, ic, TRUE);
8585 aopOp (right, ic, FALSE, FALSE);
8587 /* if bitfield then unpack the bits */
8588 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8589 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8592 /* we have can just get the values */
8593 int size = AOP_SIZE (right);
8598 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8601 emitcode ("movx", "@%s,a", rname);
8604 emitcode ("inc", "%s", rname);
8610 /* now some housekeeping stuff */
8613 /* we had to allocate for this iCode */
8614 freeAsmop (NULL, aop, ic, TRUE);
8618 /* we did not allocate which means left
8619 already in a pointer register, then
8620 if size > 0 && this could be used again
8621 we have to point it back to where it
8623 if (AOP_SIZE (right) > 1 &&
8624 !OP_SYMBOL (result)->remat &&
8625 (OP_SYMBOL (result)->liveTo > ic->seq ||
8628 int size = AOP_SIZE (right) - 1;
8630 emitcode ("dec", "%s", rname);
8635 freeAsmop (right, NULL, ic, TRUE);
8640 /*-----------------------------------------------------------------*/
8641 /* genFarPointerSet - set value from far space */
8642 /*-----------------------------------------------------------------*/
8644 genFarPointerSet (operand * right,
8645 operand * result, iCode * ic)
8648 sym_link *retype = getSpec (operandType (right));
8649 sym_link *letype = getSpec (operandType (result));
8651 aopOp (result, ic, FALSE, FALSE);
8653 /* if the operand is already in dptr
8654 then we do nothing else we move the value to dptr */
8655 if (AOP_TYPE (result) != AOP_STR)
8657 /* if this is remateriazable */
8658 if (AOP_TYPE (result) == AOP_IMMD)
8659 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8662 /* we need to get it byte by byte */
8663 _startLazyDPSEvaluation ();
8664 if (AOP_TYPE (result) != AOP_DPTR)
8666 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8667 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8668 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8672 /* We need to generate a load to DPTR indirect through DPTR. */
8673 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8675 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8676 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8677 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8678 emitcode ("pop", "dph");
8679 emitcode ("pop", "dpl");
8681 _endLazyDPSEvaluation ();
8684 /* so dptr know contains the address */
8685 freeAsmop (result, NULL, ic, TRUE);
8686 aopOp (right, ic, FALSE, TRUE);
8688 /* if bit then unpack */
8689 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8690 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8693 size = AOP_SIZE (right);
8696 _startLazyDPSEvaluation ();
8699 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8705 emitcode ("movx", "@dptr,a");
8707 emitcode ("inc", "dptr");
8709 _endLazyDPSEvaluation ();
8712 freeAsmop (right, NULL, ic, TRUE);
8715 /*-----------------------------------------------------------------*/
8716 /* genGenPointerSet - set value from generic pointer space */
8717 /*-----------------------------------------------------------------*/
8719 genGenPointerSet (operand * right,
8720 operand * result, iCode * ic)
8723 sym_link *retype = getSpec (operandType (right));
8724 sym_link *letype = getSpec (operandType (result));
8726 aopOp (result, ic, FALSE, TRUE);
8728 /* if the operand is already in dptr
8729 then we do nothing else we move the value to dptr */
8730 if (AOP_TYPE (result) != AOP_STR)
8732 _startLazyDPSEvaluation ();
8733 /* if this is remateriazable */
8734 if (AOP_TYPE (result) == AOP_IMMD)
8736 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8737 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8740 { /* we need to get it byte by byte */
8741 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8742 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8743 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8744 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8746 _endLazyDPSEvaluation ();
8748 /* so dptr know contains the address */
8749 freeAsmop (result, NULL, ic, TRUE);
8750 aopOp (right, ic, FALSE, TRUE);
8752 /* if bit then unpack */
8753 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8754 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8757 size = AOP_SIZE (right);
8760 _startLazyDPSEvaluation ();
8763 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8769 emitcode ("lcall", "__gptrput");
8771 emitcode ("inc", "dptr");
8773 _endLazyDPSEvaluation ();
8776 freeAsmop (right, NULL, ic, TRUE);
8779 /*-----------------------------------------------------------------*/
8780 /* genPointerSet - stores the value into a pointer location */
8781 /*-----------------------------------------------------------------*/
8783 genPointerSet (iCode * ic)
8785 operand *right, *result;
8786 sym_link *type, *etype;
8789 D (emitcode (";", "genPointerSet ");
8792 right = IC_RIGHT (ic);
8793 result = IC_RESULT (ic);
8795 /* depending on the type of pointer we need to
8796 move it to the correct pointer register */
8797 type = operandType (result);
8798 etype = getSpec (type);
8799 /* if left is of type of pointer then it is simple */
8800 if (IS_PTR (type) && !IS_FUNC (type->next))
8802 p_type = DCL_TYPE (type);
8806 /* we have to go by the storage class */
8807 p_type = PTR_TYPE (SPEC_OCLS (etype));
8810 /* now that we have the pointer type we assign
8811 the pointer values */
8817 genNearPointerSet (right, result, ic);
8821 genPagedPointerSet (right, result, ic);
8825 genFarPointerSet (right, result, ic);
8829 genGenPointerSet (right, result, ic);
8835 /*-----------------------------------------------------------------*/
8836 /* genIfx - generate code for Ifx statement */
8837 /*-----------------------------------------------------------------*/
8839 genIfx (iCode * ic, iCode * popIc)
8841 operand *cond = IC_COND (ic);
8844 D (emitcode (";", "genIfx "););
8846 aopOp (cond, ic, FALSE, FALSE);
8848 /* get the value into acc */
8849 if (AOP_TYPE (cond) != AOP_CRY)
8853 /* the result is now in the accumulator */
8854 freeAsmop (cond, NULL, ic, TRUE);
8856 /* if there was something to be popped then do it */
8860 /* if the condition is a bit variable */
8861 if (isbit && IS_ITEMP (cond) &&
8863 genIfxJump (ic, SPIL_LOC (cond)->rname);
8864 else if (isbit && !IS_ITEMP (cond))
8865 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8867 genIfxJump (ic, "a");
8872 /*-----------------------------------------------------------------*/
8873 /* genAddrOf - generates code for address of */
8874 /*-----------------------------------------------------------------*/
8876 genAddrOf (iCode * ic)
8878 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8881 D (emitcode (";", "genAddrOf ");
8884 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8886 /* if the operand is on the stack then we
8887 need to get the stack offset of this
8891 /* if it has an offset then we need to compute
8895 emitcode ("mov", "a,_bp");
8896 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8897 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8901 /* we can just move _bp */
8902 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8904 /* fill the result with zero */
8905 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8908 if (options.stack10bit && size < (FPTRSIZE - 1))
8911 "*** warning: pointer to stack var truncated.\n");
8918 if (options.stack10bit && offset == 2)
8920 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8924 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8931 /* object not on stack then we need the name */
8932 size = AOP_SIZE (IC_RESULT (ic));
8937 char s[SDCC_NAME_MAX];
8939 sprintf (s, "#(%s >> %d)",
8943 sprintf (s, "#%s", sym->rname);
8944 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8948 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8952 /*-----------------------------------------------------------------*/
8953 /* genFarFarAssign - assignment when both are in far space */
8954 /*-----------------------------------------------------------------*/
8956 genFarFarAssign (operand * result, operand * right, iCode * ic)
8958 int size = AOP_SIZE (right);
8964 /* This is a net loss for size == 1, but a big gain
8967 D (emitcode (";", "genFarFarAssign (improved)");
8970 aopOp (result, ic, TRUE, TRUE);
8972 _startLazyDPSEvaluation ();
8975 aopPut (AOP (result),
8976 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8979 _endLazyDPSEvaluation ();
8980 freeAsmop (result, NULL, ic, FALSE);
8981 freeAsmop (right, NULL, ic, FALSE);
8985 D (emitcode (";", "genFarFarAssign ");
8988 /* first push the right side on to the stack */
8989 _startLazyDPSEvaluation ();
8992 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8994 emitcode ("push", "acc");
8997 freeAsmop (right, NULL, ic, FALSE);
8998 /* now assign DPTR to result */
8999 aopOp (result, ic, FALSE, FALSE);
9000 size = AOP_SIZE (result);
9003 emitcode ("pop", "acc");
9004 aopPut (AOP (result), "a", --offset);
9006 freeAsmop (result, NULL, ic, FALSE);
9007 _endLazyDPSEvaluation ();
9011 /*-----------------------------------------------------------------*/
9012 /* genAssign - generate code for assignment */
9013 /*-----------------------------------------------------------------*/
9015 genAssign (iCode * ic)
9017 operand *result, *right;
9019 unsigned long lit = 0L;
9021 D (emitcode (";", "genAssign ");
9024 result = IC_RESULT (ic);
9025 right = IC_RIGHT (ic);
9027 /* if they are the same */
9028 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9031 aopOp (right, ic, FALSE, FALSE);
9033 emitcode (";", "genAssign: resultIsFar = %s",
9034 isOperandInFarSpace (result) ?
9037 /* special case both in far space */
9038 if ((AOP_TYPE (right) == AOP_DPTR ||
9039 AOP_TYPE (right) == AOP_DPTR2) &&
9040 /* IS_TRUE_SYMOP(result) && */
9041 isOperandInFarSpace (result))
9043 genFarFarAssign (result, right, ic);
9047 aopOp (result, ic, TRUE, FALSE);
9049 /* if they are the same registers */
9050 if (sameRegs (AOP (right), AOP (result)))
9053 /* if the result is a bit */
9054 if (AOP_TYPE (result) == AOP_CRY)
9057 /* if the right size is a literal then
9058 we know what the value is */
9059 if (AOP_TYPE (right) == AOP_LIT)
9061 if (((int) operandLitValue (right)))
9062 aopPut (AOP (result), one, 0);
9064 aopPut (AOP (result), zero, 0);
9068 /* the right is also a bit variable */
9069 if (AOP_TYPE (right) == AOP_CRY)
9071 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9072 aopPut (AOP (result), "c", 0);
9078 aopPut (AOP (result), "a", 0);
9082 /* bit variables done */
9084 size = AOP_SIZE (result);
9086 if (AOP_TYPE (right) == AOP_LIT)
9087 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9090 (AOP_TYPE (result) != AOP_REG) &&
9091 (AOP_TYPE (right) == AOP_LIT) &&
9092 !IS_FLOAT (operandType (right)))
9094 D (emitcode (";", "Kevin's better literal load code");
9096 _startLazyDPSEvaluation ();
9097 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9099 aopPut (AOP (result),
9100 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9105 /* And now fill the rest with zeros. */
9108 emitcode ("clr", "a");
9112 aopPut (AOP (result), "a", offset++);
9114 _endLazyDPSEvaluation ();
9118 _startLazyDPSEvaluation ();
9121 aopPut (AOP (result),
9122 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9126 _endLazyDPSEvaluation ();
9130 freeAsmop (right, NULL, ic, FALSE);
9131 freeAsmop (result, NULL, ic, TRUE);
9134 /*-----------------------------------------------------------------*/
9135 /* genJumpTab - generates code for jump table */
9136 /*-----------------------------------------------------------------*/
9138 genJumpTab (iCode * ic)
9143 D (emitcode (";", "genJumpTab ");
9146 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9147 /* get the condition into accumulator */
9148 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9150 /* multiply by four! */
9151 emitcode ("add", "a,acc");
9152 emitcode ("add", "a,acc");
9153 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9155 jtab = newiTempLabel (NULL);
9156 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9157 emitcode ("jmp", "@a+dptr");
9158 emitcode ("", "%05d$:", jtab->key + 100);
9159 /* now generate the jump labels */
9160 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9161 jtab = setNextItem (IC_JTLABELS (ic)))
9162 emitcode ("ljmp", "%05d$", jtab->key + 100);
9166 /*-----------------------------------------------------------------*/
9167 /* genCast - gen code for casting */
9168 /*-----------------------------------------------------------------*/
9170 genCast (iCode * ic)
9172 operand *result = IC_RESULT (ic);
9173 sym_link *ctype = operandType (IC_LEFT (ic));
9174 sym_link *rtype = operandType (IC_RIGHT (ic));
9175 operand *right = IC_RIGHT (ic);
9178 D (emitcode (";", "genCast ");
9181 /* if they are equivalent then do nothing */
9182 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9185 aopOp (right, ic, FALSE, FALSE);
9186 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9188 /* if the result is a bit */
9189 if (AOP_TYPE (result) == AOP_CRY)
9191 /* if the right size is a literal then
9192 we know what the value is */
9193 if (AOP_TYPE (right) == AOP_LIT)
9195 if (((int) operandLitValue (right)))
9196 aopPut (AOP (result), one, 0);
9198 aopPut (AOP (result), zero, 0);
9203 /* the right is also a bit variable */
9204 if (AOP_TYPE (right) == AOP_CRY)
9206 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9207 aopPut (AOP (result), "c", 0);
9213 aopPut (AOP (result), "a", 0);
9217 /* if they are the same size : or less */
9218 if (AOP_SIZE (result) <= AOP_SIZE (right))
9221 /* if they are in the same place */
9222 if (sameRegs (AOP (right), AOP (result)))
9225 /* if they in different places then copy */
9226 size = AOP_SIZE (result);
9228 _startLazyDPSEvaluation ();
9231 aopPut (AOP (result),
9232 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9236 _endLazyDPSEvaluation ();
9241 /* if the result is of type pointer */
9246 sym_link *type = operandType (right);
9248 /* pointer to generic pointer */
9249 if (IS_GENPTR (ctype))
9255 p_type = DCL_TYPE (type);
9259 #if OLD_CAST_BEHAVIOR
9260 /* KV: we are converting a non-pointer type to
9261 * a generic pointer. This (ifdef'd out) code
9262 * says that the resulting generic pointer
9263 * should have the same class as the storage
9264 * location of the non-pointer variable.
9266 * For example, converting an int (which happens
9267 * to be stored in DATA space) to a pointer results
9268 * in a DATA generic pointer; if the original int
9269 * in XDATA space, so will be the resulting pointer.
9271 * I don't like that behavior, and thus this change:
9272 * all such conversions will be forced to XDATA and
9273 * throw a warning. If you want some non-XDATA
9274 * type, or you want to suppress the warning, you
9275 * must go through an intermediate cast, like so:
9277 * char _generic *gp = (char _xdata *)(intVar);
9279 sym_link *etype = getSpec (type);
9281 /* we have to go by the storage class */
9282 if (SPEC_OCLS (etype) != generic)
9284 p_type = PTR_TYPE (SPEC_OCLS (etype));
9289 /* Converting unknown class (i.e. register variable)
9290 * to generic pointer. This is not good, but
9291 * we'll make a guess (and throw a warning).
9294 werror (W_INT_TO_GEN_PTR_CAST);
9298 /* the first two bytes are known */
9299 size = GPTRSIZE - 1;
9301 _startLazyDPSEvaluation ();
9304 aopPut (AOP (result),
9305 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9309 _endLazyDPSEvaluation ();
9311 /* the last byte depending on type */
9329 /* this should never happen */
9330 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9331 "got unknown pointer type");
9334 aopPut (AOP (result), l, GPTRSIZE - 1);
9338 /* just copy the pointers */
9339 size = AOP_SIZE (result);
9341 _startLazyDPSEvaluation ();
9344 aopPut (AOP (result),
9345 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9349 _endLazyDPSEvaluation ();
9353 /* so we now know that the size of destination is greater
9354 than the size of the source */
9355 /* we move to result for the size of source */
9356 size = AOP_SIZE (right);
9358 _startLazyDPSEvaluation ();
9361 aopPut (AOP (result),
9362 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9366 _endLazyDPSEvaluation ();
9368 /* now depending on the sign of the source && destination */
9369 size = AOP_SIZE (result) - AOP_SIZE (right);
9370 /* if unsigned or not an integral type */
9371 /* also, if the source is a bit, we don't need to sign extend, because
9372 * it can't possibly have set the sign bit.
9374 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9378 aopPut (AOP (result), zero, offset++);
9383 /* we need to extend the sign :{ */
9384 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9385 FALSE, FALSE, TRUE);
9387 emitcode ("rlc", "a");
9388 emitcode ("subb", "a,acc");
9390 aopPut (AOP (result), "a", offset++);
9393 /* we are done hurray !!!! */
9396 freeAsmop (right, NULL, ic, TRUE);
9397 freeAsmop (result, NULL, ic, TRUE);
9401 /*-----------------------------------------------------------------*/
9402 /* genDjnz - generate decrement & jump if not zero instrucion */
9403 /*-----------------------------------------------------------------*/
9405 genDjnz (iCode * ic, iCode * ifx)
9411 /* if the if condition has a false label
9412 then we cannot save */
9416 /* if the minus is not of the form
9418 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9419 !IS_OP_LITERAL (IC_RIGHT (ic)))
9422 if (operandLitValue (IC_RIGHT (ic)) != 1)
9425 /* if the size of this greater than one then no
9427 if (getSize (operandType (IC_RESULT (ic))) > 1)
9430 /* otherwise we can save BIG */
9431 D(emitcode(";", "genDjnz"););
9433 lbl = newiTempLabel (NULL);
9434 lbl1 = newiTempLabel (NULL);
9436 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9438 if (AOP_NEEDSACC(IC_RESULT(ic)))
9440 /* If the result is accessed indirectly via
9441 * the accumulator, we must explicitly write
9442 * it back after the decrement.
9444 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9446 if (strcmp(rByte, "a"))
9448 /* Something is hopelessly wrong */
9449 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9450 __FILE__, __LINE__);
9451 /* We can just give up; the generated code will be inefficient,
9454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9457 emitcode ("dec", "%s", rByte);
9458 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9459 emitcode ("jnz", "%05d$", lbl->key + 100);
9461 else if (IS_AOP_PREG (IC_RESULT (ic)))
9463 emitcode ("dec", "%s",
9464 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9465 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9466 emitcode ("jnz", "%05d$", lbl->key + 100);
9470 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9473 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9474 emitcode ("", "%05d$:", lbl->key + 100);
9475 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9476 emitcode ("", "%05d$:", lbl1->key + 100);
9478 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9483 /*-----------------------------------------------------------------*/
9484 /* genReceive - generate code for a receive iCode */
9485 /*-----------------------------------------------------------------*/
9487 genReceive (iCode * ic)
9490 D (emitcode (";", "genReceive ");
9493 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9494 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9495 IS_TRUE_SYMOP (IC_RESULT (ic))))
9497 int size = getSize (operandType (IC_RESULT (ic)));
9498 int offset = fReturnSizeDS390 - size;
9501 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9502 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9505 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9506 size = AOP_SIZE (IC_RESULT (ic));
9510 emitcode ("pop", "acc");
9511 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9518 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9520 assignResultValue (IC_RESULT (ic));
9523 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9526 /*-----------------------------------------------------------------*/
9527 /* gen390Code - generate code for Dallas 390 based controllers */
9528 /*-----------------------------------------------------------------*/
9530 gen390Code (iCode * lic)
9535 lineHead = lineCurr = NULL;
9539 /* print the allocation information */
9541 printAllocInfo (currFunc, codeOutFile);
9543 /* if debug information required */
9544 if (options.debug && currFunc)
9546 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9548 if (IS_STATIC (currFunc->etype))
9549 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9551 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9554 /* stack pointer name */
9555 if (options.useXstack)
9561 for (ic = lic; ic; ic = ic->next)
9564 if (cln != ic->lineno)
9569 emitcode ("", "C$%s$%d$%d$%d ==.",
9570 FileBaseName (ic->filename), ic->lineno,
9571 ic->level, ic->block);
9574 emitcode (";", "%s %d", ic->filename, ic->lineno);
9577 /* if the result is marked as
9578 spilt and rematerializable or code for
9579 this has already been generated then
9581 if (resultRemat (ic) || ic->generated)
9584 /* depending on the operation */
9604 /* IPOP happens only when trying to restore a
9605 spilt live range, if there is an ifx statement
9606 following this pop then the if statement might
9607 be using some of the registers being popped which
9608 would destory the contents of the register so
9609 we need to check for this condition and handle it */
9611 ic->next->op == IFX &&
9612 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9613 genIfx (ic->next, ic);
9631 genEndFunction (ic);
9651 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9668 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9672 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9679 /* note these two are xlated by algebraic equivalence
9680 during parsing SDCC.y */
9681 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9682 "got '>=' or '<=' shouldn't have come here");
9686 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9698 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9702 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9706 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9733 case GET_VALUE_AT_ADDRESS:
9738 if (POINTER_SET (ic))
9765 addSet (&_G.sendSet, ic);
9774 /* now we are ready to call the
9775 peep hole optimizer */
9776 if (!options.nopeep)
9777 peepHole (&lineHead);
9779 /* now do the actual printing */
9780 printLine (lineHead, codeOutFile);