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();
6668 aopPut (AOP (result), zero, LSB);
6673 _endLazyDPSEvaluation();
6674 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6678 movLeft2Result (left, LSB, result, MSB16, 0);
6679 _endLazyDPSEvaluation();
6684 _endLazyDPSEvaluation();
6688 /* 1 <= shCount <= 7 */
6693 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6697 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6705 /*-----------------------------------------------------------------*/
6706 /* shiftLLong - shift left one long from left to result */
6707 /* offl = LSB or MSB16 */
6708 /*-----------------------------------------------------------------*/
6710 shiftLLong (operand * left, operand * result, int offr)
6713 int size = AOP_SIZE (result);
6715 if (size >= LSB + offr)
6717 l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6719 emitcode ("add", "a,acc");
6720 if (sameRegs (AOP (left), AOP (result)) &&
6721 size >= MSB16 + offr && offr != LSB)
6722 emitcode ("xch", "a,%s",
6723 aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6725 aopPut (AOP (result), "a", LSB + offr);
6728 if (size >= MSB16 + offr)
6730 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6732 l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6735 emitcode ("rlc", "a");
6736 if (sameRegs (AOP (left), AOP (result)) &&
6737 size >= MSB24 + offr && offr != LSB)
6738 emitcode ("xch", "a,%s",
6739 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6741 aopPut (AOP (result), "a", MSB16 + offr);
6744 if (size >= MSB24 + offr)
6746 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6748 l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6751 emitcode ("rlc", "a");
6752 if (sameRegs (AOP (left), AOP (result)) &&
6753 size >= MSB32 + offr && offr != LSB)
6754 emitcode ("xch", "a,%s",
6755 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6757 aopPut (AOP (result), "a", MSB24 + offr);
6760 if (size > MSB32 + offr)
6762 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6764 l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6767 emitcode ("rlc", "a");
6768 aopPut (AOP (result), "a", MSB32 + offr);
6771 aopPut (AOP (result), zero, LSB);
6777 /*-----------------------------------------------------------------*/
6778 /* genlshFour - shift four byte by a known amount != 0 */
6779 /*-----------------------------------------------------------------*/
6781 genlshFour (operand * result, operand * left, int shCount)
6785 D (emitcode (";", "genlshFour ");
6788 size = AOP_SIZE (result);
6790 /* if shifting more that 3 bytes */
6795 /* lowest order of left goes to the highest
6796 order of the destination */
6797 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6799 movLeft2Result (left, LSB, result, MSB32, 0);
6800 aopPut (AOP (result), zero, LSB);
6801 aopPut (AOP (result), zero, MSB16);
6802 aopPut (AOP (result), zero, MSB24);
6806 /* more than two bytes */
6807 else if (shCount >= 16)
6809 /* lower order two bytes goes to higher order two bytes */
6811 /* if some more remaining */
6813 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6816 movLeft2Result (left, MSB16, result, MSB32, 0);
6817 movLeft2Result (left, LSB, result, MSB24, 0);
6819 aopPut (AOP (result), zero, MSB16);
6820 aopPut (AOP (result), zero, LSB);
6824 /* if more than 1 byte */
6825 else if (shCount >= 8)
6827 /* lower order three bytes goes to higher order three bytes */
6832 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6834 movLeft2Result (left, LSB, result, MSB16, 0);
6840 movLeft2Result (left, MSB24, result, MSB32, 0);
6841 movLeft2Result (left, MSB16, result, MSB24, 0);
6842 movLeft2Result (left, LSB, result, MSB16, 0);
6843 aopPut (AOP (result), zero, LSB);
6845 else if (shCount == 1)
6846 shiftLLong (left, result, MSB16);
6849 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6850 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6851 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6852 aopPut (AOP (result), zero, LSB);
6857 /* 1 <= shCount <= 7 */
6858 else if (shCount <= 2)
6860 shiftLLong (left, result, LSB);
6862 shiftLLong (result, result, LSB);
6864 /* 3 <= shCount <= 7, optimize */
6867 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6868 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6869 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6874 #ifdef BETTER_LITERAL_SHIFT
6875 /*-----------------------------------------------------------------*/
6876 /* genLeftShiftLiteral - left shifting by known count */
6877 /*-----------------------------------------------------------------*/
6879 genLeftShiftLiteral (operand * left,
6884 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6887 size = getSize (operandType (result));
6889 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6891 /* We only handle certain easy cases so far. */
6893 && (shCount < (size * 8))
6897 D(emitcode (";", "genLeftShiftLiteral wimping out"););
6901 freeAsmop (right, NULL, ic, TRUE);
6903 aopOp(left, ic, FALSE, FALSE);
6904 aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6907 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6909 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6910 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6912 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6915 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6917 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6918 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6920 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6926 emitcode ("; shift left ", "result %d, left %d", size,
6930 /* I suppose that the left size >= result size */
6933 _startLazyDPSEvaluation();
6936 movLeft2Result (left, size, result, size, 0);
6938 _endLazyDPSEvaluation();
6940 else if (shCount >= (size * 8))
6942 _startLazyDPSEvaluation();
6945 aopPut (AOP (result), zero, size);
6947 _endLazyDPSEvaluation();
6954 genlshOne (result, left, shCount);
6958 genlshTwo (result, left, shCount);
6962 genlshFour (result, left, shCount);
6966 fprintf(stderr, "*** ack! mystery literal shift!\n");
6970 freeAsmop (left, NULL, ic, TRUE);
6971 freeAsmop (result, NULL, ic, TRUE);
6976 /*-----------------------------------------------------------------*/
6977 /* genLeftShift - generates code for left shifting */
6978 /*-----------------------------------------------------------------*/
6980 genLeftShift (iCode * ic)
6982 operand *left, *right, *result;
6985 symbol *tlbl, *tlbl1;
6987 D (emitcode (";", "genLeftShift "););
6989 right = IC_RIGHT (ic);
6990 left = IC_LEFT (ic);
6991 result = IC_RESULT (ic);
6993 aopOp (right, ic, FALSE, FALSE);
6996 #ifdef BETTER_LITERAL_SHIFT
6997 /* if the shift count is known then do it
6998 as efficiently as possible */
6999 if (AOP_TYPE (right) == AOP_LIT)
7001 if (genLeftShiftLiteral (left, right, result, ic))
7008 /* shift count is unknown then we have to form
7009 a loop get the loop count in B : Note: we take
7010 only the lower order byte since shifting
7011 more that 32 bits make no sense anyway, ( the
7012 largest size of an object can be only 32 bits ) */
7014 if (AOP_TYPE (right) == AOP_LIT)
7016 /* Really should be handled by genLeftShiftLiteral,
7017 * but since I'm too lazy to fix that today, at least we can make
7018 * some small improvement.
7020 emitcode("mov", "b,#0x%02x",
7021 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7025 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7026 emitcode ("inc", "b");
7028 freeAsmop (right, NULL, ic, TRUE);
7029 aopOp (left, ic, FALSE, FALSE);
7030 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7032 /* now move the left to the result if they are not the
7034 if (!sameRegs (AOP (left), AOP (result)) &&
7035 AOP_SIZE (result) > 1)
7038 size = AOP_SIZE (result);
7040 _startLazyDPSEvaluation ();
7043 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7044 if (*l == '@' && (IS_AOP_PREG (result)))
7047 emitcode ("mov", "a,%s", l);
7048 aopPut (AOP (result), "a", offset);
7051 aopPut (AOP (result), l, offset);
7054 _endLazyDPSEvaluation ();
7057 tlbl = newiTempLabel (NULL);
7058 size = AOP_SIZE (result);
7060 tlbl1 = newiTempLabel (NULL);
7062 /* if it is only one byte then */
7065 symbol *tlbl1 = newiTempLabel (NULL);
7067 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7069 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7070 emitcode ("", "%05d$:", tlbl->key + 100);
7071 emitcode ("add", "a,acc");
7072 emitcode ("", "%05d$:", tlbl1->key + 100);
7073 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7074 aopPut (AOP (result), "a", 0);
7078 reAdjustPreg (AOP (result));
7080 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7081 emitcode ("", "%05d$:", tlbl->key + 100);
7082 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7084 emitcode ("add", "a,acc");
7085 aopPut (AOP (result), "a", offset++);
7086 _startLazyDPSEvaluation ();
7089 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7091 emitcode ("rlc", "a");
7092 aopPut (AOP (result), "a", offset++);
7094 _endLazyDPSEvaluation ();
7095 reAdjustPreg (AOP (result));
7097 emitcode ("", "%05d$:", tlbl1->key + 100);
7098 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7100 freeAsmop (left, NULL, ic, TRUE);
7101 freeAsmop (result, NULL, ic, TRUE);
7104 #ifdef BETTER_LITERAL_SHIFT
7105 /*-----------------------------------------------------------------*/
7106 /* genrshOne - right shift a one byte quantity by known count */
7107 /*-----------------------------------------------------------------*/
7109 genrshOne (operand * result, operand * left,
7110 int shCount, int sign)
7112 D (emitcode (";", "genrshOne"););
7113 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7117 #ifdef BETTER_LITERAL_SHIFT
7118 /*-----------------------------------------------------------------*/
7119 /* genrshTwo - right shift two bytes by known amount != 0 */
7120 /*-----------------------------------------------------------------*/
7122 genrshTwo (operand * result, operand * left,
7123 int shCount, int sign)
7125 D (emitcode (";", "genrshTwo"););
7127 /* if shCount >= 8 */
7131 _startLazyDPSEvaluation();
7134 shiftR1Left2Result (left, MSB16, result, LSB,
7139 movLeft2Result (left, MSB16, result, LSB, sign);
7141 addSign (result, MSB16, sign);
7142 _endLazyDPSEvaluation();
7145 /* 1 <= shCount <= 7 */
7148 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7155 /*-----------------------------------------------------------------*/
7156 /* shiftRLong - shift right one long from left to result */
7157 /* offl = LSB or MSB16 */
7158 /*-----------------------------------------------------------------*/
7160 shiftRLong (operand * left, int offl,
7161 operand * result, int sign)
7164 emitcode ("clr", "c");
7165 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7167 emitcode ("mov", "c,acc.7");
7168 emitcode ("rrc", "a");
7169 aopPut (AOP (result), "a", MSB32 - offl);
7171 /* add sign of "a" */
7172 addSign (result, MSB32, sign);
7174 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7175 emitcode ("rrc", "a");
7176 aopPut (AOP (result), "a", MSB24 - offl);
7178 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7179 emitcode ("rrc", "a");
7180 aopPut (AOP (result), "a", MSB16 - offl);
7184 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7185 emitcode ("rrc", "a");
7186 aopPut (AOP (result), "a", LSB);
7193 /*-----------------------------------------------------------------*/
7194 /* genrshFour - shift four byte by a known amount != 0 */
7195 /*-----------------------------------------------------------------*/
7197 genrshFour (operand * result, operand * left,
7198 int shCount, int sign)
7200 D (emitcode (";", "genrshFour");
7203 /* if shifting more that 3 bytes */
7208 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7210 movLeft2Result (left, MSB32, result, LSB, sign);
7211 addSign (result, MSB16, sign);
7213 else if (shCount >= 16)
7217 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7220 movLeft2Result (left, MSB24, result, LSB, 0);
7221 movLeft2Result (left, MSB32, result, MSB16, sign);
7223 addSign (result, MSB24, sign);
7225 else if (shCount >= 8)
7229 shiftRLong (left, MSB16, result, sign);
7230 else if (shCount == 0)
7232 movLeft2Result (left, MSB16, result, LSB, 0);
7233 movLeft2Result (left, MSB24, result, MSB16, 0);
7234 movLeft2Result (left, MSB32, result, MSB24, sign);
7235 addSign (result, MSB32, sign);
7239 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7240 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7241 /* the last shift is signed */
7242 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7243 addSign (result, MSB32, sign);
7247 { /* 1 <= shCount <= 7 */
7250 shiftRLong (left, LSB, result, sign);
7252 shiftRLong (result, LSB, result, sign);
7256 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7257 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7258 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7264 #ifdef BETTER_LITERAL_SHIFT
7265 /*-----------------------------------------------------------------*/
7266 /* genRightShiftLiteral - right shifting by known count */
7267 /*-----------------------------------------------------------------*/
7269 genRightShiftLiteral (operand * left,
7275 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7278 size = getSize (operandType (result));
7280 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7282 /* We only handle certain easy cases so far. */
7284 && (shCount < (size * 8))
7288 D(emitcode (";", "genRightShiftLiteral wimping out"););
7292 freeAsmop (right, NULL, ic, TRUE);
7294 aopOp (left, ic, FALSE, FALSE);
7295 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7298 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7302 /* test the LEFT size !!! */
7304 /* I suppose that the left size >= result size */
7307 size = getDataSize (result);
7308 _startLazyDPSEvaluation();
7311 movLeft2Result (left, size, result, size, 0);
7313 _endLazyDPSEvaluation();
7315 else if (shCount >= (size * 8))
7319 /* get sign in acc.7 */
7320 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7322 addSign (result, LSB, sign);
7329 genrshOne (result, left, shCount, sign);
7333 genrshTwo (result, left, shCount, sign);
7337 genrshFour (result, left, shCount, sign);
7344 freeAsmop (left, NULL, ic, TRUE);
7345 freeAsmop (result, NULL, ic, TRUE);
7351 /*-----------------------------------------------------------------*/
7352 /* genSignedRightShift - right shift of signed number */
7353 /*-----------------------------------------------------------------*/
7355 genSignedRightShift (iCode * ic)
7357 operand *right, *left, *result;
7360 symbol *tlbl, *tlbl1;
7362 D (emitcode (";", "genSignedRightShift "););
7364 /* we do it the hard way put the shift count in b
7365 and loop thru preserving the sign */
7367 right = IC_RIGHT (ic);
7368 left = IC_LEFT (ic);
7369 result = IC_RESULT (ic);
7371 aopOp (right, ic, FALSE, FALSE);
7373 #ifdef BETTER_LITERAL_SHIFT
7374 if (AOP_TYPE (right) == AOP_LIT)
7376 if (genRightShiftLiteral (left, right, result, ic, 1))
7382 /* shift count is unknown then we have to form
7383 a loop get the loop count in B : Note: we take
7384 only the lower order byte since shifting
7385 more that 32 bits make no sense anyway, ( the
7386 largest size of an object can be only 32 bits ) */
7388 if (AOP_TYPE (right) == AOP_LIT)
7390 /* Really should be handled by genRightShiftLiteral,
7391 * but since I'm too lazy to fix that today, at least we can make
7392 * some small improvement.
7394 emitcode("mov", "b,#0x%02x",
7395 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7399 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7400 emitcode ("inc", "b");
7402 freeAsmop (right, NULL, ic, TRUE);
7403 aopOp (left, ic, FALSE, FALSE);
7404 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7406 /* now move the left to the result if they are not the
7408 if (!sameRegs (AOP (left), AOP (result)) &&
7409 AOP_SIZE (result) > 1)
7412 size = AOP_SIZE (result);
7414 _startLazyDPSEvaluation ();
7417 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7418 if (*l == '@' && IS_AOP_PREG (result))
7421 emitcode ("mov", "a,%s", l);
7422 aopPut (AOP (result), "a", offset);
7425 aopPut (AOP (result), l, offset);
7428 _endLazyDPSEvaluation ();
7431 /* mov the highest order bit to OVR */
7432 tlbl = newiTempLabel (NULL);
7433 tlbl1 = newiTempLabel (NULL);
7435 size = AOP_SIZE (result);
7437 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7438 emitcode ("rlc", "a");
7439 emitcode ("mov", "ov,c");
7440 /* if it is only one byte then */
7443 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7445 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7446 emitcode ("", "%05d$:", tlbl->key + 100);
7447 emitcode ("mov", "c,ov");
7448 emitcode ("rrc", "a");
7449 emitcode ("", "%05d$:", tlbl1->key + 100);
7450 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7451 aopPut (AOP (result), "a", 0);
7455 reAdjustPreg (AOP (result));
7456 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7457 emitcode ("", "%05d$:", tlbl->key + 100);
7458 emitcode ("mov", "c,ov");
7459 _startLazyDPSEvaluation ();
7462 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7464 emitcode ("rrc", "a");
7465 aopPut (AOP (result), "a", offset--);
7467 _endLazyDPSEvaluation ();
7468 reAdjustPreg (AOP (result));
7469 emitcode ("", "%05d$:", tlbl1->key + 100);
7470 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7473 freeAsmop (left, NULL, ic, TRUE);
7474 freeAsmop (result, NULL, ic, TRUE);
7477 /*-----------------------------------------------------------------*/
7478 /* genRightShift - generate code for right shifting */
7479 /*-----------------------------------------------------------------*/
7481 genRightShift (iCode * ic)
7483 operand *right, *left, *result;
7487 symbol *tlbl, *tlbl1;
7489 D (emitcode (";", "genRightShift "););
7491 /* if signed then we do it the hard way preserve the
7492 sign bit moving it inwards */
7493 retype = getSpec (operandType (IC_RESULT (ic)));
7495 if (!SPEC_USIGN (retype))
7497 genSignedRightShift (ic);
7501 /* signed & unsigned types are treated the same : i.e. the
7502 signed is NOT propagated inwards : quoting from the
7503 ANSI - standard : "for E1 >> E2, is equivalent to division
7504 by 2**E2 if unsigned or if it has a non-negative value,
7505 otherwise the result is implementation defined ", MY definition
7506 is that the sign does not get propagated */
7508 right = IC_RIGHT (ic);
7509 left = IC_LEFT (ic);
7510 result = IC_RESULT (ic);
7512 aopOp (right, ic, FALSE, FALSE);
7514 #ifdef BETTER_LITERAL_SHIFT
7515 /* if the shift count is known then do it
7516 as efficiently as possible */
7517 if (AOP_TYPE (right) == AOP_LIT)
7519 if (genRightShiftLiteral (left, right, result, ic, 0))
7526 /* shift count is unknown then we have to form
7527 a loop get the loop count in B : Note: we take
7528 only the lower order byte since shifting
7529 more that 32 bits make no sense anyway, ( the
7530 largest size of an object can be only 32 bits ) */
7532 if (AOP_TYPE (right) == AOP_LIT)
7534 /* Really should be handled by genRightShiftLiteral,
7535 * but since I'm too lazy to fix that today, at least we can make
7536 * some small improvement.
7538 emitcode("mov", "b,#0x%02x",
7539 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7543 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7544 emitcode ("inc", "b");
7546 freeAsmop (right, NULL, ic, TRUE);
7547 aopOp (left, ic, FALSE, FALSE);
7548 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7550 /* now move the left to the result if they are not the
7552 if (!sameRegs (AOP (left), AOP (result)) &&
7553 AOP_SIZE (result) > 1)
7556 size = AOP_SIZE (result);
7558 _startLazyDPSEvaluation ();
7561 l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7562 if (*l == '@' && IS_AOP_PREG (result))
7565 emitcode ("mov", "a,%s", l);
7566 aopPut (AOP (result), "a", offset);
7569 aopPut (AOP (result), l, offset);
7572 _endLazyDPSEvaluation ();
7575 tlbl = newiTempLabel (NULL);
7576 tlbl1 = newiTempLabel (NULL);
7577 size = AOP_SIZE (result);
7580 /* if it is only one byte then */
7583 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7585 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7586 emitcode ("", "%05d$:", tlbl->key + 100);
7588 emitcode ("rrc", "a");
7589 emitcode ("", "%05d$:", tlbl1->key + 100);
7590 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7591 aopPut (AOP (result), "a", 0);
7595 reAdjustPreg (AOP (result));
7596 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7597 emitcode ("", "%05d$:", tlbl->key + 100);
7599 _startLazyDPSEvaluation ();
7602 l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7604 emitcode ("rrc", "a");
7605 aopPut (AOP (result), "a", offset--);
7607 _endLazyDPSEvaluation ();
7608 reAdjustPreg (AOP (result));
7610 emitcode ("", "%05d$:", tlbl1->key + 100);
7611 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7614 freeAsmop (left, NULL, ic, TRUE);
7615 freeAsmop (result, NULL, ic, TRUE);
7618 /*-----------------------------------------------------------------*/
7619 /* genUnpackBits - generates code for unpacking bits */
7620 /*-----------------------------------------------------------------*/
7622 genUnpackBits (operand * result, char *rname, int ptype)
7629 D (emitcode (";", "genUnpackBits ");
7632 etype = getSpec (operandType (result));
7634 /* read the first byte */
7640 emitcode ("mov", "a,@%s", rname);
7644 emitcode ("movx", "a,@%s", rname);
7648 emitcode ("movx", "a,@dptr");
7652 emitcode ("clr", "a");
7653 emitcode ("movc", "a", "@a+dptr");
7657 emitcode ("lcall", "__gptrget");
7661 /* if we have bitdisplacement then it fits */
7662 /* into this byte completely or if length is */
7663 /* less than a byte */
7664 if ((shCnt = SPEC_BSTR (etype)) ||
7665 (SPEC_BLEN (etype) <= 8))
7668 /* shift right acc */
7671 emitcode ("anl", "a,#0x%02x",
7672 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7673 aopPut (AOP (result), "a", offset);
7677 /* bit field did not fit in a byte */
7678 rlen = SPEC_BLEN (etype) - 8;
7679 aopPut (AOP (result), "a", offset++);
7688 emitcode ("inc", "%s", rname);
7689 emitcode ("mov", "a,@%s", rname);
7693 emitcode ("inc", "%s", rname);
7694 emitcode ("movx", "a,@%s", rname);
7698 emitcode ("inc", "dptr");
7699 emitcode ("movx", "a,@dptr");
7703 emitcode ("clr", "a");
7704 emitcode ("inc", "dptr");
7705 emitcode ("movc", "a", "@a+dptr");
7709 emitcode ("inc", "dptr");
7710 emitcode ("lcall", "__gptrget");
7715 /* if we are done */
7719 aopPut (AOP (result), "a", offset++);
7725 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7726 aopPut (AOP (result), "a", offset);
7733 /*-----------------------------------------------------------------*/
7734 /* genDataPointerGet - generates code when ptr offset is known */
7735 /*-----------------------------------------------------------------*/
7737 genDataPointerGet (operand * left,
7743 int size, offset = 0;
7744 aopOp (result, ic, TRUE, FALSE);
7746 /* get the string representation of the name */
7747 l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7748 size = AOP_SIZE (result);
7749 _startLazyDPSEvaluation ();
7753 sprintf (buffer, "(%s + %d)", l + 1, offset);
7755 sprintf (buffer, "%s", l + 1);
7756 aopPut (AOP (result), buffer, offset++);
7758 _endLazyDPSEvaluation ();
7760 freeAsmop (left, NULL, ic, TRUE);
7761 freeAsmop (result, NULL, ic, TRUE);
7764 /*-----------------------------------------------------------------*/
7765 /* genNearPointerGet - emitcode for near pointer fetch */
7766 /*-----------------------------------------------------------------*/
7768 genNearPointerGet (operand * left,
7775 sym_link *rtype, *retype, *letype;
7776 sym_link *ltype = operandType (left);
7779 rtype = operandType (result);
7780 retype = getSpec (rtype);
7781 letype = getSpec (ltype);
7783 aopOp (left, ic, FALSE, FALSE);
7785 /* if left is rematerialisable and
7786 result is not bit variable type and
7787 the left is pointer to data space i.e
7788 lower 128 bytes of space */
7789 if (AOP_TYPE (left) == AOP_IMMD &&
7790 !IS_BITVAR (retype) &&
7791 !IS_BITVAR (letype) &&
7792 DCL_TYPE (ltype) == POINTER)
7794 genDataPointerGet (left, result, ic);
7798 /* if the value is already in a pointer register
7799 then don't need anything more */
7800 if (!AOP_INPREG (AOP (left)))
7802 /* otherwise get a free pointer register */
7804 preg = getFreePtr (ic, &aop, FALSE);
7805 emitcode ("mov", "%s,%s",
7807 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7811 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7813 freeAsmop (left, NULL, ic, TRUE);
7814 aopOp (result, ic, FALSE, FALSE);
7816 /* if bitfield then unpack the bits */
7817 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7818 genUnpackBits (result, rname, POINTER);
7821 /* we have can just get the values */
7822 int size = AOP_SIZE (result);
7827 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7830 emitcode ("mov", "a,@%s", rname);
7831 aopPut (AOP (result), "a", offset);
7835 sprintf (buffer, "@%s", rname);
7836 aopPut (AOP (result), buffer, offset);
7840 emitcode ("inc", "%s", rname);
7844 /* now some housekeeping stuff */
7847 /* we had to allocate for this iCode */
7848 freeAsmop (NULL, aop, ic, TRUE);
7852 /* we did not allocate which means left
7853 already in a pointer register, then
7854 if size > 0 && this could be used again
7855 we have to point it back to where it
7857 if (AOP_SIZE (result) > 1 &&
7858 !OP_SYMBOL (left)->remat &&
7859 (OP_SYMBOL (left)->liveTo > ic->seq ||
7862 int size = AOP_SIZE (result) - 1;
7864 emitcode ("dec", "%s", rname);
7869 freeAsmop (result, NULL, ic, TRUE);
7873 /*-----------------------------------------------------------------*/
7874 /* genPagedPointerGet - emitcode for paged pointer fetch */
7875 /*-----------------------------------------------------------------*/
7877 genPagedPointerGet (operand * left,
7884 sym_link *rtype, *retype, *letype;
7886 rtype = operandType (result);
7887 retype = getSpec (rtype);
7888 letype = getSpec (operandType (left));
7889 aopOp (left, ic, FALSE, FALSE);
7891 /* if the value is already in a pointer register
7892 then don't need anything more */
7893 if (!AOP_INPREG (AOP (left)))
7895 /* otherwise get a free pointer register */
7897 preg = getFreePtr (ic, &aop, FALSE);
7898 emitcode ("mov", "%s,%s",
7900 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7904 rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7906 freeAsmop (left, NULL, ic, TRUE);
7907 aopOp (result, ic, FALSE, FALSE);
7909 /* if bitfield then unpack the bits */
7910 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7911 genUnpackBits (result, rname, PPOINTER);
7914 /* we have can just get the values */
7915 int size = AOP_SIZE (result);
7921 emitcode ("movx", "a,@%s", rname);
7922 aopPut (AOP (result), "a", offset);
7927 emitcode ("inc", "%s", rname);
7931 /* now some housekeeping stuff */
7934 /* we had to allocate for this iCode */
7935 freeAsmop (NULL, aop, ic, TRUE);
7939 /* we did not allocate which means left
7940 already in a pointer register, then
7941 if size > 0 && this could be used again
7942 we have to point it back to where it
7944 if (AOP_SIZE (result) > 1 &&
7945 !OP_SYMBOL (left)->remat &&
7946 (OP_SYMBOL (left)->liveTo > ic->seq ||
7949 int size = AOP_SIZE (result) - 1;
7951 emitcode ("dec", "%s", rname);
7956 freeAsmop (result, NULL, ic, TRUE);
7961 /*-----------------------------------------------------------------*/
7962 /* genFarPointerGet - gget value from far space */
7963 /*-----------------------------------------------------------------*/
7965 genFarPointerGet (operand * left,
7966 operand * result, iCode * ic)
7969 sym_link *retype = getSpec (operandType (result));
7970 sym_link *letype = getSpec (operandType (left));
7971 D (emitcode (";", "genFarPointerGet");
7974 aopOp (left, ic, FALSE, FALSE);
7976 /* if the operand is already in dptr
7977 then we do nothing else we move the value to dptr */
7978 if (AOP_TYPE (left) != AOP_STR)
7980 /* if this is remateriazable */
7981 if (AOP_TYPE (left) == AOP_IMMD)
7983 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7987 /* we need to get it byte by byte */
7988 _startLazyDPSEvaluation ();
7989 if (AOP_TYPE (left) != AOP_DPTR)
7991 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7992 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7993 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7997 /* We need to generate a load to DPTR indirect through DPTR. */
7998 D (emitcode (";", "genFarPointerGet -- indirection special case.");
8000 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8001 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8002 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8003 emitcode ("pop", "dph");
8004 emitcode ("pop", "dpl");
8006 _endLazyDPSEvaluation ();
8009 /* so dptr know contains the address */
8010 freeAsmop (left, NULL, ic, TRUE);
8011 aopOp (result, ic, FALSE, TRUE);
8013 /* if bit then unpack */
8014 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8015 genUnpackBits (result, "dptr", FPOINTER);
8018 size = AOP_SIZE (result);
8021 _startLazyDPSEvaluation ();
8028 emitcode ("movx", "a,@dptr");
8030 emitcode ("inc", "dptr");
8032 aopPut (AOP (result), "a", offset++);
8034 _endLazyDPSEvaluation ();
8037 freeAsmop (result, NULL, ic, TRUE);
8040 /*-----------------------------------------------------------------*/
8041 /* emitcodePointerGet - gget value from code space */
8042 /*-----------------------------------------------------------------*/
8044 emitcodePointerGet (operand * left,
8045 operand * result, iCode * ic)
8048 sym_link *retype = getSpec (operandType (result));
8050 aopOp (left, ic, FALSE, FALSE);
8052 /* if the operand is already in dptr
8053 then we do nothing else we move the value to dptr */
8054 if (AOP_TYPE (left) != AOP_STR)
8056 /* if this is remateriazable */
8057 if (AOP_TYPE (left) == AOP_IMMD)
8059 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8062 { /* we need to get it byte by byte */
8063 _startLazyDPSEvaluation ();
8064 if (AOP_TYPE (left) != AOP_DPTR)
8066 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8067 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8068 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8072 /* We need to generate a load to DPTR indirect through DPTR. */
8073 D (emitcode (";", "gencodePointerGet -- indirection special case.");
8075 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8076 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8077 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8078 emitcode ("pop", "dph");
8079 emitcode ("pop", "dpl");
8081 _endLazyDPSEvaluation ();
8084 /* so dptr know contains the address */
8085 freeAsmop (left, NULL, ic, TRUE);
8086 aopOp (result, ic, FALSE, TRUE);
8088 /* if bit then unpack */
8089 if (IS_BITVAR (retype))
8090 genUnpackBits (result, "dptr", CPOINTER);
8093 size = AOP_SIZE (result);
8096 _startLazyDPSEvaluation ();
8102 emitcode ("clr", "a");
8103 emitcode ("movc", "a,@a+dptr");
8105 emitcode ("inc", "dptr");
8106 aopPut (AOP (result), "a", offset++);
8108 _endLazyDPSEvaluation ();
8111 freeAsmop (result, NULL, ic, TRUE);
8114 /*-----------------------------------------------------------------*/
8115 /* genGenPointerGet - gget value from generic pointer space */
8116 /*-----------------------------------------------------------------*/
8118 genGenPointerGet (operand * left,
8119 operand * result, iCode * ic)
8122 sym_link *retype = getSpec (operandType (result));
8123 sym_link *letype = getSpec (operandType (left));
8125 D (emitcode (";", "genGenPointerGet "); );
8127 aopOp (left, ic, FALSE, TRUE);
8129 /* if the operand is already in dptr
8130 then we do nothing else we move the value to dptr */
8131 if (AOP_TYPE (left) != AOP_STR)
8133 /* if this is remateriazable */
8134 if (AOP_TYPE (left) == AOP_IMMD)
8136 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8137 emitcode ("mov", "b,#%d", pointerCode (retype));
8140 { /* we need to get it byte by byte */
8141 _startLazyDPSEvaluation ();
8142 if (AOP(left)->type==AOP_DPTR2) {
8144 l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8147 emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
8148 l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8151 emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
8152 l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8155 emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
8156 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8158 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8159 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8160 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8161 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8163 _endLazyDPSEvaluation ();
8166 /* so dptr know contains the address */
8167 freeAsmop (left, NULL, ic, TRUE);
8168 aopOp (result, ic, FALSE, TRUE);
8170 /* if bit then unpack */
8171 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8172 genUnpackBits (result, "dptr", GPOINTER);
8175 size = AOP_SIZE (result);
8180 emitcode ("lcall", "__gptrget");
8181 aopPut (AOP (result), "a", offset++);
8183 emitcode ("inc", "dptr");
8187 freeAsmop (result, NULL, ic, TRUE);
8190 /*-----------------------------------------------------------------*/
8191 /* genPointerGet - generate code for pointer get */
8192 /*-----------------------------------------------------------------*/
8194 genPointerGet (iCode * ic)
8196 operand *left, *result;
8197 sym_link *type, *etype;
8200 D (emitcode (";", "genPointerGet ");
8203 left = IC_LEFT (ic);
8204 result = IC_RESULT (ic);
8206 /* depending on the type of pointer we need to
8207 move it to the correct pointer register */
8208 type = operandType (left);
8209 etype = getSpec (type);
8210 /* if left is of type of pointer then it is simple */
8211 if (IS_PTR (type) && !IS_FUNC (type->next))
8212 p_type = DCL_TYPE (type);
8215 /* we have to go by the storage class */
8216 p_type = PTR_TYPE (SPEC_OCLS (etype));
8219 /* now that we have the pointer type we assign
8220 the pointer values */
8226 genNearPointerGet (left, result, ic);
8230 genPagedPointerGet (left, result, ic);
8234 genFarPointerGet (left, result, ic);
8238 emitcodePointerGet (left, result, ic);
8242 genGenPointerGet (left, result, ic);
8248 /*-----------------------------------------------------------------*/
8249 /* genPackBits - generates code for packed bit storage */
8250 /*-----------------------------------------------------------------*/
8252 genPackBits (sym_link * etype,
8254 char *rname, int p_type)
8262 blen = SPEC_BLEN (etype);
8263 bstr = SPEC_BSTR (etype);
8265 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8268 /* if the bit lenth is less than or */
8269 /* it exactly fits a byte then */
8270 if (SPEC_BLEN (etype) <= 8)
8272 shCount = SPEC_BSTR (etype);
8274 /* shift left acc */
8277 if (SPEC_BLEN (etype) < 8)
8278 { /* if smaller than a byte */
8284 emitcode ("mov", "b,a");
8285 emitcode ("mov", "a,@%s", rname);
8289 emitcode ("mov", "b,a");
8290 emitcode ("movx", "a,@dptr");
8294 emitcode ("push", "b");
8295 emitcode ("push", "acc");
8296 emitcode ("lcall", "__gptrget");
8297 emitcode ("pop", "b");
8301 emitcode ("anl", "a,#0x%02x", (unsigned char)
8302 ((unsigned char) (0xFF << (blen + bstr)) |
8303 (unsigned char) (0xFF >> (8 - bstr))));
8304 emitcode ("orl", "a,b");
8305 if (p_type == GPOINTER)
8306 emitcode ("pop", "b");
8313 emitcode ("mov", "@%s,a", rname);
8317 emitcode ("movx", "@dptr,a");
8321 emitcode ("lcall", "__gptrput");
8326 if (SPEC_BLEN (etype) <= 8)
8329 emitcode ("inc", "%s", rname);
8330 rLen = SPEC_BLEN (etype);
8332 /* now generate for lengths greater than one byte */
8336 l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8348 emitcode ("mov", "@%s,a", rname);
8351 emitcode ("mov", "@%s,%s", rname, l);
8356 emitcode ("movx", "@dptr,a");
8361 emitcode ("lcall", "__gptrput");
8364 emitcode ("inc", "%s", rname);
8369 /* last last was not complete */
8372 /* save the byte & read byte */
8376 emitcode ("mov", "b,a");
8377 emitcode ("mov", "a,@%s", rname);
8381 emitcode ("mov", "b,a");
8382 emitcode ("movx", "a,@dptr");
8386 emitcode ("push", "b");
8387 emitcode ("push", "acc");
8388 emitcode ("lcall", "__gptrget");
8389 emitcode ("pop", "b");
8393 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8394 emitcode ("orl", "a,b");
8397 if (p_type == GPOINTER)
8398 emitcode ("pop", "b");
8404 emitcode ("mov", "@%s,a", rname);
8408 emitcode ("movx", "@dptr,a");
8412 emitcode ("lcall", "__gptrput");
8416 /*-----------------------------------------------------------------*/
8417 /* genDataPointerSet - remat pointer to data space */
8418 /*-----------------------------------------------------------------*/
8420 genDataPointerSet (operand * right,
8424 int size, offset = 0;
8425 char *l, buffer[256];
8427 aopOp (right, ic, FALSE, FALSE);
8429 l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8430 size = AOP_SIZE (right);
8434 sprintf (buffer, "(%s + %d)", l + 1, offset);
8436 sprintf (buffer, "%s", l + 1);
8437 emitcode ("mov", "%s,%s", buffer,
8438 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8441 freeAsmop (right, NULL, ic, TRUE);
8442 freeAsmop (result, NULL, ic, TRUE);
8445 /*-----------------------------------------------------------------*/
8446 /* genNearPointerSet - emitcode for near pointer put */
8447 /*-----------------------------------------------------------------*/
8449 genNearPointerSet (operand * right,
8456 sym_link *retype, *letype;
8457 sym_link *ptype = operandType (result);
8459 retype = getSpec (operandType (right));
8460 letype = getSpec (ptype);
8462 aopOp (result, ic, FALSE, FALSE);
8464 /* if the result is rematerializable &
8465 in data space & not a bit variable */
8466 if (AOP_TYPE (result) == AOP_IMMD &&
8467 DCL_TYPE (ptype) == POINTER &&
8468 !IS_BITVAR (retype) &&
8469 !IS_BITVAR (letype))
8471 genDataPointerSet (right, result, ic);
8475 /* if the value is already in a pointer register
8476 then don't need anything more */
8477 if (!AOP_INPREG (AOP (result)))
8479 /* otherwise get a free pointer register */
8481 preg = getFreePtr (ic, &aop, FALSE);
8482 emitcode ("mov", "%s,%s",
8484 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8488 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8490 freeAsmop (result, NULL, ic, TRUE);
8491 aopOp (right, ic, FALSE, FALSE);
8493 /* if bitfield then unpack the bits */
8494 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8495 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8498 /* we have can just get the values */
8499 int size = AOP_SIZE (right);
8504 l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8508 emitcode ("mov", "@%s,a", rname);
8511 emitcode ("mov", "@%s,%s", rname, l);
8513 emitcode ("inc", "%s", rname);
8518 /* now some housekeeping stuff */
8521 /* we had to allocate for this iCode */
8522 freeAsmop (NULL, aop, ic, TRUE);
8526 /* we did not allocate which means left
8527 already in a pointer register, then
8528 if size > 0 && this could be used again
8529 we have to point it back to where it
8531 if (AOP_SIZE (right) > 1 &&
8532 !OP_SYMBOL (result)->remat &&
8533 (OP_SYMBOL (result)->liveTo > ic->seq ||
8536 int size = AOP_SIZE (right) - 1;
8538 emitcode ("dec", "%s", rname);
8543 freeAsmop (right, NULL, ic, TRUE);
8548 /*-----------------------------------------------------------------*/
8549 /* genPagedPointerSet - emitcode for Paged pointer put */
8550 /*-----------------------------------------------------------------*/
8552 genPagedPointerSet (operand * right,
8559 sym_link *retype, *letype;
8561 retype = getSpec (operandType (right));
8562 letype = getSpec (operandType (result));
8564 aopOp (result, ic, FALSE, FALSE);
8566 /* if the value is already in a pointer register
8567 then don't need anything more */
8568 if (!AOP_INPREG (AOP (result)))
8570 /* otherwise get a free pointer register */
8572 preg = getFreePtr (ic, &aop, FALSE);
8573 emitcode ("mov", "%s,%s",
8575 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8579 rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8581 freeAsmop (result, NULL, ic, TRUE);
8582 aopOp (right, ic, FALSE, FALSE);
8584 /* if bitfield then unpack the bits */
8585 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8586 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8589 /* we have can just get the values */
8590 int size = AOP_SIZE (right);
8595 l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8598 emitcode ("movx", "@%s,a", rname);
8601 emitcode ("inc", "%s", rname);
8607 /* now some housekeeping stuff */
8610 /* we had to allocate for this iCode */
8611 freeAsmop (NULL, aop, ic, TRUE);
8615 /* we did not allocate which means left
8616 already in a pointer register, then
8617 if size > 0 && this could be used again
8618 we have to point it back to where it
8620 if (AOP_SIZE (right) > 1 &&
8621 !OP_SYMBOL (result)->remat &&
8622 (OP_SYMBOL (result)->liveTo > ic->seq ||
8625 int size = AOP_SIZE (right) - 1;
8627 emitcode ("dec", "%s", rname);
8632 freeAsmop (right, NULL, ic, TRUE);
8637 /*-----------------------------------------------------------------*/
8638 /* genFarPointerSet - set value from far space */
8639 /*-----------------------------------------------------------------*/
8641 genFarPointerSet (operand * right,
8642 operand * result, iCode * ic)
8645 sym_link *retype = getSpec (operandType (right));
8646 sym_link *letype = getSpec (operandType (result));
8648 aopOp (result, ic, FALSE, FALSE);
8650 /* if the operand is already in dptr
8651 then we do nothing else we move the value to dptr */
8652 if (AOP_TYPE (result) != AOP_STR)
8654 /* if this is remateriazable */
8655 if (AOP_TYPE (result) == AOP_IMMD)
8656 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8659 /* we need to get it byte by byte */
8660 _startLazyDPSEvaluation ();
8661 if (AOP_TYPE (result) != AOP_DPTR)
8663 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8664 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8665 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8669 /* We need to generate a load to DPTR indirect through DPTR. */
8670 D (emitcode (";", "genFarPointerSet -- indirection special case.");
8672 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8673 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8674 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8675 emitcode ("pop", "dph");
8676 emitcode ("pop", "dpl");
8678 _endLazyDPSEvaluation ();
8681 /* so dptr know contains the address */
8682 freeAsmop (result, NULL, ic, TRUE);
8683 aopOp (right, ic, FALSE, TRUE);
8685 /* if bit then unpack */
8686 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8687 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8690 size = AOP_SIZE (right);
8693 _startLazyDPSEvaluation ();
8696 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8702 emitcode ("movx", "@dptr,a");
8704 emitcode ("inc", "dptr");
8706 _endLazyDPSEvaluation ();
8709 freeAsmop (right, NULL, ic, TRUE);
8712 /*-----------------------------------------------------------------*/
8713 /* genGenPointerSet - set value from generic pointer space */
8714 /*-----------------------------------------------------------------*/
8716 genGenPointerSet (operand * right,
8717 operand * result, iCode * ic)
8720 sym_link *retype = getSpec (operandType (right));
8721 sym_link *letype = getSpec (operandType (result));
8723 aopOp (result, ic, FALSE, TRUE);
8725 /* if the operand is already in dptr
8726 then we do nothing else we move the value to dptr */
8727 if (AOP_TYPE (result) != AOP_STR)
8729 _startLazyDPSEvaluation ();
8730 /* if this is remateriazable */
8731 if (AOP_TYPE (result) == AOP_IMMD)
8733 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8734 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8737 { /* we need to get it byte by byte */
8738 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8739 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8740 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8741 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8743 _endLazyDPSEvaluation ();
8745 /* so dptr know contains the address */
8746 freeAsmop (result, NULL, ic, TRUE);
8747 aopOp (right, ic, FALSE, TRUE);
8749 /* if bit then unpack */
8750 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8751 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8754 size = AOP_SIZE (right);
8757 _startLazyDPSEvaluation ();
8760 char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8766 emitcode ("lcall", "__gptrput");
8768 emitcode ("inc", "dptr");
8770 _endLazyDPSEvaluation ();
8773 freeAsmop (right, NULL, ic, TRUE);
8776 /*-----------------------------------------------------------------*/
8777 /* genPointerSet - stores the value into a pointer location */
8778 /*-----------------------------------------------------------------*/
8780 genPointerSet (iCode * ic)
8782 operand *right, *result;
8783 sym_link *type, *etype;
8786 D (emitcode (";", "genPointerSet ");
8789 right = IC_RIGHT (ic);
8790 result = IC_RESULT (ic);
8792 /* depending on the type of pointer we need to
8793 move it to the correct pointer register */
8794 type = operandType (result);
8795 etype = getSpec (type);
8796 /* if left is of type of pointer then it is simple */
8797 if (IS_PTR (type) && !IS_FUNC (type->next))
8799 p_type = DCL_TYPE (type);
8803 /* we have to go by the storage class */
8804 p_type = PTR_TYPE (SPEC_OCLS (etype));
8807 /* now that we have the pointer type we assign
8808 the pointer values */
8814 genNearPointerSet (right, result, ic);
8818 genPagedPointerSet (right, result, ic);
8822 genFarPointerSet (right, result, ic);
8826 genGenPointerSet (right, result, ic);
8832 /*-----------------------------------------------------------------*/
8833 /* genIfx - generate code for Ifx statement */
8834 /*-----------------------------------------------------------------*/
8836 genIfx (iCode * ic, iCode * popIc)
8838 operand *cond = IC_COND (ic);
8841 D (emitcode (";", "genIfx "););
8843 aopOp (cond, ic, FALSE, FALSE);
8845 /* get the value into acc */
8846 if (AOP_TYPE (cond) != AOP_CRY)
8850 /* the result is now in the accumulator */
8851 freeAsmop (cond, NULL, ic, TRUE);
8853 /* if there was something to be popped then do it */
8857 /* if the condition is a bit variable */
8858 if (isbit && IS_ITEMP (cond) &&
8860 genIfxJump (ic, SPIL_LOC (cond)->rname);
8861 else if (isbit && !IS_ITEMP (cond))
8862 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8864 genIfxJump (ic, "a");
8869 /*-----------------------------------------------------------------*/
8870 /* genAddrOf - generates code for address of */
8871 /*-----------------------------------------------------------------*/
8873 genAddrOf (iCode * ic)
8875 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8878 D (emitcode (";", "genAddrOf ");
8881 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8883 /* if the operand is on the stack then we
8884 need to get the stack offset of this
8888 /* if it has an offset then we need to compute
8892 emitcode ("mov", "a,_bp");
8893 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8894 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8898 /* we can just move _bp */
8899 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8901 /* fill the result with zero */
8902 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8905 if (options.stack10bit && size < (FPTRSIZE - 1))
8908 "*** warning: pointer to stack var truncated.\n");
8915 if (options.stack10bit && offset == 2)
8917 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8921 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8928 /* object not on stack then we need the name */
8929 size = AOP_SIZE (IC_RESULT (ic));
8934 char s[SDCC_NAME_MAX];
8936 sprintf (s, "#(%s >> %d)",
8940 sprintf (s, "#%s", sym->rname);
8941 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8945 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8949 /*-----------------------------------------------------------------*/
8950 /* genFarFarAssign - assignment when both are in far space */
8951 /*-----------------------------------------------------------------*/
8953 genFarFarAssign (operand * result, operand * right, iCode * ic)
8955 int size = AOP_SIZE (right);
8961 /* This is a net loss for size == 1, but a big gain
8964 D (emitcode (";", "genFarFarAssign (improved)");
8967 aopOp (result, ic, TRUE, TRUE);
8969 _startLazyDPSEvaluation ();
8972 aopPut (AOP (result),
8973 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
8976 _endLazyDPSEvaluation ();
8977 freeAsmop (result, NULL, ic, FALSE);
8978 freeAsmop (right, NULL, ic, FALSE);
8982 D (emitcode (";", "genFarFarAssign ");
8985 /* first push the right side on to the stack */
8986 _startLazyDPSEvaluation ();
8989 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8991 emitcode ("push", "acc");
8994 freeAsmop (right, NULL, ic, FALSE);
8995 /* now assign DPTR to result */
8996 aopOp (result, ic, FALSE, FALSE);
8997 size = AOP_SIZE (result);
9000 emitcode ("pop", "acc");
9001 aopPut (AOP (result), "a", --offset);
9003 freeAsmop (result, NULL, ic, FALSE);
9004 _endLazyDPSEvaluation ();
9008 /*-----------------------------------------------------------------*/
9009 /* genAssign - generate code for assignment */
9010 /*-----------------------------------------------------------------*/
9012 genAssign (iCode * ic)
9014 operand *result, *right;
9016 unsigned long lit = 0L;
9018 D (emitcode (";", "genAssign ");
9021 result = IC_RESULT (ic);
9022 right = IC_RIGHT (ic);
9024 /* if they are the same */
9025 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9028 aopOp (right, ic, FALSE, FALSE);
9030 emitcode (";", "genAssign: resultIsFar = %s",
9031 isOperandInFarSpace (result) ?
9034 /* special case both in far space */
9035 if ((AOP_TYPE (right) == AOP_DPTR ||
9036 AOP_TYPE (right) == AOP_DPTR2) &&
9037 /* IS_TRUE_SYMOP(result) && */
9038 isOperandInFarSpace (result))
9040 genFarFarAssign (result, right, ic);
9044 aopOp (result, ic, TRUE, FALSE);
9046 /* if they are the same registers */
9047 if (sameRegs (AOP (right), AOP (result)))
9050 /* if the result is a bit */
9051 if (AOP_TYPE (result) == AOP_CRY)
9054 /* if the right size is a literal then
9055 we know what the value is */
9056 if (AOP_TYPE (right) == AOP_LIT)
9058 if (((int) operandLitValue (right)))
9059 aopPut (AOP (result), one, 0);
9061 aopPut (AOP (result), zero, 0);
9065 /* the right is also a bit variable */
9066 if (AOP_TYPE (right) == AOP_CRY)
9068 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9069 aopPut (AOP (result), "c", 0);
9075 aopPut (AOP (result), "a", 0);
9079 /* bit variables done */
9081 size = AOP_SIZE (result);
9083 if (AOP_TYPE (right) == AOP_LIT)
9084 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9087 (AOP_TYPE (result) != AOP_REG) &&
9088 (AOP_TYPE (right) == AOP_LIT) &&
9089 !IS_FLOAT (operandType (right)))
9091 D (emitcode (";", "Kevin's better literal load code");
9093 _startLazyDPSEvaluation ();
9094 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9096 aopPut (AOP (result),
9097 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9102 /* And now fill the rest with zeros. */
9105 emitcode ("clr", "a");
9109 aopPut (AOP (result), "a", offset++);
9111 _endLazyDPSEvaluation ();
9115 _startLazyDPSEvaluation ();
9118 aopPut (AOP (result),
9119 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9123 _endLazyDPSEvaluation ();
9127 freeAsmop (right, NULL, ic, FALSE);
9128 freeAsmop (result, NULL, ic, TRUE);
9131 /*-----------------------------------------------------------------*/
9132 /* genJumpTab - generates code for jump table */
9133 /*-----------------------------------------------------------------*/
9135 genJumpTab (iCode * ic)
9140 D (emitcode (";", "genJumpTab ");
9143 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9144 /* get the condition into accumulator */
9145 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9147 /* multiply by four! */
9148 emitcode ("add", "a,acc");
9149 emitcode ("add", "a,acc");
9150 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9152 jtab = newiTempLabel (NULL);
9153 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9154 emitcode ("jmp", "@a+dptr");
9155 emitcode ("", "%05d$:", jtab->key + 100);
9156 /* now generate the jump labels */
9157 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9158 jtab = setNextItem (IC_JTLABELS (ic)))
9159 emitcode ("ljmp", "%05d$", jtab->key + 100);
9163 /*-----------------------------------------------------------------*/
9164 /* genCast - gen code for casting */
9165 /*-----------------------------------------------------------------*/
9167 genCast (iCode * ic)
9169 operand *result = IC_RESULT (ic);
9170 sym_link *ctype = operandType (IC_LEFT (ic));
9171 sym_link *rtype = operandType (IC_RIGHT (ic));
9172 operand *right = IC_RIGHT (ic);
9175 D (emitcode (";", "genCast ");
9178 /* if they are equivalent then do nothing */
9179 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9182 aopOp (right, ic, FALSE, FALSE);
9183 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9185 /* if the result is a bit */
9186 if (AOP_TYPE (result) == AOP_CRY)
9188 /* if the right size is a literal then
9189 we know what the value is */
9190 if (AOP_TYPE (right) == AOP_LIT)
9192 if (((int) operandLitValue (right)))
9193 aopPut (AOP (result), one, 0);
9195 aopPut (AOP (result), zero, 0);
9200 /* the right is also a bit variable */
9201 if (AOP_TYPE (right) == AOP_CRY)
9203 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9204 aopPut (AOP (result), "c", 0);
9210 aopPut (AOP (result), "a", 0);
9214 /* if they are the same size : or less */
9215 if (AOP_SIZE (result) <= AOP_SIZE (right))
9218 /* if they are in the same place */
9219 if (sameRegs (AOP (right), AOP (result)))
9222 /* if they in different places then copy */
9223 size = AOP_SIZE (result);
9225 _startLazyDPSEvaluation ();
9228 aopPut (AOP (result),
9229 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9233 _endLazyDPSEvaluation ();
9238 /* if the result is of type pointer */
9243 sym_link *type = operandType (right);
9245 /* pointer to generic pointer */
9246 if (IS_GENPTR (ctype))
9252 p_type = DCL_TYPE (type);
9256 #if OLD_CAST_BEHAVIOR
9257 /* KV: we are converting a non-pointer type to
9258 * a generic pointer. This (ifdef'd out) code
9259 * says that the resulting generic pointer
9260 * should have the same class as the storage
9261 * location of the non-pointer variable.
9263 * For example, converting an int (which happens
9264 * to be stored in DATA space) to a pointer results
9265 * in a DATA generic pointer; if the original int
9266 * in XDATA space, so will be the resulting pointer.
9268 * I don't like that behavior, and thus this change:
9269 * all such conversions will be forced to XDATA and
9270 * throw a warning. If you want some non-XDATA
9271 * type, or you want to suppress the warning, you
9272 * must go through an intermediate cast, like so:
9274 * char _generic *gp = (char _xdata *)(intVar);
9276 sym_link *etype = getSpec (type);
9278 /* we have to go by the storage class */
9279 if (SPEC_OCLS (etype) != generic)
9281 p_type = PTR_TYPE (SPEC_OCLS (etype));
9286 /* Converting unknown class (i.e. register variable)
9287 * to generic pointer. This is not good, but
9288 * we'll make a guess (and throw a warning).
9291 werror (W_INT_TO_GEN_PTR_CAST);
9295 /* the first two bytes are known */
9296 size = GPTRSIZE - 1;
9298 _startLazyDPSEvaluation ();
9301 aopPut (AOP (result),
9302 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9306 _endLazyDPSEvaluation ();
9308 /* the last byte depending on type */
9326 /* this should never happen */
9327 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9328 "got unknown pointer type");
9331 aopPut (AOP (result), l, GPTRSIZE - 1);
9335 /* just copy the pointers */
9336 size = AOP_SIZE (result);
9338 _startLazyDPSEvaluation ();
9341 aopPut (AOP (result),
9342 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9346 _endLazyDPSEvaluation ();
9350 /* so we now know that the size of destination is greater
9351 than the size of the source */
9352 /* we move to result for the size of source */
9353 size = AOP_SIZE (right);
9355 _startLazyDPSEvaluation ();
9358 aopPut (AOP (result),
9359 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9363 _endLazyDPSEvaluation ();
9365 /* now depending on the sign of the source && destination */
9366 size = AOP_SIZE (result) - AOP_SIZE (right);
9367 /* if unsigned or not an integral type */
9368 /* also, if the source is a bit, we don't need to sign extend, because
9369 * it can't possibly have set the sign bit.
9371 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9375 aopPut (AOP (result), zero, offset++);
9380 /* we need to extend the sign :{ */
9381 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9382 FALSE, FALSE, TRUE);
9384 emitcode ("rlc", "a");
9385 emitcode ("subb", "a,acc");
9387 aopPut (AOP (result), "a", offset++);
9390 /* we are done hurray !!!! */
9393 freeAsmop (right, NULL, ic, TRUE);
9394 freeAsmop (result, NULL, ic, TRUE);
9398 /*-----------------------------------------------------------------*/
9399 /* genDjnz - generate decrement & jump if not zero instrucion */
9400 /*-----------------------------------------------------------------*/
9402 genDjnz (iCode * ic, iCode * ifx)
9408 /* if the if condition has a false label
9409 then we cannot save */
9413 /* if the minus is not of the form
9415 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9416 !IS_OP_LITERAL (IC_RIGHT (ic)))
9419 if (operandLitValue (IC_RIGHT (ic)) != 1)
9422 /* if the size of this greater than one then no
9424 if (getSize (operandType (IC_RESULT (ic))) > 1)
9427 /* otherwise we can save BIG */
9428 D(emitcode(";", "genDjnz"););
9430 lbl = newiTempLabel (NULL);
9431 lbl1 = newiTempLabel (NULL);
9433 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9435 if (AOP_NEEDSACC(IC_RESULT(ic)))
9437 /* If the result is accessed indirectly via
9438 * the accumulator, we must explicitly write
9439 * it back after the decrement.
9441 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9443 if (strcmp(rByte, "a"))
9445 /* Something is hopelessly wrong */
9446 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9447 __FILE__, __LINE__);
9448 /* We can just give up; the generated code will be inefficient,
9451 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9454 emitcode ("dec", "%s", rByte);
9455 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9456 emitcode ("jnz", "%05d$", lbl->key + 100);
9458 else if (IS_AOP_PREG (IC_RESULT (ic)))
9460 emitcode ("dec", "%s",
9461 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9462 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9463 emitcode ("jnz", "%05d$", lbl->key + 100);
9467 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9470 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9471 emitcode ("", "%05d$:", lbl->key + 100);
9472 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9473 emitcode ("", "%05d$:", lbl1->key + 100);
9475 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9480 /*-----------------------------------------------------------------*/
9481 /* genReceive - generate code for a receive iCode */
9482 /*-----------------------------------------------------------------*/
9484 genReceive (iCode * ic)
9487 D (emitcode (";", "genReceive ");
9490 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9491 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9492 IS_TRUE_SYMOP (IC_RESULT (ic))))
9494 int size = getSize (operandType (IC_RESULT (ic)));
9495 int offset = fReturnSizeDS390 - size;
9498 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9499 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9502 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9503 size = AOP_SIZE (IC_RESULT (ic));
9507 emitcode ("pop", "acc");
9508 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9515 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9517 assignResultValue (IC_RESULT (ic));
9520 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9523 /*-----------------------------------------------------------------*/
9524 /* gen390Code - generate code for Dallas 390 based controllers */
9525 /*-----------------------------------------------------------------*/
9527 gen390Code (iCode * lic)
9532 lineHead = lineCurr = NULL;
9536 /* print the allocation information */
9538 printAllocInfo (currFunc, codeOutFile);
9540 /* if debug information required */
9541 if (options.debug && currFunc)
9543 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9545 if (IS_STATIC (currFunc->etype))
9546 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9548 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9551 /* stack pointer name */
9552 if (options.useXstack)
9558 for (ic = lic; ic; ic = ic->next)
9561 if (cln != ic->lineno)
9566 emitcode ("", "C$%s$%d$%d$%d ==.",
9567 FileBaseName (ic->filename), ic->lineno,
9568 ic->level, ic->block);
9571 emitcode (";", "%s %d", ic->filename, ic->lineno);
9574 /* if the result is marked as
9575 spilt and rematerializable or code for
9576 this has already been generated then
9578 if (resultRemat (ic) || ic->generated)
9581 /* depending on the operation */
9601 /* IPOP happens only when trying to restore a
9602 spilt live range, if there is an ifx statement
9603 following this pop then the if statement might
9604 be using some of the registers being popped which
9605 would destory the contents of the register so
9606 we need to check for this condition and handle it */
9608 ic->next->op == IFX &&
9609 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9610 genIfx (ic->next, ic);
9628 genEndFunction (ic);
9648 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9665 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9669 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9676 /* note these two are xlated by algebraic equivalence
9677 during parsing SDCC.y */
9678 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9679 "got '>=' or '<=' shouldn't have come here");
9683 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9695 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9699 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9703 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9730 case GET_VALUE_AT_ADDRESS:
9735 if (POINTER_SET (ic))
9762 addSet (&_G.sendSet, ic);
9771 /* now we are ready to call the
9772 peep hole optimizer */
9773 if (!options.nopeep)
9774 peepHole (&lineHead);
9776 /* now do the actual printing */
9777 printLine (lineHead, codeOutFile);