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. */
2225 emitcode ("mov", "b,%s", fReturn[1]);
2228 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2229 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2233 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2235 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2240 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2243 assignResultValue (IC_RESULT (ic));
2245 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2249 /* adjust the stack for parameters if
2254 if (ic->parmBytes > 3)
2256 emitcode ("mov", "a,%s", spname);
2257 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2258 emitcode ("mov", "%s,a", spname);
2261 for (i = 0; i < ic->parmBytes; i++)
2262 emitcode ("dec", "%s", spname);
2266 /* if register bank was saved then pop them */
2268 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2270 /* if we hade saved some registers then unsave them */
2271 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2272 unsaveRegisters (ic);
2277 /*-----------------------------------------------------------------*/
2278 /* genPcall - generates a call by pointer statement */
2279 /*-----------------------------------------------------------------*/
2281 genPcall (iCode * ic)
2284 symbol *rlbl = newiTempLabel (NULL);
2286 D (emitcode (";", "genPcall ");
2290 /* if caller saves & we have not saved then */
2294 /* if we are calling a function that is not using
2295 the same register bank then we need to save the
2296 destination registers on the stack */
2297 detype = getSpec (operandType (IC_LEFT (ic)));
2299 IS_ISR (currFunc->etype) &&
2300 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2301 saverbank (SPEC_BANK (detype), ic, TRUE);
2304 /* push the return address on to the stack */
2305 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2306 emitcode ("push", "acc");
2307 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2308 emitcode ("push", "acc");
2310 if (options.model == MODEL_FLAT24)
2312 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2313 emitcode ("push", "acc");
2316 /* now push the calling address */
2317 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2319 pushSide (IC_LEFT (ic), FPTRSIZE);
2321 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2323 /* if send set is not empty the assign */
2328 for (sic = setFirstItem (_G.sendSet); sic;
2329 sic = setNextItem (_G.sendSet))
2331 int size, offset = 0;
2333 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2334 size = AOP_SIZE (IC_LEFT (sic));
2335 _startLazyDPSEvaluation ();
2338 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2339 FALSE, FALSE, TRUE);
2340 if (strcmp (l, fReturn[offset]))
2342 emitcode ("mov", "%s,%s",
2348 _endLazyDPSEvaluation ();
2349 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2354 emitcode ("ret", "");
2355 emitcode ("", "%05d$:", (rlbl->key + 100));
2358 /* if we need assign a result value */
2359 if ((IS_ITEMP (IC_RESULT (ic)) &&
2360 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2361 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2362 IS_TRUE_SYMOP (IC_RESULT (ic)))
2366 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2369 assignResultValue (IC_RESULT (ic));
2371 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2374 /* adjust the stack for parameters if
2379 if (ic->parmBytes > 3)
2381 emitcode ("mov", "a,%s", spname);
2382 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2383 emitcode ("mov", "%s,a", spname);
2386 for (i = 0; i < ic->parmBytes; i++)
2387 emitcode ("dec", "%s", spname);
2391 /* if register bank was saved then unsave them */
2393 (SPEC_BANK (currFunc->etype) !=
2394 SPEC_BANK (detype)))
2395 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2397 /* if we hade saved some registers then
2400 unsaveRegisters (ic);
2404 /*-----------------------------------------------------------------*/
2405 /* resultRemat - result is rematerializable */
2406 /*-----------------------------------------------------------------*/
2408 resultRemat (iCode * ic)
2410 if (SKIP_IC (ic) || ic->op == IFX)
2413 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2415 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2416 if (sym->remat && !POINTER_SET (ic))
2423 #if defined(__BORLANDC__) || defined(_MSC_VER)
2424 #define STRCASECMP stricmp
2426 #define STRCASECMP strcasecmp
2429 /*-----------------------------------------------------------------*/
2430 /* inExcludeList - return 1 if the string is in exclude Reg list */
2431 /*-----------------------------------------------------------------*/
2433 inExcludeList (char *s)
2437 if (options.excludeRegs[i] &&
2438 STRCASECMP (options.excludeRegs[i], "none") == 0)
2441 for (i = 0; options.excludeRegs[i]; i++)
2443 if (options.excludeRegs[i] &&
2444 STRCASECMP (s, options.excludeRegs[i]) == 0)
2450 /*-----------------------------------------------------------------*/
2451 /* genFunction - generated code for function entry */
2452 /*-----------------------------------------------------------------*/
2454 genFunction (iCode * ic)
2459 D (emitcode (";", "genFunction ");
2463 /* create the function header */
2464 emitcode (";", "-----------------------------------------");
2465 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2466 emitcode (";", "-----------------------------------------");
2468 emitcode ("", "%s:", sym->rname);
2469 fetype = getSpec (operandType (IC_LEFT (ic)));
2471 /* if critical function then turn interrupts off */
2472 if (SPEC_CRTCL (fetype))
2473 emitcode ("clr", "ea");
2475 /* here we need to generate the equates for the
2476 register bank if required */
2477 if (SPEC_BANK (fetype) != rbank)
2481 rbank = SPEC_BANK (fetype);
2482 for (i = 0; i < ds390_nRegs; i++)
2484 if (strcmp (regs390[i].base, "0") == 0)
2485 emitcode ("", "%s = 0x%02x",
2487 8 * rbank + regs390[i].offset);
2489 emitcode ("", "%s = %s + 0x%02x",
2492 8 * rbank + regs390[i].offset);
2496 /* if this is an interrupt service routine then
2497 save acc, b, dpl, dph */
2498 if (IS_ISR (sym->etype))
2501 if (!inExcludeList ("acc"))
2502 emitcode ("push", "acc");
2503 if (!inExcludeList ("b"))
2504 emitcode ("push", "b");
2505 if (!inExcludeList ("dpl"))
2506 emitcode ("push", "dpl");
2507 if (!inExcludeList ("dph"))
2508 emitcode ("push", "dph");
2509 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2511 emitcode ("push", "dpx");
2512 /* Make sure we're using standard DPTR */
2513 emitcode ("push", "dps");
2514 emitcode ("mov", "dps, #0x00");
2515 if (options.stack10bit)
2517 /* This ISR could conceivably use DPTR2. Better save it. */
2518 emitcode ("push", "dpl1");
2519 emitcode ("push", "dph1");
2520 emitcode ("push", "dpx1");
2521 emitcode ("push", DP2_RESULT_REG);
2524 /* if this isr has no bank i.e. is going to
2525 run with bank 0 , then we need to save more
2527 if (!SPEC_BANK (sym->etype))
2530 /* if this function does not call any other
2531 function then we can be economical and
2532 save only those registers that are used */
2537 /* if any registers used */
2540 /* save the registers used */
2541 for (i = 0; i < sym->regsUsed->size; i++)
2543 if (bitVectBitValue (sym->regsUsed, i) ||
2544 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2545 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2552 /* this function has a function call cannot
2553 determines register usage so we will have the
2555 saverbank (0, ic, FALSE);
2561 /* if callee-save to be used for this function
2562 then save the registers being used in this function */
2563 if (sym->calleeSave)
2567 /* if any registers used */
2570 /* save the registers used */
2571 for (i = 0; i < sym->regsUsed->size; i++)
2573 if (bitVectBitValue (sym->regsUsed, i) ||
2574 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2576 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2584 /* set the register bank to the desired value */
2585 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2587 emitcode ("push", "psw");
2588 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2591 if (IS_RENT (sym->etype) || options.stackAuto)
2594 if (options.useXstack)
2596 emitcode ("mov", "r0,%s", spname);
2597 emitcode ("mov", "a,_bp");
2598 emitcode ("movx", "@r0,a");
2599 emitcode ("inc", "%s", spname);
2603 /* set up the stack */
2604 emitcode ("push", "_bp"); /* save the callers stack */
2606 emitcode ("mov", "_bp,%s", spname);
2609 /* adjust the stack for the function */
2615 werror (W_STACK_OVERFLOW, sym->name);
2617 if (i > 3 && sym->recvSize < 4)
2620 emitcode ("mov", "a,sp");
2621 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2622 emitcode ("mov", "sp,a");
2627 emitcode ("inc", "sp");
2633 emitcode ("mov", "a,_spx");
2634 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2635 emitcode ("mov", "_spx,a");
2640 /*-----------------------------------------------------------------*/
2641 /* genEndFunction - generates epilogue for functions */
2642 /*-----------------------------------------------------------------*/
2644 genEndFunction (iCode * ic)
2646 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2648 D (emitcode (";", "genEndFunction ");
2651 if (IS_RENT (sym->etype) || options.stackAuto)
2653 emitcode ("mov", "%s,_bp", spname);
2656 /* if use external stack but some variables were
2657 added to the local stack then decrement the
2659 if (options.useXstack && sym->stack)
2661 emitcode ("mov", "a,sp");
2662 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2663 emitcode ("mov", "sp,a");
2667 if ((IS_RENT (sym->etype) || options.stackAuto))
2669 if (options.useXstack)
2671 emitcode ("mov", "r0,%s", spname);
2672 emitcode ("movx", "a,@r0");
2673 emitcode ("mov", "_bp,a");
2674 emitcode ("dec", "%s", spname);
2678 emitcode ("pop", "_bp");
2682 /* restore the register bank */
2683 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2684 emitcode ("pop", "psw");
2686 if (IS_ISR (sym->etype))
2689 /* now we need to restore the registers */
2690 /* if this isr has no bank i.e. is going to
2691 run with bank 0 , then we need to save more
2693 if (!SPEC_BANK (sym->etype))
2696 /* if this function does not call any other
2697 function then we can be economical and
2698 save only those registers that are used */
2703 /* if any registers used */
2706 /* save the registers used */
2707 for (i = sym->regsUsed->size; i >= 0; i--)
2709 if (bitVectBitValue (sym->regsUsed, i) ||
2710 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2711 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2718 /* this function has a function call cannot
2719 determines register usage so we will have the
2721 unsaverbank (0, ic, FALSE);
2725 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2727 if (options.stack10bit)
2729 emitcode ("pop", DP2_RESULT_REG);
2730 emitcode ("pop", "dpx1");
2731 emitcode ("pop", "dph1");
2732 emitcode ("pop", "dpl1");
2734 emitcode ("pop", "dps");
2735 emitcode ("pop", "dpx");
2737 if (!inExcludeList ("dph"))
2738 emitcode ("pop", "dph");
2739 if (!inExcludeList ("dpl"))
2740 emitcode ("pop", "dpl");
2741 if (!inExcludeList ("b"))
2742 emitcode ("pop", "b");
2743 if (!inExcludeList ("acc"))
2744 emitcode ("pop", "acc");
2746 if (SPEC_CRTCL (sym->etype))
2747 emitcode ("setb", "ea");
2749 /* if debug then send end of function */
2750 /* if (options.debug && currFunc) { */
2754 emitcode ("", "C$%s$%d$%d$%d ==.",
2755 FileBaseName (ic->filename), currFunc->lastLine,
2756 ic->level, ic->block);
2757 if (IS_STATIC (currFunc->etype))
2758 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2760 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2764 emitcode ("reti", "");
2768 if (SPEC_CRTCL (sym->etype))
2769 emitcode ("setb", "ea");
2771 if (sym->calleeSave)
2775 /* if any registers used */
2778 /* save the registers used */
2779 for (i = sym->regsUsed->size; i >= 0; i--)
2781 if (bitVectBitValue (sym->regsUsed, i) ||
2782 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2783 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2789 /* if debug then send end of function */
2793 emitcode ("", "C$%s$%d$%d$%d ==.",
2794 FileBaseName (ic->filename), currFunc->lastLine,
2795 ic->level, ic->block);
2796 if (IS_STATIC (currFunc->etype))
2797 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2799 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2803 emitcode ("ret", "");
2808 /*-----------------------------------------------------------------*/
2809 /* genRet - generate code for return statement */
2810 /*-----------------------------------------------------------------*/
2814 int size, offset = 0, pushed = 0;
2816 D (emitcode (";", "genRet ");
2819 /* if we have no return value then
2820 just generate the "ret" */
2824 /* we have something to return then
2825 move the return value into place */
2826 aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2827 size = AOP_SIZE (IC_LEFT (ic));
2829 _startLazyDPSEvaluation ();
2833 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2835 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2836 FALSE, TRUE, FALSE);
2837 emitcode ("push", "%s", l);
2842 l = aopGet (AOP (IC_LEFT (ic)), offset,
2843 FALSE, FALSE, FALSE);
2844 if (strcmp (fReturn[offset], l))
2845 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2848 _endLazyDPSEvaluation ();
2855 if (strcmp (fReturn[pushed], "a"))
2856 emitcode ("pop", fReturn[pushed]);
2858 emitcode ("pop", "acc");
2861 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2864 /* generate a jump to the return label
2865 if the next is not the return statement */
2866 if (!(ic->next && ic->next->op == LABEL &&
2867 IC_LABEL (ic->next) == returnLabel))
2869 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2873 /*-----------------------------------------------------------------*/
2874 /* genLabel - generates a label */
2875 /*-----------------------------------------------------------------*/
2877 genLabel (iCode * ic)
2879 /* special case never generate */
2880 if (IC_LABEL (ic) == entryLabel)
2883 D (emitcode (";", "genLabel ");
2886 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2889 /*-----------------------------------------------------------------*/
2890 /* genGoto - generates a ljmp */
2891 /*-----------------------------------------------------------------*/
2893 genGoto (iCode * ic)
2895 D (emitcode (";", "genGoto ");
2897 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2900 /*-----------------------------------------------------------------*/
2901 /* findLabelBackwards: walks back through the iCode chain looking */
2902 /* for the given label. Returns number of iCode instructions */
2903 /* between that label and given ic. */
2904 /* Returns zero if label not found. */
2905 /*-----------------------------------------------------------------*/
2907 findLabelBackwards (iCode * ic, int key)
2916 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2918 /* printf("findLabelBackwards = %d\n", count); */
2926 /*-----------------------------------------------------------------*/
2927 /* genPlusIncr :- does addition with increment if possible */
2928 /*-----------------------------------------------------------------*/
2930 genPlusIncr (iCode * ic)
2932 unsigned int icount;
2933 unsigned int size = getDataSize (IC_RESULT (ic));
2935 /* will try to generate an increment */
2936 /* if the right side is not a literal
2938 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2941 /* if the literal value of the right hand side
2942 is greater than 4 then it is not worth it */
2943 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2946 /* if increment 16 bits in register */
2948 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2949 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2950 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2958 /* If the next instruction is a goto and the goto target
2959 * is <= 5 instructions previous to this, we can generate
2960 * jumps straight to that target.
2962 if (ic->next && ic->next->op == GOTO
2963 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2966 emitcode (";", "tail increment optimized (range %d)", labelRange);
2967 tlbl = IC_LABEL (ic->next);
2972 tlbl = newiTempLabel (NULL);
2975 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2976 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2977 IS_AOP_PREG (IC_RESULT (ic)))
2978 emitcode ("cjne", "%s,#0x00,%05d$"
2979 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2983 emitcode ("clr", "a");
2984 emitcode ("cjne", "a,%s,%05d$"
2985 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2989 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2992 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2993 IS_AOP_PREG (IC_RESULT (ic)))
2994 emitcode ("cjne", "%s,#0x00,%05d$"
2995 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2998 emitcode ("cjne", "a,%s,%05d$"
2999 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3002 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3006 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3007 IS_AOP_PREG (IC_RESULT (ic)))
3008 emitcode ("cjne", "%s,#0x00,%05d$"
3009 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3013 emitcode ("cjne", "a,%s,%05d$"
3014 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3017 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3022 emitcode ("", "%05d$:", tlbl->key + 100);
3027 /* if the sizes are greater than 1 then we cannot */
3028 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3029 AOP_SIZE (IC_LEFT (ic)) > 1)
3032 /* we can if the aops of the left & result match or
3033 if they are in registers and the registers are the
3036 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3037 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3038 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3043 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3044 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3045 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3050 _startLazyDPSEvaluation ();
3053 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3055 _endLazyDPSEvaluation ();
3064 /*-----------------------------------------------------------------*/
3065 /* outBitAcc - output a bit in acc */
3066 /*-----------------------------------------------------------------*/
3068 outBitAcc (operand * result)
3070 symbol *tlbl = newiTempLabel (NULL);
3071 /* if the result is a bit */
3072 if (AOP_TYPE (result) == AOP_CRY)
3074 aopPut (AOP (result), "a", 0);
3078 emitcode ("jz", "%05d$", tlbl->key + 100);
3079 emitcode ("mov", "a,%s", one);
3080 emitcode ("", "%05d$:", tlbl->key + 100);
3085 /*-----------------------------------------------------------------*/
3086 /* genPlusBits - generates code for addition of two bits */
3087 /*-----------------------------------------------------------------*/
3089 genPlusBits (iCode * ic)
3091 D (emitcode (";", "genPlusBits ");
3093 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3095 symbol *lbl = newiTempLabel (NULL);
3096 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3097 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3098 emitcode ("cpl", "c");
3099 emitcode ("", "%05d$:", (lbl->key + 100));
3100 outBitC (IC_RESULT (ic));
3104 emitcode ("clr", "a");
3105 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3106 emitcode ("rlc", "a");
3107 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3108 emitcode ("addc", "a,#0x00");
3109 outAcc (IC_RESULT (ic));
3114 adjustArithmeticResult (iCode * ic)
3116 if (opIsGptr (IC_RESULT (ic)) &&
3117 opIsGptr (IC_LEFT (ic)) &&
3118 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3120 aopPut (AOP (IC_RESULT (ic)),
3121 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3125 if (opIsGptr (IC_RESULT (ic)) &&
3126 opIsGptr (IC_RIGHT (ic)) &&
3127 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3129 aopPut (AOP (IC_RESULT (ic)),
3130 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3134 if (opIsGptr (IC_RESULT (ic)) &&
3135 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3136 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3137 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3138 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3141 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3142 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3146 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3147 // (because all three operands are in far space).
3148 #define AOP_OP_3(ic) \
3149 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3150 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3151 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3152 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3153 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3154 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3156 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3158 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3161 // Macro to aopOp all three operands of an ic. If this cannot be done,
3162 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3163 // will be set TRUE. The caller must then handle the case specially, noting
3164 // that the IC_RESULT operand is not aopOp'd.
3165 #define AOP_OP_3_NOFATAL(ic, rc) \
3166 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3167 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3168 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3169 isOperandInFarSpace(IC_RESULT(ic))) \
3171 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3176 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3177 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3179 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3180 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3182 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3184 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3188 // aopOp the left & right operands of an ic.
3189 #define AOP_OP_2(ic) \
3190 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3191 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3193 // convienience macro.
3194 #define AOP_SET_LOCALS(ic) \
3195 left = IC_LEFT(ic); \
3196 right = IC_RIGHT(ic); \
3197 result = IC_RESULT(ic);
3200 // Given an integer value of pushedSize bytes on the stack,
3201 // adjust it to be resultSize bytes, either by discarding
3202 // the most significant bytes or by zero-padding.
3204 // On exit from this macro, pushedSize will have been adjusted to
3205 // equal resultSize, and ACC may be trashed.
3206 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3207 /* If the pushed data is bigger than the result, \
3208 * simply discard unused bytes. Icky, but works. \
3210 while (pushedSize > resultSize) \
3212 D (emitcode (";", "discarding unused result byte."););\
3213 emitcode ("pop", "acc"); \
3216 if (pushedSize < resultSize) \
3218 emitcode ("clr", "a"); \
3219 /* Conversly, we haven't pushed enough here. \
3220 * just zero-pad, and all is well. \
3222 while (pushedSize < resultSize) \
3224 emitcode("push", "acc"); \
3228 assert(pushedSize == resultSize);
3230 /*-----------------------------------------------------------------*/
3231 /* genPlus - generates code for addition */
3232 /*-----------------------------------------------------------------*/
3234 genPlus (iCode * ic)
3236 int size, offset = 0;
3237 bool pushResult = FALSE;
3240 D (emitcode (";", "genPlus "););
3242 /* special cases :- */
3244 AOP_OP_3_NOFATAL (ic, pushResult);
3247 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3252 /* if literal, literal on the right or
3253 if left requires ACC or right is already
3255 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3256 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3257 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3259 operand *t = IC_RIGHT (ic);
3260 IC_RIGHT (ic) = IC_LEFT (ic);
3262 emitcode (";", "Swapped plus args.");
3265 /* if both left & right are in bit
3267 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3268 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3274 /* if left in bit space & right literal */
3275 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3276 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3278 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3279 /* if result in bit space */
3280 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3282 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3283 emitcode ("cpl", "c");
3284 outBitC (IC_RESULT (ic));
3288 size = getDataSize (IC_RESULT (ic));
3289 _startLazyDPSEvaluation ();
3292 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3293 emitcode ("addc", "a,#00");
3294 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3296 _endLazyDPSEvaluation ();
3301 /* if I can do an increment instead
3302 of add then GOOD for ME */
3303 if (genPlusIncr (ic) == TRUE)
3305 emitcode (";", "did genPlusIncr");
3310 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3312 _startLazyDPSEvaluation ();
3315 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3317 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3319 emitcode ("add", "a,%s",
3320 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3322 emitcode ("addc", "a,%s",
3323 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3327 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3329 emitcode ("add", "a,%s",
3330 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3332 emitcode ("addc", "a,%s",
3333 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3337 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3341 emitcode ("push", "acc");
3345 _endLazyDPSEvaluation ();
3349 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3351 size = getDataSize (IC_LEFT (ic));
3352 rSize = getDataSize (IC_RESULT (ic));
3354 ADJUST_PUSHED_RESULT(size, rSize);
3356 _startLazyDPSEvaluation ();
3359 emitcode ("pop", "acc");
3360 aopPut (AOP (IC_RESULT (ic)), "a", size);
3362 _endLazyDPSEvaluation ();
3365 adjustArithmeticResult (ic);
3368 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3369 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3370 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3373 /*-----------------------------------------------------------------*/
3374 /* genMinusDec :- does subtraction with deccrement if possible */
3375 /*-----------------------------------------------------------------*/
3377 genMinusDec (iCode * ic)
3379 unsigned int icount;
3380 unsigned int size = getDataSize (IC_RESULT (ic));
3382 /* will try to generate an increment */
3383 /* if the right side is not a literal
3385 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3388 /* if the literal value of the right hand side
3389 is greater than 4 then it is not worth it */
3390 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3393 /* if decrement 16 bits in register */
3394 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3395 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3396 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3404 /* If the next instruction is a goto and the goto target
3405 * is <= 5 instructions previous to this, we can generate
3406 * jumps straight to that target.
3408 if (ic->next && ic->next->op == GOTO
3409 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3412 emitcode (";", "tail decrement optimized (range %d)", labelRange);
3413 tlbl = IC_LABEL (ic->next);
3418 tlbl = newiTempLabel (NULL);
3422 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3423 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3424 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3425 IS_AOP_PREG (IC_RESULT (ic)))
3426 emitcode ("cjne", "%s,#0xff,%05d$"
3427 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3431 emitcode ("mov", "a,#0xff");
3432 emitcode ("cjne", "a,%s,%05d$"
3433 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3436 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3439 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3440 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3441 IS_AOP_PREG (IC_RESULT (ic)))
3442 emitcode ("cjne", "%s,#0xff,%05d$"
3443 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3447 emitcode ("cjne", "a,%s,%05d$"
3448 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3451 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3455 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3456 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3457 IS_AOP_PREG (IC_RESULT (ic)))
3458 emitcode ("cjne", "%s,#0xff,%05d$"
3459 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3463 emitcode ("cjne", "a,%s,%05d$"
3464 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3467 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3471 emitcode ("", "%05d$:", tlbl->key + 100);
3476 /* if the sizes are greater than 1 then we cannot */
3477 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3478 AOP_SIZE (IC_LEFT (ic)) > 1)
3481 /* we can if the aops of the left & result match or
3482 if they are in registers and the registers are the
3485 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3486 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3487 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3490 _startLazyDPSEvaluation ();
3493 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3495 _endLazyDPSEvaluation ();
3503 /*-----------------------------------------------------------------*/
3504 /* addSign - complete with sign */
3505 /*-----------------------------------------------------------------*/
3507 addSign (operand * result, int offset, int sign)
3509 int size = (getDataSize (result) - offset);
3512 _startLazyDPSEvaluation();
3515 emitcode ("rlc", "a");
3516 emitcode ("subb", "a,acc");
3519 aopPut (AOP (result), "a", offset++);
3526 aopPut (AOP (result), zero, offset++);
3529 _endLazyDPSEvaluation();
3533 /*-----------------------------------------------------------------*/
3534 /* genMinusBits - generates code for subtraction of two bits */
3535 /*-----------------------------------------------------------------*/
3537 genMinusBits (iCode * ic)
3539 symbol *lbl = newiTempLabel (NULL);
3541 D (emitcode (";", "genMinusBits "););
3543 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3545 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3546 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3547 emitcode ("cpl", "c");
3548 emitcode ("", "%05d$:", (lbl->key + 100));
3549 outBitC (IC_RESULT (ic));
3553 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3554 emitcode ("subb", "a,acc");
3555 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3556 emitcode ("inc", "a");
3557 emitcode ("", "%05d$:", (lbl->key + 100));
3558 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3559 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3563 /*-----------------------------------------------------------------*/
3564 /* genMinus - generates code for subtraction */
3565 /*-----------------------------------------------------------------*/
3567 genMinus (iCode * ic)
3569 int size, offset = 0;
3571 unsigned long lit = 0L;
3572 bool pushResult = FALSE;
3574 D (emitcode (";", "genMinus "););
3576 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3577 aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3578 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3579 (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3585 aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3587 /* special cases :- */
3588 /* if both left & right are in bit space */
3589 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3590 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3596 /* if I can do an decrement instead
3597 of subtract then GOOD for ME */
3598 if (genMinusDec (ic) == TRUE)
3603 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3605 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3611 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3616 /* if literal, add a,#-lit, else normal subb */
3617 _startLazyDPSEvaluation ();
3620 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3621 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3622 emitcode ("subb", "a,%s",
3623 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3626 /* first add without previous c */
3628 emitcode ("add", "a,#0x%02x",
3629 (unsigned int) (lit & 0x0FFL));
3631 emitcode ("addc", "a,#0x%02x",
3632 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3637 emitcode ("push", "acc");
3641 aopPut (AOP (IC_RESULT (ic)), "a", offset);
3645 _endLazyDPSEvaluation ();
3649 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3651 size = getDataSize (IC_LEFT (ic));
3652 rSize = getDataSize (IC_RESULT (ic));
3654 ADJUST_PUSHED_RESULT(size, rSize);
3656 _startLazyDPSEvaluation ();
3659 emitcode ("pop", "acc");
3660 aopPut (AOP (IC_RESULT (ic)), "a", size);
3662 _endLazyDPSEvaluation ();
3665 adjustArithmeticResult (ic);
3668 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3669 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3670 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3674 /*-----------------------------------------------------------------*/
3675 /* genMultbits :- multiplication of bits */
3676 /*-----------------------------------------------------------------*/
3678 genMultbits (operand * left,
3682 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3683 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3688 /*-----------------------------------------------------------------*/
3689 /* genMultOneByte : 8*8=8/16 bit multiplication */
3690 /*-----------------------------------------------------------------*/
3692 genMultOneByte (operand * left,
3696 sym_link *opetype = operandType (result);
3698 int size=AOP_SIZE(result);
3700 emitcode (";",__FUNCTION__);
3701 if (size<1 || size>2) {
3702 // this should never happen
3703 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3704 AOP_SIZE(result), __FUNCTION__, lineno);
3708 /* (if two literals: the value is computed before) */
3709 /* if one literal, literal on the right */
3710 if (AOP_TYPE (left) == AOP_LIT)
3715 emitcode (";", "swapped left and right");
3718 if (SPEC_USIGN(opetype)
3719 // ignore the sign of left and right, what else can we do?
3720 || (SPEC_USIGN(operandType(left)) &&
3721 SPEC_USIGN(operandType(right)))) {
3722 // just an unsigned 8*8=8/16 multiply
3723 //emitcode (";","unsigned");
3724 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3725 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3726 emitcode ("mul", "ab");
3727 aopPut (AOP (result), "a", 0);
3729 aopPut (AOP (result), "b", 1);
3734 // we have to do a signed multiply
3736 emitcode (";", "signed");
3737 emitcode ("clr", "F0"); // reset sign flag
3738 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3739 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3741 lbl=newiTempLabel(NULL);
3742 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3743 // left side is negative, 8-bit two's complement, this fails for -128
3744 emitcode ("setb", "F0"); // set sign flag
3745 emitcode ("cpl", "a");
3746 emitcode ("inc", "a");
3748 emitcode ("", "%05d$:", lbl->key+100);
3749 emitcode ("xch", "a,b");
3752 if (AOP_TYPE(right)==AOP_LIT) {
3753 /* AND literal negative */
3754 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3755 // two's complement for literal<0
3756 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3757 emitcode ("cpl", "a");
3758 emitcode ("inc", "a");
3761 lbl=newiTempLabel(NULL);
3762 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3763 // right side is negative, 8-bit two's complement
3764 emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3765 emitcode ("cpl", "a");
3766 emitcode ("inc", "a");
3767 emitcode ("", "%05d$:", lbl->key+100);
3769 emitcode ("mul", "ab");
3771 lbl=newiTempLabel(NULL);
3772 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3773 // only ONE op was negative, we have to do a 8/16-bit two's complement
3774 emitcode ("cpl", "a"); // lsb
3776 emitcode ("inc", "a");
3778 emitcode ("add", "a,#1");
3779 emitcode ("xch", "a,b");
3780 emitcode ("cpl", "a"); // msb
3781 emitcode ("addc", "a,#0");
3782 emitcode ("xch", "a,b");
3785 emitcode ("", "%05d$:", lbl->key+100);
3786 aopPut (AOP (result), "a", 0);
3788 aopPut (AOP (result), "b", 1);
3792 /*-----------------------------------------------------------------*/
3793 /* genMult - generates code for multiplication */
3794 /*-----------------------------------------------------------------*/
3796 genMult (iCode * ic)
3798 operand *left = IC_LEFT (ic);
3799 operand *right = IC_RIGHT (ic);
3800 operand *result = IC_RESULT (ic);
3802 D (emitcode (";", "genMult "););
3804 /* assign the amsops */
3807 /* special cases first */
3809 if (AOP_TYPE (left) == AOP_CRY &&
3810 AOP_TYPE (right) == AOP_CRY)
3812 genMultbits (left, right, result);
3816 /* if both are of size == 1 */
3817 if (AOP_SIZE (left) == 1 &&
3818 AOP_SIZE (right) == 1)
3820 genMultOneByte (left, right, result);
3824 /* should have been converted to function call */
3828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3829 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3830 freeAsmop (result, NULL, ic, TRUE);
3833 /*-----------------------------------------------------------------*/
3834 /* genDivbits :- division of bits */
3835 /*-----------------------------------------------------------------*/
3837 genDivbits (operand * left,
3844 /* the result must be bit */
3845 LOAD_AB_FOR_DIV (left, right, l);
3846 emitcode ("div", "ab");
3847 emitcode ("rrc", "a");
3848 aopPut (AOP (result), "c", 0);
3851 /*-----------------------------------------------------------------*/
3852 /* genDivOneByte : 8 bit division */
3853 /*-----------------------------------------------------------------*/
3855 genDivOneByte (operand * left,
3859 sym_link *opetype = operandType (result);
3864 size = AOP_SIZE (result) - 1;
3866 /* signed or unsigned */
3867 if (SPEC_USIGN (opetype))
3869 /* unsigned is easy */
3870 LOAD_AB_FOR_DIV (left, right, l);
3871 emitcode ("div", "ab");
3872 aopPut (AOP (result), "a", 0);
3874 aopPut (AOP (result), zero, offset++);
3878 /* signed is a little bit more difficult */
3880 /* save the signs of the operands */
3881 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3883 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3884 emitcode ("push", "acc"); /* save it on the stack */
3886 /* now sign adjust for both left & right */
3887 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3889 lbl = newiTempLabel (NULL);
3890 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3891 emitcode ("cpl", "a");
3892 emitcode ("inc", "a");
3893 emitcode ("", "%05d$:", (lbl->key + 100));
3894 emitcode ("mov", "b,a");
3896 /* sign adjust left side */
3897 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3900 lbl = newiTempLabel (NULL);
3901 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3902 emitcode ("cpl", "a");
3903 emitcode ("inc", "a");
3904 emitcode ("", "%05d$:", (lbl->key + 100));
3906 /* now the division */
3907 emitcode ("nop", "; workaround for DS80C390 div bug.");
3908 emitcode ("div", "ab");
3909 /* we are interested in the lower order
3911 emitcode ("mov", "b,a");
3912 lbl = newiTempLabel (NULL);
3913 emitcode ("pop", "acc");
3914 /* if there was an over flow we don't
3915 adjust the sign of the result */
3916 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3917 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3919 emitcode ("clr", "a");
3920 emitcode ("subb", "a,b");
3921 emitcode ("mov", "b,a");
3922 emitcode ("", "%05d$:", (lbl->key + 100));
3924 /* now we are done */
3925 aopPut (AOP (result), "b", 0);
3928 emitcode ("mov", "c,b.7");
3929 emitcode ("subb", "a,acc");
3932 aopPut (AOP (result), "a", offset++);
3936 /*-----------------------------------------------------------------*/
3937 /* genDiv - generates code for division */
3938 /*-----------------------------------------------------------------*/
3942 operand *left = IC_LEFT (ic);
3943 operand *right = IC_RIGHT (ic);
3944 operand *result = IC_RESULT (ic);
3946 D (emitcode (";", "genDiv ");
3949 /* assign the amsops */
3952 /* special cases first */
3954 if (AOP_TYPE (left) == AOP_CRY &&
3955 AOP_TYPE (right) == AOP_CRY)
3957 genDivbits (left, right, result);
3961 /* if both are of size == 1 */
3962 if (AOP_SIZE (left) == 1 &&
3963 AOP_SIZE (right) == 1)
3965 genDivOneByte (left, right, result);
3969 /* should have been converted to function call */
3972 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3973 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3974 freeAsmop (result, NULL, ic, TRUE);
3977 /*-----------------------------------------------------------------*/
3978 /* genModbits :- modulus of bits */
3979 /*-----------------------------------------------------------------*/
3981 genModbits (operand * left,
3988 /* the result must be bit */
3989 LOAD_AB_FOR_DIV (left, right, l);
3990 emitcode ("div", "ab");
3991 emitcode ("mov", "a,b");
3992 emitcode ("rrc", "a");
3993 aopPut (AOP (result), "c", 0);
3996 /*-----------------------------------------------------------------*/
3997 /* genModOneByte : 8 bit modulus */
3998 /*-----------------------------------------------------------------*/
4000 genModOneByte (operand * left,
4004 sym_link *opetype = operandType (result);
4008 /* signed or unsigned */
4009 if (SPEC_USIGN (opetype))
4011 /* unsigned is easy */
4012 LOAD_AB_FOR_DIV (left, right, l);
4013 emitcode ("div", "ab");
4014 aopPut (AOP (result), "b", 0);
4018 /* signed is a little bit more difficult */
4020 /* save the signs of the operands */
4021 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4024 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4025 emitcode ("push", "acc"); /* save it on the stack */
4027 /* now sign adjust for both left & right */
4028 l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4031 lbl = newiTempLabel (NULL);
4032 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4033 emitcode ("cpl", "a");
4034 emitcode ("inc", "a");
4035 emitcode ("", "%05d$:", (lbl->key + 100));
4036 emitcode ("mov", "b,a");
4038 /* sign adjust left side */
4039 l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4042 lbl = newiTempLabel (NULL);
4043 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4044 emitcode ("cpl", "a");
4045 emitcode ("inc", "a");
4046 emitcode ("", "%05d$:", (lbl->key + 100));
4048 /* now the multiplication */
4049 emitcode ("nop", "; workaround for DS80C390 div bug.");
4050 emitcode ("div", "ab");
4051 /* we are interested in the lower order
4053 lbl = newiTempLabel (NULL);
4054 emitcode ("pop", "acc");
4055 /* if there was an over flow we don't
4056 adjust the sign of the result */
4057 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4058 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4060 emitcode ("clr", "a");
4061 emitcode ("subb", "a,b");
4062 emitcode ("mov", "b,a");
4063 emitcode ("", "%05d$:", (lbl->key + 100));
4065 /* now we are done */
4066 aopPut (AOP (result), "b", 0);
4070 /*-----------------------------------------------------------------*/
4071 /* genMod - generates code for division */
4072 /*-----------------------------------------------------------------*/
4076 operand *left = IC_LEFT (ic);
4077 operand *right = IC_RIGHT (ic);
4078 operand *result = IC_RESULT (ic);
4080 D (emitcode (";", "genMod ");
4083 /* assign the amsops */
4086 /* special cases first */
4088 if (AOP_TYPE (left) == AOP_CRY &&
4089 AOP_TYPE (right) == AOP_CRY)
4091 genModbits (left, right, result);
4095 /* if both are of size == 1 */
4096 if (AOP_SIZE (left) == 1 &&
4097 AOP_SIZE (right) == 1)
4099 genModOneByte (left, right, result);
4103 /* should have been converted to function call */
4107 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4108 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4109 freeAsmop (result, NULL, ic, TRUE);
4112 /*-----------------------------------------------------------------*/
4113 /* genIfxJump :- will create a jump depending on the ifx */
4114 /*-----------------------------------------------------------------*/
4116 genIfxJump (iCode * ic, char *jval)
4119 symbol *tlbl = newiTempLabel (NULL);
4122 D (emitcode (";", "genIfxJump ");
4125 /* if true label then we jump if condition
4129 jlbl = IC_TRUE (ic);
4130 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4131 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4135 /* false label is present */
4136 jlbl = IC_FALSE (ic);
4137 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4138 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4140 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4141 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4143 emitcode (inst, "%05d$", tlbl->key + 100);
4144 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4145 emitcode ("", "%05d$:", tlbl->key + 100);
4147 /* mark the icode as generated */
4151 /*-----------------------------------------------------------------*/
4152 /* genCmp :- greater or less than comparison */
4153 /*-----------------------------------------------------------------*/
4155 genCmp (operand * left, operand * right,
4156 iCode * ic, iCode * ifx, int sign)
4158 int size, offset = 0;
4159 unsigned long lit = 0L;
4162 D (emitcode (";", "genCmp");
4165 result = IC_RESULT (ic);
4167 /* if left & right are bit variables */
4168 if (AOP_TYPE (left) == AOP_CRY &&
4169 AOP_TYPE (right) == AOP_CRY)
4171 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4172 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4176 /* subtract right from left if at the
4177 end the carry flag is set then we know that
4178 left is greater than right */
4179 size = max (AOP_SIZE (left), AOP_SIZE (right));
4181 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4182 if ((size == 1) && !sign &&
4183 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4185 symbol *lbl = newiTempLabel (NULL);
4186 emitcode ("cjne", "%s,%s,%05d$",
4187 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4188 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4190 emitcode ("", "%05d$:", lbl->key + 100);
4194 if (AOP_TYPE (right) == AOP_LIT)
4196 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4197 /* optimize if(x < 0) or if(x >= 0) */
4206 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4208 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4209 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4211 aopOp (result, ic, FALSE, FALSE);
4213 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4215 freeAsmop (result, NULL, ic, TRUE);
4216 genIfxJump (ifx, "acc.7");
4221 emitcode ("rlc", "a");
4223 goto release_freedLR;
4231 emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4232 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4233 emitcode (";", "genCmp #2");
4234 if (sign && (size == 0))
4236 emitcode (";", "genCmp #3");
4237 emitcode ("xrl", "a,#0x80");
4238 if (AOP_TYPE (right) == AOP_LIT)
4240 unsigned long lit = (unsigned long)
4241 floatFromVal (AOP (right)->aopu.aop_lit);
4242 emitcode (";", "genCmp #3.1");
4243 emitcode ("subb", "a,#0x%02x",
4244 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4248 emitcode (";", "genCmp #3.2");
4249 if (AOP_NEEDSACC (right))
4251 emitcode ("push", "acc");
4253 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4254 FALSE, FALSE, FALSE));
4255 emitcode ("xrl", "b,#0x80");
4256 if (AOP_NEEDSACC (right))
4258 emitcode ("pop", "acc");
4260 emitcode ("subb", "a,b");
4267 emitcode (";", "genCmp #4");
4268 if (AOP_NEEDSACC (right))
4271 emitcode (";", "genCmp #4.1");
4272 emitcode ("xch", "a, b");
4273 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4274 emitcode ("xch", "a, b");
4279 emitcode (";", "genCmp #4.2");
4280 s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4283 emitcode ("subb", "a,%s", s);
4290 /* Don't need the left & right operands any more; do need the result. */
4291 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4292 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4294 aopOp (result, ic, FALSE, FALSE);
4298 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4304 /* if the result is used in the next
4305 ifx conditional branch then generate
4306 code a little differently */
4309 genIfxJump (ifx, "c");
4315 /* leave the result in acc */
4317 freeAsmop (result, NULL, ic, TRUE);
4320 /*-----------------------------------------------------------------*/
4321 /* genCmpGt :- greater than comparison */
4322 /*-----------------------------------------------------------------*/
4324 genCmpGt (iCode * ic, iCode * ifx)
4326 operand *left, *right;
4327 sym_link *letype, *retype;
4330 D (emitcode (";", "genCmpGt ");
4333 left = IC_LEFT (ic);
4334 right = IC_RIGHT (ic);
4336 letype = getSpec (operandType (left));
4337 retype = getSpec (operandType (right));
4338 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4340 /* assign the left & right amsops */
4343 genCmp (right, left, ic, ifx, sign);
4346 /*-----------------------------------------------------------------*/
4347 /* genCmpLt - less than comparisons */
4348 /*-----------------------------------------------------------------*/
4350 genCmpLt (iCode * ic, iCode * ifx)
4352 operand *left, *right;
4353 sym_link *letype, *retype;
4356 D (emitcode (";", "genCmpLt "););
4358 left = IC_LEFT (ic);
4359 right = IC_RIGHT (ic);
4361 letype = getSpec (operandType (left));
4362 retype = getSpec (operandType (right));
4363 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4365 /* assign the left & right amsops */
4368 genCmp (left, right, ic, ifx, sign);
4371 /*-----------------------------------------------------------------*/
4372 /* gencjneshort - compare and jump if not equal */
4373 /*-----------------------------------------------------------------*/
4375 gencjneshort (operand * left, operand * right, symbol * lbl)
4377 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4379 unsigned long lit = 0L;
4381 D (emitcode (";", "gencjneshort");
4384 /* if the left side is a literal or
4385 if the right is in a pointer register and left
4387 if ((AOP_TYPE (left) == AOP_LIT) ||
4388 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4395 if (AOP_TYPE (right) == AOP_LIT)
4396 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4398 if (opIsGptr (left) || opIsGptr (right))
4400 /* We are comparing a generic pointer to something.
4401 * Exclude the generic type byte from the comparison.
4404 D (emitcode (";", "cjneshort: generic ptr special case.");
4409 /* if the right side is a literal then anything goes */
4410 if (AOP_TYPE (right) == AOP_LIT &&
4411 AOP_TYPE (left) != AOP_DIR)
4415 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4417 emitcode ("cjne", "a,%s,%05d$",
4418 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4424 /* if the right side is in a register or in direct space or
4425 if the left is a pointer register & right is not */
4426 else if (AOP_TYPE (right) == AOP_REG ||
4427 AOP_TYPE (right) == AOP_DIR ||
4428 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4429 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4433 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4434 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4435 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4436 emitcode ("jnz", "%05d$", lbl->key + 100);
4438 emitcode ("cjne", "a,%s,%05d$",
4439 aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4446 /* right is a pointer reg need both a & b */
4449 char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4450 if (strcmp (l, "b"))
4451 emitcode ("mov", "b,%s", l);
4452 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4453 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4459 /*-----------------------------------------------------------------*/
4460 /* gencjne - compare and jump if not equal */
4461 /*-----------------------------------------------------------------*/
4463 gencjne (operand * left, operand * right, symbol * lbl)
4465 symbol *tlbl = newiTempLabel (NULL);
4467 D (emitcode (";", "gencjne");
4470 gencjneshort (left, right, lbl);
4472 emitcode ("mov", "a,%s", one);
4473 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4474 emitcode ("", "%05d$:", lbl->key + 100);
4475 emitcode ("clr", "a");
4476 emitcode ("", "%05d$:", tlbl->key + 100);
4479 /*-----------------------------------------------------------------*/
4480 /* genCmpEq - generates code for equal to */
4481 /*-----------------------------------------------------------------*/
4483 genCmpEq (iCode * ic, iCode * ifx)
4485 operand *left, *right, *result;
4487 D (emitcode (";", "genCmpEq ");
4491 AOP_SET_LOCALS (ic);
4493 /* if literal, literal on the right or
4494 if the right is in a pointer register and left
4496 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4497 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4499 operand *t = IC_RIGHT (ic);
4500 IC_RIGHT (ic) = IC_LEFT (ic);
4504 if (ifx && /* !AOP_SIZE(result) */
4505 OP_SYMBOL (result) &&
4506 OP_SYMBOL (result)->regType == REG_CND)
4509 /* if they are both bit variables */
4510 if (AOP_TYPE (left) == AOP_CRY &&
4511 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4513 if (AOP_TYPE (right) == AOP_LIT)
4515 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4518 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4519 emitcode ("cpl", "c");
4523 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4527 emitcode ("clr", "c");
4529 /* AOP_TYPE(right) == AOP_CRY */
4533 symbol *lbl = newiTempLabel (NULL);
4534 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4535 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4536 emitcode ("cpl", "c");
4537 emitcode ("", "%05d$:", (lbl->key + 100));
4539 /* if true label then we jump if condition
4541 tlbl = newiTempLabel (NULL);
4544 emitcode ("jnc", "%05d$", tlbl->key + 100);
4545 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4549 emitcode ("jc", "%05d$", tlbl->key + 100);
4550 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4552 emitcode ("", "%05d$:", tlbl->key + 100);
4556 tlbl = newiTempLabel (NULL);
4557 gencjneshort (left, right, tlbl);
4560 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4561 emitcode ("", "%05d$:", tlbl->key + 100);
4565 symbol *lbl = newiTempLabel (NULL);
4566 emitcode ("sjmp", "%05d$", lbl->key + 100);
4567 emitcode ("", "%05d$:", tlbl->key + 100);
4568 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4569 emitcode ("", "%05d$:", lbl->key + 100);
4572 /* mark the icode as generated */
4575 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4576 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4580 /* if they are both bit variables */
4581 if (AOP_TYPE (left) == AOP_CRY &&
4582 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4584 if (AOP_TYPE (right) == AOP_LIT)
4586 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4589 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4590 emitcode ("cpl", "c");
4594 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4598 emitcode ("clr", "c");
4600 /* AOP_TYPE(right) == AOP_CRY */
4604 symbol *lbl = newiTempLabel (NULL);
4605 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4606 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4607 emitcode ("cpl", "c");
4608 emitcode ("", "%05d$:", (lbl->key + 100));
4611 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4612 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614 aopOp (result, ic, TRUE, FALSE);
4617 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4624 genIfxJump (ifx, "c");
4627 /* if the result is used in an arithmetic operation
4628 then put the result in place */
4633 gencjne (left, right, newiTempLabel (NULL));
4635 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4638 aopOp (result, ic, TRUE, FALSE);
4640 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4642 aopPut (AOP (result), "a", 0);
4647 genIfxJump (ifx, "a");
4650 /* if the result is used in an arithmetic operation
4651 then put the result in place */
4652 if (AOP_TYPE (result) != AOP_CRY)
4654 /* leave the result in acc */
4658 freeAsmop (result, NULL, ic, TRUE);
4661 /*-----------------------------------------------------------------*/
4662 /* ifxForOp - returns the icode containing the ifx for operand */
4663 /*-----------------------------------------------------------------*/
4665 ifxForOp (operand * op, iCode * ic)
4667 /* if true symbol then needs to be assigned */
4668 if (IS_TRUE_SYMOP (op))
4671 /* if this has register type condition and
4672 the next instruction is ifx with the same operand
4673 and live to of the operand is upto the ifx only then */
4675 ic->next->op == IFX &&
4676 IC_COND (ic->next)->key == op->key &&
4677 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4682 /*-----------------------------------------------------------------*/
4683 /* genAndOp - for && operation */
4684 /*-----------------------------------------------------------------*/
4686 genAndOp (iCode * ic)
4688 operand *left, *right, *result;
4691 D (emitcode (";", "genAndOp "););
4693 /* note here that && operations that are in an
4694 if statement are taken away by backPatchLabels
4695 only those used in arthmetic operations remain */
4697 AOP_SET_LOCALS (ic);
4699 /* if both are bit variables */
4700 if (AOP_TYPE (left) == AOP_CRY &&
4701 AOP_TYPE (right) == AOP_CRY)
4703 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4704 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4705 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4706 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4708 aopOp (result,ic,FALSE, FALSE);
4713 tlbl = newiTempLabel (NULL);
4715 emitcode ("jz", "%05d$", tlbl->key + 100);
4717 emitcode ("", "%05d$:", tlbl->key + 100);
4718 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4719 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4721 aopOp (result,ic,FALSE, FALSE);
4724 freeAsmop (result, NULL, ic, TRUE);
4728 /*-----------------------------------------------------------------*/
4729 /* genOrOp - for || operation */
4730 /*-----------------------------------------------------------------*/
4732 genOrOp (iCode * ic)
4734 operand *left, *right, *result;
4737 D (emitcode (";", "genOrOp "););
4739 /* note here that || operations that are in an
4740 if statement are taken away by backPatchLabels
4741 only those used in arthmetic operations remain */
4743 AOP_SET_LOCALS (ic);
4745 /* if both are bit variables */
4746 if (AOP_TYPE (left) == AOP_CRY &&
4747 AOP_TYPE (right) == AOP_CRY)
4749 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4750 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4751 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4752 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4754 aopOp (result,ic,FALSE, FALSE);
4760 tlbl = newiTempLabel (NULL);
4762 emitcode ("jnz", "%05d$", tlbl->key + 100);
4764 emitcode ("", "%05d$:", tlbl->key + 100);
4765 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4766 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4768 aopOp (result,ic,FALSE, FALSE);
4773 freeAsmop (result, NULL, ic, TRUE);
4776 /*-----------------------------------------------------------------*/
4777 /* isLiteralBit - test if lit == 2^n */
4778 /*-----------------------------------------------------------------*/
4780 isLiteralBit (unsigned long lit)
4782 unsigned long pw[32] =
4783 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4784 0x100L, 0x200L, 0x400L, 0x800L,
4785 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4786 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4787 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4788 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4789 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4792 for (idx = 0; idx < 32; idx++)
4798 /*-----------------------------------------------------------------*/
4799 /* continueIfTrue - */
4800 /*-----------------------------------------------------------------*/
4802 continueIfTrue (iCode * ic)
4805 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4809 /*-----------------------------------------------------------------*/
4811 /*-----------------------------------------------------------------*/
4813 jumpIfTrue (iCode * ic)
4816 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4820 /*-----------------------------------------------------------------*/
4821 /* jmpTrueOrFalse - */
4822 /*-----------------------------------------------------------------*/
4824 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4826 // ugly but optimized by peephole
4829 symbol *nlbl = newiTempLabel (NULL);
4830 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4831 emitcode ("", "%05d$:", tlbl->key + 100);
4832 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4833 emitcode ("", "%05d$:", nlbl->key + 100);
4837 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4838 emitcode ("", "%05d$:", tlbl->key + 100);
4843 // Generate code to perform a bit-wise logic operation
4844 // on two operands in far space (assumed to already have been
4845 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4846 // in far space. This requires pushing the result on the stack
4847 // then popping it into the result.
4849 genFarFarLogicOp(iCode *ic, char *logicOp)
4851 int size, resultSize, compSize;
4854 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4855 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
4856 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4858 _startLazyDPSEvaluation();
4859 for (size = compSize; (size--); offset++)
4861 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4862 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4863 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4865 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4866 emitcode ("push", "acc");
4868 _endLazyDPSEvaluation();
4870 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4871 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4872 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4874 resultSize = AOP_SIZE(IC_RESULT(ic));
4876 ADJUST_PUSHED_RESULT(compSize, resultSize);
4878 _startLazyDPSEvaluation();
4881 emitcode ("pop", "acc");
4882 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4884 _endLazyDPSEvaluation();
4885 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4889 /*-----------------------------------------------------------------*/
4890 /* genAnd - code for and */
4891 /*-----------------------------------------------------------------*/
4893 genAnd (iCode * ic, iCode * ifx)
4895 operand *left, *right, *result;
4896 int size, offset = 0;
4897 unsigned long lit = 0L;
4902 D (emitcode (";", "genAnd "););
4904 AOP_OP_3_NOFATAL (ic, pushResult);
4905 AOP_SET_LOCALS (ic);
4909 genFarFarLogicOp(ic, "anl");
4914 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4916 AOP_TYPE (left), AOP_TYPE (right));
4917 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4919 AOP_SIZE (left), AOP_SIZE (right));
4922 /* if left is a literal & right is not then exchange them */
4923 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4924 AOP_NEEDSACC (left))
4926 operand *tmp = right;
4931 /* if result = right then exchange them */
4932 if (sameRegs (AOP (result), AOP (right)))
4934 operand *tmp = right;
4939 /* if right is bit then exchange them */
4940 if (AOP_TYPE (right) == AOP_CRY &&
4941 AOP_TYPE (left) != AOP_CRY)
4943 operand *tmp = right;
4947 if (AOP_TYPE (right) == AOP_LIT)
4948 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4950 size = AOP_SIZE (result);
4953 // result = bit & yy;
4954 if (AOP_TYPE (left) == AOP_CRY)
4956 // c = bit & literal;
4957 if (AOP_TYPE (right) == AOP_LIT)
4961 if (size && sameRegs (AOP (result), AOP (left)))
4964 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4969 if (size && (AOP_TYPE (result) == AOP_CRY))
4971 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4974 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4979 emitcode ("clr", "c");
4984 if (AOP_TYPE (right) == AOP_CRY)
4987 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4988 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4993 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4995 emitcode ("rrc", "a");
4996 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5004 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5005 genIfxJump (ifx, "c");
5009 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5010 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5011 if ((AOP_TYPE (right) == AOP_LIT) &&
5012 (AOP_TYPE (result) == AOP_CRY) &&
5013 (AOP_TYPE (left) != AOP_CRY))
5015 int posbit = isLiteralBit (lit);
5020 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5023 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5029 sprintf (buffer, "acc.%d", posbit & 0x07);
5030 genIfxJump (ifx, buffer);
5037 symbol *tlbl = newiTempLabel (NULL);
5038 int sizel = AOP_SIZE (left);
5040 emitcode ("setb", "c");
5043 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5045 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5047 if ((posbit = isLiteralBit (bytelit)) != 0)
5048 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5051 if (bytelit != 0x0FFL)
5052 emitcode ("anl", "a,%s",
5053 aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5054 emitcode ("jnz", "%05d$", tlbl->key + 100);
5059 // bit = left & literal
5062 emitcode ("clr", "c");
5063 emitcode ("", "%05d$:", tlbl->key + 100);
5065 // if(left & literal)
5069 jmpTrueOrFalse (ifx, tlbl);
5077 /* if left is same as result */
5078 if (sameRegs (AOP (result), AOP (left)))
5080 for (; size--; offset++)
5082 if (AOP_TYPE (right) == AOP_LIT)
5084 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5086 else if (bytelit == 0)
5087 aopPut (AOP (result), zero, offset);
5088 else if (IS_AOP_PREG (result))
5090 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5091 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5092 aopPut (AOP (result), "a", offset);
5095 emitcode ("anl", "%s,%s",
5096 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5097 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5101 if (AOP_TYPE (left) == AOP_ACC)
5102 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5105 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5106 if (IS_AOP_PREG (result))
5108 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5109 aopPut (AOP (result), "a", offset);
5113 emitcode ("anl", "%s,a",
5114 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5121 // left & result in different registers
5122 if (AOP_TYPE (result) == AOP_CRY)
5125 // if(size), result in bit
5126 // if(!size && ifx), conditional oper: if(left & right)
5127 symbol *tlbl = newiTempLabel (NULL);
5128 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5130 emitcode ("setb", "c");
5133 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5134 emitcode ("anl", "a,%s",
5135 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5136 emitcode ("jnz", "%05d$", tlbl->key + 100);
5142 emitcode ("", "%05d$:", tlbl->key + 100);
5146 jmpTrueOrFalse (ifx, tlbl);
5150 for (; (size--); offset++)
5153 // result = left & right
5154 if (AOP_TYPE (right) == AOP_LIT)
5156 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5158 aopPut (AOP (result),
5159 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5163 else if (bytelit == 0)
5165 aopPut (AOP (result), zero, offset);
5168 D (emitcode (";", "better literal AND.");
5170 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5171 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5172 FALSE, FALSE, FALSE));
5177 // faster than result <- left, anl result,right
5178 // and better if result is SFR
5179 if (AOP_TYPE (left) == AOP_ACC)
5181 emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5182 FALSE, FALSE, FALSE));
5186 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5187 emitcode ("anl", "a,%s",
5188 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5191 aopPut (AOP (result), "a", offset);
5197 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5198 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5199 freeAsmop (result, NULL, ic, TRUE);
5203 /*-----------------------------------------------------------------*/
5204 /* genOr - code for or */
5205 /*-----------------------------------------------------------------*/
5207 genOr (iCode * ic, iCode * ifx)
5209 operand *left, *right, *result;
5210 int size, offset = 0;
5211 unsigned long lit = 0L;
5214 D (emitcode (";", "genOr "););
5216 AOP_OP_3_NOFATAL (ic, pushResult);
5217 AOP_SET_LOCALS (ic);
5221 genFarFarLogicOp(ic, "orl");
5227 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5229 AOP_TYPE (left), AOP_TYPE (right));
5230 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5232 AOP_SIZE (left), AOP_SIZE (right));
5235 /* if left is a literal & right is not then exchange them */
5236 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5237 AOP_NEEDSACC (left))
5239 operand *tmp = right;
5244 /* if result = right then exchange them */
5245 if (sameRegs (AOP (result), AOP (right)))
5247 operand *tmp = right;
5252 /* if right is bit then exchange them */
5253 if (AOP_TYPE (right) == AOP_CRY &&
5254 AOP_TYPE (left) != AOP_CRY)
5256 operand *tmp = right;
5260 if (AOP_TYPE (right) == AOP_LIT)
5261 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5263 size = AOP_SIZE (result);
5267 if (AOP_TYPE (left) == AOP_CRY)
5269 if (AOP_TYPE (right) == AOP_LIT)
5271 // c = bit & literal;
5274 // lit != 0 => result = 1
5275 if (AOP_TYPE (result) == AOP_CRY)
5278 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5280 continueIfTrue (ifx);
5283 emitcode ("setb", "c");
5287 // lit == 0 => result = left
5288 if (size && sameRegs (AOP (result), AOP (left)))
5290 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5295 if (AOP_TYPE (right) == AOP_CRY)
5298 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5299 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5304 symbol *tlbl = newiTempLabel (NULL);
5305 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5306 emitcode ("setb", "c");
5307 emitcode ("jb", "%s,%05d$",
5308 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5310 emitcode ("jnz", "%05d$", tlbl->key + 100);
5311 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5313 jmpTrueOrFalse (ifx, tlbl);
5319 emitcode ("", "%05d$:", tlbl->key + 100);
5328 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5329 genIfxJump (ifx, "c");
5333 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5334 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5335 if ((AOP_TYPE (right) == AOP_LIT) &&
5336 (AOP_TYPE (result) == AOP_CRY) &&
5337 (AOP_TYPE (left) != AOP_CRY))
5343 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5345 continueIfTrue (ifx);
5350 // lit = 0, result = boolean(left)
5352 emitcode ("setb", "c");
5356 symbol *tlbl = newiTempLabel (NULL);
5357 emitcode ("jnz", "%05d$", tlbl->key + 100);
5359 emitcode ("", "%05d$:", tlbl->key + 100);
5363 genIfxJump (ifx, "a");
5371 /* if left is same as result */
5372 if (sameRegs (AOP (result), AOP (left)))
5374 for (; size--; offset++)
5376 if (AOP_TYPE (right) == AOP_LIT)
5378 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5384 if (IS_AOP_PREG (left))
5386 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5387 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5388 aopPut (AOP (result), "a", offset);
5392 emitcode ("orl", "%s,%s",
5393 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5394 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5400 if (AOP_TYPE (left) == AOP_ACC)
5402 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5406 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5407 if (IS_AOP_PREG (left))
5409 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5410 aopPut (AOP (result), "a", offset);
5414 emitcode ("orl", "%s,a",
5415 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5423 // left & result in different registers
5424 if (AOP_TYPE (result) == AOP_CRY)
5427 // if(size), result in bit
5428 // if(!size && ifx), conditional oper: if(left | right)
5429 symbol *tlbl = newiTempLabel (NULL);
5430 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5432 emitcode ("setb", "c");
5435 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5436 emitcode ("orl", "a,%s",
5437 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5438 emitcode ("jnz", "%05d$", tlbl->key + 100);
5444 emitcode ("", "%05d$:", tlbl->key + 100);
5448 jmpTrueOrFalse (ifx, tlbl);
5452 for (; (size--); offset++)
5455 // result = left & right
5456 if (AOP_TYPE (right) == AOP_LIT)
5458 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5460 aopPut (AOP (result),
5461 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5465 D (emitcode (";", "better literal OR.");
5467 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5468 emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5469 FALSE, FALSE, FALSE));
5474 // faster than result <- left, anl result,right
5475 // and better if result is SFR
5476 if (AOP_TYPE (left) == AOP_ACC)
5478 emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5479 FALSE, FALSE, FALSE));
5483 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5484 emitcode ("orl", "a,%s",
5485 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5488 aopPut (AOP (result), "a", offset);
5494 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5495 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5496 freeAsmop (result, NULL, ic, TRUE);
5499 /*-----------------------------------------------------------------*/
5500 /* genXor - code for xclusive or */
5501 /*-----------------------------------------------------------------*/
5503 genXor (iCode * ic, iCode * ifx)
5505 operand *left, *right, *result;
5506 int size, offset = 0;
5507 unsigned long lit = 0L;
5510 D (emitcode (";", "genXor "););
5512 AOP_OP_3_NOFATAL (ic, pushResult);
5513 AOP_SET_LOCALS (ic);
5517 genFarFarLogicOp(ic, "xrl");
5522 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5524 AOP_TYPE (left), AOP_TYPE (right));
5525 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5527 AOP_SIZE (left), AOP_SIZE (right));
5530 /* if left is a literal & right is not ||
5531 if left needs acc & right does not */
5532 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5533 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5535 operand *tmp = right;
5540 /* if result = right then exchange them */
5541 if (sameRegs (AOP (result), AOP (right)))
5543 operand *tmp = right;
5548 /* if right is bit then exchange them */
5549 if (AOP_TYPE (right) == AOP_CRY &&
5550 AOP_TYPE (left) != AOP_CRY)
5552 operand *tmp = right;
5556 if (AOP_TYPE (right) == AOP_LIT)
5557 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5559 size = AOP_SIZE (result);
5563 if (AOP_TYPE (left) == AOP_CRY)
5565 if (AOP_TYPE (right) == AOP_LIT)
5567 // c = bit & literal;
5570 // lit>>1 != 0 => result = 1
5571 if (AOP_TYPE (result) == AOP_CRY)
5574 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5576 continueIfTrue (ifx);
5579 emitcode ("setb", "c");
5586 // lit == 0, result = left
5587 if (size && sameRegs (AOP (result), AOP (left)))
5589 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5593 // lit == 1, result = not(left)
5594 if (size && sameRegs (AOP (result), AOP (left)))
5596 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5601 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5602 emitcode ("cpl", "c");
5611 symbol *tlbl = newiTempLabel (NULL);
5612 if (AOP_TYPE (right) == AOP_CRY)
5615 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5619 int sizer = AOP_SIZE (right);
5621 // if val>>1 != 0, result = 1
5622 emitcode ("setb", "c");
5625 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5627 // test the msb of the lsb
5628 emitcode ("anl", "a,#0xfe");
5629 emitcode ("jnz", "%05d$", tlbl->key + 100);
5633 emitcode ("rrc", "a");
5635 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5636 emitcode ("cpl", "c");
5637 emitcode ("", "%05d$:", (tlbl->key + 100));
5644 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5645 genIfxJump (ifx, "c");
5649 if (sameRegs (AOP (result), AOP (left)))
5651 /* if left is same as result */
5652 for (; size--; offset++)
5654 if (AOP_TYPE (right) == AOP_LIT)
5656 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5658 else if (IS_AOP_PREG (left))
5660 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5661 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5662 aopPut (AOP (result), "a", offset);
5665 emitcode ("xrl", "%s,%s",
5666 aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5667 aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5671 if (AOP_TYPE (left) == AOP_ACC)
5672 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5675 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5676 if (IS_AOP_PREG (left))
5678 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5679 aopPut (AOP (result), "a", offset);
5682 emitcode ("xrl", "%s,a",
5683 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5690 // left & result in different registers
5691 if (AOP_TYPE (result) == AOP_CRY)
5694 // if(size), result in bit
5695 // if(!size && ifx), conditional oper: if(left ^ right)
5696 symbol *tlbl = newiTempLabel (NULL);
5697 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5699 emitcode ("setb", "c");
5702 if ((AOP_TYPE (right) == AOP_LIT) &&
5703 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5705 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5709 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5710 emitcode ("xrl", "a,%s",
5711 aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5713 emitcode ("jnz", "%05d$", tlbl->key + 100);
5719 emitcode ("", "%05d$:", tlbl->key + 100);
5723 jmpTrueOrFalse (ifx, tlbl);
5726 for (; (size--); offset++)
5729 // result = left & right
5730 if (AOP_TYPE (right) == AOP_LIT)
5732 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5734 aopPut (AOP (result),
5735 aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5739 D (emitcode (";", "better literal XOR.");
5741 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5742 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5743 FALSE, FALSE, FALSE));
5747 // faster than result <- left, anl result,right
5748 // and better if result is SFR
5749 if (AOP_TYPE (left) == AOP_ACC)
5751 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5752 FALSE, FALSE, FALSE));
5756 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5757 emitcode ("xrl", "a,%s",
5758 aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5761 aopPut (AOP (result), "a", offset);
5766 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5767 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5768 freeAsmop (result, NULL, ic, TRUE);
5771 /*-----------------------------------------------------------------*/
5772 /* genInline - write the inline code out */
5773 /*-----------------------------------------------------------------*/
5775 genInline (iCode * ic)
5777 char buffer[MAX_INLINEASM];
5781 D (emitcode (";", "genInline ");
5784 _G.inLine += (!options.asmpeep);
5785 strcpy (buffer, IC_INLINE (ic));
5787 /* emit each line as a code */
5812 /* emitcode("",buffer); */
5813 _G.inLine -= (!options.asmpeep);
5816 /*-----------------------------------------------------------------*/
5817 /* genRRC - rotate right with carry */
5818 /*-----------------------------------------------------------------*/
5822 operand *left, *result;
5823 int size, offset = 0;
5826 D (emitcode (";", "genRRC ");
5829 /* rotate right with carry */
5830 left = IC_LEFT (ic);
5831 result = IC_RESULT (ic);
5832 aopOp (left, ic, FALSE, FALSE);
5833 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5835 /* move it to the result */
5836 size = AOP_SIZE (result);
5840 _startLazyDPSEvaluation ();
5843 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5845 emitcode ("rrc", "a");
5846 if (AOP_SIZE (result) > 1)
5847 aopPut (AOP (result), "a", offset--);
5849 _endLazyDPSEvaluation ();
5851 /* now we need to put the carry into the
5852 highest order byte of the result */
5853 if (AOP_SIZE (result) > 1)
5855 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5858 emitcode ("mov", "acc.7,c");
5859 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5860 freeAsmop (left, NULL, ic, TRUE);
5861 freeAsmop (result, NULL, ic, TRUE);
5864 /*-----------------------------------------------------------------*/
5865 /* genRLC - generate code for rotate left with carry */
5866 /*-----------------------------------------------------------------*/
5870 operand *left, *result;
5871 int size, offset = 0;
5874 D (emitcode (";", "genRLC ");
5877 /* rotate right with carry */
5878 left = IC_LEFT (ic);
5879 result = IC_RESULT (ic);
5880 aopOp (left, ic, FALSE, FALSE);
5881 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5883 /* move it to the result */
5884 size = AOP_SIZE (result);
5888 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5890 emitcode ("add", "a,acc");
5891 if (AOP_SIZE (result) > 1)
5893 aopPut (AOP (result), "a", offset++);
5896 _startLazyDPSEvaluation ();
5899 l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5901 emitcode ("rlc", "a");
5902 if (AOP_SIZE (result) > 1)
5903 aopPut (AOP (result), "a", offset++);
5905 _endLazyDPSEvaluation ();
5907 /* now we need to put the carry into the
5908 highest order byte of the result */
5909 if (AOP_SIZE (result) > 1)
5911 l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5914 emitcode ("mov", "acc.0,c");
5915 aopPut (AOP (result), "a", 0);
5916 freeAsmop (left, NULL, ic, TRUE);
5917 freeAsmop (result, NULL, ic, TRUE);
5920 /*-----------------------------------------------------------------*/
5921 /* genGetHbit - generates code get highest order bit */
5922 /*-----------------------------------------------------------------*/
5924 genGetHbit (iCode * ic)
5926 operand *left, *result;
5927 left = IC_LEFT (ic);
5928 result = IC_RESULT (ic);
5929 aopOp (left, ic, FALSE, FALSE);
5930 aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5932 D (emitcode (";", "genGetHbit ");
5935 /* get the highest order byte into a */
5936 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5937 if (AOP_TYPE (result) == AOP_CRY)
5939 emitcode ("rlc", "a");
5944 emitcode ("rl", "a");
5945 emitcode ("anl", "a,#0x01");
5950 freeAsmop (left, NULL, ic, TRUE);
5951 freeAsmop (result, NULL, ic, TRUE);
5954 /*-----------------------------------------------------------------*/
5955 /* AccRol - rotate left accumulator by known count */
5956 /*-----------------------------------------------------------------*/
5958 AccRol (int shCount)
5960 shCount &= 0x0007; // shCount : 0..7
5967 emitcode ("rl", "a");
5970 emitcode ("rl", "a");
5971 emitcode ("rl", "a");
5974 emitcode ("swap", "a");
5975 emitcode ("rr", "a");
5978 emitcode ("swap", "a");
5981 emitcode ("swap", "a");
5982 emitcode ("rl", "a");
5985 emitcode ("rr", "a");
5986 emitcode ("rr", "a");
5989 emitcode ("rr", "a");
5994 /*-----------------------------------------------------------------*/
5995 /* AccLsh - left shift accumulator by known count */
5996 /*-----------------------------------------------------------------*/
5998 AccLsh (int shCount)
6003 emitcode ("add", "a,acc");
6004 else if (shCount == 2)
6006 emitcode ("add", "a,acc");
6007 emitcode ("add", "a,acc");
6011 /* rotate left accumulator */
6013 /* and kill the lower order bits */
6014 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6019 /*-----------------------------------------------------------------*/
6020 /* AccRsh - right shift accumulator by known count */
6021 /*-----------------------------------------------------------------*/
6023 AccRsh (int shCount)
6030 emitcode ("rrc", "a");
6034 /* rotate right accumulator */
6035 AccRol (8 - shCount);
6036 /* and kill the higher order bits */
6037 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6042 #ifdef BETTER_LITERAL_SHIFT
6043 /*-----------------------------------------------------------------*/
6044 /* AccSRsh - signed right shift accumulator by known count */
6045 /*-----------------------------------------------------------------*/
6047 AccSRsh (int shCount)
6054 emitcode ("mov", "c,acc.7");
6055 emitcode ("rrc", "a");
6057 else if (shCount == 2)
6059 emitcode ("mov", "c,acc.7");
6060 emitcode ("rrc", "a");
6061 emitcode ("mov", "c,acc.7");
6062 emitcode ("rrc", "a");
6066 tlbl = newiTempLabel (NULL);
6067 /* rotate right accumulator */
6068 AccRol (8 - shCount);
6069 /* and kill the higher order bits */
6070 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6071 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6072 emitcode ("orl", "a,#0x%02x",
6073 (unsigned char) ~SRMask[shCount]);
6074 emitcode ("", "%05d$:", tlbl->key + 100);
6080 #ifdef BETTER_LITERAL_SHIFT
6081 /*-----------------------------------------------------------------*/
6082 /* shiftR1Left2Result - shift right one byte from left to result */
6083 /*-----------------------------------------------------------------*/
6085 shiftR1Left2Result (operand * left, int offl,
6086 operand * result, int offr,
6087 int shCount, int sign)
6089 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6090 /* shift right accumulator */
6095 aopPut (AOP (result), "a", offr);
6099 #ifdef BETTER_LITERAL_SHIFT
6100 /*-----------------------------------------------------------------*/
6101 /* shiftL1Left2Result - shift left one byte from left to result */
6102 /*-----------------------------------------------------------------*/
6104 shiftL1Left2Result (operand * left, int offl,
6105 operand * result, int offr, int shCount)
6107 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6108 /* shift left accumulator */
6110 aopPut (AOP (result), "a", offr);
6114 #ifdef BETTER_LITERAL_SHIFT
6115 /*-----------------------------------------------------------------*/
6116 /* movLeft2Result - move byte from left to result */
6117 /*-----------------------------------------------------------------*/
6119 movLeft2Result (operand * left, int offl,
6120 operand * result, int offr, int sign)
6123 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6125 l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6127 if (*l == '@' && (IS_AOP_PREG (result)))
6129 emitcode ("mov", "a,%s", l);
6130 aopPut (AOP (result), "a", offr);
6136 aopPut (AOP (result), l, offr);
6140 /* MSB sign in acc.7 ! */
6141 if (getDataSize (left) == offl + 1)
6143 emitcode ("mov", "a,%s", l);
6144 aopPut (AOP (result), "a", offr);
6152 #ifdef BETTER_LITERAL_SHIFT
6153 /*-----------------------------------------------------------------*/
6154 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6155 /*-----------------------------------------------------------------*/
6159 emitcode ("rrc", "a");
6160 emitcode ("xch", "a,%s", x);
6161 emitcode ("rrc", "a");
6162 emitcode ("xch", "a,%s", x);
6166 #ifdef BETTER_LITERAL_SHIFT
6168 /*-----------------------------------------------------------------*/
6169 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6170 /*-----------------------------------------------------------------*/
6174 emitcode ("xch", "a,%s", x);
6175 emitcode ("rlc", "a");
6176 emitcode ("xch", "a,%s", x);
6177 emitcode ("rlc", "a");
6181 #ifdef BETTER_LITERAL_SHIFT
6182 /*-----------------------------------------------------------------*/
6183 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6184 /*-----------------------------------------------------------------*/
6188 emitcode ("xch", "a,%s", x);
6189 emitcode ("add", "a,acc");
6190 emitcode ("xch", "a,%s", x);
6191 emitcode ("rlc", "a");
6195 #ifdef BETTER_LITERAL_SHIFT
6196 /*-----------------------------------------------------------------*/
6197 /* AccAXLsh - left shift a:x by known count (0..7) */
6198 /*-----------------------------------------------------------------*/
6200 AccAXLsh (char *x, int shCount)
6215 case 5: // AAAAABBB:CCCCCDDD
6217 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6219 emitcode ("anl", "a,#0x%02x",
6220 SLMask[shCount]); // BBB00000:CCCCCDDD
6222 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6224 AccRol (shCount); // DDDCCCCC:BBB00000
6226 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6228 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6230 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6232 emitcode ("anl", "a,#0x%02x",
6233 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6235 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6237 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6240 case 6: // AAAAAABB:CCCCCCDD
6241 emitcode ("anl", "a,#0x%02x",
6242 SRMask[shCount]); // 000000BB:CCCCCCDD
6243 emitcode ("mov", "c,acc.0"); // c = B
6244 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6246 AccAXRrl1 (x); // BCCCCCCD:D000000B
6247 AccAXRrl1 (x); // BBCCCCCC:DD000000
6249 emitcode("rrc","a");
6250 emitcode("xch","a,%s", x);
6251 emitcode("rrc","a");
6252 emitcode("mov","c,acc.0"); //<< get correct bit
6253 emitcode("xch","a,%s", x);
6255 emitcode("rrc","a");
6256 emitcode("xch","a,%s", x);
6257 emitcode("rrc","a");
6258 emitcode("xch","a,%s", x);
6261 case 7: // a:x <<= 7
6263 emitcode ("anl", "a,#0x%02x",
6264 SRMask[shCount]); // 0000000B:CCCCCCCD
6266 emitcode ("mov", "c,acc.0"); // c = B
6268 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6270 AccAXRrl1 (x); // BCCCCCCC:D0000000
6279 #ifdef BETTER_LITERAL_SHIFT
6281 /*-----------------------------------------------------------------*/
6282 /* AccAXRsh - right shift a:x known count (0..7) */
6283 /*-----------------------------------------------------------------*/
6285 AccAXRsh (char *x, int shCount)
6293 AccAXRrl1 (x); // 0->a:x
6298 AccAXRrl1 (x); // 0->a:x
6301 AccAXRrl1 (x); // 0->a:x
6306 case 5: // AAAAABBB:CCCCCDDD = a:x
6308 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6310 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6312 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6314 emitcode ("anl", "a,#0x%02x",
6315 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6317 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6319 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6321 emitcode ("anl", "a,#0x%02x",
6322 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6324 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6326 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6328 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6331 case 6: // AABBBBBB:CCDDDDDD
6333 emitcode ("mov", "c,acc.7");
6334 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6336 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6338 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6340 emitcode ("anl", "a,#0x%02x",
6341 SRMask[shCount]); // 000000AA:BBBBBBCC
6344 case 7: // ABBBBBBB:CDDDDDDD
6346 emitcode ("mov", "c,acc.7"); // c = A
6348 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6350 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6352 emitcode ("anl", "a,#0x%02x",
6353 SRMask[shCount]); // 0000000A:BBBBBBBC
6362 #ifdef BETTER_LITERAL_SHIFT
6364 /*-----------------------------------------------------------------*/
6365 /* AccAXRshS - right shift signed a:x known count (0..7) */
6366 /*-----------------------------------------------------------------*/
6368 AccAXRshS (char *x, int shCount)
6376 emitcode ("mov", "c,acc.7");
6377 AccAXRrl1 (x); // s->a:x
6381 emitcode ("mov", "c,acc.7");
6382 AccAXRrl1 (x); // s->a:x
6384 emitcode ("mov", "c,acc.7");
6385 AccAXRrl1 (x); // s->a:x
6390 case 5: // AAAAABBB:CCCCCDDD = a:x
6392 tlbl = newiTempLabel (NULL);
6393 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6395 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6397 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6399 emitcode ("anl", "a,#0x%02x",
6400 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6402 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6404 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6406 emitcode ("anl", "a,#0x%02x",
6407 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6409 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6411 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6413 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6415 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6416 emitcode ("orl", "a,#0x%02x",
6417 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6419 emitcode ("", "%05d$:", tlbl->key + 100);
6420 break; // SSSSAAAA:BBBCCCCC
6422 case 6: // AABBBBBB:CCDDDDDD
6424 tlbl = newiTempLabel (NULL);
6425 emitcode ("mov", "c,acc.7");
6426 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6428 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6430 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6432 emitcode ("anl", "a,#0x%02x",
6433 SRMask[shCount]); // 000000AA:BBBBBBCC
6435 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6436 emitcode ("orl", "a,#0x%02x",
6437 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6439 emitcode ("", "%05d$:", tlbl->key + 100);
6441 case 7: // ABBBBBBB:CDDDDDDD
6443 tlbl = newiTempLabel (NULL);
6444 emitcode ("mov", "c,acc.7"); // c = A
6446 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6448 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6450 emitcode ("anl", "a,#0x%02x",
6451 SRMask[shCount]); // 0000000A:BBBBBBBC
6453 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6454 emitcode ("orl", "a,#0x%02x",
6455 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6457 emitcode ("", "%05d$:", tlbl->key + 100);
6465 #ifdef BETTER_LITERAL_SHIFT
6467 _loadLeftIntoAx(char **lsb,
6473 // Get the initial value from left into a pair of registers.
6474 // MSB must be in A, LSB can be any register.
6476 // If the result is held in registers, it is an optimization
6477 // if the LSB can be held in the register which will hold the,
6478 // result LSB since this saves us from having to copy it into
6479 // the result following AccAXLsh.
6481 // If the result is addressed indirectly, this is not a gain.
6482 if (AOP_NEEDSACC(result))
6486 _startLazyDPSEvaluation();
6487 if (AOP_TYPE(left) == AOP_DPTR2)
6490 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6491 // get LSB in DP2_RESULT_REG.
6492 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6493 assert(!strcmp(leftByte, DP2_RESULT_REG));
6497 // get LSB into DP2_RESULT_REG
6498 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6499 if (strcmp(leftByte, DP2_RESULT_REG))
6501 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6504 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6505 assert(strcmp(leftByte, DP2_RESULT_REG));
6508 _endLazyDPSEvaluation();
6509 *lsb = DP2_RESULT_REG;
6513 if (sameRegs (AOP (result), AOP (left)) &&
6514 ((offl + MSB16) == offr))
6516 /* don't crash result[offr] */
6517 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6518 emitcode ("xch", "a,%s",
6519 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6523 movLeft2Result (left, offl, result, offr, 0);
6524 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6526 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6527 assert(strcmp(*lsb,"a"));
6532 _storeAxResults(char *lsb,
6536 _startLazyDPSEvaluation();
6537 if (AOP_NEEDSACC(result))
6539 /* We have to explicitly update the result LSB.
6541 emitcode("xch","a,%s", lsb);
6542 aopPut(AOP(result), "a", offr);
6543 emitcode("mov","a,%s", lsb);
6545 if (getDataSize (result) > 1)
6547 aopPut (AOP (result), "a", offr + MSB16);
6549 _endLazyDPSEvaluation();
6552 /*-----------------------------------------------------------------*/
6553 /* shiftL2Left2Result - shift left two bytes from left to result */
6554 /*-----------------------------------------------------------------*/
6556 shiftL2Left2Result (operand * left, int offl,
6557 operand * result, int offr, int shCount)
6561 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6563 AccAXLsh (lsb, shCount);
6565 _storeAxResults(lsb, result, offr);
6569 #ifdef BETTER_LITERAL_SHIFT
6570 /*-----------------------------------------------------------------*/
6571 /* shiftR2Left2Result - shift right two bytes from left to result */
6572 /*-----------------------------------------------------------------*/
6574 shiftR2Left2Result (operand * left, int offl,
6575 operand * result, int offr,
6576 int shCount, int sign)
6580 _loadLeftIntoAx(&lsb, left, result, offl, offr);
6582 /* a:x >> shCount (x = lsb(result)) */
6585 AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6589 AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6592 _storeAxResults(lsb, result, offr);
6598 /*-----------------------------------------------------------------*/
6599 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6600 /*-----------------------------------------------------------------*/
6602 shiftLLeftOrResult (operand * left, int offl,
6603 operand * result, int offr, int shCount)
6605 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6606 /* shift left accumulator */
6608 /* or with result */
6609 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6610 /* back to result */
6611 aopPut (AOP (result), "a", offr);
6617 /*-----------------------------------------------------------------*/
6618 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6619 /*-----------------------------------------------------------------*/
6621 shiftRLeftOrResult (operand * left, int offl,
6622 operand * result, int offr, int shCount)
6624 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6625 /* shift right accumulator */
6627 /* or with result */
6628 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6629 /* back to result */
6630 aopPut (AOP (result), "a", offr);
6634 #ifdef BETTER_LITERAL_SHIFT
6635 /*-----------------------------------------------------------------*/
6636 /* genlshOne - left shift a one byte quantity by known count */
6637 /*-----------------------------------------------------------------*/
6639 genlshOne (operand * result, operand * left, int shCount)
6641 D (emitcode (";", "genlshOne "););
6642 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6646 #ifdef BETTER_LITERAL_SHIFT
6647 /*-----------------------------------------------------------------*/
6648 /* genlshTwo - left shift two bytes by known amount != 0 */
6649 /*-----------------------------------------------------------------*/
6651 genlshTwo (operand * result, operand * left, int shCount)
6655 D (emitcode (";", "genlshTwo "););
6657 size = getDataSize (result);
6659 /* if shCount >= 8 */
6664 _startLazyDPSEvaluation();
6670 _endLazyDPSEvaluation();
6671 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6672 aopPut (AOP (result), zero, LSB);
6676 movLeft2Result (left, LSB, result, MSB16, 0);
6677 aopPut (AOP (result), zero, LSB);
6678 _endLazyDPSEvaluation();
6683 aopPut (AOP (result), zero, LSB);
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
8965 // #define BETTER_FAR_FAR_ASSIGN
8966 #ifdef BETTER_FAR_FAR_ASSIGN
8967 if ((IS_SYMOP(result) && OP_SYMBOL(result) && OP_SYMBOL(result)->rname)
8968 && (IS_TRUE_SYMOP(result)
8969 || (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc->rname)))
8971 D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
8972 emitcode("mov", "dps, #21"); /* Select DPTR2 & auto-toggle. */
8973 if (IS_TRUE_SYMOP(result))
8975 emitcode ("mov", "dptr,#%s", OP_SYMBOL(result)->rname);
8979 emitcode ("mov", "dptr,#%s", OP_SYMBOL(result)->usl.spillLoc->rname);
8981 /* DP2 = result, DP1 = right, DP1 is current. */
8984 emitcode("movx", "a,@dptr");
8985 emitcode("movx", "@dptr,a");
8988 emitcode("inc", "dptr");
8989 emitcode("inc", "dptr");
8992 emitcode("mov", "dps, #0");
8997 D (emitcode (";", "genFarFarAssign (improved)"););
8998 aopOp (result, ic, TRUE, TRUE);
9000 _startLazyDPSEvaluation ();
9004 aopPut (AOP (result),
9005 aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9008 _endLazyDPSEvaluation ();
9009 freeAsmop (result, NULL, ic, FALSE);
9011 freeAsmop (right, NULL, ic, FALSE);
9015 D (emitcode (";", "genFarFarAssign "););
9017 /* first push the right side on to the stack */
9018 _startLazyDPSEvaluation ();
9021 l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9023 emitcode ("push", "acc");
9026 freeAsmop (right, NULL, ic, FALSE);
9027 /* now assign DPTR to result */
9028 aopOp (result, ic, FALSE, FALSE);
9029 size = AOP_SIZE (result);
9032 emitcode ("pop", "acc");
9033 aopPut (AOP (result), "a", --offset);
9035 freeAsmop (result, NULL, ic, FALSE);
9036 _endLazyDPSEvaluation ();
9040 /*-----------------------------------------------------------------*/
9041 /* genAssign - generate code for assignment */
9042 /*-----------------------------------------------------------------*/
9044 genAssign (iCode * ic)
9046 operand *result, *right;
9048 unsigned long lit = 0L;
9050 D (emitcode (";", "genAssign ");
9053 result = IC_RESULT (ic);
9054 right = IC_RIGHT (ic);
9056 /* if they are the same */
9057 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9060 aopOp (right, ic, FALSE, FALSE);
9062 emitcode (";", "genAssign: resultIsFar = %s",
9063 isOperandInFarSpace (result) ?
9066 /* special case both in far space */
9067 if ((AOP_TYPE (right) == AOP_DPTR ||
9068 AOP_TYPE (right) == AOP_DPTR2) &&
9069 /* IS_TRUE_SYMOP(result) && */
9070 isOperandInFarSpace (result))
9072 genFarFarAssign (result, right, ic);
9076 aopOp (result, ic, TRUE, FALSE);
9078 /* if they are the same registers */
9079 if (sameRegs (AOP (right), AOP (result)))
9082 /* if the result is a bit */
9083 if (AOP_TYPE (result) == AOP_CRY)
9086 /* if the right size is a literal then
9087 we know what the value is */
9088 if (AOP_TYPE (right) == AOP_LIT)
9090 if (((int) operandLitValue (right)))
9091 aopPut (AOP (result), one, 0);
9093 aopPut (AOP (result), zero, 0);
9097 /* the right is also a bit variable */
9098 if (AOP_TYPE (right) == AOP_CRY)
9100 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9101 aopPut (AOP (result), "c", 0);
9107 aopPut (AOP (result), "a", 0);
9111 /* bit variables done */
9113 size = AOP_SIZE (result);
9115 if (AOP_TYPE (right) == AOP_LIT)
9116 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9119 (AOP_TYPE (result) != AOP_REG) &&
9120 (AOP_TYPE (right) == AOP_LIT) &&
9121 !IS_FLOAT (operandType (right)))
9123 _startLazyDPSEvaluation ();
9124 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9126 aopPut (AOP (result),
9127 aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9132 /* And now fill the rest with zeros. */
9135 emitcode ("clr", "a");
9139 aopPut (AOP (result), "a", offset++);
9141 _endLazyDPSEvaluation ();
9145 _startLazyDPSEvaluation ();
9148 aopPut (AOP (result),
9149 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9153 _endLazyDPSEvaluation ();
9157 freeAsmop (right, NULL, ic, FALSE);
9158 freeAsmop (result, NULL, ic, TRUE);
9161 /*-----------------------------------------------------------------*/
9162 /* genJumpTab - generates code for jump table */
9163 /*-----------------------------------------------------------------*/
9165 genJumpTab (iCode * ic)
9170 D (emitcode (";", "genJumpTab ");
9173 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9174 /* get the condition into accumulator */
9175 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9177 /* multiply by four! */
9178 emitcode ("add", "a,acc");
9179 emitcode ("add", "a,acc");
9180 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9182 jtab = newiTempLabel (NULL);
9183 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9184 emitcode ("jmp", "@a+dptr");
9185 emitcode ("", "%05d$:", jtab->key + 100);
9186 /* now generate the jump labels */
9187 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9188 jtab = setNextItem (IC_JTLABELS (ic)))
9189 emitcode ("ljmp", "%05d$", jtab->key + 100);
9193 /*-----------------------------------------------------------------*/
9194 /* genCast - gen code for casting */
9195 /*-----------------------------------------------------------------*/
9197 genCast (iCode * ic)
9199 operand *result = IC_RESULT (ic);
9200 sym_link *ctype = operandType (IC_LEFT (ic));
9201 sym_link *rtype = operandType (IC_RIGHT (ic));
9202 operand *right = IC_RIGHT (ic);
9205 D (emitcode (";", "genCast ");
9208 /* if they are equivalent then do nothing */
9209 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9212 aopOp (right, ic, FALSE, FALSE);
9213 aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9215 /* if the result is a bit */
9216 if (AOP_TYPE (result) == AOP_CRY)
9218 /* if the right size is a literal then
9219 we know what the value is */
9220 if (AOP_TYPE (right) == AOP_LIT)
9222 if (((int) operandLitValue (right)))
9223 aopPut (AOP (result), one, 0);
9225 aopPut (AOP (result), zero, 0);
9230 /* the right is also a bit variable */
9231 if (AOP_TYPE (right) == AOP_CRY)
9233 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9234 aopPut (AOP (result), "c", 0);
9240 aopPut (AOP (result), "a", 0);
9244 /* if they are the same size : or less */
9245 if (AOP_SIZE (result) <= AOP_SIZE (right))
9248 /* if they are in the same place */
9249 if (sameRegs (AOP (right), AOP (result)))
9252 /* if they in different places then copy */
9253 size = AOP_SIZE (result);
9255 _startLazyDPSEvaluation ();
9258 aopPut (AOP (result),
9259 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9263 _endLazyDPSEvaluation ();
9268 /* if the result is of type pointer */
9273 sym_link *type = operandType (right);
9275 /* pointer to generic pointer */
9276 if (IS_GENPTR (ctype))
9282 p_type = DCL_TYPE (type);
9286 #if OLD_CAST_BEHAVIOR
9287 /* KV: we are converting a non-pointer type to
9288 * a generic pointer. This (ifdef'd out) code
9289 * says that the resulting generic pointer
9290 * should have the same class as the storage
9291 * location of the non-pointer variable.
9293 * For example, converting an int (which happens
9294 * to be stored in DATA space) to a pointer results
9295 * in a DATA generic pointer; if the original int
9296 * in XDATA space, so will be the resulting pointer.
9298 * I don't like that behavior, and thus this change:
9299 * all such conversions will be forced to XDATA and
9300 * throw a warning. If you want some non-XDATA
9301 * type, or you want to suppress the warning, you
9302 * must go through an intermediate cast, like so:
9304 * char _generic *gp = (char _xdata *)(intVar);
9306 sym_link *etype = getSpec (type);
9308 /* we have to go by the storage class */
9309 if (SPEC_OCLS (etype) != generic)
9311 p_type = PTR_TYPE (SPEC_OCLS (etype));
9316 /* Converting unknown class (i.e. register variable)
9317 * to generic pointer. This is not good, but
9318 * we'll make a guess (and throw a warning).
9321 werror (W_INT_TO_GEN_PTR_CAST);
9325 /* the first two bytes are known */
9326 size = GPTRSIZE - 1;
9328 _startLazyDPSEvaluation ();
9331 aopPut (AOP (result),
9332 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9336 _endLazyDPSEvaluation ();
9338 /* the last byte depending on type */
9356 /* this should never happen */
9357 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9358 "got unknown pointer type");
9361 aopPut (AOP (result), l, GPTRSIZE - 1);
9365 /* just copy the pointers */
9366 size = AOP_SIZE (result);
9368 _startLazyDPSEvaluation ();
9371 aopPut (AOP (result),
9372 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9376 _endLazyDPSEvaluation ();
9380 /* so we now know that the size of destination is greater
9381 than the size of the source */
9382 /* we move to result for the size of source */
9383 size = AOP_SIZE (right);
9385 _startLazyDPSEvaluation ();
9388 aopPut (AOP (result),
9389 aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9393 _endLazyDPSEvaluation ();
9395 /* now depending on the sign of the source && destination */
9396 size = AOP_SIZE (result) - AOP_SIZE (right);
9397 /* if unsigned or not an integral type */
9398 /* also, if the source is a bit, we don't need to sign extend, because
9399 * it can't possibly have set the sign bit.
9401 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9405 aopPut (AOP (result), zero, offset++);
9410 /* we need to extend the sign :{ */
9411 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9412 FALSE, FALSE, TRUE);
9414 emitcode ("rlc", "a");
9415 emitcode ("subb", "a,acc");
9417 aopPut (AOP (result), "a", offset++);
9420 /* we are done hurray !!!! */
9423 freeAsmop (right, NULL, ic, TRUE);
9424 freeAsmop (result, NULL, ic, TRUE);
9428 /*-----------------------------------------------------------------*/
9429 /* genDjnz - generate decrement & jump if not zero instrucion */
9430 /*-----------------------------------------------------------------*/
9432 genDjnz (iCode * ic, iCode * ifx)
9438 /* if the if condition has a false label
9439 then we cannot save */
9443 /* if the minus is not of the form
9445 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9446 !IS_OP_LITERAL (IC_RIGHT (ic)))
9449 if (operandLitValue (IC_RIGHT (ic)) != 1)
9452 /* if the size of this greater than one then no
9454 if (getSize (operandType (IC_RESULT (ic))) > 1)
9457 /* otherwise we can save BIG */
9458 D(emitcode(";", "genDjnz"););
9460 lbl = newiTempLabel (NULL);
9461 lbl1 = newiTempLabel (NULL);
9463 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9465 if (AOP_NEEDSACC(IC_RESULT(ic)))
9467 /* If the result is accessed indirectly via
9468 * the accumulator, we must explicitly write
9469 * it back after the decrement.
9471 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9473 if (strcmp(rByte, "a"))
9475 /* Something is hopelessly wrong */
9476 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9477 __FILE__, __LINE__);
9478 /* We can just give up; the generated code will be inefficient,
9481 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9484 emitcode ("dec", "%s", rByte);
9485 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9486 emitcode ("jnz", "%05d$", lbl->key + 100);
9488 else if (IS_AOP_PREG (IC_RESULT (ic)))
9490 emitcode ("dec", "%s",
9491 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9492 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9493 emitcode ("jnz", "%05d$", lbl->key + 100);
9497 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9500 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9501 emitcode ("", "%05d$:", lbl->key + 100);
9502 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9503 emitcode ("", "%05d$:", lbl1->key + 100);
9505 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9510 /*-----------------------------------------------------------------*/
9511 /* genReceive - generate code for a receive iCode */
9512 /*-----------------------------------------------------------------*/
9514 genReceive (iCode * ic)
9517 D (emitcode (";", "genReceive ");
9520 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9521 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9522 IS_TRUE_SYMOP (IC_RESULT (ic))))
9524 int size = getSize (operandType (IC_RESULT (ic)));
9525 int offset = fReturnSizeDS390 - size;
9528 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9529 fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9532 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9533 size = AOP_SIZE (IC_RESULT (ic));
9537 emitcode ("pop", "acc");
9538 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9545 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9547 assignResultValue (IC_RESULT (ic));
9550 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9553 /*-----------------------------------------------------------------*/
9554 /* gen390Code - generate code for Dallas 390 based controllers */
9555 /*-----------------------------------------------------------------*/
9557 gen390Code (iCode * lic)
9562 lineHead = lineCurr = NULL;
9566 /* print the allocation information */
9568 printAllocInfo (currFunc, codeOutFile);
9570 /* if debug information required */
9571 if (options.debug && currFunc)
9573 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9575 if (IS_STATIC (currFunc->etype))
9576 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9578 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9581 /* stack pointer name */
9582 if (options.useXstack)
9588 for (ic = lic; ic; ic = ic->next)
9591 if (cln != ic->lineno)
9596 emitcode ("", "C$%s$%d$%d$%d ==.",
9597 FileBaseName (ic->filename), ic->lineno,
9598 ic->level, ic->block);
9601 emitcode (";", "%s %d", ic->filename, ic->lineno);
9604 /* if the result is marked as
9605 spilt and rematerializable or code for
9606 this has already been generated then
9608 if (resultRemat (ic) || ic->generated)
9611 /* depending on the operation */
9631 /* IPOP happens only when trying to restore a
9632 spilt live range, if there is an ifx statement
9633 following this pop then the if statement might
9634 be using some of the registers being popped which
9635 would destory the contents of the register so
9636 we need to check for this condition and handle it */
9638 ic->next->op == IFX &&
9639 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9640 genIfx (ic->next, ic);
9658 genEndFunction (ic);
9678 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9695 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9699 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9706 /* note these two are xlated by algebraic equivalence
9707 during parsing SDCC.y */
9708 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9709 "got '>=' or '<=' shouldn't have come here");
9713 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9725 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9729 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9733 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9760 case GET_VALUE_AT_ADDRESS:
9765 if (POINTER_SET (ic))
9792 addSet (&_G.sendSet, ic);
9801 /* now we are ready to call the
9802 peep hole optimizer */
9803 if (!options.nopeep)
9804 peepHole (&lineHead);
9806 /* now do the actual printing */
9807 printLine (lineHead, codeOutFile);